@te-river/opencode-team-mode 1.6.0 → 1.6.1

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.
Files changed (150) hide show
  1. package/README.md +80 -15
  2. package/README.zh-CN.md +67 -18
  3. package/dist/host/note.d.ts +7 -0
  4. package/dist/host/note.d.ts.map +1 -0
  5. package/dist/host/note.js +28 -0
  6. package/dist/host/note.js.map +1 -0
  7. package/dist/host/v1.d.ts +14 -0
  8. package/dist/host/v1.d.ts.map +1 -0
  9. package/dist/host/v1.js +340 -0
  10. package/dist/host/v1.js.map +1 -0
  11. package/dist/host/v2-browser-gate.d.ts +45 -0
  12. package/dist/host/v2-browser-gate.d.ts.map +1 -0
  13. package/dist/host/v2-browser-gate.js +319 -0
  14. package/dist/host/v2-browser-gate.js.map +1 -0
  15. package/dist/host/v2-capabilities.d.ts +68 -0
  16. package/dist/host/v2-capabilities.d.ts.map +1 -0
  17. package/dist/host/v2-capabilities.js +146 -0
  18. package/dist/host/v2-capabilities.js.map +1 -0
  19. package/dist/host/v2-client.d.ts +53 -0
  20. package/dist/host/v2-client.d.ts.map +1 -0
  21. package/dist/host/v2-client.js +193 -0
  22. package/dist/host/v2-client.js.map +1 -0
  23. package/dist/host/v2-events.d.ts +56 -0
  24. package/dist/host/v2-events.d.ts.map +1 -0
  25. package/dist/host/v2-events.js +158 -0
  26. package/dist/host/v2-events.js.map +1 -0
  27. package/dist/host/v2-guard.d.ts +101 -0
  28. package/dist/host/v2-guard.d.ts.map +1 -0
  29. package/dist/host/v2-guard.js +199 -0
  30. package/dist/host/v2-guard.js.map +1 -0
  31. package/dist/host/v2-offload.d.ts +148 -0
  32. package/dist/host/v2-offload.d.ts.map +1 -0
  33. package/dist/host/v2-offload.js +288 -0
  34. package/dist/host/v2-offload.js.map +1 -0
  35. package/dist/host/v2-permissions.d.ts +123 -0
  36. package/dist/host/v2-permissions.d.ts.map +1 -0
  37. package/dist/host/v2-permissions.js +190 -0
  38. package/dist/host/v2-permissions.js.map +1 -0
  39. package/dist/host/v2-probe.d.ts +85 -0
  40. package/dist/host/v2-probe.d.ts.map +1 -0
  41. package/dist/host/v2-probe.js +268 -0
  42. package/dist/host/v2-probe.js.map +1 -0
  43. package/dist/host/v2-scope.d.ts +51 -0
  44. package/dist/host/v2-scope.d.ts.map +1 -0
  45. package/dist/host/v2-scope.js +58 -0
  46. package/dist/host/v2-scope.js.map +1 -0
  47. package/dist/host/v2-session-client.d.ts +74 -0
  48. package/dist/host/v2-session-client.d.ts.map +1 -0
  49. package/dist/host/v2-session-client.js +171 -0
  50. package/dist/host/v2-session-client.js.map +1 -0
  51. package/dist/host/v2-session.d.ts +85 -0
  52. package/dist/host/v2-session.d.ts.map +1 -0
  53. package/dist/host/v2-session.js +171 -0
  54. package/dist/host/v2-session.js.map +1 -0
  55. package/dist/host/v2-subagent.d.ts +157 -0
  56. package/dist/host/v2-subagent.d.ts.map +1 -0
  57. package/dist/host/v2-subagent.js +286 -0
  58. package/dist/host/v2-subagent.js.map +1 -0
  59. package/dist/host/v2-tool.d.ts +67 -0
  60. package/dist/host/v2-tool.d.ts.map +1 -0
  61. package/dist/host/v2-tool.js +209 -0
  62. package/dist/host/v2-tool.js.map +1 -0
  63. package/dist/host/v2-transcript.d.ts +73 -0
  64. package/dist/host/v2-transcript.d.ts.map +1 -0
  65. package/dist/host/v2-transcript.js +151 -0
  66. package/dist/host/v2-transcript.js.map +1 -0
  67. package/dist/host/v2-types.d.ts +229 -0
  68. package/dist/host/v2-types.d.ts.map +1 -0
  69. package/dist/host/v2-types.js +17 -0
  70. package/dist/host/v2-types.js.map +1 -0
  71. package/dist/host/v2.d.ts +42 -0
  72. package/dist/host/v2.d.ts.map +1 -0
  73. package/dist/host/v2.js +706 -0
  74. package/dist/host/v2.js.map +1 -0
  75. package/dist/index.d.ts +23 -17
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +29 -366
  78. package/dist/index.js.map +1 -1
  79. package/dist/prompts/lead.d.ts +1 -1
  80. package/dist/prompts/lead.d.ts.map +1 -1
  81. package/dist/prompts/lead.js +452 -426
  82. package/dist/prompts/lead.js.map +1 -1
  83. package/dist/prompts/shared.d.ts +2 -2
  84. package/dist/prompts/shared.d.ts.map +1 -1
  85. package/dist/prompts/shared.js +30 -10
  86. package/dist/prompts/shared.js.map +1 -1
  87. package/dist/prompts/specialists.d.ts +2 -2
  88. package/dist/prompts/specialists.d.ts.map +1 -1
  89. package/dist/prompts/specialists.js +7 -6
  90. package/dist/prompts/specialists.js.map +1 -1
  91. package/dist/task-offload.d.ts +16 -0
  92. package/dist/task-offload.d.ts.map +1 -1
  93. package/dist/task-offload.js +51 -0
  94. package/dist/task-offload.js.map +1 -1
  95. package/dist/tm/browser.d.ts.map +1 -1
  96. package/dist/tm/browser.js +41 -10
  97. package/dist/tm/browser.js.map +1 -1
  98. package/dist/tm/dispatch.d.ts +47 -0
  99. package/dist/tm/dispatch.d.ts.map +1 -1
  100. package/dist/tm/dispatch.js +230 -31
  101. package/dist/tm/dispatch.js.map +1 -1
  102. package/dist/tm/dupe-guard.d.ts +16 -3
  103. package/dist/tm/dupe-guard.d.ts.map +1 -1
  104. package/dist/tm/dupe-guard.js +27 -7
  105. package/dist/tm/dupe-guard.js.map +1 -1
  106. package/dist/tm/index.d.ts +40 -1
  107. package/dist/tm/index.d.ts.map +1 -1
  108. package/dist/tm/index.js +40 -11
  109. package/dist/tm/index.js.map +1 -1
  110. package/dist/tm/ledger.d.ts +114 -0
  111. package/dist/tm/ledger.d.ts.map +1 -0
  112. package/dist/tm/ledger.js +308 -0
  113. package/dist/tm/ledger.js.map +1 -0
  114. package/dist/tm/perm-ask.d.ts +1 -3
  115. package/dist/tm/perm-ask.d.ts.map +1 -1
  116. package/dist/tm/perm-ask.js +10 -1
  117. package/dist/tm/perm-ask.js.map +1 -1
  118. package/dist/tm/preview.d.ts +55 -0
  119. package/dist/tm/preview.d.ts.map +1 -1
  120. package/dist/tm/preview.js +225 -0
  121. package/dist/tm/preview.js.map +1 -1
  122. package/dist/tm/search.d.ts.map +1 -1
  123. package/dist/tm/search.js +40 -10
  124. package/dist/tm/search.js.map +1 -1
  125. package/dist/tm/serp-loop.d.ts +45 -0
  126. package/dist/tm/serp-loop.d.ts.map +1 -0
  127. package/dist/tm/serp-loop.js +80 -0
  128. package/dist/tm/serp-loop.js.map +1 -0
  129. package/dist/tm/stats.d.ts +10 -0
  130. package/dist/tm/stats.d.ts.map +1 -1
  131. package/dist/tm/stats.js +160 -0
  132. package/dist/tm/stats.js.map +1 -1
  133. package/dist/tm/webfetch.d.ts +4 -0
  134. package/dist/tm/webfetch.d.ts.map +1 -1
  135. package/dist/tm/webfetch.js +75 -8
  136. package/dist/tm/webfetch.js.map +1 -1
  137. package/docs/installation-v2.md +436 -0
  138. package/docs/installation.md +12 -0
  139. package/docs/research/agent-data-exchange.md +117 -0
  140. package/docs/research/browser-pane.md +89 -0
  141. package/docs/research/host-http-api.md +132 -0
  142. package/docs/research/host-subagent-injection.md +187 -0
  143. package/docs/research/plugin-loader-contract.md +261 -0
  144. package/docs/research/v2-builtin-tools.md +447 -0
  145. package/docs/v2-port-notes.md +315 -0
  146. package/index.js +7 -0
  147. package/package.json +64 -61
  148. package/scripts/gen-v2-config.mjs +304 -0
  149. package/scripts/lib/config-surgery.cjs +239 -0
  150. package/scripts/lib/fake-ctx.mjs +146 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-session-client.js","sourceRoot":"","sources":["../../src/host/v2-session-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * The v2 session-request layer (goal #4 and #6 of the product).
3
+ *
4
+ * Three things that v1 could only approximate, because 1.18.x gave a plugin one
5
+ * mutable slot before execution and no way to touch an assembled request:
6
+ *
7
+ * 1. the tool surface. v1's whitelist was enforced by permission DENY, which
8
+ * stops a call but leaves the tool's description and schema in EVERY request
9
+ * — the model pays ~9.5K tokens for thirteen governed tools plus the native
10
+ * catalog it is forbidden to use. `session.hook("context")` can `delete
11
+ * event.tools.<name>`, so the whitelist finally decides what the model sees.
12
+ * 2. `temperature`. It is a documented legacy agent field on v2 (and the
13
+ * runner "preserves these values but does not yet send them"), so the
14
+ * all-agents-0.2 invariant has to be set on the outgoing request instead.
15
+ * 3. the blackboard root. v1 appended the resolved path to the team prompt at
16
+ * config time; a v2 agent is a config FILE, which cannot carry a
17
+ * per-workspace path, so it goes on the request.
18
+ *
19
+ * Everything here is additive and reversible: each hook returns a disposable
20
+ * registration, and nothing is claimed that the host did not hand us.
21
+ */
22
+ import type { V2Registration, V2Context } from "./v2-types.js";
23
+ /** Sentinel for "this role may not browse at all" — it removes the host's whole
24
+ * browser catalog (45 `browser_*` tools on 2.0.16), not just our own door.
25
+ * Leaving them in would hand back, at the request layer, exactly the surface the
26
+ * whitelist exists to withhold. */
27
+ export declare const BROWSER_CATALOG = "browser_*";
28
+ /**
29
+ * The tools one agent must never be offered. Only a literal `deny` removes:
30
+ * the `{ "*": "ask" }` object form means "callable, gated", and deleting such a
31
+ * tool would silently drop a capability the matrix grants with a dialog.
32
+ *
33
+ * `read`/`grep`/`glob` are exempted by name (`V2_LADDER_ACTIONS`), which is the
34
+ * other half of the `tm_read`/`tm_grep`/`tm_bash` retirement: v1 denied the
35
+ * native file tools because the governed aliases existed, and on v2 those
36
+ * aliases are not registered, so honouring the deny here would leave a role with
37
+ * no way to open a file at all. Nothing is lost by letting them ride — the path
38
+ * scope P2 enforced in code is the host's own `external_directory` action, which
39
+ * was observed live answering `effect:"ask"` with a real `permission.asked`
40
+ * behind it, i.e. a dialog instead of a hard throw.
41
+ */
42
+ export declare function toolsToRemove(permission: Record<string, unknown> | undefined | null): string[];
43
+ /** Built once per agent id so the hook body stays a set lookup on a hot path. */
44
+ export declare function removalPlan(agents: Record<string, {
45
+ permission?: Record<string, unknown>;
46
+ }>): Map<string, Set<string>>;
47
+ export interface SessionLayerInput {
48
+ /** 0 disables the temperature write entirely (the host's model default wins). */
49
+ temperature: number | false;
50
+ /** The resolved blackboard addendum, or "" when there is nothing to say. */
51
+ note: string;
52
+ /** Which agent ids receive the note — v1 gave it to the lead only. */
53
+ noteAgents: string[];
54
+ plan: Map<string, Set<string>>;
55
+ /** Team-scope isolation (#22). `session.context` fires for EVERY agent on the
56
+ * host, so temperature, the board note and the compaction survival list are
57
+ * writes to somebody else's request unless the agent is one of ours. The tool
58
+ * trim is already keyed by agent (a foreign role is not in the plan, so nothing
59
+ * is deleted); this closes the other three. */
60
+ scope?: import("./v2-scope.js").TeamScope;
61
+ }
62
+ export interface SessionLayerReport {
63
+ temperature: number | false;
64
+ removed: Record<string, number>;
65
+ notePushed: boolean;
66
+ compactionLines: number;
67
+ /** Did a `tm_*` name ever appear in an assembled request's own tool surface?
68
+ * This is the only evidence that direct delivery happened: `options.codemode:false`
69
+ * is what WE send, and a live 2.0.16 session proved the host still put every
70
+ * `tm_*` in the Code Mode catalog ("They cannot be called directly…") while the
71
+ * model's own callable list was nine native tools. Reporting the sent flag as if it
72
+ * were the outcome is the overstated claim this product exists to refuse. */
73
+ tmInRequestSurface: boolean;
74
+ }
75
+ /**
76
+ * Register the request-layer hooks. Returns the registrations (so the caller
77
+ * can dispose them) and a live report object — the counts are read off what the
78
+ * hooks actually did, not off what the matrix intends, because "we trimmed the
79
+ * surface" is a claim the user can only check against the request.
80
+ */
81
+ export declare function applyV2SessionLayer(ctx: V2Context, input: SessionLayerInput): Promise<{
82
+ registrations: V2Registration[];
83
+ report: SessionLayerReport;
84
+ }>;
85
+ //# sourceMappingURL=v2-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-session.d.ts","sourceRoot":"","sources":["../../src/host/v2-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAoB,SAAS,EAAE,MAAM,eAAe,CAAA;AAUhF;;;oCAGoC;AACpC,eAAO,MAAM,eAAe,cAAc,CAAA;AAI1C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,EAAE,CAyB9F;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GAC/D,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAI1B;AAKD,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,WAAW,EAAE,MAAM,GAAG,KAAK,CAAA;IAC3B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAA;IACZ,sEAAsE;IACtE,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;IAC9B;;;;oDAIgD;IAChD,KAAK,CAAC,EAAE,OAAO,eAAe,EAAE,SAAS,CAAA;CAC1C;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,UAAU,EAAE,OAAO,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB;;;;;kFAK8E;IAC9E,kBAAkB,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC;IAAE,aAAa,EAAE,cAAc,EAAE,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAC,CAgF1E"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * The v2 session-request layer (goal #4 and #6 of the product).
3
+ *
4
+ * Three things that v1 could only approximate, because 1.18.x gave a plugin one
5
+ * mutable slot before execution and no way to touch an assembled request:
6
+ *
7
+ * 1. the tool surface. v1's whitelist was enforced by permission DENY, which
8
+ * stops a call but leaves the tool's description and schema in EVERY request
9
+ * — the model pays ~9.5K tokens for thirteen governed tools plus the native
10
+ * catalog it is forbidden to use. `session.hook("context")` can `delete
11
+ * event.tools.<name>`, so the whitelist finally decides what the model sees.
12
+ * 2. `temperature`. It is a documented legacy agent field on v2 (and the
13
+ * runner "preserves these values but does not yet send them"), so the
14
+ * all-agents-0.2 invariant has to be set on the outgoing request instead.
15
+ * 3. the blackboard root. v1 appended the resolved path to the team prompt at
16
+ * config time; a v2 agent is a config FILE, which cannot carry a
17
+ * per-workspace path, so it goes on the request.
18
+ *
19
+ * Everything here is additive and reversible: each hook returns a disposable
20
+ * registration, and nothing is claimed that the host did not hand us.
21
+ */
22
+ import { COMPACTION_CONTEXT } from "../host-hooks.js";
23
+ import { V2_LADDER_ACTIONS } from "./v2-permissions.js";
24
+ /** v1 named three built-in tools differently from v2's tool ids. Anything not
25
+ * listed is already spelled the same on both sides. */
26
+ const TOOL_RENAMES = {
27
+ bash: "shell",
28
+ task: "subagent",
29
+ apply_patch: "patch",
30
+ };
31
+ /** Sentinel for "this role may not browse at all" — it removes the host's whole
32
+ * browser catalog (45 `browser_*` tools on 2.0.16), not just our own door.
33
+ * Leaving them in would hand back, at the request layer, exactly the surface the
34
+ * whitelist exists to withhold. */
35
+ export const BROWSER_CATALOG = "browser_*";
36
+ const isDeny = (value) => value === "deny";
37
+ /**
38
+ * The tools one agent must never be offered. Only a literal `deny` removes:
39
+ * the `{ "*": "ask" }` object form means "callable, gated", and deleting such a
40
+ * tool would silently drop a capability the matrix grants with a dialog.
41
+ *
42
+ * `read`/`grep`/`glob` are exempted by name (`V2_LADDER_ACTIONS`), which is the
43
+ * other half of the `tm_read`/`tm_grep`/`tm_bash` retirement: v1 denied the
44
+ * native file tools because the governed aliases existed, and on v2 those
45
+ * aliases are not registered, so honouring the deny here would leave a role with
46
+ * no way to open a file at all. Nothing is lost by letting them ride — the path
47
+ * scope P2 enforced in code is the host's own `external_directory` action, which
48
+ * was observed live answering `effect:"ask"` with a real `permission.asked`
49
+ * behind it, i.e. a dialog instead of a hard throw.
50
+ */
51
+ export function toolsToRemove(permission) {
52
+ const names = [];
53
+ for (const [key, value] of Object.entries(permission ?? {})) {
54
+ if (!isDeny(value))
55
+ continue;
56
+ if (key === "tm_browser") {
57
+ // Both doors go: our own tool AND the host's catalog. Removing only
58
+ // tm_browser would leave 45 native browser tools in the request, which is
59
+ // the exact surface the whitelist withholds.
60
+ names.push(BROWSER_CATALOG);
61
+ }
62
+ // A `tm_*` key IS a tool name, so a DENY on one has to remove it too —
63
+ // leaving the denied doors in the request would keep charging the model for
64
+ // tools this role may not touch, which is the whole tax this layer exists
65
+ // to stop. The `tm_*` wildcard itself is an allow; if it ever read "deny",
66
+ // deleting a tool literally named `tm_*` is a no-op.
67
+ const action = TOOL_RENAMES[key] ?? key;
68
+ if (V2_LADDER_ACTIONS.has(action))
69
+ continue;
70
+ names.push(action);
71
+ // tm_ledger is v2-only and the frozen v1 matrix cannot name it, so the lead
72
+ // marker carries the denial: a role that may not `tm_join` is a role that does
73
+ // not own the list. Leaving it offered would charge every specialist for a
74
+ // tool that refuses them at execute — the tax this layer exists to remove.
75
+ if (key === "tm_join")
76
+ names.push("tm_ledger");
77
+ }
78
+ return [...new Set(names)];
79
+ }
80
+ /** Built once per agent id so the hook body stays a set lookup on a hot path. */
81
+ export function removalPlan(agents) {
82
+ const plan = new Map();
83
+ for (const [id, cfg] of Object.entries(agents))
84
+ plan.set(id, new Set(toolsToRemove(cfg?.permission)));
85
+ return plan;
86
+ }
87
+ const removable = (name, denied) => denied.has(name) || (denied.has(BROWSER_CATALOG) && name.startsWith("browser_"));
88
+ /**
89
+ * Register the request-layer hooks. Returns the registrations (so the caller
90
+ * can dispose them) and a live report object — the counts are read off what the
91
+ * hooks actually did, not off what the matrix intends, because "we trimmed the
92
+ * surface" is a claim the user can only check against the request.
93
+ */
94
+ export async function applyV2SessionLayer(ctx, input) {
95
+ const registrations = [];
96
+ const report = {
97
+ temperature: input.temperature,
98
+ removed: {},
99
+ notePushed: false,
100
+ compactionLines: 0,
101
+ tmInRequestSurface: false,
102
+ };
103
+ const session = ctx.session;
104
+ if (!session || typeof session.hook !== "function") {
105
+ return { registrations, report };
106
+ }
107
+ // Property-access calls, never a captured reference — a detached `hook` loses
108
+ // its receiver and the host's client throws (see the §10 rule in dispatch.ts).
109
+ registrations.push(await session.hook("context", (event) => {
110
+ const agent = String(event?.agent ?? "");
111
+ // Anything below this line MUTATES the outgoing request. On a host where
112
+ // one plugin serves every agent, an unguarded write here would set a build
113
+ // session's temperature, push our board note into a plan session's system
114
+ // prompt, and delete tools the user's own config granted (#22).
115
+ if (input.scope && input.scope.count(input.scope.decide(event)) !== "ours")
116
+ return;
117
+ input.scope?.learn(agent, event.sessionID);
118
+ const denied = input.plan.get(agent);
119
+ if (denied?.size && event.tools && typeof event.tools === "object") {
120
+ let cut = 0;
121
+ for (const name of Object.keys(event.tools)) {
122
+ if (!removable(name, denied))
123
+ continue;
124
+ delete event.tools[name];
125
+ cut++;
126
+ }
127
+ if (cut)
128
+ report.removed[agent] = (report.removed[agent] ?? 0) + cut;
129
+ }
130
+ // The observation that settles the delivery question: whatever is left in the
131
+ // request's own tool map is what the model can call directly. A `tm_*` name
132
+ // appearing here means direct delivery worked; never appearing means the host
133
+ // kept our tools in the Code Mode catalog regardless of `options.codemode`.
134
+ if (event.tools && typeof event.tools === "object") {
135
+ for (const name of Object.keys(event.tools)) {
136
+ if (name.startsWith("tm_")) {
137
+ report.tmInRequestSurface = true;
138
+ break;
139
+ }
140
+ }
141
+ }
142
+ if (input.temperature !== false && event.options && typeof event.options === "object") { // Only fill it when the request carries none: a per-session model variant
143
+ // the user chose outranks our invariant.
144
+ if (event.options.temperature === undefined)
145
+ event.options.temperature = input.temperature;
146
+ }
147
+ if (input.note && input.noteAgents.includes(agent) && Array.isArray(event.system)) {
148
+ // The hook runs before EVERY model call; if the host reuses the array,
149
+ // an unguarded push would repeat the note until it crowds out the work.
150
+ const already = event.system.some((p) => typeof p?.text === "string" && p.text.includes("## Team Blackboard"));
151
+ if (!already) {
152
+ event.system.push({ type: "text", text: input.note });
153
+ report.notePushed = true;
154
+ }
155
+ }
156
+ }));
157
+ registrations.push(await session.hook("compaction", (event) => {
158
+ if (input.scope && input.scope.count(input.scope.decide(event)) !== "ours")
159
+ return;
160
+ if (!Array.isArray(event?.system))
161
+ return;
162
+ for (const line of COMPACTION_CONTEXT) {
163
+ if (event.system.some((p) => p?.text === line))
164
+ continue;
165
+ event.system.push({ type: "text", text: line });
166
+ report.compactionLines++;
167
+ }
168
+ }));
169
+ return { registrations, report };
170
+ }
171
+ //# sourceMappingURL=v2-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-session.js","sourceRoot":"","sources":["../../src/host/v2-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * The v2 host's own sub-agents, made collectable by `tm_join` (decision 4, 2026-09-26).
3
+ *
4
+ * What was broken: on v2 every dispatch goes through the host's `subagent` tool (v1's
5
+ * `tm_dispatch` is gone and the plugin forces `background:true`), so the child session
6
+ * was never entered into `tm_join`'s registry. `tm_join` then answered 没有待收集的派发
7
+ * about work that was running on screen, a wait could never end, and the lead had to
8
+ * re-read the round from the injected message like a person paging through mail. The
9
+ * event feed added in 1.7.x made this worse in the specific way goal #6 refuses: the
10
+ * dispatcher ignores a session id it has no record of, so a settled child produced
11
+ * silence that read as "nothing to report".
12
+ *
13
+ * Why these two hooks and not a session query: the v2 plugin ctx has no
14
+ * `session.children` and our `ctx.session.get` bridge has never resolved a shape on a
15
+ * live host, so a tree walk is not available. What IS available is measured, from the
16
+ * user's own desktop session (`docs/research/host-subagent-injection.md`):
17
+ *
18
+ * execute.before subagent {agent, background, description, prompt}
19
+ * execute.after result.metadata = {sessionID:"ses_…", status:"running", truncated:false}
20
+ * result text "The subagent is working in the background
21
+ * (sessionID: ses_…). You will be notified…"
22
+ * later, as a message the plugin never sees as a tool result:
23
+ * metadata {source:"subagent", childID:"ses_…", agent, state}
24
+ * text <subagent sessionID="ses_…" state="completed" …>body</subagent>
25
+ *
26
+ * So the before hook supplies who and what-for, the after hook supplies the child's id,
27
+ * and the pairing is per CALLER session — a lead that fires three dispatches in one round
28
+ * gets three pending rows and pairs them oldest-first as the acks come back.
29
+ *
30
+ * The reply BODY is deliberately not promised: it reaches the parent as an injected
31
+ * message, not through this seam, so a registered child reports where its answer comes
32
+ * from instead of pretending we can fetch it. Claiming to hold a report we never read
33
+ * is the defect this product exists to refuse.
34
+ *
35
+ * Privacy: the trajectory records the child id and the agent name only — never the
36
+ * description or the prompt (R6 binds a diagnostic as much as a guard).
37
+ */
38
+ import type { V2Registration } from "./v2-types.js";
39
+ import type { TeamScope } from "./v2-scope.js";
40
+ /** A dispatch we saw being made, waiting for its ack. */
41
+ export interface PendingDispatch {
42
+ agent: string;
43
+ label: string;
44
+ at: number;
45
+ }
46
+ /** What `tm_join` needs to open a row for a child it did not dispatch itself. */
47
+ export interface HostChildInput {
48
+ sessionID: string;
49
+ parentSessionID: string;
50
+ agent: string;
51
+ label: string;
52
+ }
53
+ /** How many unclaimed acks one caller may have in flight before we stop guessing which
54
+ * `description` belongs to which child. Past this the child is registered with a
55
+ * generic label rather than a possibly-wrong one. */
56
+ export declare const PENDING_PER_CALLER = 8;
57
+ /** Read the dispatch out of the tool input (the host's `execute.before` field is
58
+ * `input`, and it IS the argument object). Returns null for anything that is not a
59
+ * recognisable `subagent` call — a non-object input is left alone, never invented. */
60
+ export declare function pendingDispatchOf(raw: unknown, at?: number): PendingDispatch | null;
61
+ /** The child's session id, from the two places the host puts it (measured). A
62
+ * synchronous child DOES have a `metadata.sessionID` — the host always sets
63
+ * `{sessionID, status}` — but its `status` is already `completed` and its content IS the
64
+ * reply, so there is nothing to
65
+ * collect and null is the correct answer, not a failure. */
66
+ export declare function hostChildIdOf(result: unknown): string | null;
67
+ /** True when the ack says the child is still open — i.e. worth registering. Read from
68
+ * the host's own code (2.0.18): the `subagent` result always carries
69
+ * `metadata:{sessionID, status}`, and a SYNCHRONOUS child arrives with
70
+ * `status:"completed"` and the body itself, so there is nothing left to collect. A
71
+ * `status` we do not recognise registers anyway, because a missed child costs the lead a
72
+ * whole round while a spurious row only costs a line in a table. */
73
+ export declare function hostChildIsOpen(result: unknown): boolean;
74
+ export interface SubagentRegistryReport {
75
+ /** `subagent` calls seen on a Team session */
76
+ seen: number;
77
+ /** children actually opened in tm_join's registry */
78
+ registered: number;
79
+ /** acks that carried no child id at all */
80
+ noChildId: number;
81
+ /** acks that arrived with the child ALREADY completed — a synchronous `subagent` call,
82
+ * whose result is the body itself, so there is nothing for tm_join to collect */
83
+ settledAtOnce: number;
84
+ /** acks that arrived with nothing pending to pair them with */
85
+ unpaired: number;
86
+ /** children registered with a generic label because the caller had >PENDING_PER_CALLER
87
+ * in flight, so pairing would have been a guess */
88
+ labelGuessed: number;
89
+ }
90
+ export interface V2SubagentRegistry {
91
+ registrations: Promise<V2Registration>[];
92
+ report: SubagentRegistryReport;
93
+ active: boolean;
94
+ }
95
+ /** The host's own completion envelope, in either generation's spelling. Returns the child
96
+ * id and the state the host asserted, or null when the text is not an injection.
97
+ * `[B]` 2.0.18 builds the wrapper as `<subagent sessionID="…" state="completed" …>`; v1
98
+ * used `<task id="…" state="completed">`. Both are matched because a plugin reload can
99
+ * serve a session whose history contains either. */
100
+ export declare function completionFromText(text: string): {
101
+ sessionID: string;
102
+ state: string;
103
+ } | null;
104
+ export interface CompletionWatchReport {
105
+ /** times the seam fired on a Team session */
106
+ contextFired: number;
107
+ promptFired: number;
108
+ /** envelopes recognised */
109
+ seen: number;
110
+ /** children actually settled through this path */
111
+ settled: number;
112
+ /** scans skipped because nothing was open (the cheap path) */
113
+ skipped: number;
114
+ }
115
+ /**
116
+ * The settle path for a child the plugin never created (#31, 2026-09-26).
117
+ *
118
+ * A live 2.0.18 round proved the two obvious paths do not work: the host does NOT forward a
119
+ * child session's `session.idle` to a plugin subscriber, and the parent-idle presumption
120
+ * cannot fire mid-turn because the parent is by definition busy while it works. So a
121
+ * background child whose full report had ALREADY been injected stayed 运行中 — goal #6's
122
+ * overstated claim wearing the opposite face.
123
+ *
124
+ * A second round then proved a hook can exist and still be the wrong one: `session.prompt`
125
+ * fired 0 times and `session.model.request` fired 6 but carried no messages at all (the
126
+ * message list is assembled separately from that payload). The seam that DOES carry the
127
+ * parent's history is `session.hook("context")` — the same one the request trim and the
128
+ * probe read, and the one whose `messages` the probe counted at 8 in that round.
129
+ *
130
+ * So: watch `context`, and only when something is actually open. The scan is O(messages)
131
+ * per request, which is a real cost on a long-lived lead session, so an idle registry skips
132
+ * it entirely and the skip is counted — "we did not look because there was nothing to look
133
+ * for" stays distinguishable from "we looked and saw nothing".
134
+ *
135
+ * `session.prompt` is kept registered and counted as well: it costs nothing, and if a future
136
+ * host routes the injection through it, the counter is where we would learn that.
137
+ */
138
+ export declare function applyV2CompletionWatch(ctx: unknown, deps: {
139
+ /** Settle the named child if this process knows it. Returns false when the id is not
140
+ * registered (somebody else's session, or already settled) — never an error. */
141
+ settle: (sessionID: string, state: string) => boolean;
142
+ /** Anything still open? When this says no, the scan is skipped. */
143
+ hasOpen?: () => boolean;
144
+ scope?: TeamScope;
145
+ }): {
146
+ registrations: Promise<V2Registration>[];
147
+ report: CompletionWatchReport;
148
+ active: boolean;
149
+ };
150
+ export declare function applyV2SubagentRegistry(ctx: unknown, deps: {
151
+ /** Open a row in tm_join's registry. Returns false when the child is already known
152
+ * (a plugin reload replays hooks) or the id is the caller's own session. */
153
+ register: (child: HostChildInput) => boolean;
154
+ scope?: TeamScope;
155
+ now?: () => number;
156
+ }): V2SubagentRegistry;
157
+ //# sourceMappingURL=v2-subagent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-subagent.d.ts","sourceRoot":"","sources":["../../src/host/v2-subagent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,EAAE,EAAE,MAAM,CAAA;CACX;AAED,iFAAiF;AACjF,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;sDAEsD;AACtD,eAAO,MAAM,kBAAkB,IAAI,CAAA;AAEnC;;uFAEuF;AACvF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,GAAE,MAAmB,GAAG,eAAe,GAAG,IAAI,CAO/F;AAED;;;;6DAI6D;AAC7D,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAgB5D;AAED;;;;;qEAKqE;AACrE,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAGxD;AAED,MAAM,WAAW,sBAAsB;IACrC,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB;sFACkF;IAClF,aAAa,EAAE,MAAM,CAAA;IACrB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAA;IAChB;wDACoD;IACpD,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,CAAA;IACxC,MAAM,EAAE,sBAAsB,CAAA;IAC9B,MAAM,EAAE,OAAO,CAAA;CAChB;AAED;;;;qDAIqD;AACrD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAG5F;AA6BD,MAAM,WAAW,qBAAqB;IACpC,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAA;IACf,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE;IACJ;qFACiF;IACjF,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;IACrD,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,OAAO,CAAA;IACvB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,GACA;IAAE,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAiC9F;AAED,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE;IACJ;iFAC6E;IAC7E,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAA;IAC5C,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB,GACA,kBAAkB,CA8EpB"}