@te-river/opencode-team-mode 1.6.1 → 1.7.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.
Files changed (201) hide show
  1. package/README.md +117 -118
  2. package/README.zh-CN.md +98 -100
  3. package/dist/agents.d.ts.map +1 -1
  4. package/dist/agents.js +89 -79
  5. package/dist/agents.js.map +1 -1
  6. package/dist/approval-gate.d.ts +8 -9
  7. package/dist/approval-gate.d.ts.map +1 -1
  8. package/dist/approval-gate.js +13 -14
  9. package/dist/approval-gate.js.map +1 -1
  10. package/dist/capabilities.d.ts +11 -37
  11. package/dist/capabilities.d.ts.map +1 -1
  12. package/dist/capabilities.js +11 -141
  13. package/dist/capabilities.js.map +1 -1
  14. package/dist/commands.js +1 -1
  15. package/dist/envprotect/hook.d.ts +12 -31
  16. package/dist/envprotect/hook.d.ts.map +1 -1
  17. package/dist/envprotect/hook.js +13 -91
  18. package/dist/envprotect/hook.js.map +1 -1
  19. package/dist/envprotect/patterns.d.ts +6 -4
  20. package/dist/envprotect/patterns.d.ts.map +1 -1
  21. package/dist/envprotect/patterns.js +6 -4
  22. package/dist/envprotect/patterns.js.map +1 -1
  23. package/dist/envprotect.d.ts +1 -1
  24. package/dist/envprotect.d.ts.map +1 -1
  25. package/dist/envprotect.js +1 -1
  26. package/dist/envprotect.js.map +1 -1
  27. package/dist/host/note.d.ts.map +1 -1
  28. package/dist/host/note.js +8 -5
  29. package/dist/host/note.js.map +1 -1
  30. package/dist/host/v2-browser-gate.d.ts +19 -1
  31. package/dist/host/v2-browser-gate.d.ts.map +1 -1
  32. package/dist/host/v2-browser-gate.js +47 -6
  33. package/dist/host/v2-browser-gate.js.map +1 -1
  34. package/dist/host/v2-capabilities.d.ts +43 -0
  35. package/dist/host/v2-capabilities.d.ts.map +1 -1
  36. package/dist/host/v2-capabilities.js +77 -1
  37. package/dist/host/v2-capabilities.js.map +1 -1
  38. package/dist/host/v2-compaction.d.ts +129 -0
  39. package/dist/host/v2-compaction.d.ts.map +1 -0
  40. package/dist/host/v2-compaction.js +346 -0
  41. package/dist/host/v2-compaction.js.map +1 -0
  42. package/dist/host/v2-default-agent.d.ts +37 -0
  43. package/dist/host/v2-default-agent.d.ts.map +1 -0
  44. package/dist/host/v2-default-agent.js +128 -0
  45. package/dist/host/v2-default-agent.js.map +1 -0
  46. package/dist/host/v2-events.d.ts +2 -0
  47. package/dist/host/v2-events.d.ts.map +1 -1
  48. package/dist/host/v2-events.js +27 -0
  49. package/dist/host/v2-events.js.map +1 -1
  50. package/dist/host/v2-guard.d.ts +178 -0
  51. package/dist/host/v2-guard.d.ts.map +1 -1
  52. package/dist/host/v2-guard.js +324 -8
  53. package/dist/host/v2-guard.js.map +1 -1
  54. package/dist/host/v2-offload.d.ts +1 -1
  55. package/dist/host/v2-offload.js +2 -2
  56. package/dist/host/v2-permissions.d.ts +45 -44
  57. package/dist/host/v2-permissions.d.ts.map +1 -1
  58. package/dist/host/v2-permissions.js +48 -49
  59. package/dist/host/v2-permissions.js.map +1 -1
  60. package/dist/host/v2-probe-chain.d.ts +93 -0
  61. package/dist/host/v2-probe-chain.d.ts.map +1 -0
  62. package/dist/host/v2-probe-chain.js +146 -0
  63. package/dist/host/v2-probe-chain.js.map +1 -0
  64. package/dist/host/v2-prune.d.ts +157 -0
  65. package/dist/host/v2-prune.d.ts.map +1 -0
  66. package/dist/host/v2-prune.js +507 -0
  67. package/dist/host/v2-prune.js.map +1 -0
  68. package/dist/host/v2-retry.d.ts +143 -0
  69. package/dist/host/v2-retry.d.ts.map +1 -0
  70. package/dist/host/v2-retry.js +315 -0
  71. package/dist/host/v2-retry.js.map +1 -0
  72. package/dist/host/v2-scope.d.ts.map +1 -1
  73. package/dist/host/v2-scope.js +14 -7
  74. package/dist/host/v2-scope.js.map +1 -1
  75. package/dist/host/v2-session-client.d.ts +62 -7
  76. package/dist/host/v2-session-client.d.ts.map +1 -1
  77. package/dist/host/v2-session-client.js +485 -26
  78. package/dist/host/v2-session-client.js.map +1 -1
  79. package/dist/host/v2-session.d.ts +72 -1
  80. package/dist/host/v2-session.d.ts.map +1 -1
  81. package/dist/host/v2-session.js +154 -10
  82. package/dist/host/v2-session.js.map +1 -1
  83. package/dist/host/v2-tool.d.ts +2 -3
  84. package/dist/host/v2-tool.d.ts.map +1 -1
  85. package/dist/host/v2-tool.js +2 -3
  86. package/dist/host/v2-tool.js.map +1 -1
  87. package/dist/host/v2-types.d.ts +25 -0
  88. package/dist/host/v2-types.d.ts.map +1 -1
  89. package/dist/host/v2.d.ts +14 -12
  90. package/dist/host/v2.d.ts.map +1 -1
  91. package/dist/host/v2.js +648 -74
  92. package/dist/host/v2.js.map +1 -1
  93. package/dist/identity.d.ts +27 -0
  94. package/dist/identity.d.ts.map +1 -0
  95. package/dist/identity.js +34 -0
  96. package/dist/identity.js.map +1 -0
  97. package/dist/index.d.ts +9 -24
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +17 -27
  100. package/dist/index.js.map +1 -1
  101. package/dist/prompts/lead.d.ts +1 -1
  102. package/dist/prompts/lead.d.ts.map +1 -1
  103. package/dist/prompts/lead.js +44 -27
  104. package/dist/prompts/lead.js.map +1 -1
  105. package/dist/prompts/shared.d.ts +2 -2
  106. package/dist/prompts/shared.d.ts.map +1 -1
  107. package/dist/prompts/shared.js +74 -57
  108. package/dist/prompts/shared.js.map +1 -1
  109. package/dist/prompts/specialists.d.ts +2 -2
  110. package/dist/prompts/specialists.d.ts.map +1 -1
  111. package/dist/prompts/specialists.js +53 -83
  112. package/dist/prompts/specialists.js.map +1 -1
  113. package/dist/tm/args-schema.d.ts +7 -32
  114. package/dist/tm/args-schema.d.ts.map +1 -1
  115. package/dist/tm/args-schema.js +12 -153
  116. package/dist/tm/args-schema.js.map +1 -1
  117. package/dist/tm/board.d.ts +10 -9
  118. package/dist/tm/board.d.ts.map +1 -1
  119. package/dist/tm/board.js +11 -10
  120. package/dist/tm/board.js.map +1 -1
  121. package/dist/tm/config-files.d.ts +81 -0
  122. package/dist/tm/config-files.d.ts.map +1 -0
  123. package/dist/tm/config-files.js +209 -0
  124. package/dist/tm/config-files.js.map +1 -0
  125. package/dist/tm/config-layers.d.ts +117 -0
  126. package/dist/tm/config-layers.d.ts.map +1 -0
  127. package/dist/tm/config-layers.js +320 -0
  128. package/dist/tm/config-layers.js.map +1 -0
  129. package/dist/tm/config.d.ts +10 -101
  130. package/dist/tm/config.d.ts.map +1 -1
  131. package/dist/tm/config.js +17 -71
  132. package/dist/tm/config.js.map +1 -1
  133. package/dist/tm/dispatch.d.ts +154 -22
  134. package/dist/tm/dispatch.d.ts.map +1 -1
  135. package/dist/tm/dispatch.js +559 -80
  136. package/dist/tm/dispatch.js.map +1 -1
  137. package/dist/tm/egress.d.ts +19 -7
  138. package/dist/tm/egress.d.ts.map +1 -1
  139. package/dist/tm/egress.js +21 -9
  140. package/dist/tm/egress.js.map +1 -1
  141. package/dist/tm/index.d.ts +23 -20
  142. package/dist/tm/index.d.ts.map +1 -1
  143. package/dist/tm/index.js +117 -116
  144. package/dist/tm/index.js.map +1 -1
  145. package/dist/tm/ledger.d.ts +9 -2
  146. package/dist/tm/ledger.d.ts.map +1 -1
  147. package/dist/tm/ledger.js +4 -1
  148. package/dist/tm/ledger.js.map +1 -1
  149. package/dist/tm/perm-ask.d.ts +3 -3
  150. package/dist/tm/perm-ask.d.ts.map +1 -1
  151. package/dist/tm/perm-ask.js +3 -3
  152. package/dist/tm/perm-ask.js.map +1 -1
  153. package/dist/tm/pipelines.d.ts +12 -11
  154. package/dist/tm/pipelines.d.ts.map +1 -1
  155. package/dist/tm/pipelines.js +40 -207
  156. package/dist/tm/pipelines.js.map +1 -1
  157. package/dist/tm/preview.d.ts +1 -1
  158. package/dist/tm/preview.js +3 -3
  159. package/dist/tm/preview.js.map +1 -1
  160. package/dist/tm/refs.d.ts +31 -4
  161. package/dist/tm/refs.d.ts.map +1 -1
  162. package/dist/tm/refs.js +48 -4
  163. package/dist/tm/refs.js.map +1 -1
  164. package/dist/tm/result.d.ts +1 -1
  165. package/dist/tm/result.d.ts.map +1 -1
  166. package/dist/tm/result.js +4 -3
  167. package/dist/tm/result.js.map +1 -1
  168. package/dist/tm/search.d.ts +2 -2
  169. package/dist/tm/search.js +7 -7
  170. package/dist/tm/search.js.map +1 -1
  171. package/dist/tm/serp-loop.d.ts +19 -7
  172. package/dist/tm/serp-loop.d.ts.map +1 -1
  173. package/dist/tm/serp-loop.js +24 -9
  174. package/dist/tm/serp-loop.js.map +1 -1
  175. package/dist/tm/stats.d.ts +31 -27
  176. package/dist/tm/stats.d.ts.map +1 -1
  177. package/dist/tm/stats.js +170 -58
  178. package/dist/tm/stats.js.map +1 -1
  179. package/dist/tm/store.d.ts +18 -5
  180. package/dist/tm/store.d.ts.map +1 -1
  181. package/dist/tm/store.js +39 -9
  182. package/dist/tm/store.js.map +1 -1
  183. package/dist/tm/tools.d.ts +7 -5
  184. package/dist/tm/tools.d.ts.map +1 -1
  185. package/dist/tm/tools.js +10 -41
  186. package/dist/tm/tools.js.map +1 -1
  187. package/dist/tm/webfetch.d.ts +1 -1
  188. package/dist/tm/webfetch.d.ts.map +1 -1
  189. package/dist/tm/webfetch.js +38 -23
  190. package/dist/tm/webfetch.js.map +1 -1
  191. package/dist/types.d.ts +40 -123
  192. package/dist/types.d.ts.map +1 -1
  193. package/dist/types.js +7 -21
  194. package/dist/types.js.map +1 -1
  195. package/docs/installation-v2.md +124 -39
  196. package/docs/installation.md +9 -0
  197. package/docs/research/browser-pane.md +5 -0
  198. package/docs/v2-port-notes.md +500 -315
  199. package/package.json +1 -1
  200. package/scripts/gen-v2-config.mjs +246 -94
  201. package/scripts/lib/fake-ctx.mjs +244 -146
