@sema-agent/core 3.0.0 → 5.0.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/CHANGELOG.md +2382 -0
- package/dist/agents/cascade.d.ts +3 -1
- package/dist/agents/cascade.js +31 -32
- package/dist/agents/cumulative-stats.d.ts +29 -0
- package/dist/agents/cumulative-stats.js +29 -0
- package/dist/agents/observer.d.ts +4 -0
- package/dist/agents/observer.js +11 -10
- package/dist/agents/repair-loop.d.ts +2 -0
- package/dist/agents/repair-loop.js +48 -24
- package/dist/agents/retain-ledger.d.ts +2 -0
- package/dist/agents/retain-ledger.js +6 -5
- package/dist/agents/roster-store.d.ts +1 -0
- package/dist/agents/roster-store.js +3 -5
- package/dist/agents/send-message-tool.d.ts +1 -0
- package/dist/agents/send-message-tool.js +2 -0
- package/dist/agents/subagent.d.ts +3 -1
- package/dist/agents/subagent.js +79 -94
- package/dist/agents/teacher.d.ts +1 -9
- package/dist/agents/teacher.js +21 -24
- package/dist/agents/tool-filter.js +6 -7
- package/dist/agents/verify.d.ts +1 -0
- package/dist/agents/verify.js +15 -14
- package/dist/brain/anthropic.js +24 -21
- package/dist/brain/openai.js +24 -21
- package/dist/brain/stream-engine.js +5 -2
- package/dist/brain/stream-shared.d.ts +1 -0
- package/dist/brain/stream-shared.js +14 -0
- package/dist/brain/terminal-cause.d.ts +4 -0
- package/dist/brain/terminal-cause.js +12 -0
- package/dist/brain/tool-call-id.d.ts +1 -0
- package/dist/brain/tool-call-id.js +3 -0
- package/dist/brain/tool-call-repair.js +2 -1
- package/dist/core/arg-summary.d.ts +21 -1
- package/dist/core/arg-summary.js +61 -14
- package/dist/core/auto-compaction.d.ts +1 -0
- package/dist/core/auto-compaction.js +16 -25
- package/dist/core/background-agent-store.d.ts +22 -22
- package/dist/core/background-agent-store.js +19 -23
- package/dist/core/checkpoint-store.d.ts +6 -13
- package/dist/core/checkpoint-store.js +11 -5
- package/dist/core/file-snapshot-store.d.ts +8 -0
- package/dist/core/file-snapshot-store.js +4 -3
- package/dist/core/fs-write-gate-policy.js +2 -3
- package/dist/core/hooks.d.ts +4 -1
- package/dist/core/hooks.js +8 -18
- package/dist/core/lsp.js +4 -3
- package/dist/core/mailbox-store.d.ts +7 -10
- package/dist/core/mcp.d.ts +7 -10
- package/dist/core/mcp.js +7 -9
- package/dist/core/memory-engine/engine.d.ts +0 -1
- package/dist/core/memory-engine/engine.js +24 -34
- package/dist/core/memory-engine/file-backend.d.ts +1 -2
- package/dist/core/memory-engine/file-backend.js +25 -36
- package/dist/core/memory-engine/layout.d.ts +8 -0
- package/dist/core/memory-engine/layout.js +60 -4
- package/dist/core/memory-engine/scope-contract.js +9 -3
- package/dist/core/memory-engine/types.d.ts +1 -1
- package/dist/core/permission-rules.js +2 -3
- package/dist/core/runner/active-skill-scope.d.ts +0 -1
- package/dist/core/runner/active-skill-scope.js +2 -17
- package/dist/core/runner/assemble-result.d.ts +2 -7
- package/dist/core/runner/assemble-result.js +3 -4
- package/dist/core/runner/compaction-call-options.d.ts +7 -0
- package/dist/core/runner/compaction-call-options.js +30 -0
- package/dist/core/runner/prepare-task.d.ts +6 -23
- package/dist/core/runner/prepare-task.js +36 -61
- package/dist/core/runner/runtask.d.ts +1 -0
- package/dist/core/runner/runtask.js +84 -172
- package/dist/core/runner/session-rule-policy.js +7 -5
- package/dist/core/runner/teardown-bounded.d.ts +7 -0
- package/dist/core/runner/teardown-bounded.js +36 -0
- package/dist/core/runner/tool-disclosure.d.ts +2 -5
- package/dist/core/runner/turn-attachments.d.ts +5 -15
- package/dist/core/runner/turn-attachments.js +1 -1
- package/dist/core/safe-notify.d.ts +17 -0
- package/dist/core/safe-notify.js +59 -0
- package/dist/core/sensitive-path-policy.js +4 -4
- package/dist/core/session-reconcile.js +1 -2
- package/dist/core/skill-tool-specifier.js +2 -3
- package/dist/core/skills-directory.js +2 -3
- package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
- package/dist/core/stub-env.d.ts +2 -6
- package/dist/core/surrogate-safe-slice.d.ts +4 -0
- package/dist/core/surrogate-safe-slice.js +18 -0
- package/dist/core/task-registry-monitor.js +8 -13
- package/dist/core/task-registry-shared.d.ts +23 -1
- package/dist/core/task-registry-shared.js +16 -0
- package/dist/core/task-registry.d.ts +6 -1
- package/dist/core/task-registry.js +52 -87
- package/dist/core/task-tool-shape.d.ts +0 -2
- package/dist/core/task-tool-shape.js +2 -5
- package/dist/core/tool-errors.js +5 -4
- package/dist/core/tool-name-aliases.d.ts +1 -2
- package/dist/core/tool-name-aliases.js +42 -59
- package/dist/core/tool-policy.js +21 -17
- package/dist/core/tool-result-store.d.ts +1 -0
- package/dist/core/tool-result-store.js +17 -1
- package/dist/core/trace.d.ts +9 -9
- package/dist/core/types.d.ts +15 -12
- package/dist/core/untrusted-egress.d.ts +4 -2
- package/dist/core/untrusted-egress.js +28 -14
- package/dist/core/workflow-journal-store.d.ts +9 -20
- package/dist/core/workflow-run-store.d.ts +11 -10
- package/dist/core/workflow-run-store.js +22 -16
- package/dist/engine/compaction/utils.js +4 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +2 -24
- package/dist/engine/execution-env/node-execution-env.js +1 -1
- package/dist/engine/harness/agent-harness.d.ts +1 -0
- package/dist/engine/harness/agent-harness.js +13 -33
- package/dist/engine/harness/types.d.ts +29 -67
- package/dist/engine/llm/types.d.ts +1 -1
- package/dist/engine/loop/agent-loop.js +12 -14
- package/dist/engine/loop/types.d.ts +11 -9
- package/dist/engine/session/memory-repo.d.ts +2 -6
- package/dist/engine/session/session.d.ts +5 -30
- package/dist/index.d.ts +6 -3
- package/dist/index.js +4 -3
- package/dist/internal/harness-types.d.ts +3 -1
- package/dist/orchestration/run-spec.js +6 -4
- package/dist/orchestration/run-workflow-tool.js +3 -36
- package/dist/orchestration/workflow-governance.js +2 -1
- package/dist/orchestration/workflow.d.ts +4 -11
- package/dist/orchestration/workflow.js +164 -204
- package/dist/prompt-assembly/packs/sema-default.js +1 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +10 -9
- package/dist/prompt-assembly/turn-snapshot.d.ts +2 -5
- package/dist/prompts/default.js +1 -3
- package/dist/prompts/simple-sections.d.ts +0 -1
- package/dist/prompts/simple-sections.js +0 -1
- package/dist/stores/file/background-agent-store.d.ts +3 -12
- package/dist/stores/file/background-agent-store.js +3 -41
- package/dist/stores/file/checkpoint-store.js +6 -6
- package/dist/stores/file/mailbox-store.d.ts +2 -6
- package/dist/stores/file/session-policy-store.js +15 -1
- package/dist/stores/file/session-store.d.ts +2 -6
- package/dist/stores/file/workflow-journal-store.d.ts +3 -11
- package/dist/stores/file/workflow-run-store.d.ts +3 -7
- package/dist/stores/file/workflow-run-store.js +4 -17
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -0
- package/dist/tools/fs/bash-readonly-classifier.js +60 -25
- package/dist/tools/fs/fs-bash.js +330 -104
- package/dist/tools/fs/fs-pdf.d.ts +2 -12
- package/dist/tools/fs/fs-shared.js +2 -2
- package/dist/tools/fs/fs-write.js +0 -1
- package/dist/tools/fs/notebook.d.ts +2 -5
- package/dist/tools/fs/safety.d.ts +3 -0
- package/dist/tools/fs/safety.js +43 -14
- package/dist/tools/fs/search.js +5 -5
- package/dist/tools/monitor.d.ts +1 -0
- package/dist/tools/monitor.js +7 -5
- package/dist/tools/worktree.d.ts +2 -7
- package/dist/tools/worktree.js +3 -1
- package/package.json +6 -2
package/dist/agents/subagent.js
CHANGED
|
@@ -5,12 +5,12 @@ import { OUTPUT_TOOL_NAME, REPORT_BLOCKED_TOOL_NAME } from "../core/runner/synth
|
|
|
5
5
|
import { TOOL_SEARCH_NAME } from "../core/runner/tool-disclosure.js";
|
|
6
6
|
import { OFFLOAD_TOOL_NAME } from "../core/tool-result-store.js";
|
|
7
7
|
import { resolveToolSubset, toolNameAllowed } from "./tool-filter.js";
|
|
8
|
-
import { canonicalToolName } from "../core/tool-name-aliases.js";
|
|
9
8
|
import { builtinAgentDefinitions } from "./builtin-agents.js";
|
|
10
9
|
import { SUBAGENT_PROMPT } from "../prompts/default.js";
|
|
11
10
|
import { hasSessionFork } from "../core/session.js";
|
|
12
11
|
import { isDurablePause } from "./suspend-guard.js";
|
|
13
12
|
import { delimitUntrusted, inlineUntrusted } from "../core/untrusted-text.js";
|
|
13
|
+
import { createSafeNotifier } from "../core/safe-notify.js";
|
|
14
14
|
import { boundedRedactedSummary } from "../core/untrusted-egress.js";
|
|
15
15
|
import { uuidv7 } from "../internal/harness.js";
|
|
16
16
|
import { addWorktree } from "../core/git-worktree-env.js";
|
|
@@ -18,6 +18,17 @@ import { shellQuote } from "../tools/fs/search.js";
|
|
|
18
18
|
import { BG_AGENT_REAP_STOP_ERROR } from "../core/task-registry.js";
|
|
19
19
|
import { extractErrorCode } from "../brain/errors.js";
|
|
20
20
|
import { FORK_DEFAULT_MAX_TURNS, SESSION_BG_DEFAULT_TIMEOUT_SEC, RETAIN_DEFAULT_TTL_MS, RETAIN_DEFAULT_MAX, RUNNING_AGENT_OBSERVE_EVERY_BEATS } from "../config/defaults.js";
|
|
21
|
+
function rollupDelegatedCost(stats, nested) {
|
|
22
|
+
if (stats.costMicroUsd === undefined)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (nested !== undefined && nested.costMicroUsd === undefined)
|
|
25
|
+
return undefined;
|
|
26
|
+
return stats.costMicroUsd + (nested?.costMicroUsd ?? 0);
|
|
27
|
+
}
|
|
28
|
+
function delegatedCostField(stats) {
|
|
29
|
+
const total = rollupDelegatedCost(stats, stats.nested);
|
|
30
|
+
return total !== undefined ? { costMicroUsd: total } : {};
|
|
31
|
+
}
|
|
21
32
|
export { FORK_DEFAULT_MAX_TURNS, SESSION_BG_DEFAULT_TIMEOUT_SEC, RETAIN_DEFAULT_TTL_MS, RETAIN_DEFAULT_MAX };
|
|
22
33
|
import { SUBAGENT_RESUME_CAP, SubagentRetainLedger, getOrCreateSessionRetainLedger, ensureSessionReapHook, createResumePrompt, } from "./retain-ledger.js";
|
|
23
34
|
import { recordRosterSpawn } from "./roster-store.js";
|
|
@@ -63,7 +74,6 @@ export function inheritedManifestScopeFor(snapshot) {
|
|
|
63
74
|
return frames;
|
|
64
75
|
}
|
|
65
76
|
export const DEFAULT_SUBAGENT_TOOL_NAME = "Agent";
|
|
66
|
-
export const LEGACY_SUBAGENT_TOOL_NAME = "Task";
|
|
67
77
|
export const EXTRA_TOOLS_MAX_FACTORY_CALLS_PER_TREE = 64;
|
|
68
78
|
export const DEFAULT_SUBAGENT_MAX_DEPTH = 3;
|
|
69
79
|
export const EXTRA_TOOLS_FAILED_NOTE = "note: extraTools evaluation failed — the injected tool set was skipped for this spawn.";
|
|
@@ -73,7 +83,7 @@ function countArgLines(v) {
|
|
|
73
83
|
}
|
|
74
84
|
function createToolStatsCounter(delegationToolName) {
|
|
75
85
|
const t = { readCount: 0, searchCount: 0, bashCount: 0, editFileCount: 0, linesAdded: 0, linesRemoved: 0, otherToolCount: 0 };
|
|
76
|
-
const excluded = new Set([delegationToolName, DEFAULT_SUBAGENT_TOOL_NAME
|
|
86
|
+
const excluded = new Set([delegationToolName, DEFAULT_SUBAGENT_TOOL_NAME]);
|
|
77
87
|
const recordEditLines = (args) => {
|
|
78
88
|
if (args === null || typeof args !== "object")
|
|
79
89
|
return;
|
|
@@ -198,7 +208,7 @@ const ccElapsedTag = (ms) => {
|
|
|
198
208
|
};
|
|
199
209
|
const ccCompletionText = (desc, settled, rawStatus, elapsedMs) => `Agent "${desc}" ${settled === "killed" ? "stopped" : settled === "completed" ? "finished" : rawStatus}${ccElapsedTag(elapsedMs)}`;
|
|
200
210
|
const BG_AGENT_COLLATERAL_REAP_REASON = "its parent run ended";
|
|
201
|
-
const RESERVED_AGENT_NAMES = new Set([OUTPUT_TOOL_NAME, TOOL_SEARCH_NAME, OFFLOAD_TOOL_NAME, REPORT_BLOCKED_TOOL_NAME, DEFAULT_SUBAGENT_TOOL_NAME
|
|
211
|
+
const RESERVED_AGENT_NAMES = new Set([OUTPUT_TOOL_NAME, TOOL_SEARCH_NAME, OFFLOAD_TOOL_NAME, REPORT_BLOCKED_TOOL_NAME, DEFAULT_SUBAGENT_TOOL_NAME]);
|
|
202
212
|
export const REPORT_FIELD_MAX = 300;
|
|
203
213
|
function configError(message, code) {
|
|
204
214
|
const e = new Error(message);
|
|
@@ -264,6 +274,7 @@ function createSteerHandle(stream, parentToolCallId, agentName, settled, retain)
|
|
|
264
274
|
};
|
|
265
275
|
}
|
|
266
276
|
export function createSubagentResume(deps) {
|
|
277
|
+
const notifier = createSafeNotifier(deps.onNotifyError !== undefined ? { onError: deps.onNotifyError } : undefined);
|
|
267
278
|
const resume = async (content) => {
|
|
268
279
|
const ledger = deps.ledger;
|
|
269
280
|
if (!ledger) {
|
|
@@ -360,8 +371,8 @@ export function createSubagentResume(deps) {
|
|
|
360
371
|
...(deps.parentToolCallId !== undefined ? { parentToolCallId: deps.parentToolCallId } : {}),
|
|
361
372
|
...(deps.rowParentTaskId !== undefined ? { parentTaskId: deps.rowParentTaskId } : {}),
|
|
362
373
|
...(deps.rowParentSessionId !== undefined ? { parentSessionId: deps.rowParentSessionId } : {}),
|
|
363
|
-
...(deps.rowRootSessionId !== undefined ? { rootSessionId: deps.rowRootSessionId } : {}),
|
|
364
|
-
startedAt: Date.now(),
|
|
374
|
+
...((deps.rowRootSessionId ?? deps.rowParentSessionId) !== undefined ? { rootSessionId: deps.rowRootSessionId ?? deps.rowParentSessionId } : {}),
|
|
375
|
+
startedAt: deps.rowSpawnedAt ?? Date.now(),
|
|
365
376
|
});
|
|
366
377
|
}
|
|
367
378
|
}
|
|
@@ -403,6 +414,7 @@ export function createSubagentResume(deps) {
|
|
|
403
414
|
taskId: deps.taskId,
|
|
404
415
|
sessionScoped: deps.sessionScoped === true,
|
|
405
416
|
...(deps.rowAgentType !== undefined ? { agentType: deps.rowAgentType } : {}),
|
|
417
|
+
sessionId: entry.childSessionId,
|
|
406
418
|
transcriptId: entry.childSessionId,
|
|
407
419
|
...(deps.parentToolCallId !== undefined ? { parentToolCallId: deps.parentToolCallId } : {}),
|
|
408
420
|
progressTaskId: e.taskId,
|
|
@@ -442,11 +454,7 @@ export function createSubagentResume(deps) {
|
|
|
442
454
|
settleResolve = r;
|
|
443
455
|
});
|
|
444
456
|
if (deps.sink) {
|
|
445
|
-
|
|
446
|
-
deps.sink(createSteerHandle(stream, deps.parentToolCallId, entry.agentName, settled, { resume, childSessionId: entry.childSessionId }));
|
|
447
|
-
}
|
|
448
|
-
catch {
|
|
449
|
-
}
|
|
457
|
+
notifier.notify(() => deps.sink?.(createSteerHandle(stream, deps.parentToolCallId, entry.agentName, settled, { resume, childSessionId: entry.childSessionId })), "subagent.resume.sink");
|
|
450
458
|
}
|
|
451
459
|
void (async () => {
|
|
452
460
|
try {
|
|
@@ -493,8 +501,9 @@ export function createSubagentResume(deps) {
|
|
|
493
501
|
seq: entry.cycleSeq,
|
|
494
502
|
...(stoppedByRevive !== undefined ? { stoppedBy: stoppedByRevive } : {}),
|
|
495
503
|
summary: reviveTerminalSummary,
|
|
504
|
+
...resumeResidual(),
|
|
496
505
|
resumable: status !== "killed",
|
|
497
|
-
usage: { tokens: child.stats.tokens, turns: child.stats.turns,
|
|
506
|
+
usage: { tokens: child.stats.tokens, turns: child.stats.turns, ...delegatedCostField(child.stats) },
|
|
498
507
|
...(completionIdRevive !== undefined ? { completionId: completionIdRevive } : {}),
|
|
499
508
|
});
|
|
500
509
|
const resumeFrame = {
|
|
@@ -512,7 +521,7 @@ export function createSubagentResume(deps) {
|
|
|
512
521
|
...(status === "killed" && child.result ? { partial: true } : {}),
|
|
513
522
|
...resumeResidual(),
|
|
514
523
|
resumable: status !== "killed",
|
|
515
|
-
usage: { tokens: child.stats.tokens, turns: child.stats.turns,
|
|
524
|
+
usage: { tokens: child.stats.tokens, turns: child.stats.turns, ...delegatedCostField(child.stats) },
|
|
516
525
|
...(completionIdRevive !== undefined ? { completionId: completionIdRevive } : {}),
|
|
517
526
|
};
|
|
518
527
|
const gateOwner = ownsTerminalFacesRevive && status === "completed" && deps.notify !== undefined && deps.registry !== undefined && ledger.get(deps.parentToolCallId) === entry
|
|
@@ -632,18 +641,6 @@ function parkCompletionNotify(deps) {
|
|
|
632
641
|
};
|
|
633
642
|
entry.deferredNotify = { ...(payload.seq !== undefined ? { seq: payload.seq } : {}), cancel, flush: () => deliver(false) };
|
|
634
643
|
}
|
|
635
|
-
function adaptLegacyForkArgs(args) {
|
|
636
|
-
const raw = args;
|
|
637
|
-
if (raw !== null && typeof raw === "object" && raw.prompt === undefined && typeof raw.directive === "string") {
|
|
638
|
-
return {
|
|
639
|
-
...args,
|
|
640
|
-
prompt: raw.directive,
|
|
641
|
-
subagent_type: FORK_SUBAGENT_TYPE,
|
|
642
|
-
description: typeof raw.description === "string" ? raw.description : "forked agent (legacy Fork call)",
|
|
643
|
-
};
|
|
644
|
-
}
|
|
645
|
-
return args;
|
|
646
|
-
}
|
|
647
644
|
export function normalizeSubagentType(value) {
|
|
648
645
|
return value.normalize("NFKC").toLowerCase().replace(/[\p{White_Space}\p{Pd}_]+/gu, "");
|
|
649
646
|
}
|
|
@@ -777,6 +774,7 @@ export function agentWhenToUseText(def, lean = true) {
|
|
|
777
774
|
function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
778
775
|
const maxDepth = opts.maxDepth ?? DEFAULT_SUBAGENT_MAX_DEPTH;
|
|
779
776
|
const toolName = opts.name ?? DEFAULT_SUBAGENT_TOOL_NAME;
|
|
777
|
+
const notifier = createSafeNotifier(opts.onObserverError !== undefined ? { onError: (f) => opts.onObserverError?.(f.error, { site: f.site }) } : undefined);
|
|
780
778
|
const deploymentNames = new Set((opts.agents ?? []).map((a) => a.name));
|
|
781
779
|
const builtins = opts.builtinAgents === false ? [] : builtinAgentDefinitions(toolName).filter((d) => !deploymentNames.has(d.name));
|
|
782
780
|
const available = [...(opts.agents ?? []), ...builtins].filter((a) => !excluded.has(a.name));
|
|
@@ -813,7 +811,6 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
813
811
|
agentListing,
|
|
814
812
|
...(rosterNames !== undefined ? { agentModels: rosterNames } : {}),
|
|
815
813
|
executionMode: "parallel",
|
|
816
|
-
...(!opts.name ? { aliases: [LEGACY_SUBAGENT_TOOL_NAME] } : {}),
|
|
817
814
|
contract: { contractId: "core.agent@1", implementationRevision: "1" },
|
|
818
815
|
description: `Launch a new agent to handle complex, multi-step tasks. Each agent type has specific capabilities and tools available to it.\n` +
|
|
819
816
|
(opts.purpose ? `\nThis sub-agent is for: ${opts.purpose}.\n` : "") +
|
|
@@ -897,9 +894,9 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
897
894
|
}
|
|
898
895
|
: {}),
|
|
899
896
|
}),
|
|
900
|
-
prepareArguments: (args) => foldGeneralPurposeAlias(
|
|
897
|
+
prepareArguments: (args) => foldGeneralPurposeAlias(args, generalPurposeShadowed),
|
|
901
898
|
execute: async (args, ctx) => {
|
|
902
|
-
const a = foldGeneralPurposeAlias(
|
|
899
|
+
const a = foldGeneralPurposeAlias(args, generalPurposeShadowed);
|
|
903
900
|
const wantsBackground = opts.background !== undefined && a.run_in_background !== false;
|
|
904
901
|
const reviveClaim = ctx.reviveClaim;
|
|
905
902
|
if (reviveClaim !== undefined && opts.background === undefined) {
|
|
@@ -1125,18 +1122,16 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1125
1122
|
if (injectedTools.length > 0) {
|
|
1126
1123
|
const taken = new Set();
|
|
1127
1124
|
const reserve = (t) => {
|
|
1128
|
-
taken.add(
|
|
1125
|
+
taken.add(t.name);
|
|
1129
1126
|
for (const alias of t.aliases ?? [])
|
|
1130
|
-
taken.add(
|
|
1127
|
+
taken.add(alias);
|
|
1131
1128
|
};
|
|
1132
1129
|
for (const t of opts.tools ?? [])
|
|
1133
1130
|
reserve(t);
|
|
1134
|
-
taken.add(
|
|
1135
|
-
if (!opts.name)
|
|
1136
|
-
taken.add(canonicalToolName(LEGACY_SUBAGENT_TOOL_NAME));
|
|
1131
|
+
taken.add(toolName);
|
|
1137
1132
|
const merged = [...(opts.tools ?? [])];
|
|
1138
1133
|
for (const t of injectedTools) {
|
|
1139
|
-
const names = [
|
|
1134
|
+
const names = [t.name, ...(t.aliases ?? [])];
|
|
1140
1135
|
if (names.some((n) => taken.has(n)))
|
|
1141
1136
|
continue;
|
|
1142
1137
|
for (const n of names)
|
|
@@ -1153,8 +1148,9 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1153
1148
|
: perCallModel ?? (def ? (def.model ?? ctx.model ?? opts.model) : opts.model);
|
|
1154
1149
|
const childSystemPrompt = def?.systemPrompt ?? opts.systemPrompt;
|
|
1155
1150
|
const childDefaultPersona = childSystemPrompt === undefined && !wantsFork ? SUBAGENT_PROMPT : undefined;
|
|
1156
|
-
const
|
|
1157
|
-
|
|
1151
|
+
const defMaxTurns = typeof def?.maxTurns === "number" && Number.isFinite(def.maxTurns) && def.maxTurns > 0 ? def.maxTurns : undefined;
|
|
1152
|
+
const childLimits = defMaxTurns !== undefined
|
|
1153
|
+
? { ...opts.limits, maxTurns: defMaxTurns }
|
|
1158
1154
|
: wantsFork && opts.limits?.maxTurns === undefined
|
|
1159
1155
|
? { ...opts.limits, maxTurns: FORK_DEFAULT_MAX_TURNS }
|
|
1160
1156
|
: opts.limits;
|
|
@@ -1188,14 +1184,10 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1188
1184
|
else if (observerFailure === undefined) {
|
|
1189
1185
|
observerFailure = msg;
|
|
1190
1186
|
}
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
});
|
|
1196
|
-
}
|
|
1197
|
-
catch {
|
|
1198
|
-
}
|
|
1187
|
+
notifier.notify(() => opts.onObserverError?.(err, {
|
|
1188
|
+
...(def !== undefined ? { observedAgent: def.name } : {}),
|
|
1189
|
+
...(observerArm ? { observerAgent: observerArm.observerDefinition.name } : {}),
|
|
1190
|
+
}), "subagent.onObserverError");
|
|
1199
1191
|
};
|
|
1200
1192
|
const observedSteerRef = {};
|
|
1201
1193
|
let pendingTrigger = [];
|
|
@@ -1239,7 +1231,10 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1239
1231
|
...(ctx.alwaysLoadTools !== undefined ? { alwaysLoadTools: [...ctx.alwaysLoadTools] } : {}),
|
|
1240
1232
|
...(ctx.promptProfile !== undefined ? { promptProfile: ctx.promptProfile } : {}),
|
|
1241
1233
|
enableBlockedReport: false,
|
|
1242
|
-
limits: {
|
|
1234
|
+
limits: {
|
|
1235
|
+
maxTurns: typeof observerDef.maxTurns === "number" && Number.isFinite(observerDef.maxTurns) && observerDef.maxTurns > 0 ? observerDef.maxTurns : 8,
|
|
1236
|
+
timeoutSec: 120,
|
|
1237
|
+
},
|
|
1243
1238
|
});
|
|
1244
1239
|
const runObserverLeg = async (spec) => {
|
|
1245
1240
|
if (!isObserverTaskId(sid))
|
|
@@ -1683,21 +1678,17 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1683
1678
|
resumable: false,
|
|
1684
1679
|
...(completionIdReap !== undefined ? { completionId: completionIdReap } : {}),
|
|
1685
1680
|
});
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
}, { priority: "later" });
|
|
1698
|
-
}
|
|
1699
|
-
catch {
|
|
1700
|
-
}
|
|
1681
|
+
notifier.notify(() => notify?.({
|
|
1682
|
+
task_id: taskId,
|
|
1683
|
+
task_type: "background_agent",
|
|
1684
|
+
toolUseId: ctx.toolCallId,
|
|
1685
|
+
status: "killed",
|
|
1686
|
+
stoppedBy: stoppedByReap,
|
|
1687
|
+
summary: summaryReap,
|
|
1688
|
+
sessionId: forkedId,
|
|
1689
|
+
resumable: false,
|
|
1690
|
+
...(completionIdReap !== undefined ? { completionId: completionIdReap } : {}),
|
|
1691
|
+
}, { priority: "later" }), "subagent.reapTerminalNotify");
|
|
1701
1692
|
});
|
|
1702
1693
|
if (agentName !== undefined) {
|
|
1703
1694
|
recordRosterSpawn(ctx.roster, { name: agentName, agentId: taskId, sessionId: forkedId, toolUseId: ctx.toolCallId, owner: bgOwner, scope: bgScope, ...((typeof childModel === "string" ? resolveModelDisplayLabel(childModel) : childModel?.id) !== undefined ? { model: typeof childModel === "string" ? childModel : childModel?.id } : {}), ...((ctx.rootSessionId ?? ctx.sessionId) !== undefined ? { rootSessionId: ctx.rootSessionId ?? ctx.sessionId } : {}), ...(sessionScopedBg ? { sessionScoped: true } : {}), createdAt: Date.now() });
|
|
@@ -1770,6 +1761,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1770
1761
|
kind: "tick",
|
|
1771
1762
|
taskId,
|
|
1772
1763
|
sessionScoped: sessionScopedBg === true,
|
|
1764
|
+
sessionId: forkedId,
|
|
1773
1765
|
transcriptId: forkedId,
|
|
1774
1766
|
parentToolCallId: ctx.toolCallId,
|
|
1775
1767
|
progressTaskId: e.taskId,
|
|
@@ -1805,7 +1797,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1805
1797
|
tokens: child.stats.tokens + (nsb?.tokens ?? 0),
|
|
1806
1798
|
turns: child.stats.turns + (nsb?.turns ?? 0),
|
|
1807
1799
|
tasks: 1 + (nsb?.tasks ?? 0),
|
|
1808
|
-
costMicroUsd: (child.stats
|
|
1800
|
+
costMicroUsd: rollupDelegatedCost(child.stats, nsb),
|
|
1809
1801
|
});
|
|
1810
1802
|
}
|
|
1811
1803
|
catch {
|
|
@@ -1857,7 +1849,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1857
1849
|
summary: forkTerminalSummary,
|
|
1858
1850
|
...residualFork,
|
|
1859
1851
|
resumable: resumableFork,
|
|
1860
|
-
usage: { tokens: child.stats.tokens, turns: child.stats.turns,
|
|
1852
|
+
usage: { tokens: child.stats.tokens, turns: child.stats.turns, ...delegatedCostField(child.stats) },
|
|
1861
1853
|
...(completionIdFork !== undefined ? { completionId: completionIdFork } : {}),
|
|
1862
1854
|
});
|
|
1863
1855
|
try {
|
|
@@ -1876,7 +1868,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1876
1868
|
...(settledBg === "killed" && child.result ? { partial: true } : {}),
|
|
1877
1869
|
...residualFork,
|
|
1878
1870
|
resumable: resumableFork,
|
|
1879
|
-
usage: { tokens: child.stats.tokens, turns: child.stats.turns,
|
|
1871
|
+
usage: { tokens: child.stats.tokens, turns: child.stats.turns, ...delegatedCostField(child.stats) },
|
|
1880
1872
|
...(completionIdFork !== undefined ? { completionId: completionIdFork } : {}),
|
|
1881
1873
|
}, { priority: "later" });
|
|
1882
1874
|
}
|
|
@@ -1980,7 +1972,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1980
1972
|
tokens: forkChild.stats.tokens + (nsf?.tokens ?? 0),
|
|
1981
1973
|
turns: forkChild.stats.turns + (nsf?.turns ?? 0),
|
|
1982
1974
|
tasks: 1 + (nsf?.tasks ?? 0),
|
|
1983
|
-
costMicroUsd: (forkChild.stats
|
|
1975
|
+
costMicroUsd: rollupDelegatedCost(forkChild.stats, nsf),
|
|
1984
1976
|
});
|
|
1985
1977
|
if (isDurablePause(forkChild.status)) {
|
|
1986
1978
|
return {
|
|
@@ -2100,7 +2092,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2100
2092
|
return { isError: true, content: `Sub-agent not started in background: ${e instanceof Error ? e.message : String(e)}${wt ? `\n${wt}` : ""}`, details: { error: "register_failed" } };
|
|
2101
2093
|
}
|
|
2102
2094
|
if (agentName !== undefined) {
|
|
2103
|
-
recordRosterSpawn(ctx.roster, { name: agentName, agentId: taskId, toolUseId: ctx.toolCallId, owner: bgOwner, scope: bgScope, ...((typeof childModel === "string" ? resolveModelDisplayLabel(childModel) : childModel?.id) !== undefined ? { model: typeof childModel === "string" ? childModel : childModel?.id } : {}), ...(reviveRow !== undefined ? (reviveRow.rootSessionId !== undefined ? { rootSessionId: reviveRow.rootSessionId } : {}) : (ctx.rootSessionId ?? ctx.sessionId) !== undefined ? { rootSessionId: ctx.rootSessionId ?? ctx.sessionId } : {}), ...(sessionScopedBg ? { sessionScoped: true } : {}), createdAt: reviveRow?.spawnedAt ?? Date.now() });
|
|
2095
|
+
recordRosterSpawn(ctx.roster, { name: agentName, agentId: taskId, toolUseId: ctx.toolCallId, owner: bgOwner, scope: bgScope, ...((typeof childModel === "string" ? resolveModelDisplayLabel(childModel) : childModel?.id) !== undefined ? { model: typeof childModel === "string" ? childModel : childModel?.id } : {}), ...(reviveRow !== undefined ? ((reviveRow.rootSessionId ?? reviveRow.parentSessionId) !== undefined ? { rootSessionId: reviveRow.rootSessionId ?? reviveRow.parentSessionId } : {}) : (ctx.rootSessionId ?? ctx.sessionId) !== undefined ? { rootSessionId: ctx.rootSessionId ?? ctx.sessionId } : {}), ...(sessionScopedBg ? { sessionScoped: true } : {}), createdAt: reviveRow?.spawnedAt ?? Date.now() });
|
|
2104
2096
|
}
|
|
2105
2097
|
const bgSink = ctx.onBackgroundChildEvent;
|
|
2106
2098
|
const sinkEmit = (event) => {
|
|
@@ -2131,21 +2123,17 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2131
2123
|
resumable: false,
|
|
2132
2124
|
...(completionIdReap !== undefined ? { completionId: completionIdReap } : {}),
|
|
2133
2125
|
});
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
}, { priority: "later" });
|
|
2146
|
-
}
|
|
2147
|
-
catch {
|
|
2148
|
-
}
|
|
2126
|
+
notifier.notify(() => notify?.({
|
|
2127
|
+
task_id: taskId,
|
|
2128
|
+
task_type: "background_agent",
|
|
2129
|
+
toolUseId: ctx.toolCallId,
|
|
2130
|
+
status: "killed",
|
|
2131
|
+
stoppedBy: stoppedByReap,
|
|
2132
|
+
summary: summaryReap,
|
|
2133
|
+
sessionId: bgChildSessionId,
|
|
2134
|
+
resumable: false,
|
|
2135
|
+
...(completionIdReap !== undefined ? { completionId: completionIdReap } : {}),
|
|
2136
|
+
}, { priority: "later" }), "subagent.reapTerminalNotify");
|
|
2149
2137
|
});
|
|
2150
2138
|
const bgDurableProbe = bg.registry.durableAgentRowProbe(taskId);
|
|
2151
2139
|
const bgRowConfirmed = async () => (bgDurableProbe ? await bgDurableProbe().catch(() => false) : false);
|
|
@@ -2165,14 +2153,14 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2165
2153
|
? {
|
|
2166
2154
|
...(reviveRow.parentTaskId !== undefined ? { parentTaskId: reviveRow.parentTaskId } : {}),
|
|
2167
2155
|
...(reviveRow.parentSessionId !== undefined ? { parentSessionId: reviveRow.parentSessionId } : {}),
|
|
2168
|
-
...(reviveRow.rootSessionId !== undefined ? { rootSessionId: reviveRow.rootSessionId } : {}),
|
|
2156
|
+
...((reviveRow.rootSessionId ?? reviveRow.parentSessionId) !== undefined ? { rootSessionId: reviveRow.rootSessionId ?? reviveRow.parentSessionId } : {}),
|
|
2169
2157
|
}
|
|
2170
2158
|
: {
|
|
2171
2159
|
...(ctx.taskId !== undefined && ctx.taskId !== ctx.sessionId ? { parentTaskId: ctx.taskId } : {}),
|
|
2172
2160
|
...(ctx.sessionId !== undefined ? { parentSessionId: ctx.sessionId } : {}),
|
|
2173
2161
|
...((ctx.rootSessionId ?? ctx.sessionId) !== undefined ? { rootSessionId: ctx.rootSessionId ?? ctx.sessionId } : {}),
|
|
2174
2162
|
}),
|
|
2175
|
-
startedAt: Date.now(),
|
|
2163
|
+
startedAt: reviveRow?.spawnedAt ?? Date.now(),
|
|
2176
2164
|
});
|
|
2177
2165
|
const bgRetainLedger = reviveRow !== undefined
|
|
2178
2166
|
? undefined
|
|
@@ -2249,6 +2237,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2249
2237
|
kind: "tick",
|
|
2250
2238
|
taskId,
|
|
2251
2239
|
sessionScoped: sessionScopedBg === true,
|
|
2240
|
+
sessionId: bgChildSessionId,
|
|
2252
2241
|
transcriptId: bgChildSessionId,
|
|
2253
2242
|
parentToolCallId: ctx.toolCallId,
|
|
2254
2243
|
progressTaskId: e.taskId,
|
|
@@ -2405,7 +2394,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2405
2394
|
tokens: child.stats.tokens + (ns2?.tokens ?? 0),
|
|
2406
2395
|
turns: child.stats.turns + (ns2?.turns ?? 0),
|
|
2407
2396
|
tasks: 1 + (ns2?.tasks ?? 0),
|
|
2408
|
-
costMicroUsd: (child.stats
|
|
2397
|
+
costMicroUsd: rollupDelegatedCost(child.stats, ns2),
|
|
2409
2398
|
});
|
|
2410
2399
|
}
|
|
2411
2400
|
catch {
|
|
@@ -2515,7 +2504,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2515
2504
|
summary: bgTerminalSummary,
|
|
2516
2505
|
...residual,
|
|
2517
2506
|
resumable: resumableBg,
|
|
2518
|
-
usage: { tokens: child.stats.tokens, turns: child.stats.turns,
|
|
2507
|
+
usage: { tokens: child.stats.tokens, turns: child.stats.turns, ...delegatedCostField(child.stats) },
|
|
2519
2508
|
...(completionIdBg !== undefined ? { completionId: completionIdBg } : {}),
|
|
2520
2509
|
});
|
|
2521
2510
|
const completionFrame = {
|
|
@@ -2533,7 +2522,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2533
2522
|
...(settled === "killed" && child.result ? { partial: true } : {}),
|
|
2534
2523
|
...residual,
|
|
2535
2524
|
resumable: resumableBg,
|
|
2536
|
-
usage: { tokens: child.stats.tokens, turns: child.stats.turns,
|
|
2525
|
+
usage: { tokens: child.stats.tokens, turns: child.stats.turns, ...delegatedCostField(child.stats) },
|
|
2537
2526
|
...(completionIdBg !== undefined ? { completionId: completionIdBg } : {}),
|
|
2538
2527
|
};
|
|
2539
2528
|
const gateOwner = ownsTerminalFaces && settled === "completed" && notify !== undefined ? bgRetain?.childSessionId : undefined;
|
|
@@ -2685,14 +2674,10 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2685
2674
|
sink: ctx.onSubagentSpawn,
|
|
2686
2675
|
...(opts.background ? { registry: opts.background.registry } : {}),
|
|
2687
2676
|
});
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
}));
|
|
2693
|
-
}
|
|
2694
|
-
catch {
|
|
2695
|
-
}
|
|
2677
|
+
notifier.notify(() => ctx.onSubagentSpawn?.(createSteerHandle(stream, ctx.toolCallId, childAgentName, settled, {
|
|
2678
|
+
resume,
|
|
2679
|
+
...(retainEntry ? { childSessionId: retainEntry.childSessionId } : {}),
|
|
2680
|
+
})), "subagent.onSubagentSpawn");
|
|
2696
2681
|
}
|
|
2697
2682
|
try {
|
|
2698
2683
|
for await (const ev of stream)
|
|
@@ -2737,7 +2722,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2737
2722
|
tokens: child.stats.tokens + (ns?.tokens ?? 0),
|
|
2738
2723
|
turns: child.stats.turns + (ns?.turns ?? 0),
|
|
2739
2724
|
tasks: 1 + (ns?.tasks ?? 0),
|
|
2740
|
-
costMicroUsd: (child.stats
|
|
2725
|
+
costMicroUsd: rollupDelegatedCost(child.stats, ns),
|
|
2741
2726
|
});
|
|
2742
2727
|
if (isDurablePause(child.status)) {
|
|
2743
2728
|
if (retainEntry)
|
package/dist/agents/teacher.d.ts
CHANGED
|
@@ -53,15 +53,7 @@ export interface TeacherRunResult extends TaskResult {
|
|
|
53
53
|
tokens: number;
|
|
54
54
|
tasks: number;
|
|
55
55
|
costMicroUsd?: number;
|
|
56
|
-
humanReview?:
|
|
57
|
-
count: number;
|
|
58
|
-
totalWaitMs: number;
|
|
59
|
-
gates: Array<{
|
|
60
|
-
kind: string;
|
|
61
|
-
waitMs: number;
|
|
62
|
-
decision?: string;
|
|
63
|
-
}>;
|
|
64
|
-
};
|
|
56
|
+
humanReview?: NonNullable<TaskResult["stats"]["humanReview"]>;
|
|
65
57
|
};
|
|
66
58
|
}
|
|
67
59
|
export declare function parseTeacherAdvice(text: string): TeacherAdvice;
|
package/dist/agents/teacher.js
CHANGED
|
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { mapNestedSuspend, isDurablePause } from "./suspend-guard.js";
|
|
3
3
|
import { isDefineToolProduct, stampDefineToolBrand } from "../core/tools.js";
|
|
4
4
|
import { delimitUntrusted, inlineUntrusted } from "../core/untrusted-text.js";
|
|
5
|
+
import { buildCumulativeStats } from "./cumulative-stats.js";
|
|
5
6
|
export const TEACHER_PROMPT = `You are an expert advisor to a less-capable "student" agent that got stuck.
|
|
6
7
|
You receive the task and the student's recent failed attempts. Your job is to help the student RECOVER,
|
|
7
8
|
not to do the work for it.
|
|
@@ -84,6 +85,7 @@ async function runTeacherCore(runner, studentSpec, teacher) {
|
|
|
84
85
|
let studentTokens = 0;
|
|
85
86
|
let studentTurns = 0;
|
|
86
87
|
let studentCostMicro = 0;
|
|
88
|
+
let anyStudentLegUnpriced = false;
|
|
87
89
|
let studentPrompt = 0;
|
|
88
90
|
let studentTotalInput = 0;
|
|
89
91
|
let studentCached = 0;
|
|
@@ -202,6 +204,8 @@ async function runTeacherCore(runner, studentSpec, teacher) {
|
|
|
202
204
|
studentTokens += s.tokens;
|
|
203
205
|
studentTurns += s.turns;
|
|
204
206
|
studentCostMicro += s.costMicroUsd ?? 0;
|
|
207
|
+
if (s.costMicroUsd === undefined)
|
|
208
|
+
anyStudentLegUnpriced = true;
|
|
205
209
|
studentPrompt += s.promptTokens ?? 0;
|
|
206
210
|
studentTotalInput += s.totalInputTokens ?? 0;
|
|
207
211
|
studentCached += s.cachedTokens ?? 0;
|
|
@@ -442,34 +446,27 @@ async function runTeacherCore(runner, studentSpec, teacher) {
|
|
|
442
446
|
function finalize(result) {
|
|
443
447
|
return {
|
|
444
448
|
...result,
|
|
445
|
-
stats: {
|
|
446
|
-
...result.stats,
|
|
449
|
+
stats: buildCumulativeStats(result.stats, {
|
|
447
450
|
tokens: studentTokens,
|
|
448
451
|
turns: studentTurns,
|
|
449
452
|
costMicroUsd: studentCostMicro || undefined,
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
: undefined,
|
|
465
|
-
costBreakdown: {
|
|
466
|
-
llmRootMicroUsd: studentLlmRootMicro,
|
|
467
|
-
nestedSubagentMicroUsd: studentNestedCostMicro,
|
|
468
|
-
memoryConsolidationMicroUsd: 0,
|
|
469
|
-
compactionMicroUsd: studentCompactionMicro,
|
|
453
|
+
anyLegUnpriced: anyStudentLegUnpriced,
|
|
454
|
+
promptTokens: studentPrompt,
|
|
455
|
+
totalInputTokens: studentTotalInput,
|
|
456
|
+
cachedTokens: studentCached,
|
|
457
|
+
outputTokens: studentOutput,
|
|
458
|
+
cacheWriteTokens: studentCacheWrite,
|
|
459
|
+
cacheWriteTokensLong: studentCacheWriteLong,
|
|
460
|
+
llmRootMicroUsd: studentLlmRootMicro,
|
|
461
|
+
compactionMicroUsd: studentCompactionMicro,
|
|
462
|
+
nested: {
|
|
463
|
+
tokens: studentNestedTokens,
|
|
464
|
+
turns: studentNestedTurns,
|
|
465
|
+
tasks: studentNestedTasks,
|
|
466
|
+
costMicroUsd: studentNestedCostMicro,
|
|
470
467
|
},
|
|
471
|
-
humanReview:
|
|
472
|
-
},
|
|
468
|
+
humanReview: { count: hrCount, totalWaitMs: hrWaitMs, gates: hrGates },
|
|
469
|
+
}),
|
|
473
470
|
escalations,
|
|
474
471
|
teacherStats: {
|
|
475
472
|
tokens: teacherTokens,
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { canonicalToolName } from "../core/tool-name-aliases.js";
|
|
2
1
|
export function toolNameAllowed(name, allowTools, denyTools) {
|
|
3
|
-
const allow = allowTools !== undefined && !allowTools.includes("*") ? new Set(allowTools
|
|
4
|
-
const deny = denyTools && denyTools.length > 0 ? new Set(denyTools
|
|
5
|
-
const n =
|
|
2
|
+
const allow = allowTools !== undefined && !allowTools.includes("*") ? new Set(allowTools) : undefined;
|
|
3
|
+
const deny = denyTools && denyTools.length > 0 ? new Set(denyTools) : undefined;
|
|
4
|
+
const n = name;
|
|
6
5
|
return (!allow || allow.has(n)) && (!deny || !deny.has(n));
|
|
7
6
|
}
|
|
8
7
|
export function resolveToolSubset(pool, allowTools, denyTools) {
|
|
9
|
-
const allow = allowTools !== undefined && !allowTools.includes("*") ? new Set(allowTools
|
|
10
|
-
const deny = denyTools && denyTools.length > 0 ? new Set(denyTools
|
|
8
|
+
const allow = allowTools !== undefined && !allowTools.includes("*") ? new Set(allowTools) : undefined;
|
|
9
|
+
const deny = denyTools && denyTools.length > 0 ? new Set(denyTools) : undefined;
|
|
11
10
|
if (!allow && !deny)
|
|
12
11
|
return [...pool];
|
|
13
12
|
return pool.filter((t) => {
|
|
14
|
-
const matches = (set) => set.has(
|
|
13
|
+
const matches = (set) => set.has(t.name) || (t.aliases ?? []).some((a) => set.has(a));
|
|
15
14
|
return (!allow || matches(allow)) && (!deny || !matches(deny));
|
|
16
15
|
});
|
|
17
16
|
}
|
package/dist/agents/verify.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare const VerdictSchema: Type.TObject<{
|
|
|
11
11
|
}>;
|
|
12
12
|
export type Verdict = Static<typeof VerdictSchema>;
|
|
13
13
|
export interface VerifyConfig {
|
|
14
|
+
onNotifyError?: (failure: import("../core/safe-notify.js").SafeNotifyFailure) => void;
|
|
14
15
|
verifierModel?: ModelRef;
|
|
15
16
|
verifierTools?: ToolSpec[];
|
|
16
17
|
maxRounds?: number;
|
package/dist/agents/verify.js
CHANGED
|
@@ -3,6 +3,7 @@ import { CODE_AGENT_PROMPT } from "../prompts/default.js";
|
|
|
3
3
|
import { releaseSession } from "./session-util.js";
|
|
4
4
|
import { mapNestedSuspend, isDurablePause } from "./suspend-guard.js";
|
|
5
5
|
import { delimitUntrusted, sanitizeUntrustedText } from "../core/untrusted-text.js";
|
|
6
|
+
import { createSafeNotifier } from "../core/safe-notify.js";
|
|
6
7
|
export const VERIFICATION_PROMPT = `You are a verification specialist. Your job is NOT to confirm the implementation works — it is to try to BREAK it.
|
|
7
8
|
|
|
8
9
|
You have two documented failure patterns. First, verification avoidance: faced with a check, you find reasons not to run it — you read code, narrate what you would test, declare "PASS," and move on. Second, being seduced by the first 80%: a polished result or a passing test suite makes you inclined to pass it, not noticing the edge that crashes, the state that vanishes, the bad input that is unhandled. The first 80% is the easy part. Your entire value is in finding the last 20%.
|
|
@@ -58,6 +59,8 @@ export const VerdictSchema = Type.Object({
|
|
|
58
59
|
}),
|
|
59
60
|
evidence: Type.Optional(Type.String({ description: "Commands run + observed output backing the verdict." })),
|
|
60
61
|
});
|
|
62
|
+
const VERIFY_ON_ROUND_SITE = "verify.onRound";
|
|
63
|
+
const VERIFY_ON_VERIFIER_PAUSE_SITE = "verify.onVerifierPause";
|
|
61
64
|
function fixObjective(findings) {
|
|
62
65
|
const list = findings.length
|
|
63
66
|
? findings.map((f) => `- ${sanitizeUntrustedText(f)}`).join("\n")
|
|
@@ -82,7 +85,8 @@ export async function verifyCompleted(runner, result, specBase, objective, confi
|
|
|
82
85
|
if (result.status !== "completed") {
|
|
83
86
|
return { ...result, verification: { verdict: "unverified", unverifiedReason: "impl_incomplete", rounds: 0, findings: [] } };
|
|
84
87
|
}
|
|
85
|
-
const maxRounds = Math.max(1, Math.floor(config.maxRounds
|
|
88
|
+
const maxRounds = Number.isFinite(config.maxRounds) ? Math.max(1, Math.floor(config.maxRounds)) : 2;
|
|
89
|
+
const notifier = createSafeNotifier(config.onNotifyError !== undefined ? { onError: config.onNotifyError } : undefined);
|
|
86
90
|
const verifierTools = config.verifierTools ?? (specBase.tools ?? []).filter((t) => t.effect === "read");
|
|
87
91
|
const evidenceMode = config.evidence != null && config.evidence.trim() !== "";
|
|
88
92
|
const verifierPrompt = config.verifierPrompt ?? (evidenceMode ? STATIC_VERIFICATION_PROMPT : VERIFICATION_PROMPT);
|
|
@@ -126,6 +130,7 @@ export async function verifyCompleted(runner, result, specBase, objective, confi
|
|
|
126
130
|
spend += v.cost;
|
|
127
131
|
verifierSpend += v.cost;
|
|
128
132
|
if (v.paused) {
|
|
133
|
+
const paused = v.paused;
|
|
129
134
|
outcome = {
|
|
130
135
|
verdict: "unverified",
|
|
131
136
|
unverifiedReason: "verifier_paused",
|
|
@@ -139,18 +144,14 @@ export async function verifyCompleted(runner, result, specBase, objective, confi
|
|
|
139
144
|
...(v.paused.checkpointGate ? { checkpointGate: v.paused.checkpointGate } : {}),
|
|
140
145
|
},
|
|
141
146
|
};
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
catch {
|
|
152
|
-
}
|
|
153
|
-
config.onRound?.({ round, verdict: outcome.verdict, findings: outcome.findings });
|
|
147
|
+
notifier.notify(() => config.onVerifierPause?.({
|
|
148
|
+
round,
|
|
149
|
+
status: paused.status,
|
|
150
|
+
sessionId: paused.sessionId,
|
|
151
|
+
...(paused.checkpointToken ? { checkpointToken: paused.checkpointToken } : {}),
|
|
152
|
+
...(paused.checkpointGate ? { checkpointGate: paused.checkpointGate } : {}),
|
|
153
|
+
}), VERIFY_ON_VERIFIER_PAUSE_SITE);
|
|
154
|
+
notifier.notify(() => config.onRound?.({ round, verdict: outcome.verdict, findings: outcome.findings }), VERIFY_ON_ROUND_SITE);
|
|
154
155
|
break;
|
|
155
156
|
}
|
|
156
157
|
const rawVerdict = v.verdict?.verdict ?? "unverified";
|
|
@@ -164,7 +165,7 @@ export async function verifyCompleted(runner, result, specBase, objective, confi
|
|
|
164
165
|
evidence: v.verdict?.evidence,
|
|
165
166
|
verifierCost: verifierSpend,
|
|
166
167
|
};
|
|
167
|
-
config.onRound?.({ round, verdict: outcome.verdict, findings: outcome.findings });
|
|
168
|
+
notifier.notify(() => config.onRound?.({ round, verdict: outcome.verdict, findings: outcome.findings }), VERIFY_ON_ROUND_SITE);
|
|
168
169
|
if (outcome.verdict !== "FAIL")
|
|
169
170
|
break;
|
|
170
171
|
if (round >= maxRounds)
|