@te-river/opencode-team-mode 1.5.14 → 1.6.0
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/README.md +788 -674
- package/README.zh-CN.md +712 -618
- package/dist/agents.d.ts +5 -3
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +19 -8
- package/dist/agents.js.map +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/capabilities.js +2 -2
- package/dist/capabilities.js.map +1 -1
- package/dist/host-hooks.d.ts +13 -2
- package/dist/host-hooks.d.ts.map +1 -1
- package/dist/host-hooks.js +19 -5
- package/dist/host-hooks.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -14
- package/dist/index.js.map +1 -1
- package/dist/prompts/lead.d.ts +1 -1
- package/dist/prompts/lead.d.ts.map +1 -1
- package/dist/prompts/lead.js +135 -17
- package/dist/prompts/lead.js.map +1 -1
- package/dist/prompts/shared.d.ts +2 -2
- package/dist/prompts/shared.d.ts.map +1 -1
- package/dist/prompts/shared.js +94 -16
- package/dist/prompts/shared.js.map +1 -1
- package/dist/prompts/specialists.d.ts +2 -2
- package/dist/prompts/specialists.d.ts.map +1 -1
- package/dist/prompts/specialists.js +43 -10
- package/dist/prompts/specialists.js.map +1 -1
- package/dist/task-offload.d.ts +67 -0
- package/dist/task-offload.d.ts.map +1 -0
- package/dist/task-offload.js +123 -0
- package/dist/task-offload.js.map +1 -0
- package/dist/tm/args-schema.d.ts +4 -0
- package/dist/tm/args-schema.d.ts.map +1 -1
- package/dist/tm/args-schema.js +44 -3
- package/dist/tm/args-schema.js.map +1 -1
- package/dist/tm/board.d.ts +113 -0
- package/dist/tm/board.d.ts.map +1 -0
- package/dist/tm/board.js +275 -0
- package/dist/tm/board.js.map +1 -0
- package/dist/tm/browser.d.ts +325 -6
- package/dist/tm/browser.d.ts.map +1 -1
- package/dist/tm/browser.js +1329 -135
- package/dist/tm/browser.js.map +1 -1
- package/dist/tm/config.d.ts +36 -1
- package/dist/tm/config.d.ts.map +1 -1
- package/dist/tm/config.js +29 -1
- package/dist/tm/config.js.map +1 -1
- package/dist/tm/dispatch.d.ts +118 -31
- package/dist/tm/dispatch.d.ts.map +1 -1
- package/dist/tm/dispatch.js +385 -131
- package/dist/tm/dispatch.js.map +1 -1
- package/dist/tm/dupe-guard.js +1 -1
- package/dist/tm/dupe-guard.js.map +1 -1
- package/dist/tm/egress.d.ts +44 -0
- package/dist/tm/egress.d.ts.map +1 -0
- package/dist/tm/egress.js +191 -0
- package/dist/tm/egress.js.map +1 -0
- package/dist/tm/guard.js +1 -1
- package/dist/tm/guard.js.map +1 -1
- package/dist/tm/index.d.ts +28 -2
- package/dist/tm/index.d.ts.map +1 -1
- package/dist/tm/index.js +198 -10
- package/dist/tm/index.js.map +1 -1
- package/dist/tm/perm-ask.d.ts +47 -5
- package/dist/tm/perm-ask.d.ts.map +1 -1
- package/dist/tm/perm-ask.js +98 -7
- package/dist/tm/perm-ask.js.map +1 -1
- package/dist/tm/pipelines.d.ts.map +1 -1
- package/dist/tm/pipelines.js +24 -2
- package/dist/tm/pipelines.js.map +1 -1
- package/dist/tm/ptc/tool.d.ts.map +1 -1
- package/dist/tm/ptc/tool.js +2 -4
- package/dist/tm/ptc/tool.js.map +1 -1
- package/dist/tm/pty.d.ts.map +1 -1
- package/dist/tm/pty.js +6 -3
- package/dist/tm/pty.js.map +1 -1
- package/dist/tm/search.d.ts +5 -0
- package/dist/tm/search.d.ts.map +1 -1
- package/dist/tm/search.js +19 -17
- package/dist/tm/search.js.map +1 -1
- package/dist/tm/stats.d.ts +46 -0
- package/dist/tm/stats.d.ts.map +1 -1
- package/dist/tm/stats.js +124 -7
- package/dist/tm/stats.js.map +1 -1
- package/dist/tm/store.d.ts +3 -0
- package/dist/tm/store.d.ts.map +1 -1
- package/dist/tm/store.js +6 -1
- package/dist/tm/store.js.map +1 -1
- package/dist/tm/webfetch.d.ts +52 -0
- package/dist/tm/webfetch.d.ts.map +1 -1
- package/dist/tm/webfetch.js +128 -22
- package/dist/tm/webfetch.js.map +1 -1
- package/dist/tool-coerce.d.ts +24 -0
- package/dist/tool-coerce.d.ts.map +1 -0
- package/dist/tool-coerce.js +63 -0
- package/dist/tool-coerce.js.map +1 -0
- package/dist/types.d.ts +7 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/installation.md +69 -2
- package/package.json +61 -59
|
@@ -136,9 +136,19 @@ For user-visible frontend changes, verify through the governed tm_browser
|
|
|
136
136
|
1. \`open { url }\` once, \`navigate_page\` for follow-ups; take_snapshot
|
|
137
137
|
FIRST and act ONLY on the [uid=…] tokens it returned — guessed
|
|
138
138
|
selectors or guessed text are BANNED (the \`selector\` escape hatch is
|
|
139
|
-
only for a node the snapshot cannot express).
|
|
139
|
+
only for a node the snapshot cannot express). \`open\` also returns the
|
|
140
|
+
id of YOUR browser (\`[b1]\`) and every reply repeats it: one browser
|
|
141
|
+
per agent, so pass \`id\` on each action once another agent has one
|
|
142
|
+
open, and never use somebody else's id — a shared window is how two
|
|
143
|
+
agents end up renumbering each other's uids and clicking the wrong
|
|
144
|
+
element while both report success.
|
|
140
145
|
2. One action, one observation: after click/fill/press_key, take_snapshot
|
|
141
|
-
(or read) again BEFORE concluding; never stack blind actions.
|
|
146
|
+
(or read) again BEFORE concluding; never stack blind actions. A
|
|
147
|
+
"0 个可寻址节点" snapshot is a claim about the page or about our own
|
|
148
|
+
gate — never about the site being empty. Read the note under it: a
|
|
149
|
+
blocked script domain means \`allow_host { host }\` then re-navigate;
|
|
150
|
+
a 安全验证 wall means a human has to pass it, so report UI NOT
|
|
151
|
+
VERIFIED instead of retrying it into the ground.
|
|
142
152
|
3. Popups, dialogs and new tabs fold into the SAME observation round —
|
|
143
153
|
handle_dialog / select_page plus one take_snapshot, not one round each.
|
|
144
154
|
4. Waits: \`wait_for { text }\` inside a 3000 ms budget (the engine
|
|
@@ -230,20 +240,43 @@ You are one of the two network roles (the other is the team lead).
|
|
|
230
240
|
tm_browser it.
|
|
231
241
|
- tm_browser (interactive): snapshot-first automation — open →
|
|
232
242
|
take_snapshot → act ONLY on the [uid=eN] tokens → observe again.
|
|
233
|
-
|
|
234
|
-
hover, drag, press_key, select_page, upload_file, wait_for,
|
|
243
|
+
18 playwright verbs (navigate_page, take_snapshot, click, fill,
|
|
244
|
+
hover, drag, press_key, select_page, new_page, close_page, upload_file, wait_for,
|
|
235
245
|
evaluate_script, list_console_messages, list_network_requests,
|
|
236
246
|
list_pages, take_screenshot, handle_dialog) plus compat verbs open
|
|
237
|
-
/ navigate / read (page text) / screenshot / close.
|
|
247
|
+
/ navigate / read (page text) / screenshot / close. ONE BROWSER PER
|
|
248
|
+
AGENT: open returns YOUR id (\`[b1]\`) and every reply repeats it, so
|
|
249
|
+
pass \`id\` on each action once another agent has a browser open —
|
|
250
|
+
another agent's id is refused with the owner named, because sharing a
|
|
251
|
+
window means two agents renumbering each other's uids. On a desktop
|
|
238
252
|
this opens a VISIBLE window of the user's OWN browser channel (an
|
|
239
253
|
Edge Beta default opens Edge Beta); headless only when the operator
|
|
240
254
|
sets TM_BROWSER_HEADLESS — there is no headless parameter for you
|
|
241
|
-
to pass.
|
|
255
|
+
to pass. Absence of a confirmation dialog is NOT evidence the host
|
|
256
|
+
is on the allowlist: the reply now says which path let a page through
|
|
257
|
+
(静态白名单 / 你刚批准的窗 / 宿主按已记住的"始终允许"秒回). A saved
|
|
258
|
+
"always" is project-wide, so it can let YOUR session through without
|
|
259
|
+
ever asking you — quote the tool's own line instead of concluding
|
|
260
|
+
"该 URL 在白名单内". When a snapshot ends with "N 个子资源请求被拦截" the
|
|
242
261
|
governance gate trimmed the page: that is NOT "the site has no
|
|
243
|
-
images" — report the blocked hosts in FINDINGS instead.
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
262
|
+
images" — report the blocked hosts in FINDINGS instead. And when the
|
|
263
|
+
page comes back with 0 个可寻址节点 WHILE a script host was blocked,
|
|
264
|
+
the blankness is our gate, not an empty site (a site's own bundle can
|
|
265
|
+
live on a brand-unrelated CDN — Baidu's bdimg.com is the standing
|
|
266
|
+
example): call \`allow_host { host }\` for that one domain (one
|
|
267
|
+
official dialog, your browser only, nothing written to config), then
|
|
268
|
+
re-navigate — or name the host in HANDOFF so the user can add it to
|
|
269
|
+
TM_WEBFETCH_ALLOWED_DOMAINS and restart. A reply that calls the page
|
|
270
|
+
a 安全验证 wall is a different fact again: a human has to pass it, so
|
|
271
|
+
change source (another engine, another site) and never write "该网站
|
|
272
|
+
没有内容" about either case. When your
|
|
273
|
+
UI work is done, action:"close" and quote the tool's own verdict —
|
|
274
|
+
已确认关闭 (a pid was checked and is gone) / 进程未核验 (no pid was
|
|
275
|
+
available, so nothing was verified) / 警告:关闭未完全成功 (the
|
|
276
|
+
leftovers are named). Only the first may become "浏览器已关闭" in
|
|
277
|
+
your report; the other two are "窗口可能还在,请用户确认". Never tell
|
|
278
|
+
the user a window is gone because you asked for it to close.
|
|
279
|
+
Isolated temp profile;
|
|
247
280
|
navigation is domain-allowlisted at the network layer.
|
|
248
281
|
2. FALLBACK — user-configured MCP/plugin tools (browser automation, web
|
|
249
282
|
search, page fetchers) for what tm_search / tm_browser / tm_webfetch
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specialists.js","sourceRoot":"","sources":["../../src/prompts/specialists.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B/B,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBjC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2C9B,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG
|
|
1
|
+
{"version":3,"file":"specialists.js","sourceRoot":"","sources":["../../src/prompts/specialists.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B/B,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBjC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2C9B,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqF5B,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsIhC,CAAA"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan B — the host's own background sub-agent, with our context governance.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS FILE EXISTS
|
|
5
|
+
* The built-in `task { background: true }` is the only sub-agent path the
|
|
6
|
+
* desktop can SHOW: its card links to the live child session, and on completion
|
|
7
|
+
* the host wakes the parent by prompting it with a synthetic text part holding
|
|
8
|
+
* the child's FULL reply (`TaskTool.injectBackgroundResult` → `renderOutput` →
|
|
9
|
+
* `ops.prompt({parts:[{type:"text", synthetic:true, text}]})`, read out of the
|
|
10
|
+
* desktop binary). Nothing a plugin returns can ever be that card — the
|
|
11
|
+
* renderer's registry holds only its own tool names.
|
|
12
|
+
*
|
|
13
|
+
* So we take the other half of the deal: the injection is a message arriving at
|
|
14
|
+
* the parent session, and `chat.message` hands plugins that message's `parts`
|
|
15
|
+
* array BEFORE the host persists them (the binary keeps iterating the same
|
|
16
|
+
* `resolvedParts` after the trigger). We swap an oversized body for a preview
|
|
17
|
+
* and a pointer, and the parent gets visibility + wake from the host while the
|
|
18
|
+
* full text stays out of the context window.
|
|
19
|
+
*
|
|
20
|
+
* WHAT THIS MUST NEVER DO
|
|
21
|
+
* Rewrite something the user typed. Three independent locks, all required:
|
|
22
|
+
* 1. `part.synthetic === true` — a typed message is never synthetic;
|
|
23
|
+
* 2. the text must match the host's own `<task id="…" state="completed">`
|
|
24
|
+
* envelope exactly, `<task_result>` included;
|
|
25
|
+
* 3. the body must exceed the same text-tier offload threshold every other
|
|
26
|
+
* governed result passes.
|
|
27
|
+
* Miss any one and the part is left byte-for-byte alone: a false negative costs
|
|
28
|
+
* a big message, a false positive silently deletes someone's content.
|
|
29
|
+
*
|
|
30
|
+
* NO DISK WRITE. The full text already lives in the child session — copying it
|
|
31
|
+
* into our store would put the user's most private payload (this is how the
|
|
32
|
+
* feature gets used) on disk for no gain. The pointer says: `tm_join {ids:[…]}`
|
|
33
|
+
* to pull it deliberately, or open the card.
|
|
34
|
+
*/
|
|
35
|
+
export interface TaskEnvelope {
|
|
36
|
+
/** The child session the host spawned. */
|
|
37
|
+
sessionId: string;
|
|
38
|
+
summary: string;
|
|
39
|
+
body: string;
|
|
40
|
+
}
|
|
41
|
+
/** Parse the host's completed-task envelope; null when it is anything else. */
|
|
42
|
+
export declare function parseTaskEnvelope(text: unknown): TaskEnvelope | null;
|
|
43
|
+
/** The replacement: same envelope, same summary, preview + a way to the whole. */
|
|
44
|
+
export declare function renderOffloadedTask(env: TaskEnvelope, preview: string, tokens: number, previewTokens: number): string;
|
|
45
|
+
export interface TaskOffloadDeps {
|
|
46
|
+
/** TM_TASK_OFFLOAD — off restores the host's verbatim injection. */
|
|
47
|
+
enabled: boolean;
|
|
48
|
+
/** Same text-tier threshold every other governed result obeys. */
|
|
49
|
+
thresholdTokens: number;
|
|
50
|
+
previewLines: number;
|
|
51
|
+
previewMaxTokens: number;
|
|
52
|
+
/** Observability: the hook reports EVERY envelope it recognises, not only
|
|
53
|
+
* the ones it rewrites. A counter that moves only on a rewrite cannot tell
|
|
54
|
+
* "the channel is alive and nothing was big enough" apart from "the host
|
|
55
|
+
* stopped routing injections through chat.message" — and the second case is
|
|
56
|
+
* exactly what a future OpenCode upgrade would do silently. */
|
|
57
|
+
log?: (event: Record<string, unknown>) => void;
|
|
58
|
+
}
|
|
59
|
+
export declare function createTaskOffload(deps: TaskOffloadDeps): (input: {
|
|
60
|
+
sessionID?: string;
|
|
61
|
+
}, output: {
|
|
62
|
+
message?: {
|
|
63
|
+
role?: unknown;
|
|
64
|
+
};
|
|
65
|
+
parts?: Array<Record<string, unknown>>;
|
|
66
|
+
}) => void;
|
|
67
|
+
//# sourceMappingURL=task-offload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-offload.d.ts","sourceRoot":"","sources":["../src/task-offload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAUH,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAiBpE;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAerH;AAED,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,OAAO,EAAE,OAAO,CAAA;IAChB,kEAAkE;IAClE,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;IACxB;;;;oEAIgE;IAChE,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CAC/C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,IAEnD,OAAO;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7B,QAAQ;IAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,KAC/E,IAAI,CAkCR"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan B — the host's own background sub-agent, with our context governance.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS FILE EXISTS
|
|
5
|
+
* The built-in `task { background: true }` is the only sub-agent path the
|
|
6
|
+
* desktop can SHOW: its card links to the live child session, and on completion
|
|
7
|
+
* the host wakes the parent by prompting it with a synthetic text part holding
|
|
8
|
+
* the child's FULL reply (`TaskTool.injectBackgroundResult` → `renderOutput` →
|
|
9
|
+
* `ops.prompt({parts:[{type:"text", synthetic:true, text}]})`, read out of the
|
|
10
|
+
* desktop binary). Nothing a plugin returns can ever be that card — the
|
|
11
|
+
* renderer's registry holds only its own tool names.
|
|
12
|
+
*
|
|
13
|
+
* So we take the other half of the deal: the injection is a message arriving at
|
|
14
|
+
* the parent session, and `chat.message` hands plugins that message's `parts`
|
|
15
|
+
* array BEFORE the host persists them (the binary keeps iterating the same
|
|
16
|
+
* `resolvedParts` after the trigger). We swap an oversized body for a preview
|
|
17
|
+
* and a pointer, and the parent gets visibility + wake from the host while the
|
|
18
|
+
* full text stays out of the context window.
|
|
19
|
+
*
|
|
20
|
+
* WHAT THIS MUST NEVER DO
|
|
21
|
+
* Rewrite something the user typed. Three independent locks, all required:
|
|
22
|
+
* 1. `part.synthetic === true` — a typed message is never synthetic;
|
|
23
|
+
* 2. the text must match the host's own `<task id="…" state="completed">`
|
|
24
|
+
* envelope exactly, `<task_result>` included;
|
|
25
|
+
* 3. the body must exceed the same text-tier offload threshold every other
|
|
26
|
+
* governed result passes.
|
|
27
|
+
* Miss any one and the part is left byte-for-byte alone: a false negative costs
|
|
28
|
+
* a big message, a false positive silently deletes someone's content.
|
|
29
|
+
*
|
|
30
|
+
* NO DISK WRITE. The full text already lives in the child session — copying it
|
|
31
|
+
* into our store would put the user's most private payload (this is how the
|
|
32
|
+
* feature gets used) on disk for no gain. The pointer says: `tm_join {ids:[…]}`
|
|
33
|
+
* to pull it deliberately, or open the card.
|
|
34
|
+
*/
|
|
35
|
+
import { buildPreview } from "./tm/preview.js";
|
|
36
|
+
import { estimateTokens } from "./tm/config.js";
|
|
37
|
+
/** The host's own wrapper — `renderOutput()` in the desktop binary. */
|
|
38
|
+
const ENVELOPE_RE = /^<task id="([^"]+)" state="completed">([\s\S]*)<\/task>$/;
|
|
39
|
+
const RESULT_RE = /<task_result>([\s\S]*)<\/task_result>/;
|
|
40
|
+
const SUMMARY_RE = /<summary>([\s\S]*?)<\/summary>/;
|
|
41
|
+
/** Parse the host's completed-task envelope; null when it is anything else. */
|
|
42
|
+
export function parseTaskEnvelope(text) {
|
|
43
|
+
if (typeof text !== "string")
|
|
44
|
+
return null;
|
|
45
|
+
const t = text.trim();
|
|
46
|
+
const env = ENVELOPE_RE.exec(t);
|
|
47
|
+
if (!env)
|
|
48
|
+
return null;
|
|
49
|
+
const inner = env[2] ?? "";
|
|
50
|
+
const res = RESULT_RE.exec(inner);
|
|
51
|
+
if (!res)
|
|
52
|
+
return null;
|
|
53
|
+
// The host joins its envelope lines with "\n", so the captured body carries
|
|
54
|
+
// the wrapper's newlines — they are not part of the reply.
|
|
55
|
+
const body = (res[1] ?? "").trim();
|
|
56
|
+
if (!body)
|
|
57
|
+
return null;
|
|
58
|
+
return {
|
|
59
|
+
sessionId: (env[1] ?? "").trim(),
|
|
60
|
+
summary: (SUMMARY_RE.exec(inner)?.[1] ?? "").trim(),
|
|
61
|
+
body,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** The replacement: same envelope, same summary, preview + a way to the whole. */
|
|
65
|
+
export function renderOffloadedTask(env, preview, tokens, previewTokens) {
|
|
66
|
+
return [
|
|
67
|
+
`<task id="${env.sessionId}" state="completed">`,
|
|
68
|
+
...(env.summary ? [`<summary>${env.summary}</summary>`] : []),
|
|
69
|
+
`<task_result tokens="${tokens}" delivered="preview-only">`,
|
|
70
|
+
preview,
|
|
71
|
+
``,
|
|
72
|
+
`[TeamMode 上下文治理] 这条后台子任务的完整回复(约 ${tokens} token)没有进入本会话——`,
|
|
73
|
+
`它一个字都没丢,就在子会话 ${env.sessionId} 里。需要时二选一:`,
|
|
74
|
+
`① tm_join { ids: ["${env.sessionId}"] } 取回(可加 includeText:false 只看状态);`,
|
|
75
|
+
`② 在 UI 里点开这张 task 卡片,直接看那个子会话。`,
|
|
76
|
+
`只要上面这段就够回答的问题,不要为此多花一次往返。`,
|
|
77
|
+
`</task_result>`,
|
|
78
|
+
`</task>`,
|
|
79
|
+
].join("\n");
|
|
80
|
+
}
|
|
81
|
+
export function createTaskOffload(deps) {
|
|
82
|
+
return (input, output) => {
|
|
83
|
+
try {
|
|
84
|
+
if (!deps.enabled)
|
|
85
|
+
return;
|
|
86
|
+
// A user-role message is what the injection is; never touch an assistant
|
|
87
|
+
// part, and never touch anything that is not a synthetic text part.
|
|
88
|
+
if (output?.message?.role !== "user")
|
|
89
|
+
return;
|
|
90
|
+
const parts = Array.isArray(output.parts) ? output.parts : [];
|
|
91
|
+
for (const part of parts) {
|
|
92
|
+
if (!part || part.type !== "text" || part.synthetic !== true)
|
|
93
|
+
continue;
|
|
94
|
+
const env = parseTaskEnvelope(part.text);
|
|
95
|
+
if (!env)
|
|
96
|
+
continue;
|
|
97
|
+
const tokens = estimateTokens(env.body);
|
|
98
|
+
const offload = tokens >= deps.thresholdTokens;
|
|
99
|
+
deps.log?.({
|
|
100
|
+
tool: "task_offload",
|
|
101
|
+
step_id: "chat.message",
|
|
102
|
+
event: "envelope",
|
|
103
|
+
action: offload ? "offloaded" : "passthrough",
|
|
104
|
+
session_id: input?.sessionID ?? "",
|
|
105
|
+
child: env.sessionId,
|
|
106
|
+
tokens,
|
|
107
|
+
threshold: deps.thresholdTokens,
|
|
108
|
+
});
|
|
109
|
+
if (!offload)
|
|
110
|
+
continue;
|
|
111
|
+
const preview = buildPreview(env.body, "text", {
|
|
112
|
+
lines: deps.previewLines,
|
|
113
|
+
maxTokens: deps.previewMaxTokens,
|
|
114
|
+
});
|
|
115
|
+
part.text = renderOffloadedTask(env, preview, tokens, estimateTokens(preview));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// A governance hook that throws would eat the message. Fail open, always.
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=task-offload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-offload.js","sourceRoot":"","sources":["../src/task-offload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C,uEAAuE;AACvE,MAAM,WAAW,GAAG,0DAA0D,CAAA;AAC9E,MAAM,SAAS,GAAG,uCAAuC,CAAA;AACzD,MAAM,UAAU,GAAG,gCAAgC,CAAA;AASnD,+EAA+E;AAC/E,MAAM,UAAU,iBAAiB,CAAC,IAAa;IAC7C,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACzC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IACrB,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC/B,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1B,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,4EAA4E;IAC5E,2DAA2D;IAC3D,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IACtB,OAAO;QACL,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QAChC,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QACnD,IAAI;KACL,CAAA;AACH,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,mBAAmB,CAAC,GAAiB,EAAE,OAAe,EAAE,MAAc,EAAE,aAAqB;IAC3G,OAAO;QACL,aAAa,GAAG,CAAC,SAAS,sBAAsB;QAChD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,wBAAwB,MAAM,6BAA6B;QAC3D,OAAO;QACP,EAAE;QACF,mCAAmC,MAAM,kBAAkB;QAC3D,iBAAiB,GAAG,CAAC,SAAS,YAAY;QAC1C,sBAAsB,GAAG,CAAC,SAAS,qCAAqC;QACxE,gCAAgC;QAChC,2BAA2B;QAC3B,gBAAgB;QAChB,SAAS;KACV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAiBD,MAAM,UAAU,iBAAiB,CAAC,IAAqB;IACrD,OAAO,CACL,KAA6B,EAC7B,MAAgF,EAC1E,EAAE;QACR,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,OAAO;gBAAE,OAAM;YACzB,yEAAyE;YACzE,oEAAoE;YACpE,IAAI,MAAM,EAAE,OAAO,EAAE,IAAI,KAAK,MAAM;gBAAE,OAAM;YAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;YAC7D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;oBAAE,SAAQ;gBACtE,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACxC,IAAI,CAAC,GAAG;oBAAE,SAAQ;gBAClB,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBACvC,MAAM,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC,eAAe,CAAA;gBAC9C,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,cAAc;oBACvB,KAAK,EAAE,UAAU;oBACjB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa;oBAC7C,UAAU,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE;oBAClC,KAAK,EAAE,GAAG,CAAC,SAAS;oBACpB,MAAM;oBACN,SAAS,EAAE,IAAI,CAAC,eAAe;iBAChC,CAAC,CAAA;gBACF,IAAI,CAAC,OAAO;oBAAE,SAAQ;gBACtB,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE;oBAC7C,KAAK,EAAE,IAAI,CAAC,YAAY;oBACxB,SAAS,EAAE,IAAI,CAAC,gBAAgB;iBACjC,CAAC,CAAA;gBACF,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;YAChF,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;QAC5E,CAAC;IACH,CAAC,CAAA;AACH,CAAC"}
|
package/dist/tm/args-schema.d.ts
CHANGED
|
@@ -69,4 +69,8 @@ export declare function buildMemoryArgsSchema(): Promise<Record<string, unknown>
|
|
|
69
69
|
* is the fix, not a validation layer.
|
|
70
70
|
*/
|
|
71
71
|
export declare function buildBrowserArgsSchema(): Promise<Record<string, unknown>>;
|
|
72
|
+
/** tm_board_write — four strings, and the shape of the PATH is the tool's
|
|
73
|
+
* business, not the model's (that is what makes it safe to hand a writer to a
|
|
74
|
+
* role that owns no file tool). */
|
|
75
|
+
export declare function buildBoardArgsSchema(): Promise<Record<string, unknown>>;
|
|
72
76
|
//# sourceMappingURL=args-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args-schema.d.ts","sourceRoot":"","sources":["../../src/tm/args-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"args-schema.d.ts","sourceRoot":"","sources":["../../src/tm/args-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAuCH,iBAAe,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAuFlF;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAE3B;;;;;GAKG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA2D3E;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA0ChF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA2BlC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA+C9E;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAyE/E;AACD;;oCAEoC;AACpC,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAoB7E"}
|
package/dist/tm/args-schema.js
CHANGED
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
* times), even though flat args reached execute fine.
|
|
10
10
|
*/
|
|
11
11
|
import { resolveTmConfig } from "./config.js";
|
|
12
|
+
// The browser verb list lives in ONE place (browser.ts). A second hand-written
|
|
13
|
+
// copy here is how a shipped verb went missing from the tool schema.
|
|
14
|
+
import { BROWSER_ACTION_MENU, BROWSER_PLAYWRIGHT_ACTIONS } from "./browser.js";
|
|
12
15
|
/**
|
|
13
16
|
* Load zod when the host environment provides it (opencode ships it as a
|
|
14
17
|
* peer); fall back to plain arg descriptors so the plugin never hard-depends
|
|
@@ -152,6 +155,7 @@ export async function buildWebfetchArgsSchema() {
|
|
|
152
155
|
return {
|
|
153
156
|
url: { descriptor: "url: string (required, absolute https URL on an allowlisted host, query URL-encoded)" },
|
|
154
157
|
fields: { descriptor: "fields: string (optional, dot-path projection over a JSON response, e.g. items[].name; ignored on non-JSON)" },
|
|
158
|
+
fresh: { descriptor: "fresh: true (optional — bypass the URL cache and hit the network)" },
|
|
155
159
|
};
|
|
156
160
|
}
|
|
157
161
|
// describe-LAST on the optional `fields` chain (zod v4 drops a
|
|
@@ -165,6 +169,13 @@ export async function buildWebfetchArgsSchema() {
|
|
|
165
169
|
.string()
|
|
166
170
|
.optional()
|
|
167
171
|
.describe("Dot-path projection over a JSON response body (Wave B M2): e.g. items[].name or user.email — returns ONLY the matched values, mirroring tm_fetch's `fields`. Ignored when the response is not JSON."),
|
|
172
|
+
// The cache is a throughput win with a freshness cost, so the escape hatch
|
|
173
|
+
// has to be on the model-visible surface: "the page changed" is a claim
|
|
174
|
+
// only a real fetch can settle.
|
|
175
|
+
fresh: zz
|
|
176
|
+
.boolean()
|
|
177
|
+
.optional()
|
|
178
|
+
.describe("Bypass the URL cache (TM_WEB_CACHE_TTL_SEC) and fetch the network again — use when you specifically need the page as it is NOW, e.g. you expect it changed since a cached read."),
|
|
168
179
|
};
|
|
169
180
|
}
|
|
170
181
|
/**
|
|
@@ -275,11 +286,17 @@ export async function buildMemoryArgsSchema() {
|
|
|
275
286
|
*/
|
|
276
287
|
export async function buildBrowserArgsSchema() {
|
|
277
288
|
const z = await loadZod();
|
|
278
|
-
|
|
289
|
+
// Derived from the action table itself (browser.ts) — the hand-written verb
|
|
290
|
+
// list here is how `new_page` and `close_page` went missing from the schema
|
|
291
|
+
// while the gate accepted them.
|
|
292
|
+
const ACTION_LIST = `${BROWSER_ACTION_MENU} (required) — the ${BROWSER_PLAYWRIGHT_ACTIONS.length} chrome-devtools-mcp verbs, ` +
|
|
293
|
+
`plus open|navigate|read|screenshot|close (compat) and allow_host (ask the user to un-block ONE script domain).`;
|
|
279
294
|
if (!z) {
|
|
280
295
|
return {
|
|
281
|
-
action: { descriptor: `action: ${ACTION_LIST}
|
|
282
|
-
|
|
296
|
+
action: { descriptor: `action: ${ACTION_LIST}` },
|
|
297
|
+
id: { descriptor: 'id: which browser ("b1" from open) — one per agent; required once more than one is live, another agent\'s id is refused' },
|
|
298
|
+
url: { descriptor: "url: string (open/navigate/navigate_page/new_page, allowlisted https)" },
|
|
299
|
+
host: { descriptor: "host: one bare domain for allow_host (no wildcards, no URL, no port)" },
|
|
283
300
|
image: { descriptor: "image: true with take_screenshot — inline the PNG pixels in this result" },
|
|
284
301
|
uid: { descriptor: "uid: snapshot [uid=eN] token (click/fill/hover/drag/upload_file/wait_for)" },
|
|
285
302
|
selector: { descriptor: "selector: CSS/text locator escape hatch (only when a snapshot cannot express the node)" },
|
|
@@ -306,7 +323,9 @@ export async function buildBrowserArgsSchema() {
|
|
|
306
323
|
const bool = (d) => zz.boolean().optional().describe(d);
|
|
307
324
|
return {
|
|
308
325
|
action: zz.string().describe(ACTION_LIST),
|
|
326
|
+
id: str('Which browser to drive — the id `open` returned ("b1"). Each agent gets its OWN browser: the id is required as soon as more than one is live, another agent\'s id is refused with the owner named, and close {id:"all"} closes all of yours.'),
|
|
309
327
|
url: str("Absolute https URL on an allowlisted host (open/navigate/navigate_page). URL-encode the query (CJK terms too)."),
|
|
328
|
+
host: str("allow_host only: ONE bare domain whose script the subresource gate blocked (e.g. bkssl.bdimg.com). Wildcards/URLs/ports are refused — the user approves exactly this string."),
|
|
310
329
|
image: bool("take_screenshot only: inline the PNG pixels into this tool result (default false = path only; pixels cost context, so ask only when the screenshot IS the evidence)."),
|
|
311
330
|
uid: str("Snapshot [uid=eN] token from the LATEST take_snapshot (click/fill/hover/drag source/upload_file/wait_for)."),
|
|
312
331
|
selector: str("CSS/text locator escape hatch — only for a node the snapshot cannot express; never guess locators."),
|
|
@@ -326,4 +345,26 @@ export async function buildBrowserArgsSchema() {
|
|
|
326
345
|
fullPage: bool("take_screenshot captures the full page (default: viewport only)."),
|
|
327
346
|
};
|
|
328
347
|
}
|
|
348
|
+
/** tm_board_write — four strings, and the shape of the PATH is the tool's
|
|
349
|
+
* business, not the model's (that is what makes it safe to hand a writer to a
|
|
350
|
+
* role that owns no file tool). */
|
|
351
|
+
export async function buildBoardArgsSchema() {
|
|
352
|
+
const z = await loadZod();
|
|
353
|
+
if (!z) {
|
|
354
|
+
return {
|
|
355
|
+
task: { descriptor: "task: task-slug folder (required)" },
|
|
356
|
+
topic: { descriptor: "topic: file topic (required)" },
|
|
357
|
+
content: { descriptor: "content: the deliverable text (required)" },
|
|
358
|
+
session: { descriptor: "session: existing session-key folder (optional; stamped when omitted)" },
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
const zz = z;
|
|
362
|
+
const str = (d) => zz.string().optional().describe(d);
|
|
363
|
+
return {
|
|
364
|
+
task: zz.string().describe("Task-slug folder under the session — use the one the dispatch named (a new slug creates it). Path separators collapse to '-', so 'auth/design' becomes 'auth-design'."),
|
|
365
|
+
topic: zz.string().describe("What this file IS (design / report / findings). It becomes NN-<your-role>-<topic>.md; the NN and any -rN revision suffix are chosen here and a revision NEVER overwrites."),
|
|
366
|
+
content: zz.string().describe("The deliverable itself. It goes to disk and is NOT echoed back — after the write, the report carries the path this tool returns, never the text."),
|
|
367
|
+
session: str("The conversation's session-key folder. Pass the one the lead's dispatch named so every role writes into the same folder; omit it and this tool stamps yyyyMMdd-HHmmss for you."),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
329
370
|
//# sourceMappingURL=args-schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args-schema.js","sourceRoot":"","sources":["../../src/tm/args-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"args-schema.js","sourceRoot":"","sources":["../../src/tm/args-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tm_board_write — the write side of the blackboard (2026-09-23).
|
|
3
|
+
*
|
|
4
|
+
* Why it exists: the board is the one place an oversized deliverable is
|
|
5
|
+
* supposed to go, but reaching it needs a file tool — and three of the six
|
|
6
|
+
* roles carry none. `architect` and `researcher` have no write/edit/bash at
|
|
7
|
+
* all (a deliberate permission-matrix decision), so every "write the design
|
|
8
|
+
* doc to the board" dispatch ended as `BLACKBOARD WRITE FAILED` with the
|
|
9
|
+
* document pasted inline anyway — the reply shape this team exists to enforce
|
|
10
|
+
* (skeleton + path, never a wall of text) was un-followable for exactly the two
|
|
11
|
+
* roles that produce the longest artifacts. Even the documented session folder
|
|
12
|
+
* is out of reach: creating it means running `Get-Date`, which those roles
|
|
13
|
+
* cannot run either.
|
|
14
|
+
*
|
|
15
|
+
* What this is NOT: a general file writer. It places a NEW markdown file
|
|
16
|
+
* inside `<board-root>/<session-key>/<task-slug>/` and nothing else — no
|
|
17
|
+
* overwrite (a revision is a new `-rN` round, per the documented layout), no
|
|
18
|
+
* traversal (each segment is a sanitized slug, then realpath-verified against
|
|
19
|
+
* the root), no workspace or user paths, no `.env` family. The reply returns
|
|
20
|
+
* the path plus the byte count, never the content: bytes riding back through
|
|
21
|
+
* the context window is the very thing the board exists to avoid.
|
|
22
|
+
*/
|
|
23
|
+
import type { ToolResult } from "../types.js";
|
|
24
|
+
import type { TmPipelines } from "./pipelines.js";
|
|
25
|
+
/** Content cap for one board file (characters). A deliverable past this is not
|
|
26
|
+
* a board file — it is two, or it is the wrong tool. */
|
|
27
|
+
export declare const BOARD_MAX_CONTENT_CHARS = 200000;
|
|
28
|
+
/** Files per session folder (across its task dirs): the TTL sweeper is the only
|
|
29
|
+
* reclaim path by design, so an unbounded count is a disk leak. */
|
|
30
|
+
export declare const BOARD_MAX_FILES_PER_SESSION = 200;
|
|
31
|
+
export declare const BOARD_MAX_TASKS_PER_SESSION = 40;
|
|
32
|
+
/** `yyyyMMdd-HHmmss`, local — the SAME shape the blackboard note tells the lead
|
|
33
|
+
* to build with `Get-Date -Format yyyyMMdd-HHmmss` / `date +%Y%m%d-%H%M%S`, so
|
|
34
|
+
* a tool-made session folder is indistinguishable from a hand-made one. */
|
|
35
|
+
export declare function sessionKeyStamp(now?: Date): string;
|
|
36
|
+
/**
|
|
37
|
+
* One path segment out of untrusted model text. Separators and `..` are
|
|
38
|
+
* REWRITTEN rather than rejected (a model that writes `auth/design` means the
|
|
39
|
+
* task `auth-design`), anything that cannot survive a filename is dropped, and
|
|
40
|
+
* CJK is preserved because this project's users write CJK. "" means "nothing
|
|
41
|
+
* usable was given", which the caller turns into an args error.
|
|
42
|
+
*/
|
|
43
|
+
export declare function sanitizeSlug(raw: unknown, max?: number): string;
|
|
44
|
+
/** `NN` for the next file in a task dir: max existing ordinal + 1, so a hand
|
|
45
|
+
* -written `07-…md` the lead created is counted too. */
|
|
46
|
+
export declare function nextOrdinal(names: readonly string[]): number;
|
|
47
|
+
/** The round suffix for a revision: "" when the base name is free, else
|
|
48
|
+
* `-r2`, `-r3`… — never a rewrite, because the board's history IS the audit
|
|
49
|
+
* trail the lead reads back. */
|
|
50
|
+
export declare function roundSuffix(names: readonly string[], base: string): string;
|
|
51
|
+
/** The `NN` that anchors a revision: a family keeps the number its first file
|
|
52
|
+
* got, so `01-architect-design.md` and `01-architect-design-r2.md` sit
|
|
53
|
+
* together in a listing. Advancing the ordinal instead (the first version of
|
|
54
|
+
* this code did) means a revision never gets the `-rN` suffix the documented
|
|
55
|
+
* layout promises, and the round history becomes invisible. */
|
|
56
|
+
export declare function findFamily(names: readonly string[], role: string, topic: string): {
|
|
57
|
+
base: string;
|
|
58
|
+
round: string;
|
|
59
|
+
} | null;
|
|
60
|
+
export interface BoardTarget {
|
|
61
|
+
dir: string;
|
|
62
|
+
file: string;
|
|
63
|
+
rel: string;
|
|
64
|
+
round: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Plan the write: `<root>/<session>/<task>/<NN>-<role>-<topic><round>.md`.
|
|
68
|
+
* Every segment is sanitized and the resolved session/task pair is checked
|
|
69
|
+
* against the root by REALPATH, because a task dir somebody made earlier could
|
|
70
|
+
* be a symlink pointing at `~/.ssh` — and a writer that only strings paths
|
|
71
|
+
* together would follow it happily.
|
|
72
|
+
*/
|
|
73
|
+
export declare function planBoardWrite(opts: {
|
|
74
|
+
root: string;
|
|
75
|
+
session: string;
|
|
76
|
+
task: string;
|
|
77
|
+
role: string;
|
|
78
|
+
topic: string;
|
|
79
|
+
list: (dir: string) => string[];
|
|
80
|
+
}): BoardTarget | {
|
|
81
|
+
error: string;
|
|
82
|
+
};
|
|
83
|
+
/** Count what this session folder already holds, so the caps can be enforced
|
|
84
|
+
* before another 400 files arrive. Never throws: an unreadable tree simply
|
|
85
|
+
* counts as nothing. */
|
|
86
|
+
export declare function sessionUsage(root: string, session: string): {
|
|
87
|
+
files: number;
|
|
88
|
+
tasks: number;
|
|
89
|
+
};
|
|
90
|
+
/** Atomic-ish: write a sibling temp file then rename, so a crash mid-write
|
|
91
|
+
* cannot leave a half-written board file that a reader mistakes for the real
|
|
92
|
+
* deliverable. (win32 rename over an existing target throws — which is fine
|
|
93
|
+
* here, because the name was chosen as unused.) */
|
|
94
|
+
export declare function writeNewFile(file: string, text: string): void;
|
|
95
|
+
export declare function buildBoardWriteTool(deps: {
|
|
96
|
+
pipelines: TmPipelines;
|
|
97
|
+
/** The board root the blackboard note publishes: `<repo>/.git/opencode-team`
|
|
98
|
+
* (or the sharded temp fallback). Injected, not recomputed, so a write can
|
|
99
|
+
* never land somewhere the lead was never told to read. */
|
|
100
|
+
boardRoot: string;
|
|
101
|
+
cfg?: {
|
|
102
|
+
boardMaxChars?: number;
|
|
103
|
+
boardMaxFiles?: number;
|
|
104
|
+
};
|
|
105
|
+
args?: Record<string, unknown>;
|
|
106
|
+
/** seam for the session-key stamp in tests */
|
|
107
|
+
stamp?: () => string;
|
|
108
|
+
}): {
|
|
109
|
+
description: string;
|
|
110
|
+
args: Record<string, unknown>;
|
|
111
|
+
execute: (rawArgs: Record<string, unknown>, ctx: unknown) => Promise<ToolResult>;
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=board.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/tm/board.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAkB,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD;yDACyD;AACzD,eAAO,MAAM,uBAAuB,SAAU,CAAA;AAC9C;oEACoE;AACpE,eAAO,MAAM,2BAA2B,MAAM,CAAA;AAC9C,eAAO,MAAM,2BAA2B,KAAK,CAAA;AAE7C;;4EAE4E;AAC5E,wBAAgB,eAAe,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAM9D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,SAAK,GAAG,MAAM,CAU3D;AAED;yDACyD;AACzD,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAO5D;AAED;;iCAEiC;AACjC,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAK1E;AAED;;;;gEAIgE;AAChE,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAaxC;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EAAE,CAAA;CAChC,GAAG,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAkClC;AAED;;yBAEyB;AACzB,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiB5F;AAED;;;oDAGoD;AACpD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAa7D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,SAAS,EAAE,WAAW,CAAA;IACtB;;gEAE4D;IAC5D,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;CACrB,GAAG;IACF,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;CACjF,CA4FA"}
|