@sema-agent/core 5.7.0 → 5.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/CHANGELOG.md +79 -0
- package/dist/agents/cascade.d.ts +1 -1
- package/dist/agents/cascade.js +24 -0
- package/dist/agents/subagent.d.ts +7 -7
- package/dist/agents/subagent.js +74 -33
- package/dist/agents/teacher.js +3 -3
- package/dist/agents/team.d.ts +1 -1
- package/dist/agents/team.js +1 -1
- package/dist/agents/verify.js +1 -1
- package/dist/brain/anthropic.js +24 -35
- package/dist/brain/open-responses.d.ts +11 -0
- package/dist/brain/open-responses.js +721 -0
- package/dist/brain/openai.js +22 -33
- package/dist/brain/request-params.d.ts +1 -0
- package/dist/brain/request-params.js +16 -0
- package/dist/brain/stream-engine.d.ts +0 -2
- package/dist/brain/stream-engine.js +5 -47
- package/dist/brain/stream-shared.d.ts +0 -10
- package/dist/brain/stream-shared.js +0 -23
- package/dist/brain/terminal-cause.d.ts +0 -1
- package/dist/brain/terminal-cause.js +0 -3
- package/dist/brain/timeout.d.ts +4 -2
- package/dist/brain/timeout.js +4 -14
- package/dist/config/catalog.d.ts +3 -11
- package/dist/config/catalog.js +30 -69
- package/dist/config/defaults.d.ts +0 -3
- package/dist/config/defaults.js +0 -3
- package/dist/core/auto-compaction.d.ts +2 -11
- package/dist/core/auto-compaction.js +3 -67
- package/dist/core/checkpoint-store.d.ts +10 -8
- package/dist/core/checkpoint-store.js +7 -7
- package/dist/core/fs-write-gate-policy.js +2 -2
- package/dist/core/lsp-diagnostics.d.ts +3 -2
- package/dist/core/lsp-diagnostics.js +20 -7
- package/dist/core/memory-engine/file-backend.js +20 -17
- package/dist/core/memory-engine/layout.d.ts +5 -0
- package/dist/core/memory-engine/layout.js +72 -47
- package/dist/core/runner/assemble-result.d.ts +3 -8
- package/dist/core/runner/assemble-result.js +24 -18
- package/dist/core/runner/prepare-task.d.ts +27 -6
- package/dist/core/runner/prepare-task.js +209 -144
- package/dist/core/runner/runtask.d.ts +0 -2
- package/dist/core/runner/runtask.js +228 -266
- package/dist/core/runner/session-rule-policy.d.ts +1 -0
- package/dist/core/runner/session-rule-policy.js +4 -3
- package/dist/core/session-policy-store.d.ts +5 -0
- package/dist/core/session-policy-store.js +3 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
- package/dist/core/task-registry-agent.d.ts +2 -0
- package/dist/core/task-registry-agent.js +33 -1
- package/dist/core/task-registry-shared.d.ts +0 -1
- package/dist/core/task-registry.d.ts +2 -0
- package/dist/core/task-registry.js +9 -1
- package/dist/core/tool-errors.js +10 -2
- package/dist/core/tool-policy.d.ts +8 -0
- package/dist/core/tool-policy.js +11 -0
- package/dist/core/trace.d.ts +1 -10
- package/dist/core/types.d.ts +27 -30
- package/dist/core/usage-window-store.d.ts +39 -0
- package/dist/core/usage-window-store.js +115 -0
- package/dist/engine/execution-env/node-execution-env.js +0 -22
- package/dist/engine/harness/agent-harness.d.ts +1 -7
- package/dist/engine/harness/agent-harness.js +16 -53
- package/dist/engine/harness/types.d.ts +3 -15
- package/dist/engine/llm/types.d.ts +3 -75
- package/dist/engine/loop/agent-loop.d.ts +1 -1
- package/dist/engine/loop/agent-loop.js +7 -173
- package/dist/engine/loop/types.d.ts +1 -18
- package/dist/engine/session/repo-utils.d.ts +1 -2
- package/dist/engine/session/repo-utils.js +0 -7
- package/dist/index.d.ts +13 -7
- package/dist/index.js +10 -5
- package/dist/internal/llm.d.ts +1 -1
- package/dist/orchestration/goal.js +1 -5
- package/dist/orchestration/run-workflow-tool.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.js +1 -2
- package/dist/orchestration/workflow-governance.d.ts +6 -6
- package/dist/orchestration/workflow-governance.js +33 -47
- package/dist/orchestration/workflow.js +14 -5
- package/dist/prompt-assembly/event-registry.js +2 -3
- package/dist/stores/cc/lockfile.js +9 -11
- package/dist/stores/cc/mailbox-store.js +49 -38
- package/dist/stores/file/index.d.ts +3 -0
- package/dist/stores/file/index.js +4 -0
- package/dist/stores/file/usage-window-store.d.ts +9 -0
- package/dist/stores/file/usage-window-store.js +86 -0
- package/dist/tools/fs/fs-bash.d.ts +1 -10
- package/dist/tools/fs/fs-bash.js +20 -60
- package/dist/tools/fs/index.d.ts +0 -2
- package/dist/tools/fs/index.js +1 -2
- package/dist/tools/web.js +20 -19
- package/package.json +4 -5
- package/dist/bin/sema-tb.d.ts +0 -31
- package/dist/bin/sema-tb.js +0 -448
- package/dist/bin/tb-env.d.ts +0 -2
- package/dist/bin/tb-env.js +0 -17
- package/dist/brain/walltime.d.ts +0 -1
- package/dist/brain/walltime.js +0 -1
- package/dist/core/runner/call-cap.d.ts +0 -67
- package/dist/core/runner/call-cap.js +0 -145
- package/dist/core/runner/cut-kill.d.ts +0 -10
- package/dist/core/runner/cut-kill.js +0 -37
|
@@ -3,6 +3,7 @@ import type { ToolEffect } from "../types.js";
|
|
|
3
3
|
import { type NamedToolPolicy } from "../tool-policy.js";
|
|
4
4
|
import type { SessionPermissionRules } from "../session-policy-store.js";
|
|
5
5
|
export declare const PATH_WRITE_TOOLS: ReadonlySet<string>;
|
|
6
|
+
export declare const PATH_CONFINABLE_WRITE_TOOLS: ReadonlySet<string>;
|
|
6
7
|
export declare function isWithin(root: string, p: string): boolean;
|
|
7
8
|
export declare function createSessionRulePolicy(rules: SessionPermissionRules, opts: {
|
|
8
9
|
env: ExecutionEnv;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { canonicalizeTarget,
|
|
1
|
+
import { canonicalizeTarget, writeTargetPath } from "../../tools/fs/safety.js";
|
|
2
2
|
import { isWinFormPath } from "../../tools/fs/safety.js";
|
|
3
3
|
import { createCoarseCommandNamePolicy } from "../tool-policy.js";
|
|
4
4
|
export const PATH_WRITE_TOOLS = new Set(["Write", "Edit", "MultiEdit"]);
|
|
5
|
+
export const PATH_CONFINABLE_WRITE_TOOLS = new Set([...PATH_WRITE_TOOLS, "NotebookEdit"]);
|
|
5
6
|
export function isWithin(root, p) {
|
|
6
7
|
if (!root)
|
|
7
8
|
return false;
|
|
@@ -46,14 +47,14 @@ export function createSessionRulePolicy(rules, opts) {
|
|
|
46
47
|
return d;
|
|
47
48
|
}
|
|
48
49
|
if (allowDirs) {
|
|
49
|
-
if (!
|
|
50
|
+
if (!PATH_CONFINABLE_WRITE_TOOLS.has(toolName)) {
|
|
50
51
|
const eff = toolEffects?.get(toolName) ?? "write";
|
|
51
52
|
if (eff !== "read") {
|
|
52
53
|
return deny(`write-capable tool "${req.toolName}" denied: session rule confines writes to allowDirs but this tool cannot be path-confined`);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
else {
|
|
56
|
-
const path =
|
|
57
|
+
const path = writeTargetPath(toolName, req.args);
|
|
57
58
|
if (typeof path !== "string" || path.length === 0) {
|
|
58
59
|
return deny(`write tool "${req.toolName}" denied: session rule confines writes to allowDirs but the call has no resolvable path`);
|
|
59
60
|
}
|
|
@@ -26,6 +26,7 @@ export interface SessionPolicyStore {
|
|
|
26
26
|
listBySession?(sessionId: string): Promise<SessionRulesRecord[]>;
|
|
27
27
|
deleteBySession?(sessionId: string): Promise<void>;
|
|
28
28
|
}
|
|
29
|
+
declare function lexWithin(root: string, p: string): boolean;
|
|
29
30
|
export declare function normalizeRules(rules: SessionPermissionRules): SessionPermissionRules;
|
|
30
31
|
export declare function loosenReasons(prior: SessionPermissionRules, next: SessionPermissionRules): string[];
|
|
31
32
|
export declare function stripRev(rules: SessionPermissionRules): SessionPermissionRules;
|
|
@@ -37,3 +38,7 @@ export declare class InMemorySessionPolicyStore implements SessionPolicyStore {
|
|
|
37
38
|
listBySession(sessionId: string): Promise<SessionRulesRecord[]>;
|
|
38
39
|
deleteBySession(sessionId: string): Promise<void>;
|
|
39
40
|
}
|
|
41
|
+
export declare const __testables: {
|
|
42
|
+
lexWithin: typeof lexWithin;
|
|
43
|
+
};
|
|
44
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { posix } from "node:path";
|
|
2
|
+
import { isWinFormPath } from "../tools/fs/safety.js";
|
|
2
3
|
export class SessionPolicyError extends Error {
|
|
3
4
|
code;
|
|
4
5
|
constructor(code, message) {
|
|
@@ -9,7 +10,7 @@ export class SessionPolicyError extends Error {
|
|
|
9
10
|
}
|
|
10
11
|
function lexWithin(root, p) {
|
|
11
12
|
const fold = (x) => {
|
|
12
|
-
let n = x.replace(/\\/g, "/");
|
|
13
|
+
let n = isWinFormPath(x) ? x.replace(/\\/g, "/") : x;
|
|
13
14
|
if (/^[A-Za-z]:(\/|$)/.test(n))
|
|
14
15
|
n = n[0].toLowerCase() + n.slice(1);
|
|
15
16
|
return n;
|
|
@@ -116,3 +117,4 @@ export class InMemorySessionPolicyStore {
|
|
|
116
117
|
}
|
|
117
118
|
}
|
|
118
119
|
}
|
|
120
|
+
export const __testables = { lexWithin };
|
|
@@ -157,8 +157,8 @@ export async function checkpointListByScopeSummaries(store) {
|
|
|
157
157
|
scope: "tenant-a",
|
|
158
158
|
sessionId: "out-of-budget",
|
|
159
159
|
createdAt: 1_700_000_000_001,
|
|
160
|
-
gate: { kind: "resource_limit", reason: "
|
|
161
|
-
pendingAction: { kind: "resource_limit", reason: "
|
|
160
|
+
gate: { kind: "resource_limit", reason: "budget_tokens" },
|
|
161
|
+
pendingAction: { kind: "resource_limit", reason: "budget_tokens" },
|
|
162
162
|
resourceLedger: { totalBudgetMicroUsd: 10_000_000, spentMicroUsd: 4_200_000, spentTokens: 9, spentTurns: 3, sliceCount: 2 },
|
|
163
163
|
});
|
|
164
164
|
const resolved = createCheckpointFixture({ token: "tok-resolved", scope: "tenant-a", sessionId: "done" });
|
|
@@ -106,6 +106,8 @@ export declare function settleRevivedAgentLane(core: DurableAgentCore, id: strin
|
|
|
106
106
|
retryable?: boolean;
|
|
107
107
|
errorKind?: string;
|
|
108
108
|
}): "completed" | "failed" | "killed" | undefined;
|
|
109
|
+
export declare function noteBackgroundAgentActivityLane(core: DurableAgentCore, id: string, now?: number): void;
|
|
110
|
+
export declare function reapStaleSessionBackgroundAgentsLane(core: DurableAgentCore, staleMs: number, now?: number, onTerminal?: (note: () => void) => void): number;
|
|
109
111
|
export declare function unmarkRetainedContinuationLane(core: DurableAgentCore, id: string): void;
|
|
110
112
|
export declare function attachAgentNotifyLane(core: DurableAgentCore, id: string, notify: NonNullable<BackgroundAgentTaskHandle["notify"]>, cycle?: number): void;
|
|
111
113
|
export declare function deliverToRunningAgentLane(core: DurableAgentCore, id: string, access: TaskAccess, notification: import("./task-notification.js").TaskNotificationPayload, opts?: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { uuidv7 } from "../internal/harness.js";
|
|
3
|
-
import { canAccessAgentRecord, BackgroundAgentStoreError, REVIVED_ROW_CLEARED_FIELDS, } from "./background-agent-store.js";
|
|
3
|
+
import { canAccessAgentRecord, BackgroundAgentStoreError, REVIVED_ROW_CLEARED_FIELDS, STALE_RUNNING_REAP_ATTRIBUTION, } 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";
|
|
@@ -870,6 +870,38 @@ export function reviveBackgroundAgentLane(core, id, access, abort) {
|
|
|
870
870
|
export function settleRevivedAgentLane(core, id, cycle, outcome) {
|
|
871
871
|
return settleBackgroundAgentLane(core, id, { ...outcome, cycle });
|
|
872
872
|
}
|
|
873
|
+
export function noteBackgroundAgentActivityLane(core, id, now = Date.now()) {
|
|
874
|
+
const handle = core.handles.get(id);
|
|
875
|
+
if (!handle || handle.type !== "background_agent" || handle.status !== "running")
|
|
876
|
+
return;
|
|
877
|
+
handle.updatedAt = now;
|
|
878
|
+
}
|
|
879
|
+
export function reapStaleSessionBackgroundAgentsLane(core, staleMs, now = Date.now(), onTerminal) {
|
|
880
|
+
if (!Number.isFinite(staleMs) || staleMs <= 0) {
|
|
881
|
+
throw new Error(`reapStaleSessionBackgroundAgents: staleMs must be a positive finite number of milliseconds (got ${String(staleMs)})`);
|
|
882
|
+
}
|
|
883
|
+
let reaped = 0;
|
|
884
|
+
for (const handle of core.handles.values()) {
|
|
885
|
+
if (handle.type !== "background_agent" || handle.status !== "running" || handle.sessionScoped !== true)
|
|
886
|
+
continue;
|
|
887
|
+
if (now - handle.updatedAt <= staleMs)
|
|
888
|
+
continue;
|
|
889
|
+
core.markStopSource(handle.id, "system");
|
|
890
|
+
const reapTerminalNote = handle.onReapTerminal;
|
|
891
|
+
handle.abort.abort();
|
|
892
|
+
settleBackgroundAgentLane(core, handle.id, {
|
|
893
|
+
status: "killed",
|
|
894
|
+
error: STALE_RUNNING_REAP_ATTRIBUTION,
|
|
895
|
+
cycle: handle.reviveCycle ?? 0,
|
|
896
|
+
});
|
|
897
|
+
if (reapTerminalNote !== undefined && handle.terminalNotified !== true) {
|
|
898
|
+
handle.terminalNotified = true;
|
|
899
|
+
onTerminal?.(reapTerminalNote);
|
|
900
|
+
}
|
|
901
|
+
reaped++;
|
|
902
|
+
}
|
|
903
|
+
return reaped;
|
|
904
|
+
}
|
|
873
905
|
export function unmarkRetainedContinuationLane(core, id) {
|
|
874
906
|
const handle = core.handles.get(id);
|
|
875
907
|
if (handle && handle.type === "background_agent")
|
|
@@ -145,6 +145,8 @@ export declare class TaskRegistry {
|
|
|
145
145
|
seq?: number;
|
|
146
146
|
cycle?: number;
|
|
147
147
|
}): "completed" | "failed" | "killed" | undefined;
|
|
148
|
+
noteBackgroundAgentActivity(id: string, now?: number): void;
|
|
149
|
+
reapStaleSessionBackgroundAgents(staleMs: number, now?: number): number;
|
|
148
150
|
abortBackgroundAgentsForOwner(access: TaskAccess, opts?: {
|
|
149
151
|
skipSessionScoped?: boolean;
|
|
150
152
|
sessionScopedOnly?: boolean;
|
|
@@ -10,7 +10,7 @@ import { registerWorkflowLane, pollWorkflowLane, stopWorkflowLane } from "./task
|
|
|
10
10
|
import { mintCompletionId, canAccessWorkflowRun, formatWorkflowRun, clipTaskOutput, assertOwnership, sleepPollStep, statusFromBackground, rollSpoolText, accountDroppedBytes, renderSpoolBody, spoolDropNote, droppedGapNote, alreadyTerminalStopNote, terminalTaskSummary, TASK_OUTPUT_MAX_CHARS, MONITOR_BATCH_WINDOW_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_MAX_TIMEOUT_MS, MONITOR_MAX_BATCHES_PER_MINUTE, canAccess, DURABLE_AGENT_HANDLE_RE, } from "./task-registry-shared.js";
|
|
11
11
|
export { normalizeAgentName, DURABLE_AGENT_HEARTBEAT_MS, DURABLE_AGENT_HANDLE_RE, BG_AGENT_REAP_STOP_ERROR } from "./task-registry-shared.js";
|
|
12
12
|
import { TASK_OUTPUT_TOOL_NAME, TASK_STOP_TOOL_NAME, TASK_OUTPUT_CONTRACT, TASK_STOP_CONTRACT, TASK_OUTPUT_MISSING_ID_MESSAGE, TASK_STOP_MISSING_ID_MESSAGE, TASK_STOP_PARAMS, resolveTaskIdArg, REGISTRY_TASK_TOOL_CAPS, composeTaskOutputDescription, composeTaskOutputParams, composeTaskStopDescription, } from "./task-tool-shape.js";
|
|
13
|
-
import { durableAgentArmedLane, durableAgentRowProbeLane, beginDurableClaimLane, endDurableClaimLane, reapDurableAgentsLane, releaseDurableTranscriptAnchorLane, bindBackgroundAgentSessionLane, registerBackgroundAgentLane, parkBackgroundAgentLane, reconcileParkedAgentsLane, claimParkedAgentLane, rollbackParkedClaimLane, consumeParkedFlipLane, finalizeParkedResumeLane, settleBackgroundAgentLane, abortBackgroundAgentsForOwnerLane, serveDurableAgentRowLane, resolveBackgroundAgentByNameLane, markRetainedContinuationLane, reviveBackgroundAgentLane, settleRevivedAgentLane, unmarkRetainedContinuationLane, attachAgentNotifyLane, deliverToRunningAgentLane, runningBackgroundAgentLabelsLane, runningAgentFooterLane, notFoundRunningAgentsTail, pollBackgroundAgentLane, stopBackgroundAgentLane, } from "./task-registry-agent.js";
|
|
13
|
+
import { durableAgentArmedLane, durableAgentRowProbeLane, beginDurableClaimLane, endDurableClaimLane, reapDurableAgentsLane, noteBackgroundAgentActivityLane, reapStaleSessionBackgroundAgentsLane, releaseDurableTranscriptAnchorLane, bindBackgroundAgentSessionLane, registerBackgroundAgentLane, parkBackgroundAgentLane, reconcileParkedAgentsLane, claimParkedAgentLane, rollbackParkedClaimLane, consumeParkedFlipLane, finalizeParkedResumeLane, settleBackgroundAgentLane, abortBackgroundAgentsForOwnerLane, serveDurableAgentRowLane, resolveBackgroundAgentByNameLane, markRetainedContinuationLane, reviveBackgroundAgentLane, settleRevivedAgentLane, unmarkRetainedContinuationLane, attachAgentNotifyLane, deliverToRunningAgentLane, runningBackgroundAgentLabelsLane, runningAgentFooterLane, notFoundRunningAgentsTail, pollBackgroundAgentLane, stopBackgroundAgentLane, } from "./task-registry-agent.js";
|
|
14
14
|
export { canAccessWorkflowRun, clipTaskOutput, MONITOR_BATCH_WINDOW_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_MAX_TIMEOUT_MS, MONITOR_MAX_BATCHES_PER_MINUTE };
|
|
15
15
|
const BLOCK_DEFAULT_TIMEOUT_MS = 30_000;
|
|
16
16
|
const BLOCK_MAX_TIMEOUT_MS = 600_000;
|
|
@@ -167,6 +167,14 @@ export class TaskRegistry {
|
|
|
167
167
|
settleBackgroundAgent(id, outcome) {
|
|
168
168
|
return settleBackgroundAgentLane(this.core, id, outcome);
|
|
169
169
|
}
|
|
170
|
+
noteBackgroundAgentActivity(id, now) {
|
|
171
|
+
return noteBackgroundAgentActivityLane(this.core, id, now);
|
|
172
|
+
}
|
|
173
|
+
reapStaleSessionBackgroundAgents(staleMs, now) {
|
|
174
|
+
return reapStaleSessionBackgroundAgentsLane(this.core, staleMs, now, (note) => {
|
|
175
|
+
this.notifier.notify(() => note(), "taskRegistry.reapTerminalNote");
|
|
176
|
+
});
|
|
177
|
+
}
|
|
170
178
|
abortBackgroundAgentsForOwner(access, opts) {
|
|
171
179
|
return abortBackgroundAgentsForOwnerLane(this.core, access, opts);
|
|
172
180
|
}
|
package/dist/core/tool-errors.js
CHANGED
|
@@ -65,9 +65,14 @@ const BRAIN_FLAT_CODES = new Set([
|
|
|
65
65
|
"refusal",
|
|
66
66
|
"length_empty",
|
|
67
67
|
]);
|
|
68
|
+
const EXACT_CODE_CLASS = new Map([
|
|
69
|
+
["limits.max_tokens_exceeded", "budget"],
|
|
70
|
+
["limits.max_cost_exceeded", "budget"],
|
|
71
|
+
["limits.max_turns_exceeded", "limit"],
|
|
72
|
+
["limits.max_walltime_exceeded", "limit"],
|
|
73
|
+
]);
|
|
68
74
|
const DOTTED_PREFIX_CLASS = [
|
|
69
|
-
["
|
|
70
|
-
["limit.", "limit"],
|
|
75
|
+
["limits.", "limit"],
|
|
71
76
|
["output.", "output"],
|
|
72
77
|
["suspend.", "suspend"],
|
|
73
78
|
["review.", "review"],
|
|
@@ -79,6 +84,9 @@ const DOTTED_PREFIX_CLASS = [
|
|
|
79
84
|
export function errorClassOf(errorCode) {
|
|
80
85
|
if (!errorCode)
|
|
81
86
|
return "unknown";
|
|
87
|
+
const exact = EXACT_CODE_CLASS.get(errorCode);
|
|
88
|
+
if (exact !== undefined)
|
|
89
|
+
return exact;
|
|
82
90
|
for (const [prefix, cls] of DOTTED_PREFIX_CLASS) {
|
|
83
91
|
if (errorCode.startsWith(prefix))
|
|
84
92
|
return cls;
|
|
@@ -70,6 +70,11 @@ export declare function createTranscriptIntegrityPolicy(opts?: {
|
|
|
70
70
|
readAllow?: readonly string[];
|
|
71
71
|
tools?: string[];
|
|
72
72
|
}): ToolPolicy;
|
|
73
|
+
export interface AskDelegationProvenance {
|
|
74
|
+
readonly parentToolCallId: string;
|
|
75
|
+
readonly depth: number;
|
|
76
|
+
readonly agentName?: string;
|
|
77
|
+
}
|
|
73
78
|
export interface AskRequest {
|
|
74
79
|
toolName: string;
|
|
75
80
|
toolCallId: string;
|
|
@@ -81,12 +86,15 @@ export interface AskRequest {
|
|
|
81
86
|
readonly fromSubagent?: true;
|
|
82
87
|
readonly sourceAgentName?: string;
|
|
83
88
|
readonly requiresRealApproval?: boolean;
|
|
89
|
+
readonly delegation?: AskDelegationProvenance;
|
|
84
90
|
}
|
|
85
91
|
export type OnAsk = "deny" | "allow" | ((req: AskRequest, signal?: AbortSignal) => AskOutcome | Promise<AskOutcome>);
|
|
86
92
|
export type AskOutcome = boolean | "unavailable" | {
|
|
87
93
|
allow: boolean;
|
|
88
94
|
updatedInput?: unknown;
|
|
89
95
|
};
|
|
96
|
+
export declare function withDelegationProvenance(onAsk: OnAsk, delegation: AskDelegationProvenance): OnAsk;
|
|
97
|
+
export declare function askApproverIdentity(onAsk: unknown): unknown;
|
|
90
98
|
export type ResolvedAsk = PermissionResult & {
|
|
91
99
|
approverUnavailable?: true;
|
|
92
100
|
presentedInput?: unknown;
|
package/dist/core/tool-policy.js
CHANGED
|
@@ -516,6 +516,17 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
516
516
|
},
|
|
517
517
|
};
|
|
518
518
|
}
|
|
519
|
+
const delegatedApproverRoot = new WeakMap();
|
|
520
|
+
export function withDelegationProvenance(onAsk, delegation) {
|
|
521
|
+
if (typeof onAsk !== "function")
|
|
522
|
+
return onAsk;
|
|
523
|
+
const wrapper = (req, signal) => req.delegation !== undefined ? onAsk(req, signal) : onAsk({ ...req, delegation }, signal);
|
|
524
|
+
delegatedApproverRoot.set(wrapper, askApproverIdentity(onAsk));
|
|
525
|
+
return wrapper;
|
|
526
|
+
}
|
|
527
|
+
export function askApproverIdentity(onAsk) {
|
|
528
|
+
return typeof onAsk === "function" ? (delegatedApproverRoot.get(onAsk) ?? onAsk) : onAsk;
|
|
529
|
+
}
|
|
519
530
|
function tryCloneArgs(v) {
|
|
520
531
|
try {
|
|
521
532
|
const value = structuredClone(v);
|
package/dist/core/trace.d.ts
CHANGED
|
@@ -2,17 +2,10 @@ import type { TaskStatus, ToolEffect } from "./types.js";
|
|
|
2
2
|
import type { ThinkingLevel } from "../internal/harness-types.js";
|
|
3
3
|
import type { ToolManifestRow } from "../prompt-assembly/tool-catalog.js";
|
|
4
4
|
export interface TraceMechanismsSummary {
|
|
5
|
-
finalizeInjected?: true;
|
|
6
|
-
nudgesSent?: number;
|
|
7
|
-
capShrinks?: number;
|
|
8
|
-
callCutoffs?: number;
|
|
9
|
-
toolClamps?: number;
|
|
10
|
-
toolCuts?: number;
|
|
11
|
-
toolCutKills?: number;
|
|
12
|
-
pendingCutTools?: number;
|
|
13
5
|
finalVerifyInjected?: true;
|
|
14
6
|
finalVerifyInjections?: number;
|
|
15
7
|
attachmentsInjected?: number;
|
|
8
|
+
approachNoticesSent?: number;
|
|
16
9
|
repetitionCuts?: number;
|
|
17
10
|
repetitionSpared?: number;
|
|
18
11
|
}
|
|
@@ -141,8 +134,6 @@ export type TraceEvent = {
|
|
|
141
134
|
firstTokenMs?: number;
|
|
142
135
|
callStartedAt?: number;
|
|
143
136
|
costMicroUsd?: number;
|
|
144
|
-
callCap?: number;
|
|
145
|
-
capThinkingSkipped?: boolean;
|
|
146
137
|
stopReason?: string;
|
|
147
138
|
ts: number;
|
|
148
139
|
} | {
|
package/dist/core/types.d.ts
CHANGED
|
@@ -98,6 +98,7 @@ export interface ToolExecuteContext {
|
|
|
98
98
|
model?: Model;
|
|
99
99
|
thinkingLevel?: ThinkingLevel;
|
|
100
100
|
principal?: string;
|
|
101
|
+
onAsk?: import("./tool-policy.js").OnAsk;
|
|
101
102
|
oneShot?: boolean;
|
|
102
103
|
clientContext?: TaskSpec["clientContext"];
|
|
103
104
|
excludeTools?: readonly string[];
|
|
@@ -244,6 +245,22 @@ export type ImageInput = {
|
|
|
244
245
|
} | {
|
|
245
246
|
url: string;
|
|
246
247
|
};
|
|
248
|
+
export interface TaskLimits {
|
|
249
|
+
maxTokens?: number;
|
|
250
|
+
maxCostUsd?: number;
|
|
251
|
+
maxTurns?: number;
|
|
252
|
+
maxWalltimeMs?: number;
|
|
253
|
+
maxOutputTokens?: number;
|
|
254
|
+
approachNotice?: false | {
|
|
255
|
+
at?: [number, number];
|
|
256
|
+
};
|
|
257
|
+
budgetStreamCancel?: boolean;
|
|
258
|
+
degrade?: {
|
|
259
|
+
to: ModelRef;
|
|
260
|
+
atCostFraction: number;
|
|
261
|
+
};
|
|
262
|
+
brainCallGuardrailMs?: import("../brain/timeout.js").BrainCallGuardrailKnob;
|
|
263
|
+
}
|
|
247
264
|
export interface TaskSpec {
|
|
248
265
|
taskId?: string;
|
|
249
266
|
objective: string;
|
|
@@ -293,7 +310,7 @@ export interface TaskSpec {
|
|
|
293
310
|
resourceSuspend?: {
|
|
294
311
|
scope: string;
|
|
295
312
|
totalBudgetUsd?: number;
|
|
296
|
-
|
|
313
|
+
totalTokens?: number;
|
|
297
314
|
maxSlices?: number;
|
|
298
315
|
ttlMs?: number;
|
|
299
316
|
};
|
|
@@ -324,17 +341,7 @@ export interface TaskSpec {
|
|
|
324
341
|
note?: string;
|
|
325
342
|
};
|
|
326
343
|
};
|
|
327
|
-
limits?:
|
|
328
|
-
maxTurns?: number;
|
|
329
|
-
timeoutSec?: number;
|
|
330
|
-
maxOutputTokens?: number;
|
|
331
|
-
deadlineNudge?: false | {
|
|
332
|
-
at?: [number, number];
|
|
333
|
-
};
|
|
334
|
-
callCapByDeadline?: false;
|
|
335
|
-
gracefulFinalize?: false;
|
|
336
|
-
brainCallGuardrailMs?: import("../brain/timeout.js").BrainCallGuardrailKnob;
|
|
337
|
-
};
|
|
344
|
+
limits?: TaskLimits;
|
|
338
345
|
configOverrides?: ReadonlyArray<import("../config/catalog.js").ConfigOverrideDeclaration>;
|
|
339
346
|
forwardSubagentEvents?: boolean;
|
|
340
347
|
retainSubagentSessions?: boolean | {
|
|
@@ -343,13 +350,6 @@ export interface TaskSpec {
|
|
|
343
350
|
};
|
|
344
351
|
retainBackgroundProcesses?: boolean;
|
|
345
352
|
streamingToolExecution?: boolean;
|
|
346
|
-
maxCostUsd?: number;
|
|
347
|
-
maxTokens?: number;
|
|
348
|
-
budgetStreamCancel?: boolean;
|
|
349
|
-
degrade?: {
|
|
350
|
-
to: ModelRef;
|
|
351
|
-
atCostFraction: number;
|
|
352
|
-
};
|
|
353
353
|
outputSchema?: TSchema;
|
|
354
354
|
outputRetries?: number;
|
|
355
355
|
tracer?: import("./trace.js").TracerHook;
|
|
@@ -389,7 +389,7 @@ export interface TaskSpec {
|
|
|
389
389
|
} | undefined>;
|
|
390
390
|
signal?: AbortSignal;
|
|
391
391
|
}
|
|
392
|
-
export type TaskStatus = "completed" | "blocked" | "failed" | "
|
|
392
|
+
export type TaskStatus = "completed" | "blocked" | "failed" | "suspended" | "needs_review";
|
|
393
393
|
export interface RemoteEnvFailureNote {
|
|
394
394
|
op: "suspendVM" | "resumeVM" | "postResumeInit";
|
|
395
395
|
code: import("./remote-env.js").RemoteExecutionErrorCode;
|
|
@@ -411,6 +411,7 @@ export interface TaskResult {
|
|
|
411
411
|
remoteEnvFailures?: RemoteEnvFailureNote[];
|
|
412
412
|
errorMessage?: string;
|
|
413
413
|
errorCode?: string;
|
|
414
|
+
retryAfterMs?: number;
|
|
414
415
|
degraded?: {
|
|
415
416
|
from: string;
|
|
416
417
|
to: string;
|
|
@@ -446,17 +447,10 @@ export interface TaskResult {
|
|
|
446
447
|
costMicroUsd: number;
|
|
447
448
|
};
|
|
448
449
|
mechanisms?: {
|
|
449
|
-
finalizeInjected?: true;
|
|
450
|
-
nudgesSent?: number;
|
|
451
|
-
capShrinks?: number;
|
|
452
|
-
callCutoffs?: number;
|
|
453
|
-
toolClamps?: number;
|
|
454
|
-
toolCuts?: number;
|
|
455
|
-
toolCutKills?: number;
|
|
456
|
-
pendingCutTools?: number;
|
|
457
450
|
finalVerifyInjected?: true;
|
|
458
451
|
finalVerifyInjections?: number;
|
|
459
452
|
attachmentsInjected?: number;
|
|
453
|
+
approachNoticesSent?: number;
|
|
460
454
|
repetitionCuts?: number;
|
|
461
455
|
repetitionSpared?: number;
|
|
462
456
|
repetitionEvents?: Array<{
|
|
@@ -531,6 +525,7 @@ export type TaskEvent = ({
|
|
|
531
525
|
isError: boolean;
|
|
532
526
|
output?: unknown;
|
|
533
527
|
structured?: unknown;
|
|
528
|
+
errorCode?: string;
|
|
534
529
|
truncated?: boolean;
|
|
535
530
|
totalChars?: number;
|
|
536
531
|
} & TaskEventIdentity) | ({
|
|
@@ -568,7 +563,7 @@ export type TaskEvent = ({
|
|
|
568
563
|
modelFallback?: true;
|
|
569
564
|
fallbackReason?: "window";
|
|
570
565
|
clampedRatio?: number;
|
|
571
|
-
clampReason?: "budget" | "
|
|
566
|
+
clampReason?: "budget" | "tolerance";
|
|
572
567
|
phaseDurations?: import("./auto-compaction.js").CompactionPhaseDurations;
|
|
573
568
|
} & TaskEventIdentity) | ({
|
|
574
569
|
type: "compaction_outcome";
|
|
@@ -577,7 +572,7 @@ export type TaskEvent = ({
|
|
|
577
572
|
reason?: string;
|
|
578
573
|
} & TaskEventIdentity) | ({
|
|
579
574
|
type: "steering_injected";
|
|
580
|
-
source: "
|
|
575
|
+
source: "limit_approach" | "todo_reminder" | "task_reminder" | "tool_search_usage_reminder" | "changed_files" | "plan_mode" | "date_change" | "instructions_change" | "workflow_size_guideline_change" | "budget_usd" | "background_tasks" | "tools_delta" | "agent_listing" | "skills_listing" | "mcp_instructions" | "mcp_dropped_tools";
|
|
581
576
|
preview: string;
|
|
582
577
|
} & TaskEventIdentity) | ({
|
|
583
578
|
type: "diagnostics";
|
|
@@ -750,6 +745,8 @@ export interface RunnerDeps {
|
|
|
750
745
|
workflowRunStore?: import("./workflow-run-store.js").WorkflowRunStore;
|
|
751
746
|
backgroundAgentStore?: import("./background-agent-store.js").BackgroundAgentStore;
|
|
752
747
|
mailboxStore?: import("./mailbox-store.js").MailboxStore;
|
|
748
|
+
usageWindows?: readonly import("./usage-window-store.js").UsageWindow[];
|
|
749
|
+
usageWindowStore?: import("./usage-window-store.js").UsageWindowStore;
|
|
753
750
|
workflowJournalStore?: import("./workflow-journal-store.js").WorkflowJournalStore;
|
|
754
751
|
workflowScriptStore?: import("../orchestration/workflow-script-store.js").WorkflowScriptStore;
|
|
755
752
|
builtinWorkflows?: boolean;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface UsageWindow {
|
|
2
|
+
windowMs: number;
|
|
3
|
+
maxTokens: number;
|
|
4
|
+
anchor: "first-use" | "rolling";
|
|
5
|
+
}
|
|
6
|
+
export interface UsageSlot {
|
|
7
|
+
at: number;
|
|
8
|
+
tokens: number;
|
|
9
|
+
}
|
|
10
|
+
export interface UsageBucketRow {
|
|
11
|
+
windowMs: number;
|
|
12
|
+
openedAt: number;
|
|
13
|
+
tokens: number;
|
|
14
|
+
}
|
|
15
|
+
export interface UsageWindowRecord {
|
|
16
|
+
slots: readonly UsageSlot[];
|
|
17
|
+
buckets: readonly UsageBucketRow[];
|
|
18
|
+
}
|
|
19
|
+
export interface UsageWindowReading {
|
|
20
|
+
window: UsageWindow;
|
|
21
|
+
tokens: number;
|
|
22
|
+
exhausted: boolean;
|
|
23
|
+
retryAfterMs: number;
|
|
24
|
+
}
|
|
25
|
+
export interface UsageWindowStore {
|
|
26
|
+
charge(key: string, tokens: number, at: number, windows: readonly UsageWindow[]): Promise<void>;
|
|
27
|
+
read(key: string, windows: readonly UsageWindow[], now: number): Promise<readonly UsageWindowReading[]>;
|
|
28
|
+
}
|
|
29
|
+
export declare const GLOBAL_USAGE_KEY = "__usage_global__";
|
|
30
|
+
export declare const EMPTY_USAGE_WINDOW_RECORD: UsageWindowRecord;
|
|
31
|
+
export declare function resolveUsageWindows(windows: readonly UsageWindow[] | undefined): readonly UsageWindow[] | undefined;
|
|
32
|
+
export declare function chargeUsageRecord(record: UsageWindowRecord, tokens: number, at: number, windows: readonly UsageWindow[]): UsageWindowRecord;
|
|
33
|
+
export declare function readUsageRecord(record: UsageWindowRecord, windows: readonly UsageWindow[], now: number): UsageWindowReading[];
|
|
34
|
+
export declare function usageRetryAfterMs(readings: readonly UsageWindowReading[]): number | undefined;
|
|
35
|
+
export declare class InMemoryUsageWindowStore implements UsageWindowStore {
|
|
36
|
+
private readonly records;
|
|
37
|
+
charge(key: string, tokens: number, at: number, windows: readonly UsageWindow[]): Promise<void>;
|
|
38
|
+
read(key: string, windows: readonly UsageWindow[], now: number): Promise<readonly UsageWindowReading[]>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
export const GLOBAL_USAGE_KEY = "__usage_global__";
|
|
2
|
+
export const EMPTY_USAGE_WINDOW_RECORD = Object.freeze({
|
|
3
|
+
slots: Object.freeze([]),
|
|
4
|
+
buckets: Object.freeze([]),
|
|
5
|
+
});
|
|
6
|
+
function usageConfigError(code, message) {
|
|
7
|
+
const e = new Error(message);
|
|
8
|
+
e.code = code;
|
|
9
|
+
return e;
|
|
10
|
+
}
|
|
11
|
+
export function resolveUsageWindows(windows) {
|
|
12
|
+
if (windows === undefined)
|
|
13
|
+
return undefined;
|
|
14
|
+
if (!Array.isArray(windows)) {
|
|
15
|
+
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows must be an array (got ${typeof windows})`);
|
|
16
|
+
}
|
|
17
|
+
for (const w of windows) {
|
|
18
|
+
if (w === null || typeof w !== "object") {
|
|
19
|
+
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows entries must be objects (got ${String(w)})`);
|
|
20
|
+
}
|
|
21
|
+
if (typeof w.windowMs !== "number" || !Number.isFinite(w.windowMs) || w.windowMs <= 0) {
|
|
22
|
+
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows[].windowMs must be a finite number of milliseconds > 0 (got ${String(w.windowMs)})`);
|
|
23
|
+
}
|
|
24
|
+
if (typeof w.maxTokens !== "number" || !Number.isFinite(w.maxTokens) || w.maxTokens < 0) {
|
|
25
|
+
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows[].maxTokens must be a finite, non-negative number (got ${String(w.maxTokens)})`);
|
|
26
|
+
}
|
|
27
|
+
if (w.anchor !== "first-use" && w.anchor !== "rolling") {
|
|
28
|
+
throw usageConfigError("config.usage_window_invalid", `RunnerDeps.usageWindows[].anchor must be "first-use" or "rolling" (got ${String(w.anchor)})`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return windows;
|
|
32
|
+
}
|
|
33
|
+
function rollingHorizonMs(windows) {
|
|
34
|
+
let widest;
|
|
35
|
+
for (const w of windows) {
|
|
36
|
+
if (w.anchor !== "rolling")
|
|
37
|
+
continue;
|
|
38
|
+
if (widest === undefined || w.windowMs > widest)
|
|
39
|
+
widest = w.windowMs;
|
|
40
|
+
}
|
|
41
|
+
return widest;
|
|
42
|
+
}
|
|
43
|
+
export function chargeUsageRecord(record, tokens, at, windows) {
|
|
44
|
+
const horizon = rollingHorizonMs(windows);
|
|
45
|
+
const keptSlots = horizon === undefined ? [] : record.slots.filter((s) => s.at > at - horizon).map((s) => ({ at: s.at, tokens: s.tokens }));
|
|
46
|
+
if (horizon !== undefined && tokens > 0)
|
|
47
|
+
keptSlots.push({ at, tokens });
|
|
48
|
+
const buckets = [];
|
|
49
|
+
for (const w of windows) {
|
|
50
|
+
if (w.anchor !== "first-use")
|
|
51
|
+
continue;
|
|
52
|
+
if (buckets.some((b) => b.windowMs === w.windowMs))
|
|
53
|
+
continue;
|
|
54
|
+
const prior = record.buckets.find((b) => b.windowMs === w.windowMs);
|
|
55
|
+
const lapsed = prior === undefined || at >= prior.openedAt + w.windowMs;
|
|
56
|
+
if (lapsed) {
|
|
57
|
+
if (tokens > 0)
|
|
58
|
+
buckets.push({ windowMs: w.windowMs, openedAt: at, tokens });
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
buckets.push({ windowMs: w.windowMs, openedAt: prior.openedAt, tokens: prior.tokens + tokens });
|
|
62
|
+
}
|
|
63
|
+
return { slots: keptSlots, buckets };
|
|
64
|
+
}
|
|
65
|
+
export function readUsageRecord(record, windows, now) {
|
|
66
|
+
const readings = [];
|
|
67
|
+
for (const w of windows) {
|
|
68
|
+
let tokens = 0;
|
|
69
|
+
let freesAt;
|
|
70
|
+
if (w.anchor === "rolling") {
|
|
71
|
+
const floor = now - w.windowMs;
|
|
72
|
+
let oldest;
|
|
73
|
+
for (const s of record.slots) {
|
|
74
|
+
if (s.at <= floor)
|
|
75
|
+
continue;
|
|
76
|
+
tokens += s.tokens;
|
|
77
|
+
if (oldest === undefined || s.at < oldest)
|
|
78
|
+
oldest = s.at;
|
|
79
|
+
}
|
|
80
|
+
if (oldest !== undefined)
|
|
81
|
+
freesAt = oldest + w.windowMs;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const row = record.buckets.find((b) => b.windowMs === w.windowMs);
|
|
85
|
+
if (row !== undefined && now < row.openedAt + w.windowMs) {
|
|
86
|
+
tokens = row.tokens;
|
|
87
|
+
freesAt = row.openedAt + w.windowMs;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const exhausted = tokens >= w.maxTokens;
|
|
91
|
+
const retryAfterMs = exhausted ? Math.max(1, freesAt === undefined ? w.windowMs : freesAt - now) : 0;
|
|
92
|
+
readings.push({ window: w, tokens, exhausted, retryAfterMs });
|
|
93
|
+
}
|
|
94
|
+
return readings;
|
|
95
|
+
}
|
|
96
|
+
export function usageRetryAfterMs(readings) {
|
|
97
|
+
let worst;
|
|
98
|
+
for (const r of readings) {
|
|
99
|
+
if (!r.exhausted)
|
|
100
|
+
continue;
|
|
101
|
+
if (worst === undefined || r.retryAfterMs > worst)
|
|
102
|
+
worst = r.retryAfterMs;
|
|
103
|
+
}
|
|
104
|
+
return worst;
|
|
105
|
+
}
|
|
106
|
+
export class InMemoryUsageWindowStore {
|
|
107
|
+
records = new Map();
|
|
108
|
+
async charge(key, tokens, at, windows) {
|
|
109
|
+
const prior = this.records.get(key) ?? EMPTY_USAGE_WINDOW_RECORD;
|
|
110
|
+
this.records.set(key, chargeUsageRecord(prior, tokens, at, windows));
|
|
111
|
+
}
|
|
112
|
+
async read(key, windows, now) {
|
|
113
|
+
return readUsageRecord(this.records.get(key) ?? EMPTY_USAGE_WINDOW_RECORD, windows, now);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -432,23 +432,6 @@ export class NodeExecutionEnv {
|
|
|
432
432
|
return;
|
|
433
433
|
}
|
|
434
434
|
closeSpoolFds();
|
|
435
|
-
if (options?.onSpawn && child.pid !== undefined) {
|
|
436
|
-
const spawnedPid = child.pid;
|
|
437
|
-
const spawnedChild = child;
|
|
438
|
-
try {
|
|
439
|
-
options.onSpawn({
|
|
440
|
-
pid: spawnedPid,
|
|
441
|
-
kill: () => {
|
|
442
|
-
abortKillInFlight = true;
|
|
443
|
-
killProcessTree(spawnedPid, {
|
|
444
|
-
stillRunning: () => spawnedChild.exitCode === null && spawnedChild.signalCode === null,
|
|
445
|
-
});
|
|
446
|
-
},
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
catch {
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
435
|
const timeoutMs = resolveExecTimeoutMs(options?.timeout);
|
|
453
436
|
timeoutRef.current =
|
|
454
437
|
timeoutMs === undefined
|
|
@@ -580,11 +563,6 @@ export class NodeExecutionEnv {
|
|
|
580
563
|
return false;
|
|
581
564
|
if (spoolPumpRef.current)
|
|
582
565
|
clearInterval(spoolPumpRef.current);
|
|
583
|
-
try {
|
|
584
|
-
options?.onDetachAdopted?.();
|
|
585
|
-
}
|
|
586
|
-
catch {
|
|
587
|
-
}
|
|
588
566
|
if (timeoutRef.current)
|
|
589
567
|
clearTimeout(timeoutRef.current);
|
|
590
568
|
const dso = stdoutTail.result();
|
|
@@ -17,11 +17,6 @@ export interface HarnessLoopRecovery {
|
|
|
17
17
|
detect: (message: AssistantMessage) => boolean;
|
|
18
18
|
maxContinues?: number;
|
|
19
19
|
};
|
|
20
|
-
walltimeCutoff?: {
|
|
21
|
-
detect: (message: AssistantMessage) => boolean;
|
|
22
|
-
maxContinues?: number;
|
|
23
|
-
hasLiveWriteoutWindow?: () => boolean;
|
|
24
|
-
};
|
|
25
20
|
promptTooLong?: {
|
|
26
21
|
recover: (attempt: number) => Promise<boolean>;
|
|
27
22
|
detect?: (message: AssistantMessage) => boolean;
|
|
@@ -54,9 +49,8 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
54
49
|
private steeringQueueMode;
|
|
55
50
|
private maxOutputTokens?;
|
|
56
51
|
private maxOutputTokensPerCall?;
|
|
57
|
-
private callDeadlineMsPerCall?;
|
|
58
52
|
private stallTimeoutsPerCall?;
|
|
59
|
-
private
|
|
53
|
+
private abortResultDetails?;
|
|
60
54
|
private loopTrace?;
|
|
61
55
|
private resilience?;
|
|
62
56
|
private maxToolConcurrency?;
|