@sema-agent/core 4.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 +37 -0
- package/dist/agents/cascade.d.ts +1 -0
- package/dist/agents/cascade.js +1 -1
- package/dist/agents/repair-loop.d.ts +2 -0
- package/dist/agents/repair-loop.js +21 -5
- package/dist/agents/roster-store.d.ts +1 -0
- package/dist/agents/roster-store.js +1 -1
- 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 +15 -32
- package/dist/agents/tool-filter.js +6 -7
- package/dist/agents/verify.d.ts +1 -0
- package/dist/agents/verify.js +1 -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 +1 -1
- package/dist/core/fs-write-gate-policy.js +2 -3
- package/dist/core/hooks.d.ts +1 -0
- package/dist/core/hooks.js +1 -1
- package/dist/core/mcp.js +0 -6
- package/dist/core/permission-rules.js +2 -3
- package/dist/core/runner/active-skill-scope.js +1 -2
- package/dist/core/runner/prepare-task.js +16 -8
- package/dist/core/runner/runtask.js +19 -16
- package/dist/core/runner/session-rule-policy.js +3 -4
- package/dist/core/sensitive-path-policy.js +2 -3
- 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/task-registry-shared.d.ts +1 -1
- package/dist/core/task-registry.d.ts +5 -1
- package/dist/core/task-registry.js +12 -30
- package/dist/core/task-tool-shape.d.ts +0 -2
- package/dist/core/task-tool-shape.js +2 -5
- package/dist/core/tool-name-aliases.d.ts +1 -2
- package/dist/core/tool-name-aliases.js +42 -60
- package/dist/core/tool-policy.js +11 -12
- package/dist/core/trace.d.ts +7 -0
- package/dist/core/untrusted-egress.d.ts +4 -2
- package/dist/core/untrusted-egress.js +21 -9
- package/dist/engine/execution-env/node-execution-env.js +1 -1
- package/dist/engine/loop/agent-loop.js +3 -12
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -2
- package/dist/orchestration/run-spec.js +2 -3
- package/dist/orchestration/run-workflow-tool.js +0 -1
- package/dist/orchestration/workflow-governance.js +2 -1
- package/dist/orchestration/workflow.d.ts +1 -0
- package/dist/orchestration/workflow.js +1 -1
- package/dist/prompt-assembly/packs/sema-default.js +1 -3
- 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/tools/fs/fs-bash.js +6 -8
- package/dist/tools/fs/fs-write.js +0 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.0.0 (2026-08-02)
|
|
4
|
+
|
|
5
|
+
_The baggage-unload major: the compatibility faces RB-476 cleared for tool NAMES are now cleared for id arguments, adapters and indexes too (RB-479), plus the revive-frame anchoring fix a downstream consumer was blocked on (RB-478). Everything that used to resolve silently under an old spelling now refuses loudly with the current spelling named._
|
|
6
|
+
|
|
7
|
+
**BREAKING — old tool names no longer resolve (RB-476, both stages)**
|
|
8
|
+
|
|
9
|
+
1. Callable aliases are cleared: `BashOutput`, `KillShell`, `KillBash`, `AgentOutput`, `WorkflowStatus`, `Fork`, `Sleep`, `Remember`, `recall` (and the rest of the rename table) are LOUD roster misses listing the live roster. A deployment's own same-named custom tool still wins (roster hit first).
|
|
10
|
+
2. The durable rename machinery is retired: `canonicalToolName` and `TOMBSTONED_TOOLS` root exports are REMOVED; `tool-name-aliases.ts` now exports only `RETIRED_TOOL_NAMES` (old name → guidance). A persisted pre-rename checkpoint action misses loudly on resume (`resume.tool_unavailable` + reopen) instead of silently folding onto the new tool.
|
|
11
|
+
3. A RETIRED name in a policy deny/ask/allow list that matches nothing in the run's roster is a HARD prepare failure (`config.legacy_tool_name`) — silent deny-widening is not a migration strategy.
|
|
12
|
+
4. The roster miss carries structured details for UI rendering: `{code: "tool.not_found", toolName, availableTools}`.
|
|
13
|
+
|
|
14
|
+
**BREAKING — undeclared id-argument pass-throughs cleared (RB-479-A①/②)**
|
|
15
|
+
|
|
16
|
+
- `TaskOutput` resolves ONLY `task_id`; `TaskStop` resolves ONLY `task_id`/`shell_id` (`shell_id` is the CC-declared surface and stays). The formerly smuggled `bash_id`/`runId` keys land on the loud missing-parameter refusal. The workflow-run poll capability is unchanged — address it as `task_id` (the value is the run id).
|
|
17
|
+
- The registry's internal `legacyToTaskId` shellId index is deleted: the minted `b*` task id is the ONLY registry address; a raw shellId as `task_id` is a loud not_found. `markStopSourceByShellId`/`clearPendingStopSourceByShellId` resolve by the (shellId, env) scan alone (this also removes a single-value index collision defect); calling them without `env` is a no-op.
|
|
18
|
+
- The env-direct background launch receipt drops its `Legacy bash_id=` sentence and the TaskOutput description drops the compatibility-acceptance sentence.
|
|
19
|
+
|
|
20
|
+
**BREAKING — legacy adapters retired (RB-479-A③/④)**
|
|
21
|
+
|
|
22
|
+
- The standalone-Fork `{directive}` argument adapter is deleted: a `{directive}`-shaped Agent call refuses loudly (empty prompt) instead of silently rerouting to the fork lane. `{prompt, subagent_type: "fork"}` is the (unchanged) explicit route; the `general-purpose` alias fold stays (live CC parity).
|
|
23
|
+
- `BackgroundAgentTaskHandle.notify` requires a disposition (`"queued" | "parked" | "dropped_duplicate"`, sync or Promise) — the `void` arm is removed from the type. Run-time behavior is unchanged (a non-conforming undefined still reads as queued).
|
|
24
|
+
|
|
25
|
+
**Fixed — revive frames anchor the row (RB-478, unblocks server residual-arm deletion)**
|
|
26
|
+
|
|
27
|
+
- All three revive-emission legs (SendMessage resume face, revive-claim spawn, roster record) now chain `rootSessionId ?? parentSessionId` UNCONDITIONALLY — a pre-floor row without a persisted root anchor still lands its host mark downstream.
|
|
28
|
+
- A revive frame's `startedAt` is the ROW's original spawn instant (durable `spawnedAt` / registry registration time), not the wake call's `Date.now()`. `AccessibleTaskRow` gains `createdAt` (additive).
|
|
29
|
+
|
|
30
|
+
**Added**
|
|
31
|
+
|
|
32
|
+
- `observer.notify_failed` trace event (additive union member): a host observer callback that throws inside a safe-notify isolation scope is disclosed (bounded, first failure per site). RB-473: the disclosure channel now reaches every deployment-reachable owner — `onNotifyError` options on auto-compaction/cascade/verify/roster-store/workflow/SendMessage, `TaskRegistry.notifierFailureCounts()`, the delegation tool's `onObserverError` (site attached), and the tool gate via the new trace event.
|
|
33
|
+
- Behavior changes declared from the ruling batch: the simple prompt profile's roster shrinks two sections (RB-322, CC-220 alignment); workflow-script-authored child personas carry a provenance head line (RB-461); the default background command budget is 60 minutes, was 30 (RB-366).
|
|
34
|
+
- `test/legacy-residue-gate.test.ts`: a both-ways ratchet freezing the residual compatibility lexicon per file — new compatibility machinery reds the gate until explicitly registered.
|
|
35
|
+
|
|
36
|
+
**Migration**
|
|
37
|
+
|
|
38
|
+
- Old tool names → current names (the refusal text lists the live roster). `bash_id`/`runId` → `task_id`. `{directive}` → `{prompt, subagent_type: "fork"}`. Void notify injectors → return `"queued"`. Policy lists naming retired tools → rename or remove the entry (prepare fails loudly otherwise).
|
|
39
|
+
|
|
3
40
|
## 4.0.0 (2026-08-02)
|
|
4
41
|
|
|
5
42
|
_Refactor campaign (50 candidates, three new discipline gates) + a test-discriminance pass + a three-class defect sweep + the closing four-lens review (22 findings, all dispositioned). Major because four config sentinels change MEANING under unchanged types — ENGINEERING-CODE §J2: same name, same type, new behavior is the semver case that compiles clean and computes wrong._
|
package/dist/agents/cascade.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface CascadeRung {
|
|
|
9
9
|
overrides?: Partial<Pick<TaskSpec, "limits" | "degrade" | "systemPrompt">>;
|
|
10
10
|
}
|
|
11
11
|
export interface CascadeConfig {
|
|
12
|
+
onNotifyError?: (failure: import("../core/safe-notify.js").SafeNotifyFailure) => void;
|
|
12
13
|
ladder: CascadeRung[];
|
|
13
14
|
gate?: (result: TaskResult, rung: {
|
|
14
15
|
index: number;
|
package/dist/agents/cascade.js
CHANGED
|
@@ -17,7 +17,7 @@ export async function runCascade(runner, spec, config) {
|
|
|
17
17
|
const gate = config.gate ?? createDefaultGate(spec);
|
|
18
18
|
const startedAt = Date.now();
|
|
19
19
|
const deadlineAt = config.totalTimeoutMs != null ? startedAt + config.totalTimeoutMs : undefined;
|
|
20
|
-
const notifier = createSafeNotifier();
|
|
20
|
+
const notifier = createSafeNotifier(config.onNotifyError !== undefined ? { onError: config.onNotifyError } : undefined);
|
|
21
21
|
const attempts = [];
|
|
22
22
|
let totalCost = 0;
|
|
23
23
|
let ceilingCostKnown = true;
|
|
@@ -87,7 +87,14 @@ export async function runRepairLoop(runner, implSpec, config) {
|
|
|
87
87
|
? { ...config.resumeBundle, diagnostics: [...config.resumeBundle.diagnostics], rejectedHypotheses: [...config.resumeBundle.rejectedHypotheses] }
|
|
88
88
|
: freshBundle();
|
|
89
89
|
const startedAt = Date.now();
|
|
90
|
-
|
|
90
|
+
const seededSpend = config.resumeBundle?.spentMicroUsd;
|
|
91
|
+
const seededActiveMs = config.resumeBundle?.activeElapsedMs;
|
|
92
|
+
const priorActiveMs = typeof seededActiveMs === "number" && Number.isFinite(seededActiveMs) ? Math.max(0, seededActiveMs) : 0;
|
|
93
|
+
let spend = typeof seededSpend === "number" && Number.isFinite(seededSpend) ? Math.max(0, seededSpend) : 0;
|
|
94
|
+
const stampAccount = () => {
|
|
95
|
+
bundle.spentMicroUsd = spend;
|
|
96
|
+
bundle.activeElapsedMs = priorActiveMs + (Date.now() - startedAt);
|
|
97
|
+
};
|
|
91
98
|
let lastResult;
|
|
92
99
|
let lastOracle;
|
|
93
100
|
let ownTokens = 0, ownTurns = 0, ownPrompt = 0, ownTotalInput = 0, ownCached = 0, ownOutput = 0;
|
|
@@ -148,11 +155,11 @@ export async function runRepairLoop(runner, implSpec, config) {
|
|
|
148
155
|
const { sessionId: _drop, ...rest } = implSpec;
|
|
149
156
|
return { ...rest, objective: `${implSpec.objective}\n\n${repairObjective(bundle)}` };
|
|
150
157
|
};
|
|
151
|
-
const exhaustedBeforeDispatch = () => ({
|
|
158
|
+
const exhaustedBeforeDispatch = (message, errorCode) => ({
|
|
152
159
|
taskId: implSpec.taskId ?? "",
|
|
153
160
|
status: "failed",
|
|
154
|
-
result: `repair loop: attempt budget already spent (attemptCount ${bundle.attemptCount} >= maxAttempts ${maxAttempts}) — no attempt dispatched`,
|
|
155
|
-
errorCode: "repair.attempts_exhausted",
|
|
161
|
+
result: message ?? `repair loop: attempt budget already spent (attemptCount ${bundle.attemptCount} >= maxAttempts ${maxAttempts}) — no attempt dispatched`,
|
|
162
|
+
errorCode: errorCode ?? "repair.attempts_exhausted",
|
|
156
163
|
sessionId: implSpec.sessionId ?? "",
|
|
157
164
|
stats: { tokens: 0, turns: 0, costMicroUsd: 0 },
|
|
158
165
|
terminal: "gave_up",
|
|
@@ -164,6 +171,13 @@ export async function runRepairLoop(runner, implSpec, config) {
|
|
|
164
171
|
while (true) {
|
|
165
172
|
if (!restartedOnce && bundle.attemptCount >= maxAttempts)
|
|
166
173
|
return exhaustedBeforeDispatch();
|
|
174
|
+
if (config.costCeilingMicroUsd != null && spend >= config.costCeilingMicroUsd) {
|
|
175
|
+
return exhaustedBeforeDispatch(`repair loop: cost ceiling already spent (carried ${spend} >= ceiling ${config.costCeilingMicroUsd} micro-USD) — no attempt dispatched`, "repair.budget_exhausted");
|
|
176
|
+
}
|
|
177
|
+
if (config.totalTimeoutMs != null && priorActiveMs + (Date.now() - startedAt) >= config.totalTimeoutMs) {
|
|
178
|
+
return exhaustedBeforeDispatch(`repair loop: active time budget already spent (carried ${priorActiveMs + (Date.now() - startedAt)}ms >= ${config.totalTimeoutMs}ms) — no attempt dispatched`, "repair.budget_exhausted");
|
|
179
|
+
}
|
|
180
|
+
stampAccount();
|
|
167
181
|
const isRepair = bundle.attemptCount > 0 && lastResult !== undefined && !restartedOnce;
|
|
168
182
|
const isSeededResume = !restartedOnce &&
|
|
169
183
|
lastResult === undefined &&
|
|
@@ -182,6 +196,7 @@ export async function runRepairLoop(runner, implSpec, config) {
|
|
|
182
196
|
restartedOnce = false;
|
|
183
197
|
const result = await runner.runTask(spec, { repairBundle: bundle });
|
|
184
198
|
spend += (result.stats.costMicroUsd ?? 0) + (result.stats.nested?.costMicroUsd ?? 0);
|
|
199
|
+
stampAccount();
|
|
185
200
|
accumulate(result.stats);
|
|
186
201
|
lastResult = result;
|
|
187
202
|
bundle.attemptCount += 1;
|
|
@@ -210,6 +225,7 @@ export async function runRepairLoop(runner, implSpec, config) {
|
|
|
210
225
|
const oracle = await config.oracle(config.graderEnv, result.result);
|
|
211
226
|
oracleCostMicroUsd += oracle.costMicroUsd ?? 0;
|
|
212
227
|
spend += oracle.costMicroUsd ?? 0;
|
|
228
|
+
stampAccount();
|
|
213
229
|
lastOracle = oracle;
|
|
214
230
|
bundle.oracleTier = oracle.tier;
|
|
215
231
|
const projected = terminalForTier(oracle);
|
|
@@ -230,7 +246,7 @@ export async function runRepairLoop(runner, implSpec, config) {
|
|
|
230
246
|
if (bundle.diagnostics.length < 3)
|
|
231
247
|
bundle.diagnostics.push(oracle.trace);
|
|
232
248
|
}
|
|
233
|
-
const overTime = config.totalTimeoutMs != null && Date.now() - startedAt >= config.totalTimeoutMs;
|
|
249
|
+
const overTime = config.totalTimeoutMs != null && priorActiveMs + (Date.now() - startedAt) >= config.totalTimeoutMs;
|
|
234
250
|
const overCost = config.costCeilingMicroUsd != null && spend >= config.costCeilingMicroUsd;
|
|
235
251
|
if (bundle.attemptCount >= maxAttempts || overTime || overCost) {
|
|
236
252
|
if (bundle.attemptCount >= maxAttempts && !overTime && !overCost && lastResult !== undefined && !restartUsed) {
|
|
@@ -23,6 +23,7 @@ export interface RosterStore {
|
|
|
23
23
|
releaseAgent(agentId: string): void | Promise<void>;
|
|
24
24
|
}
|
|
25
25
|
export interface RosterGcOptions {
|
|
26
|
+
onNotifyError?: (failure: import("../core/safe-notify.js").SafeNotifyFailure) => void;
|
|
26
27
|
maxAgeMs?: number;
|
|
27
28
|
maxEntries?: number;
|
|
28
29
|
onEvicted?: (entry: RosterEntry) => void;
|
|
@@ -36,7 +36,7 @@ function capped(entries, opts) {
|
|
|
36
36
|
const max = opts?.maxEntries;
|
|
37
37
|
if (max === undefined || entries.length <= max)
|
|
38
38
|
return entries;
|
|
39
|
-
const notifier = createSafeNotifier();
|
|
39
|
+
const notifier = createSafeNotifier(opts?.onNotifyError !== undefined ? { onError: opts.onNotifyError } : undefined);
|
|
40
40
|
const byAge = [...entries].sort((a, b) => a.createdAt - b.createdAt);
|
|
41
41
|
const dropCount = Math.max(0, entries.length - Math.max(0, max));
|
|
42
42
|
const dropped = new Set(byAge.slice(0, dropCount));
|
|
@@ -36,6 +36,7 @@ export interface SendMessageToolOptions {
|
|
|
36
36
|
content: string;
|
|
37
37
|
details?: unknown;
|
|
38
38
|
}>;
|
|
39
|
+
onNotifyError?: (failure: import("../core/safe-notify.js").SafeNotifyFailure) => void;
|
|
39
40
|
enrichCtx?: ToolCtxEnricher;
|
|
40
41
|
}
|
|
41
42
|
export declare const SEND_MESSAGE_SUMMARY_MAX = 200;
|
|
@@ -525,6 +525,8 @@ export function createSendMessageTool(opts) {
|
|
|
525
525
|
...(row.parentTaskId !== undefined ? { rowParentTaskId: row.parentTaskId } : {}),
|
|
526
526
|
...(row.parentSessionId !== undefined ? { rowParentSessionId: row.parentSessionId } : {}),
|
|
527
527
|
...(row.rootSessionId !== undefined ? { rowRootSessionId: row.rootSessionId } : {}),
|
|
528
|
+
...(row.createdAt !== undefined ? { rowSpawnedAt: row.createdAt } : {}),
|
|
529
|
+
...(opts.onNotifyError !== undefined ? { onNotifyError: opts.onNotifyError } : {}),
|
|
528
530
|
...(opts.notify ? { currentParentNotify: opts.notify } : {}),
|
|
529
531
|
});
|
|
530
532
|
const fromPrefix = senderIsChild ? `(message from teammate "${senderLabel}")\n` : "";
|
|
@@ -10,7 +10,6 @@ export type { SubagentStep, SubagentEditedFile } from "./subagent-steps.js";
|
|
|
10
10
|
export declare function notifyResultField(result: string | undefined): string | undefined;
|
|
11
11
|
export declare function inheritedManifestScopeFor(snapshot: readonly unknown[] | undefined): RunInternals["inheritedManifestScope"];
|
|
12
12
|
export declare const DEFAULT_SUBAGENT_TOOL_NAME = "Agent";
|
|
13
|
-
export declare const LEGACY_SUBAGENT_TOOL_NAME = "Task";
|
|
14
13
|
export declare const EXTRA_TOOLS_MAX_FACTORY_CALLS_PER_TREE = 64;
|
|
15
14
|
export declare const DEFAULT_SUBAGENT_MAX_DEPTH = 3;
|
|
16
15
|
export declare const EXTRA_TOOLS_FAILED_NOTE = "note: extraTools evaluation failed \u2014 the injected tool set was skipped for this spawn.";
|
|
@@ -76,6 +75,8 @@ export declare function createSubagentResume(deps: {
|
|
|
76
75
|
rowParentTaskId?: string;
|
|
77
76
|
rowParentSessionId?: string;
|
|
78
77
|
rowRootSessionId?: string;
|
|
78
|
+
rowSpawnedAt?: number;
|
|
79
|
+
onNotifyError?: (failure: import("../core/safe-notify.js").SafeNotifyFailure) => void;
|
|
79
80
|
}): (content: string) => Promise<string>;
|
|
80
81
|
export interface SubagentToolOptions {
|
|
81
82
|
runner: Runner;
|
|
@@ -109,6 +110,7 @@ export interface SubagentToolOptions {
|
|
|
109
110
|
onObserverError?: (err: unknown, info: {
|
|
110
111
|
observedAgent?: string;
|
|
111
112
|
observerAgent?: string;
|
|
113
|
+
site?: string;
|
|
112
114
|
}) => void;
|
|
113
115
|
extraTools?: (ctx: SubagentSpawnContext) => ToolSpec[] | Promise<ToolSpec[]>;
|
|
114
116
|
onExtraToolsError?: (err: unknown, info: {
|
package/dist/agents/subagent.js
CHANGED
|
@@ -5,7 +5,6 @@ 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";
|
|
@@ -75,7 +74,6 @@ export function inheritedManifestScopeFor(snapshot) {
|
|
|
75
74
|
return frames;
|
|
76
75
|
}
|
|
77
76
|
export const DEFAULT_SUBAGENT_TOOL_NAME = "Agent";
|
|
78
|
-
export const LEGACY_SUBAGENT_TOOL_NAME = "Task";
|
|
79
77
|
export const EXTRA_TOOLS_MAX_FACTORY_CALLS_PER_TREE = 64;
|
|
80
78
|
export const DEFAULT_SUBAGENT_MAX_DEPTH = 3;
|
|
81
79
|
export const EXTRA_TOOLS_FAILED_NOTE = "note: extraTools evaluation failed — the injected tool set was skipped for this spawn.";
|
|
@@ -85,7 +83,7 @@ function countArgLines(v) {
|
|
|
85
83
|
}
|
|
86
84
|
function createToolStatsCounter(delegationToolName) {
|
|
87
85
|
const t = { readCount: 0, searchCount: 0, bashCount: 0, editFileCount: 0, linesAdded: 0, linesRemoved: 0, otherToolCount: 0 };
|
|
88
|
-
const excluded = new Set([delegationToolName, DEFAULT_SUBAGENT_TOOL_NAME
|
|
86
|
+
const excluded = new Set([delegationToolName, DEFAULT_SUBAGENT_TOOL_NAME]);
|
|
89
87
|
const recordEditLines = (args) => {
|
|
90
88
|
if (args === null || typeof args !== "object")
|
|
91
89
|
return;
|
|
@@ -210,7 +208,7 @@ const ccElapsedTag = (ms) => {
|
|
|
210
208
|
};
|
|
211
209
|
const ccCompletionText = (desc, settled, rawStatus, elapsedMs) => `Agent "${desc}" ${settled === "killed" ? "stopped" : settled === "completed" ? "finished" : rawStatus}${ccElapsedTag(elapsedMs)}`;
|
|
212
210
|
const BG_AGENT_COLLATERAL_REAP_REASON = "its parent run ended";
|
|
213
|
-
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]);
|
|
214
212
|
export const REPORT_FIELD_MAX = 300;
|
|
215
213
|
function configError(message, code) {
|
|
216
214
|
const e = new Error(message);
|
|
@@ -276,7 +274,7 @@ function createSteerHandle(stream, parentToolCallId, agentName, settled, retain)
|
|
|
276
274
|
};
|
|
277
275
|
}
|
|
278
276
|
export function createSubagentResume(deps) {
|
|
279
|
-
const notifier = createSafeNotifier();
|
|
277
|
+
const notifier = createSafeNotifier(deps.onNotifyError !== undefined ? { onError: deps.onNotifyError } : undefined);
|
|
280
278
|
const resume = async (content) => {
|
|
281
279
|
const ledger = deps.ledger;
|
|
282
280
|
if (!ledger) {
|
|
@@ -373,8 +371,8 @@ export function createSubagentResume(deps) {
|
|
|
373
371
|
...(deps.parentToolCallId !== undefined ? { parentToolCallId: deps.parentToolCallId } : {}),
|
|
374
372
|
...(deps.rowParentTaskId !== undefined ? { parentTaskId: deps.rowParentTaskId } : {}),
|
|
375
373
|
...(deps.rowParentSessionId !== undefined ? { parentSessionId: deps.rowParentSessionId } : {}),
|
|
376
|
-
...(deps.rowRootSessionId !== undefined ? { rootSessionId: deps.rowRootSessionId } : {}),
|
|
377
|
-
startedAt: Date.now(),
|
|
374
|
+
...((deps.rowRootSessionId ?? deps.rowParentSessionId) !== undefined ? { rootSessionId: deps.rowRootSessionId ?? deps.rowParentSessionId } : {}),
|
|
375
|
+
startedAt: deps.rowSpawnedAt ?? Date.now(),
|
|
378
376
|
});
|
|
379
377
|
}
|
|
380
378
|
}
|
|
@@ -643,18 +641,6 @@ function parkCompletionNotify(deps) {
|
|
|
643
641
|
};
|
|
644
642
|
entry.deferredNotify = { ...(payload.seq !== undefined ? { seq: payload.seq } : {}), cancel, flush: () => deliver(false) };
|
|
645
643
|
}
|
|
646
|
-
function adaptLegacyForkArgs(args) {
|
|
647
|
-
const raw = args;
|
|
648
|
-
if (raw !== null && typeof raw === "object" && raw.prompt === undefined && typeof raw.directive === "string") {
|
|
649
|
-
return {
|
|
650
|
-
...args,
|
|
651
|
-
prompt: raw.directive,
|
|
652
|
-
subagent_type: FORK_SUBAGENT_TYPE,
|
|
653
|
-
description: typeof raw.description === "string" ? raw.description : "forked agent (legacy Fork call)",
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
return args;
|
|
657
|
-
}
|
|
658
644
|
export function normalizeSubagentType(value) {
|
|
659
645
|
return value.normalize("NFKC").toLowerCase().replace(/[\p{White_Space}\p{Pd}_]+/gu, "");
|
|
660
646
|
}
|
|
@@ -788,7 +774,7 @@ export function agentWhenToUseText(def, lean = true) {
|
|
|
788
774
|
function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
789
775
|
const maxDepth = opts.maxDepth ?? DEFAULT_SUBAGENT_MAX_DEPTH;
|
|
790
776
|
const toolName = opts.name ?? DEFAULT_SUBAGENT_TOOL_NAME;
|
|
791
|
-
const notifier = createSafeNotifier();
|
|
777
|
+
const notifier = createSafeNotifier(opts.onObserverError !== undefined ? { onError: (f) => opts.onObserverError?.(f.error, { site: f.site }) } : undefined);
|
|
792
778
|
const deploymentNames = new Set((opts.agents ?? []).map((a) => a.name));
|
|
793
779
|
const builtins = opts.builtinAgents === false ? [] : builtinAgentDefinitions(toolName).filter((d) => !deploymentNames.has(d.name));
|
|
794
780
|
const available = [...(opts.agents ?? []), ...builtins].filter((a) => !excluded.has(a.name));
|
|
@@ -825,7 +811,6 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
825
811
|
agentListing,
|
|
826
812
|
...(rosterNames !== undefined ? { agentModels: rosterNames } : {}),
|
|
827
813
|
executionMode: "parallel",
|
|
828
|
-
...(!opts.name ? { aliases: [LEGACY_SUBAGENT_TOOL_NAME] } : {}),
|
|
829
814
|
contract: { contractId: "core.agent@1", implementationRevision: "1" },
|
|
830
815
|
description: `Launch a new agent to handle complex, multi-step tasks. Each agent type has specific capabilities and tools available to it.\n` +
|
|
831
816
|
(opts.purpose ? `\nThis sub-agent is for: ${opts.purpose}.\n` : "") +
|
|
@@ -909,9 +894,9 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
909
894
|
}
|
|
910
895
|
: {}),
|
|
911
896
|
}),
|
|
912
|
-
prepareArguments: (args) => foldGeneralPurposeAlias(
|
|
897
|
+
prepareArguments: (args) => foldGeneralPurposeAlias(args, generalPurposeShadowed),
|
|
913
898
|
execute: async (args, ctx) => {
|
|
914
|
-
const a = foldGeneralPurposeAlias(
|
|
899
|
+
const a = foldGeneralPurposeAlias(args, generalPurposeShadowed);
|
|
915
900
|
const wantsBackground = opts.background !== undefined && a.run_in_background !== false;
|
|
916
901
|
const reviveClaim = ctx.reviveClaim;
|
|
917
902
|
if (reviveClaim !== undefined && opts.background === undefined) {
|
|
@@ -1137,18 +1122,16 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1137
1122
|
if (injectedTools.length > 0) {
|
|
1138
1123
|
const taken = new Set();
|
|
1139
1124
|
const reserve = (t) => {
|
|
1140
|
-
taken.add(
|
|
1125
|
+
taken.add(t.name);
|
|
1141
1126
|
for (const alias of t.aliases ?? [])
|
|
1142
|
-
taken.add(
|
|
1127
|
+
taken.add(alias);
|
|
1143
1128
|
};
|
|
1144
1129
|
for (const t of opts.tools ?? [])
|
|
1145
1130
|
reserve(t);
|
|
1146
|
-
taken.add(
|
|
1147
|
-
if (!opts.name)
|
|
1148
|
-
taken.add(canonicalToolName(LEGACY_SUBAGENT_TOOL_NAME));
|
|
1131
|
+
taken.add(toolName);
|
|
1149
1132
|
const merged = [...(opts.tools ?? [])];
|
|
1150
1133
|
for (const t of injectedTools) {
|
|
1151
|
-
const names = [
|
|
1134
|
+
const names = [t.name, ...(t.aliases ?? [])];
|
|
1152
1135
|
if (names.some((n) => taken.has(n)))
|
|
1153
1136
|
continue;
|
|
1154
1137
|
for (const n of names)
|
|
@@ -2109,7 +2092,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2109
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" } };
|
|
2110
2093
|
}
|
|
2111
2094
|
if (agentName !== undefined) {
|
|
2112
|
-
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() });
|
|
2113
2096
|
}
|
|
2114
2097
|
const bgSink = ctx.onBackgroundChildEvent;
|
|
2115
2098
|
const sinkEmit = (event) => {
|
|
@@ -2170,14 +2153,14 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2170
2153
|
? {
|
|
2171
2154
|
...(reviveRow.parentTaskId !== undefined ? { parentTaskId: reviveRow.parentTaskId } : {}),
|
|
2172
2155
|
...(reviveRow.parentSessionId !== undefined ? { parentSessionId: reviveRow.parentSessionId } : {}),
|
|
2173
|
-
...(reviveRow.rootSessionId !== undefined ? { rootSessionId: reviveRow.rootSessionId } : {}),
|
|
2156
|
+
...((reviveRow.rootSessionId ?? reviveRow.parentSessionId) !== undefined ? { rootSessionId: reviveRow.rootSessionId ?? reviveRow.parentSessionId } : {}),
|
|
2174
2157
|
}
|
|
2175
2158
|
: {
|
|
2176
2159
|
...(ctx.taskId !== undefined && ctx.taskId !== ctx.sessionId ? { parentTaskId: ctx.taskId } : {}),
|
|
2177
2160
|
...(ctx.sessionId !== undefined ? { parentSessionId: ctx.sessionId } : {}),
|
|
2178
2161
|
...((ctx.rootSessionId ?? ctx.sessionId) !== undefined ? { rootSessionId: ctx.rootSessionId ?? ctx.sessionId } : {}),
|
|
2179
2162
|
}),
|
|
2180
|
-
startedAt: Date.now(),
|
|
2163
|
+
startedAt: reviveRow?.spawnedAt ?? Date.now(),
|
|
2181
2164
|
});
|
|
2182
2165
|
const bgRetainLedger = reviveRow !== undefined
|
|
2183
2166
|
? undefined
|
|
@@ -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
|
@@ -86,7 +86,7 @@ export async function verifyCompleted(runner, result, specBase, objective, confi
|
|
|
86
86
|
return { ...result, verification: { verdict: "unverified", unverifiedReason: "impl_incomplete", rounds: 0, findings: [] } };
|
|
87
87
|
}
|
|
88
88
|
const maxRounds = Number.isFinite(config.maxRounds) ? Math.max(1, Math.floor(config.maxRounds)) : 2;
|
|
89
|
-
const notifier = createSafeNotifier();
|
|
89
|
+
const notifier = createSafeNotifier(config.onNotifyError !== undefined ? { onError: config.onNotifyError } : undefined);
|
|
90
90
|
const verifierTools = config.verifierTools ?? (specBase.tools ?? []).filter((t) => t.effect === "read");
|
|
91
91
|
const evidenceMode = config.evidence != null && config.evidence.trim() !== "";
|
|
92
92
|
const verifierPrompt = config.verifierPrompt ?? (evidenceMode ? STATIC_VERIFICATION_PROMPT : VERIFICATION_PROMPT);
|
|
@@ -1,2 +1,22 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type RedactionConfidence = "high" | "medium" | "low";
|
|
2
|
+
export interface RedactionFinding {
|
|
3
|
+
kind: string;
|
|
4
|
+
span: readonly [number, number];
|
|
5
|
+
confidence: RedactionConfidence;
|
|
6
|
+
marker: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RedactionReport {
|
|
9
|
+
findings: RedactionFinding[];
|
|
10
|
+
preexistingMarkers?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface RedactionPass {
|
|
13
|
+
kind: string;
|
|
14
|
+
confidence: RedactionConfidence;
|
|
15
|
+
marker: string;
|
|
16
|
+
re: RegExp;
|
|
17
|
+
replace: string | ((match: string, ...groups: string[]) => string);
|
|
18
|
+
}
|
|
19
|
+
export declare function runRedactionPasses(input: string, passes: readonly RedactionPass[], report?: RedactionReport): string;
|
|
20
|
+
export declare const SECRET_PASSES: readonly RedactionPass[];
|
|
21
|
+
export declare function scrubSecrets(s: string, report?: RedactionReport): string;
|
|
2
22
|
export declare function primaryActivityArg(args: unknown): string | undefined;
|
package/dist/core/arg-summary.js
CHANGED
|
@@ -1,24 +1,71 @@
|
|
|
1
1
|
const ACTIVITY_ARG_MAX = 80;
|
|
2
2
|
const SENSITIVE_KEY = /token|secret|key|password|passwd|credential|auth/i;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
function mapBackOnePass(edits, pos) {
|
|
4
|
+
let delta = 0;
|
|
5
|
+
for (const e of edits) {
|
|
6
|
+
const outStart = e.at + delta;
|
|
7
|
+
if (pos < outStart)
|
|
8
|
+
return pos - delta;
|
|
9
|
+
const outEnd = outStart + e.insertedLen;
|
|
10
|
+
if (pos < outEnd)
|
|
11
|
+
return e.at;
|
|
12
|
+
delta += e.insertedLen - e.removedLen;
|
|
13
|
+
}
|
|
14
|
+
return pos - delta;
|
|
15
|
+
}
|
|
16
|
+
const PREEXISTING_MARKER_RE = /\[redacted(?:-[a-z]+)?\]/g;
|
|
17
|
+
export function runRedactionPasses(input, passes, report) {
|
|
18
|
+
if (report !== undefined && report.preexistingMarkers === undefined) {
|
|
19
|
+
report.preexistingMarkers = input.match(PREEXISTING_MARKER_RE)?.length ?? 0;
|
|
20
|
+
}
|
|
21
|
+
const batches = [];
|
|
22
|
+
let cur = input;
|
|
23
|
+
for (const pass of passes) {
|
|
24
|
+
const edits = [];
|
|
25
|
+
cur = cur.replace(pass.re, (...args) => {
|
|
26
|
+
const match = args[0];
|
|
27
|
+
const offset = args[args.length - 2];
|
|
28
|
+
const groups = args.slice(1, -2);
|
|
29
|
+
const inserted = typeof pass.replace === "string"
|
|
30
|
+
? pass.replace.replace(/\$(\d)/g, (_m, d) => groups[Number(d) - 1] ?? "")
|
|
31
|
+
: pass.replace(match, ...groups);
|
|
32
|
+
if (inserted !== match) {
|
|
33
|
+
if (report !== undefined) {
|
|
34
|
+
let s0 = offset;
|
|
35
|
+
let e0 = offset + match.length;
|
|
36
|
+
for (let i = batches.length - 1; i >= 0; i--) {
|
|
37
|
+
s0 = mapBackOnePass(batches[i], s0);
|
|
38
|
+
e0 = mapBackOnePass(batches[i], e0);
|
|
39
|
+
}
|
|
40
|
+
report.findings.push({ kind: pass.kind, confidence: pass.confidence, span: [s0, e0], marker: pass.marker });
|
|
41
|
+
}
|
|
42
|
+
edits.push({ at: offset, removedLen: match.length, insertedLen: inserted.length });
|
|
43
|
+
}
|
|
44
|
+
return inserted;
|
|
45
|
+
});
|
|
46
|
+
batches.push(edits);
|
|
47
|
+
}
|
|
48
|
+
return cur;
|
|
49
|
+
}
|
|
50
|
+
export const SECRET_PASSES = [
|
|
51
|
+
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", re: /(?<![A-Za-z0-9])(?:sk|pk|rk|gh[opsur])[-_][A-Za-z0-9_-]{8,}/g, replace: "[redacted]" },
|
|
52
|
+
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", re: /(?<![A-Za-z0-9])AIza[A-Za-z0-9_-]{20,}/g, replace: "[redacted]" },
|
|
53
|
+
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", re: /(?<![A-Za-z0-9])xox[baprs]-[A-Za-z0-9-]{10,}/g, replace: "[redacted]" },
|
|
54
|
+
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", re: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{12,}/g, replace: "[redacted]" },
|
|
55
|
+
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", re: /(?<![A-Za-z0-9])hf_[A-Za-z0-9]{20,}/g, replace: "[redacted]" },
|
|
56
|
+
{ kind: "jwt", confidence: "high", marker: "[redacted]", re: /(?<![A-Za-z0-9])eyJ[A-Za-z0-9._-]{20,}/g, replace: "[redacted]" },
|
|
57
|
+
{ kind: "private-key-block", confidence: "high", marker: "[redacted]", re: /-----BEGIN[ A-Z]*PRIVATE KEY-----[\s\S]*?(?:-----END[ A-Z]*PRIVATE KEY-----|$)/g, replace: "[redacted]" },
|
|
58
|
+
{ kind: "bearer-token", confidence: "high", marker: "[redacted]", re: /(?<![A-Za-z0-9])Bearer\s+[A-Za-z0-9._~+/-]{8,}=*/gi, replace: "[redacted]" },
|
|
12
59
|
{
|
|
60
|
+
kind: "keyword-value",
|
|
61
|
+
confidence: "medium",
|
|
62
|
+
marker: "[redacted]",
|
|
13
63
|
re: /(?<![A-Za-z0-9])((?:token|secret|key|password|passwd|credential|authorization)["']?\s*[=:]\s*["']?)[^\s"';|&]{4,}/gi,
|
|
14
64
|
replace: "$1[redacted]",
|
|
15
65
|
},
|
|
16
66
|
];
|
|
17
|
-
export function scrubSecrets(s) {
|
|
18
|
-
|
|
19
|
-
for (const { re, replace } of SECRET_PATTERNS)
|
|
20
|
-
out = out.replace(re, replace);
|
|
21
|
-
return out;
|
|
67
|
+
export function scrubSecrets(s, report) {
|
|
68
|
+
return runRedactionPasses(s, SECRET_PASSES, report);
|
|
22
69
|
}
|
|
23
70
|
function truncCodePoints(s) {
|
|
24
71
|
const cp = Array.from(s);
|
|
@@ -23,6 +23,7 @@ export interface CompactionWindowSafetyInfo {
|
|
|
23
23
|
export declare const STALE_ANCHOR_STRUCTURAL_MARGIN = 2;
|
|
24
24
|
export declare function sanitizeCompactionSettings(settings: CompactionSettings, contextWindow: number | undefined): CompactionSettings;
|
|
25
25
|
export interface MaybeCompactOptions {
|
|
26
|
+
onNotifyError?: (failure: import("./safe-notify.js").SafeNotifyFailure) => void;
|
|
26
27
|
session: Session;
|
|
27
28
|
epochDeclaredSections?: import("../prompt-assembly/epoch.js").EpochDeclaredSections;
|
|
28
29
|
centerAdoption?: {
|
|
@@ -97,7 +97,7 @@ export async function maybeCompact(opts) {
|
|
|
97
97
|
return { contextUsage, compacted: false, noop: true };
|
|
98
98
|
}
|
|
99
99
|
const trigger = opts.trigger ?? "auto";
|
|
100
|
-
const notifier = createSafeNotifier();
|
|
100
|
+
const notifier = createSafeNotifier(opts.onNotifyError !== undefined ? { onError: opts.onNotifyError } : undefined);
|
|
101
101
|
let hookInstructions;
|
|
102
102
|
if (opts.preCompact) {
|
|
103
103
|
let pre;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { canonicalizeTarget, writeTargetPath } from "../tools/fs/safety.js";
|
|
2
|
-
import { canonicalToolName } from "./tool-name-aliases.js";
|
|
3
2
|
import { PATH_WRITE_TOOLS, isWithin } from "./runner/session-rule-policy.js";
|
|
4
3
|
const ask = (message) => ({ action: "ask", message, decisionReason: "rule" });
|
|
5
4
|
export function createFsWriteGatePolicy(opts) {
|
|
6
5
|
const { env, rootPath, defaultWrite } = opts;
|
|
7
|
-
const gated = new Set([...PATH_WRITE_TOOLS, "NotebookEdit"]
|
|
6
|
+
const gated = new Set([...PATH_WRITE_TOOLS, "NotebookEdit"]);
|
|
8
7
|
const acceptDirs = opts.acceptDirs && opts.acceptDirs.length > 0 ? opts.acceptDirs : undefined;
|
|
9
8
|
const exemptDirs = opts.exemptDirs && opts.exemptDirs.length > 0 ? opts.exemptDirs : undefined;
|
|
10
9
|
return {
|
|
11
10
|
async check(req, signal) {
|
|
12
|
-
const canonical =
|
|
11
|
+
const canonical = req.toolName;
|
|
13
12
|
if (!gated.has(canonical))
|
|
14
13
|
return { action: "allow" };
|
|
15
14
|
const path = writeTargetPath(canonical, req.args);
|
package/dist/core/hooks.d.ts
CHANGED
package/dist/core/hooks.js
CHANGED
|
@@ -59,7 +59,7 @@ export async function runToolGate(input) {
|
|
|
59
59
|
let currentInput = event.input;
|
|
60
60
|
const preToolContext = [];
|
|
61
61
|
let hookAsk;
|
|
62
|
-
const notifier = createSafeNotifier();
|
|
62
|
+
const notifier = createSafeNotifier(input.onNotifyError !== undefined ? { onError: input.onNotifyError } : undefined);
|
|
63
63
|
if (preToolUse) {
|
|
64
64
|
let r;
|
|
65
65
|
try {
|
package/dist/core/mcp.js
CHANGED
|
@@ -756,9 +756,6 @@ function applyCallerAxisOverride(name, hint, override) {
|
|
|
756
756
|
const LIST_MCP_RESOURCES = "ListMcpResourcesTool";
|
|
757
757
|
const READ_MCP_RESOURCE = "ReadMcpResourceTool";
|
|
758
758
|
const READ_MCP_RESOURCE_DIR = "ReadMcpResourceDirTool";
|
|
759
|
-
const LEGACY_LIST_MCP_RESOURCES = "ListMcpResources";
|
|
760
|
-
const LEGACY_READ_MCP_RESOURCE = "ReadMcpResource";
|
|
761
|
-
const LEGACY_READ_MCP_RESOURCE_DIR = "ReadMcpResourceDir";
|
|
762
759
|
const MCP_SKILLS_EXTENSION = "io.modelcontextprotocol/skills";
|
|
763
760
|
const MAX_DIR_READ_PAGES = 20;
|
|
764
761
|
const DIR_READ_NOT_A_DIRECTORY_RE = /not a directory|isn'?t a directory|not a folder/i;
|
|
@@ -843,7 +840,6 @@ function buildResourceTools(resourceServers) {
|
|
|
843
840
|
if (listable.length > 0) {
|
|
844
841
|
tools.push({
|
|
845
842
|
name: LIST_MCP_RESOURCES,
|
|
846
|
-
aliases: [LEGACY_LIST_MCP_RESOURCES],
|
|
847
843
|
description: "List the resources available from connected MCP servers (uri / name / description). Pass `server` to limit " +
|
|
848
844
|
"to one server, or omit it to list across all. Resource metadata is external/untrusted data.",
|
|
849
845
|
label: LIST_MCP_RESOURCES,
|
|
@@ -903,7 +899,6 @@ function buildResourceTools(resourceServers) {
|
|
|
903
899
|
if (readable.length > 0) {
|
|
904
900
|
tools.push({
|
|
905
901
|
name: READ_MCP_RESOURCE,
|
|
906
|
-
aliases: [LEGACY_READ_MCP_RESOURCE],
|
|
907
902
|
description: "Read a specific MCP resource by `server` + `uri` (from ListMcpResourcesTool). Its content is external/untrusted data.",
|
|
908
903
|
label: READ_MCP_RESOURCE,
|
|
909
904
|
executionMode: "parallel",
|
|
@@ -953,7 +948,6 @@ function buildResourceTools(resourceServers) {
|
|
|
953
948
|
if (listable.length > 0) {
|
|
954
949
|
tools.push({
|
|
955
950
|
name: READ_MCP_RESOURCE_DIR,
|
|
956
|
-
aliases: [LEGACY_READ_MCP_RESOURCE_DIR],
|
|
957
951
|
description: "List the MCP resources UNDER a directory `uri` on `server` — its child resources (those whose uri is " +
|
|
958
952
|
"nested below it; subdirectories carry mimeType \"inode/directory\"). Use it to browse a hierarchical " +
|
|
959
953
|
"resource namespace after ListMcpResourcesTool. Resource metadata is external/untrusted data.",
|