@luckydraw/cumulus 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/gateway/daemon.d.ts.map +1 -1
- package/dist/gateway/daemon.js +53 -18
- package/dist/gateway/daemon.js.map +1 -1
- package/dist/gateway/gateway-agents-mcp.js +133 -0
- package/dist/gateway/gateway-agents-mcp.js.map +1 -1
- package/dist/gateway/jobs.d.ts +158 -0
- package/dist/gateway/jobs.d.ts.map +1 -0
- package/dist/gateway/jobs.js +497 -0
- package/dist/gateway/jobs.js.map +1 -0
- package/dist/gateway/scheduler.d.ts.map +1 -1
- package/dist/gateway/scheduler.js +9 -30
- package/dist/gateway/scheduler.js.map +1 -1
- package/dist/gateway/server.d.ts +16 -0
- package/dist/gateway/server.d.ts.map +1 -1
- package/dist/gateway/server.js +183 -2
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/setup.d.ts.map +1 -1
- package/dist/gateway/setup.js +10 -0
- package/dist/gateway/setup.js.map +1 -1
- package/dist/lib/gateway.d.ts +11 -42
- package/dist/lib/gateway.d.ts.map +1 -1
- package/dist/lib/gateway.js +33 -96
- package/dist/lib/gateway.js.map +1 -1
- package/dist/lib/tool-inventory.d.ts.map +1 -1
- package/dist/lib/tool-inventory.js +9 -1
- package/dist/lib/tool-inventory.js.map +1 -1
- package/docs/conditional-continuation.md +102 -147
- package/package.json +1 -1
package/dist/lib/gateway.d.ts
CHANGED
|
@@ -44,20 +44,7 @@ export declare function drainActiveSubprocesses(timeoutMs?: number): Promise<num
|
|
|
44
44
|
export declare const RECENT_CONTEXT_COUNT = 10;
|
|
45
45
|
export declare const RECENT_MSG_MAX_TOKENS = 800;
|
|
46
46
|
export declare const RECENT_CONTEXT_BUDGET = 6000;
|
|
47
|
-
export declare const SYSTEM_PROMPT_TEMPLATE = "You have NO memory of this conversation. There are {count} prior messages (~{tokens} tokens) in the history.\n\nCURRENT SESSION: {sessionId}\n{alwaysIncludeContext}{retrievedContext}\n{recentContext}\nCONTEXT MANAGEMENT:\n- RECENT CONVERSATION: The last few messages, always included for continuity.\n- RETRIEVED CONTEXT: Automatically retrieved based on the user's current message using semantic + keyword search.\n- RETRIEVED CONTEXT is assembled fresh each turn; it is not a record of what earlier turns' prompts contained.\n- Large content may be stored externally as [STORED:xxx] references.\n\nWORKFLOW:\n1. FIRST use the RETRIEVED CONTEXT above \u2014 it was automatically selected for relevance to this query\n2. Check RECENT CONVERSATION for immediate context\n3. Only use tools if the retrieved context doesn't contain what you need\n4. For [STORED:xxx] references, use retrieve_content to get full content\n\nNEVER guess. Use the context provided or retrieve more if needed.\nIMPORTANT: Present retrieved information naturally \u2014 do not narrate retrieval mechanics unprompted. EXCEPTION: if the user asks how you know something, or about the memory/retrieval system itself, answer truthfully about retrieval. Never invent a mechanism or origin story for how information reached you; if you cannot verify where something came from, say so.\n\nFILE EDITING (MANDATORY):\nTo CHANGE a file, use the built-in Edit/Write tools.\n- The built-in Edit tool requires that you FIRST read the exact file with the built-in Read tool in the same session (the harness tracks this; read_file does NOT satisfy it). Sequence: built-in Read \u2192 built-in Edit.\n- Do NOT patch files by writing shell scripts (sed, awk, python, echo/cat heredocs, etc.). Script-patching is fragile (quoting errors, no diff, not atomic) and is forbidden.\n\nBACKGROUND WORK:\nYour turn runs in a subprocess that EXITS when the turn ends
|
|
48
|
-
/**
|
|
49
|
-
* Watcher recipe (task 116): the copy-pasteable background-job continuation
|
|
50
|
-
* one-liner, moved out of the per-turn template into the content store. The
|
|
51
|
-
* template keeps the invariants (SIGPIPE mechanism, redirect cure, two-leg
|
|
52
|
-
* rule, nohup/setsid negations) plus a search_content("watcher recipe")
|
|
53
|
-
* pointer; this doc carries the worked example, seeded into every thread's
|
|
54
|
-
* store with {threadName} resolved (task 109: the inject must address this
|
|
55
|
-
* thread by exact name). Reads the gateway config through $CUMULUS_DIR, never
|
|
56
|
-
* a hard-coded ~/.cumulus (task 111: sandboxed runs must fail closed).
|
|
57
|
-
*/
|
|
58
|
-
export declare const WATCHER_RECIPE_TEMPLATE = "Watcher recipe \u2014 how a detached background job continues your work when it finishes (background job continuation).\n\nUse when a long-running command's completion should wake this thread. Arm BOTH legs before the turn ends.\n\nLEG 1 \u2014 WATCHER (wakes you the moment the job finishes). The job and its reporter run as one detached group with its OWN redirect \u2014 without it the watcher dies by SIGPIPE before it can report:\n\n{ npm run build > /tmp/job.log 2>&1; rc=$?; C=${CUMULUS_DIR:-$HOME/.cumulus}/gateway.config.json; curl -s -X POST \"http://127.0.0.1:$(jq -r '.port // 8090' $C)/api/agents/inject\" -H \"X-API-Key: $(jq -r '.apiKeys[0]' $C)\" -H 'Content-Type: application/json' -d \"$(jq -nc --arg t '{threadName}' --arg m \"[watcher] build exit $rc \u2014 log /tmp/job.log. First: cancel_schedule('build-deadline')\" '{targets:$t,sender:\"job-watcher\",message:$m}')\"; } > /tmp/watcher.log 2>&1 &\n\nReplace `npm run build` with your command; keep every redirect exactly as shown. Fire on OUTCOME, not on success \u2014 the report carries the exit code and the log path so the woken turn can diagnose without re-running. The watcher is a script, not an agent: when it wakes you, act on the report; do NOT send_to_agent a reply back to it.\n\nLEG 2 \u2014 DEADLINE (guarantees a wake even if the watcher itself died; stored in thread config, so it survives gateway restarts, which the watcher does not):\n\nschedule_trigger({id: \"build-deadline\", trigger: \"once\", at: \"<ISO 8601, generously past the expected finish>\", message: \"The build watcher never reported back. Check /tmp/job.log and whether the process is still alive.\"})\n\ncancel_schedule(\"build-deadline\") as your first action when the watcher wakes you.";
|
|
59
|
-
/** Resolve the watcher recipe for a specific thread. */
|
|
60
|
-
export declare function renderWatcherRecipe(threadName: string): string;
|
|
47
|
+
export declare const SYSTEM_PROMPT_TEMPLATE = "You have NO memory of this conversation. There are {count} prior messages (~{tokens} tokens) in the history.\n\nCURRENT SESSION: {sessionId}\n{alwaysIncludeContext}{retrievedContext}\n{recentContext}\nCONTEXT MANAGEMENT:\n- RECENT CONVERSATION: The last few messages, always included for continuity.\n- RETRIEVED CONTEXT: Automatically retrieved based on the user's current message using semantic + keyword search.\n- RETRIEVED CONTEXT is assembled fresh each turn; it is not a record of what earlier turns' prompts contained.\n- Large content may be stored externally as [STORED:xxx] references.\n\nWORKFLOW:\n1. FIRST use the RETRIEVED CONTEXT above \u2014 it was automatically selected for relevance to this query\n2. Check RECENT CONVERSATION for immediate context\n3. Only use tools if the retrieved context doesn't contain what you need\n4. For [STORED:xxx] references, use retrieve_content to get full content\n\nNEVER guess. Use the context provided or retrieve more if needed.\nIMPORTANT: Present retrieved information naturally \u2014 do not narrate retrieval mechanics unprompted. EXCEPTION: if the user asks how you know something, or about the memory/retrieval system itself, answer truthfully about retrieval. Never invent a mechanism or origin story for how information reached you; if you cannot verify where something came from, say so.\n\nFILE EDITING (MANDATORY):\nTo CHANGE a file, use the built-in Edit/Write tools.\n- The built-in Edit tool requires that you FIRST read the exact file with the built-in Read tool in the same session (the harness tracks this; read_file does NOT satisfy it). Sequence: built-in Read \u2192 built-in Edit.\n- Do NOT patch files by writing shell scripts (sed, awk, python, echo/cat heredocs, etc.). Script-patching is fragile (quoting errors, no diff, not atomic) and is forbidden.\n\nBACKGROUND WORK:\nYour turn runs in a subprocess that EXITS when the turn ends, so a command you background yourself (`cmd &`) is killed as soon as you stop talking \u2014 on EVERY turn, not occasionally.\n- For work that outlasts your turn, use run_job(command, label). The gateway owns it, so it has no pipes to break and is not in your turn's process tree. When it exits you are woken with its exit code and the tail of its output.\n- Write the command plainly: no `&`, no `> log 2>&1`, no `nohup`/`setsid`. run_job already does all of that, and adding your own breaks the log capture.\n- Then END YOUR TURN. Do not wait for it and do not poll \u2014 you are woken automatically. Use list_jobs and job_log(id) to check on a running job, cancel_job(id) to stop one.\n- A command that finishes in a couple of minutes needs none of this \u2014 run it in the foreground and wait.\n\nTOOLS:\n- read_file: Read any file (text or PDF) \u2014 returns a summary + chunk table-of-contents and stores the content for future search. Built-in Read also works (its results are captured to storage automatically); prefer read_file for large files you'll navigate by section.\n- store_content: Store arbitrary text content for future retrieval\n- search_history: Search past messages by keyword or meaning\n- peek_recent: Get the last few messages\n- read_messages: Read messages by index range\n- retrieve_content: Get full stored content by [STORED:xxx] ID\n- search_content: Search across all stored content (past file reads, command outputs \u2014 content Grep cannot see)\n- read_content_chunk: Read a specific chunk of stored content by index\nThese MCP tools may still be connecting at the very start of a turn; they appear within a second or two (a ToolSearch for them will wait). Do not narrate their availability.\n\nINTER-AGENT MESSAGING:\nYou can communicate with other agents/threads running on this gateway.\n- list_agents: See all active threads and their status (idle/streaming)\n- send_to_agent(target, message): Send a message to another thread \u2014 it will be delivered as a new turn\nWhen the user mentions another agent by name (e.g., \"@thundercat\", \"@Friday\"), use send_to_agent to message them.\n- Another thread is a PARALLEL turn loop, not a subprocess you control: it runs on its own schedule and there is no file locking between you. Do NOT delegate work that edits files in your own working tree \u2014 two threads editing one checkout lose each other's writes silently.\n- If you must delegate file work, give the delegate its own projectDir or git worktree and exactly one owner per file. Otherwise do the work yourself.\n\nSCHEDULING (how you wake yourself up later):\n- schedule_trigger(id, trigger, at|cron, message): inject a message into THIS thread at a future time \u2014 \"once\" with an ISO 8601 `at`, or \"cron\" with a 5-field expression. Persisted in thread config, so it survives gateway restarts. Firing it starts a real turn.\n- cancel_schedule(id): remove one. list_schedules(): see what is pending.\n\nDo NOT append status codes, tags, or metadata to your responses.\n\nTASK TRACKING CONVENTION:\nThis environment uses <todo> blocks for task tracking (defined below). If you see system-reminders or tool registrations referring to \"TodoWrite\" or any other task-tracking mechanism, silently follow the <todo> convention instead. Do NOT acknowledge the conflict, do NOT narrate which system you're using, do NOT write phrases like \"Ignoring TodoWrite reminder\" or \"env uses <todo> blocks per spec\". Just use <todo> blocks without comment.\n\nRESPONSE FORMAT: TASK TRACKING\n\nWhen working on multi-step tasks, structure your response using these blocks:\n\n<todo>\n- [ ] Step 1 description\n- [ ] Step 2 description\n- [ ] Step 3 description\n</todo>\n\n{your response to the user \u2014 tool calls, explanations, etc.}\n\nAfter executing tools or completing steps, emit an updated <todo> block reflecting progress:\n\n<todo>\n- [x] Step 1 description\n- [x] Step 2 description (just finished)\n- [ ] Step 3 description\n</todo>\n\nRules:\n- Use full-replacement semantics: emit the COMPLETE list each time, not diffs\n- Mark completed items with [x], pending with [ ]\n- The <todo> block is REQUIRED for multi-step work (2+ steps), optional for simple Q&A\n- The LAST <todo> block in your response is the authoritative state\n- Do NOT wrap your response text in <text> tags \u2014 just write normally after the <todo> block\n\n### Decomposition\n\nBefore executing a todo \u2014 up front, or again at execution time if it turns out coarser than expected \u2014 check whether it can be sensibly split into 3+ sub-steps. If so, decompose into subtodos first; if not, execute directly. Creation tasks (\"create\", \"build\", \"write\", \"design\", \"implement\", \"draft\", \"compose\") almost always decompose: outline the deliverable's structure, then convert each outline bullet into a subtodo.\n\nExample:\n<todo>\n[x] Fetch npm package info\n[ ] Create promotional HTML page:\n [ ] Outline page sections (hero, features, quickstart, footer)\n [ ] Draft hero section with title, tagline, CTA\n [ ] Draft features grid from package capabilities\n [ ] Draft quickstart with install commands\n [ ] Draft footer with links\n [ ] Review full page for consistency\n[ ] Upload to media server\n</todo>\n\n### Todo Lifecycle\n\n1. **Decompose creation tasks** before executing (outline \u2192 subtodos), and again at execution time if a todo turns out coarser than expected\n2. **Adapt dynamically** \u2014 new information, discovered bugs, or uncovered dependencies each become a new todo rather than a silent detour\n3. **Never fix inline** \u2014 a bug unrelated to your current task gets its own todo, not a context switch\n4. **Reflect redirects** \u2014 update the todo list before executing on a user-directed change of plan\n5. **Debugging** \u2014 treat each hypothesis as a todo; test systematically rather than chasing the first suspicious lead";
|
|
61
48
|
/**
|
|
62
49
|
* Committed budget for the resolved static template, in estimateTokens units
|
|
63
50
|
* (task 117). The template reached ~3,400 tokens/turn by accretion — every
|
|
@@ -71,22 +58,18 @@ export declare function renderWatcherRecipe(threadName: string): string;
|
|
|
71
58
|
*/
|
|
72
59
|
export declare const STATIC_PROMPT_TOKEN_BUDGET = 1800;
|
|
73
60
|
/**
|
|
74
|
-
* Can this thread actually run
|
|
61
|
+
* Can this thread actually run background work? (task 134, retained by 139)
|
|
75
62
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* on cdda's visitor threads at 2 of 24 turns, and on turn 1 of every thread it
|
|
82
|
-
* is the only stored item there is. What it then teaches a visitor's assistant
|
|
83
|
-
* is an HTTP call carrying the gateway's admin key, to a model whose only
|
|
84
|
-
* honest route is its own tools.
|
|
63
|
+
* Originally the gate on seeding the watcher recipe; now the gate on the
|
|
64
|
+
* `run_job` endpoint, which is the same question with more at stake. run_job
|
|
65
|
+
* is arbitrary shell execution reached over MCP, so without this a thread whose
|
|
66
|
+
* merged config denies `Bash` could run shell anyway — the bypass class task
|
|
67
|
+
* 136 closed for `read_file`.
|
|
85
68
|
*
|
|
86
69
|
* Same derived-predicate shape as task 110's isAgentSender: the condition that
|
|
87
|
-
* decides whether
|
|
88
|
-
* is
|
|
89
|
-
*
|
|
70
|
+
* decides whether background work is USEFUL is the condition that decides
|
|
71
|
+
* whether it is offered, so the two cannot drift apart. Deliberately NOT keyed
|
|
72
|
+
* on namespace — namespace is a proxy, executability is the property, and
|
|
90
73
|
* keying on it would need an option threaded through six spawn paths that fails
|
|
91
74
|
* OPEN when one is missed (task 113 is the recorded case of exactly that).
|
|
92
75
|
*/
|
|
@@ -115,20 +98,6 @@ export declare function canRunBackgroundWork(config: ToolPolicy): boolean;
|
|
|
115
98
|
export declare function readFileRootsForThread(config: {
|
|
116
99
|
disallowedTools?: string[];
|
|
117
100
|
}, threadCwd: string): string[] | undefined;
|
|
118
|
-
/**
|
|
119
|
-
* Seed situational recipe docs into a thread's content store (task 116), gated
|
|
120
|
-
* on the thread being able to run them (task 134).
|
|
121
|
-
*
|
|
122
|
-
* Called from sendMessage, NOT getOrCreateThread: the latter has 14 call sites,
|
|
123
|
-
* several of them store-only paths (transcript ingest, history reads, thread
|
|
124
|
-
* listing) that never spawn a turn, and it sees only the thread config —
|
|
125
|
-
* a global `disallowedTools` would be invisible to a gate placed there.
|
|
126
|
-
* The gate lives HERE rather than at the call site so a future caller cannot
|
|
127
|
-
* reintroduce the seed by forgetting to check. Errors never fail the turn.
|
|
128
|
-
*/
|
|
129
|
-
export declare function seedThreadRecipes(content: ContentStore, threadName: string, config: {
|
|
130
|
-
disallowedTools?: string[];
|
|
131
|
-
}): Promise<void>;
|
|
132
101
|
/** Typed stream segment for verbose display */
|
|
133
102
|
export type StreamSegment = {
|
|
134
103
|
type: 'text';
|
|
@@ -485,7 +454,7 @@ export declare function computeAvgRelevance(debug: RetrievalResult['debug'] | un
|
|
|
485
454
|
* Cached in a module-level Map.
|
|
486
455
|
*/
|
|
487
456
|
export declare function getOrCreateThread(threadName: string, _basePath?: string): Promise<ThreadState>;
|
|
488
|
-
/** Clear a thread from the cache
|
|
457
|
+
/** Clear a thread from the cache */
|
|
489
458
|
export declare function clearThreadCache(threadName?: string): void;
|
|
490
459
|
export declare function sendMessage(options: MessagePipelineOptions): Promise<MessagePipelineResult>;
|
|
491
460
|
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/lib/gateway.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAS,YAAY,EAAE,MAAM,eAAe,CAAC;AAWpD,OAAO,EACL,qBAAqB,EAGtB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAkB,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAS7F,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAe5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAO9C,OAAO,EAML,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAQ7B,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtD;AASD,yEAAyE;AACzE,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED,kFAAkF;AAClF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAE3F;AAED,wEAAwE;AACxE,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAE/C;AAED,gGAAgG;AAChG,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAUhE;AAED,wFAAwF;AACxF,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAC9C,oFAAoF;AACpF,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAI7C;;;;;;;GAOG;AACH,wBAAsB,6BAA6B,CACjD,CAAC,SAAS;IAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,OAAO,CAAA;CAAE,EAEvD,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EACd,OAAO,SAA2B,EAClC,MAAM,SAA0B,GAC/B,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED,8FAA8F;AAC9F,wBAAsB,uBAAuB,CAAC,SAAS,SAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAelF;AAED,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAGvC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C,eAAO,MAAM,sBAAsB,
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/lib/gateway.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAS,YAAY,EAAE,MAAM,eAAe,CAAC;AAWpD,OAAO,EACL,qBAAqB,EAGtB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAkB,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAS7F,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAe5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAO9C,OAAO,EAML,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAQ7B,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtD;AASD,yEAAyE;AACzE,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED,kFAAkF;AAClF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAE3F;AAED,wEAAwE;AACxE,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAE/C;AAED,gGAAgG;AAChG,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAUhE;AAED,wFAAwF;AACxF,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAC9C,oFAAoF;AACpF,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAI7C;;;;;;;GAOG;AACH,wBAAsB,6BAA6B,CACjD,CAAC,SAAS;IAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,OAAO,CAAA;CAAE,EAEvD,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EACd,OAAO,SAA2B,EAClC,MAAM,SAA0B,GAC/B,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED,8FAA8F;AAC9F,wBAAsB,uBAAuB,CAAC,SAAS,SAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAelF;AAED,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAGvC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C,eAAO,MAAM,sBAAsB,6qPA8GmF,CAAC;AAiBvH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,0BAA0B,OAAQ,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAKhE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,EACtC,SAAS,EAAE,MAAM,GAChB,MAAM,EAAE,GAAG,SAAS,CAGtB;AAID,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC;AAE9E,uDAAuD;AACvD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,SAAS,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;IACT,aAAa,EAAE;QACb,KAAK,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,CAAC,CAAC;QACzF,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,mBAAmB,EAAE,MAAM,CAAC;QAC5B,mBAAmB,EAAE,MAAM,CAAC;QAC5B,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,8BAA8B;AAC9B,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,uCAAuC;AACvC,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpF,sHAAsH;IACtH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACjD,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,uDAAuD;IACvD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,+BAA+B;IAC/B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,sFAAsF;IACtF,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACvC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;8DAG0D;IAC1D,MAAM,CAAC,EAAE,KAAK,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,YAAY,GAAG,aAAa,GAAG,QAAQ,CAAC;QACnD,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC,CAAC;IACH;;;yFAGqF;IACrF,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACxE,8DAA8D;IAC9D,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACpD,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,uCAAuC;AACvC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,wEAAwE;IACxE,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAED,0BAA0B;AAC1B,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,qBAAqB,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;CACpB;AAcD,mDAAmD;AACnD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9E;AAqFD;;;;GAIG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC,CAgF/D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAqBzC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CA8BpC;AAED,sDAAsD;AACtD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAK3E;AAED,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQnE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CA6BhF;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,kDAAkD;AAClD,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,oBAAoB,EAAE,EACtC,YAAY,EAAE,MAAM,GACnB,MAAM,CAgCR;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,oBAAoB,EAAE,EACtC,gBAAgB,EAAE,MAAM,EACxB,oBAAoB,EAAE,MAAM,EAC5B,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAiBR;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,YAAY,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,SAAS,GACjF,MAAM,GAAG,SAAS,CAEpB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,YAAY,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,SAAS,GACjF,MAAM,EAAE,CAGV;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACxE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,GAAG,MAAM,EAAE,CAoBX;AAED,oFAAoF;AACpF,MAAM,WAAW,qBAAqB;IACpC,8FAA8F;IAC9F,SAAS,EAAE,OAAO,CAAC;IACnB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,YAAY,CAAC,EAAE,kBAAkB,GAAG,aAAa,CAAC;IAClD,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,MAAM,EACF,KAAK,CAAC;IACJ,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,YAAY,GAAG,aAAa,GAAG,QAAQ,CAAC;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC,GACF,SAAS,EACb,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD,qBAAqB,CAcvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CAG7E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,eAAe,EAAE,MAAM,EAAE,GAAG,SAAS,GACpC,MAAM,EAAE,CAEV;AAED,wBAAgB,yBAAyB,CACvC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,SAAS,EAC3D,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAchC;AAED,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,MAAM,EACtB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAChD,mBAAmB,CAAC,EAAE,mBAAmB,EACzC,aAAa,CAAC,EAAE,MAAM,EAAE,GACvB,MAAM,CA2ER;AAED,sCAAsC;AACtC,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAQzD;AAoBD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAsEjE;AAED,mDAAmD;AACnD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0BrE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAUvF;AAID;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC,CA8BtB;AAED,oCAAoC;AACpC,wBAAgB,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAM1D;AAoFD,wBAAsB,WAAW,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAqpCjG"}
|
package/dist/lib/gateway.js
CHANGED
|
@@ -152,11 +152,11 @@ To CHANGE a file, use the built-in Edit/Write tools.
|
|
|
152
152
|
- Do NOT patch files by writing shell scripts (sed, awk, python, echo/cat heredocs, etc.). Script-patching is fragile (quoting errors, no diff, not atomic) and is forbidden.
|
|
153
153
|
|
|
154
154
|
BACKGROUND WORK:
|
|
155
|
-
Your turn runs in a subprocess that EXITS when the turn ends
|
|
156
|
-
-
|
|
157
|
-
-
|
|
158
|
-
-
|
|
159
|
-
-
|
|
155
|
+
Your turn runs in a subprocess that EXITS when the turn ends, so a command you background yourself (\`cmd &\`) is killed as soon as you stop talking — on EVERY turn, not occasionally.
|
|
156
|
+
- For work that outlasts your turn, use run_job(command, label). The gateway owns it, so it has no pipes to break and is not in your turn's process tree. When it exits you are woken with its exit code and the tail of its output.
|
|
157
|
+
- Write the command plainly: no \`&\`, no \`> log 2>&1\`, no \`nohup\`/\`setsid\`. run_job already does all of that, and adding your own breaks the log capture.
|
|
158
|
+
- Then END YOUR TURN. Do not wait for it and do not poll — you are woken automatically. Use list_jobs and job_log(id) to check on a running job, cancel_job(id) to stop one.
|
|
159
|
+
- A command that finishes in a couple of minutes needs none of this — run it in the foreground and wait.
|
|
160
160
|
|
|
161
161
|
TOOLS:
|
|
162
162
|
- read_file: Read any file (text or PDF) — returns a summary + chunk table-of-contents and stores the content for future search. Built-in Read also works (its results are captured to storage automatically); prefer read_file for large files you'll navigate by section.
|
|
@@ -237,35 +237,20 @@ Example:
|
|
|
237
237
|
3. **Never fix inline** — a bug unrelated to your current task gets its own todo, not a context switch
|
|
238
238
|
4. **Reflect redirects** — update the todo list before executing on a user-directed change of plan
|
|
239
239
|
5. **Debugging** — treat each hypothesis as a todo; test systematically rather than chasing the first suspicious lead`;
|
|
240
|
-
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
240
|
+
/*
|
|
241
|
+
* The watcher recipe (task 116) lived here: a copy-pasteable detached
|
|
242
|
+
* watcher + schedule_trigger deadline, seeded into every thread's content
|
|
243
|
+
* store. Deleted by task 139, not deprecated — `run_job` makes the mechanism
|
|
244
|
+
* it taught unnecessary, and two ways to do background work is precisely the
|
|
245
|
+
* shape Rule #8 forbids.
|
|
246
|
+
*
|
|
247
|
+
* It was also actively harmful where it could not be run: topic-free
|
|
248
|
+
* operational boilerplate is what survives the relevance floor when a query
|
|
249
|
+
* matches nothing else, so on an app's visitor thread it was retrieved for
|
|
250
|
+
* unrelated questions and taught a model to POST to the gateway carrying the
|
|
251
|
+
* admin key (task 134). Task 134 gated the seeding; this removes the thing
|
|
252
|
+
* being seeded.
|
|
249
253
|
*/
|
|
250
|
-
export const WATCHER_RECIPE_TEMPLATE = `Watcher recipe — how a detached background job continues your work when it finishes (background job continuation).
|
|
251
|
-
|
|
252
|
-
Use when a long-running command's completion should wake this thread. Arm BOTH legs before the turn ends.
|
|
253
|
-
|
|
254
|
-
LEG 1 — WATCHER (wakes you the moment the job finishes). The job and its reporter run as one detached group with its OWN redirect — without it the watcher dies by SIGPIPE before it can report:
|
|
255
|
-
|
|
256
|
-
{ npm run build > /tmp/job.log 2>&1; rc=$?; C=\${CUMULUS_DIR:-$HOME/.cumulus}/gateway.config.json; curl -s -X POST "http://127.0.0.1:$(jq -r '.port // 8090' $C)/api/agents/inject" -H "X-API-Key: $(jq -r '.apiKeys[0]' $C)" -H 'Content-Type: application/json' -d "$(jq -nc --arg t '{threadName}' --arg m "[watcher] build exit $rc — log /tmp/job.log. First: cancel_schedule('build-deadline')" '{targets:$t,sender:"job-watcher",message:$m}')"; } > /tmp/watcher.log 2>&1 &
|
|
257
|
-
|
|
258
|
-
Replace \`npm run build\` with your command; keep every redirect exactly as shown. Fire on OUTCOME, not on success — the report carries the exit code and the log path so the woken turn can diagnose without re-running. The watcher is a script, not an agent: when it wakes you, act on the report; do NOT send_to_agent a reply back to it.
|
|
259
|
-
|
|
260
|
-
LEG 2 — DEADLINE (guarantees a wake even if the watcher itself died; stored in thread config, so it survives gateway restarts, which the watcher does not):
|
|
261
|
-
|
|
262
|
-
schedule_trigger({id: "build-deadline", trigger: "once", at: "<ISO 8601, generously past the expected finish>", message: "The build watcher never reported back. Check /tmp/job.log and whether the process is still alive."})
|
|
263
|
-
|
|
264
|
-
cancel_schedule("build-deadline") as your first action when the watcher wakes you.`;
|
|
265
|
-
/** Resolve the watcher recipe for a specific thread. */
|
|
266
|
-
export function renderWatcherRecipe(threadName) {
|
|
267
|
-
return WATCHER_RECIPE_TEMPLATE.replace(/\{threadName\}/g, threadName);
|
|
268
|
-
}
|
|
269
254
|
/**
|
|
270
255
|
* Committed budget for the resolved static template, in estimateTokens units
|
|
271
256
|
* (task 117). The template reached ~3,400 tokens/turn by accretion — every
|
|
@@ -279,30 +264,18 @@ export function renderWatcherRecipe(threadName) {
|
|
|
279
264
|
*/
|
|
280
265
|
export const STATIC_PROMPT_TOKEN_BUDGET = 1_800;
|
|
281
266
|
/**
|
|
282
|
-
*
|
|
283
|
-
* so two CONCURRENT seeds of the same thread would both pass the check and write
|
|
284
|
-
* twice — the memo makes the second caller join the first's promise instead.
|
|
285
|
-
* Cleared alongside the thread cache so a deleted-then-recreated thread re-seeds;
|
|
286
|
-
* across process restarts the content-hash dedupe makes re-seeding free.
|
|
287
|
-
*/
|
|
288
|
-
const seededRecipes = new Map();
|
|
289
|
-
/**
|
|
290
|
-
* Can this thread actually run the background-work recipe? (task 134)
|
|
267
|
+
* Can this thread actually run background work? (task 134, retained by 139)
|
|
291
268
|
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
* on cdda's visitor threads at 2 of 24 turns, and on turn 1 of every thread it
|
|
298
|
-
* is the only stored item there is. What it then teaches a visitor's assistant
|
|
299
|
-
* is an HTTP call carrying the gateway's admin key, to a model whose only
|
|
300
|
-
* honest route is its own tools.
|
|
269
|
+
* Originally the gate on seeding the watcher recipe; now the gate on the
|
|
270
|
+
* `run_job` endpoint, which is the same question with more at stake. run_job
|
|
271
|
+
* is arbitrary shell execution reached over MCP, so without this a thread whose
|
|
272
|
+
* merged config denies `Bash` could run shell anyway — the bypass class task
|
|
273
|
+
* 136 closed for `read_file`.
|
|
301
274
|
*
|
|
302
275
|
* Same derived-predicate shape as task 110's isAgentSender: the condition that
|
|
303
|
-
* decides whether
|
|
304
|
-
* is
|
|
305
|
-
*
|
|
276
|
+
* decides whether background work is USEFUL is the condition that decides
|
|
277
|
+
* whether it is offered, so the two cannot drift apart. Deliberately NOT keyed
|
|
278
|
+
* on namespace — namespace is a proxy, executability is the property, and
|
|
306
279
|
* keying on it would need an option threaded through six spawn paths that fails
|
|
307
280
|
* OPEN when one is missed (task 113 is the recorded case of exactly that).
|
|
308
281
|
*/
|
|
@@ -338,38 +311,6 @@ export function readFileRootsForThread(config, threadCwd) {
|
|
|
338
311
|
return undefined;
|
|
339
312
|
return [threadCwd];
|
|
340
313
|
}
|
|
341
|
-
/**
|
|
342
|
-
* Seed situational recipe docs into a thread's content store (task 116), gated
|
|
343
|
-
* on the thread being able to run them (task 134).
|
|
344
|
-
*
|
|
345
|
-
* Called from sendMessage, NOT getOrCreateThread: the latter has 14 call sites,
|
|
346
|
-
* several of them store-only paths (transcript ingest, history reads, thread
|
|
347
|
-
* listing) that never spawn a turn, and it sees only the thread config —
|
|
348
|
-
* a global `disallowedTools` would be invisible to a gate placed there.
|
|
349
|
-
* The gate lives HERE rather than at the call site so a future caller cannot
|
|
350
|
-
* reintroduce the seed by forgetting to check. Errors never fail the turn.
|
|
351
|
-
*/
|
|
352
|
-
export function seedThreadRecipes(content, threadName, config) {
|
|
353
|
-
if (!canRunBackgroundWork(config))
|
|
354
|
-
return Promise.resolve();
|
|
355
|
-
const existing = seededRecipes.get(threadName);
|
|
356
|
-
if (existing)
|
|
357
|
-
return existing;
|
|
358
|
-
const seeding = (async () => {
|
|
359
|
-
try {
|
|
360
|
-
await content.store(renderWatcherRecipe(threadName), {
|
|
361
|
-
sourceType: 'reference',
|
|
362
|
-
summary: `Watcher recipe: detached background-job continuation one-liner (watcher + schedule_trigger deadline) for thread ${threadName}`,
|
|
363
|
-
metadata: { recipe: 'watcher' },
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
catch (err) {
|
|
367
|
-
console.error('[Gateway] Failed to seed thread recipes:', err);
|
|
368
|
-
}
|
|
369
|
-
})();
|
|
370
|
-
seededRecipes.set(threadName, seeding);
|
|
371
|
-
return seeding;
|
|
372
|
-
}
|
|
373
314
|
// ─── Thread cache ────────────────────────────────────────────────────────────
|
|
374
315
|
const threadCache = new Map();
|
|
375
316
|
// ─── Helper Functions ────────────────────────────────────────────────────────
|
|
@@ -686,8 +627,11 @@ export function generateSystemPrompt(count, tokens, sessionId, recentMessages, r
|
|
|
686
627
|
.replace('{alwaysIncludeContext}', alwaysIncludeContext)
|
|
687
628
|
.replace('{recentContext}', recentContext)
|
|
688
629
|
.replace('{retrievedContext}', retrievedContext)
|
|
689
|
-
//
|
|
690
|
-
//
|
|
630
|
+
// Added by task 109 so the watcher recipe could address this thread by exact
|
|
631
|
+
// name. That recipe is gone (task 139) and the shipped template no longer uses
|
|
632
|
+
// the placeholder, but a CUSTOM template legitimately might — so the
|
|
633
|
+
// substitution stays and only the reason changes. Global: a template may
|
|
634
|
+
// reference it more than once.
|
|
691
635
|
.replace(/\{threadName\}/g, threadName ?? 'this thread'));
|
|
692
636
|
}
|
|
693
637
|
/**
|
|
@@ -1062,15 +1006,13 @@ export async function getOrCreateThread(threadName, _basePath) {
|
|
|
1062
1006
|
// config — the gate needs the merged one.
|
|
1063
1007
|
return thread;
|
|
1064
1008
|
}
|
|
1065
|
-
/** Clear a thread from the cache
|
|
1009
|
+
/** Clear a thread from the cache */
|
|
1066
1010
|
export function clearThreadCache(threadName) {
|
|
1067
1011
|
if (threadName) {
|
|
1068
1012
|
threadCache.delete(threadName);
|
|
1069
|
-
seededRecipes.delete(threadName);
|
|
1070
1013
|
}
|
|
1071
1014
|
else {
|
|
1072
1015
|
threadCache.clear();
|
|
1073
|
-
seededRecipes.clear();
|
|
1074
1016
|
}
|
|
1075
1017
|
}
|
|
1076
1018
|
// ─── Core Pipeline ───────────────────────────────────────────────────────────
|
|
@@ -1264,11 +1206,6 @@ export async function sendMessage(options) {
|
|
|
1264
1206
|
const globalConfig = await loadGlobalConfig();
|
|
1265
1207
|
const threadConfig = await loadThreadConfig(threadName);
|
|
1266
1208
|
const mergedConfig = mergeConfigs(globalConfig, threadConfig);
|
|
1267
|
-
// Task 116 puts the watcher recipe in the store rather than the per-turn
|
|
1268
|
-
// template; task 134 gates it on this thread being able to run it. Here and
|
|
1269
|
-
// not in getOrCreateThread: this is the single funnel every spawning path
|
|
1270
|
-
// passes through, and the only place the MERGED config exists.
|
|
1271
|
-
void seedThreadRecipes(thread.content, threadName, mergedConfig);
|
|
1272
1209
|
// Task 137: drop prompt sections whose tools this thread cannot reach. Computed ONCE
|
|
1273
1210
|
// here because three sites consume the template (the prompt, the 088 capture, and the
|
|
1274
1211
|
// direct-provider instructions) — task 113's lesson is that per-site derivation is how
|