@sema-agent/core 5.64.0 → 6.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 +70 -0
- package/dist/agents/subagent.d.ts +2 -2
- package/dist/agents/subagent.js +11 -0
- package/dist/agents/verify.d.ts +1 -1
- package/dist/brain/anthropic.js +1 -1
- package/dist/brain/errors.d.ts +29 -0
- package/dist/brain/errors.js +20 -0
- package/dist/brain/open-responses.js +2 -2
- package/dist/brain/route-adjudicator.d.ts +8 -1
- package/dist/brain/route-adjudicator.js +1 -0
- package/dist/brain/status-sink.js +12 -1
- package/dist/brain/stream-engine.js +17 -6
- package/dist/core/auto-compaction.d.ts +26 -0
- package/dist/core/auto-compaction.js +7 -2
- package/dist/core/auto-mode-arming.d.ts +138 -0
- package/dist/core/auto-mode-arming.js +181 -0
- package/dist/core/auto-mode-defaults.d.ts +13 -0
- package/dist/core/auto-mode-defaults.js +5 -0
- package/dist/core/auto-mode-prompt.d.ts +14 -3
- package/dist/core/auto-mode-prompt.js +10 -7
- package/dist/core/auto-mode-rebuild.d.ts +75 -0
- package/dist/core/auto-mode-rebuild.js +41 -0
- package/dist/core/auto-mode.d.ts +15 -0
- package/dist/core/auto-mode.js +4 -2
- package/dist/core/checkpoint-store.d.ts +113 -4
- package/dist/core/context-edit.d.ts +47 -5
- package/dist/core/context-guard.d.ts +1 -1
- package/dist/core/file-history-retention.d.ts +106 -0
- package/dist/core/file-history-retention.js +36 -0
- package/dist/core/file-history-store.d.ts +768 -0
- package/dist/core/file-history-store.js +880 -0
- package/dist/core/governance-codes.d.ts +2 -1
- package/dist/core/governance-codes.js +14 -0
- package/dist/core/hooks.d.ts +48 -8
- package/dist/core/hooks.js +39 -22
- package/dist/core/lsp.d.ts +2 -2
- package/dist/core/mcp.d.ts +29 -7
- package/dist/core/memory-engine/consolidation-driver.d.ts +11 -0
- package/dist/core/memory-engine/consolidation-driver.js +71 -4
- package/dist/core/memory-engine/consolidation.d.ts +25 -2
- package/dist/core/memory-engine/consolidation.js +4 -1
- package/dist/core/memory-engine/distiller.d.ts +84 -1
- package/dist/core/memory-engine/distiller.js +68 -0
- package/dist/core/memory-engine/dual-root.js +6 -0
- package/dist/core/memory-engine/engine.d.ts +329 -15
- package/dist/core/memory-engine/engine.js +364 -34
- package/dist/core/memory-engine/file-backend.d.ts +30 -0
- package/dist/core/memory-engine/file-backend.js +14 -13
- package/dist/core/memory-engine/frontmatter.d.ts +22 -1
- package/dist/core/memory-engine/frontmatter.js +3 -0
- package/dist/core/memory-engine/header-hints.d.ts +5 -0
- package/dist/core/memory-engine/index.d.ts +5 -4
- package/dist/core/memory-engine/index.js +5 -4
- package/dist/core/memory-engine/layout.d.ts +88 -2
- package/dist/core/memory-engine/layout.js +112 -3
- package/dist/core/memory-engine/provenance-wording.d.ts +7 -0
- package/dist/core/memory-engine/provenance-wording.js +3 -0
- package/dist/core/memory-engine/tools.d.ts +89 -8
- package/dist/core/memory-engine/tools.js +263 -22
- package/dist/core/memory-engine/types.d.ts +80 -1
- package/dist/core/memory-recall.d.ts +6 -0
- package/dist/core/memory.d.ts +27 -1
- package/dist/core/memory.js +16 -2
- package/dist/core/permission-rule-consent.d.ts +20 -0
- package/dist/core/permission-rule-consent.js +12 -3
- package/dist/core/permission-rule-model.d.ts +67 -7
- package/dist/core/permission-rule-model.js +53 -7
- package/dist/core/permission-rule-store.js +15 -10
- package/dist/core/permission-rule-sync.js +15 -11
- package/dist/core/remote-env.d.ts +3 -3
- package/dist/core/retention-policy.d.ts +9 -0
- package/dist/core/retention-policy.js +5 -2
- package/dist/core/retention.d.ts +13 -2
- package/dist/core/runner/assemble-result.d.ts +19 -1
- package/dist/core/runner/assemble-result.js +17 -2
- package/dist/core/runner/compaction-call-options.d.ts +93 -0
- package/dist/core/runner/compaction-call-options.js +3 -0
- package/dist/core/runner/memory-capture-optout.d.ts +80 -0
- package/dist/core/runner/memory-capture-optout.js +53 -0
- package/dist/core/runner/prepare-config-doors.d.ts +5 -0
- package/dist/core/runner/prepare-config-doors.js +16 -0
- package/dist/core/runner/prepare-hands-readface.d.ts +119 -5
- package/dist/core/runner/prepare-hands-readface.js +103 -8
- package/dist/core/runner/prepare-memory.d.ts +88 -0
- package/dist/core/runner/prepare-memory.js +306 -25
- package/dist/core/runner/prepare-task.d.ts +156 -5
- package/dist/core/runner/prepare-task.js +488 -98
- package/dist/core/runner/runtask.d.ts +27 -20
- package/dist/core/runner/runtask.js +283 -99
- package/dist/core/runner/session-file-state-replay.d.ts +18 -10
- package/dist/core/runner/session-file-state-replay.js +52 -1
- package/dist/core/runner/tool-disclosure.js +2 -1
- package/dist/core/runner/turn-attachments.d.ts +22 -12
- package/dist/core/session-store.d.ts +1 -1
- package/dist/core/session-store.js +6 -1
- package/dist/core/session.d.ts +34 -1
- package/dist/core/store-contracts/file-history-store-contract.d.ts +3 -0
- package/dist/core/store-contracts/file-history-store-contract.js +720 -0
- package/dist/core/stub-env.d.ts +4 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/task-registry-shared.js +30 -2
- package/dist/core/tool-errors.js +1 -0
- package/dist/core/tool-policy.d.ts +172 -1
- package/dist/core/tool-policy.js +32 -1
- package/dist/core/tool-result-store.js +2 -1
- package/dist/core/trace.d.ts +24 -0
- package/dist/core/types.d.ts +875 -97
- package/dist/core/types.js +4 -3
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/core/untrusted-text.js +8 -0
- package/dist/core/workflow-run-store-contract.js +17 -0
- package/dist/core/workflow-run-store.d.ts +20 -0
- package/dist/core/workflow-run-store.js +1 -0
- package/dist/engine/compaction/compaction.d.ts +88 -10
- package/dist/engine/compaction/compaction.js +109 -30
- package/dist/engine/execution-env/node-execution-env.d.ts +9 -1
- package/dist/engine/execution-env/node-execution-env.js +28 -0
- package/dist/engine/harness/agent-harness.d.ts +52 -1
- package/dist/engine/harness/agent-harness.js +36 -1
- package/dist/engine/harness/types.d.ts +44 -1
- package/dist/engine/llm/types.d.ts +50 -4
- package/dist/engine/loop/agent-loop.d.ts +5 -1
- package/dist/engine/loop/agent-loop.js +25 -0
- package/dist/engine/loop/types.d.ts +19 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +1 -1
- package/dist/engine/session/session.js +1 -1
- package/dist/index.d.ts +18 -8
- package/dist/index.js +14 -6
- package/dist/orchestration/run-workflow-tool.d.ts +20 -2
- package/dist/orchestration/run-workflow-tool.js +22 -3
- package/dist/orchestration/workflow-governance.d.ts +59 -1
- package/dist/orchestration/workflow-governance.js +61 -8
- package/dist/orchestration/workflow-meta.d.ts +4 -2
- package/dist/orchestration/workflow-primitives.js +56 -13
- package/dist/orchestration/workflow-types.d.ts +112 -1
- package/dist/orchestration/workflow-types.js +2 -2
- package/dist/orchestration/workflow.d.ts +20 -0
- package/dist/orchestration/workflow.js +182 -14
- package/dist/prompt-assembly/event-registry.js +1 -1
- package/dist/prompts/default.d.ts +15 -7
- package/dist/prompts/default.js +3 -0
- package/dist/stores/file/file-history-store.d.ts +368 -0
- package/dist/stores/file/file-history-store.js +1248 -0
- package/dist/stores/file/index.d.ts +22 -13
- package/dist/stores/file/index.js +4 -4
- package/dist/stores/file/permission-rule-store.js +1 -0
- package/dist/stores/file/strategy-store.d.ts +3 -3
- package/dist/tools/fs/bash-readonly-classifier.d.ts +87 -3
- package/dist/tools/fs/bash-readonly-classifier.js +106 -4
- package/dist/tools/fs/fs-bash.js +9 -5
- package/dist/tools/fs/fs-shared.d.ts +52 -1
- package/dist/tools/fs/fs-shared.js +14 -0
- package/dist/tools/fs/fs-write.d.ts +5 -5
- package/dist/tools/fs/fs-write.js +71 -14
- package/dist/tools/fs/index.d.ts +6 -1
- package/dist/tools/fs/index.js +1 -1
- package/dist/tools/web.js +2 -1
- package/package.json +5 -1
- package/test/export-surface.snapshot.json +159 -23
- package/dist/core/file-snapshot-store.d.ts +0 -165
- package/dist/core/file-snapshot-store.js +0 -259
- package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +0 -13
- package/dist/core/store-contracts/file-snapshot-store-contract.js +0 -134
- package/dist/stores/file/file-snapshot-store.d.ts +0 -58
- package/dist/stores/file/file-snapshot-store.js +0 -353
|
@@ -18,11 +18,17 @@
|
|
|
18
18
|
* a `git checkout`, a bash command — anything this transcript does not record) therefore fails
|
|
19
19
|
* the staleness comparison and the edit is refused, exactly as it is inside a single task. A
|
|
20
20
|
* reconstruction that re-read the file to build its hash would instead wave the dirty edit
|
|
21
|
-
* through; that is the one thing this module must never do.
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
21
|
+
* through; that is the one thing this module must never do. (#483 D1, ruled 2026-08-28: this is
|
|
22
|
+
* deliberately STRICTER than CC's own rehydrate, whose Edit arm re-reads the disk and would
|
|
23
|
+
* admit a between-turns external change — same gate satisfaction, no staleness give-up.)
|
|
24
|
+
* 2. **Only records whose full post-condition is PROVABLE qualify.** A whole-file `Read` and a
|
|
25
|
+
* `Write` carry the text verbatim. An `Edit` card (#483 rung-2) carries a diff BASE — the
|
|
26
|
+
* pre-edit whole text plus the resolved mutations — so its post-condition is RECOMPUTED through
|
|
27
|
+
* the same single-source application step the tool itself used (`applyRecordedEdit`); a card
|
|
28
|
+
* that cannot recompute (malformed, offloaded, or its oldString absent from its own base) falls
|
|
29
|
+
* back to RETRACTING the file's record, never to a guess. A partial read or a notebook
|
|
30
|
+
* projection proves nothing and is simply not reported: the gate then behaves exactly as before
|
|
31
|
+
* (the model re-reads), which is the pre-existing cost, not a new failure.
|
|
26
32
|
*/
|
|
27
33
|
import type { AgentMessage } from "../../internal/harness.js";
|
|
28
34
|
/** The whole text of one file at the moment the transcript recorded it. */
|
|
@@ -39,11 +45,13 @@ export interface TranscriptFileRecord {
|
|
|
39
45
|
*
|
|
40
46
|
* Records are read only from SUCCESSFUL results (an `isError` result changed nothing and proves
|
|
41
47
|
* nothing). A `Write` proves the post-condition it just persisted; a whole-file `Read` proves what it
|
|
42
|
-
* just served. An `Edit`
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
48
|
+
* just served. An `Edit` card (#483 rung-2) proves the post-condition RECOMPUTED from its recorded
|
|
49
|
+
* diff base + mutations — or, when it cannot prove (malformed / offloaded / inconsistent), retracts
|
|
50
|
+
* whatever an earlier record said (leaving a stale entry behind would blame the user for the agent's
|
|
51
|
+
* own edit, "modified since read", the next turn). A `NotebookEdit` always retracts (deliberate
|
|
52
|
+
* residual — see {@link RETRACTING_RESULTS}). Anything else (partial reads, dedup stubs, notebook
|
|
53
|
+
* projections, image/document reads, foreign tools) is inert: it neither proves nor retracts,
|
|
54
|
+
* because reading a file does not change it.
|
|
47
55
|
*
|
|
48
56
|
* The parameter is the session's own message lane (`AgentMessage`, custom lanes included) rather than
|
|
49
57
|
* the narrowed model-facing union: this reads the branch as the session stores it, and every lane that
|
|
@@ -1,11 +1,49 @@
|
|
|
1
1
|
import { isAbsolutePathForm } from "../../tools/fs/safety.js";
|
|
2
|
+
import { applyRecordedEdit } from "../../tools/fs/fs-shared.js";
|
|
3
|
+
import { normalizeFileText } from "../../tools/fs/encoding.js";
|
|
2
4
|
import { isOffloadedDetailReplacement } from "../tool-result-store.js";
|
|
3
5
|
const READ_TOOL = "Read";
|
|
4
6
|
const WRITE_TOOL = "Write";
|
|
7
|
+
const EDIT_TOOL = "Edit";
|
|
5
8
|
const RETRACTING_RESULTS = [
|
|
6
|
-
{ toolName: "Edit", type: "edit", pathField: "filePath" },
|
|
7
9
|
{ toolName: "NotebookEdit", type: "notebook-edit", pathField: "notebookPath" },
|
|
8
10
|
];
|
|
11
|
+
function replayedEditContent(rest) {
|
|
12
|
+
const originalFile = rest.originalFile;
|
|
13
|
+
if (typeof originalFile !== "string" || isOffloadedDetailReplacement(originalFile))
|
|
14
|
+
return undefined;
|
|
15
|
+
const member = (v) => (typeof v === "string" && !isOffloadedDetailReplacement(v) ? v : undefined);
|
|
16
|
+
let edits;
|
|
17
|
+
const rawEdits = rest.edits;
|
|
18
|
+
if (Array.isArray(rawEdits) && rawEdits.length > 0) {
|
|
19
|
+
const out = [];
|
|
20
|
+
for (const e of rawEdits) {
|
|
21
|
+
const r = e;
|
|
22
|
+
const oldS = member(r?.oldString);
|
|
23
|
+
const newS = member(r?.newString);
|
|
24
|
+
if (oldS === undefined || newS === undefined)
|
|
25
|
+
return undefined;
|
|
26
|
+
out.push({ oldString: oldS, newString: newS, replaceAll: r.replaceAll === true });
|
|
27
|
+
}
|
|
28
|
+
edits = out;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
const oldS = member(rest.oldString);
|
|
32
|
+
const newS = member(rest.newString);
|
|
33
|
+
if (oldS === undefined || newS === undefined)
|
|
34
|
+
return undefined;
|
|
35
|
+
edits = [{ oldString: oldS, newString: newS, replaceAll: rest.replaceAll === true }];
|
|
36
|
+
}
|
|
37
|
+
let working = originalFile;
|
|
38
|
+
for (const e of edits) {
|
|
39
|
+
if (e.oldString !== "" && !working.includes(e.oldString))
|
|
40
|
+
return undefined;
|
|
41
|
+
working = applyRecordedEdit(working, e);
|
|
42
|
+
}
|
|
43
|
+
if (normalizeFileText(working) !== working)
|
|
44
|
+
return undefined;
|
|
45
|
+
return working;
|
|
46
|
+
}
|
|
9
47
|
function cardOf(details) {
|
|
10
48
|
if (typeof details !== "object" || details === null)
|
|
11
49
|
return undefined;
|
|
@@ -32,6 +70,19 @@ export function wholeFileRecordsFromTranscript(messages) {
|
|
|
32
70
|
if (card === undefined)
|
|
33
71
|
continue;
|
|
34
72
|
const { type, rest } = card;
|
|
73
|
+
if (m.toolName === EDIT_TOOL && type === "edit") {
|
|
74
|
+
const changed = rest.filePath;
|
|
75
|
+
if (typeof changed !== "string")
|
|
76
|
+
continue;
|
|
77
|
+
const replayed = replayedEditContent(rest);
|
|
78
|
+
if (replayed !== undefined && isAbsolutePathForm(changed)) {
|
|
79
|
+
byPath.set(changed, { path: changed, content: replayed, at: m.timestamp });
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
byPath.delete(changed);
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
35
86
|
const retracts = RETRACTING_RESULTS.find((r) => r.toolName === m.toolName && r.type === type);
|
|
36
87
|
if (retracts !== undefined) {
|
|
37
88
|
const changed = rest[retracts.pathField];
|
|
@@ -2,9 +2,10 @@ import { Type } from "typebox";
|
|
|
2
2
|
import { Value } from "typebox/value";
|
|
3
3
|
import { defineTool, errorResult } from "../tools.js";
|
|
4
4
|
import { formatZodValidationError, truncateError } from "../tool-errors.js";
|
|
5
|
+
import { DEFAULT_CHARS_PER_TOKEN } from "../../internal/harness.js";
|
|
5
6
|
export const TOOL_SEARCH_NAME = "ToolSearch";
|
|
6
7
|
const DEFER_AUTO_FRACTION = 0.1;
|
|
7
|
-
const CHARS_PER_TOKEN =
|
|
8
|
+
const CHARS_PER_TOKEN = DEFAULT_CHARS_PER_TOKEN;
|
|
8
9
|
export const TOOL_SEARCH_DEFAULT_MAX_RESULTS = 5;
|
|
9
10
|
const MAX_QUERY_RESULTS = 25;
|
|
10
11
|
export const DEFERRED_NO_PROGRESS_LIMIT = 3;
|
|
@@ -437,9 +437,11 @@ export interface AttachmentInputs {
|
|
|
437
437
|
/**
|
|
438
438
|
* RB-318 (裁 B, 2026-08-26) — `total_tokens_reminder` (CC 2.1.245 producer `MPs`, renderer `Oje`,
|
|
439
439
|
* registered in the SHARED producer group beside `budget_usd`, so a subagent carrying its own
|
|
440
|
-
* ceiling sees it too — the RB-311 attribution verbatim).
|
|
441
|
-
*
|
|
442
|
-
*
|
|
440
|
+
* ceiling sees it too — the RB-311 attribution verbatim). DEFAULT ON since design/374 slice 4
|
|
441
|
+
* (ruled 2026-08-28, matching 2.1.245+'s own default); explicit `false` opts out. Before the
|
|
442
|
+
* flip an un-opted deployment rendered no reminder frame at all. The countdown arms still need a
|
|
443
|
+
* declared ceiling, so a task without one is silent either way. (Scoped deliberately to this lane:
|
|
444
|
+
* registering
|
|
443
445
|
* `<total_tokens>` in ENGINE_ENVELOPES changed the SANITIZE/DISCLOSURE faces for every
|
|
444
446
|
* deployment, opted or not — untrusted text carrying that spelling is now defused on the fenced
|
|
445
447
|
* lanes and envelope-shaped external data trips the design/319 disclosure tail. That is the
|
|
@@ -454,6 +456,14 @@ export interface AttachmentInputs {
|
|
|
454
456
|
* ({@link AttachmentInputs.totalTokens}), the ceiling is the deployment's own declared
|
|
455
457
|
* `limits.maxTokens`, and with no ceiling declared the countdown arms simply never fire.
|
|
456
458
|
*
|
|
459
|
+
* AND WHY IT IS NOW ON BY DEFAULT (design/374 slice 4, 2026-08-28): the same 245 fact that
|
|
460
|
+
* justified BUILDING it is a statement about its DEFAULT, so shipping it opt-in left the engine
|
|
461
|
+
* one ruling short of the anchor. Both halves of "is this safe on by default" hold here — the
|
|
462
|
+
* readout cannot be wrong (it reads the enforced coordinate, never an estimate), and it cannot
|
|
463
|
+
* appear where nobody asked for a ceiling (no ceiling ⇒ no numbers ⇒ silence). The `budget_usd`
|
|
464
|
+
* twin stays opt-in: CC has no default-on posture for it, and inventing one would be the
|
|
465
|
+
* unanchored move.
|
|
466
|
+
*
|
|
457
467
|
* The arm is chosen by {@link totalTokensReminderMode} (default {@link
|
|
458
468
|
* TOTAL_TOKENS_REMINDER_DEFAULT_MODE}); `off` there silences the lane without un-wiring it.
|
|
459
469
|
*/
|
|
@@ -482,7 +492,7 @@ export interface AttachmentInputs {
|
|
|
482
492
|
* activated), sorted, snapshotted by the run loop. CC 220's equivalent is
|
|
483
493
|
* `tools.filter(iY(u) && !discovered.has(u.name)).map(name).sort()` (@608934-608938). Only passed
|
|
484
494
|
* when `config.toolSearchReminder` is opted in AND the task actually has deferred tools — an empty
|
|
485
|
-
* or absent list silences the lane permanently (CC `no_undiscovered_tools`, @608939). */
|
|
495
|
+
* or absent list silences the lane permanently (CC `no_undiscovered_tools`, @608939 (cli250.js:44368)). */
|
|
486
496
|
undiscoveredTools?: readonly string[];
|
|
487
497
|
/** RB-403 — is the direct-call lane mounted on this run's placeholders (`Prepared.deferDirectCall`,
|
|
488
498
|
* i.e. `TaskSpec.deferSelfResolve` not disabled)? Selects which closing sentence the
|
|
@@ -673,7 +683,7 @@ export declare function renderOrphanedBackgroundTasks(tasks: ReadonlyArray<{
|
|
|
673
683
|
description?: string;
|
|
674
684
|
}>): string;
|
|
675
685
|
/**
|
|
676
|
-
* RB-309 — CC's per-frame list cap for the `deferred_tools_delta` arms (`lP`, pretty220.js:518269).
|
|
686
|
+
* RB-309 — CC's per-frame list cap for the `deferred_tools_delta` arms (`lP`, (pretty220.js:518269, historical; not relocated in 250 — see cc-250 anchors)).
|
|
677
687
|
* Lists longer than this collapse to a grouped one-liner + "…and N more".
|
|
678
688
|
*/
|
|
679
689
|
export declare const TOOLS_DELTA_LIST_MAX = 30;
|
|
@@ -682,13 +692,13 @@ export declare const TOOLS_DELTA_LIST_MAX = 30;
|
|
|
682
692
|
* are CALLER-drained on intact cap survival, exactly like {@link AttachmentInputs.newTools}. */
|
|
683
693
|
export interface McpToolsDeltaFacts {
|
|
684
694
|
/** Previously-announced deferred tools that LEFT the harness roster (their server withdrew them —
|
|
685
|
-
* reached through RefreshMcpTools's prefix re-splice). CC `removedNames` @626530. */
|
|
695
|
+
* reached through RefreshMcpTools's prefix re-splice). CC `removedNames` @626530 (cli250.js:45892). */
|
|
686
696
|
removed?: readonly string[];
|
|
687
697
|
/** Previously-announced-then-withdrawn deferred tools that came BACK. CC `readdedNames` @626525. */
|
|
688
698
|
readded?: readonly string[];
|
|
689
699
|
/** Declared MCP servers that failed to connect at materialize (`MaterializedMcp.statuses`, status
|
|
690
700
|
* `"failed"`). `error` is REMOTE/transport text — the producer neutralizes + bounds it at intake.
|
|
691
|
-
* CC `failedMcpServers` @626561. */
|
|
701
|
+
* CC `failedMcpServers` @626561 (cli250.js:45904). */
|
|
692
702
|
failedServers?: ReadonlyArray<{
|
|
693
703
|
name: string;
|
|
694
704
|
error?: string;
|
|
@@ -704,15 +714,15 @@ export interface McpToolsDeltaFacts {
|
|
|
704
714
|
* the middle clause is inverted to match sema's actual contract. Same CC shape: lead sentence +
|
|
705
715
|
* name list.
|
|
706
716
|
*
|
|
707
|
-
* RB-309 — CC 2.1.220 (`deferred_tools_delta`,
|
|
717
|
+
* RB-309 — CC 2.1.220 (`deferred_tools_delta`, cli250.js:45890-45918) carries SIX arms; sema
|
|
708
718
|
* shipped only the `added` one. The arms below are the ones whose STATE IS REACHABLE in this engine
|
|
709
719
|
* (data-side audit, RB-309):
|
|
710
|
-
* - `readded` (@626525) / `removed` (@626530): reachable via RefreshMcpTools — the refresh splices a
|
|
720
|
+
* - `readded` (@626525) / `removed` (@626530 (cli250.js:45892)): reachable via RefreshMcpTools — the refresh splices a
|
|
711
721
|
* server's whole `mcp__<server>__` prefix domain out of the live tool array and pushes the fresh
|
|
712
722
|
* listing back, so a withdrawn tool genuinely leaves (and a re-advertised one genuinely returns)
|
|
713
723
|
* the roster mid-task. CC's trailing "Load via ToolSearch as before" / "Do not search for them —
|
|
714
724
|
* ToolSearch will return no match" clauses are kept, because sema mounts the SAME ToolSearch name.
|
|
715
|
-
* - `failed` (@626561): reachable from `MaterializedMcp.statuses` (`status: "failed"`, fail-open
|
|
725
|
+
* - `failed` (@626561 (cli250.js:45904)): reachable from `MaterializedMcp.statuses` (`status: "failed"`, fail-open
|
|
716
726
|
* connect skip). CC additionally splits a MANAGED-POLICY sub-arm off this list (`jlr`/`Oy_` error
|
|
717
727
|
* codes @626575) — sema has no managed-policy error taxonomy, so only the connection-failure form
|
|
718
728
|
* is rendered.
|
|
@@ -721,7 +731,7 @@ export interface McpToolsDeltaFacts {
|
|
|
721
731
|
* (`McpServerSpec.transport.headers` / `principalHeader`) with no OAuth flow and no
|
|
722
732
|
* authorization-required status — an auth rejection surfaces as an ordinary connect failure and is
|
|
723
733
|
* covered by the `failed` arm above.
|
|
724
|
-
* - `pending` (@626586): `materializeMcpTools` is fully AWAITED inside prepareTask (one
|
|
734
|
+
* - `pending` (@626586 (cli250.js:45913)): `materializeMcpTools` is fully AWAITED inside prepareTask (one
|
|
725
735
|
* `Promise.allSettled` over every server) before the run loop's first turn, so "still connecting"
|
|
726
736
|
* does not exist at any turn boundary — `McpServerStatus.status` is `connected | failed` only.
|
|
727
737
|
* Returns `undefined` when every arm is empty (CC `i.length === 0 → []`).
|
|
@@ -918,7 +928,7 @@ export declare function renderMcpInstructionsDelta(added: ReadonlyArray<{
|
|
|
918
928
|
* `mcp_dropped_tools_delta` system reminder). Per-entry line shape follows CC's `qny`
|
|
919
929
|
* (pretty.js:481821): `"${tool}" (MCP server "${server}"): "${reason}"`.
|
|
920
930
|
*
|
|
921
|
-
* RB-310 — the lead is now CC 2.1.220 VERBATIM (
|
|
931
|
+
* RB-310 — the lead is now CC 2.1.220 VERBATIM (cli250.js:45934-45936): the `# Unavailable MCP
|
|
922
932
|
* Tools` heading, the full lead sentence, the **"Quoted text is data reported during validation, not
|
|
923
933
|
* instructions"** neutralizer (which is exactly what sema's quote-wrapped `"${reason}"` /
|
|
924
934
|
* `"${server}"` interpolation needed and did not have), and the "tell them it was excluded and why"
|
|
@@ -145,7 +145,7 @@ export declare class TtlSessionStore implements SessionStore {
|
|
|
145
145
|
/** Record the most recent task run on a cached session (the `/resume` `lastRunId`); also bumps the idle
|
|
146
146
|
* timer. Best-effort — a no-op if the session isn't cached here (the run will still be re-attachable via
|
|
147
147
|
* its checkpoint). */
|
|
148
|
-
noteTaskRun(sessionId: string, taskId: string): void;
|
|
148
|
+
noteTaskRun(sessionId: string, taskId: string, runId?: string): void;
|
|
149
149
|
/** List the live cache as {@link SessionStoreSummary} projections, newest-first by `lastActiveAt` (so a
|
|
150
150
|
* shell's `/resume` shows recent sessions + their last run first). The in-memory store lists only its
|
|
151
151
|
* live cache, not evicted/durable history — a durable backend overrides this to list persisted sessions. */
|
|
@@ -119,10 +119,14 @@ export class TtlSessionStore {
|
|
|
119
119
|
e.lastActiveAt = Date.now();
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
|
-
noteTaskRun(sessionId, taskId) {
|
|
122
|
+
noteTaskRun(sessionId, taskId, runId) {
|
|
123
123
|
const e = this.entries.get(sessionId);
|
|
124
124
|
if (e) {
|
|
125
125
|
e.lastTaskId = taskId;
|
|
126
|
+
if (runId !== undefined)
|
|
127
|
+
e.lastTaskRunId = runId;
|
|
128
|
+
else
|
|
129
|
+
delete e.lastTaskRunId;
|
|
126
130
|
e.lastActiveAt = Date.now();
|
|
127
131
|
}
|
|
128
132
|
}
|
|
@@ -134,6 +138,7 @@ export class TtlSessionStore {
|
|
|
134
138
|
lastActiveAt: e.lastActiveAt,
|
|
135
139
|
...(e.createdAt !== undefined && e.createdAt !== "" ? { createdAt: e.createdAt } : {}),
|
|
136
140
|
...(e.lastTaskId !== undefined ? { lastTaskId: e.lastTaskId } : {}),
|
|
141
|
+
...(e.lastTaskRunId !== undefined ? { lastTaskRunId: e.lastTaskRunId } : {}),
|
|
137
142
|
...(e.forkedFrom !== undefined ? { forkedFrom: e.forkedFrom } : {}),
|
|
138
143
|
}))
|
|
139
144
|
.sort((a, b) => b.lastActiveAt - a.lastActiveAt);
|
package/dist/core/session.d.ts
CHANGED
|
@@ -73,6 +73,30 @@ export interface SessionStoreSummary {
|
|
|
73
73
|
/** The most recent task run on this session (core's `taskId`; the service projects it as `lastRunId`).
|
|
74
74
|
* Absent until a task has run on the session (recorded via {@link SessionStore.noteTaskRun}). */
|
|
75
75
|
lastTaskId?: string;
|
|
76
|
+
/**
|
|
77
|
+
* #499 — an ENGINE-minted run identity for this session ({@link import("./types.js").TaskResult.runId}),
|
|
78
|
+
* recorded by the most recent {@link SessionStore.noteTaskRun} write to LAND.
|
|
79
|
+
* {@link lastTaskId} above is `spec.taskId ?? sessionId`, so on the ordinary deployment that supplies no
|
|
80
|
+
* host task id it answers the SESSION's own id: a "last run" handle that names the session it hangs off
|
|
81
|
+
* cannot say WHICH run it means. This one names a specific run — read the ORDERING clause below for
|
|
82
|
+
* exactly how strong "most recent" is here, which is weaker than the sibling field's wording implies.
|
|
83
|
+
*
|
|
84
|
+
* Named `lastTaskRunId`, NOT `lastRunId`: the paragraph above this interface records that a service
|
|
85
|
+
* backend renames `lastTaskId` → the WIRE field `lastRunId`, so a store field spelled `lastRunId` would
|
|
86
|
+
* be the same name carrying a different identity one hop apart — a mixed-version mapper (or an object
|
|
87
|
+
* spread) could then publish either value under the one wire name with no type error. Same
|
|
88
|
+
* collision-avoidance as {@link import("../orchestration/workflow-types.js").WorkflowAgentRun.taskRunId}.
|
|
89
|
+
*
|
|
90
|
+
* ORDERING (honest limit): the Runner records this fire-and-forget, exactly as it always has for
|
|
91
|
+
* `lastTaskId`, so on a store whose write is asynchronous two runs of one session race and the loser's
|
|
92
|
+
* id can land last. That race was invisible while both runs wrote the same `lastTaskId`; it is
|
|
93
|
+
* observable here. Read this as "an id of a recent run", and take strict ordering from the runs'
|
|
94
|
+
* own results, not from this projection.
|
|
95
|
+
*
|
|
96
|
+
* Additive and optional: absent on a store that predates it, absent until a task has run, and absent
|
|
97
|
+
* whenever the recording caller had no run id (see {@link SessionStore.noteTaskRun}).
|
|
98
|
+
*/
|
|
99
|
+
lastTaskRunId?: string;
|
|
76
100
|
/** F7 fork-GC seam: the parent session this one was forked from ({@link SessionMetadata.forkedFrom}).
|
|
77
101
|
* Lets a consumer render/reap fork lineage; absent on non-forked sessions and on cache views that
|
|
78
102
|
* predate the fork. The durable source of truth is the repo's persisted metadata. */
|
|
@@ -175,8 +199,17 @@ export interface SessionStore {
|
|
|
175
199
|
* re-attach to the most recent run, even one still in-flight or suspended. **Optional + best-effort**: a
|
|
176
200
|
* store that surfaces no session list may ignore it; it MUST NOT throw. The engine's `taskId` is the
|
|
177
201
|
* service's `lastRunId`.
|
|
202
|
+
*
|
|
203
|
+
* `runId` (#499, additive third parameter — an existing implementation keeps typechecking and keeps
|
|
204
|
+
* working): the engine's own identity for THIS run, for {@link SessionStoreSummary.lastTaskRunId}. It
|
|
205
|
+
* is supplied because `taskId` cannot answer "which run": with no host task id it IS the session id.
|
|
206
|
+
*
|
|
207
|
+
* The two seats describe ONE run and MUST move together: a call that omits `runId` records the new
|
|
208
|
+
* `lastTaskId` and CLEARS `lastTaskRunId`. Keeping the previous run's id beside a newer task id would
|
|
209
|
+
* assert that an id belonging to an older run identifies the latest one — absence is the honest answer
|
|
210
|
+
* to "which run was last" when the caller does not know.
|
|
178
211
|
*/
|
|
179
|
-
noteTaskRun?(sessionId: string, taskId: string): void | Promise<void>;
|
|
212
|
+
noteTaskRun?(sessionId: string, taskId: string, runId?: string): void | Promise<void>;
|
|
180
213
|
/**
|
|
181
214
|
* Enumerate known sessions as lightweight {@link SessionStoreSummary} projections (newest-first by
|
|
182
215
|
* `lastActiveAt`) so a shell's `/resume` lists sessions + their last run in ONE call. **Optional**: the
|