@sema-agent/core 5.56.0 → 5.58.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 +122 -0
- package/dist/agents/cascade.d.ts +1 -1
- package/dist/agents/cumulative-stats.d.ts +1 -1
- package/dist/agents/observer.d.ts +2 -2
- package/dist/agents/peer-admission.d.ts +1 -1
- package/dist/agents/retain-ledger.d.ts +2 -2
- package/dist/agents/roster-store.d.ts +8 -8
- package/dist/agents/send-message-tool.d.ts +13 -2
- package/dist/agents/send-message-tool.js +34 -12
- package/dist/agents/subagent-steps.d.ts +1 -1
- package/dist/agents/subagent.d.ts +13 -13
- package/dist/agents/team.d.ts +15 -6
- package/dist/agents/team.js +1 -0
- package/dist/agents/tool-filter.d.ts +2 -2
- package/dist/agents/verify.d.ts +1 -1
- package/dist/bench/metrics.d.ts +35 -35
- package/dist/brain/anthropic.js +15 -5
- package/dist/brain/circuit-breaker.js +2 -1
- package/dist/brain/degrading.d.ts +1 -1
- package/dist/brain/degrading.js +4 -1
- package/dist/brain/errors.d.ts +3 -3
- package/dist/brain/failover.js +16 -1
- package/dist/brain/open-responses.js +15 -5
- package/dist/brain/openai.js +16 -5
- package/dist/brain/reasoning.d.ts +2 -2
- package/dist/brain/repetition.d.ts +1 -1
- package/dist/brain/request-params.d.ts +30 -27
- package/dist/brain/request-params.js +1 -7
- package/dist/brain/route-adjudicator.d.ts +190 -0
- package/dist/brain/route-adjudicator.js +189 -0
- package/dist/brain/route-conformance.d.ts +55 -0
- package/dist/brain/route-conformance.js +136 -0
- package/dist/brain/routing.js +8 -3
- package/dist/brain/status-sink.d.ts +2 -2
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/config/catalog.d.ts +5 -5
- package/dist/core/arg-summary.d.ts +4 -4
- package/dist/core/ask-class.d.ts +2 -2
- package/dist/core/ask-question.d.ts +1 -1
- package/dist/core/auto-compaction.d.ts +15 -15
- package/dist/core/auto-mode.d.ts +5 -5
- package/dist/core/background-agent-store.d.ts +20 -20
- package/dist/core/background-shell.d.ts +4 -4
- package/dist/core/checkpoint-store.d.ts +35 -27
- package/dist/core/context-edit.d.ts +1 -1
- package/dist/core/context-guard.d.ts +1 -1
- package/dist/core/exec-output-tail.d.ts +6 -6
- package/dist/core/file-snapshot-store.d.ts +8 -8
- package/dist/core/git-worktree-env.d.ts +3 -3
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/hooks.d.ts +73 -33
- package/dist/core/hooks.js +87 -25
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/locked-config.d.ts +1 -1
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mailbox-store.d.ts +1 -1
- package/dist/core/mcp.d.ts +3 -3
- package/dist/core/mcp.js +4 -4
- package/dist/core/memory-engine/consolidation-driver.d.ts +207 -0
- package/dist/core/memory-engine/consolidation-driver.js +378 -0
- package/dist/core/memory-engine/consolidation.d.ts +46 -2
- package/dist/core/memory-engine/consolidation.js +1 -0
- package/dist/core/memory-engine/data-plane.d.ts +1 -1
- package/dist/core/memory-engine/distiller.d.ts +550 -0
- package/dist/core/memory-engine/distiller.js +598 -0
- package/dist/core/memory-engine/dual-root.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +62 -8
- package/dist/core/memory-engine/engine.js +40 -4
- package/dist/core/memory-engine/file-backend.d.ts +1 -1
- package/dist/core/memory-engine/index.d.ts +4 -2
- package/dist/core/memory-engine/index.js +4 -2
- package/dist/core/memory-engine/origin-clearance.d.ts +1 -1
- package/dist/core/memory-engine/scope-contract.d.ts +4 -4
- package/dist/core/memory-engine/sync-client.d.ts +16 -16
- package/dist/core/memory-engine/sync.d.ts +4 -4
- package/dist/core/memory-recall.d.ts +1 -1
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/permission-rule-consent.d.ts +230 -36
- package/dist/core/permission-rule-consent.js +258 -54
- package/dist/core/permission-rule-model.d.ts +295 -97
- package/dist/core/permission-rule-model.js +132 -41
- package/dist/core/permission-rules.d.ts +9 -9
- package/dist/core/remote-env.d.ts +8 -8
- package/dist/core/roles.d.ts +3 -3
- package/dist/core/roles.js +1 -0
- package/dist/core/runner/assemble-result.d.ts +2 -2
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/memory-consolidation-driver.d.ts +49 -0
- package/dist/core/runner/memory-consolidation-driver.js +60 -0
- package/dist/core/runner/memory-consolidation.d.ts +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +3 -3
- package/dist/core/runner/prepare-task.d.ts +21 -21
- package/dist/core/runner/prepare-task.js +54 -18
- package/dist/core/runner/prepare-workspace-restore.d.ts +2 -2
- package/dist/core/runner/runtask.d.ts +15 -12
- package/dist/core/runner/runtask.js +48 -0
- package/dist/core/runner/session-rule-policy.d.ts +1 -1
- package/dist/core/runner/teardown-bounded.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +11 -11
- package/dist/core/scheduler.d.ts +10 -5
- package/dist/core/secret-env.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/session-policy-store.d.ts +2 -2
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +3 -3
- package/dist/core/session.d.ts +1 -1
- package/dist/core/shutdown-debug.d.ts +2 -2
- package/dist/core/side-query.d.ts +14 -7
- package/dist/core/spec-contract.d.ts +1 -1
- package/dist/core/store-contracts/contract-harness.d.ts +2 -2
- package/dist/core/store-contracts/contract-kit-version.d.ts +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +1 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +1 -1
- package/dist/core/task-notification.d.ts +5 -5
- package/dist/core/task-registry-agent.d.ts +12 -12
- package/dist/core/task-registry-monitor.d.ts +1 -1
- package/dist/core/task-registry-shared.d.ts +41 -41
- package/dist/core/task-registry.d.ts +12 -12
- package/dist/core/tool-detach.d.ts +2 -2
- package/dist/core/tool-errors.d.ts +3 -3
- package/dist/core/tool-policy.d.ts +55 -28
- package/dist/core/tool-result-budget.d.ts +1 -1
- package/dist/core/tool-result-store.d.ts +2 -2
- package/dist/core/tools.d.ts +1 -1
- package/dist/core/trace.d.ts +26 -23
- package/dist/core/types.d.ts +155 -70
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +7 -7
- package/dist/core/wiring-manifest.d.ts +5 -5
- package/dist/core/workflow-journal-store.d.ts +14 -14
- package/dist/core/workflow-run-store-contract.d.ts +1 -1
- package/dist/core/workflow-run-store-contract.js +1 -1
- package/dist/core/workflow-run-store.d.ts +4 -4
- package/dist/engine/compaction/compaction.d.ts +3 -3
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/execution-env/kill-tree.d.ts +1 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +8 -8
- package/dist/engine/harness/agent-harness.d.ts +6 -6
- package/dist/engine/harness/agent-harness.js +26 -1
- package/dist/engine/harness/messages.d.ts +1 -1
- package/dist/engine/harness/types.d.ts +15 -11
- package/dist/engine/llm/types.d.ts +79 -14
- package/dist/engine/loop/agent-loop.d.ts +3 -3
- package/dist/engine/loop/types.d.ts +4 -4
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.d.ts +1 -1
- package/dist/engine/session/log-digest.d.ts +1 -1
- package/dist/engine/session/memory-repo.d.ts +2 -2
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/fixtures/index.d.ts +4 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.js +5 -2
- package/dist/internal/llm.d.ts +1 -1
- package/dist/orchestration/goal.d.ts +1 -1
- package/dist/orchestration/run-spec.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +12 -12
- package/dist/orchestration/workflow-governance.d.ts +4 -4
- package/dist/orchestration/workflow-observe.d.ts +1 -1
- package/dist/orchestration/workflow-script-runner.d.ts +1 -1
- package/dist/orchestration/workflow-script-store.d.ts +9 -9
- package/dist/orchestration/workflow-size-guideline.d.ts +1 -1
- package/dist/orchestration/workflow-types.d.ts +5 -5
- package/dist/orchestration/workflow.d.ts +10 -10
- package/dist/prompt-assembly/artifact-store.d.ts +1 -1
- package/dist/prompt-assembly/artifact.d.ts +1 -1
- package/dist/prompt-assembly/assemble.d.ts +1 -1
- package/dist/prompt-assembly/composer.d.ts +2 -2
- package/dist/prompt-assembly/epoch.d.ts +2 -2
- package/dist/prompt-assembly/event-registry.d.ts +1 -1
- package/dist/prompt-assembly/explain.d.ts +3 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +1 -1
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -4
- package/dist/prompt-assembly/types.d.ts +12 -12
- package/dist/prompts/coordinator.d.ts +1 -1
- package/dist/prompts/default.d.ts +10 -10
- package/dist/prompts/default.js +2 -0
- package/dist/prompts/simple-sections.d.ts +3 -3
- package/dist/prompts/supervisor.d.ts +2 -2
- package/dist/scenarios/full-body.d.ts +3 -3
- package/dist/scenarios/scenario-registry.d.ts +6 -2
- package/dist/scenarios/scenario-registry.js +4 -2
- package/dist/stores/cc/sidecar-transcript.d.ts +3 -3
- package/dist/stores/file/fs-atomic.d.ts +2 -2
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/session-store.d.ts +2 -2
- package/dist/stores/file/workflow-journal-store.d.ts +4 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/encoding.d.ts +4 -4
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-pdf.d.ts +1 -1
- package/dist/tools/fs/fs-shared.d.ts +6 -6
- package/dist/tools/fs/index.d.ts +2 -2
- package/dist/tools/fs/index.js +8 -1
- package/dist/tools/fs/notebook.d.ts +1 -1
- package/dist/tools/fs/pdf.d.ts +1 -1
- package/dist/tools/fs/read-deny.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +2 -2
- package/dist/tools/monitor.d.ts +3 -3
- package/dist/tools/scheduler-tools.js +28 -6
- package/dist/tools/task-list.d.ts +2 -2
- package/dist/tools/web.d.ts +19 -4
- package/dist/tools/web.js +8 -2
- package/dist/tools/worktree.d.ts +5 -5
- package/dist/tools/worktree.js +2 -2
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +74 -3
|
@@ -157,7 +157,7 @@ export declare function matchSegmentPatterns(path: string, compiled: readonly Co
|
|
|
157
157
|
readonly aliasResolved?: boolean;
|
|
158
158
|
}): string | null;
|
|
159
159
|
/**
|
|
160
|
-
*
|
|
160
|
+
* the PURE validation/canonicality predicate over a PERSISTED deny entry (checkpoint v9
|
|
161
161
|
* face section), for the resume pre-CAS ladder: it must refuse BEFORE the approval CAS everything
|
|
162
162
|
* {@link compileReadDeny} would throw on AFTER it (a post-CAS compile throw consumes the human's
|
|
163
163
|
* approval and strands the row), plus non-canonical spellings (normalizeEntry canonicalizes at every
|
|
@@ -14,13 +14,13 @@ import type { ExecutionEnv } from "../../internal/harness-types.js";
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function fileArgPath(args: unknown): string | undefined;
|
|
16
16
|
/**
|
|
17
|
-
* The WRITE TARGET of a path-confinable write call, tool-aware (
|
|
17
|
+
* The WRITE TARGET of a path-confinable write call, tool-aware (b — single source for every
|
|
18
18
|
* gate that confines a write target, same discipline as {@link fileArgPath} above):
|
|
19
19
|
*
|
|
20
20
|
* · canonical `NotebookEdit` → `notebook_path` FIRST, `file_path`/`path` only as fallback. The tool
|
|
21
21
|
* itself writes `notebook_path`; its schema tolerates extra keys, so a stray/decoy `file_path` on a
|
|
22
22
|
* NotebookEdit call must never become the judged target while the real write lands elsewhere
|
|
23
|
-
* (a gate that read `file_path` first would confine the decoy — the
|
|
23
|
+
* (a gate that read `file_path` first would confine the decoy — the hole).
|
|
24
24
|
* · every other tool → `file_path`/`path` first ({@link fileArgPath}), `notebook_path` as the
|
|
25
25
|
* historical fallback (unchanged behavior for the pre-existing gate callers).
|
|
26
26
|
*
|
|
@@ -63,7 +63,7 @@ export interface ReadEntry {
|
|
|
63
63
|
start: number;
|
|
64
64
|
end: number;
|
|
65
65
|
};
|
|
66
|
-
/** Millisecond timestamp of the last read/write-back that recorded this entry (
|
|
66
|
+
/** Millisecond timestamp of the last read/write-back that recorded this entry (
|
|
67
67
|
* 2026-07-03, compact re-read parity: the post-compaction attachment picks the most RECENTLY
|
|
68
68
|
* read files — CC sorts readFileState by timestamp). Optional/additive: undefined (an entry
|
|
69
69
|
* seeded from an older checkpoint) sorts last, never breaks. */
|
|
@@ -125,7 +125,7 @@ export interface FsViolation {
|
|
|
125
125
|
*/
|
|
126
126
|
export declare function isAbsolutePathForm(p: string): boolean;
|
|
127
127
|
/**
|
|
128
|
-
* Windows-FAMILY spelling of a path (
|
|
128
|
+
* Windows-FAMILY spelling of a path (extracted here so {@link canonicalizeTarget} judges
|
|
129
129
|
* the UNC family by the same rule): drive-rooted (`C:\…`/`C:/…`), UNC-backslash (`\\host\share`), or a
|
|
130
130
|
* RELATIVE path using `\` as its separator. Never keyed on `process.platform` — the exec env may be remote
|
|
131
131
|
* and of the other family than the host. A `/`-rooted path is POSIX-form even when a file NAME inside it
|
|
@@ -184,7 +184,7 @@ export declare function hasBinaryExtension(path: string): boolean;
|
|
|
184
184
|
export declare function imageMimeForRead(path: string): string | undefined;
|
|
185
185
|
/** Verify the raw bytes actually ARE the image format the extension claims (magic-number sniff). Extension alone
|
|
186
186
|
* is forgeable: a `.png` holding text / an empty file / a truncated blob would otherwise become a malformed
|
|
187
|
-
* `ImageContent` that makes the NEXT provider request fail (400). Pure — no I/O. (batch-C
|
|
187
|
+
* `ImageContent` that makes the NEXT provider request fail (400). Pure — no I/O. (batch-C.) */
|
|
188
188
|
export declare function imageMagicMatches(bytes: Uint8Array, mimeType: string): boolean;
|
|
189
189
|
/** One contiguous byte pattern that must appear at a fixed offset for its signature to match. */
|
|
190
190
|
export interface BinaryMagicSegment {
|
|
@@ -349,8 +349,8 @@ export declare const PATH_NOT_IN_ROOT_ESCAPE_HINT = "(This boundary applies to t
|
|
|
349
349
|
* Message is CC 2.1.198 live-verbatim (all-tools-live-probe 2026-07-08 §2.1/§3.1/§5.1 — one message for
|
|
350
350
|
* Edit/Write/NotebookEdit: "before writing to it", not the old sema "before editing").
|
|
351
351
|
*
|
|
352
|
-
* RB-200 F2(
|
|
353
|
-
* `!p || p.isPartialView
|
|
352
|
+
* RB-200 F2 (CC 220 corpus-confirmed, @367198/@367671 — Edit and Write spell the read gate identically,
|
|
353
|
+
* `!p || p.isPartialView`): an AUTO-TRUNCATED read (the model asked for the
|
|
354
354
|
* file by default, no explicit offset/limit, and the token cap cut it anyway — {@link ReadEntry.isPartialView})
|
|
355
355
|
* used to satisfy this gate exactly like a full read (`state.has(key)` alone was the whole check) — the
|
|
356
356
|
* model could Write (full overwrite) or Edit a file having genuinely seen only its first page, silently
|
|
@@ -372,7 +372,7 @@ export declare function requireRead(state: ReadFileState, key: string): FsViolat
|
|
|
372
372
|
*/
|
|
373
373
|
export declare const OVERSIZE_READ_ESCAPE_HINT = "(This file is over the Read tool's whole-file byte cap, so a default Read is refused \u2014 read it in slices with explicit offset/limit to satisfy the read-first rule, or inspect/transform it with bash (e.g. `sed -n`, `grep`) instead.)";
|
|
374
374
|
/**
|
|
375
|
-
* RB-264 N1 (
|
|
375
|
+
* RB-264 N1 (repro `notebookedit-tool-read-gate-deadlock` assertion A.c2) —
|
|
376
376
|
* the escape-hatch parenthetical for the OTHER shape of the read-before-edit refusal: the file was read,
|
|
377
377
|
* but the read was AUTO-PAGINATED by the output token cap ({@link ReadEntry.isPartialView}), so only the
|
|
378
378
|
* first page was ever seen. The oversize branch above has named its escape route since the fidelity
|
|
@@ -384,7 +384,7 @@ export declare const OVERSIZE_READ_ESCAPE_HINT = "(This file is over the Read to
|
|
|
384
384
|
*/
|
|
385
385
|
export declare const PARTIAL_VIEW_READ_ESCAPE_HINT = "(Your last Read of this file returned only a PARTIAL view \u2014 the output token cap paginated it, so a default Read will keep returning the same page. Re-read it with explicit offset/limit (start from the page marker's next-page hint) until you have seen the part you are about to change; an explicit slice that fits satisfies the read-first rule. Or inspect/transform it with bash (e.g. `sed -n`, `grep`) instead.)";
|
|
386
386
|
/**
|
|
387
|
-
* RB-264 ⑥W1
|
|
387
|
+
* RB-264 ⑥W1 — the escape-hatch parenthetical for the ONE shape of the
|
|
388
388
|
* read-first deadlock that nothing observable diagnoses: a file the Read tool REFUSES (binary /
|
|
389
389
|
* BOM-less UTF-16 / unknown encoding) can never satisfy read-before-write, and — unlike the oversize
|
|
390
390
|
* and partial-view shapes — leaves no trace the refusal renderer can stat for. It is therefore the
|
|
@@ -95,8 +95,8 @@ export declare function gitignoreMatcher(content: string): (rel: string, isDir:
|
|
|
95
95
|
/** Build the combined ignore predicate (ignore-set ∪ .gitignore) for a JS-fallback walk.
|
|
96
96
|
* Exported so repo-map (design/72 §1) walks with the SAME ignore semantics as grep/glob.
|
|
97
97
|
*
|
|
98
|
-
* RB-200 F1(
|
|
99
|
-
* "!"+N)
|
|
98
|
+
* RB-200 F1 (CC 220 corpus-confirmed, @368590-368592 Grep `T=["--hidden"]; for(N of Ok_) T.push("--glob",
|
|
99
|
+
* "!"+N)`, @367957/367959-367965 Glob `CLAUDE_CODE_GLOB_HIDDEN` defaults to true and also passes `--hidden`): CC's own
|
|
100
100
|
* "keep it quiet" posture is NOT "every dot-prefixed name is invisible" — it's `--hidden` (show
|
|
101
101
|
* everything dot-prefixed) plus an explicit VCS-directory exclusion list ({@link DEFAULT_IGNORE_DIRS}).
|
|
102
102
|
* The blanket rule this function used to apply here (`base.startsWith(".")`) instead made EVERY hidden
|
package/dist/tools/monitor.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* design/135 G2 (审计
|
|
2
|
+
* design/135 G2 (审计 🔴) — the `Monitor` tool: run a shell command in the background and watch its
|
|
3
3
|
* stdout as a stream of NOTIFICATION EVENTS (the自主循环 core piece: "watch this and tell me when something
|
|
4
4
|
* happens" without burning poll turns).
|
|
5
5
|
*
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
* TaskNotificationPayload lane at "later" priority (delivered at the next turn boundary like every
|
|
18
18
|
* notification — ruled 2026-08-05; consecutive frames drain as one boundary batch, and a backlog past
|
|
19
19
|
* the engine-note cap parks per session, so a chatty watcher cannot monopolize the run's boundaries).
|
|
20
|
-
*
|
|
20
|
+
* (1.257): events born BETWEEN turns (run torn down / harness idle — the long-watch main case)
|
|
21
21
|
* are no longer lost: the Runner parks them per session (bounded, drop-disclosing) and the session's next
|
|
22
22
|
* run redelivers them through the same notification lane at its first turn boundary.
|
|
23
|
-
*
|
|
23
|
+
* (CC parity): a monitor's lifetime = min(timeout_ms, process exit, TaskStop); a `persistent`
|
|
24
24
|
* one is SESSION-anchored (reaped at session release). NEITHER is run-anchored: the run teardown leaves an
|
|
25
25
|
* in-window non-persistent watch alive (process on the dispose except-list, watcher ticking, row kept), so
|
|
26
26
|
* cross-turn watching — CC's main Monitor use case — works with the default persistent:false too; its
|
|
@@ -396,10 +396,19 @@ Only use minute 0 or 30 when the user names that exact time and clearly means it
|
|
|
396
396
|
wakeupChain = next.then(() => undefined, () => undefined);
|
|
397
397
|
return next;
|
|
398
398
|
};
|
|
399
|
+
const wakeupMountNote = sched.schedulerCapabilities.supportsSessionWakeup === false
|
|
400
|
+
? `
|
|
401
|
+
|
|
402
|
+
MOUNT NOTE: this host has no resident wakeup leg, so ${SCHEDULE_WAKEUP_TOOL_NAME} refuses every scheduling call here — do not plan a self-paced loop around it (\`stop: true\` still works).`
|
|
403
|
+
: sched.schedulerCapabilities.supportsSessionLifetime === true
|
|
404
|
+
? ""
|
|
405
|
+
: `
|
|
406
|
+
|
|
407
|
+
MOUNT NOTE: this host does not vouch for session-scoped scheduling, so a wakeup scheduled here is PERSISTENT — contrary to the paragraph above, it can outlive this session instead of ending with it. End the loop explicitly with \`stop: true\` when the work is done; do not rely on the session ending to cancel it.`;
|
|
399
408
|
const scheduleWakeup = defineTool({
|
|
400
409
|
name: SCHEDULE_WAKEUP_TOOL_NAME,
|
|
401
410
|
contract: { contractId: "core.schedule_wakeup@1", implementationRevision: "1" },
|
|
402
|
-
description: SCHEDULE_WAKEUP_PROMPT
|
|
411
|
+
description: `${SCHEDULE_WAKEUP_PROMPT}${wakeupMountNote}`,
|
|
403
412
|
parameters: Type.Object({
|
|
404
413
|
delaySeconds: Type.Optional(Type.Number({
|
|
405
414
|
description: "Seconds from now to wake up. Clamped to [60, 3600] by the runtime. Required unless `stop` is true.",
|
|
@@ -433,20 +442,33 @@ Only use minute 0 or 30 when the user names that exact time and clearly means it
|
|
|
433
442
|
if (sched.schedulerCapabilities.supportsSessionWakeup === false) {
|
|
434
443
|
return errorResult(`Error (${SCHEDULE_WAKEUP_TOOL_NAME}): this environment has no resident scheduler that can honor a session wakeup — the wakeup would never fire. Wait in the foreground instead, or start the work in a self-detaching form.`);
|
|
435
444
|
}
|
|
445
|
+
const sessionReapVouched = sched.schedulerCapabilities.supportsSessionLifetime === true;
|
|
436
446
|
const clampedDelaySeconds = Math.min(3600, Math.max(60, Math.round(a.delaySeconds)));
|
|
437
447
|
const wasClamped = clampedDelaySeconds !== a.delaySeconds;
|
|
438
448
|
const pending = await listPendingWakeups();
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
const r = await sched.schedule({
|
|
449
|
+
const cancelledCount = "err" in pending ? 0 : await cancelWakeups(pending.ids);
|
|
450
|
+
const cleanupIncomplete = "err" in pending || cancelledCount < pending.ids.length;
|
|
451
|
+
const r = await sched.schedule({
|
|
452
|
+
prompt: a.prompt,
|
|
453
|
+
when: { kind: "delay", delaySec: clampedDelaySeconds },
|
|
454
|
+
label: WAKEUP_LABEL,
|
|
455
|
+
mode: "session-wakeup",
|
|
456
|
+
...(sessionReapVouched ? { lifetime: "session" } : {}),
|
|
457
|
+
}, sessionCtx);
|
|
442
458
|
if (!r.ok)
|
|
443
459
|
return errorResult(`Error (${SCHEDULE_WAKEUP_TOOL_NAME}): ${r.error.message}`);
|
|
444
460
|
const scheduledFor = Date.now() + clampedDelaySeconds * 1000;
|
|
445
461
|
const hhmmss = new Date(scheduledFor).toTimeString().slice(0, 8);
|
|
446
462
|
const clampNote = wasClamped ? ` (clamped to ${clampedDelaySeconds}s from your requested value)` : "";
|
|
463
|
+
const cleanupNote = cleanupIncomplete
|
|
464
|
+
? " Warning: the previously pending wakeup(s) for this session could not all be listed or cancelled, so MORE THAN ONE wakeup may now be armed (you would be re-invoked twice). Call this tool with `stop: true` and then re-schedule to get back to a single one."
|
|
465
|
+
: "";
|
|
466
|
+
const reapNote = sessionReapVouched
|
|
467
|
+
? ""
|
|
468
|
+
: " Note: this scheduler does not vouch for session-lifetime reap, so this wakeup is scheduled as a persistent one and may outlive the session — end the loop explicitly with `stop: true` rather than relying on the session ending.";
|
|
447
469
|
return {
|
|
448
|
-
content: `Next wakeup scheduled for ${hhmmss} (in ${clampedDelaySeconds}s)${clampNote}. Nothing more to do this turn — the harness re-invokes you when the wakeup fires or a task-notification arrives
|
|
449
|
-
details: { type: "schedule-wakeup", stopped: false, scheduledFor, clampedDelaySeconds, wasClamped },
|
|
470
|
+
content: `Next wakeup scheduled for ${hhmmss} (in ${clampedDelaySeconds}s)${clampNote}. Nothing more to do this turn — the harness re-invokes you when the wakeup fires or a task-notification arrives.${reapNote}${cleanupNote}`,
|
|
471
|
+
details: { type: "schedule-wakeup", stopped: false, scheduledFor, clampedDelaySeconds, wasClamped, reason: a.reason },
|
|
450
472
|
};
|
|
451
473
|
}),
|
|
452
474
|
});
|
|
@@ -62,7 +62,7 @@ export interface TaskListStore {
|
|
|
62
62
|
delete(id: string): boolean | Promise<boolean>;
|
|
63
63
|
list(): TaskListItem[] | Promise<TaskListItem[]>;
|
|
64
64
|
allocateId(): string | Promise<string>;
|
|
65
|
-
/**
|
|
65
|
+
/** the transaction boundary for adapters whose backend outlives one wrapper
|
|
66
66
|
* instance (pg, shared files): when present, the tools run EVERY read-modify-write sequence
|
|
67
67
|
* inside `mutate` and the adapter supplies sequence-level atomicity (a DB transaction, an
|
|
68
68
|
* advisory lock keyed on the backend — not on this object). Absent ⇒ the tools fall back to the
|
|
@@ -70,7 +70,7 @@ export interface TaskListStore {
|
|
|
70
70
|
* backend IS this object) and wrong for anything shared wider — implement `mutate` there. */
|
|
71
71
|
mutate?<T>(fn: (tx: TaskListStore) => Promise<T>): Promise<T>;
|
|
72
72
|
}
|
|
73
|
-
/**
|
|
73
|
+
/** the clone policy behind the detached-copy contract: metadata must be JSON-shaped
|
|
74
74
|
* (structuredClone would accept — and SHARE — SharedArrayBuffer backing memory, and throws opaquely
|
|
75
75
|
* on functions/proxies; the tool lane is always JSON, so this guards DIRECT store users). */
|
|
76
76
|
/**
|
package/dist/tools/web.d.ts
CHANGED
|
@@ -91,12 +91,12 @@ export declare function webFetchToolSpec(config?: WebFetchConfig): ToolSpec;
|
|
|
91
91
|
export declare function createWebFetchTool(config?: WebFetchConfig): AgentTool;
|
|
92
92
|
/** {@link createWebFetchSummarizer}'s truncation bound — CC's `MAX_MARKDOWN_LENGTH`
|
|
93
93
|
* (WebFetchTool/utils.ts:128). Exported so a deployment wiring the reference summarizer doesn't need
|
|
94
|
-
* its own copy of this number to reason about (
|
|
94
|
+
* its own copy of this number to reason about (a downstream deployment asked for this explicitly,
|
|
95
95
|
* to avoid a value-copy of the truncation threshold drifting from this one). */
|
|
96
96
|
export declare const WEBFETCH_SUMMARY_MAX_CONTENT = 100000;
|
|
97
97
|
/** {@link createWebFetchSummarizer}'s fixed guidelines block — CC's `makeSecondaryModelPrompt`
|
|
98
98
|
* (WebFetchTool/prompt.ts, non-preapproved-domain arm, guidelines verbatim). Exported alongside
|
|
99
|
-
* {@link WEBFETCH_SUMMARY_MAX_CONTENT} for the same reason
|
|
99
|
+
* {@link WEBFETCH_SUMMARY_MAX_CONTENT} for the same reason: a deployment composing
|
|
100
100
|
* its OWN summarizer (not this reference one) that still wants CC-parity guidance text doesn't need its
|
|
101
101
|
* own copy of this string. Not runtime-parameterized — the page content and the caller's `prompt` are
|
|
102
102
|
* interpolated AROUND this block, never inside it. */
|
|
@@ -160,9 +160,24 @@ export declare function resolveSummaryInputChars(model: Model, override?: number
|
|
|
160
160
|
export interface WebFetchSummarizerOptions {
|
|
161
161
|
/** Override the derived page-content budget (see {@link resolveSummaryInputChars}). */
|
|
162
162
|
maxContentChars?: number;
|
|
163
|
+
/**
|
|
164
|
+
* Per-model auth — MIRRORS {@link TaskSpec.getApiKeyAndHeaders} (same signature, resolved per
|
|
165
|
+
* call against the summarizer's model, the side-query seat's form). Without this seat the
|
|
166
|
+
* summarizer called the brain with `{ signal }` only, so a summarizer model on a
|
|
167
|
+
* per-model-credential route fell to the brain's construction-time credential — which the
|
|
168
|
+
* key↔URL pairing gate refuses off the deployment root. Absent ⇒ the options object is
|
|
169
|
+
* byte-identical to the pre-seat shape (no keys added).
|
|
170
|
+
*/
|
|
171
|
+
getApiKeyAndHeaders?: (model: Model) => Promise<{
|
|
172
|
+
apiKey?: string;
|
|
173
|
+
headers?: Record<string, string>;
|
|
174
|
+
} | undefined> | {
|
|
175
|
+
apiKey?: string;
|
|
176
|
+
headers?: Record<string, string>;
|
|
177
|
+
} | undefined;
|
|
163
178
|
}
|
|
164
179
|
/**
|
|
165
|
-
*
|
|
180
|
+
* A reference {@link WebFetchConfig.summarize} implementation: reuses a
|
|
166
181
|
* caller-supplied `brain` (rather than requiring a dedicated second model) to extract a focused answer
|
|
167
182
|
* from fetched content per the caller's `prompt`, instead of the tool dumping the whole (fenced, still
|
|
168
183
|
* untrusted) page. CC ALWAYS routes fetched content through a secondary model this way
|
|
@@ -212,7 +227,7 @@ export interface WebSearchConfig {
|
|
|
212
227
|
}>>;
|
|
213
228
|
/** Max results returned to the model (default 10). */
|
|
214
229
|
maxResults?: number;
|
|
215
|
-
/** Wall-clock budget for one `search` call, in ms. Default 30 000 (RB-231
|
|
230
|
+
/** Wall-clock budget for one `search` call, in ms. Default 30 000 (RB-231). The backend is
|
|
216
231
|
* deployment-injected and may ignore the AbortSignal entirely, so this is enforced with BOTH an abort
|
|
217
232
|
* and a race — a hung backend must not hang the turn, and without this the deployment had no interface
|
|
218
233
|
* to bound it. */
|
package/dist/tools/web.js
CHANGED
|
@@ -725,9 +725,15 @@ export function createWebFetchSummarizer(brain, model, options = {}) {
|
|
|
725
725
|
const truncated = inputTruncated ? content.slice(0, budget) + "\n\n[Content truncated due to length...]" : content;
|
|
726
726
|
const userPrompt = `\nWeb page content:\n---\n${truncated}\n---\n\n${prompt}\n\n` + WEBFETCH_SUMMARY_GROUNDING_CLAUSE + "\n" + WEBFETCH_SUMMARY_GUIDELINES;
|
|
727
727
|
const context = { messages: [{ role: "user", content: userPrompt, timestamp: Date.now() }] };
|
|
728
|
+
const auth = await options.getApiKeyAndHeaders?.(model);
|
|
729
|
+
const callOptions = {
|
|
730
|
+
signal,
|
|
731
|
+
...(auth?.apiKey !== undefined ? { apiKey: auth.apiKey } : {}),
|
|
732
|
+
...(auth?.headers !== undefined ? { headers: auth.headers } : {}),
|
|
733
|
+
};
|
|
728
734
|
const msg = brain.complete
|
|
729
|
-
? await brain.complete(model, context,
|
|
730
|
-
: await (await Promise.resolve(brain.stream(model, context,
|
|
735
|
+
? await brain.complete(model, context, callOptions)
|
|
736
|
+
: await (await Promise.resolve(brain.stream(model, context, callOptions))).result();
|
|
731
737
|
if (msg.stopReason === "error" || msg.stopReason === "aborted") {
|
|
732
738
|
throw new Error(msg.errorMessage ?? `summarizer stopped with ${msg.stopReason}`);
|
|
733
739
|
}
|
package/dist/tools/worktree.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 审计深挖 G4 — the `EnterWorktree` / `ExitWorktree` tool pair: SESSION-level git-worktree
|
|
3
3
|
* isolation (CC 2.1.198 parity). EnterWorktree creates a managed worktree under `.sema-worktrees/`
|
|
4
4
|
* (the same {@link WORKTREE_PARENT} the subagent `isolation:"worktree"` lane uses) and REALLY switches
|
|
5
5
|
* the task's working directory into it; ExitWorktree returns to the original directory and cleans up.
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* containment is untouched: the worktree lives UNDER the task root, so resolveKey's canonical-within
|
|
28
28
|
* check still holds for every subsequent fs op.
|
|
29
29
|
*
|
|
30
|
-
* ⚠️ Containment ruling (
|
|
30
|
+
* ⚠️ Containment ruling (deliberate): entering a worktree is a **cwd switch, NOT a
|
|
31
31
|
* sandbox**. resolveKey's containment anchor stays the ORIGINAL task root — it is deliberately NOT
|
|
32
32
|
* re-anchored/tightened to the worktree dir, so `../../` from inside the worktree can still reach the
|
|
33
33
|
* rest of the repository (which is WITHIN the task root and was reachable before Enter too), while
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
* arbitrary command surface), but they create/delete on-disk state ⇒ effect:"write" (plan mode gates
|
|
41
41
|
* them like every other write tool; read-only hands never mount them — see prepare-task).
|
|
42
42
|
*
|
|
43
|
-
* Durability
|
|
43
|
+
* Durability: the active session lives in a SHARED, ALL-SERIALIZABLE
|
|
44
44
|
* {@link WorktreeSessionRef} owned by prepare-task (never a closure-only var, and no captured destroy
|
|
45
45
|
* closure — Exit re-derives removal as a plain `git worktree remove`). A durable suspend stamps it into
|
|
46
46
|
* `CheckpointState.activeWorktree` (+ the cwd into `handsCwd`); resume re-seeds both, so
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
*/
|
|
49
49
|
import type { ActiveWorktreeSession, AgentTool, ExecutionEnv } from "../internal/harness-types.js";
|
|
50
50
|
import type { CwdRef } from "./fs/index.js";
|
|
51
|
-
/**
|
|
51
|
+
/** the ACTIVE worktree session, ALL-SERIALIZABLE (plain strings, no closures):
|
|
52
52
|
* prepare-task owns the ref, stamps `current` into `CheckpointState.activeWorktree` at a durable
|
|
53
53
|
* suspend, and re-seeds it on resume, so ExitWorktree works across the suspend/resume boundary (the
|
|
54
54
|
* tree survives on disk; removal is re-derived as a plain `git worktree remove`).
|
|
@@ -80,7 +80,7 @@ export interface WorktreeToolsOptions {
|
|
|
80
80
|
* assigns it to the worktree path (a REAL cwd switch: Bash/Read/Edit/Write/Monitor all follow),
|
|
81
81
|
* ExitWorktree restores it. */
|
|
82
82
|
cwdRef: CwdRef;
|
|
83
|
-
/**
|
|
83
|
+
/** the shared session-state ref (checkpointable — prepare-task serializes it into
|
|
84
84
|
* the durable checkpoint and re-seeds it on resume). Omitted ⇒ a private per-mount ref (same live
|
|
85
85
|
* behavior, minus durable-suspend survival — prepare-task always passes one). */
|
|
86
86
|
session?: WorktreeSessionRef;
|
package/dist/tools/worktree.js
CHANGED
|
@@ -248,10 +248,10 @@ export function createWorktreeTools(env, opts) {
|
|
|
248
248
|
description: "true = remove the worktree even when it has uncommitted files or new commits, permanently discarding them. Default false: a changed worktree is kept and its changes listed. Cannot be combined with `keep: true`.",
|
|
249
249
|
})),
|
|
250
250
|
action: Type.Optional(Type.Union([Type.Literal("keep"), Type.Literal("remove")], {
|
|
251
|
-
description: '"keep" leaves the worktree
|
|
251
|
+
description: '"keep" leaves the worktree on disk. "remove" takes the default removal path: an unchanged worktree is removed, a changed one is still KEPT unless `discard_changes: true`. The worktree is detached — no branch is created or deleted either way.',
|
|
252
252
|
})),
|
|
253
253
|
discard_changes: Type.Optional(Type.Boolean({
|
|
254
|
-
description: '
|
|
254
|
+
description: 'Set true to remove the worktree even when it has uncommitted files or unmerged commits — they are permanently discarded. Without it a changed worktree is KEPT (the exit still completes and the reply lists the changes plus this escape), never refused.',
|
|
255
255
|
})),
|
|
256
256
|
}),
|
|
257
257
|
effect: "write",
|