@@ -0,0 +1,346 @@
1
+ /**
2
+ * Early compaction — Team's own trigger at a fraction of the context window.
3
+ *
4
+ * WHY THIS EXISTS AS PLUGIN LOGIC
5
+ * The host's `compaction` config block (authoritative: `https://opencode.ai/config.json`
6
+ * `$defs.Config.properties.compaction`, read 2026-10-05) exposes exactly five keys —
7
+ * `auto`, `prune`, `tail_turns`, `preserve_recent_tokens`, `reserved` — and NONE of them
8
+ * is a percentage. The trigger is "when context is full", with `reserved`/`buffer` as an
9
+ * ABSOLUTE token window. So "start compacting at 75%" is not expressible in config, and
10
+ * a plugin cannot write config at runtime either: the 2.x `ctx` has no `config` domain
11
+ * (measured on 2.0.23 with a zero-token probe). What 2.x DOES give is
12
+ * `ctx.session.compact({sessionID})` — `compact({})` fails with `Missing key at
13
+ * ["sessionID"]`, a bogus id with `Session.NotFoundError` — so the threshold lives here,
14
+ * in the package, and ships to every user instead of one machine's file.
15
+ *
16
+ * WHERE THE NUMBER COMES FROM — MEASURED, NOT ASSUMED
17
+ * The first version read usage off `session.hook("context")`'s `messages`, on the theory
18
+ * that the host's own meter does `o.tokens.input + … + o.model.providerID` off message
19
+ * objects. A live 2.0.23 turn disproved it: on the SECOND request of a session, with
20
+ * three messages including an assistant one, the payload still carried no usage numbers
21
+ * (`measured source=no_usage messages=3`, run r-20261005-235343-114738). The numbers are
22
+ * on the EVENT FEED instead — read out of the binary:
23
+ *
24
+ * jq = rt({ type: "session.usage.updated", schema: { ...e, cost: Ps, tokens: Yp } })
25
+ * case "session.usage.updated": m("session","info", D.data.sessionID, {cost, tokens})
26
+ *
27
+ * and our own trajectory shows that event firing 440 times in one desktop session. So the
28
+ * event is the primary source; the message read stays as a secondary (a host that moves
29
+ * the numbers back onto messages must not strand the feature), and a session where neither
30
+ * answers is counted `no_usage` rather than guessed at.
31
+ *
32
+ * THE DENOMINATOR
33
+ * `limit.context` comes from `ctx.model.list()` keyed by providerID+modelID — the same
34
+ * lookup the desktop's usage meter does (`contextLimit:(s)=>providers.find(…).models[…].limit.context`).
35
+ * The model itself comes from the session record (`ctx.session.get({sessionID})`, which is
36
+ * where the reducer just wrote cost/tokens) or, failing that, from the usage-bearing
37
+ * message. No model → no percentage → counted `no_limit`, never a guessed one.
38
+ *
39
+ * THE TEAM GATE
40
+ * An event carries a sessionID and no agent, so it cannot be scope-decided on its own.
41
+ * The layer only ever acts on sessions the request layer has already LEARNED as ours (the
42
+ * context hook passes the same `scope.count(decide(...)) === "ours"` gate every other
43
+ * writer uses and records the id). A usage event for a stranger session is counted and
44
+ * dropped.
45
+ *
46
+ * WHY IT IS SAFE TO ASK MID-TURN
47
+ * Compaction on 2.x is an INBOX INPUT, not a side effect (`SessionInbox.admitCompaction`,
48
+ * handler `a.compact({sessionID, id, delivery})`, duplicate id → `Session.CompactionConflictError`).
49
+ * We admit one per usage number per session with a floor interval, so a ratio that does
50
+ * not drop cannot become a compaction loop, and a failed admission is forgotten so the
51
+ * next signal may retry.
52
+ *
53
+ * WHAT IS DELIBERATELY NOT HERE
54
+ * - No config rewriting, no reading of `compaction.auto`: we cannot see it, so we do not
55
+ * claim to respect it. `TM_COMPACT_TRIGGER=off` restores host-only timing on our side.
56
+ * - No throwing into a hook or an event loop, ever. Every failure is a counted verdict and
57
+ * its own `v2-compact` trajectory line, because the counters ride rows a CLI run never
58
+ * produces (`v2-shutdown` needs dispose, `v2-surface` is throttled).
59
+ */
60
+ const DEFAULT_PERCENT = 75;
61
+ const DEFAULT_MIN_INTERVAL_MS = 60_000;
62
+ /** `off` is the only opt-out; a garbage percent falls back to the documented default. */
63
+ export function resolveCompactConfig(env = process.env) {
64
+ const raw = String(env.TM_COMPACT_TRIGGER ?? "on").trim().toLowerCase();
65
+ const enabled = raw !== "off" && raw !== "false" && raw !== "0" && raw !== "no";
66
+ const p = Number(env.TM_COMPACT_AT_PERCENT);
67
+ const percent = Number.isFinite(p) && p >= 5 && p <= 95 ? p : DEFAULT_PERCENT;
68
+ const ms = Number(env.TM_COMPACT_MIN_MS);
69
+ const minIntervalMs = Number.isFinite(ms) && ms >= 0 ? Math.min(ms, 600_000) : DEFAULT_MIN_INTERVAL_MS;
70
+ return { enabled, percent, minIntervalMs };
71
+ }
72
+ const num = (v) => (typeof v === "number" && Number.isFinite(v) ? v : 0);
73
+ /**
74
+ * The host's usage block, summed the way the host sums it:
75
+ * `input + output + reasoning + cache.read + cache.write`. Returns null when the object
76
+ * carries no numbers at all — "we did not find them" is not "usage is zero".
77
+ */
78
+ export function readUsedTokens(message) {
79
+ const m = message;
80
+ if (!m || typeof m !== "object")
81
+ return null;
82
+ const candidates = [m.tokens, m.metadata?.tokens, m.info?.tokens, m.usage?.tokens, m.usage];
83
+ for (const t of candidates) {
84
+ if (!t || typeof t !== "object")
85
+ continue;
86
+ const cache = t.cache && typeof t.cache === "object" ? t.cache : {};
87
+ const sum = num(t.input) + num(t.output) + num(t.reasoning) + num(cache.read) + num(cache.write);
88
+ if (sum > 0)
89
+ return sum;
90
+ }
91
+ return null;
92
+ }
93
+ /** The model that produced that usage — the key we need to find its context limit. */
94
+ export function readModelKey(message) {
95
+ const m = message;
96
+ if (!m || typeof m !== "object")
97
+ return null;
98
+ for (const c of [m.model, m.metadata?.model, m.info?.model]) {
99
+ if (!c || typeof c !== "object")
100
+ continue;
101
+ const providerID = typeof c.providerID === "string" ? c.providerID : typeof c.provider === "string" ? c.provider : "";
102
+ const id = typeof c.id === "string" ? c.id : typeof c.modelID === "string" ? c.modelID : "";
103
+ if (providerID && id)
104
+ return { providerID, id };
105
+ }
106
+ return null;
107
+ }
108
+ /** Newest message that carries usage wins — that is what the host's meter calls `usage.last`. */
109
+ export function lastUsageOf(messages) {
110
+ if (!Array.isArray(messages))
111
+ return null;
112
+ for (let i = messages.length - 1; i >= 0; i--) {
113
+ const used = readUsedTokens(messages[i]);
114
+ if (used !== null)
115
+ return { used, model: readModelKey(messages[i]) };
116
+ }
117
+ return null;
118
+ }
119
+ export function percentOf(used, limit) {
120
+ if (!Number.isFinite(used) || !Number.isFinite(limit) || limit <= 0)
121
+ return 0;
122
+ return Math.round((used / limit) * 100);
123
+ }
124
+ export async function applyV2EarlyCompaction(ctx, input = {}) {
125
+ const config = input.config ?? resolveCompactConfig();
126
+ const now = input.now ?? (() => Date.now());
127
+ const report = {
128
+ enabled: config.enabled,
129
+ percent: config.percent,
130
+ checked: 0,
131
+ usageSeen: 0,
132
+ usageEvents: 0,
133
+ eventDecided: 0,
134
+ fired: 0,
135
+ confirmed: 0,
136
+ below: 0,
137
+ deduped: 0,
138
+ noUsage: 0,
139
+ noLimit: 0,
140
+ conflicts: 0,
141
+ threw: 0,
142
+ foreignSkipped: 0,
143
+ lastSource: "(none)",
144
+ lastPercent: 0,
145
+ lastError: "",
146
+ };
147
+ const registrations = [];
148
+ const session = ctx.session;
149
+ const hasCompact = !!session && typeof session.hook === "function" && typeof session.compact === "function";
150
+ if (!config.enabled || !session || !hasCompact) {
151
+ return { registrations, report, observeUsage: () => { } };
152
+ }
153
+ /** Sessions the request layer has already proven are ours. An event alone cannot prove it. */
154
+ const teamSessions = new Set();
155
+ const usageBySession = new Map();
156
+ const modelBySession = new Map();
157
+ const measured = new Set();
158
+ const lastBySession = new Map();
159
+ const emit = (kind, fields) => {
160
+ try {
161
+ input.onEvent?.({ kind, ...fields });
162
+ }
163
+ catch {
164
+ /* a diagnostic that cannot be written never breaks the thing it describes */
165
+ }
166
+ };
167
+ // Catalog cache: one `model.list()` per process, refreshed once per unknown key.
168
+ let limits = null;
169
+ const askedUnknown = new Set();
170
+ async function loadLimits(force = false) {
171
+ if (!limits || force) {
172
+ const next = new Map();
173
+ try {
174
+ // Property access, never a captured reference (§10 in dispatch.ts).
175
+ const res = (await ctx.model?.list?.({}));
176
+ const data = Array.isArray(res?.data) ? res.data : [];
177
+ for (const m of data) {
178
+ const any = m;
179
+ const providerID = typeof any?.providerID === "string" ? any.providerID : typeof any?.id === "string" ? any.id : "";
180
+ const id = typeof any?.id === "string" ? any.id : typeof any?.modelID === "string" ? any.modelID : "";
181
+ const limit = any?.limit?.context;
182
+ if (providerID && id && typeof limit === "number" && limit > 0)
183
+ next.set(`${providerID}/${id}`, limit);
184
+ }
185
+ }
186
+ catch {
187
+ /* no catalog is a counted no_limit, never a guess */
188
+ }
189
+ limits = next;
190
+ }
191
+ return limits;
192
+ }
193
+ /** The session record is where the host's own reducer writes cost/tokens, and where the
194
+ * model of the session lives. Read once per session, refreshed when we have no model. */
195
+ async function sessionModel(sessionID) {
196
+ const known = modelBySession.get(sessionID);
197
+ if (known)
198
+ return known;
199
+ try {
200
+ // Typed through the index signature, and called with the domain as receiver — a
201
+ // detached `get` loses it and the host's client throws (§10 in dispatch.ts).
202
+ const get = session.get;
203
+ const rec = get ? (await get.call(session, { sessionID })) : undefined;
204
+ const found = readModelKey(rec);
205
+ if (found)
206
+ modelBySession.set(sessionID, found);
207
+ return found;
208
+ }
209
+ catch {
210
+ return null;
211
+ }
212
+ }
213
+ async function decide(sessionID, from, fallback) {
214
+ let used = usageBySession.get(sessionID);
215
+ let source = "event";
216
+ let model = modelBySession.get(sessionID) ?? null;
217
+ if (used === undefined) {
218
+ if (!fallback) {
219
+ report.noUsage++;
220
+ if (!measured.has(sessionID)) {
221
+ measured.add(sessionID);
222
+ emit("measured", { sessionID, source: "no_usage", from });
223
+ }
224
+ return;
225
+ }
226
+ used = fallback.used;
227
+ source = "message";
228
+ model = fallback.model ?? null;
229
+ }
230
+ if (used <= 0) {
231
+ report.noUsage++;
232
+ return;
233
+ }
234
+ if (!model)
235
+ model = (await sessionModel(sessionID)) ?? fallback?.model ?? null;
236
+ if (!model) {
237
+ report.noLimit++;
238
+ emit("no_denominator", { sessionID, used, from });
239
+ return;
240
+ }
241
+ modelBySession.set(sessionID, model);
242
+ const key = `${model.providerID}/${model.id}`;
243
+ const table = await loadLimits();
244
+ let limit = table.get(key);
245
+ if (!limit && !askedUnknown.has(key)) {
246
+ askedUnknown.add(key);
247
+ limit = (await loadLimits(true)).get(key);
248
+ }
249
+ if (!limit) {
250
+ report.noLimit++;
251
+ emit("no_denominator", { sessionID, used, model: key, from });
252
+ return;
253
+ }
254
+ const pct = percentOf(used, limit);
255
+ report.lastSource = source;
256
+ report.lastPercent = pct;
257
+ if (!measured.has(sessionID)) {
258
+ measured.add(sessionID);
259
+ emit("measured", { sessionID, source, from, used, limit, percent: pct, threshold: config.percent, model: key });
260
+ }
261
+ if (pct < config.percent) {
262
+ report.below++;
263
+ return;
264
+ }
265
+ const prev = lastBySession.get(sessionID);
266
+ const t = now();
267
+ if (prev && (t - prev.at < config.minIntervalMs || prev.used >= used)) {
268
+ report.deduped++;
269
+ return;
270
+ }
271
+ lastBySession.set(sessionID, { at: t, used });
272
+ report.fired++;
273
+ emit("admit", { sessionID, percent: pct, threshold: config.percent, used, limit, source, from });
274
+ try {
275
+ // Property access at the call site, never a captured reference — a detached
276
+ // `compact` loses the receiver and the host's client throws (§10 in dispatch.ts).
277
+ await session.compact({ sessionID });
278
+ report.confirmed++;
279
+ emit("confirmed", { sessionID, percent: pct, from });
280
+ }
281
+ catch (err) {
282
+ const msg = String(err?.message ?? err ?? "").replace(/\s+/g, " ").slice(0, 120);
283
+ // The host's refusal shapes stay distinct: a duplicate input id is a conflict,
284
+ // anything else is a failure we know nothing about.
285
+ if (/CompactionConflict/i.test(msg)) {
286
+ report.conflicts++;
287
+ emit("conflict", { sessionID, percent: pct, error: msg });
288
+ }
289
+ else {
290
+ report.threw++;
291
+ emit("threw", { sessionID, percent: pct, error: msg });
292
+ }
293
+ report.lastError = msg;
294
+ // A failed admission is not a success: let the next signal retry.
295
+ lastBySession.delete(sessionID);
296
+ }
297
+ }
298
+ registrations.push(await session.hook("context", (event) => {
299
+ try {
300
+ const sessionID = typeof event?.sessionID === "string" ? String(event.sessionID) : "";
301
+ if (!sessionID)
302
+ return;
303
+ if (input.scope && input.scope.count(input.scope.decide(event)) !== "ours") {
304
+ report.foreignSkipped++;
305
+ return;
306
+ }
307
+ teamSessions.add(sessionID);
308
+ report.checked++;
309
+ // Secondary source only: the live 2.0.23 payload carries no usage on messages.
310
+ const fallback = lastUsageOf(event.messages) ?? undefined;
311
+ void decide(sessionID, "request", fallback).catch(() => {
312
+ report.threw++;
313
+ });
314
+ }
315
+ catch {
316
+ /* the request must not be held hostage by a threshold check */
317
+ }
318
+ }));
319
+ return {
320
+ registrations,
321
+ report,
322
+ observeUsage: (data) => {
323
+ const d = data;
324
+ const sessionID = typeof d?.sessionID === "string" ? d.sessionID : "";
325
+ if (!sessionID)
326
+ return;
327
+ report.usageSeen++;
328
+ if (!teamSessions.has(sessionID)) {
329
+ // A usage event carries no agent, so it cannot be scope-decided on its own: an
330
+ // id the request layer never proved is ours is counted and dropped, never acted on.
331
+ report.foreignSkipped++;
332
+ return;
333
+ }
334
+ const used = readUsedTokens(d);
335
+ if (used === null)
336
+ return;
337
+ report.usageEvents++;
338
+ usageBySession.set(sessionID, used);
339
+ report.eventDecided++;
340
+ void decide(sessionID, "event").catch(() => {
341
+ report.threw++;
342
+ });
343
+ },
344
+ };
345
+ }
346
+ //# sourceMappingURL=v2-compaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-compaction.js","sourceRoot":"","sources":["../../src/host/v2-compaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAaH,MAAM,eAAe,GAAG,EAAE,CAAA;AAC1B,MAAM,uBAAuB,GAAG,MAAM,CAAA;AAEtC,yFAAyF;AACzF,MAAM,UAAU,oBAAoB,CAAC,MAA0C,OAAO,CAAC,GAAG;IACxF,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IACvE,MAAM,OAAO,GAAG,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,IAAI,CAAA;IAC/E,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;IAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAA;IAC7E,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IACxC,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAA;IACtG,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,CAAA;AAC5C,CAAC;AAED,MAAM,GAAG,GAAG,CAAC,CAAU,EAAU,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAEzF;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,MAAM,CAAC,GAAG,OAAiD,CAAA;IAC3D,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC5C,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;IAC3F,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,SAAQ;QACzC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QACnE,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAChG,IAAI,GAAG,GAAG,CAAC;YAAE,OAAO,GAAG,CAAA;IACzB,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,MAAM,CAAC,GAAG,OAAiD,CAAA;IAC3D,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC5C,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;QAC5D,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,SAAQ;QACzC,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;QACrH,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3F,IAAI,UAAU,IAAI,EAAE;YAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAA;IACjD,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,WAAW,CAAC,QAAiB;IAC3C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAA;IACzC,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;QACxC,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACtE,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAa;IACnD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IAC7E,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAA;AACzC,CAAC;AA0CD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,GAAc,EACd,QAAsB,EAAE;IAExB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,oBAAoB,EAAE,CAAA;IACrD,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IAC3C,MAAM,MAAM,GAAkB;QAC5B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,CAAC;QACZ,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,CAAC;QACf,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,CAAC;QACZ,KAAK,EAAE,CAAC;QACR,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,CAAC;QACZ,KAAK,EAAE,CAAC;QACR,cAAc,EAAE,CAAC;QACjB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,EAAE;KACd,CAAA;IACD,MAAM,aAAa,GAAqB,EAAE,CAAA;IAC1C,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAA;IAC3B,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,CAAA;IAC3G,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;QAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAA;IAC1D,CAAC;IAED,8FAA8F;IAC9F,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;IACtC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAA;IAChD,MAAM,cAAc,GAAG,IAAI,GAAG,EAA8C,CAAA;IAC5E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAA;IAClC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAwC,CAAA;IAErE,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,MAA+B,EAAE,EAAE;QAC7D,IAAI,CAAC;YACH,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,6EAA6E;QAC/E,CAAC;IACH,CAAC,CAAA;IAED,iFAAiF;IACjF,IAAI,MAAM,GAA+B,IAAI,CAAA;IAC7C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;IACtC,KAAK,UAAU,UAAU,CAAC,KAAK,GAAG,KAAK;QACrC,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAA;YACtC,IAAI,CAAC;gBACH,oEAAoE;gBACpE,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAmC,CAAA;gBAC3E,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;gBACtD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;oBACrB,MAAM,GAAG,GAAG,CAAwB,CAAA;oBACpC,MAAM,UAAU,GAAG,OAAO,GAAG,EAAE,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,GAAG,EAAE,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;oBACnH,MAAM,EAAE,GAAG,OAAO,GAAG,EAAE,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;oBACrG,MAAM,KAAK,GAAG,GAAG,EAAE,KAAK,EAAE,OAAO,CAAA;oBACjC,IAAI,UAAU,IAAI,EAAE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,GAAG,CAAC;wBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,CAAA;gBACxG,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,qDAAqD;YACvD,CAAC;YACD,MAAM,GAAG,IAAI,CAAA;QACf,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED;8FAC0F;IAC1F,KAAK,UAAU,YAAY,CAAC,SAAiB;QAC3C,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAC3C,IAAI,KAAK;YAAE,OAAO,KAAK,CAAA;QACvB,IAAI,CAAC;YACH,gFAAgF;YAChF,6EAA6E;YAC7E,MAAM,GAAG,GAAG,OAAQ,CAAC,GAAmE,CAAA;YACxF,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,CAAyC,CAAC,CAAC,CAAC,SAAS,CAAA;YAC/G,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;YAC/B,IAAI,KAAK;gBAAE,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;YAC/C,OAAO,KAAK,CAAA;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED,KAAK,UAAU,MAAM,CAAC,SAAiB,EAAE,IAAyB,EAAE,QAA6E;QAC/I,IAAI,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACxC,IAAI,MAAM,GAAG,OAAO,CAAA;QACpB,IAAI,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAA;QACjD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,CAAC,OAAO,EAAE,CAAA;gBAChB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC7B,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;oBACvB,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;gBAC3D,CAAC;gBACD,OAAM;YACR,CAAC;YACD,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAA;YACpB,MAAM,GAAG,SAAS,CAAA;YAClB,KAAK,GAAG,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAA;QAChC,CAAC;QACD,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YACd,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,OAAM;QACR,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,KAAK,GAAG,CAAC,MAAM,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,QAAQ,EAAE,KAAK,IAAI,IAAI,CAAA;QAC9E,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,IAAI,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;YACjD,OAAM;QACR,CAAC;QACD,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACpC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,EAAE,EAAE,CAAA;QAC7C,MAAM,KAAK,GAAG,MAAM,UAAU,EAAE,CAAA;QAChC,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC1B,IAAI,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACrB,KAAK,GAAG,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3C,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,IAAI,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAA;YAC7D,OAAM;QACR,CAAC;QACD,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAClC,MAAM,CAAC,UAAU,GAAG,MAAM,CAAA;QAC1B,MAAM,CAAC,WAAW,GAAG,GAAG,CAAA;QACxB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACvB,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;QACjH,CAAC;QACD,IAAI,GAAG,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YACzB,MAAM,CAAC,KAAK,EAAE,CAAA;YACd,OAAM;QACR,CAAC;QACD,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACzC,MAAM,CAAC,GAAG,GAAG,EAAE,CAAA;QACf,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YACtE,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,OAAM;QACR,CAAC;QACD,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7C,MAAM,CAAC,KAAK,EAAE,CAAA;QACd,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;QAChG,IAAI,CAAC;YACH,4EAA4E;YAC5E,kFAAkF;YAClF,MAAM,OAAQ,CAAC,OAAQ,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;YACtC,MAAM,CAAC,SAAS,EAAE,CAAA;YAClB,IAAI,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAA;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,MAAM,CAAE,GAAa,EAAE,OAAO,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YAC3F,+EAA+E;YAC/E,oDAAoD;YACpD,IAAI,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,CAAC,SAAS,EAAE,CAAA;gBAClB,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;YAC3D,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,EAAE,CAAA;gBACd,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;YACxD,CAAC;YACD,MAAM,CAAC,SAAS,GAAG,GAAG,CAAA;YACtB,kEAAkE;YAClE,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IAED,aAAa,CAAC,IAAI,CAChB,MAAM,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,KAAuB,EAAE,EAAE;QACxD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,OAAQ,KAAiC,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAE,KAAgC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YAC9I,IAAI,CAAC,SAAS;gBAAE,OAAM;YACtB,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;gBAC3E,MAAM,CAAC,cAAc,EAAE,CAAA;gBACvB,OAAM;YACR,CAAC;YACD,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YAC3B,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,+EAA+E;YAC/E,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAA;YACzD,KAAK,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACrD,MAAM,CAAC,KAAK,EAAE,CAAA;YAChB,CAAC,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,+DAA+D;QACjE,CAAC;IACH,CAAC,CAAC,CACH,CAAA;IAED,OAAO;QACL,aAAa;QACb,MAAM;QACN,YAAY,EAAE,CAAC,IAAa,EAAE,EAAE;YAC9B,MAAM,CAAC,GAAG,IAA8C,CAAA;YACxD,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAA;YACrE,IAAI,CAAC,SAAS;gBAAE,OAAM;YACtB,MAAM,CAAC,SAAS,EAAE,CAAA;YAClB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjC,+EAA+E;gBAC/E,oFAAoF;gBACpF,MAAM,CAAC,cAAc,EAAE,CAAA;gBACvB,OAAM;YACR,CAAC;YACD,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;YAC9B,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAM;YACzB,MAAM,CAAC,WAAW,EAAE,CAAA;YACpB,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;YACnC,MAAM,CAAC,YAAY,EAAE,CAAA;YACrB,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACzC,MAAM,CAAC,KAAK,EAAE,CAAA;YAChB,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * #38 runtime fallback — is the configured `default_agent` role actually on disk?
3
+ *
4
+ * The plugin cannot see config-directory roles through `ctx.agent`: a zero-token
5
+ * probe measured `ctx.agent.list({})` returning only the 7 built-ins and
6
+ * `ctx.agent.get({agentID:"team"})` → `Agent not found: team`. So the only way
7
+ * to warn about a `default_agent` that points at a role file which does not exist
8
+ * is to read the global config from disk ourselves.
9
+ *
10
+ * Why this matters: the host falls back to `build` SILENTLY when `default_agent`
11
+ * names a missing agent, so the user's sessions quietly stop being Team and
12
+ * nothing says so. This check turns that silence into one warning line.
13
+ *
14
+ * Boundaries, all deliberate:
15
+ * · never throws — a missing/unreadable/unparseable config is a counted state,
16
+ * not a startup failure;
17
+ * · never prints config CONTENT — only the role name and the file path it looked
18
+ * for (the two facts the user needs to fix it);
19
+ * · reads only the global config dir the host itself reads.
20
+ */
21
+ export interface DefaultAgentCheck {
22
+ /** ok = the role file exists; missing-role = default_agent names a role with no
23
+ * file; no-default = the key is absent; no-config = no config file found;
24
+ * unreadable = the file exists but could not be read or parsed. */
25
+ state: "ok" | "missing-role" | "no-default" | "no-config" | "unreadable";
26
+ defaultAgent?: string;
27
+ roleFile?: string;
28
+ }
29
+ /** The global config dir the host reads: `OPENCODE_CONFIG_DIR` when set, else
30
+ * `~/.config/opencode` (on Windows `os.homedir()` reads `USERPROFILE`). */
31
+ export declare function globalConfigDir(env?: NodeJS.ProcessEnv): string;
32
+ export declare function checkDefaultAgentRole(opts: {
33
+ configDir: string;
34
+ readFile?: (p: string) => string;
35
+ exists?: (p: string) => boolean;
36
+ }): DefaultAgentCheck;
37
+ //# sourceMappingURL=v2-default-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-default-agent.d.ts","sourceRoot":"","sources":["../../src/host/v2-default-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,MAAM,WAAW,iBAAiB;IAChC;;wEAEoE;IACpE,KAAK,EAAE,IAAI,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,YAAY,CAAA;IACxE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;4EAC4E;AAC5E,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAI5E;AAwDD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAChC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;CAChC,GAAG,iBAAiB,CAsCpB"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * #38 runtime fallback — is the configured `default_agent` role actually on disk?
3
+ *
4
+ * The plugin cannot see config-directory roles through `ctx.agent`: a zero-token
5
+ * probe measured `ctx.agent.list({})` returning only the 7 built-ins and
6
+ * `ctx.agent.get({agentID:"team"})` → `Agent not found: team`. So the only way
7
+ * to warn about a `default_agent` that points at a role file which does not exist
8
+ * is to read the global config from disk ourselves.
9
+ *
10
+ * Why this matters: the host falls back to `build` SILENTLY when `default_agent`
11
+ * names a missing agent, so the user's sessions quietly stop being Team and
12
+ * nothing says so. This check turns that silence into one warning line.
13
+ *
14
+ * Boundaries, all deliberate:
15
+ * · never throws — a missing/unreadable/unparseable config is a counted state,
16
+ * not a startup failure;
17
+ * · never prints config CONTENT — only the role name and the file path it looked
18
+ * for (the two facts the user needs to fix it);
19
+ * · reads only the global config dir the host itself reads.
20
+ */
21
+ import * as fs from "node:fs";
22
+ import * as os from "node:os";
23
+ import * as path from "node:path";
24
+ /** The global config dir the host reads: `OPENCODE_CONFIG_DIR` when set, else
25
+ * `~/.config/opencode` (on Windows `os.homedir()` reads `USERPROFILE`). */
26
+ export function globalConfigDir(env = process.env) {
27
+ const override = env.OPENCODE_CONFIG_DIR;
28
+ if (typeof override === "string" && override.trim())
29
+ return override.trim();
30
+ return path.join(os.homedir(), ".config", "opencode");
31
+ }
32
+ /** Strip `//` line and block comments so a JSONC file parses as JSON. A tiny
33
+ * state machine, because a naive regex would eat a `//` inside a string value. */
34
+ function stripJsonc(src) {
35
+ let out = "";
36
+ let inString = false;
37
+ let inLine = false;
38
+ let inBlock = false;
39
+ for (let i = 0; i < src.length; i++) {
40
+ const ch = src[i];
41
+ const next = src[i + 1];
42
+ if (inLine) {
43
+ if (ch === "\n") {
44
+ inLine = false;
45
+ out += ch;
46
+ }
47
+ continue;
48
+ }
49
+ if (inBlock) {
50
+ if (ch === "*" && next === "/") {
51
+ inBlock = false;
52
+ i++;
53
+ }
54
+ continue;
55
+ }
56
+ if (inString) {
57
+ out += ch;
58
+ if (ch === "\\") {
59
+ out += next ?? "";
60
+ i++;
61
+ }
62
+ else if (ch === '"') {
63
+ inString = false;
64
+ }
65
+ continue;
66
+ }
67
+ if (ch === '"') {
68
+ inString = true;
69
+ out += ch;
70
+ continue;
71
+ }
72
+ if (ch === "/" && next === "/") {
73
+ inLine = true;
74
+ i++;
75
+ continue;
76
+ }
77
+ if (ch === "/" && next === "*") {
78
+ inBlock = true;
79
+ i++;
80
+ continue;
81
+ }
82
+ out += ch;
83
+ }
84
+ return out;
85
+ }
86
+ export function checkDefaultAgentRole(opts) {
87
+ const readFile = opts.readFile ?? ((p) => fs.readFileSync(p, "utf8"));
88
+ const exists = opts.exists ?? ((p) => fs.existsSync(p));
89
+ const candidates = [
90
+ path.join(opts.configDir, "opencode.jsonc"),
91
+ path.join(opts.configDir, "opencode.json"),
92
+ ];
93
+ let raw = null;
94
+ for (const c of candidates) {
95
+ try {
96
+ if (exists(c)) {
97
+ raw = readFile(c);
98
+ break;
99
+ }
100
+ }
101
+ catch {
102
+ /* try the next candidate */
103
+ }
104
+ }
105
+ if (raw === null)
106
+ return { state: "no-config" };
107
+ let parsed;
108
+ try {
109
+ parsed = JSON.parse(stripJsonc(raw));
110
+ }
111
+ catch {
112
+ return { state: "unreadable" };
113
+ }
114
+ const def = parsed && typeof parsed === "object" ? parsed.default_agent : undefined;
115
+ if (typeof def !== "string" || !def.trim())
116
+ return { state: "no-default" };
117
+ const role = def.trim();
118
+ const roleFile = path.join(opts.configDir, "agents", `${role}.md`);
119
+ try {
120
+ if (exists(roleFile))
121
+ return { state: "ok", defaultAgent: role, roleFile };
122
+ }
123
+ catch {
124
+ return { state: "unreadable" };
125
+ }
126
+ return { state: "missing-role", defaultAgent: role, roleFile };
127
+ }
128
+ //# sourceMappingURL=v2-default-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-default-agent.js","sourceRoot":"","sources":["../../src/host/v2-default-agent.ts"],"names":[],"mappings":"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"}
@@ -52,5 +52,7 @@ export interface V2EventFeed {
52
52
  export declare function applyV2EventFeed(ctx: unknown, opts: {
53
53
  onEvent: (event: HostEvent) => void;
54
54
  types?: readonly string[];
55
+ onUsage?: (data: unknown) => void;
56
+ onError?: (data: unknown) => void;
55
57
  }): Promise<V2EventFeed>;
56
58
  //# sourceMappingURL=v2-events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"v2-events.d.ts","sourceRoot":"","sources":["../../src/host/v2-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEnD;+CAC+C;AAC/C,eAAO,MAAM,UAAU,qGAMb,CAAA;AAEV,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B;iCAC6B;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;IAClC,aAAa,EAAE,cAAc,EAAE,CAAA;IAC/B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAeD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE;IAAE,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACvE,OAAO,CAAC,WAAW,CAAC,CAsGtB"}
1
+ {"version":3,"file":"v2-events.d.ts","sourceRoot":"","sources":["../../src/host/v2-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEnD;+CAC+C;AAC/C,eAAO,MAAM,UAAU,qGAMb,CAAA;AAEV,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B;iCAC6B;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;IAClC,aAAa,EAAE,cAAc,EAAE,CAAA;IAC/B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAeD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE;IAAE,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,GAC7I,OAAO,CAAC,WAAW,CAAC,CA+HtB"}
@@ -96,6 +96,33 @@ export async function applyV2EventFeed(ctx, opts) {
96
96
  const ev = eventOf(raw);
97
97
  report.received++;
98
98
  const type = String(ev.type ?? "");
99
+ // #39: the usage tap. `session.usage.updated` is not a settle event, so it must NOT
100
+ // enter the dispatcher — but the early-compaction layer needs its numbers, and this is
101
+ // the only place the host publishes them (measured on 2.0.23: the context hook's
102
+ // messages carry none, while this event fired 440 times in one desktop session). The
103
+ // payload never reaches the trajectory; only the count does (R6 binds a diagnostic).
104
+ if (type === "session.usage.updated" && ev.properties && typeof opts.onUsage === "function") {
105
+ try {
106
+ opts.onUsage(ev.properties);
107
+ }
108
+ catch {
109
+ /* a usage tap that throws never closes the feed */
110
+ }
111
+ }
112
+ // #49 feature 3: the retry layer's error tap. `session.error` is the only
113
+ // place the host publishes a provider throttle, and the retry governor needs
114
+ // its text — but the dispatcher must not have to care, so this is a separate
115
+ // tap with the same never-throw discipline as the usage tap. The payload
116
+ // never reaches the trajectory; only the classification count does (R6 binds
117
+ // a diagnostic).
118
+ if (type === "session.error" && typeof opts.onError === "function") {
119
+ try {
120
+ opts.onError(ev);
121
+ }
122
+ catch {
123
+ /* an error tap that throws never closes the feed */
124
+ }
125
+ }
99
126
  if (!type || !allowed.has(type)) {
100
127
  const key = type || "(no type)";
101
128
  report.unknown[key] = (report.unknown[key] ?? 0) + 1;
@@ -1 +1 @@
1
- {"version":3,"file":"v2-events.js","sourceRoot":"","sources":["../../src/host/v2-events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"v2-events.js","sourceRoot":"","sources":["../../src/host/v2-events.ts"],"names":[],"mappings":"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"}