@sema-agent/core 2.7.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/send-message-tool.d.ts +2 -0
- package/dist/agents/send-message-tool.js +38 -30
- package/dist/agents/subagent.js +15 -3
- package/dist/brain/circuit-breaker.js +18 -8
- package/dist/brain/retry.d.ts +1 -0
- package/dist/brain/retry.js +29 -7
- package/dist/brain/stream-engine.d.ts +1 -0
- package/dist/brain/stream-engine.js +74 -12
- package/dist/core/auto-compaction.js +9 -1
- package/dist/core/background-agent-store.d.ts +2 -0
- package/dist/core/background-agent-store.js +20 -0
- package/dist/core/mcp.js +8 -5
- package/dist/core/runner/prepare-task.js +25 -8
- package/dist/core/runner/runtask.js +20 -7
- package/dist/core/runner/tool-disclosure.d.ts +8 -3
- package/dist/core/runner/tool-disclosure.js +22 -8
- package/dist/core/skills-directory.d.ts +1 -1
- package/dist/core/skills-directory.js +257 -28
- package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +3 -1
- package/dist/core/store-contracts/file-snapshot-store-contract.js +11 -3
- package/dist/core/task-registry-agent.d.ts +2 -1
- package/dist/core/task-registry-agent.js +47 -54
- package/dist/core/task-registry.d.ts +1 -0
- package/dist/core/task-registry.js +1 -1
- package/dist/core/tools.d.ts +6 -2
- package/dist/core/tools.js +3 -2
- package/dist/core/types.d.ts +5 -1
- package/dist/engine/compaction/compaction.js +71 -20
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +1 -0
- package/dist/orchestration/run-workflow-tool.js +4 -1
- package/dist/orchestration/workflow.d.ts +1 -1
- package/dist/orchestration/workflow.js +2 -2
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -0
- package/dist/tools/fs/bash-readonly-classifier.js +113 -33
- package/dist/tools/fs/fs-bash.d.ts +2 -1
- package/dist/tools/fs/fs-bash.js +26 -6
- package/dist/tools/fs/fs-shared.d.ts +1 -0
- package/dist/tools/fs/fs-shared.js +44 -2
- package/dist/tools/fs/index.js +1 -0
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { type BackgroundAgentRecord, type BackgroundAgentStore } from "./backgro
|
|
|
2
2
|
import { type StopSource, type TaskAccess, type UnifiedTaskResult, type BackgroundAgentTaskHandle, type DurableAgentCore, type ParkedClaimTicket, type RegisterBackgroundAgentInput } from "./task-registry-shared.js";
|
|
3
3
|
import { type ToolResultStore } from "./tool-result-store.js";
|
|
4
4
|
export declare function ensureDurableHeartbeatLane(core: DurableAgentCore): void;
|
|
5
|
-
export declare function durableAgentWriteLane(handle: BackgroundAgentTaskHandle, patch: Partial<BackgroundAgentRecord>, clear?: (keyof BackgroundAgentRecord)[]): void;
|
|
5
|
+
export declare function durableAgentWriteLane(handle: BackgroundAgentTaskHandle, patch: Partial<BackgroundAgentRecord>, clear?: readonly (keyof BackgroundAgentRecord)[]): void;
|
|
6
6
|
export declare function durableAgentArmedLane(core: DurableAgentCore, id: string): boolean;
|
|
7
7
|
export declare function durableAgentRowProbeLane(core: DurableAgentCore, id: string): (() => Promise<boolean>) | undefined;
|
|
8
8
|
export declare function beginDurableClaimLane(core: DurableAgentCore, id: string): boolean;
|
|
@@ -71,6 +71,7 @@ export declare function settleBackgroundAgentLane(core: DurableAgentCore, id: st
|
|
|
71
71
|
errorKind?: string;
|
|
72
72
|
stoppedBy?: StopSource;
|
|
73
73
|
seq?: number;
|
|
74
|
+
cycle?: number;
|
|
74
75
|
}): "completed" | "failed" | "killed" | undefined;
|
|
75
76
|
export declare function abortBackgroundAgentsForOwnerLane(core: DurableAgentCore, access: TaskAccess, opts?: {
|
|
76
77
|
skipSessionScoped?: boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { uuidv7 } from "../internal/harness.js";
|
|
3
|
-
import { canAccessAgentRecord, BackgroundAgentStoreError, } from "./background-agent-store.js";
|
|
3
|
+
import { canAccessAgentRecord, BackgroundAgentStoreError, REVIVED_ROW_CLEARED_FIELDS, } from "./background-agent-store.js";
|
|
4
4
|
import { shutdownDebug } from "./shutdown-debug.js";
|
|
5
5
|
import { delimitUntrusted } from "./untrusted-text.js";
|
|
6
6
|
import { boundedRedactedSummary } from "./untrusted-egress.js";
|
|
@@ -652,6 +652,8 @@ export function settleBackgroundAgentLane(core, id, outcome) {
|
|
|
652
652
|
const handle = core.handles.get(id);
|
|
653
653
|
if (!handle || handle.type !== "background_agent")
|
|
654
654
|
return undefined;
|
|
655
|
+
if ((outcome.cycle ?? 0) !== (handle.reviveCycle ?? 0))
|
|
656
|
+
return undefined;
|
|
655
657
|
if (handle.status !== "running") {
|
|
656
658
|
if (handle.status === "killed") {
|
|
657
659
|
mintCompletionId(handle);
|
|
@@ -859,31 +861,11 @@ export function reviveBackgroundAgentLane(core, id, access, abort) {
|
|
|
859
861
|
handle.reviveCycle = (handle.reviveCycle ?? 0) + 1;
|
|
860
862
|
handle.cycleSeq = (handle.cycleSeq ?? 1) + 1;
|
|
861
863
|
handle.updatedAt = Date.now();
|
|
862
|
-
durableAgentWriteLane(handle, { status: "running" },
|
|
863
|
-
"settledAt",
|
|
864
|
-
"stoppedBy",
|
|
865
|
-
"finalOutput",
|
|
866
|
-
"finalOutputFull",
|
|
867
|
-
"error",
|
|
868
|
-
"errorCode",
|
|
869
|
-
"errorRetryable",
|
|
870
|
-
"errorKind",
|
|
871
|
-
"resultIsPartial",
|
|
872
|
-
"completionId",
|
|
873
|
-
"summary",
|
|
874
|
-
"recentSteps",
|
|
875
|
-
"editedFiles",
|
|
876
|
-
"usage",
|
|
877
|
-
]);
|
|
864
|
+
durableAgentWriteLane(handle, { status: "running" }, REVIVED_ROW_CLEARED_FIELDS);
|
|
878
865
|
return { ok: true, cycle: handle.reviveCycle };
|
|
879
866
|
}
|
|
880
867
|
export function settleRevivedAgentLane(core, id, cycle, outcome) {
|
|
881
|
-
|
|
882
|
-
if (!handle || handle.type !== "background_agent")
|
|
883
|
-
return undefined;
|
|
884
|
-
if ((handle.reviveCycle ?? 0) !== cycle)
|
|
885
|
-
return undefined;
|
|
886
|
-
return settleBackgroundAgentLane(core, id, outcome);
|
|
868
|
+
return settleBackgroundAgentLane(core, id, { ...outcome, cycle });
|
|
887
869
|
}
|
|
888
870
|
export function unmarkRetainedContinuationLane(core, id) {
|
|
889
871
|
const handle = core.handles.get(id);
|
|
@@ -1023,18 +1005,33 @@ export function notFoundRunningAgentsTail(footer) {
|
|
|
1023
1005
|
return ((footer.named.length > 0 ? `. Running named agents: ${footer.named.join(", ")}` : "") +
|
|
1024
1006
|
(footer.background.length > 0 ? `. Running background agents: ${footer.background.join(", ")}` : ""));
|
|
1025
1007
|
}
|
|
1008
|
+
function buildAgentPollDetails(input) {
|
|
1009
|
+
const failed = input.status === "failed";
|
|
1010
|
+
return {
|
|
1011
|
+
task_id: input.taskId,
|
|
1012
|
+
type: "background_agent",
|
|
1013
|
+
status: input.status,
|
|
1014
|
+
retrieval_status: input.retrievalStatus,
|
|
1015
|
+
...(input.seq !== undefined ? { seq: input.seq } : {}),
|
|
1016
|
+
...(input.status === "killed" && input.stoppedBy !== undefined ? { stoppedBy: input.stoppedBy } : {}),
|
|
1017
|
+
...(failed && input.error !== undefined ? { error: delimitUntrusted("agent error", boundedRedactedSummary(input.error, 300)) } : {}),
|
|
1018
|
+
...(failed && input.errorCode !== undefined ? { errorCode: input.errorCode } : {}),
|
|
1019
|
+
...(failed && input.errorRetryable !== undefined ? { retryable: input.errorRetryable } : {}),
|
|
1020
|
+
...(input.resultIsPartial === true ? { partial_result: true } : {}),
|
|
1021
|
+
...(input.completionId !== undefined ? { completionId: input.completionId } : {}),
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1026
1024
|
export function serveDurableAgentRowLane(row) {
|
|
1027
1025
|
if (row.status === "parked") {
|
|
1028
1026
|
return {
|
|
1029
1027
|
content: delimitUntrusted(`TaskOutput ${row.handle}`, `status: parked
|
|
1030
1028
|
The agent is durably suspended, waiting for an approval decision. It resumes when the pending approval is decided (durable approval inbox), or lands failed if the approval expires.`),
|
|
1031
|
-
details: {
|
|
1032
|
-
|
|
1033
|
-
type: "background_agent",
|
|
1029
|
+
details: buildAgentPollDetails({
|
|
1030
|
+
taskId: row.handle,
|
|
1034
1031
|
status: "parked",
|
|
1035
|
-
|
|
1032
|
+
retrievalStatus: "success",
|
|
1036
1033
|
...(row.seq !== undefined ? { seq: row.seq } : {}),
|
|
1037
|
-
},
|
|
1034
|
+
}),
|
|
1038
1035
|
};
|
|
1039
1036
|
}
|
|
1040
1037
|
const kindClause = row.status === "failed" && row.errorKind !== undefined && row.errorRetryable !== undefined
|
|
@@ -1046,18 +1043,18 @@ ${row.error ? `error: ${row.error}${kindClause}
|
|
|
1046
1043
|
${clipTaskOutput(row.finalOutputFull ?? row.finalOutput)}` : "(no result text)"}`;
|
|
1047
1044
|
return {
|
|
1048
1045
|
content: delimitUntrusted(`TaskOutput ${row.handle}`, body),
|
|
1049
|
-
details: {
|
|
1050
|
-
|
|
1051
|
-
type: "background_agent",
|
|
1046
|
+
details: buildAgentPollDetails({
|
|
1047
|
+
taskId: row.handle,
|
|
1052
1048
|
status: row.status,
|
|
1053
|
-
|
|
1054
|
-
...(row.status === "killed" && row.stoppedBy !== undefined ? { stoppedBy: row.stoppedBy } : {}),
|
|
1049
|
+
retrievalStatus: "success",
|
|
1055
1050
|
...(row.seq !== undefined ? { seq: row.seq } : {}),
|
|
1056
|
-
...(row.
|
|
1051
|
+
...(row.stoppedBy !== undefined ? { stoppedBy: row.stoppedBy } : {}),
|
|
1052
|
+
...(row.error !== undefined ? { error: row.error } : {}),
|
|
1053
|
+
...(row.errorCode !== undefined ? { errorCode: row.errorCode } : {}),
|
|
1054
|
+
...(row.errorRetryable !== undefined ? { errorRetryable: row.errorRetryable } : {}),
|
|
1055
|
+
...(row.resultIsPartial === true ? { resultIsPartial: true } : {}),
|
|
1057
1056
|
...(row.completionId !== undefined ? { completionId: row.completionId } : {}),
|
|
1058
|
-
|
|
1059
|
-
...(row.status === "failed" && row.errorRetryable !== undefined ? { retryable: row.errorRetryable } : {}),
|
|
1060
|
-
},
|
|
1057
|
+
}),
|
|
1061
1058
|
...(row.status === "failed" ? { isError: true } : {}),
|
|
1062
1059
|
};
|
|
1063
1060
|
}
|
|
@@ -1083,13 +1080,12 @@ export async function pollBackgroundAgentLane(handle, deadline, signal, oneShot,
|
|
|
1083
1080
|
return {
|
|
1084
1081
|
content: delimitUntrusted(`TaskOutput ${handle.id}`, `status: parked
|
|
1085
1082
|
The agent is durably suspended, waiting for an approval decision. It resumes when the pending approval is decided (durable approval inbox), or lands failed if the approval expires.`),
|
|
1086
|
-
details: {
|
|
1087
|
-
|
|
1088
|
-
type: "background_agent",
|
|
1083
|
+
details: buildAgentPollDetails({
|
|
1084
|
+
taskId: handle.id,
|
|
1089
1085
|
status: "parked",
|
|
1090
|
-
|
|
1086
|
+
retrievalStatus: "success",
|
|
1091
1087
|
...(handle.cycleSeq !== undefined ? { seq: handle.cycleSeq } : {}),
|
|
1092
|
-
},
|
|
1088
|
+
}),
|
|
1093
1089
|
};
|
|
1094
1090
|
}
|
|
1095
1091
|
const fullResult = handle.result ? (handle.resultFull ?? handle.result) : undefined;
|
|
@@ -1109,21 +1105,18 @@ ${handle.error ? `error: ${handle.error}${kindClause}
|
|
|
1109
1105
|
${resultText}` : "(no result text)"}`;
|
|
1110
1106
|
return {
|
|
1111
1107
|
content: delimitUntrusted(`TaskOutput ${handle.id}`, body),
|
|
1112
|
-
details: {
|
|
1113
|
-
|
|
1114
|
-
type: "background_agent",
|
|
1108
|
+
details: buildAgentPollDetails({
|
|
1109
|
+
taskId: handle.id,
|
|
1115
1110
|
status: handle.status,
|
|
1116
|
-
|
|
1111
|
+
retrievalStatus: retrieval,
|
|
1117
1112
|
...(handle.cycleSeq !== undefined ? { seq: handle.cycleSeq } : {}),
|
|
1118
|
-
...(handle.
|
|
1119
|
-
...(handle.
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
...(handle.
|
|
1123
|
-
...(handle.status === "failed" && handle.errorRetryable !== undefined ? { retryable: handle.errorRetryable } : {}),
|
|
1124
|
-
...(handle.resultIsPartial ? { partial_result: true } : {}),
|
|
1113
|
+
...(handle.stoppedBy !== undefined ? { stoppedBy: handle.stoppedBy } : {}),
|
|
1114
|
+
...(handle.error !== undefined ? { error: handle.error } : {}),
|
|
1115
|
+
...(handle.errorCode !== undefined ? { errorCode: handle.errorCode } : {}),
|
|
1116
|
+
...(handle.errorRetryable !== undefined ? { errorRetryable: handle.errorRetryable } : {}),
|
|
1117
|
+
...(handle.resultIsPartial === true ? { resultIsPartial: true } : {}),
|
|
1125
1118
|
...(handle.completionId !== undefined ? { completionId: handle.completionId } : {}),
|
|
1126
|
-
},
|
|
1119
|
+
}),
|
|
1127
1120
|
...(handle.status === "failed" ? { isError: true } : {}),
|
|
1128
1121
|
};
|
|
1129
1122
|
}
|
|
@@ -138,6 +138,7 @@ export declare class TaskRegistry {
|
|
|
138
138
|
errorKind?: string;
|
|
139
139
|
stoppedBy?: StopSource;
|
|
140
140
|
seq?: number;
|
|
141
|
+
cycle?: number;
|
|
141
142
|
}): "completed" | "failed" | "killed" | undefined;
|
|
142
143
|
abortBackgroundAgentsForOwner(access: TaskAccess, opts?: {
|
|
143
144
|
skipSessionScoped?: boolean;
|
|
@@ -518,7 +518,7 @@ export class TaskRegistry {
|
|
|
518
518
|
this.markStopSource(handle.id, "system");
|
|
519
519
|
const reapTerminalNote = handle.onReapTerminal;
|
|
520
520
|
handle.abort.abort();
|
|
521
|
-
this.settleBackgroundAgent(handle.id, { status: "killed", error: "session released" });
|
|
521
|
+
this.settleBackgroundAgent(handle.id, { status: "killed", error: "session released", cycle: handle.reviveCycle ?? 0 });
|
|
522
522
|
if (reapTerminalNote !== undefined && handle.terminalNotified !== true) {
|
|
523
523
|
handle.terminalNotified = true;
|
|
524
524
|
try {
|
package/dist/core/tools.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TSchema } from "typebox";
|
|
2
2
|
import type { AgentTool } from "../internal/harness.js";
|
|
3
|
-
import type { ToolSpec } from "./types.js";
|
|
3
|
+
import type { ToolExecuteContext, ToolSpec } from "./types.js";
|
|
4
4
|
export declare function errorResult(text: string, details?: unknown): {
|
|
5
5
|
content: string;
|
|
6
6
|
isError: true;
|
|
@@ -8,4 +8,8 @@ export declare function errorResult(text: string, details?: unknown): {
|
|
|
8
8
|
};
|
|
9
9
|
export declare function isDefineToolProduct(x: unknown): x is AgentTool;
|
|
10
10
|
export declare function stampDefineToolBrand<T extends object>(tool: T): T;
|
|
11
|
-
export
|
|
11
|
+
export type ToolCtxEnricher = (base: ToolExecuteContext) => ToolExecuteContext;
|
|
12
|
+
export interface DefineToolOptions {
|
|
13
|
+
enrichCtx?: ToolCtxEnricher;
|
|
14
|
+
}
|
|
15
|
+
export declare function defineTool<TParams extends TSchema = TSchema>(spec: ToolSpec<TParams>, options?: DefineToolOptions): AgentTool<TParams>;
|
package/dist/core/tools.js
CHANGED
|
@@ -33,7 +33,7 @@ export function stampDefineToolBrand(tool) {
|
|
|
33
33
|
Object.defineProperty(tool, DEFINE_TOOL_BRAND, { value: true, enumerable: false });
|
|
34
34
|
return tool;
|
|
35
35
|
}
|
|
36
|
-
export function defineTool(spec) {
|
|
36
|
+
export function defineTool(spec, options) {
|
|
37
37
|
const executionMode = spec.executionMode ?? (spec.effect === "read" ? "parallel" : "sequential");
|
|
38
38
|
const tool = {
|
|
39
39
|
name: spec.name,
|
|
@@ -60,7 +60,8 @@ export function defineTool(spec) {
|
|
|
60
60
|
}
|
|
61
61
|
let ret;
|
|
62
62
|
try {
|
|
63
|
-
|
|
63
|
+
const baseCtx = { toolCallId, signal };
|
|
64
|
+
ret = await spec.execute(params, options?.enrichCtx ? { ...options.enrichCtx(baseCtx), toolCallId, signal } : baseCtx);
|
|
64
65
|
}
|
|
65
66
|
catch (err) {
|
|
66
67
|
throw new Error(formatToolError(err));
|
package/dist/core/types.d.ts
CHANGED
|
@@ -97,6 +97,7 @@ export interface ToolExecuteContext {
|
|
|
97
97
|
clientContext?: TaskSpec["clientContext"];
|
|
98
98
|
excludeTools?: readonly string[];
|
|
99
99
|
deferTools?: readonly string[];
|
|
100
|
+
alwaysLoadTools?: readonly string[];
|
|
100
101
|
promptProfile?: "simple" | "classic";
|
|
101
102
|
additionalDirectories?: readonly string[];
|
|
102
103
|
envFacts?: TaskSpec["envFacts"];
|
|
@@ -465,11 +466,14 @@ export interface TaskEventIdentity {
|
|
|
465
466
|
sourceTaskId?: string;
|
|
466
467
|
bgAgentId?: string;
|
|
467
468
|
}
|
|
468
|
-
export type BrainStatusPhase = "rate_limited" | "retrying" | "reconnecting" | "circuit_open";
|
|
469
|
+
export type BrainStatusPhase = "rate_limited" | "retrying" | "reconnecting" | "circuit_open" | "recovered" | "gave_up";
|
|
469
470
|
export interface BrainStatus {
|
|
470
471
|
phase: BrainStatusPhase;
|
|
471
472
|
detail?: string;
|
|
472
473
|
retryInSec?: number;
|
|
474
|
+
retryInMs?: number;
|
|
475
|
+
attempt?: number;
|
|
476
|
+
maxRetries?: number;
|
|
473
477
|
}
|
|
474
478
|
export interface ToolActivity {
|
|
475
479
|
phase: "start" | "end";
|
|
@@ -256,7 +256,7 @@ export function findTurnStartIndex(entries, entryIndex, startIndex) {
|
|
|
256
256
|
}
|
|
257
257
|
return -1;
|
|
258
258
|
}
|
|
259
|
-
function
|
|
259
|
+
function collectToolCallSites(entries, startIndex, endIndex) {
|
|
260
260
|
const callSites = new Map();
|
|
261
261
|
for (let i = startIndex; i < endIndex; i++) {
|
|
262
262
|
const entry = entries[i];
|
|
@@ -275,6 +275,22 @@ function enforceToolPairContainment(entries, startIndex, endIndex, cutIndex) {
|
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
|
+
return callSites;
|
|
279
|
+
}
|
|
280
|
+
function emittingCallSite(callSites, toolCallId, resultIndex) {
|
|
281
|
+
const sites = callSites.get(toolCallId);
|
|
282
|
+
if (sites === undefined)
|
|
283
|
+
return -1;
|
|
284
|
+
let site = -1;
|
|
285
|
+
for (const s of sites) {
|
|
286
|
+
if (s < resultIndex)
|
|
287
|
+
site = s;
|
|
288
|
+
else
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
return site;
|
|
292
|
+
}
|
|
293
|
+
function enforceToolPairContainment(entries, callSites, endIndex, cutIndex) {
|
|
278
294
|
if (callSites.size === 0)
|
|
279
295
|
return cutIndex;
|
|
280
296
|
for (let i = cutIndex; i < endIndex; i++) {
|
|
@@ -284,16 +300,7 @@ function enforceToolPairContainment(entries, startIndex, endIndex, cutIndex) {
|
|
|
284
300
|
const msg = entry.message;
|
|
285
301
|
if (msg.role !== "toolResult")
|
|
286
302
|
continue;
|
|
287
|
-
const
|
|
288
|
-
if (sites === undefined)
|
|
289
|
-
continue;
|
|
290
|
-
let site = -1;
|
|
291
|
-
for (const s of sites) {
|
|
292
|
-
if (s < i)
|
|
293
|
-
site = s;
|
|
294
|
-
else
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
303
|
+
const site = emittingCallSite(callSites, msg.toolCallId, i);
|
|
297
304
|
if (site === -1 || site >= cutIndex)
|
|
298
305
|
continue;
|
|
299
306
|
cutIndex = site;
|
|
@@ -301,6 +308,49 @@ function enforceToolPairContainment(entries, startIndex, endIndex, cutIndex) {
|
|
|
301
308
|
}
|
|
302
309
|
return cutIndex;
|
|
303
310
|
}
|
|
311
|
+
function foldToolPairsForward(entries, callSites, cutPoints, endIndex, cutIndex) {
|
|
312
|
+
for (let i = cutIndex; i < endIndex; i++) {
|
|
313
|
+
const entry = entries[i];
|
|
314
|
+
if (entry.type !== "message")
|
|
315
|
+
continue;
|
|
316
|
+
const msg = entry.message;
|
|
317
|
+
if (msg.role !== "toolResult")
|
|
318
|
+
continue;
|
|
319
|
+
const site = emittingCallSite(callSites, msg.toolCallId, i);
|
|
320
|
+
if (site === -1 || site >= cutIndex)
|
|
321
|
+
continue;
|
|
322
|
+
const next = cutPoints.find((c) => c > i);
|
|
323
|
+
if (next === undefined)
|
|
324
|
+
return -1;
|
|
325
|
+
cutIndex = next;
|
|
326
|
+
i = cutIndex - 1;
|
|
327
|
+
}
|
|
328
|
+
return cutIndex;
|
|
329
|
+
}
|
|
330
|
+
function deriveCutPoint(entries, startIndex, cutIndex) {
|
|
331
|
+
const cutEntry = entries[cutIndex];
|
|
332
|
+
const isUserMessage = cutEntry.type === "message" && cutEntry.message.role === "user";
|
|
333
|
+
const turnStartIndex = isUserMessage ? -1 : findTurnStartIndex(entries, cutIndex, startIndex);
|
|
334
|
+
return {
|
|
335
|
+
firstKeptEntryIndex: cutIndex,
|
|
336
|
+
turnStartIndex,
|
|
337
|
+
isSplitTurn: !isUserMessage && turnStartIndex !== -1,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function leavesSummarizableHistory(entries, startIndex, cut) {
|
|
341
|
+
const historyEnd = cut.isSplitTurn ? cut.turnStartIndex : cut.firstKeptEntryIndex;
|
|
342
|
+
for (let i = startIndex; i < historyEnd; i++) {
|
|
343
|
+
if (getMessageFromEntryForCompaction(entries[i]) !== undefined)
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
if (!cut.isSplitTurn)
|
|
347
|
+
return false;
|
|
348
|
+
for (let i = cut.turnStartIndex; i < cut.firstKeptEntryIndex; i++) {
|
|
349
|
+
if (getMessageFromEntryForCompaction(entries[i]) !== undefined)
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
304
354
|
export function findCutPoint(entries, startIndex, endIndex, keepRecentTokens, charsPerToken = DEFAULT_CHARS_PER_TOKEN) {
|
|
305
355
|
const cutPoints = findValidCutPoints(entries, startIndex, endIndex);
|
|
306
356
|
if (cutPoints.length === 0) {
|
|
@@ -335,15 +385,16 @@ export function findCutPoint(entries, startIndex, endIndex, keepRecentTokens, ch
|
|
|
335
385
|
break;
|
|
336
386
|
}
|
|
337
387
|
}
|
|
338
|
-
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
388
|
+
const callSites = collectToolCallSites(entries, startIndex, endIndex);
|
|
389
|
+
const budgetCutIndex = cutIndex;
|
|
390
|
+
cutIndex = enforceToolPairContainment(entries, callSites, endIndex, cutIndex);
|
|
391
|
+
const kept = deriveCutPoint(entries, startIndex, cutIndex);
|
|
392
|
+
if (cutIndex !== budgetCutIndex && !leavesSummarizableHistory(entries, startIndex, kept)) {
|
|
393
|
+
const folded = foldToolPairsForward(entries, callSites, cutPoints, endIndex, budgetCutIndex);
|
|
394
|
+
if (folded !== -1)
|
|
395
|
+
return deriveCutPoint(entries, startIndex, folded);
|
|
396
|
+
}
|
|
397
|
+
return kept;
|
|
347
398
|
}
|
|
348
399
|
export const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.
|
|
349
400
|
|
package/dist/index.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ export type { InvariantKind, FunctionContract, Invariant, InvariantViolation, Ch
|
|
|
69
69
|
export { HAND_TOOL_EFFECTS, bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName, classifyCompoundReadonly, MAX_EDIT_BYTES } from "./tools/fs/index.js";
|
|
70
70
|
export { classifyCompoundReadonlyDetailed, formatOutOfRootReadApprovalOption, type BashReadonlyRootBoundary, type CompoundReadonlyVerdict, } from "./tools/fs/index.js";
|
|
71
71
|
export { resolveBashTimeoutCaps } from "./tools/fs/index.js";
|
|
72
|
-
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, type ToolResultStore, type ToolResultSlice, } from "./core/tool-result-store.js";
|
|
72
|
+
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, type ToolResultStore, type ToolResultSlice, } from "./core/tool-result-store.js";
|
|
73
73
|
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, WALLTIME_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingWalltimeMs, winnerFromOutcome, validatePendingSteer, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, type RiskDescriptor, type CheckpointStore, type CheckpointSummary, type Checkpoint, type CheckpointToken, type CheckpointGate, type CheckpointState, type SerializedCheckpointState, type CheckpointFaultMode, type PendingAction, type ResumeOutcome, type ResolvedOutcome, type ReopenReason, type ResolveExpectation, type SafetyAxis, type ResourceLedger, type ResourceLimitReason, } from "./core/checkpoint-store.js";
|
|
74
74
|
export { InMemoryFileSnapshotStore, DEFAULT_SNAPSHOT_BOUNDS } from "./core/file-snapshot-store.js";
|
|
75
75
|
export { captureManifest, applyManifest } from "./core/file-snapshot-store.js";
|
package/dist/index.js
CHANGED
|
@@ -60,7 +60,7 @@ export { deriveInvariants, checkInvariants } from "./core/property-harness.js";
|
|
|
60
60
|
export { HAND_TOOL_EFFECTS, bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName, classifyCompoundReadonly, MAX_EDIT_BYTES } from "./tools/fs/index.js";
|
|
61
61
|
export { classifyCompoundReadonlyDetailed, formatOutOfRootReadApprovalOption, } from "./tools/fs/index.js";
|
|
62
62
|
export { resolveBashTimeoutCaps } from "./tools/fs/index.js";
|
|
63
|
-
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, } from "./core/tool-result-store.js";
|
|
63
|
+
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, } from "./core/tool-result-store.js";
|
|
64
64
|
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, WALLTIME_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingWalltimeMs, winnerFromOutcome, validatePendingSteer, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, } from "./core/checkpoint-store.js";
|
|
65
65
|
export { InMemoryFileSnapshotStore, DEFAULT_SNAPSHOT_BOUNDS } from "./core/file-snapshot-store.js";
|
|
66
66
|
export { captureManifest, applyManifest } from "./core/file-snapshot-store.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type { CompactionPreparation, SummarizationClampDryRun } from "../engine/compaction/compaction.js";
|
|
2
2
|
export type { InvokedSkillRetention } from "../engine/compaction/utils.js";
|
|
3
3
|
export type { AgentCoreRuntimeDeps } from "../engine/loop/runtime-deps.js";
|
|
4
|
-
export type { AgentMessage, AgentTool, AgentToolResult, ThinkingLevel, } from "../engine/loop/types.js";
|
|
4
|
+
export type { AgentMessage, AgentTool, AgentToolResult, AgentToolUpdateCallback, ThinkingLevel, ToolExecutionMode, } from "../engine/loop/types.js";
|
|
5
5
|
export type { AgentHarnessEvent, CompactionSettings, ExecutionEnv, ExecutionErrorCode, FileErrorCode, FileInfo, Result, Session, SessionMetadata, SessionRepo, SessionStorage, SessionTreeEntry, Skill, } from "../engine/harness/types.js";
|
|
6
6
|
export type { ExecutionEnvExecOptions } from "../engine/harness/types.js";
|
|
7
7
|
export type { SessionWriteOptions, CompactionEntry } from "../engine/harness/types.js";
|
|
@@ -2,7 +2,7 @@ export * from "./harness-types.js";
|
|
|
2
2
|
export { AgentHarness } from "../engine/harness/agent-harness.js";
|
|
3
3
|
export { CompactionError, ExecutionError, FileError, ok, err } from "../engine/harness/types.js";
|
|
4
4
|
export { DEFAULT_CHARS_PER_TOKEN, DEFAULT_CLAMP_TOLERANCE, DEFAULT_COMPACTION_SETTINGS, compact, computeFileLists, dryRunSummarizationClamp, estimateContextTokens, estimateTokens, prepareCompaction, shouldCompact, summaryOutputBudgetTokens, } from "../engine/compaction/compaction.js";
|
|
5
|
-
export { SKILL_RETENTION_PER_SKILL_MAX_CHARS, SKILL_RETENTION_TOTAL_MAX_CHARS, SKILL_RETENTION_TRUNCATION_MARKER, readCompactionActiveTools, readRetainedInvokedSkills, renderInvokedSkillsRetention, } from "../engine/compaction/utils.js";
|
|
5
|
+
export { SKILL_RETENTION_PER_SKILL_MAX_CHARS, SKILL_RETENTION_TOTAL_MAX_CHARS, SKILL_RETENTION_TRUNCATION_MARKER, formatPersistedOutputRefs, readCompactionActiveTools, readRetainedInvokedSkills, renderInvokedSkillsRetention, } from "../engine/compaction/utils.js";
|
|
6
6
|
export { NodeExecutionEnv } from "../engine/execution-env/node-execution-env.js";
|
|
7
7
|
export { StoredSession, buildSessionContext } from "../engine/session/session.js";
|
|
8
8
|
export { getEntriesToFork } from "../engine/session/repo-utils.js";
|
package/dist/internal/harness.js
CHANGED
|
@@ -2,7 +2,7 @@ export * from "./harness-types.js";
|
|
|
2
2
|
export { AgentHarness } from "../engine/harness/agent-harness.js";
|
|
3
3
|
export { CompactionError, ExecutionError, FileError, ok, err } from "../engine/harness/types.js";
|
|
4
4
|
export { DEFAULT_CHARS_PER_TOKEN, DEFAULT_CLAMP_TOLERANCE, DEFAULT_COMPACTION_SETTINGS, compact, computeFileLists, dryRunSummarizationClamp, estimateContextTokens, estimateTokens, prepareCompaction, shouldCompact, summaryOutputBudgetTokens, } from "../engine/compaction/compaction.js";
|
|
5
|
-
export { SKILL_RETENTION_PER_SKILL_MAX_CHARS, SKILL_RETENTION_TOTAL_MAX_CHARS, SKILL_RETENTION_TRUNCATION_MARKER, readCompactionActiveTools, readRetainedInvokedSkills, renderInvokedSkillsRetention, } from "../engine/compaction/utils.js";
|
|
5
|
+
export { SKILL_RETENTION_PER_SKILL_MAX_CHARS, SKILL_RETENTION_TOTAL_MAX_CHARS, SKILL_RETENTION_TRUNCATION_MARKER, formatPersistedOutputRefs, readCompactionActiveTools, readRetainedInvokedSkills, renderInvokedSkillsRetention, } from "../engine/compaction/utils.js";
|
|
6
6
|
export { NodeExecutionEnv } from "../engine/execution-env/node-execution-env.js";
|
|
7
7
|
export { StoredSession, buildSessionContext } from "../engine/session/session.js";
|
|
8
8
|
export { getEntriesToFork } from "../engine/session/repo-utils.js";
|
|
@@ -58,6 +58,7 @@ export interface RunWorkflowToolDeps {
|
|
|
58
58
|
governanceBaseline: WorkflowGovernanceBaseline;
|
|
59
59
|
parentExcludeTools?: readonly string[];
|
|
60
60
|
parentDeferTools?: readonly string[];
|
|
61
|
+
parentAlwaysLoadTools?: readonly string[];
|
|
61
62
|
parentPromptProfile?: "simple" | "classic";
|
|
62
63
|
models?: Record<string, Model>;
|
|
63
64
|
agents?: import("../core/types.js").AgentDefinition[];
|
|
@@ -154,9 +154,12 @@ export async function createRunWorkflowTool(d) {
|
|
|
154
154
|
...(d.parentDeferTools?.length
|
|
155
155
|
? { deferTools: [...new Set([...(base.deferTools ?? []), ...d.parentDeferTools])] }
|
|
156
156
|
: {}),
|
|
157
|
+
...(d.parentAlwaysLoadTools?.length
|
|
158
|
+
? { alwaysLoadTools: [...new Set([...(base.alwaysLoadTools ?? []), ...d.parentAlwaysLoadTools])] }
|
|
159
|
+
: {}),
|
|
157
160
|
});
|
|
158
161
|
const withParentProfile = (base) => d.parentPromptProfile !== undefined && base.promptProfile === undefined ? { ...base, promptProfile: d.parentPromptProfile } : base;
|
|
159
|
-
const baselineWithParentFace = (d.parentExcludeTools?.length ?? 0) > 0 || (d.parentDeferTools?.length ?? 0) > 0 || d.parentPromptProfile !== undefined
|
|
162
|
+
const baselineWithParentFace = (d.parentExcludeTools?.length ?? 0) > 0 || (d.parentDeferTools?.length ?? 0) > 0 || (d.parentAlwaysLoadTools?.length ?? 0) > 0 || d.parentPromptProfile !== undefined
|
|
160
163
|
? {
|
|
161
164
|
...d.governanceBaseline,
|
|
162
165
|
base: withParentProfile(withParentFace(d.governanceBaseline.base)),
|
|
@@ -18,7 +18,7 @@ export declare function workflowAgentCallKey(ordinal: number, spec: TaskSpec, op
|
|
|
18
18
|
schema?: TSchema;
|
|
19
19
|
isolation?: "worktree";
|
|
20
20
|
}): string;
|
|
21
|
-
export declare function assertSupportedAgentIsolation(isolation: unknown):
|
|
21
|
+
export declare function assertSupportedAgentIsolation(isolation: unknown): void;
|
|
22
22
|
export interface WorkflowFanOutSlotError {
|
|
23
23
|
index: number;
|
|
24
24
|
kind: string;
|
|
@@ -100,7 +100,7 @@ export function workflowAgentCallKey(ordinal, spec, opts) {
|
|
|
100
100
|
tools: spec.tools?.map((t) => t.name).slice().sort(),
|
|
101
101
|
mcp: spec.mcp?.map((m) => m.name).slice().sort(),
|
|
102
102
|
outputSchema: opts.schema ?? spec.outputSchema,
|
|
103
|
-
isolation: opts.isolation,
|
|
103
|
+
isolation: opts.isolation ? opts.isolation : undefined,
|
|
104
104
|
};
|
|
105
105
|
return `${ordinal}:${boundInputHashOf(identity)}`;
|
|
106
106
|
}
|
|
@@ -112,7 +112,7 @@ function resolveChildSessionIdAtSpawn(spec) {
|
|
|
112
112
|
return randomUUID();
|
|
113
113
|
}
|
|
114
114
|
export function assertSupportedAgentIsolation(isolation) {
|
|
115
|
-
if (isolation
|
|
115
|
+
if (isolation && isolation !== "worktree") {
|
|
116
116
|
const shown = typeof isolation === "string" ? JSON.stringify(isolation) : String(isolation);
|
|
117
117
|
const e = new Error(`isolation ${shown} is not supported in workflow agents — only "worktree" (omit the option to run in the shared working tree). The agent was not started (fail-closed: an unrecognized isolation value must never silently run in the shared working tree).`);
|
|
118
118
|
e.code = "isolation.invalid";
|
|
@@ -17,4 +17,5 @@ export interface CompoundReadonlyVerdict {
|
|
|
17
17
|
}
|
|
18
18
|
export declare function formatOutOfRootReadApprovalOption(directory: string): string;
|
|
19
19
|
export declare function classifyCompoundReadonlyDetailed(command: string, allow: ReadonlySet<string>, boundary?: BashReadonlyRootBoundary): CompoundReadonlyVerdict;
|
|
20
|
+
export declare function classifySimpleCommandReadBoundary(command: string, boundary: BashReadonlyRootBoundary): CompoundReadonlyVerdict;
|
|
20
21
|
export declare function classifyCompoundReadonly(command: string, allow: ReadonlySet<string>, boundary?: BashReadonlyRootBoundary): string | undefined;
|