@wrongstack/core 0.250.0 → 0.256.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/dist/{agent-bridge-4gc0vfW2.d.ts → agent-bridge-BrxWHEOm.d.ts} +1 -1
- package/dist/{agent-subagent-runner-Dz-9kiE6.d.ts → agent-subagent-runner-US741uBH.d.ts} +17 -8
- package/dist/{brain-sCZ3lCjq.d.ts → brain-TjEEwSpw.d.ts} +18 -1
- package/dist/{compactor-BRfg3QPd.d.ts → compactor-C5sT4U7I.d.ts} +1 -1
- package/dist/{config-eSsrto5d.d.ts → config-DuAu23zm.d.ts} +16 -1
- package/dist/{context-CLz3z_E8.d.ts → context-CGdgA0q6.d.ts} +13 -0
- package/dist/coordination/index.d.ts +14 -14
- package/dist/coordination/index.js +153 -2
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +25 -25
- package/dist/defaults/index.js +238 -42
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +15 -15
- package/dist/execution/index.js +121 -22
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/{goal-preamble-BjJpnLW4.d.ts → goal-preamble-UiEkbNmW.d.ts} +21 -10
- package/dist/{index-Dy8OwfBD.d.ts → index-CC0Mcm05.d.ts} +9 -9
- package/dist/{index-IehiNryU.d.ts → index-CitPrI3a.d.ts} +20 -7
- package/dist/index.d.ts +112 -42
- package/dist/index.js +759 -114
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/infrastructure/index.js +12 -0
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +10 -10
- package/dist/kernel/index.js.map +1 -1
- package/dist/{llm-selector-D22R4AFz.d.ts → llm-selector-CJ4SyAFE.d.ts} +2 -2
- package/dist/{mcp-servers-DfXxCASH.d.ts → mcp-servers-D8YnLaEp.d.ts} +3 -3
- package/dist/models/index.d.ts +5 -5
- package/dist/{models-registry-DpanBg8D.d.ts → models-registry-ByZCdFuQ.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-CnbEqpv0.d.ts → multi-agent-coordinator-DqTUEAeC.d.ts} +1 -1
- package/dist/{null-fleet-bus-Do1OLYpj.d.ts → null-fleet-bus-B5mfTJXT.d.ts} +17 -6
- package/dist/observability/index.d.ts +2 -2
- package/dist/{package-outdated-watcher-CA5GGB4C.d.ts → package-outdated-watcher-BSgR_kK-.d.ts} +24 -3
- package/dist/{parallel-eternal-engine-UZg1xOzE.d.ts → parallel-eternal-engine-C0juOszP.d.ts} +24 -10
- package/dist/{path-resolver-BaP06Owy.d.ts → path-resolver-CbkT-RMU.d.ts} +3 -3
- package/dist/{permission-DbWPbuoA.d.ts → permission-CwBBpCoF.d.ts} +1 -1
- package/dist/{permission-policy-AOk0LVsV.d.ts → permission-policy-B8rSu908.d.ts} +39 -2
- package/dist/{pipeline-D1n-gQI-.d.ts → pipeline-JG8XoudC.d.ts} +43 -3
- package/dist/{plan-templates-BUVRY0pU.d.ts → plan-templates-DPiQMkBz.d.ts} +5 -5
- package/dist/{provider-runner-D0HgUqwV.d.ts → provider-runner-hM7EXlLI.d.ts} +3 -3
- package/dist/{retry-policy-BVnkbMET.d.ts → retry-policy-Tg7LXkoK.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -8
- package/dist/{secret-vault-CeVNiy_f.d.ts → secret-vault-BkYkJWQs.d.ts} +1 -1
- package/dist/security/index.d.ts +4 -4
- package/dist/security/index.js +89 -18
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-Cb4_9-hf.d.ts → selector-DWsqVjGf.d.ts} +1 -1
- package/dist/{session-event-bridge-BhtkkFFy.d.ts → session-event-bridge-BAFWdgQ3.d.ts} +1 -1
- package/dist/{session-reader-CCOssnBS.d.ts → session-reader-CqRvaL5v.d.ts} +1 -1
- package/dist/{skill-Bj6Ezqb8.d.ts → skill-DGIXCtdv.d.ts} +6 -0
- package/dist/skills/index.d.ts +1 -1
- package/dist/storage/index.d.ts +10 -10
- package/dist/storage/index.js +8 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.d.ts +19 -19
- package/dist/types/index.js +95 -25
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -1
- package/package.json +2 -2
- package/skills/api-design/SKILL.md +1 -0
- package/skills/api-design/SKILL.save.md +26 -0
- package/skills/audit-log/SKILL.md +9 -2
- package/skills/audit-log/SKILL.save.md +22 -0
- package/skills/bug-hunter/SKILL.md +10 -2
- package/skills/bug-hunter/SKILL.save.md +33 -0
- package/skills/chimera/SKILL.md +12 -18
- package/skills/chimera/SKILL.save.md +26 -0
- package/skills/docker-deploy/SKILL.md +1 -0
- package/skills/docker-deploy/SKILL.save.md +23 -0
- package/skills/git-flow/SKILL.md +23 -2
- package/skills/git-flow/SKILL.save.md +25 -0
- package/skills/multi-agent/SKILL.md +23 -2
- package/skills/multi-agent/SKILL.save.md +26 -0
- package/skills/node-modern/SKILL.md +2 -1
- package/skills/node-modern/SKILL.save.md +21 -0
- package/skills/observability/SKILL.md +1 -0
- package/skills/observability/SKILL.save.md +34 -0
- package/skills/output-standards/SKILL.md +133 -0
- package/skills/output-standards/SKILL.save.md +21 -0
- package/skills/prompt-engineering/SKILL.md +2 -1
- package/skills/prompt-engineering/SKILL.save.md +29 -0
- package/skills/react-modern/SKILL.md +2 -1
- package/skills/react-modern/SKILL.save.md +24 -0
- package/skills/refactor-planner/SKILL.md +9 -2
- package/skills/refactor-planner/SKILL.save.md +26 -0
- package/skills/research-web/SKILL.md +1 -0
- package/skills/research-web/SKILL.save.md +25 -0
- package/skills/sdd/SKILL.md +2 -1
- package/skills/sdd/SKILL.save.md +19 -0
- package/skills/security-scanner/SKILL.md +10 -3
- package/skills/security-scanner/SKILL.save.md +23 -0
- package/skills/skill-creator/SKILL.md +2 -1
- package/skills/skill-creator/SKILL.save.md +20 -0
- package/skills/tech-stack/SKILL.md +13 -226
- package/skills/tech-stack/SKILL.save.md +25 -0
- package/skills/testing/SKILL.md +1 -0
- package/skills/testing/SKILL.save.md +22 -0
- package/skills/typescript-strict/SKILL.md +2 -1
- package/skills/typescript-strict/SKILL.save.md +19 -0
package/dist/index.js
CHANGED
|
@@ -190,6 +190,10 @@ var init_session_registry = __esm({
|
|
|
190
190
|
* Starts the heartbeat timer.
|
|
191
191
|
*/
|
|
192
192
|
async register(entry) {
|
|
193
|
+
if (this.heartbeatTimer) {
|
|
194
|
+
clearInterval(this.heartbeatTimer);
|
|
195
|
+
this.heartbeatTimer = null;
|
|
196
|
+
}
|
|
193
197
|
this.currentSessionId = entry.sessionId;
|
|
194
198
|
const full = {
|
|
195
199
|
...entry,
|
|
@@ -201,7 +205,10 @@ var init_session_registry = __esm({
|
|
|
201
205
|
await this.atomicUpdate((registry) => {
|
|
202
206
|
const now = Date.now();
|
|
203
207
|
for (const [id, existing] of Object.entries(registry)) {
|
|
204
|
-
if (existing.pid === entry.pid)
|
|
208
|
+
if (existing.pid === entry.pid) {
|
|
209
|
+
if (id !== entry.sessionId) delete registry[id];
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
205
212
|
const heartbeatAge = now - new Date(existing.lastHeartbeatAt).getTime();
|
|
206
213
|
if (heartbeatAge > STALE_TIMEOUT_MS && !pidAlive(existing.pid)) {
|
|
207
214
|
delete registry[id];
|
|
@@ -2045,6 +2052,10 @@ var DefaultTokenCounter = class {
|
|
|
2045
2052
|
const price = model ? this.priceCache.get(model) : void 0;
|
|
2046
2053
|
if (price) {
|
|
2047
2054
|
this.applyPrice(usage, price);
|
|
2055
|
+
this.events?.emit("token.accounted", {
|
|
2056
|
+
usage: this.total(),
|
|
2057
|
+
cost: { input: this.costInput, output: this.costOutput, total: this.costInput + this.costOutput }
|
|
2058
|
+
});
|
|
2048
2059
|
} else if (this.registry && this.providerId && model) {
|
|
2049
2060
|
if (this.priceCache.size >= PRICE_CACHE_MAX_SIZE) {
|
|
2050
2061
|
const keys = [...this.priceCache.keys()];
|
|
@@ -2055,6 +2066,10 @@ var DefaultTokenCounter = class {
|
|
|
2055
2066
|
const p = priceFromModel(m);
|
|
2056
2067
|
this.priceCache.set(model, p);
|
|
2057
2068
|
this.applyPrice(usage, p);
|
|
2069
|
+
this.events?.emit("token.accounted", {
|
|
2070
|
+
usage: this.total(),
|
|
2071
|
+
cost: { input: this.costInput, output: this.costOutput, total: this.costInput + this.costOutput }
|
|
2072
|
+
});
|
|
2058
2073
|
}
|
|
2059
2074
|
}).catch(() => {
|
|
2060
2075
|
this.events?.emit("token.cost_estimate_unavailable", { model: model ?? "<unknown>" });
|
|
@@ -2077,6 +2092,10 @@ var DefaultTokenCounter = class {
|
|
|
2077
2092
|
}
|
|
2078
2093
|
this.priceCache.set(resolved.modelId, price);
|
|
2079
2094
|
this.applyPrice(usage, price);
|
|
2095
|
+
this.events?.emit("token.accounted", {
|
|
2096
|
+
usage: this.total(),
|
|
2097
|
+
cost: { input: this.costInput, output: this.costOutput, total: this.costInput + this.costOutput }
|
|
2098
|
+
});
|
|
2080
2099
|
}
|
|
2081
2100
|
total() {
|
|
2082
2101
|
return {
|
|
@@ -3042,9 +3061,28 @@ var PATTERNS = [
|
|
|
3042
3061
|
}
|
|
3043
3062
|
];
|
|
3044
3063
|
var SCRUB_CHUNK_BYTES = 64 * 1024;
|
|
3064
|
+
function hasCredentialAnchors(text) {
|
|
3065
|
+
return text.includes("-----BEGIN") || // Private keys (most unique → cheap reject)
|
|
3066
|
+
text.includes("sk-") || // Anthropic + OpenAI keys
|
|
3067
|
+
text.includes("sk_") || // Stripe live/test keys
|
|
3068
|
+
text.includes("ghp_") || // GitHub PAT v1
|
|
3069
|
+
text.includes("github_pat_") || // GitHub PAT v2
|
|
3070
|
+
text.includes("eyJ") || // JWT
|
|
3071
|
+
text.includes("AKIA") || // AWS access key
|
|
3072
|
+
text.includes("AIza") || // GCP service key
|
|
3073
|
+
text.includes("xox") || // Slack token (xoxa/xoxb/xoxp/xoxo/xoxs)
|
|
3074
|
+
text.includes("Bearer ") || // Bearer token (space suffix reduces false positives)
|
|
3075
|
+
text.includes("/bot") || // Telegram bot token (URL path pattern)
|
|
3076
|
+
text.includes("_KEY=") || // High-entropy env vars: API_KEY=, SECRET_KEY=, ...
|
|
3077
|
+
text.includes("_TOKEN=") || // ACCESS_TOKEN=, AUTH_TOKEN=, ...
|
|
3078
|
+
text.includes("_SECRET=") || // API_SECRET=, CLIENT_SECRET=, ...
|
|
3079
|
+
text.includes("_PASSWORD=") || // DB_PASSWORD=, ROOT_PASSWORD=, ...
|
|
3080
|
+
text.includes("mongodb://") || text.includes("mongodb+srv://") || text.includes("postgres://") || text.includes("postgresql://") || text.includes("mysql://") || text.includes("redis://");
|
|
3081
|
+
}
|
|
3045
3082
|
var DefaultSecretScrubber = class {
|
|
3046
3083
|
scrub(text) {
|
|
3047
3084
|
if (!text) return text;
|
|
3085
|
+
if (!hasCredentialAnchors(text)) return text;
|
|
3048
3086
|
if (text.length <= SCRUB_CHUNK_BYTES) {
|
|
3049
3087
|
return this.scrubOne(text);
|
|
3050
3088
|
}
|
|
@@ -3062,6 +3100,7 @@ var DefaultSecretScrubber = class {
|
|
|
3062
3100
|
return out.join("");
|
|
3063
3101
|
}
|
|
3064
3102
|
scrubOne(text) {
|
|
3103
|
+
if (!hasCredentialAnchors(text)) return text;
|
|
3065
3104
|
let out = text;
|
|
3066
3105
|
for (const p of PATTERNS) {
|
|
3067
3106
|
out = out.replace(p.regex, (_match, group1, group2) => {
|
|
@@ -4099,10 +4138,14 @@ var ToolCapabilities = {
|
|
|
4099
4138
|
SHELL_ARBITRARY: "shell.arbitrary",
|
|
4100
4139
|
/** Can execute a restricted set of commands (the `exec` tool). */
|
|
4101
4140
|
SHELL_RESTRICTED: "shell.restricted",
|
|
4141
|
+
/** Can read files inside the project (and possibly outside via symlinks if not guarded). */
|
|
4142
|
+
FS_READ: "fs.read",
|
|
4102
4143
|
/** Can write / modify / delete files inside the project. */
|
|
4103
4144
|
FS_WRITE: "fs.write",
|
|
4104
4145
|
/** Can write files outside the current project root (very high risk). */
|
|
4105
4146
|
FS_WRITE_OUTSIDE_PROJECT: "fs.write.outside-project",
|
|
4147
|
+
/** Can perform outbound network requests. */
|
|
4148
|
+
NET_OUTBOUND: "net.outbound",
|
|
4106
4149
|
/** Proxies tools from external MCP servers (unknown capability). */
|
|
4107
4150
|
MCP_PROXY: "mcp.proxy",
|
|
4108
4151
|
/** Can spawn or manage subagents / multi-agent tasks. */
|
|
@@ -4339,7 +4382,7 @@ var ToolExecutor = class _ToolExecutor {
|
|
|
4339
4382
|
const tool = this.registry.get(use.name);
|
|
4340
4383
|
if (!tool) {
|
|
4341
4384
|
const result = this.unknownToolResult(use, () => this.registry.list().map((t2) => t2.name));
|
|
4342
|
-
budget = this.
|
|
4385
|
+
budget = this.budgetForString(result.content, budget);
|
|
4343
4386
|
return { result, tool, durationMs: Date.now() - start };
|
|
4344
4387
|
}
|
|
4345
4388
|
const validation = validateAgainstSchema(use.input, tool.inputSchema);
|
|
@@ -4356,20 +4399,20 @@ ${errorDetails}
|
|
|
4356
4399
|
Please call the tool again with arguments that match its inputSchema. You can use the "tool-help" tool with name="${tool.name}" to see the exact expected schema.`,
|
|
4357
4400
|
is_error: true
|
|
4358
4401
|
};
|
|
4359
|
-
budget = this.
|
|
4402
|
+
budget = this.budgetForString(result.content, budget);
|
|
4360
4403
|
return { result, tool, durationMs: Date.now() - start };
|
|
4361
4404
|
}
|
|
4362
4405
|
const toolDangerousCaps = getDangerousCapabilities(tool);
|
|
4363
4406
|
if (hasMalformedArguments(use.input)) {
|
|
4364
4407
|
const result = this.malformedInputResult(use, extractMalformedRaw(use.input));
|
|
4365
|
-
budget = this.
|
|
4408
|
+
budget = this.budgetForString(result.content, budget);
|
|
4366
4409
|
return { result, tool, durationMs: Date.now() - start };
|
|
4367
4410
|
}
|
|
4368
4411
|
if (this.opts.hookRunner?.has("PreToolUse")) {
|
|
4369
4412
|
const pre = await this.opts.hookRunner.preToolUse(tool.name, use.input, ctx);
|
|
4370
4413
|
if (pre.block) {
|
|
4371
4414
|
const result = this.blockedByHookResult(use, pre.reason);
|
|
4372
|
-
budget = this.
|
|
4415
|
+
budget = this.budgetForString(result.content, budget);
|
|
4373
4416
|
return { result, tool, durationMs: Date.now() - start };
|
|
4374
4417
|
}
|
|
4375
4418
|
if (pre.input) {
|
|
@@ -4385,7 +4428,7 @@ Validation errors:
|
|
|
4385
4428
|
${errorDetails}`,
|
|
4386
4429
|
is_error: true
|
|
4387
4430
|
};
|
|
4388
|
-
budget = this.
|
|
4431
|
+
budget = this.budgetForString(result.content, budget);
|
|
4389
4432
|
return { result, tool, durationMs: Date.now() - start };
|
|
4390
4433
|
}
|
|
4391
4434
|
use = { ...use, input: pre.input };
|
|
@@ -4400,7 +4443,7 @@ ${errorDetails}`,
|
|
|
4400
4443
|
}
|
|
4401
4444
|
if (effectivePermission === "deny") {
|
|
4402
4445
|
const result = this.deniedResult(use, decision.reason);
|
|
4403
|
-
budget = this.
|
|
4446
|
+
budget = this.budgetForString(result.content, budget);
|
|
4404
4447
|
return { result, tool, durationMs: Date.now() - start };
|
|
4405
4448
|
}
|
|
4406
4449
|
if (effectivePermission === "confirm") {
|
|
@@ -4413,7 +4456,7 @@ ${errorDetails}`,
|
|
|
4413
4456
|
content: `Tool "${tool.name}" denied by user.`,
|
|
4414
4457
|
is_error: true
|
|
4415
4458
|
};
|
|
4416
|
-
budget = this.
|
|
4459
|
+
budget = this.budgetForString(result.content, budget);
|
|
4417
4460
|
return { result, tool, durationMs: Date.now() - start };
|
|
4418
4461
|
}
|
|
4419
4462
|
} else {
|
|
@@ -4437,7 +4480,8 @@ ${errorDetails}`,
|
|
|
4437
4480
|
"tool.has_dangerous_capabilities": toolCapsForAudit.length > 0
|
|
4438
4481
|
});
|
|
4439
4482
|
try {
|
|
4440
|
-
let result = await this.executeTool(tool, use, ctx, budget);
|
|
4483
|
+
let { block: result, bytes } = await this.executeTool(tool, use, ctx, budget);
|
|
4484
|
+
budget -= bytes;
|
|
4441
4485
|
if (this.opts.hookRunner?.has("PostToolUse")) {
|
|
4442
4486
|
const post = await this.opts.hookRunner.postToolUse(
|
|
4443
4487
|
tool.name,
|
|
@@ -4446,12 +4490,13 @@ ${errorDetails}`,
|
|
|
4446
4490
|
ctx
|
|
4447
4491
|
);
|
|
4448
4492
|
if (post.additionalContext) {
|
|
4449
|
-
|
|
4493
|
+
const appended = `
|
|
4450
4494
|
|
|
4451
|
-
${post.additionalContext}
|
|
4495
|
+
${post.additionalContext}`;
|
|
4496
|
+
result = { ...result, content: `${result.content}${appended}` };
|
|
4497
|
+
budget = Math.max(0, budget - Buffer.byteLength(appended, "utf8"));
|
|
4452
4498
|
}
|
|
4453
4499
|
}
|
|
4454
|
-
budget = this.decrementBudget(result, budget);
|
|
4455
4500
|
span?.setAttribute("tool.is_error", !!result.is_error);
|
|
4456
4501
|
span?.setAttribute(
|
|
4457
4502
|
"tool.output_bytes",
|
|
@@ -4468,7 +4513,7 @@ ${post.additionalContext}` };
|
|
|
4468
4513
|
content: `Tool "${tool.name}" threw: ${scrubbed}`,
|
|
4469
4514
|
is_error: true
|
|
4470
4515
|
};
|
|
4471
|
-
budget = this.
|
|
4516
|
+
budget = this.budgetForString(result.content, budget);
|
|
4472
4517
|
if (err instanceof Error) span?.recordError(err);
|
|
4473
4518
|
span?.setAttribute("tool.is_error", true);
|
|
4474
4519
|
return { result, tool, durationMs: Date.now() - start };
|
|
@@ -4488,7 +4533,7 @@ ${post.additionalContext}` };
|
|
|
4488
4533
|
content: `Tool "${use.name}" execution failed: ${scrubbed}`,
|
|
4489
4534
|
is_error: true
|
|
4490
4535
|
};
|
|
4491
|
-
budget = this.
|
|
4536
|
+
budget = this.budgetForString(result.content, budget);
|
|
4492
4537
|
return { result, tool: this.registry.get(use.name), durationMs: 0 };
|
|
4493
4538
|
}
|
|
4494
4539
|
};
|
|
@@ -4537,14 +4582,20 @@ ${post.additionalContext}` };
|
|
|
4537
4582
|
const output = await this.runWithTimeout(tool, use.input, ctx.signal, ctx, use.id);
|
|
4538
4583
|
const text = this.serializer.serialize(output);
|
|
4539
4584
|
const scrubbed = this.opts.secretScrubber.scrub(text);
|
|
4540
|
-
const { text: capped } = this.serializer.enforceCap(scrubbed, budget);
|
|
4585
|
+
const { text: capped, newBudget } = this.serializer.enforceCap(scrubbed, budget);
|
|
4541
4586
|
this.opts.renderer?.writeToolResult(tool.name, capped, false);
|
|
4542
4587
|
return {
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4588
|
+
block: {
|
|
4589
|
+
type: "tool_result",
|
|
4590
|
+
tool_use_id: use.id,
|
|
4591
|
+
name: tool.name,
|
|
4592
|
+
content: capped,
|
|
4593
|
+
is_error: false
|
|
4594
|
+
},
|
|
4595
|
+
// `budget - newBudget` is the exact byte count enforceCap spent
|
|
4596
|
+
// (capped at `budget` so a truncated output shows as `budget`
|
|
4597
|
+
// consumed, matching the pre-fix `decrementBudget` semantics).
|
|
4598
|
+
bytes: budget - newBudget
|
|
4548
4599
|
};
|
|
4549
4600
|
}
|
|
4550
4601
|
async runWithTimeout(tool, input, parentSignal, ctx, toolUseId) {
|
|
@@ -4684,9 +4735,19 @@ ${excerpt}`;
|
|
|
4684
4735
|
is_error: true
|
|
4685
4736
|
};
|
|
4686
4737
|
}
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4738
|
+
/**
|
|
4739
|
+
* Subtract a string-content result's UTF-8 byte length from the
|
|
4740
|
+
* iteration output budget. Used for synthesized results (unknown tool,
|
|
4741
|
+
* validation error, blocked, threw) where the content is a small
|
|
4742
|
+
* string built in the executor. The success path no longer goes
|
|
4743
|
+
* through here — `executeTool` carries the exact byte count it spent
|
|
4744
|
+
* in its return value, derived from `enforceCap`'s `newBudget`.
|
|
4745
|
+
*
|
|
4746
|
+
* Floors the result at 0 to match the pre-fix `decrementBudget`
|
|
4747
|
+
* semantics (over-budget spends don't underflow the running total).
|
|
4748
|
+
*/
|
|
4749
|
+
budgetForString(content, budget) {
|
|
4750
|
+
return Math.max(0, budget - Buffer.byteLength(content, "utf8"));
|
|
4690
4751
|
}
|
|
4691
4752
|
/**
|
|
4692
4753
|
* Compute the suggestedPattern string for a tool+input pair.
|
|
@@ -4792,10 +4853,19 @@ var ConversationState = class {
|
|
|
4792
4853
|
this.emit({ kind: "message_appended", message });
|
|
4793
4854
|
}
|
|
4794
4855
|
replaceMessages(messages) {
|
|
4856
|
+
let hasToolBlock = false;
|
|
4795
4857
|
for (const m of messages) {
|
|
4796
4858
|
if (m._estTokens === void 0) {
|
|
4797
4859
|
m._estTokens = computeMessageTokens(m);
|
|
4798
4860
|
}
|
|
4861
|
+
if (!hasToolBlock && Array.isArray(m.content)) {
|
|
4862
|
+
for (const b of m.content) {
|
|
4863
|
+
if (b.type === "tool_use" || b.type === "tool_result") {
|
|
4864
|
+
hasToolBlock = true;
|
|
4865
|
+
break;
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4799
4869
|
}
|
|
4800
4870
|
const arr = this.ctx.messages;
|
|
4801
4871
|
if (messages.length < arr.length) {
|
|
@@ -4804,9 +4874,7 @@ var ConversationState = class {
|
|
|
4804
4874
|
for (let i = 0; i < messages.length; i++) {
|
|
4805
4875
|
arr[i] = messages[i];
|
|
4806
4876
|
}
|
|
4807
|
-
if (
|
|
4808
|
-
(m) => Array.isArray(m.content) && m.content.some((b) => b.type === "tool_use" || b.type === "tool_result")
|
|
4809
|
-
)) {
|
|
4877
|
+
if (hasToolBlock) {
|
|
4810
4878
|
this.ctx.toolAdjacencyDirty = true;
|
|
4811
4879
|
}
|
|
4812
4880
|
this.emit({ kind: "messages_replaced", messages: [...messages] });
|
|
@@ -4885,6 +4953,19 @@ var Context = class {
|
|
|
4885
4953
|
* on iterations where no tool content was added (pure text responses).
|
|
4886
4954
|
*/
|
|
4887
4955
|
toolAdjacencyDirty = false;
|
|
4956
|
+
/**
|
|
4957
|
+
* H1: pre-computed total-request token estimate from the most recent
|
|
4958
|
+
* `estimateRequestTokens()` call in the agent loop's pre-flight step.
|
|
4959
|
+
* The middleware that decides when to compact, the `emitContextPct`
|
|
4960
|
+
* helper that drives the live context-fill bar, and the pre-flight
|
|
4961
|
+
* itself all need this number; previously each one walked the same
|
|
4962
|
+
* messages/system/tools arrays independently. Stashing it here lets
|
|
4963
|
+
* the three call sites share a single compute per iteration.
|
|
4964
|
+
*
|
|
4965
|
+
* The value is the **uncalibrated** total. Callers that want the
|
|
4966
|
+
* calibrated number apply the per-(provider,model) ratio themselves.
|
|
4967
|
+
*/
|
|
4968
|
+
lastRequestTokens = void 0;
|
|
4888
4969
|
constructor(init) {
|
|
4889
4970
|
this.systemPrompt = init.systemPrompt;
|
|
4890
4971
|
this.provider = init.provider;
|
|
@@ -5921,8 +6002,10 @@ function buildChildEnv(optsOrSessionId) {
|
|
|
5921
6002
|
);
|
|
5922
6003
|
}
|
|
5923
6004
|
const out = {};
|
|
6005
|
+
const nodeEnvDefaulted = process.env["WRONGSTACK_NODE_ENV_DEFAULTED"] === "1";
|
|
5924
6006
|
for (const [k, v] of Object.entries(process.env)) {
|
|
5925
6007
|
if (v === void 0) continue;
|
|
6008
|
+
if (nodeEnvDefaulted && (k === "NODE_ENV" || k === "WRONGSTACK_NODE_ENV_DEFAULTED")) continue;
|
|
5926
6009
|
if (passthrough) {
|
|
5927
6010
|
out[k] = v;
|
|
5928
6011
|
continue;
|
|
@@ -6081,6 +6164,9 @@ async function expandGlob(pattern) {
|
|
|
6081
6164
|
function completePartialObject(s) {
|
|
6082
6165
|
if (!s.trim().startsWith("{")) return s;
|
|
6083
6166
|
if (tryParse(s).ok) return s;
|
|
6167
|
+
return repairTruncated(s);
|
|
6168
|
+
}
|
|
6169
|
+
function repairTruncated(s) {
|
|
6084
6170
|
const stack = [];
|
|
6085
6171
|
let inString = false;
|
|
6086
6172
|
let escaped = false;
|
|
@@ -9314,6 +9400,21 @@ var DefaultPermissionPolicy = class {
|
|
|
9314
9400
|
promptDelegate;
|
|
9315
9401
|
/** Pre-compiled wildcard patterns — rebuilt on reload for O(1) lookup. */
|
|
9316
9402
|
wildcardEntries = [];
|
|
9403
|
+
/**
|
|
9404
|
+
* Evaluate-result cache. Keyed by `tool.name::subject` so repeated calls
|
|
9405
|
+
* with the same tool+input skip namespace matching, subject computation,
|
|
9406
|
+
* pattern matching (matchAny), and YOLO destructive gating.
|
|
9407
|
+
*
|
|
9408
|
+
* Cleared on any state change (reload, trust, deny, yolo toggle) because
|
|
9409
|
+
* the result depends on the full policy state. The write-tool smart-bypass
|
|
9410
|
+
* (step 7 in `evaluate()`) is not cached since `ctx.hasRead()` changes
|
|
9411
|
+
* dynamically within a session.
|
|
9412
|
+
*
|
|
9413
|
+
* LRU eviction is not needed — the cache is cleared on state changes
|
|
9414
|
+
* that are rare (trust file ops, user confirm) and the number of unique
|
|
9415
|
+
* tool+subject pairs per iteration is small (<50).
|
|
9416
|
+
*/
|
|
9417
|
+
_evalCache = /* @__PURE__ */ new Map();
|
|
9317
9418
|
constructor(opts) {
|
|
9318
9419
|
this.trustFile = opts.trustFile;
|
|
9319
9420
|
this.yolo = opts.yolo ?? false;
|
|
@@ -9332,6 +9433,7 @@ var DefaultPermissionPolicy = class {
|
|
|
9332
9433
|
}
|
|
9333
9434
|
/** Toggle YOLO (auto-approve) mode at runtime. */
|
|
9334
9435
|
setYolo(enabled) {
|
|
9436
|
+
if (this.yolo !== enabled) this._evalCache.clear();
|
|
9335
9437
|
this.yolo = enabled;
|
|
9336
9438
|
}
|
|
9337
9439
|
/** Check whether YOLO mode is currently active. */
|
|
@@ -9340,6 +9442,7 @@ var DefaultPermissionPolicy = class {
|
|
|
9340
9442
|
}
|
|
9341
9443
|
/** Toggle the destructive YOLO override at runtime. */
|
|
9342
9444
|
setYoloDestructive(enabled) {
|
|
9445
|
+
if (this.yoloDestructive !== enabled) this._evalCache.clear();
|
|
9343
9446
|
this.yoloDestructive = enabled;
|
|
9344
9447
|
}
|
|
9345
9448
|
/** Check whether the destructive YOLO override is active. */
|
|
@@ -9348,6 +9451,7 @@ var DefaultPermissionPolicy = class {
|
|
|
9348
9451
|
}
|
|
9349
9452
|
/** Toggle destructive confirmation gate (only meaningful when yolo is active). */
|
|
9350
9453
|
setConfirmDestructive(enabled) {
|
|
9454
|
+
if (this.confirmDestructive !== enabled) this._evalCache.clear();
|
|
9351
9455
|
this.confirmDestructive = enabled;
|
|
9352
9456
|
}
|
|
9353
9457
|
/** Check whether destructive confirmation gate is active. */
|
|
@@ -9368,6 +9472,7 @@ var DefaultPermissionPolicy = class {
|
|
|
9368
9472
|
}
|
|
9369
9473
|
this.sessionDenied.clear();
|
|
9370
9474
|
this.sessionAllowed.clear();
|
|
9475
|
+
this._evalCache.clear();
|
|
9371
9476
|
this.loaded = true;
|
|
9372
9477
|
}
|
|
9373
9478
|
async evaluate(tool, input, ctx) {
|
|
@@ -9375,44 +9480,60 @@ var DefaultPermissionPolicy = class {
|
|
|
9375
9480
|
const namespaceEntry = this.findNamespaceEntry(tool.name);
|
|
9376
9481
|
const entry = this.policy[tool.name] ?? namespaceEntry;
|
|
9377
9482
|
const subject = this.subjectFor(tool.name, input, tool.subjectKey);
|
|
9378
|
-
const
|
|
9379
|
-
if (
|
|
9380
|
-
|
|
9483
|
+
const cacheKey = `${tool.name}::${subject ?? tool.name}`;
|
|
9484
|
+
if (tool.name !== "write") {
|
|
9485
|
+
const cached = this._evalCache.get(cacheKey);
|
|
9486
|
+
if (cached !== void 0) return cached;
|
|
9487
|
+
}
|
|
9488
|
+
if (this.sessionDenied.has(cacheKey)) {
|
|
9489
|
+
const decision = { permission: "deny", source: "deny", reason: "session soft deny (user pressed no)" };
|
|
9490
|
+
this._evalCache.set(cacheKey, decision);
|
|
9491
|
+
return decision;
|
|
9381
9492
|
}
|
|
9382
|
-
if (this.sessionAllowed.has(
|
|
9383
|
-
|
|
9493
|
+
if (this.sessionAllowed.has(cacheKey)) {
|
|
9494
|
+
const decision = {
|
|
9384
9495
|
permission: "auto",
|
|
9385
9496
|
source: "trust",
|
|
9386
9497
|
reason: "session soft allow (user pressed yes)"
|
|
9387
9498
|
};
|
|
9499
|
+
this._evalCache.set(cacheKey, decision);
|
|
9500
|
+
return decision;
|
|
9388
9501
|
}
|
|
9389
9502
|
if (entry?.deny && subject && matchAny(entry.deny, subject)) {
|
|
9390
|
-
|
|
9503
|
+
const decision = { permission: "deny", source: "deny", reason: "matched deny pattern" };
|
|
9504
|
+
this._evalCache.set(cacheKey, decision);
|
|
9505
|
+
return decision;
|
|
9391
9506
|
}
|
|
9392
9507
|
if (tool.permission === "deny") {
|
|
9393
|
-
|
|
9508
|
+
const decision = { permission: "deny", source: "default", reason: "tool default deny" };
|
|
9509
|
+
this._evalCache.set(cacheKey, decision);
|
|
9510
|
+
return decision;
|
|
9394
9511
|
}
|
|
9395
9512
|
if (entry?.allow && subject && matchAny(entry.allow, subject)) {
|
|
9396
|
-
|
|
9513
|
+
const decision = { permission: "auto", source: "trust", reason: "matched allow pattern" };
|
|
9514
|
+
this._evalCache.set(cacheKey, decision);
|
|
9515
|
+
return decision;
|
|
9397
9516
|
}
|
|
9398
9517
|
if (entry?.auto) {
|
|
9399
|
-
|
|
9518
|
+
const decision = { permission: "auto", source: "trust" };
|
|
9519
|
+
this._evalCache.set(cacheKey, decision);
|
|
9520
|
+
return decision;
|
|
9400
9521
|
}
|
|
9401
9522
|
if (this.yolo) {
|
|
9402
9523
|
if (this.confirmDestructive) {
|
|
9403
9524
|
const destructive = this.isDestructiveYoloCall(tool, input, ctx);
|
|
9404
9525
|
if (destructive) {
|
|
9405
9526
|
if (this.promptDelegate) {
|
|
9406
|
-
const
|
|
9407
|
-
if (
|
|
9527
|
+
const decision2 = await this.promptDelegate(tool, input, subject ?? tool.name);
|
|
9528
|
+
if (decision2 === "always") {
|
|
9408
9529
|
await this.trust({ tool: tool.name, pattern: subject ?? tool.name });
|
|
9409
9530
|
return { permission: "auto", source: "user", reason: "destructive yolo always-allowed" };
|
|
9410
9531
|
}
|
|
9411
|
-
if (
|
|
9532
|
+
if (decision2 === "deny") {
|
|
9412
9533
|
await this.deny({ tool: tool.name, pattern: subject ?? tool.name });
|
|
9413
9534
|
return { permission: "deny", source: "user", reason: "user denied destructive yolo" };
|
|
9414
9535
|
}
|
|
9415
|
-
return { permission:
|
|
9536
|
+
return { permission: decision2 === "yes" ? "auto" : "deny", source: "user" };
|
|
9416
9537
|
}
|
|
9417
9538
|
return {
|
|
9418
9539
|
permission: "confirm",
|
|
@@ -9422,7 +9543,9 @@ var DefaultPermissionPolicy = class {
|
|
|
9422
9543
|
};
|
|
9423
9544
|
}
|
|
9424
9545
|
}
|
|
9425
|
-
|
|
9546
|
+
const decision = { permission: "auto", source: "yolo" };
|
|
9547
|
+
this._evalCache.set(cacheKey, decision);
|
|
9548
|
+
return decision;
|
|
9426
9549
|
}
|
|
9427
9550
|
if (tool.name === "write" && subject) {
|
|
9428
9551
|
if (ctx.hasRead(subject)) {
|
|
@@ -9434,7 +9557,9 @@ var DefaultPermissionPolicy = class {
|
|
|
9434
9557
|
}
|
|
9435
9558
|
}
|
|
9436
9559
|
if (tool.permission === "auto" && !tool.mutating) {
|
|
9437
|
-
|
|
9560
|
+
const decision = { permission: "auto", source: "default" };
|
|
9561
|
+
this._evalCache.set(cacheKey, decision);
|
|
9562
|
+
return decision;
|
|
9438
9563
|
}
|
|
9439
9564
|
if (this.promptDelegate) {
|
|
9440
9565
|
const decision = await this.promptDelegate(tool, input, subject ?? tool.name);
|
|
@@ -9467,6 +9592,7 @@ var DefaultPermissionPolicy = class {
|
|
|
9467
9592
|
const entry = this.policy[rule.tool] ?? {};
|
|
9468
9593
|
entry.allow = Array.from(/* @__PURE__ */ new Set([...entry.allow ?? [], rule.pattern]));
|
|
9469
9594
|
this.policy[rule.tool] = entry;
|
|
9595
|
+
this._evalCache.clear();
|
|
9470
9596
|
try {
|
|
9471
9597
|
await atomicWrite(this.trustFile, JSON.stringify(this.policy, null, 2));
|
|
9472
9598
|
} catch (err) {
|
|
@@ -9484,6 +9610,7 @@ var DefaultPermissionPolicy = class {
|
|
|
9484
9610
|
const entry = this.policy[rule.tool] ?? {};
|
|
9485
9611
|
entry.deny = Array.from(/* @__PURE__ */ new Set([...entry.deny ?? [], rule.pattern]));
|
|
9486
9612
|
this.policy[rule.tool] = entry;
|
|
9613
|
+
this._evalCache.clear();
|
|
9487
9614
|
try {
|
|
9488
9615
|
await atomicWrite(this.trustFile, JSON.stringify(this.policy, null, 2));
|
|
9489
9616
|
} catch (err) {
|
|
@@ -9498,10 +9625,12 @@ var DefaultPermissionPolicy = class {
|
|
|
9498
9625
|
/** Block this tool+pattern for the rest of this session (no trust file). */
|
|
9499
9626
|
denyOnce(rule) {
|
|
9500
9627
|
this.sessionDenied.set(`${rule.tool}::${rule.pattern}`, true);
|
|
9628
|
+
this._evalCache.clear();
|
|
9501
9629
|
}
|
|
9502
9630
|
/** Auto-approve this tool+pattern for the rest of this session (no trust file). */
|
|
9503
9631
|
allowOnce(rule) {
|
|
9504
9632
|
this.sessionAllowed.set(`${rule.tool}::${rule.pattern}`, true);
|
|
9633
|
+
this._evalCache.clear();
|
|
9505
9634
|
}
|
|
9506
9635
|
subjectFor(toolName, input, subjectKey) {
|
|
9507
9636
|
if (!input || typeof input !== "object") return void 0;
|
|
@@ -9537,15 +9666,23 @@ var DefaultPermissionPolicy = class {
|
|
|
9537
9666
|
}
|
|
9538
9667
|
};
|
|
9539
9668
|
var AutoApprovePermissionPolicy = class _AutoApprovePermissionPolicy {
|
|
9669
|
+
allowedCapabilities;
|
|
9670
|
+
constructor(allowedCapabilities) {
|
|
9671
|
+
this.allowedCapabilities = allowedCapabilities ?? [
|
|
9672
|
+
ToolCapabilities.FS_READ,
|
|
9673
|
+
ToolCapabilities.NET_OUTBOUND
|
|
9674
|
+
];
|
|
9675
|
+
}
|
|
9540
9676
|
static isMcpTool(name) {
|
|
9541
9677
|
return name.startsWith("mcp__");
|
|
9542
9678
|
}
|
|
9543
9679
|
async evaluate(tool) {
|
|
9544
|
-
const
|
|
9680
|
+
const caps = tool.capabilities ?? [];
|
|
9681
|
+
const hasAllowedCap = caps.some((c) => this.allowedCapabilities.includes(c));
|
|
9545
9682
|
const isMcp = _AutoApprovePermissionPolicy.isMcpTool(tool.name);
|
|
9546
|
-
const blocked = tool.permission === "deny" ||
|
|
9683
|
+
const blocked = tool.permission === "deny" || isMcp || !hasAllowedCap;
|
|
9547
9684
|
if (blocked) {
|
|
9548
|
-
const reason =
|
|
9685
|
+
const reason = isMcp ? `MCP tool ${tool.name} is not auto-approved for subagents \u2014 ask the leader to allow it explicitly` : tool.permission === "deny" ? "tool default deny" : `tool lacks allowed capability (has: ${caps.join(", ") || "none"}, allowed: ${this.allowedCapabilities.join(", ")})`;
|
|
9549
9686
|
return {
|
|
9550
9687
|
permission: "deny",
|
|
9551
9688
|
source: "subagent_guard",
|
|
@@ -9565,6 +9702,35 @@ var AutoApprovePermissionPolicy = class _AutoApprovePermissionPolicy {
|
|
|
9565
9702
|
async reload() {
|
|
9566
9703
|
}
|
|
9567
9704
|
};
|
|
9705
|
+
function stripFrontmatter(raw) {
|
|
9706
|
+
if (!raw.startsWith("---")) return raw;
|
|
9707
|
+
const end = raw.indexOf("\n---", 4);
|
|
9708
|
+
if (end === -1) return raw;
|
|
9709
|
+
let body = raw.slice(end + 4);
|
|
9710
|
+
if (body.startsWith("\n")) body = body.slice(1);
|
|
9711
|
+
return body;
|
|
9712
|
+
}
|
|
9713
|
+
function compactSkillBody(body) {
|
|
9714
|
+
const sections = [];
|
|
9715
|
+
const overviewMatch = body.match(/##\s*Overview\s*\n([\s\S]*?)(?=\n##|\n$|$)/i);
|
|
9716
|
+
const overview = overviewMatch?.[1];
|
|
9717
|
+
if (overview?.trim()) {
|
|
9718
|
+
sections.push(overview.trim().slice(0, 200));
|
|
9719
|
+
}
|
|
9720
|
+
const rulesMatch = body.match(/##\s*Rules\s*\n([\s\S]*?)(?=\n##|\n$|$)/i);
|
|
9721
|
+
const rules = rulesMatch?.[1];
|
|
9722
|
+
if (rules?.trim()) {
|
|
9723
|
+
const trimmed = rules.trim().slice(0, 350);
|
|
9724
|
+
const ruleLines = trimmed.split("\n").filter((l) => /^\s*[-*]\s/.test(l) || /^\s*\d+[.)]\s/.test(l)).slice(0, 6).join("\n");
|
|
9725
|
+
if (ruleLines) sections.push(ruleLines);
|
|
9726
|
+
}
|
|
9727
|
+
if (sections.length === 0) {
|
|
9728
|
+
const first = body.trim().slice(0, 200);
|
|
9729
|
+
if (first) sections.push(first);
|
|
9730
|
+
}
|
|
9731
|
+
const result = sections.join("\n\n");
|
|
9732
|
+
return result.length > 450 ? result.slice(0, 447) + "\u2026" : result;
|
|
9733
|
+
}
|
|
9568
9734
|
var DefaultSkillLoader = class {
|
|
9569
9735
|
dirs;
|
|
9570
9736
|
cache;
|
|
@@ -9646,6 +9812,24 @@ var DefaultSkillLoader = class {
|
|
|
9646
9812
|
if (!m) throw new Error(`Skill "${name}" not found`);
|
|
9647
9813
|
return fsp3.readFile(m.path, "utf8");
|
|
9648
9814
|
}
|
|
9815
|
+
async readSaveBody(name) {
|
|
9816
|
+
const m = await this.find(name);
|
|
9817
|
+
if (!m) throw new Error(`Skill "${name}" not found`);
|
|
9818
|
+
const savePath = path7.join(path7.dirname(m.path), "SKILL.save.md");
|
|
9819
|
+
try {
|
|
9820
|
+
return await fsp3.readFile(savePath, "utf8");
|
|
9821
|
+
} catch {
|
|
9822
|
+
const full = await fsp3.readFile(m.path, "utf8");
|
|
9823
|
+
const body = stripFrontmatter(full);
|
|
9824
|
+
const compact = compactSkillBody(body);
|
|
9825
|
+
if (compact) {
|
|
9826
|
+
return `## Overview
|
|
9827
|
+
|
|
9828
|
+
${compact}`;
|
|
9829
|
+
}
|
|
9830
|
+
return body.trim().slice(0, 300);
|
|
9831
|
+
}
|
|
9832
|
+
}
|
|
9649
9833
|
};
|
|
9650
9834
|
function parseFrontmatter(raw) {
|
|
9651
9835
|
if (!raw.startsWith("---")) return {};
|
|
@@ -10726,6 +10910,13 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
10726
10910
|
tokens = this._estimator(ctx);
|
|
10727
10911
|
} else if (msgCount === this._cachedMsgCount && toolCount === this._cachedToolCount && this._cachedTokens >= 0) {
|
|
10728
10912
|
tokens = this._cachedTokens;
|
|
10913
|
+
} else if (this.tryStashedTokens(ctx, msgCount, toolCount) !== null) {
|
|
10914
|
+
const stashed = this.tryStashedTokens(ctx, msgCount, toolCount);
|
|
10915
|
+
const cal = getCalibrationState(`${ctx.provider?.id ?? "unknown"}/${ctx.model}`);
|
|
10916
|
+
tokens = cal.calibrated ? Math.round(stashed * Math.min(1.5, Math.max(0.5, cal.ratio))) : stashed;
|
|
10917
|
+
this._cachedTokens = tokens;
|
|
10918
|
+
this._cachedMsgCount = msgCount;
|
|
10919
|
+
this._cachedToolCount = toolCount;
|
|
10729
10920
|
} else {
|
|
10730
10921
|
tokens = estimateRequestTokensCalibrated(
|
|
10731
10922
|
ctx.messages,
|
|
@@ -10758,6 +10949,25 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
10758
10949
|
return next(ctx);
|
|
10759
10950
|
};
|
|
10760
10951
|
}
|
|
10952
|
+
/**
|
|
10953
|
+
* H1: try to read a pre-computed token total from `ctx.lastRequestTokens`
|
|
10954
|
+
* (set by the agent loop's pre-flight or its restash in emitContextPct).
|
|
10955
|
+
* Returns the uncalibrated total when the stash is valid for the current
|
|
10956
|
+
* context shape (positive number, and the message count it was computed
|
|
10957
|
+
* at matches the current one — otherwise tool results have been appended
|
|
10958
|
+
* since and the value is stale). Returns null when missing or stale so
|
|
10959
|
+
* the caller falls back to a fresh walk.
|
|
10960
|
+
*/
|
|
10961
|
+
tryStashedTokens(ctx, msgCount, toolCount) {
|
|
10962
|
+
const stashed = ctx.lastRequestTokens;
|
|
10963
|
+
if (typeof stashed !== "number" || stashed <= 0) return null;
|
|
10964
|
+
const stashedAt = ctx.meta?.["lastRequestTokensAt"];
|
|
10965
|
+
if (typeof stashedAt !== "object" || stashedAt === null) return null;
|
|
10966
|
+
const meta = stashedAt;
|
|
10967
|
+
if (meta.msgCount !== msgCount) return null;
|
|
10968
|
+
if (typeof meta.toolCount === "number" && meta.toolCount !== toolCount) return null;
|
|
10969
|
+
return stashed;
|
|
10970
|
+
}
|
|
10761
10971
|
/**
|
|
10762
10972
|
* Returns true when the previous compaction at the same or higher pressure
|
|
10763
10973
|
* level reduced nothing and context has not grown materially since. Prevents
|
|
@@ -18665,6 +18875,17 @@ var Director = class _Director {
|
|
|
18665
18875
|
* default cap.
|
|
18666
18876
|
*/
|
|
18667
18877
|
taskCompletedListener = null;
|
|
18878
|
+
/**
|
|
18879
|
+
* Unsub handles for the two `FleetBus.filter()` calls installed in the
|
|
18880
|
+
* constructor for timeout-heartbeat tracking. Without capturing these
|
|
18881
|
+
* and calling them in `shutdown()`, repeated Director construction
|
|
18882
|
+
* (tests, hot reloads, `--director` restarts) accumulates 2 dangling
|
|
18883
|
+
* listeners per Director on the FleetBus, slowly drifting the
|
|
18884
|
+
* EventEmitter past its default cap. Mirrors the rationale on
|
|
18885
|
+
* `taskCompletedListener` above.
|
|
18886
|
+
*/
|
|
18887
|
+
toolExecFilter = null;
|
|
18888
|
+
budgetFilter = null;
|
|
18668
18889
|
/** Optional LLM classifier for smart dispatch. Passed from options. */
|
|
18669
18890
|
dispatchClassifier;
|
|
18670
18891
|
/** Leader agent's current context pressure (full request tokens). */
|
|
@@ -18802,10 +19023,10 @@ var Director = class _Director {
|
|
|
18802
19023
|
const extendCounts = /* @__PURE__ */ new Map();
|
|
18803
19024
|
const progressBySubagent = /* @__PURE__ */ new Map();
|
|
18804
19025
|
const lastTimeoutProgress = /* @__PURE__ */ new Map();
|
|
18805
|
-
this.fleet.filter("tool.executed", (e) => {
|
|
19026
|
+
this.toolExecFilter = this.fleet.filter("tool.executed", (e) => {
|
|
18806
19027
|
progressBySubagent.set(e.subagentId, (progressBySubagent.get(e.subagentId) ?? 0) + 1);
|
|
18807
19028
|
});
|
|
18808
|
-
this.fleet.filter("budget.threshold_reached", (e) => {
|
|
19029
|
+
this.budgetFilter = this.fleet.filter("budget.threshold_reached", (e) => {
|
|
18809
19030
|
const payload = e.payload;
|
|
18810
19031
|
if (e.subagentId.startsWith("bug-hunter-") || e.subagentId.startsWith("refactor-planner-") || e.subagentId.startsWith("critic-")) {
|
|
18811
19032
|
return;
|
|
@@ -19336,6 +19557,14 @@ var Director = class _Director {
|
|
|
19336
19557
|
this.coordinator.off("task.completed", this.taskCompletedListener);
|
|
19337
19558
|
this.taskCompletedListener = null;
|
|
19338
19559
|
}
|
|
19560
|
+
if (this.toolExecFilter) {
|
|
19561
|
+
this.toolExecFilter();
|
|
19562
|
+
this.toolExecFilter = null;
|
|
19563
|
+
}
|
|
19564
|
+
if (this.budgetFilter) {
|
|
19565
|
+
this.budgetFilter();
|
|
19566
|
+
this.budgetFilter = null;
|
|
19567
|
+
}
|
|
19339
19568
|
await this.coordinator.stopAll();
|
|
19340
19569
|
for (const b of this.subagentBridges.values()) {
|
|
19341
19570
|
await b.stop().catch((err) => this.logShutdownError("subagent_bridge_stop", err));
|
|
@@ -28714,15 +28943,15 @@ function createMcpControlTool(opts) {
|
|
|
28714
28943
|
properties: {
|
|
28715
28944
|
action: {
|
|
28716
28945
|
type: "string",
|
|
28717
|
-
enum: ["list", "search", "enable", "disable", "restart"],
|
|
28718
|
-
description: "The management action to perform."
|
|
28946
|
+
enum: ["list", "search", "enable", "disable", "restart", "activate", "deactivate"],
|
|
28947
|
+
description: "The management action to perform. activate/deactivate toggle tool registration ephemerally without disconnecting."
|
|
28719
28948
|
},
|
|
28720
28949
|
/** Filter for `search`. Matches server name or description case-insensitively. */
|
|
28721
28950
|
query: {
|
|
28722
28951
|
type: "string",
|
|
28723
28952
|
description: "Search term for `search` action. Matches server name or description."
|
|
28724
28953
|
},
|
|
28725
|
-
/** Target server name for `enable`, `disable`, `restart`. */
|
|
28954
|
+
/** Target server name for `enable`, `disable`, `restart`, `activate`, `deactivate`. */
|
|
28726
28955
|
server: {
|
|
28727
28956
|
type: "string",
|
|
28728
28957
|
description: 'Server name (e.g. "github", "filesystem", "brave-search").'
|
|
@@ -28732,7 +28961,7 @@ function createMcpControlTool(opts) {
|
|
|
28732
28961
|
};
|
|
28733
28962
|
return {
|
|
28734
28963
|
name: "mcp_control",
|
|
28735
|
-
description: "Manage MCP server lifecycle: list available servers, search by name or capability, enable or disable servers at runtime, restart running servers.",
|
|
28964
|
+
description: "Manage MCP server lifecycle: list available servers, search by name or capability, enable or disable servers at runtime, restart running servers. Use activate/deactivate to ephemerally toggle tool registration without disconnecting \u2014 ideal for token-saving mode where MCP tools are lazy-loaded on demand.",
|
|
28736
28965
|
category: "mcp",
|
|
28737
28966
|
permission: "auto",
|
|
28738
28967
|
mutating: true,
|
|
@@ -28757,8 +28986,12 @@ async function mcpControlDispatch(input, deps) {
|
|
|
28757
28986
|
return server ? runDisable(server, deps) : "`server` is required for disable.";
|
|
28758
28987
|
case "restart":
|
|
28759
28988
|
return server ? runRestart(server, deps) : "`server` is required for restart.";
|
|
28989
|
+
case "activate":
|
|
28990
|
+
return server ? runActivate(server, deps) : "`server` is required for activate.";
|
|
28991
|
+
case "deactivate":
|
|
28992
|
+
return server ? runDeactivate(server, deps) : "`server` is required for deactivate.";
|
|
28760
28993
|
default:
|
|
28761
|
-
return `Unknown action "${action}". Use one of: list, search, enable, disable, restart.`;
|
|
28994
|
+
return `Unknown action "${action}". Use one of: list, search, enable, disable, restart, activate, deactivate.`;
|
|
28762
28995
|
}
|
|
28763
28996
|
}
|
|
28764
28997
|
function renderList(deps) {
|
|
@@ -28883,6 +29116,36 @@ async function runRestart(name, deps) {
|
|
|
28883
29116
|
return `${red("\u2717 Restart failed")} for "${name}": ${err instanceof Error ? err.message : String(err)}`;
|
|
28884
29117
|
}
|
|
28885
29118
|
}
|
|
29119
|
+
async function runActivate(name, deps) {
|
|
29120
|
+
if (!name) return "`server` is required for activate.";
|
|
29121
|
+
if (!deps.registry.activateServer) {
|
|
29122
|
+
return `Registry does not support ephemeral activation. Use \`enable\` to start "${name}" instead.`;
|
|
29123
|
+
}
|
|
29124
|
+
const live = deps.registry.describe().find((s) => s.name === name);
|
|
29125
|
+
if (!live) {
|
|
29126
|
+
return `Server "${name}" is not registered. Use \`mcp_control({ action: "enable", server: "${name}" })\` first.`;
|
|
29127
|
+
}
|
|
29128
|
+
if (live.state !== "connected") {
|
|
29129
|
+
return `Server "${name}" is not connected (state: ${live.state}). Use \`enable\` to start it first.`;
|
|
29130
|
+
}
|
|
29131
|
+
if (deps.registry.isActivated?.(name)) {
|
|
29132
|
+
return `${green("\u25CF")} Server "${name}" tools are already active. Use \`deactivate\` to hide them.`;
|
|
29133
|
+
}
|
|
29134
|
+
deps.registry.activateServer(name);
|
|
29135
|
+
const updated = deps.registry.describe().find((s) => s.name === name);
|
|
29136
|
+
return `${green("\u2713 Activated")} "${name}" \u2014 ${updated?.toolCount ?? 0} tool(s) now registered. Use \`mcp_control({ action: "deactivate", server: "${name}" })\` to hide them when done.`;
|
|
29137
|
+
}
|
|
29138
|
+
async function runDeactivate(name, deps) {
|
|
29139
|
+
if (!name) return "`server` is required for deactivate.";
|
|
29140
|
+
if (!deps.registry.deactivateServer) {
|
|
29141
|
+
return `Registry does not support ephemeral deactivation. Use \`disable\` to stop "${name}" instead.`;
|
|
29142
|
+
}
|
|
29143
|
+
if (!deps.registry.isActivated?.(name)) {
|
|
29144
|
+
return `Server "${name}" tools are not currently active.`;
|
|
29145
|
+
}
|
|
29146
|
+
const count = deps.registry.deactivateServer(name);
|
|
29147
|
+
return `${yellow("\u25CB Deactivated")} "${name}" \u2014 ${count} tool(s) unregistered. Server stays connected.`;
|
|
29148
|
+
}
|
|
28886
29149
|
async function readConfig(p) {
|
|
28887
29150
|
try {
|
|
28888
29151
|
return JSON.parse(await fsp3.readFile(p, "utf8"));
|
|
@@ -28928,6 +29191,70 @@ function badge(state) {
|
|
|
28928
29191
|
}
|
|
28929
29192
|
}
|
|
28930
29193
|
|
|
29194
|
+
// src/tools/mcp-use.ts
|
|
29195
|
+
function createMcpUseTool(opts) {
|
|
29196
|
+
const { registry, toolRegistry } = opts;
|
|
29197
|
+
const inputSchema = {
|
|
29198
|
+
type: "object",
|
|
29199
|
+
properties: {
|
|
29200
|
+
server: {
|
|
29201
|
+
type: "string",
|
|
29202
|
+
description: 'MCP server name (e.g. "github", "filesystem", "brave-search"). Use mcp_control list or search first to discover available servers.'
|
|
29203
|
+
},
|
|
29204
|
+
tool: {
|
|
29205
|
+
type: "string",
|
|
29206
|
+
description: "Tool name on the MCP server to call (without the mcp__server__ prefix \u2014 just the bare tool name)."
|
|
29207
|
+
},
|
|
29208
|
+
input: {
|
|
29209
|
+
type: "object",
|
|
29210
|
+
description: "JSON input to pass to the tool. Use the tool's own input schema \u2014 check with mcp_control describe or the server's documentation.",
|
|
29211
|
+
properties: {},
|
|
29212
|
+
additionalProperties: true
|
|
29213
|
+
}
|
|
29214
|
+
},
|
|
29215
|
+
required: ["server", "tool", "input"]
|
|
29216
|
+
};
|
|
29217
|
+
return {
|
|
29218
|
+
name: "mcp_use",
|
|
29219
|
+
description: "Call an MCP tool on a lazy-loaded server. Activates the server temporarily, calls the tool, returns the result, and deactivates. Use this instead of the manual activate\u2192use\u2192deactivate cycle. First call mcp_control list/search to find the right server and tool name.",
|
|
29220
|
+
category: "mcp",
|
|
29221
|
+
permission: "auto",
|
|
29222
|
+
mutating: true,
|
|
29223
|
+
riskTier: "standard",
|
|
29224
|
+
inputSchema,
|
|
29225
|
+
async execute(raw) {
|
|
29226
|
+
const input = raw;
|
|
29227
|
+
const { server: serverName, tool: toolName, input: toolInput } = input;
|
|
29228
|
+
const servers = registry.describe();
|
|
29229
|
+
const serverInfo = servers.find((s) => s.name === serverName);
|
|
29230
|
+
if (!serverInfo) {
|
|
29231
|
+
return `Server "${serverName}" not found. Available: ${servers.map((s) => s.name).join(", ") || "none"}.`;
|
|
29232
|
+
}
|
|
29233
|
+
if (serverInfo.state !== "connected") {
|
|
29234
|
+
return `Server "${serverName}" is not connected (state: ${serverInfo.state}). Use \`mcp_control({ action: "enable", server: "${serverName}" })\` first.`;
|
|
29235
|
+
}
|
|
29236
|
+
if (registry.activateServer) {
|
|
29237
|
+
registry.activateServer(serverName);
|
|
29238
|
+
}
|
|
29239
|
+
try {
|
|
29240
|
+
const qualifiedName = `mcp__${serverName}__${toolName}`;
|
|
29241
|
+
const mcpTool = toolRegistry.get(qualifiedName);
|
|
29242
|
+
if (!mcpTool) {
|
|
29243
|
+
const allTools = toolRegistry.list().filter((t2) => t2.name.startsWith(`mcp__${serverName}__`)).map((t2) => t2.name.replace(`mcp__${serverName}__`, ""));
|
|
29244
|
+
const hint = allTools.length > 0 ? `Available tools on "${serverName}": ${allTools.join(", ")}.` : `No tools found on "${serverName}". The server may not have published any tools.`;
|
|
29245
|
+
return `Tool "${toolName}" not found on server "${serverName}". ${hint}`;
|
|
29246
|
+
}
|
|
29247
|
+
const result = await mcpTool.execute(toolInput ?? {}, {}, {});
|
|
29248
|
+
return result;
|
|
29249
|
+
} finally {
|
|
29250
|
+
if (registry.deactivateServer) {
|
|
29251
|
+
registry.deactivateServer(serverName);
|
|
29252
|
+
}
|
|
29253
|
+
}
|
|
29254
|
+
}
|
|
29255
|
+
};
|
|
29256
|
+
}
|
|
29257
|
+
|
|
28931
29258
|
// src/extension/registry.ts
|
|
28932
29259
|
var ExtensionRegistry = class {
|
|
28933
29260
|
extensions = [];
|
|
@@ -29154,7 +29481,7 @@ function createAgentToolHandler(a) {
|
|
|
29154
29481
|
a.ctx,
|
|
29155
29482
|
a.perIterationOutputCapBytes
|
|
29156
29483
|
);
|
|
29157
|
-
return { result, durationMs: Date.now() - start };
|
|
29484
|
+
return { result: result.block, durationMs: Date.now() - start };
|
|
29158
29485
|
} catch (err) {
|
|
29159
29486
|
const msg = err instanceof Error ? err.message : String(err);
|
|
29160
29487
|
return {
|
|
@@ -29296,9 +29623,10 @@ function createAgentToolHandler(a) {
|
|
|
29296
29623
|
// src/core/continue-to-next-iteration.ts
|
|
29297
29624
|
function parseContinueDirective(text) {
|
|
29298
29625
|
const LINE_MARKERS = /^\s*\[(continue|next step|proceed|done)\]\s*$/gim;
|
|
29626
|
+
const tail = text.length <= DIRECTIVE_SCAN_WINDOW ? text : text.slice(text.length - DIRECTIVE_SCAN_WINDOW);
|
|
29299
29627
|
let match;
|
|
29300
29628
|
let lastDirective = "none";
|
|
29301
|
-
while ((match = LINE_MARKERS.exec(
|
|
29629
|
+
while ((match = LINE_MARKERS.exec(tail)) !== null) {
|
|
29302
29630
|
const value = (match[1] ?? "").toLowerCase();
|
|
29303
29631
|
if (value === "continue" || value === "next step" || value === "proceed") {
|
|
29304
29632
|
lastDirective = "continue";
|
|
@@ -29308,6 +29636,7 @@ function parseContinueDirective(text) {
|
|
|
29308
29636
|
}
|
|
29309
29637
|
return lastDirective;
|
|
29310
29638
|
}
|
|
29639
|
+
var DIRECTIVE_SCAN_WINDOW = 2048;
|
|
29311
29640
|
var META_KEY = "_autonomousContinue";
|
|
29312
29641
|
function setAutonomousContinue(ctx) {
|
|
29313
29642
|
ctx.meta[META_KEY] = true;
|
|
@@ -29390,21 +29719,22 @@ function createAgentResponseHandler(a) {
|
|
|
29390
29719
|
});
|
|
29391
29720
|
await a.ctx.session.flush();
|
|
29392
29721
|
if (a.ctx.signal.aborted) {
|
|
29393
|
-
|
|
29722
|
+
const parts2 = [];
|
|
29394
29723
|
for (const block of res.content) {
|
|
29395
|
-
if (isTextBlock(block))
|
|
29724
|
+
if (isTextBlock(block)) parts2.push(block.text);
|
|
29396
29725
|
}
|
|
29397
|
-
return { finalText:
|
|
29726
|
+
return { finalText: parts2.join(""), aborted: true, done: false };
|
|
29398
29727
|
}
|
|
29399
|
-
|
|
29728
|
+
const parts = [];
|
|
29400
29729
|
const streamed = a.ctx.provider.capabilities.streaming;
|
|
29401
29730
|
for (const block of res.content) {
|
|
29402
29731
|
if (isTextBlock(block)) {
|
|
29403
29732
|
const rendered = await a.pipelines.assistantOutput.run(block);
|
|
29404
|
-
|
|
29733
|
+
parts.push(rendered.text);
|
|
29405
29734
|
if (!streamed) a.renderer?.write(rendered);
|
|
29406
29735
|
}
|
|
29407
29736
|
}
|
|
29737
|
+
const finalText = parts.join("");
|
|
29408
29738
|
let directive = "none";
|
|
29409
29739
|
if (finalText) {
|
|
29410
29740
|
directive = parseContinueDirective(finalText);
|
|
@@ -29514,7 +29844,9 @@ function normalizeRecipient(to) {
|
|
|
29514
29844
|
|
|
29515
29845
|
// src/coordination/global-mailbox.ts
|
|
29516
29846
|
var MAILBOX_FILE = "_mailbox.jsonl";
|
|
29847
|
+
var CLIENT_REGISTRY_FILE = "_mailbox.clients.json";
|
|
29517
29848
|
var AGENT_STALE_MS = 6e4;
|
|
29849
|
+
var CLIENT_STALE_MS = 6e4;
|
|
29518
29850
|
var HEARTBEAT_THROTTLE_MS = 5e3;
|
|
29519
29851
|
var REGISTRY_CACHE_TTL_MS = 2e3;
|
|
29520
29852
|
var LINE_SEPARATOR = "\n";
|
|
@@ -29526,6 +29858,8 @@ var GlobalMailbox = class {
|
|
|
29526
29858
|
messagePath;
|
|
29527
29859
|
/** Path to the JSON agent registry file. */
|
|
29528
29860
|
registryPath;
|
|
29861
|
+
/** Path to the JSON client registry file. */
|
|
29862
|
+
clientRegistryPath;
|
|
29529
29863
|
/** Optional event bus for emitting agent registration/heartbeat events. */
|
|
29530
29864
|
_events;
|
|
29531
29865
|
/**
|
|
@@ -29537,8 +29871,17 @@ var GlobalMailbox = class {
|
|
|
29537
29871
|
_registryCache = null;
|
|
29538
29872
|
/** When the registry cache was last refreshed from disk (epoch ms). */
|
|
29539
29873
|
_registryCacheAt = 0;
|
|
29874
|
+
/**
|
|
29875
|
+
* Local cache of the client registry to avoid re-reading on every call.
|
|
29876
|
+
* Same reasoning as agent registry cache.
|
|
29877
|
+
*/
|
|
29878
|
+
_clientRegistryCache = null;
|
|
29879
|
+
/** When the client registry cache was last refreshed from disk (epoch ms). */
|
|
29880
|
+
_clientRegistryCacheAt = 0;
|
|
29540
29881
|
/** Last time each local agent sent a heartbeat (throttle). */
|
|
29541
29882
|
_lastHeartbeat = /* @__PURE__ */ new Map();
|
|
29883
|
+
/** Last time each local client sent a heartbeat (throttle). */
|
|
29884
|
+
_lastClientHeartbeat = /* @__PURE__ */ new Map();
|
|
29542
29885
|
/**
|
|
29543
29886
|
* @param projectDir — `~/.wrongstack/projects/<slug>/`
|
|
29544
29887
|
* @param events — optional EventBus for real-time TUI/WebUI notifications
|
|
@@ -29546,6 +29889,7 @@ var GlobalMailbox = class {
|
|
|
29546
29889
|
constructor(projectDir, events) {
|
|
29547
29890
|
this.messagePath = path7.join(projectDir, MAILBOX_FILE);
|
|
29548
29891
|
this.registryPath = path7.join(projectDir, "_mailbox.registry.json");
|
|
29892
|
+
this.clientRegistryPath = path7.join(projectDir, CLIENT_REGISTRY_FILE);
|
|
29549
29893
|
this._events = events;
|
|
29550
29894
|
}
|
|
29551
29895
|
// ── Messages ────────────────────────────────────────────────────────────
|
|
@@ -29727,9 +30071,74 @@ var GlobalMailbox = class {
|
|
|
29727
30071
|
const all = await this.getAgentStatuses();
|
|
29728
30072
|
return all.filter((a) => a.online);
|
|
29729
30073
|
}
|
|
30074
|
+
// ── Client registry ─────────────────────────────────────────────────────
|
|
30075
|
+
async registerClient(input) {
|
|
30076
|
+
await this._ensureClientRegistry();
|
|
30077
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
30078
|
+
const client = {
|
|
30079
|
+
clientId: input.clientId,
|
|
30080
|
+
sessionId: input.sessionId,
|
|
30081
|
+
name: input.name,
|
|
30082
|
+
source: input.source,
|
|
30083
|
+
registeredAt: now,
|
|
30084
|
+
lastSeenAt: now,
|
|
30085
|
+
pid: input.pid
|
|
30086
|
+
};
|
|
30087
|
+
await withFileLock(this.clientRegistryPath, async () => {
|
|
30088
|
+
const registry = await this._readClientRegistry({ fresh: true });
|
|
30089
|
+
this._pruneStaleClientsInPlace(registry);
|
|
30090
|
+
registry.set(input.clientId, client);
|
|
30091
|
+
this._clientRegistryCache = registry;
|
|
30092
|
+
this._clientRegistryCacheAt = Date.now();
|
|
30093
|
+
await this._writeClientRegistry(registry);
|
|
30094
|
+
});
|
|
30095
|
+
this._events?.emitCustom("mailbox.client_registered", {
|
|
30096
|
+
clientId: input.clientId,
|
|
30097
|
+
sessionId: input.sessionId,
|
|
30098
|
+
name: input.name,
|
|
30099
|
+
source: input.source
|
|
30100
|
+
});
|
|
30101
|
+
}
|
|
30102
|
+
async clientHeartbeat(input) {
|
|
30103
|
+
const last = this._lastClientHeartbeat.get(input.clientId) ?? 0;
|
|
30104
|
+
const now = Date.now();
|
|
30105
|
+
if (now - last < HEARTBEAT_THROTTLE_MS) return;
|
|
30106
|
+
this._lastClientHeartbeat.set(input.clientId, now);
|
|
30107
|
+
await this._ensureClientRegistry();
|
|
30108
|
+
await withFileLock(this.clientRegistryPath, async () => {
|
|
30109
|
+
const registry = await this._readClientRegistry({ fresh: true });
|
|
30110
|
+
this._pruneStaleClientsInPlace(registry);
|
|
30111
|
+
const client = registry.get(input.clientId);
|
|
30112
|
+
if (client) {
|
|
30113
|
+
client.lastSeenAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
30114
|
+
}
|
|
30115
|
+
this._clientRegistryCache = registry;
|
|
30116
|
+
this._clientRegistryCacheAt = Date.now();
|
|
30117
|
+
await this._writeClientRegistry(registry);
|
|
30118
|
+
});
|
|
30119
|
+
this._events?.emitCustom("mailbox.client_heartbeat", {
|
|
30120
|
+
clientId: input.clientId
|
|
30121
|
+
});
|
|
30122
|
+
}
|
|
30123
|
+
async getClientStatuses() {
|
|
30124
|
+
await this._ensureClientRegistry();
|
|
30125
|
+
const registry = await this._readClientRegistry();
|
|
30126
|
+
this._pruneStaleClientsInPlace(registry);
|
|
30127
|
+
const now = Date.now();
|
|
30128
|
+
return Array.from(registry.values()).map((c) => ({
|
|
30129
|
+
clientId: c.clientId,
|
|
30130
|
+
name: c.name,
|
|
30131
|
+
source: c.source,
|
|
30132
|
+
sessionId: c.sessionId,
|
|
30133
|
+
lastSeenAt: c.lastSeenAt,
|
|
30134
|
+
online: now - new Date(c.lastSeenAt).getTime() < CLIENT_STALE_MS,
|
|
30135
|
+
pid: c.pid
|
|
30136
|
+
})).sort((a, b) => b.lastSeenAt.localeCompare(a.lastSeenAt));
|
|
30137
|
+
}
|
|
29730
30138
|
// ── Lifecycle ───────────────────────────────────────────────────────────
|
|
29731
30139
|
async close() {
|
|
29732
30140
|
this._registryCache = null;
|
|
30141
|
+
this._clientRegistryCache = null;
|
|
29733
30142
|
}
|
|
29734
30143
|
async clearAll() {
|
|
29735
30144
|
await withFileLock(this.messagePath, async () => {
|
|
@@ -29808,6 +30217,51 @@ var GlobalMailbox = class {
|
|
|
29808
30217
|
await fsp3.writeFile(tmp, JSON.stringify(obj, null, 2), "utf8");
|
|
29809
30218
|
await fsp3.rename(tmp, this.registryPath);
|
|
29810
30219
|
}
|
|
30220
|
+
// ── Client registry internals ───────────────────────────────────────────
|
|
30221
|
+
async _ensureClientRegistry() {
|
|
30222
|
+
await fsp3.mkdir(path7.dirname(this.clientRegistryPath), { recursive: true });
|
|
30223
|
+
}
|
|
30224
|
+
async _readClientRegistry(opts) {
|
|
30225
|
+
if (!opts?.fresh && this._clientRegistryCache && Date.now() - this._clientRegistryCacheAt < REGISTRY_CACHE_TTL_MS) {
|
|
30226
|
+
return new Map(this._clientRegistryCache);
|
|
30227
|
+
}
|
|
30228
|
+
try {
|
|
30229
|
+
const raw = await fsp3.readFile(this.clientRegistryPath, "utf8");
|
|
30230
|
+
const data = JSON.parse(raw);
|
|
30231
|
+
const map = /* @__PURE__ */ new Map();
|
|
30232
|
+
for (const [id, client] of Object.entries(data)) {
|
|
30233
|
+
map.set(id, client);
|
|
30234
|
+
}
|
|
30235
|
+
this._clientRegistryCache = map;
|
|
30236
|
+
this._clientRegistryCacheAt = Date.now();
|
|
30237
|
+
return new Map(map);
|
|
30238
|
+
} catch (err) {
|
|
30239
|
+
if (err.code === "ENOENT") {
|
|
30240
|
+
const empty = /* @__PURE__ */ new Map();
|
|
30241
|
+
this._clientRegistryCache = empty;
|
|
30242
|
+
this._clientRegistryCacheAt = Date.now();
|
|
30243
|
+
return empty;
|
|
30244
|
+
}
|
|
30245
|
+
throw err;
|
|
30246
|
+
}
|
|
30247
|
+
}
|
|
30248
|
+
_pruneStaleClientsInPlace(registry) {
|
|
30249
|
+
const cutoff = Date.now() - CLIENT_STALE_MS;
|
|
30250
|
+
for (const client of registry.values()) {
|
|
30251
|
+
if (new Date(client.lastSeenAt).getTime() < cutoff) {
|
|
30252
|
+
client.lastSeenAt = new Date(cutoff).toISOString();
|
|
30253
|
+
}
|
|
30254
|
+
}
|
|
30255
|
+
}
|
|
30256
|
+
async _writeClientRegistry(registry) {
|
|
30257
|
+
const obj = {};
|
|
30258
|
+
for (const [id, client] of registry) {
|
|
30259
|
+
obj[id] = client;
|
|
30260
|
+
}
|
|
30261
|
+
const tmp = `${this.clientRegistryPath}.${randomUUID().slice(0, 8)}.tmp`;
|
|
30262
|
+
await fsp3.writeFile(tmp, JSON.stringify(obj, null, 2), "utf8");
|
|
30263
|
+
await fsp3.rename(tmp, this.clientRegistryPath);
|
|
30264
|
+
}
|
|
29811
30265
|
};
|
|
29812
30266
|
function defaultResolveProjectDir(ctx) {
|
|
29813
30267
|
return resolveProjectDir(ctx.projectRoot, wstackGlobalRoot());
|
|
@@ -30298,7 +30752,16 @@ function signalAbortReason(signal) {
|
|
|
30298
30752
|
function createAgentLoopHandler(a, handlers) {
|
|
30299
30753
|
const checkMailbox = attachMailboxChecker(a);
|
|
30300
30754
|
async function compactContextIfNeeded() {
|
|
30755
|
+
const msgCount = a.ctx.messages.length;
|
|
30756
|
+
if (_lastCompactionMsgCount === msgCount && _lastCompactionWasNoop && _maxContext > 0) {
|
|
30757
|
+
return;
|
|
30758
|
+
}
|
|
30301
30759
|
await a.pipelines.contextWindow.run(a.ctx);
|
|
30760
|
+
_lastCompactionMsgCount = msgCount;
|
|
30761
|
+
const stashed = a.ctx.lastRequestTokens;
|
|
30762
|
+
const tokens = typeof stashed === "number" && stashed > 0 ? stashed : 0;
|
|
30763
|
+
const load = _maxContext > 0 ? tokens / _maxContext : 0;
|
|
30764
|
+
_lastCompactionWasNoop = tokens > 0 && load < 0.5;
|
|
30302
30765
|
}
|
|
30303
30766
|
const calibrationKey = (model = a.ctx.model) => `${a.ctx.provider?.id ?? "unknown"}/${model}`;
|
|
30304
30767
|
function emitContextPct() {
|
|
@@ -30309,22 +30772,42 @@ function createAgentLoopHandler(a, handlers) {
|
|
|
30309
30772
|
}
|
|
30310
30773
|
_lastEmittedMsgCount = msgCount;
|
|
30311
30774
|
_lastEmittedToolCount = toolCount;
|
|
30775
|
+
if (msgCount !== _lastPreFlightMsgCount) {
|
|
30776
|
+
a.ctx.lastRequestTokens = estimateRequestTokens(
|
|
30777
|
+
a.ctx.messages,
|
|
30778
|
+
a.ctx.systemPrompt,
|
|
30779
|
+
a.ctx.tools ?? []
|
|
30780
|
+
).total;
|
|
30781
|
+
_lastPreFlightMsgCount = msgCount;
|
|
30782
|
+
a.ctx.meta["lastRequestTokensAt"] = { msgCount, toolCount };
|
|
30783
|
+
}
|
|
30312
30784
|
if (!_maxContext) {
|
|
30313
30785
|
const metaLimit = a.ctx.meta?.["effectiveMaxContext"];
|
|
30314
30786
|
const providerMax = a.ctx.provider.capabilities.maxContext;
|
|
30315
30787
|
_maxContext = typeof metaLimit === "number" && metaLimit > 0 ? metaLimit : typeof providerMax === "number" && providerMax > 0 ? providerMax : 2e5;
|
|
30316
30788
|
}
|
|
30317
|
-
|
|
30318
|
-
|
|
30319
|
-
|
|
30320
|
-
|
|
30321
|
-
|
|
30322
|
-
|
|
30789
|
+
let total;
|
|
30790
|
+
const stashed = a.ctx.lastRequestTokens;
|
|
30791
|
+
if (typeof stashed === "number" && stashed > 0) {
|
|
30792
|
+
const cal = getCalibrationState(calibrationKey());
|
|
30793
|
+
total = cal.calibrated ? Math.round(stashed * Math.min(1.5, Math.max(0.5, cal.ratio))) : stashed;
|
|
30794
|
+
} else {
|
|
30795
|
+
const est = estimateRequestTokensCalibrated(
|
|
30796
|
+
a.ctx.messages,
|
|
30797
|
+
a.ctx.systemPrompt,
|
|
30798
|
+
a.ctx.tools ?? [],
|
|
30799
|
+
calibrationKey()
|
|
30800
|
+
);
|
|
30801
|
+
total = est.total;
|
|
30802
|
+
}
|
|
30323
30803
|
a.events.emit("ctx.pct", { load: total / _maxContext, tokens: total, maxContext: _maxContext });
|
|
30324
30804
|
}
|
|
30325
30805
|
let _maxContext = 0;
|
|
30326
30806
|
let _lastEmittedMsgCount = -1;
|
|
30327
30807
|
let _lastEmittedToolCount = -1;
|
|
30808
|
+
let _lastPreFlightMsgCount = -1;
|
|
30809
|
+
let _lastCompactionMsgCount = -1;
|
|
30810
|
+
let _lastCompactionWasNoop = false;
|
|
30328
30811
|
function foldBlockIntoConversation(block) {
|
|
30329
30812
|
const messages = a.ctx.messages;
|
|
30330
30813
|
const last = messages[messages.length - 1];
|
|
@@ -30442,6 +30925,12 @@ function createAgentLoopHandler(a, handlers) {
|
|
|
30442
30925
|
});
|
|
30443
30926
|
const req = await handlers.response.buildAndRunRequestPipeline(opts);
|
|
30444
30927
|
const preFlight = estimateRequestTokens(req.messages, req.system, req.tools ?? []);
|
|
30928
|
+
a.ctx.lastRequestTokens = preFlight.total;
|
|
30929
|
+
_lastPreFlightMsgCount = req.messages.length;
|
|
30930
|
+
a.ctx.meta["lastRequestTokensAt"] = {
|
|
30931
|
+
msgCount: req.messages.length,
|
|
30932
|
+
toolCount: (req.tools ?? []).length
|
|
30933
|
+
};
|
|
30445
30934
|
await a.ctx.session.append({
|
|
30446
30935
|
type: "llm_request",
|
|
30447
30936
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -31137,6 +31626,10 @@ function flagsToConfigPatch(flags) {
|
|
|
31137
31626
|
skills: false
|
|
31138
31627
|
};
|
|
31139
31628
|
}
|
|
31629
|
+
if (flags["token-saving-mode"]) {
|
|
31630
|
+
patch.features ??= {};
|
|
31631
|
+
patch.features.tokenSavingMode = true;
|
|
31632
|
+
}
|
|
31140
31633
|
return patch;
|
|
31141
31634
|
}
|
|
31142
31635
|
async function writeProjectMeta(paths, projectRoot) {
|
|
@@ -31438,14 +31931,15 @@ Never silently skip a failure \u2014 always report it, even when you choose not
|
|
|
31438
31931
|
## After-task suggestions
|
|
31439
31932
|
|
|
31440
31933
|
After completing a significant task, end your response with 2\u20134 suggested next
|
|
31441
|
-
actions
|
|
31934
|
+
actions in a \`<next_steps>\` block. Use this exact format so the user can
|
|
31442
31935
|
select them with \`/next 1\`, \`/next 2\`, or \`/next 1 2 3\`:
|
|
31443
31936
|
|
|
31444
31937
|
\`\`\`
|
|
31445
|
-
|
|
31938
|
+
<next_steps>
|
|
31446
31939
|
1. First suggestion \u2014 imperative, specific, actionable
|
|
31447
31940
|
2. Second suggestion
|
|
31448
31941
|
3. Third suggestion
|
|
31942
|
+
</next_steps>
|
|
31449
31943
|
\`\`\`
|
|
31450
31944
|
|
|
31451
31945
|
Rules:
|
|
@@ -31483,6 +31977,10 @@ var DefaultSystemPromptBuilder = class {
|
|
|
31483
31977
|
skillBodyCache;
|
|
31484
31978
|
/** Tools from last build — used for memory relevance scoring. */
|
|
31485
31979
|
_lastBuildTools;
|
|
31980
|
+
/** Cached rendered online agents string, keyed by array reference. */
|
|
31981
|
+
_lastOnlineAgents;
|
|
31982
|
+
/** Cached full buildToolUsage output — keyed by tools array + online agents refs. */
|
|
31983
|
+
_toolsUsageCache;
|
|
31486
31984
|
async build(ctx) {
|
|
31487
31985
|
this._lastBuildTools = ctx.tools;
|
|
31488
31986
|
if (this.opts.skillLoader && !this.skillCache) {
|
|
@@ -31618,6 +32116,9 @@ var DefaultSystemPromptBuilder = class {
|
|
|
31618
32116
|
}
|
|
31619
32117
|
buildToolUsage(tools, ctx) {
|
|
31620
32118
|
if (tools.length === 0) return "## Tool usage\n\nNo tools registered.";
|
|
32119
|
+
if (this._toolsUsageCache?.toolsRef === tools && this._toolsUsageCache?.agentsRef === ctx.onlineAgents) {
|
|
32120
|
+
return this._toolsUsageCache.text;
|
|
32121
|
+
}
|
|
31621
32122
|
const byCat = /* @__PURE__ */ new Map();
|
|
31622
32123
|
const uncategorized = [];
|
|
31623
32124
|
for (const t2 of tools) {
|
|
@@ -31638,7 +32139,7 @@ var DefaultSystemPromptBuilder = class {
|
|
|
31638
32139
|
### ${cat}`);
|
|
31639
32140
|
for (const t2 of catTools) {
|
|
31640
32141
|
const hint = t2.usageHint ?? t2.description;
|
|
31641
|
-
const desc = hint.length > 80 ? `${hint.slice(0, 77)}...` : hint.trim();
|
|
32142
|
+
const desc = this.opts.tokenSavingMode ? hint.length > 60 ? hint.slice(0, hint.indexOf(".", 20) + 1 || 60) + (hint.length > 60 ? "\u2026" : "") : hint.trim() : hint.length > 80 ? `${hint.slice(0, 77)}...` : hint.trim();
|
|
31642
32143
|
lines.push(`- **${t2.name}** \u2014 ${desc}`);
|
|
31643
32144
|
}
|
|
31644
32145
|
}
|
|
@@ -31651,7 +32152,8 @@ var DefaultSystemPromptBuilder = class {
|
|
|
31651
32152
|
${hint.trim()}`);
|
|
31652
32153
|
}
|
|
31653
32154
|
}
|
|
31654
|
-
|
|
32155
|
+
if (!this.opts.tokenSavingMode) {
|
|
32156
|
+
lines.push(`
|
|
31655
32157
|
## Common patterns
|
|
31656
32158
|
|
|
31657
32159
|
- **Inspect before edit:** \`read\`/\`glob\`/\`grep\` \u2192 locate target \u2192 \`edit\`
|
|
@@ -31661,6 +32163,7 @@ ${hint.trim()}`);
|
|
|
31661
32163
|
- **Batch ops:** Use \`replace\` with glob patterns for multi-file surgical changes
|
|
31662
32164
|
|
|
31663
32165
|
When unsure about a file's current state, read it first rather than assuming.`);
|
|
32166
|
+
}
|
|
31664
32167
|
const hasDelegate = tools.some((t2) => t2.name === "delegate");
|
|
31665
32168
|
if (hasDelegate) {
|
|
31666
32169
|
const delegateTool = tools.find((t2) => t2.name === "delegate");
|
|
@@ -31669,7 +32172,12 @@ When unsure about a file's current state, read it first rather than assuming.`);
|
|
|
31669
32172
|
return Array.isArray(role) ? role.filter((r) => typeof r === "string") : [];
|
|
31670
32173
|
})();
|
|
31671
32174
|
const roleList = enumValues.length > 0 ? enumValues.join(", ") : "(no roster configured)";
|
|
31672
|
-
|
|
32175
|
+
if (this.opts.tokenSavingMode) {
|
|
32176
|
+
lines.push(`## Delegation
|
|
32177
|
+
|
|
32178
|
+
Use \`delegate\` to hand work to a subagent (roles: ${roleList}).`);
|
|
32179
|
+
} else {
|
|
32180
|
+
lines.push(`
|
|
31673
32181
|
## Delegation
|
|
31674
32182
|
|
|
31675
32183
|
You have a \`delegate\` tool that hands a discrete piece of work to a
|
|
@@ -31732,21 +32240,20 @@ it's called \u2014 you do not need to call any setup tool. For fine-grained
|
|
|
31732
32240
|
control over a long-running fleet (spawn N workers, hand them tasks
|
|
31733
32241
|
one by one, roll up results), use \`spawn_subagent\` + \`assign_task\` +
|
|
31734
32242
|
\`await_tasks\` directly; \`delegate\` is the one-call shortcut.`);
|
|
32243
|
+
}
|
|
31735
32244
|
}
|
|
31736
32245
|
const hasMailbox = tools.some(
|
|
31737
32246
|
(t2) => t2.name === "mailbox" || t2.name === "mail_send" || t2.name === "mail_inbox"
|
|
31738
32247
|
);
|
|
31739
32248
|
if (hasMailbox) {
|
|
31740
|
-
|
|
31741
|
-
if (
|
|
31742
|
-
|
|
31743
|
-
|
|
31744
|
-
onlineAgentsInfo = `
|
|
32249
|
+
const onlineAgentsInfo = this.renderOnlineAgents(ctx.onlineAgents);
|
|
32250
|
+
if (this.opts.tokenSavingMode) {
|
|
32251
|
+
lines.push(`
|
|
32252
|
+
## Inter-agent mailbox${onlineAgentsInfo}
|
|
31745
32253
|
|
|
31746
|
-
|
|
31747
|
-
|
|
31748
|
-
|
|
31749
|
-
lines.push(`
|
|
32254
|
+
Use \`mail_inbox\` for new messages, \`mail_send\` to communicate with other agents.`);
|
|
32255
|
+
} else {
|
|
32256
|
+
lines.push(`
|
|
31750
32257
|
## Inter-agent mailbox${onlineAgentsInfo}
|
|
31751
32258
|
|
|
31752
32259
|
You share a persistent project mailbox with every other agent working on
|
|
@@ -31805,9 +32312,52 @@ inline, the rest as a summary. To catch up explicitly:
|
|
|
31805
32312
|
|
|
31806
32313
|
- \`mailbox action=ack messageId=<id> completed=true outcome="What you did"\`
|
|
31807
32314
|
- Messages you \`check\` are auto-marked as read; use \`ack\` to mark complete.`);
|
|
32315
|
+
}
|
|
32316
|
+
}
|
|
32317
|
+
const hasMcpControl = tools.some((t2) => t2.name === "mcp_control");
|
|
32318
|
+
const hasMcpUse = tools.some((t2) => t2.name === "mcp_use");
|
|
32319
|
+
if (hasMcpControl && this.opts.tokenSavingMode) {
|
|
32320
|
+
if (hasMcpUse) {
|
|
32321
|
+
lines.push(`
|
|
32322
|
+
## MCP tools (lazy-loaded)
|
|
32323
|
+
|
|
32324
|
+
MCP server tools are NOT registered by default in token-saving mode to keep
|
|
32325
|
+
the prompt compact. Each server's process is running in the background; only
|
|
32326
|
+
tool registration is deferred.
|
|
32327
|
+
|
|
32328
|
+
**Preferred approach** \u2014 one-shot meta-tool:
|
|
32329
|
+
\`mcp_use({ server: "<name>", tool: "<bare-tool>", input: { ... } })\`
|
|
32330
|
+
This activates the server, calls the tool, returns the result, and
|
|
32331
|
+
deactivates \u2014 all in one call. No need to track activate/deactivate state.
|
|
32332
|
+
|
|
32333
|
+
**Manual approach** (for exploration):
|
|
32334
|
+
1. \`mcp_control({ action: "list" })\` \u2014 see which servers are connected
|
|
32335
|
+
2. \`mcp_control({ action: "activate", server: "<name>" })\` \u2014 register tools
|
|
32336
|
+
3. Use the tools normally
|
|
32337
|
+
4. \`mcp_control({ action: "deactivate", server: "<name>" })\` \u2014 clean up
|
|
32338
|
+
|
|
32339
|
+
Activation/deactivation is ephemeral (no config writes) and does NOT affect
|
|
32340
|
+
the server connection \u2014 only tool visibility changes.`);
|
|
32341
|
+
} else {
|
|
32342
|
+
lines.push(`
|
|
32343
|
+
## MCP tools (lazy-loaded)
|
|
32344
|
+
|
|
32345
|
+
MCP server tools are NOT registered by default in token-saving mode to keep
|
|
32346
|
+
the prompt compact. Each server's process is running in the background; only
|
|
32347
|
+
tool registration is deferred.
|
|
32348
|
+
|
|
32349
|
+
When you need a specific MCP server's tools:
|
|
32350
|
+
1. \`mcp_control({ action: "list" })\` \u2014 see which servers are connected
|
|
32351
|
+
2. \`mcp_control({ action: "activate", server: "<name>" })\` \u2014 register its tools
|
|
32352
|
+
3. Use the tools as needed
|
|
32353
|
+
4. \`mcp_control({ action: "deactivate", server: "<name>" })\` \u2014 unregister when done
|
|
32354
|
+
|
|
32355
|
+
Activation/deactivation is ephemeral (no config writes) and does NOT affect
|
|
32356
|
+
the server connection \u2014 only tool visibility changes.`);
|
|
32357
|
+
}
|
|
31808
32358
|
}
|
|
31809
32359
|
const hasContextManager = tools.some((t2) => t2.name === "context_manager");
|
|
31810
|
-
if (hasContextManager) {
|
|
32360
|
+
if (hasContextManager && !this.opts.tokenSavingMode) {
|
|
31811
32361
|
const maxCtx = this.opts.modelCapabilities?.maxContextTokens ?? 128e3;
|
|
31812
32362
|
const threshold = maxCtx <= 32e3 ? "50" : "70";
|
|
31813
32363
|
lines.push(`
|
|
@@ -31824,7 +32374,32 @@ use the context_manager tool proactively \u2014 do NOT wait to be told:
|
|
|
31824
32374
|
**Never** stuff redundant information into a tool result. If you summarize a file, do not paste its full content \u2014
|
|
31825
32375
|
summarize it, and let the tool result hold only the summary.`);
|
|
31826
32376
|
}
|
|
31827
|
-
|
|
32377
|
+
const text = lines.join("\n");
|
|
32378
|
+
this._toolsUsageCache = { toolsRef: tools, agentsRef: ctx.onlineAgents, text };
|
|
32379
|
+
return text;
|
|
32380
|
+
}
|
|
32381
|
+
/**
|
|
32382
|
+
* Render the online agents list, cached by array reference. The agents
|
|
32383
|
+
* list changes at join/leave pace (seconds to minutes), not every prompt
|
|
32384
|
+
* build turn (hundreds of ms). Reference equality avoids re-stringifying
|
|
32385
|
+
* the same array on every iteration while still being correct when the
|
|
32386
|
+
* caller passes a fresh array.
|
|
32387
|
+
*/
|
|
32388
|
+
renderOnlineAgents(agents) {
|
|
32389
|
+
if (!agents || agents.length === 0) return "";
|
|
32390
|
+
if (this._lastOnlineAgents?.ref === agents) {
|
|
32391
|
+
return this._lastOnlineAgents.text;
|
|
32392
|
+
}
|
|
32393
|
+
const totalCount = agents.length;
|
|
32394
|
+
const agentList = agents.map(
|
|
32395
|
+
(a) => `- **${a.name}** (${a.source ?? "unknown"}${a.sessionId ? `, session: ${a.sessionId.slice(0, 8)}` : ""})`
|
|
32396
|
+
).join("\n");
|
|
32397
|
+
const text = `
|
|
32398
|
+
|
|
32399
|
+
**Currently online (${totalCount} agent${totalCount !== 1 ? "s" : ""}):**
|
|
32400
|
+
${agentList}`;
|
|
32401
|
+
this._lastOnlineAgents = { ref: agents, text };
|
|
32402
|
+
return text;
|
|
31828
32403
|
}
|
|
31829
32404
|
async buildEnvironment(ctx) {
|
|
31830
32405
|
const cached = this.envCacheByRoot.get(ctx.projectRoot);
|
|
@@ -31867,7 +32442,7 @@ summarize it, and let the tool result hold only the summary.`);
|
|
|
31867
32442
|
"## Skills in scope for this session",
|
|
31868
32443
|
this.skillCache,
|
|
31869
32444
|
"",
|
|
31870
|
-
"Full skill instructions are injected in the Active Skills block below."
|
|
32445
|
+
this.opts.tokenSavingMode ? "Compact skill instructions are injected in the Active Skills block below (Overview + Rules only)." : "Full skill instructions are injected in the Active Skills block below."
|
|
31871
32446
|
);
|
|
31872
32447
|
}
|
|
31873
32448
|
const text = lines.join("\n");
|
|
@@ -31906,41 +32481,83 @@ ${mem}`);
|
|
|
31906
32481
|
} catch {
|
|
31907
32482
|
}
|
|
31908
32483
|
}
|
|
31909
|
-
if (this.opts.skillLoader
|
|
31910
|
-
|
|
31911
|
-
|
|
31912
|
-
|
|
31913
|
-
|
|
31914
|
-
|
|
31915
|
-
|
|
31916
|
-
|
|
31917
|
-
|
|
31918
|
-
|
|
31919
|
-
|
|
32484
|
+
if (this.opts.skillLoader) {
|
|
32485
|
+
if (this.opts.tokenSavingMode) {
|
|
32486
|
+
if (this.skillBodyCache === void 0) {
|
|
32487
|
+
await this.buildCompactSkillBodies();
|
|
32488
|
+
}
|
|
32489
|
+
} else {
|
|
32490
|
+
if (this.skillBodyCache === void 0) {
|
|
32491
|
+
await this.buildFullSkillBodies();
|
|
32492
|
+
}
|
|
32493
|
+
}
|
|
32494
|
+
}
|
|
32495
|
+
if (this.skillBodyCache) {
|
|
32496
|
+
parts.push(`# Active Skills
|
|
32497
|
+
|
|
32498
|
+
${this.skillBodyCache}`);
|
|
32499
|
+
}
|
|
32500
|
+
return parts.join("\n\n");
|
|
32501
|
+
}
|
|
32502
|
+
/** Build full skill bodies (token-saving OFF). */
|
|
32503
|
+
async buildFullSkillBodies() {
|
|
32504
|
+
try {
|
|
32505
|
+
const skills = await this.opts.skillLoader.list();
|
|
32506
|
+
if (skills.length > 0) {
|
|
32507
|
+
const bodies = [];
|
|
32508
|
+
for (const s of skills) {
|
|
32509
|
+
try {
|
|
32510
|
+
const raw = await this.opts.skillLoader.readBody(s.name);
|
|
32511
|
+
const body = stripFrontmatter2(raw);
|
|
32512
|
+
if (body.trim()) {
|
|
32513
|
+
bodies.push(`## Skill: ${s.name}
|
|
31920
32514
|
|
|
31921
32515
|
${body.trim()}`);
|
|
31922
|
-
}
|
|
31923
|
-
} catch {
|
|
31924
32516
|
}
|
|
32517
|
+
} catch {
|
|
31925
32518
|
}
|
|
31926
|
-
if (bodies.length > 0) {
|
|
31927
|
-
this.skillBodyCache = bodies.join("\n\n---\n\n");
|
|
31928
|
-
} else {
|
|
31929
|
-
this.skillBodyCache = "";
|
|
31930
|
-
}
|
|
31931
|
-
} else {
|
|
31932
|
-
this.skillBodyCache = "";
|
|
31933
32519
|
}
|
|
31934
|
-
|
|
32520
|
+
this.skillBodyCache = bodies.length > 0 ? bodies.join("\n\n---\n\n") : "";
|
|
32521
|
+
} else {
|
|
31935
32522
|
this.skillBodyCache = "";
|
|
31936
32523
|
}
|
|
32524
|
+
} catch {
|
|
32525
|
+
this.skillBodyCache = "";
|
|
31937
32526
|
}
|
|
31938
|
-
|
|
31939
|
-
|
|
32527
|
+
}
|
|
32528
|
+
/**
|
|
32529
|
+
* Build compact skill bodies for token-saving mode.
|
|
32530
|
+
* Uses `readSaveBody` from the skill loader which tries `SKILL.save.md`
|
|
32531
|
+
* first, then falls back to auto-compaction.
|
|
32532
|
+
*/
|
|
32533
|
+
async buildCompactSkillBodies() {
|
|
32534
|
+
if (!this.opts.skillLoader) {
|
|
32535
|
+
this.skillBodyCache = "";
|
|
32536
|
+
return;
|
|
32537
|
+
}
|
|
32538
|
+
try {
|
|
32539
|
+
const skills = await this.opts.skillLoader.list();
|
|
32540
|
+
if (skills.length > 0) {
|
|
32541
|
+
const bodies = [];
|
|
32542
|
+
for (const s of skills) {
|
|
32543
|
+
try {
|
|
32544
|
+
const saveBody = await this.opts.skillLoader.readSaveBody(s.name);
|
|
32545
|
+
const clean = stripFrontmatter2(saveBody);
|
|
32546
|
+
if (clean.trim()) {
|
|
32547
|
+
bodies.push(`## Skill: ${s.name}
|
|
31940
32548
|
|
|
31941
|
-
${
|
|
32549
|
+
${clean.trim()}`);
|
|
32550
|
+
}
|
|
32551
|
+
} catch {
|
|
32552
|
+
}
|
|
32553
|
+
}
|
|
32554
|
+
this.skillBodyCache = bodies.length > 0 ? bodies.join("\n\n---\n\n") : "";
|
|
32555
|
+
} else {
|
|
32556
|
+
this.skillBodyCache = "";
|
|
32557
|
+
}
|
|
32558
|
+
} catch {
|
|
32559
|
+
this.skillBodyCache = "";
|
|
31942
32560
|
}
|
|
31943
|
-
return parts.join("\n\n");
|
|
31944
32561
|
}
|
|
31945
32562
|
async buildMode() {
|
|
31946
32563
|
if (this.opts.modePrompt) return this.opts.modePrompt;
|
|
@@ -32030,7 +32647,7 @@ ${this.skillBodyCache}`);
|
|
|
32030
32647
|
return langs.size === 0 ? "unknown" : Array.from(langs).join(", ");
|
|
32031
32648
|
}
|
|
32032
32649
|
};
|
|
32033
|
-
function
|
|
32650
|
+
function stripFrontmatter2(raw) {
|
|
32034
32651
|
if (!raw.startsWith("---")) return raw;
|
|
32035
32652
|
const end = raw.indexOf("\n---", 4);
|
|
32036
32653
|
if (end === -1) return raw;
|
|
@@ -32050,6 +32667,11 @@ function compactTrigger(trigger) {
|
|
|
32050
32667
|
// src/registry/tool-registry.ts
|
|
32051
32668
|
var ToolRegistry = class _ToolRegistry {
|
|
32052
32669
|
tools = /* @__PURE__ */ new Map();
|
|
32670
|
+
/** Monotonic version bumped on every registry mutation. */
|
|
32671
|
+
_version = 0;
|
|
32672
|
+
/** Cached `list()` result, frozen after build. Invalidated on _version change. */
|
|
32673
|
+
_listSnapshot;
|
|
32674
|
+
_listSnapshotVersion = -1;
|
|
32053
32675
|
/** Pre-compute tool definition token estimate once at registration time. */
|
|
32054
32676
|
_stampDefTokens(tool) {
|
|
32055
32677
|
if (tool._estDefTokens === void 0) {
|
|
@@ -32075,6 +32697,7 @@ var ToolRegistry = class _ToolRegistry {
|
|
|
32075
32697
|
}
|
|
32076
32698
|
this._stampDefTokens(tool);
|
|
32077
32699
|
this.tools.set(tool.name, { tool, owner });
|
|
32700
|
+
this._version++;
|
|
32078
32701
|
}
|
|
32079
32702
|
/**
|
|
32080
32703
|
* Attempt to register a tool. Returns true if successful, false if a tool
|
|
@@ -32088,6 +32711,7 @@ var ToolRegistry = class _ToolRegistry {
|
|
|
32088
32711
|
}
|
|
32089
32712
|
this._stampDefTokens(tool);
|
|
32090
32713
|
this.tools.set(tool.name, { tool, owner });
|
|
32714
|
+
this._version++;
|
|
32091
32715
|
return true;
|
|
32092
32716
|
}
|
|
32093
32717
|
/**
|
|
@@ -32159,6 +32783,7 @@ var ToolRegistry = class _ToolRegistry {
|
|
|
32159
32783
|
wrapped._estDefTokens = void 0;
|
|
32160
32784
|
this._stampDefTokens(wrapped);
|
|
32161
32785
|
this.tools.set(name, { tool: wrapped, owner: `${entry.owner}+${owner}` });
|
|
32786
|
+
this._version++;
|
|
32162
32787
|
}
|
|
32163
32788
|
get(name) {
|
|
32164
32789
|
return this.tools.get(name)?.tool;
|
|
@@ -32167,7 +32792,13 @@ var ToolRegistry = class _ToolRegistry {
|
|
|
32167
32792
|
return this.tools.get(name)?.owner;
|
|
32168
32793
|
}
|
|
32169
32794
|
list() {
|
|
32170
|
-
|
|
32795
|
+
if (this._listSnapshot && this._version === this._listSnapshotVersion) {
|
|
32796
|
+
return this._listSnapshot;
|
|
32797
|
+
}
|
|
32798
|
+
const arr = Array.from(this.tools.values()).map((e) => e.tool);
|
|
32799
|
+
this._listSnapshot = arr;
|
|
32800
|
+
this._listSnapshotVersion = this._version;
|
|
32801
|
+
return arr;
|
|
32171
32802
|
}
|
|
32172
32803
|
/**
|
|
32173
32804
|
* Group tools by their `category` field. Tools without a category
|
|
@@ -32415,14 +33046,19 @@ var DefaultPluginAPI = class {
|
|
|
32415
33046
|
this.pipelines = readonlyPipelines;
|
|
32416
33047
|
const tr = init.toolRegistry;
|
|
32417
33048
|
const isOfficial = init.official === true;
|
|
33049
|
+
const capabilities = init.capabilities;
|
|
32418
33050
|
const assertCanMutateTool = (name, op) => {
|
|
32419
33051
|
if (isOfficial) return;
|
|
32420
33052
|
const currentOwner = tr.ownerOf(name);
|
|
32421
33053
|
if (currentOwner === void 0) return;
|
|
32422
33054
|
const ownedSolelyByMe = currentOwner.split("+").every((seg) => seg === owner);
|
|
32423
|
-
if (
|
|
33055
|
+
if (ownedSolelyByMe) return;
|
|
33056
|
+
const toolCaps = tr.get(name)?.capabilities ?? [];
|
|
33057
|
+
const pluginMutateCaps = capabilities?.toolMutateCapabilities ?? [];
|
|
33058
|
+
const hasRequiredCap = toolCaps.some((c) => pluginMutateCaps.includes(c));
|
|
33059
|
+
if (!hasRequiredCap) {
|
|
32424
33060
|
throw new Error(
|
|
32425
|
-
`Plugin "${owner}" may not ${op} tool "${name}" \u2014 it is owned by "${currentOwner}".
|
|
33061
|
+
`Plugin "${owner}" may not ${op} tool "${name}" \u2014 it is owned by "${currentOwner}". Tool capabilities: [${toolCaps.join(", ") || "none"}]. Plugin toolMutateCapabilities: [${pluginMutateCaps.join(", ") || "none"}]. Missing required capability to mutate this tool.`
|
|
32426
33062
|
);
|
|
32427
33063
|
}
|
|
32428
33064
|
};
|
|
@@ -34714,6 +35350,7 @@ ${check.stderr}`);
|
|
|
34714
35350
|
return new Promise((res) => {
|
|
34715
35351
|
let stdout = "";
|
|
34716
35352
|
let stderr = "";
|
|
35353
|
+
const MAX_GIT_OUTPUT = 1e6;
|
|
34717
35354
|
const child = spawn(this.gitBin, args, {
|
|
34718
35355
|
cwd,
|
|
34719
35356
|
env: buildChildEnv(),
|
|
@@ -34722,10 +35359,10 @@ ${check.stderr}`);
|
|
|
34722
35359
|
windowsHide: true
|
|
34723
35360
|
});
|
|
34724
35361
|
child.stdout?.on("data", (c) => {
|
|
34725
|
-
stdout += c.toString();
|
|
35362
|
+
if (stdout.length < MAX_GIT_OUTPUT) stdout += c.toString();
|
|
34726
35363
|
});
|
|
34727
35364
|
child.stderr?.on("data", (c) => {
|
|
34728
|
-
stderr += c.toString();
|
|
35365
|
+
if (stderr.length < MAX_GIT_OUTPUT) stderr += c.toString();
|
|
34729
35366
|
});
|
|
34730
35367
|
child.on("error", (err) => res({ code: 1, stdout, stderr: err.message }));
|
|
34731
35368
|
child.on("close", (code) => res({ code: code ?? 1, stdout, stderr }));
|
|
@@ -35093,7 +35730,7 @@ var CollaborationBus = class {
|
|
|
35093
35730
|
const timeoutPromise = new Promise((resolve14) => {
|
|
35094
35731
|
timer = setTimeout(() => resolve14("timeout"), timeoutMs);
|
|
35095
35732
|
});
|
|
35096
|
-
const resumedPromise = this.pausePromise.then(() => "resumed");
|
|
35733
|
+
const resumedPromise = this.pausePromise.then(() => "resumed").catch(() => "resumed");
|
|
35097
35734
|
const winner = await Promise.race([resumedPromise, timeoutPromise]);
|
|
35098
35735
|
if (timer) clearTimeout(timer);
|
|
35099
35736
|
if (winner === "timeout") {
|
|
@@ -35285,6 +35922,14 @@ var DefaultMailbox = class {
|
|
|
35285
35922
|
await fsp3.writeFile(this.filePath, "", "utf8");
|
|
35286
35923
|
});
|
|
35287
35924
|
}
|
|
35925
|
+
// ── Client registry stubs (not applicable per-session) ─────────────────
|
|
35926
|
+
async registerClient(_input) {
|
|
35927
|
+
}
|
|
35928
|
+
async clientHeartbeat(_input) {
|
|
35929
|
+
}
|
|
35930
|
+
async getClientStatuses() {
|
|
35931
|
+
return [];
|
|
35932
|
+
}
|
|
35288
35933
|
// ── Internal ──────────────────────────────────────────────────────────
|
|
35289
35934
|
async _readAll() {
|
|
35290
35935
|
try {
|
|
@@ -37600,6 +38245,6 @@ function createChimeraPlugin() {
|
|
|
37600
38245
|
};
|
|
37601
38246
|
}
|
|
37602
38247
|
|
|
37603
|
-
export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AgentStatusTracker, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BrainMonitor, BudgetExceededError, CHIMERA_REVIEW_PROMPT, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DEPENDENCY_FILE_PATTERNS, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMailbox, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FORBIDDEN_PROTO_KEYS, FileMemoryBackend, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, GlobalMailbox, GraphMemoryBackend, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, MEMORY_TYPE_LABELS, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddError, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionMemoryConsolidator, SessionRecovery, SessionRegistry, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, StreamHangError, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertNever, assertSafePath, atomicWrite, attachAutoExtend, attachDepWatcherBridge, attachMailboxChecker, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildLosslessDigest, buildMailboxBlock, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildQueuedMessagesBlock, buildRecoveryStrategies, buildSmartDigest, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compactLog, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeMessageTokens, computeTaskItemProgress, computeTaskProgress, consumeBtwNotes, consumeQueuedMessagesUpdate, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createAutonomyBrain, createChimeraPlugin, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMailboxChecker, createMcpControlTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createStrategyCompactor, createSyncPlugin, createTieredBrainArbiter, createToolOutputSerializer, decryptConfigSecrets, deepMerge, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, detectEcosystem as detectPackageEcosystem, dispatchAgent, downloadGitHubTarball, eliseOldToolResults, emptyGoal, emptyPlan, emptyTaskFile, encryptConfigSecrets, enhanceUserPrompt, ensureDir, estimateMessageTokens, estimateMessages, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, expectDefined, extractRunEnv, extractText, filesystemServer, findCriticalPath, findPreserveStart, flagsToConfigPatch, formatContextWindowModeList, formatDecisionSummary, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTaskList, formatTaskProgress, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getFileHistory, getFilesByAgent, getFullLog, getFullPackageLog, getLastAuthor, getManifestPackages, getPackageAuthor, getPackagesByAgent, getPlanTemplate, getSessionRegistry, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hasSessionRegistry, hasTextContent, hashRequest, hookMatcherMatches, injectPendingMailboxMessages, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isPluginError, isPrimitiveArray, isSddError, isSecretField, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTasks, loadTodosCheckpoint, loadUserModes, mailboxSessionTag, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDependencyWatcherConfig, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeMailInboxTool, makeMailSendTool, makeMailboxTool, makeRollUpTool, makeSpawnTool, makeTerminateTool, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, mutatePlan, mutateTasks, noOpLogger, noOpVault, normalizeRecipient, normalizeToLf, normalizedEqual, onResize, parseContinueDirective, parseEntries, parseProgressFromText, parseSkillRef, peekQueuedMessages, pendingBtwCount, phaseForRole, projectHash, projectSlug, recentTextTurns, recordActualUsage, recordFileAction, recordPackageAction, recordProgress, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveChimeraConfig, resolveContextWindowPolicy, resolveMailboxIdentity, resolveModelMatrix, resolveProjectDir, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, scoreAgents, scoreMessage, securitySlashCommand, sentinelServer, setBtwNote, setOutputLineGuard, setPlanItemStatus, setProgress, setQueuedMessagesSnapshot, setRawMode, shouldEnhance, slackServer, sleep, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, startPackageOutdatedWatcher, startTechStackConsumer, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, truncate, unifiedDiff, unloadPlugins, updatePackageOutdatedStatus, validateAgainstSchema, wireMetricsToEvents, withFileLock, wrapAsState, writeErr, writeOut, wstackGlobalRoot, zaiVisionServer };
|
|
38248
|
+
export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AgentStatusTracker, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BrainMonitor, BudgetExceededError, CHIMERA_REVIEW_PROMPT, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DEPENDENCY_FILE_PATTERNS, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMailbox, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FORBIDDEN_PROTO_KEYS, FileMemoryBackend, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, GlobalMailbox, GraphMemoryBackend, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, MEMORY_TYPE_LABELS, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddError, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionMemoryConsolidator, SessionRecovery, SessionRegistry, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, StreamHangError, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertNever, assertSafePath, atomicWrite, attachAutoExtend, attachDepWatcherBridge, attachMailboxChecker, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildLosslessDigest, buildMailboxBlock, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildQueuedMessagesBlock, buildRecoveryStrategies, buildSmartDigest, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compactLog, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeMessageTokens, computeTaskItemProgress, computeTaskProgress, consumeBtwNotes, consumeQueuedMessagesUpdate, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createAutonomyBrain, createChimeraPlugin, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMailboxChecker, createMcpControlTool, createMcpUseTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createStrategyCompactor, createSyncPlugin, createTieredBrainArbiter, createToolOutputSerializer, decryptConfigSecrets, deepMerge, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, detectEcosystem as detectPackageEcosystem, dispatchAgent, downloadGitHubTarball, eliseOldToolResults, emptyGoal, emptyPlan, emptyTaskFile, encryptConfigSecrets, enhanceUserPrompt, ensureDir, estimateMessageTokens, estimateMessages, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, expectDefined, extractRunEnv, extractText, filesystemServer, findCriticalPath, findPreserveStart, flagsToConfigPatch, formatContextWindowModeList, formatDecisionSummary, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTaskList, formatTaskProgress, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getFileHistory, getFilesByAgent, getFullLog, getFullPackageLog, getLastAuthor, getManifestPackages, getPackageAuthor, getPackagesByAgent, getPlanTemplate, getSessionRegistry, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hasSessionRegistry, hasTextContent, hashRequest, hookMatcherMatches, injectPendingMailboxMessages, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isPluginError, isPrimitiveArray, isSddError, isSecretField, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTasks, loadTodosCheckpoint, loadUserModes, mailboxSessionTag, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDependencyWatcherConfig, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeMailInboxTool, makeMailSendTool, makeMailboxTool, makeRollUpTool, makeSpawnTool, makeTerminateTool, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, mutatePlan, mutateTasks, noOpLogger, noOpVault, normalizeRecipient, normalizeToLf, normalizedEqual, onResize, parseContinueDirective, parseEntries, parseProgressFromText, parseSkillRef, peekQueuedMessages, pendingBtwCount, phaseForRole, projectHash, projectSlug, recentTextTurns, recordActualUsage, recordFileAction, recordPackageAction, recordProgress, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveChimeraConfig, resolveContextWindowPolicy, resolveMailboxIdentity, resolveModelMatrix, resolveProjectDir, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, scoreAgents, scoreMessage, securitySlashCommand, sentinelServer, setBtwNote, setOutputLineGuard, setPlanItemStatus, setProgress, setQueuedMessagesSnapshot, setRawMode, shouldEnhance, slackServer, sleep, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, startPackageOutdatedWatcher, startTechStackConsumer, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, truncate, unifiedDiff, unloadPlugins, updatePackageOutdatedStatus, validateAgainstSchema, wireMetricsToEvents, withFileLock, wrapAsState, writeErr, writeOut, wstackGlobalRoot, zaiVisionServer };
|
|
37604
38249
|
//# sourceMappingURL=index.js.map
|
|
37605
38250
|
//# sourceMappingURL=index.js.map
|