summaryrefslogtreecommitdiffhomepage
path: root/packages/core/src/llm
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-01 01:46:13 +0900
committerAdam Malczewski <[email protected]>2026-06-01 01:46:13 +0900
commit8b9533c22a47bbf6f916667e2c25d8e8e419da37 (patch)
tree715a6a3d6f43781395e7dc7c8cdb519cef46a870 /packages/core/src/llm
parent1853dd1d40308deb829bc621beb79c5d39b9c57f (diff)
downloaddispatch-8b9533c22a47bbf6f916667e2c25d8e8e419da37.tar.gz
dispatch-8b9533c22a47bbf6f916667e2c25d8e8e419da37.zip
feat(tabs): tab-to-tab agent communication via short handles
Add send_to_tab / read_tab tools so an agent can message or read another tab by a git-style short handle (shortest unique prefix of the tab UUID, min 4 chars), shown in the tab bar. - core/db/tabs: resolveTabPrefix + shortestUniquePrefix (open tabs only, LIKE-sanitized prefix matching) - new tools read-tab.ts / send-to-tab.ts (+ tests) decoupled from the DB TabRow via a minimal ResolvedTabRef projection - agent-manager: unified deliverMessage routing (busy -> queue, idle -> new turn) shared by POST /chat and send_to_tab; agent->agent auto-wake budget (MAX_AGENT_AUTO_WAKES) to bound ping-pong loops - summon/loader: send_to_tab + read_tab as grantable tools - frontend: shortHandleFor + handle badge in TabBar; perm toggles - notes: tab-comm / user-agents / todo-redesign plans - chore: biome format fixes (debug-logger, summon.test) Refs notes/plan-tab-comm.md
Diffstat (limited to 'packages/core/src/llm')
-rw-r--r--packages/core/src/llm/debug-logger.ts21
1 files changed, 8 insertions, 13 deletions
diff --git a/packages/core/src/llm/debug-logger.ts b/packages/core/src/llm/debug-logger.ts
index 2b7420c..072a7a1 100644
--- a/packages/core/src/llm/debug-logger.ts
+++ b/packages/core/src/llm/debug-logger.ts
@@ -281,11 +281,7 @@ export function logStepLifecycle(data: {
* Log agent loop-level events (loop start, break conditions, etc.).
* Only logs at verbosity >= 3.
*/
-export function logAgentLoop(data: {
- tabId?: string;
- event: string;
- detail?: unknown;
-}): void {
+export function logAgentLoop(data: { tabId?: string; event: string; detail?: unknown }): void {
if (!ENABLED || VERBOSITY < 3) return;
const detail = data.detail !== undefined ? ` ${JSON.stringify(data.detail)}` : "";
console.error(`[dispatch-debug] AGENT tab=${data.tabId ?? "?"} ${data.event}${detail}`);
@@ -308,16 +304,14 @@ export function logAgentLoop(data: {
* we just clone and read once via `.text()` — simpler and safe because
* non-streaming bodies are bounded.
*/
-export function wrapFetchWithLogging<
- F extends (...args: never[]) => Promise<Response> | Response,
->(baseFetch: F, opts: { tabId?: string; modelHint?: string }): F {
+export function wrapFetchWithLogging<F extends (...args: never[]) => Promise<Response> | Response>(
+ baseFetch: F,
+ opts: { tabId?: string; modelHint?: string },
+): F {
if (!ENABLED) return baseFetch;
const wrapped = async (...args: Parameters<F>) => {
const requestId = ++seq;
- const [input, init] = args as unknown as [
- RequestInfo | URL,
- RequestInit | undefined,
- ];
+ const [input, init] = args as unknown as [RequestInfo | URL, RequestInit | undefined];
const url =
typeof input === "string"
? input
@@ -325,7 +319,8 @@ export function wrapFetchWithLogging<
? input.toString()
: (input as Request).url;
const method =
- init?.method ?? (typeof input === "object" && "method" in input ? (input as Request).method : "POST");
+ init?.method ??
+ (typeof input === "object" && "method" in input ? (input as Request).method : "POST");
// Snapshot headers as a plain object for logging.
const headerObj: Record<string, string> = {};