@sema-agent/core 3.0.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2382 -0
- package/dist/agents/cascade.d.ts +3 -1
- package/dist/agents/cascade.js +31 -32
- package/dist/agents/cumulative-stats.d.ts +29 -0
- package/dist/agents/cumulative-stats.js +29 -0
- package/dist/agents/observer.d.ts +4 -0
- package/dist/agents/observer.js +11 -10
- package/dist/agents/repair-loop.d.ts +2 -0
- package/dist/agents/repair-loop.js +48 -24
- package/dist/agents/retain-ledger.d.ts +2 -0
- package/dist/agents/retain-ledger.js +6 -5
- package/dist/agents/roster-store.d.ts +1 -0
- package/dist/agents/roster-store.js +3 -5
- package/dist/agents/send-message-tool.d.ts +1 -0
- package/dist/agents/send-message-tool.js +2 -0
- package/dist/agents/subagent.d.ts +3 -1
- package/dist/agents/subagent.js +79 -94
- package/dist/agents/teacher.d.ts +1 -9
- package/dist/agents/teacher.js +21 -24
- package/dist/agents/tool-filter.js +6 -7
- package/dist/agents/verify.d.ts +1 -0
- package/dist/agents/verify.js +15 -14
- package/dist/brain/anthropic.js +24 -21
- package/dist/brain/openai.js +24 -21
- package/dist/brain/stream-engine.js +5 -2
- package/dist/brain/stream-shared.d.ts +1 -0
- package/dist/brain/stream-shared.js +14 -0
- package/dist/brain/terminal-cause.d.ts +4 -0
- package/dist/brain/terminal-cause.js +12 -0
- package/dist/brain/tool-call-id.d.ts +1 -0
- package/dist/brain/tool-call-id.js +3 -0
- package/dist/brain/tool-call-repair.js +2 -1
- package/dist/core/arg-summary.d.ts +21 -1
- package/dist/core/arg-summary.js +61 -14
- package/dist/core/auto-compaction.d.ts +1 -0
- package/dist/core/auto-compaction.js +16 -25
- package/dist/core/background-agent-store.d.ts +22 -22
- package/dist/core/background-agent-store.js +19 -23
- package/dist/core/checkpoint-store.d.ts +6 -13
- package/dist/core/checkpoint-store.js +11 -5
- package/dist/core/file-snapshot-store.d.ts +8 -0
- package/dist/core/file-snapshot-store.js +4 -3
- package/dist/core/fs-write-gate-policy.js +2 -3
- package/dist/core/hooks.d.ts +4 -1
- package/dist/core/hooks.js +8 -18
- package/dist/core/lsp.js +4 -3
- package/dist/core/mailbox-store.d.ts +7 -10
- package/dist/core/mcp.d.ts +7 -10
- package/dist/core/mcp.js +7 -9
- package/dist/core/memory-engine/engine.d.ts +0 -1
- package/dist/core/memory-engine/engine.js +24 -34
- package/dist/core/memory-engine/file-backend.d.ts +1 -2
- package/dist/core/memory-engine/file-backend.js +25 -36
- package/dist/core/memory-engine/layout.d.ts +8 -0
- package/dist/core/memory-engine/layout.js +60 -4
- package/dist/core/memory-engine/scope-contract.js +9 -3
- package/dist/core/memory-engine/types.d.ts +1 -1
- package/dist/core/permission-rules.js +2 -3
- package/dist/core/runner/active-skill-scope.d.ts +0 -1
- package/dist/core/runner/active-skill-scope.js +2 -17
- package/dist/core/runner/assemble-result.d.ts +2 -7
- package/dist/core/runner/assemble-result.js +3 -4
- package/dist/core/runner/compaction-call-options.d.ts +7 -0
- package/dist/core/runner/compaction-call-options.js +30 -0
- package/dist/core/runner/prepare-task.d.ts +6 -23
- package/dist/core/runner/prepare-task.js +36 -61
- package/dist/core/runner/runtask.d.ts +1 -0
- package/dist/core/runner/runtask.js +84 -172
- package/dist/core/runner/session-rule-policy.js +7 -5
- package/dist/core/runner/teardown-bounded.d.ts +7 -0
- package/dist/core/runner/teardown-bounded.js +36 -0
- package/dist/core/runner/tool-disclosure.d.ts +2 -5
- package/dist/core/runner/turn-attachments.d.ts +5 -15
- package/dist/core/runner/turn-attachments.js +1 -1
- package/dist/core/safe-notify.d.ts +17 -0
- package/dist/core/safe-notify.js +59 -0
- package/dist/core/sensitive-path-policy.js +4 -4
- package/dist/core/session-reconcile.js +1 -2
- package/dist/core/skill-tool-specifier.js +2 -3
- package/dist/core/skills-directory.js +2 -3
- package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
- package/dist/core/stub-env.d.ts +2 -6
- package/dist/core/surrogate-safe-slice.d.ts +4 -0
- package/dist/core/surrogate-safe-slice.js +18 -0
- package/dist/core/task-registry-monitor.js +8 -13
- package/dist/core/task-registry-shared.d.ts +23 -1
- package/dist/core/task-registry-shared.js +16 -0
- package/dist/core/task-registry.d.ts +6 -1
- package/dist/core/task-registry.js +52 -87
- package/dist/core/task-tool-shape.d.ts +0 -2
- package/dist/core/task-tool-shape.js +2 -5
- package/dist/core/tool-errors.js +5 -4
- package/dist/core/tool-name-aliases.d.ts +1 -2
- package/dist/core/tool-name-aliases.js +42 -59
- package/dist/core/tool-policy.js +21 -17
- package/dist/core/tool-result-store.d.ts +1 -0
- package/dist/core/tool-result-store.js +17 -1
- package/dist/core/trace.d.ts +9 -9
- package/dist/core/types.d.ts +15 -12
- package/dist/core/untrusted-egress.d.ts +4 -2
- package/dist/core/untrusted-egress.js +28 -14
- package/dist/core/workflow-journal-store.d.ts +9 -20
- package/dist/core/workflow-run-store.d.ts +11 -10
- package/dist/core/workflow-run-store.js +22 -16
- package/dist/engine/compaction/utils.js +4 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +2 -24
- package/dist/engine/execution-env/node-execution-env.js +1 -1
- package/dist/engine/harness/agent-harness.d.ts +1 -0
- package/dist/engine/harness/agent-harness.js +13 -33
- package/dist/engine/harness/types.d.ts +29 -67
- package/dist/engine/llm/types.d.ts +1 -1
- package/dist/engine/loop/agent-loop.js +12 -14
- package/dist/engine/loop/types.d.ts +11 -9
- package/dist/engine/session/memory-repo.d.ts +2 -6
- package/dist/engine/session/session.d.ts +5 -30
- package/dist/index.d.ts +6 -3
- package/dist/index.js +4 -3
- package/dist/internal/harness-types.d.ts +3 -1
- package/dist/orchestration/run-spec.js +6 -4
- package/dist/orchestration/run-workflow-tool.js +3 -36
- package/dist/orchestration/workflow-governance.js +2 -1
- package/dist/orchestration/workflow.d.ts +4 -11
- package/dist/orchestration/workflow.js +164 -204
- package/dist/prompt-assembly/packs/sema-default.js +1 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +10 -9
- package/dist/prompt-assembly/turn-snapshot.d.ts +2 -5
- package/dist/prompts/default.js +1 -3
- package/dist/prompts/simple-sections.d.ts +0 -1
- package/dist/prompts/simple-sections.js +0 -1
- package/dist/stores/file/background-agent-store.d.ts +3 -12
- package/dist/stores/file/background-agent-store.js +3 -41
- package/dist/stores/file/checkpoint-store.js +6 -6
- package/dist/stores/file/mailbox-store.d.ts +2 -6
- package/dist/stores/file/session-policy-store.js +15 -1
- package/dist/stores/file/session-store.d.ts +2 -6
- package/dist/stores/file/workflow-journal-store.d.ts +3 -11
- package/dist/stores/file/workflow-run-store.d.ts +3 -7
- package/dist/stores/file/workflow-run-store.js +4 -17
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -0
- package/dist/tools/fs/bash-readonly-classifier.js +60 -25
- package/dist/tools/fs/fs-bash.js +330 -104
- package/dist/tools/fs/fs-pdf.d.ts +2 -12
- package/dist/tools/fs/fs-shared.js +2 -2
- package/dist/tools/fs/fs-write.js +0 -1
- package/dist/tools/fs/notebook.d.ts +2 -5
- package/dist/tools/fs/safety.d.ts +3 -0
- package/dist/tools/fs/safety.js +43 -14
- package/dist/tools/fs/search.js +5 -5
- package/dist/tools/monitor.d.ts +1 -0
- package/dist/tools/monitor.js +7 -5
- package/dist/tools/worktree.d.ts +2 -7
- package/dist/tools/worktree.js +3 -1
- package/package.json +6 -2
|
@@ -29,6 +29,10 @@ export class InMemoryToolResultStore {
|
|
|
29
29
|
totalChars = 0;
|
|
30
30
|
constructor(opts) {
|
|
31
31
|
this.opts = opts;
|
|
32
|
+
const cap = opts?.maxTotalChars;
|
|
33
|
+
if (cap !== undefined && Number.isNaN(cap)) {
|
|
34
|
+
throw new Error("InMemoryToolResultStore: maxTotalChars must be a number (got NaN) — omit it for an unbounded store");
|
|
35
|
+
}
|
|
32
36
|
}
|
|
33
37
|
put(ref, content) {
|
|
34
38
|
assertSafeToolResultRef(ref);
|
|
@@ -37,7 +41,7 @@ export class InMemoryToolResultStore {
|
|
|
37
41
|
this.map.set(ref, content);
|
|
38
42
|
this.totalChars += content.length;
|
|
39
43
|
const cap = this.opts?.maxTotalChars;
|
|
40
|
-
if (cap !== undefined && cap
|
|
44
|
+
if (cap !== undefined && Number.isFinite(cap)) {
|
|
41
45
|
for (const [oldRef, oldContent] of this.map) {
|
|
42
46
|
if (this.totalChars <= cap || oldRef === ref)
|
|
43
47
|
break;
|
|
@@ -93,6 +97,16 @@ export function isVolatileOffloadStore(store) {
|
|
|
93
97
|
return store instanceof InMemoryToolResultStore;
|
|
94
98
|
}
|
|
95
99
|
export const OFFLOAD_TOOL_NAME = "ReadToolResult";
|
|
100
|
+
export function createOffloadPersist(store, sessionId) {
|
|
101
|
+
return (toolCallId, fullText) => {
|
|
102
|
+
const ref = buildToolResultRef(sessionId, toolCallId);
|
|
103
|
+
void Promise.resolve(store.put(ref, fullText)).catch((err) => {
|
|
104
|
+
const cause = err instanceof Error ? err.message : String(err);
|
|
105
|
+
void Promise.resolve(store.put(ref, `[offload LOST at write time: ${cause} — the inline preview is all that survived]`)).catch(() => undefined);
|
|
106
|
+
});
|
|
107
|
+
return ref;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
96
110
|
export function offloadPagebackHint(ref, form, reachableTools) {
|
|
97
111
|
const activate = reachableTools !== undefined && !reachableTools.has(OFFLOAD_TOOL_NAME)
|
|
98
112
|
? `${OFFLOAD_TOOL_NAME} is not active yet — call ${TOOL_SEARCH_NAME} with {"query":"select:${OFFLOAD_TOOL_NAME}"} to activate it, then `
|
|
@@ -144,6 +158,8 @@ export function buildPreview(full, ref, sizes, reachableTools) {
|
|
|
144
158
|
`</persisted-output>`);
|
|
145
159
|
}
|
|
146
160
|
export function withToolResultOffload(tool, store, thresholdChars, sessionId, reachableTools) {
|
|
161
|
+
if (!(Number.isFinite(thresholdChars) && thresholdChars > 0))
|
|
162
|
+
return tool;
|
|
147
163
|
const wrappedExecute = async (toolCallId, params, signal, onUpdate) => {
|
|
148
164
|
const res = await tool.execute(toolCallId, params, signal, onUpdate);
|
|
149
165
|
if (totalTextChars(res.content) <= thresholdChars)
|
package/dist/core/trace.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { TaskStatus, ToolEffect } from "./types.js";
|
|
2
2
|
import type { ThinkingLevel } from "../internal/harness-types.js";
|
|
3
|
+
import type { ToolManifestRow } from "../prompt-assembly/tool-catalog.js";
|
|
3
4
|
export interface TraceMechanismsSummary {
|
|
4
5
|
finalizeInjected?: true;
|
|
5
6
|
nudgesSent?: number;
|
|
@@ -42,15 +43,7 @@ export type TraceEvent = {
|
|
|
42
43
|
hash: string;
|
|
43
44
|
contentHash?: string;
|
|
44
45
|
}>;
|
|
45
|
-
tools?:
|
|
46
|
-
wireName: string;
|
|
47
|
-
aliases: string[];
|
|
48
|
-
contractId: string;
|
|
49
|
-
implementationRevision: string;
|
|
50
|
-
cardId: string;
|
|
51
|
-
shapeDigest: string;
|
|
52
|
-
wireSchemaDigest: string;
|
|
53
|
-
}>;
|
|
46
|
+
tools?: ToolManifestRow[];
|
|
54
47
|
totalChars: number;
|
|
55
48
|
snapshot?: {
|
|
56
49
|
cacheIdentity: string;
|
|
@@ -183,6 +176,13 @@ export type TraceEvent = {
|
|
|
183
176
|
reason: "breaker_open" | "rate_limit" | "budget" | "server_error" | "last_resort";
|
|
184
177
|
atTurn: number;
|
|
185
178
|
ts: number;
|
|
179
|
+
} | {
|
|
180
|
+
kind: "observer.notify_failed";
|
|
181
|
+
version: 1;
|
|
182
|
+
taskId: string;
|
|
183
|
+
site: string;
|
|
184
|
+
message: string;
|
|
185
|
+
ts: number;
|
|
186
186
|
} | {
|
|
187
187
|
kind: "brain.failover";
|
|
188
188
|
version: 1;
|
package/dist/core/types.d.ts
CHANGED
|
@@ -57,6 +57,19 @@ export type ToolReturn = string | {
|
|
|
57
57
|
terminate?: boolean;
|
|
58
58
|
isError?: boolean;
|
|
59
59
|
};
|
|
60
|
+
export interface NestedUsage {
|
|
61
|
+
tokens: number;
|
|
62
|
+
turns: number;
|
|
63
|
+
tasks: number;
|
|
64
|
+
costMicroUsd?: number;
|
|
65
|
+
}
|
|
66
|
+
export interface NestedUsageAccum {
|
|
67
|
+
tokens: number;
|
|
68
|
+
turns: number;
|
|
69
|
+
tasks: number;
|
|
70
|
+
costMicroUsd: number;
|
|
71
|
+
anyUnpriced: boolean;
|
|
72
|
+
}
|
|
60
73
|
export interface ToolExecuteContext {
|
|
61
74
|
toolCallId: string;
|
|
62
75
|
signal?: AbortSignal;
|
|
@@ -81,12 +94,7 @@ export interface ToolExecuteContext {
|
|
|
81
94
|
release: () => Promise<void>;
|
|
82
95
|
} | null>;
|
|
83
96
|
parentCwd?: string;
|
|
84
|
-
reportUsage?: (usage:
|
|
85
|
-
tokens: number;
|
|
86
|
-
turns: number;
|
|
87
|
-
tasks: number;
|
|
88
|
-
costMicroUsd?: number;
|
|
89
|
-
}) => void;
|
|
97
|
+
reportUsage?: (usage: NestedUsage) => void;
|
|
90
98
|
model?: Model;
|
|
91
99
|
thinkingLevel?: ThinkingLevel;
|
|
92
100
|
principal?: string;
|
|
@@ -412,12 +420,7 @@ export interface TaskResult {
|
|
|
412
420
|
outputTokens?: number;
|
|
413
421
|
cacheWriteTokensLong?: number;
|
|
414
422
|
costMicroUsd?: number;
|
|
415
|
-
nested?:
|
|
416
|
-
tokens: number;
|
|
417
|
-
turns: number;
|
|
418
|
-
tasks: number;
|
|
419
|
-
costMicroUsd?: number;
|
|
420
|
-
};
|
|
423
|
+
nested?: NestedUsage;
|
|
421
424
|
memory?: {
|
|
422
425
|
tokens: number;
|
|
423
426
|
costMicroUsd: number;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import { type RedactionReport } from "./arg-summary.js";
|
|
2
|
+
export type { RedactionFinding, RedactionReport, RedactionConfidence } from "./arg-summary.js";
|
|
3
|
+
export declare function redactSecrets(s: string, report?: RedactionReport): string;
|
|
4
|
+
export declare function redactHostLeaks(s: string, report?: RedactionReport): string;
|
|
3
5
|
export declare function boundedRedactedSummary(value: unknown, max: number): string;
|
|
4
6
|
export declare function untrustedEgressForHuman(value: unknown, opts: {
|
|
5
7
|
label: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { delimitUntrusted } from "./untrusted-text.js";
|
|
2
|
-
import { scrubSecrets } from "./arg-summary.js";
|
|
2
|
+
import { scrubSecrets, SECRET_PASSES, runRedactionPasses } from "./arg-summary.js";
|
|
3
|
+
import { sliceHeadSafe } from "./surrogate-safe-slice.js";
|
|
3
4
|
const URI_SCHEME = String.raw `[A-Za-z][A-Za-z0-9+.\-_]{0,63}`;
|
|
4
5
|
const CREDENTIALS_IN_AUTHORITY = new RegExp(String.raw `(${URI_SCHEME}:\/\/)((?:[^/\s"'@]*@)+)`, "gi");
|
|
5
6
|
const URL_OF_ANY_PROTOCOL = new RegExp(String.raw `${URI_SCHEME}:\/\/[^\s"'\`]+`, "gi");
|
|
@@ -14,15 +15,27 @@ function redactUserinfo(scheme, userinfoWithAt) {
|
|
|
14
15
|
}
|
|
15
16
|
return `${scheme}${userinfo.slice(0, colonIdx)}:[redacted-credentials]@`;
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const SECRET_TIER_PASSES = [
|
|
19
|
+
...SECRET_PASSES,
|
|
20
|
+
{
|
|
21
|
+
kind: "url-credentials",
|
|
22
|
+
confidence: "medium",
|
|
23
|
+
marker: "[redacted-credentials]",
|
|
24
|
+
re: CREDENTIALS_IN_AUTHORITY,
|
|
25
|
+
replace: (_m, scheme, userinfo) => redactUserinfo(scheme, userinfo),
|
|
26
|
+
},
|
|
27
|
+
{ kind: "signed-url-param", confidence: "high", marker: "[redacted]", re: /([?&#](?:sig|signature|sas|code)=)[^&\s"'#]+/gi, replace: "$1[redacted]" },
|
|
28
|
+
];
|
|
29
|
+
export function redactSecrets(s, report) {
|
|
30
|
+
return runRedactionPasses(s, SECRET_TIER_PASSES, report);
|
|
21
31
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
const HOST_LEAK_PASSES = [
|
|
33
|
+
...SECRET_TIER_PASSES,
|
|
34
|
+
{ kind: "url", confidence: "medium", marker: "[redacted-url]", re: URL_OF_ANY_PROTOCOL, replace: "[redacted-url]" },
|
|
35
|
+
{ kind: "fs-path", confidence: "low", marker: "[redacted-path]", re: /(?:\/[A-Za-z0-9_.-]+){2,}/g, replace: "[redacted-path]" },
|
|
36
|
+
];
|
|
37
|
+
export function redactHostLeaks(s, report) {
|
|
38
|
+
return runRedactionPasses(s, HOST_LEAK_PASSES, report);
|
|
26
39
|
}
|
|
27
40
|
const REDACTION_MARKER_RE = /\[redacted(?:-[a-z]+)?\]/g;
|
|
28
41
|
function countRedactionMarkers(s) {
|
|
@@ -52,16 +65,17 @@ function boundedString(value, max, redact) {
|
|
|
52
65
|
if (s.length <= max)
|
|
53
66
|
return s;
|
|
54
67
|
const totalMarkers = countRedactionMarkers(s);
|
|
55
|
-
const plainSuffix = (
|
|
56
|
-
const enrichedSuffix = (
|
|
57
|
-
const lost = totalMarkers - countRedactionMarkers(
|
|
58
|
-
return lost > 0 ? `…[+${s.length -
|
|
68
|
+
const plainSuffix = (kept) => `…[+${s.length - kept.length} chars]`;
|
|
69
|
+
const enrichedSuffix = (kept) => {
|
|
70
|
+
const lost = totalMarkers - countRedactionMarkers(kept);
|
|
71
|
+
return lost > 0 ? `…[+${s.length - kept.length} chars, ${lost} redaction marker(s) among them]` : plainSuffix(kept);
|
|
59
72
|
};
|
|
60
73
|
const converge = (suffixFor) => {
|
|
61
74
|
let keep = max;
|
|
62
75
|
let out = "";
|
|
63
76
|
for (let i = 0; i < 4; i++) {
|
|
64
|
-
|
|
77
|
+
const kept = sliceHeadSafe(s, keep);
|
|
78
|
+
out = `${kept}${suffixFor(kept)}`;
|
|
65
79
|
if (out.length <= max)
|
|
66
80
|
return out;
|
|
67
81
|
if (keep === 0)
|
|
@@ -3,23 +3,20 @@ export interface WorkflowJournalEntry {
|
|
|
3
3
|
callKey: string;
|
|
4
4
|
result: TaskResult;
|
|
5
5
|
}
|
|
6
|
+
export interface ResumeClaimArgs {
|
|
7
|
+
sourceRunId: string;
|
|
8
|
+
newRunId: string;
|
|
9
|
+
scope: string;
|
|
10
|
+
}
|
|
6
11
|
export interface WorkflowJournalStore {
|
|
7
12
|
load(runId: string, scope: string): Promise<WorkflowJournalEntry[]>;
|
|
8
13
|
append(runId: string, scope: string, entry: WorkflowJournalEntry): Promise<void>;
|
|
9
14
|
locator?(runId: string, scope: string): string | undefined;
|
|
10
|
-
resumeClaim?(input: {
|
|
11
|
-
sourceRunId: string;
|
|
12
|
-
newRunId: string;
|
|
13
|
-
scope: string;
|
|
14
|
-
}): Promise<{
|
|
15
|
+
resumeClaim?(input: ResumeClaimArgs): Promise<{
|
|
15
16
|
granted: boolean;
|
|
16
17
|
holder?: string;
|
|
17
18
|
}>;
|
|
18
|
-
releaseResumeClaim?(input:
|
|
19
|
-
sourceRunId: string;
|
|
20
|
-
newRunId: string;
|
|
21
|
-
scope: string;
|
|
22
|
-
}): Promise<void>;
|
|
19
|
+
releaseResumeClaim?(input: ResumeClaimArgs): Promise<void>;
|
|
23
20
|
}
|
|
24
21
|
export declare const MAX_JOURNAL_RESULT_BYTES: number;
|
|
25
22
|
export declare function oversizeJournalResult(serialized: string): boolean;
|
|
@@ -31,19 +28,11 @@ export declare class InMemoryWorkflowJournalStore implements WorkflowJournalStor
|
|
|
31
28
|
private readonly runs;
|
|
32
29
|
private readonly resumeClaims;
|
|
33
30
|
private claimsForScope;
|
|
34
|
-
resumeClaim(input: {
|
|
35
|
-
sourceRunId: string;
|
|
36
|
-
newRunId: string;
|
|
37
|
-
scope: string;
|
|
38
|
-
}): Promise<{
|
|
31
|
+
resumeClaim(input: ResumeClaimArgs): Promise<{
|
|
39
32
|
granted: boolean;
|
|
40
33
|
holder?: string;
|
|
41
34
|
}>;
|
|
42
|
-
releaseResumeClaim(input:
|
|
43
|
-
sourceRunId: string;
|
|
44
|
-
newRunId: string;
|
|
45
|
-
scope: string;
|
|
46
|
-
}): Promise<void>;
|
|
35
|
+
releaseResumeClaim(input: ResumeClaimArgs): Promise<void>;
|
|
47
36
|
load(runId: string, scope: string): Promise<WorkflowJournalEntry[]>;
|
|
48
37
|
append(runId: string, scope: string, entry: WorkflowJournalEntry): Promise<void>;
|
|
49
38
|
}
|
|
@@ -21,22 +21,27 @@ export declare class WorkflowRunStoreError extends Error {
|
|
|
21
21
|
readonly code: "workflow_run.already_exists";
|
|
22
22
|
constructor(code: "workflow_run.already_exists", message: string);
|
|
23
23
|
}
|
|
24
|
+
export interface WorkflowRunListByScopeOptions {
|
|
25
|
+
status?: WorkflowRunStatus;
|
|
26
|
+
limit?: number;
|
|
27
|
+
session?: string;
|
|
28
|
+
}
|
|
24
29
|
export interface WorkflowRunStore {
|
|
25
30
|
put(id: string, run: WorkflowRun): Promise<void>;
|
|
26
31
|
get(id: string): Promise<WorkflowRun | null>;
|
|
27
32
|
update(id: string, scope: string, run: WorkflowRun, expect?: {
|
|
28
33
|
rev: number;
|
|
29
34
|
}): Promise<boolean>;
|
|
30
|
-
listByScope(scope: string, opts?:
|
|
31
|
-
status?: WorkflowRunStatus;
|
|
32
|
-
limit?: number;
|
|
33
|
-
session?: string;
|
|
34
|
-
}): Promise<WorkflowRunSummary[]>;
|
|
35
|
+
listByScope(scope: string, opts?: WorkflowRunListByScopeOptions): Promise<WorkflowRunSummary[]>;
|
|
35
36
|
reap(scope: string, now: number, opts?: {
|
|
36
37
|
maxAgeMs?: number;
|
|
37
38
|
keep?: number;
|
|
38
39
|
}): Promise<number>;
|
|
39
40
|
}
|
|
41
|
+
export declare function nextWorkflowRunOnUpdate(cur: WorkflowRun | undefined, id: string, scope: string, run: WorkflowRun, expect?: {
|
|
42
|
+
rev: number;
|
|
43
|
+
}): WorkflowRun | null;
|
|
44
|
+
export declare function queryWorkflowRuns(runs: Iterable<WorkflowRun>, scope: string, opts?: WorkflowRunListByScopeOptions): WorkflowRunSummary[];
|
|
40
45
|
export declare class InMemoryWorkflowRunStore implements WorkflowRunStore {
|
|
41
46
|
private runs;
|
|
42
47
|
put(id: string, run: WorkflowRun): Promise<void>;
|
|
@@ -44,11 +49,7 @@ export declare class InMemoryWorkflowRunStore implements WorkflowRunStore {
|
|
|
44
49
|
update(id: string, scope: string, run: WorkflowRun, expect?: {
|
|
45
50
|
rev: number;
|
|
46
51
|
}): Promise<boolean>;
|
|
47
|
-
listByScope(scope: string, opts?:
|
|
48
|
-
status?: WorkflowRunStatus;
|
|
49
|
-
limit?: number;
|
|
50
|
-
session?: string;
|
|
51
|
-
}): Promise<WorkflowRunSummary[]>;
|
|
52
|
+
listByScope(scope: string, opts?: WorkflowRunListByScopeOptions): Promise<WorkflowRunSummary[]>;
|
|
52
53
|
reap(scope: string, now: number, opts?: {
|
|
53
54
|
maxAgeMs?: number;
|
|
54
55
|
keep?: number;
|
|
@@ -28,6 +28,25 @@ export class WorkflowRunStoreError extends Error {
|
|
|
28
28
|
this.name = "WorkflowRunStoreError";
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
export function nextWorkflowRunOnUpdate(cur, id, scope, run, expect) {
|
|
32
|
+
if (!cur || cur.scope !== scope)
|
|
33
|
+
return null;
|
|
34
|
+
if (expect !== undefined && (cur.rev ?? 0) !== expect.rev)
|
|
35
|
+
return null;
|
|
36
|
+
const next = structuredClone(run);
|
|
37
|
+
next.id = id;
|
|
38
|
+
next.scope = scope;
|
|
39
|
+
next.rev = (cur.rev ?? 0) + 1;
|
|
40
|
+
return next;
|
|
41
|
+
}
|
|
42
|
+
export function queryWorkflowRuns(runs, scope, opts) {
|
|
43
|
+
const rows = [...runs].filter((r) => r.scope === scope &&
|
|
44
|
+
(opts?.status === undefined || r.status === opts.status) &&
|
|
45
|
+
(opts?.session === undefined || r.originatingSessionId === opts.session));
|
|
46
|
+
rows.sort((a, b) => b.createdAt - a.createdAt);
|
|
47
|
+
const limited = opts?.limit !== undefined ? rows.slice(0, Math.max(0, opts.limit)) : rows;
|
|
48
|
+
return limited.map(summarizeWorkflowRun);
|
|
49
|
+
}
|
|
31
50
|
export class InMemoryWorkflowRunStore {
|
|
32
51
|
runs = new Map();
|
|
33
52
|
async put(id, run) {
|
|
@@ -44,27 +63,14 @@ export class InMemoryWorkflowRunStore {
|
|
|
44
63
|
return run ? structuredClone(run) : null;
|
|
45
64
|
}
|
|
46
65
|
async update(id, scope, run, expect) {
|
|
47
|
-
const
|
|
48
|
-
if (!
|
|
66
|
+
const next = nextWorkflowRunOnUpdate(this.runs.get(id), id, scope, run, expect);
|
|
67
|
+
if (!next)
|
|
49
68
|
return false;
|
|
50
|
-
}
|
|
51
|
-
if (expect !== undefined && (cur.rev ?? 0) !== expect.rev) {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
const next = structuredClone(run);
|
|
55
|
-
next.id = id;
|
|
56
|
-
next.scope = scope;
|
|
57
|
-
next.rev = (cur.rev ?? 0) + 1;
|
|
58
69
|
this.runs.set(id, next);
|
|
59
70
|
return true;
|
|
60
71
|
}
|
|
61
72
|
async listByScope(scope, opts) {
|
|
62
|
-
|
|
63
|
-
(opts?.status === undefined || r.status === opts.status) &&
|
|
64
|
-
(opts?.session === undefined || r.originatingSessionId === opts.session));
|
|
65
|
-
rows.sort((a, b) => b.createdAt - a.createdAt);
|
|
66
|
-
const limited = opts?.limit !== undefined ? rows.slice(0, Math.max(0, opts.limit)) : rows;
|
|
67
|
-
return limited.map(summarizeWorkflowRun);
|
|
73
|
+
return queryWorkflowRuns(this.runs.values(), scope, opts);
|
|
68
74
|
}
|
|
69
75
|
async reap(scope, now, opts) {
|
|
70
76
|
if (opts?.maxAgeMs === undefined && opts?.keep === undefined)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeLlmMessageContent } from "../harness/messages.js";
|
|
2
|
+
import { sliceHeadSafe } from "../../core/surrogate-safe-slice.js";
|
|
2
3
|
import { cutEnginePrefix, cutEngineSegments, flattenableUserText } from "../../core/untrusted-text.js";
|
|
3
4
|
import { fileArgPath } from "../../tools/fs/safety.js";
|
|
4
5
|
export function createFileOps() {
|
|
@@ -287,11 +288,12 @@ function truncateForSummary(text, maxChars) {
|
|
|
287
288
|
let keep = maxChars;
|
|
288
289
|
let out = "";
|
|
289
290
|
for (let i = 0; i < 4; i++) {
|
|
290
|
-
|
|
291
|
+
const kept = sliceHeadSafe(text, keep);
|
|
292
|
+
out = `${kept}\n\n[... ${text.length - kept.length} more characters truncated]`;
|
|
291
293
|
if (out.length <= maxChars)
|
|
292
294
|
break;
|
|
293
295
|
if (keep === 0)
|
|
294
|
-
return maxChars >= 1 ? `${text
|
|
296
|
+
return maxChars >= 1 ? `${sliceHeadSafe(text, maxChars - 1)}…` : "";
|
|
295
297
|
keep = Math.max(0, keep - (out.length - maxChars));
|
|
296
298
|
}
|
|
297
299
|
return out.length < text.length ? out : text;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ExecutionEnv, ExecutionError, FileError, type FileInfo, type Result } from "../harness/types.js";
|
|
1
|
+
import { type ExecResult, type ExecutionEnv, ExecutionError, type ExecutionEnvExecOptions, FileError, type FileInfo, type Result } from "../harness/types.js";
|
|
2
2
|
import type { BackgroundShellCapability, BackgroundShellId, BackgroundPoll, BackgroundSpawnOptions } from "../../core/background-shell.js";
|
|
3
3
|
import { BackgroundShellError } from "../../core/background-shell.js";
|
|
4
4
|
import type { SchedulerCapability, ScheduledIntent, SchedulerContext, ScheduledTaskId, ScheduledTaskSummary } from "../../core/scheduler.js";
|
|
@@ -54,29 +54,7 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
|
|
|
54
54
|
list(ctx: SchedulerContext): Promise<Result<ScheduledTaskSummary[], SchedulerError>>;
|
|
55
55
|
absolutePath(path: string): Promise<Result<string, FileError>>;
|
|
56
56
|
joinPath(parts: string[]): Promise<Result<string, FileError>>;
|
|
57
|
-
exec(command: string, options?:
|
|
58
|
-
cwd?: string;
|
|
59
|
-
env?: Record<string, string>;
|
|
60
|
-
timeout?: number;
|
|
61
|
-
abortSignal?: AbortSignal;
|
|
62
|
-
onStdout?: (chunk: string) => void;
|
|
63
|
-
onStderr?: (chunk: string) => void;
|
|
64
|
-
detachSignal?: AbortSignal;
|
|
65
|
-
onSpawn?: (handle: {
|
|
66
|
-
pid: number;
|
|
67
|
-
kill: () => void;
|
|
68
|
-
}) => void;
|
|
69
|
-
onDetachAdopted?: () => void;
|
|
70
|
-
autoBackgroundOnTimeout?: boolean;
|
|
71
|
-
}): Promise<Result<{
|
|
72
|
-
stdout: string;
|
|
73
|
-
stderr: string;
|
|
74
|
-
exitCode: number;
|
|
75
|
-
detached?: {
|
|
76
|
-
shellId: string;
|
|
77
|
-
cause?: "timeout";
|
|
78
|
-
};
|
|
79
|
-
}, ExecutionError>>;
|
|
57
|
+
exec(command: string, options?: ExecutionEnvExecOptions): Promise<Result<ExecResult, ExecutionError>>;
|
|
80
58
|
readTextFile(path: string, abortSignal?: AbortSignal): Promise<Result<string, FileError>>;
|
|
81
59
|
readTextLines(path: string, options?: {
|
|
82
60
|
maxLines?: number;
|
|
@@ -270,7 +270,7 @@ export class NodeExecutionEnv {
|
|
|
270
270
|
this.backgroundCapabilities = {
|
|
271
271
|
supported: true,
|
|
272
272
|
maxConcurrent: 8,
|
|
273
|
-
defaultBgTimeoutSec:
|
|
273
|
+
defaultBgTimeoutSec: 60 * 60,
|
|
274
274
|
maxBgTimeoutSec: 2 * 60 * 60,
|
|
275
275
|
supportsDetach: true,
|
|
276
276
|
retainBackgroundProcesses: this.retainBackgroundProcesses,
|
|
@@ -92,6 +92,7 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
92
92
|
images?: ImageContent[];
|
|
93
93
|
} & UserMessageProvenance): Promise<AssistantMessage>;
|
|
94
94
|
private static emptyInjection;
|
|
95
|
+
private enqueueInjection;
|
|
95
96
|
steer(text: string, options?: {
|
|
96
97
|
images?: ImageContent[];
|
|
97
98
|
} & UserMessageProvenance): Promise<void>;
|
|
@@ -478,14 +478,7 @@ export class AgentHarness {
|
|
|
478
478
|
details: result.details,
|
|
479
479
|
isError,
|
|
480
480
|
});
|
|
481
|
-
return patch
|
|
482
|
-
? {
|
|
483
|
-
content: patch.content,
|
|
484
|
-
details: patch.details,
|
|
485
|
-
isError: patch.isError,
|
|
486
|
-
terminate: patch.terminate,
|
|
487
|
-
}
|
|
488
|
-
: undefined;
|
|
481
|
+
return patch;
|
|
489
482
|
},
|
|
490
483
|
prepareNextTurn: async () => {
|
|
491
484
|
await this.flushPendingSessionWrites();
|
|
@@ -725,42 +718,29 @@ export class AgentHarness {
|
|
|
725
718
|
static emptyInjection(text, options) {
|
|
726
719
|
return text.trim().length === 0 && (options?.images === undefined || options.images.length === 0);
|
|
727
720
|
}
|
|
721
|
+
async enqueueInjection(queue, text, options) {
|
|
722
|
+
if (AgentHarness.emptyInjection(text, options))
|
|
723
|
+
return;
|
|
724
|
+
const m = createUserMessage(text, options?.images, options);
|
|
725
|
+
if (options?.enginePayload !== undefined)
|
|
726
|
+
engineNotePayloads.set(m, options.enginePayload);
|
|
727
|
+
queue.push(m);
|
|
728
|
+
await this.emitQueueUpdate();
|
|
729
|
+
}
|
|
728
730
|
async steer(text, options) {
|
|
729
731
|
if (this.phase === "idle") {
|
|
730
732
|
throw new AgentHarnessError("invalid_state", "Cannot steer while idle");
|
|
731
733
|
}
|
|
732
|
-
|
|
733
|
-
return;
|
|
734
|
-
{
|
|
735
|
-
const m = createUserMessage(text, options?.images, options);
|
|
736
|
-
if (options?.enginePayload !== undefined)
|
|
737
|
-
engineNotePayloads.set(m, options.enginePayload);
|
|
738
|
-
this.steerQueue.push(m);
|
|
739
|
-
}
|
|
740
|
-
await this.emitQueueUpdate();
|
|
734
|
+
await this.enqueueInjection(this.steerQueue, text, options);
|
|
741
735
|
}
|
|
742
736
|
async followUp(text, options) {
|
|
743
737
|
if (this.phase === "idle") {
|
|
744
738
|
throw new AgentHarnessError("invalid_state", "Cannot follow up while idle");
|
|
745
739
|
}
|
|
746
|
-
|
|
747
|
-
return;
|
|
748
|
-
{
|
|
749
|
-
const m = createUserMessage(text, options?.images, options);
|
|
750
|
-
if (options?.enginePayload !== undefined)
|
|
751
|
-
engineNotePayloads.set(m, options.enginePayload);
|
|
752
|
-
this.followUpQueue.push(m);
|
|
753
|
-
}
|
|
754
|
-
await this.emitQueueUpdate();
|
|
740
|
+
await this.enqueueInjection(this.followUpQueue, text, options);
|
|
755
741
|
}
|
|
756
742
|
async nextTurn(text, options) {
|
|
757
|
-
|
|
758
|
-
return;
|
|
759
|
-
const m = createUserMessage(text, options?.images, options);
|
|
760
|
-
if (options?.enginePayload !== undefined)
|
|
761
|
-
engineNotePayloads.set(m, options.enginePayload);
|
|
762
|
-
this.nextTurnQueue.push(m);
|
|
763
|
-
await this.emitQueueUpdate();
|
|
743
|
+
await this.enqueueInjection(this.nextTurnQueue, text, options);
|
|
764
744
|
}
|
|
765
745
|
async appendMessage(message) {
|
|
766
746
|
try {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { PromptEpochDescriptor } from "../../prompt-assembly/epoch.js";
|
|
1
2
|
import type { DocumentContent, ImageContent, Model, SimpleStreamOptions, TextContent, Transport } from "../llm/index.js";
|
|
2
|
-
import type { AgentEvent, AgentMessage, AgentTool, QueueMode, ThinkingLevel } from "../loop/types.js";
|
|
3
|
+
import type { AfterToolCallResult, AgentEvent, AgentMessage, AgentTool, BeforeToolCallResult, QueueMode, ThinkingLevel } from "../loop/types.js";
|
|
3
4
|
import type { AgentCoreRuntimeDeps } from "../loop/runtime-deps.js";
|
|
4
5
|
export type Result<TValue, TError> = {
|
|
5
6
|
ok: true;
|
|
@@ -129,16 +130,17 @@ export interface FileSystem {
|
|
|
129
130
|
}): Promise<Result<string, FileError>>;
|
|
130
131
|
cleanup(): Promise<void>;
|
|
131
132
|
}
|
|
133
|
+
export interface ExecResult {
|
|
134
|
+
stdout: string;
|
|
135
|
+
stderr: string;
|
|
136
|
+
exitCode: number;
|
|
137
|
+
detached?: {
|
|
138
|
+
shellId: string;
|
|
139
|
+
cause?: "timeout";
|
|
140
|
+
};
|
|
141
|
+
}
|
|
132
142
|
export interface Shell {
|
|
133
|
-
exec(command: string, options?: ExecutionEnvExecOptions): Promise<Result<
|
|
134
|
-
stdout: string;
|
|
135
|
-
stderr: string;
|
|
136
|
-
exitCode: number;
|
|
137
|
-
detached?: {
|
|
138
|
-
shellId: string;
|
|
139
|
-
cause?: "timeout";
|
|
140
|
-
};
|
|
141
|
-
}, ExecutionError>>;
|
|
143
|
+
exec(command: string, options?: ExecutionEnvExecOptions): Promise<Result<ExecResult, ExecutionError>>;
|
|
142
144
|
cleanup(): Promise<void>;
|
|
143
145
|
}
|
|
144
146
|
export interface ExecutionEnv extends FileSystem, Shell {
|
|
@@ -195,15 +197,8 @@ export interface LeafEntry extends SessionTreeEntryBase {
|
|
|
195
197
|
type: "leaf";
|
|
196
198
|
targetId: string | null;
|
|
197
199
|
}
|
|
198
|
-
export interface PromptEpochEntry extends SessionTreeEntryBase {
|
|
200
|
+
export interface PromptEpochEntry extends SessionTreeEntryBase, PromptEpochDescriptor {
|
|
199
201
|
type: "prompt_epoch";
|
|
200
|
-
epoch: number;
|
|
201
|
-
artifactDigest: string;
|
|
202
|
-
packId: string;
|
|
203
|
-
assemblyApi: number;
|
|
204
|
-
activatedBy: "session_start" | "compaction" | "legacy_migration";
|
|
205
|
-
centerArtifactDigest?: string;
|
|
206
|
-
sourceRevision?: string;
|
|
207
202
|
}
|
|
208
203
|
export interface AnnouncedListingEntry extends SessionTreeEntryBase {
|
|
209
204
|
type: "announced_listing";
|
|
@@ -211,28 +206,22 @@ export interface AnnouncedListingEntry extends SessionTreeEntryBase {
|
|
|
211
206
|
skills?: string[];
|
|
212
207
|
models?: string[];
|
|
213
208
|
}
|
|
214
|
-
export interface
|
|
215
|
-
|
|
209
|
+
export interface ActiveWorktreeSession {
|
|
210
|
+
worktreeDir: string;
|
|
211
|
+
originalCwd: string;
|
|
212
|
+
baseSha: string;
|
|
213
|
+
entered?: boolean;
|
|
214
|
+
}
|
|
215
|
+
export interface WorkspaceState {
|
|
216
216
|
taskRoot: string;
|
|
217
217
|
handsCwd?: string;
|
|
218
|
-
activeWorktree?:
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
entered?: boolean;
|
|
223
|
-
};
|
|
218
|
+
activeWorktree?: ActiveWorktreeSession;
|
|
219
|
+
}
|
|
220
|
+
export interface WorkspaceStateEntry extends SessionTreeEntryBase, WorkspaceState {
|
|
221
|
+
type: "workspace_state";
|
|
224
222
|
}
|
|
225
223
|
export declare const WORKSPACE_STATE_MAX_PATH_CHARS = 4096;
|
|
226
|
-
export declare function normalizeWorkspaceState(value: unknown):
|
|
227
|
-
taskRoot: string;
|
|
228
|
-
handsCwd?: string;
|
|
229
|
-
activeWorktree?: {
|
|
230
|
-
worktreeDir: string;
|
|
231
|
-
originalCwd: string;
|
|
232
|
-
baseSha: string;
|
|
233
|
-
entered?: boolean;
|
|
234
|
-
};
|
|
235
|
-
} | undefined;
|
|
224
|
+
export declare function normalizeWorkspaceState(value: unknown): WorkspaceState | undefined;
|
|
236
225
|
export declare const ANNOUNCED_LISTING_MAX_NAMES = 500;
|
|
237
226
|
export declare const ANNOUNCED_LISTING_MAX_NAME_CHARS = 200;
|
|
238
227
|
export declare function normalizeCompactionStateCarrier(v: unknown): {
|
|
@@ -331,26 +320,8 @@ export interface Session<TMetadata extends SessionMetadata = SessionMetadata> {
|
|
|
331
320
|
skills?: string[];
|
|
332
321
|
models?: string[];
|
|
333
322
|
} | undefined>;
|
|
334
|
-
appendWorkspaceState(state:
|
|
335
|
-
|
|
336
|
-
handsCwd?: string;
|
|
337
|
-
activeWorktree?: {
|
|
338
|
-
worktreeDir: string;
|
|
339
|
-
originalCwd: string;
|
|
340
|
-
baseSha: string;
|
|
341
|
-
entered?: boolean;
|
|
342
|
-
};
|
|
343
|
-
}): Promise<string>;
|
|
344
|
-
getWorkspaceState(): Promise<{
|
|
345
|
-
taskRoot: string;
|
|
346
|
-
handsCwd?: string;
|
|
347
|
-
activeWorktree?: {
|
|
348
|
-
worktreeDir: string;
|
|
349
|
-
originalCwd: string;
|
|
350
|
-
baseSha: string;
|
|
351
|
-
entered?: boolean;
|
|
352
|
-
};
|
|
353
|
-
} | undefined>;
|
|
323
|
+
appendWorkspaceState(state: WorkspaceState): Promise<string>;
|
|
324
|
+
getWorkspaceState(): Promise<WorkspaceState | undefined>;
|
|
354
325
|
getPromptEpoch?(): Promise<import("../../prompt-assembly/epoch.js").PromptEpochDescriptor | undefined>;
|
|
355
326
|
}
|
|
356
327
|
export interface SessionCreateOptions {
|
|
@@ -487,17 +458,8 @@ export interface BeforeProviderRequestResult {
|
|
|
487
458
|
export interface BeforeProviderPayloadResult {
|
|
488
459
|
payload: unknown;
|
|
489
460
|
}
|
|
490
|
-
export
|
|
491
|
-
|
|
492
|
-
reason?: string;
|
|
493
|
-
updatedInput?: unknown;
|
|
494
|
-
}
|
|
495
|
-
export interface ToolResultPatch {
|
|
496
|
-
content?: Array<TextContent | ImageContent | DocumentContent>;
|
|
497
|
-
details?: unknown;
|
|
498
|
-
isError?: boolean;
|
|
499
|
-
terminate?: boolean;
|
|
500
|
-
}
|
|
461
|
+
export type ToolCallResult = BeforeToolCallResult;
|
|
462
|
+
export type ToolResultPatch = AfterToolCallResult;
|
|
501
463
|
export interface SessionBeforeCompactResult {
|
|
502
464
|
cancel?: boolean;
|
|
503
465
|
compaction?: CompactResult;
|
|
@@ -143,7 +143,7 @@ export interface AssistantMessage {
|
|
|
143
143
|
usageMissing?: true;
|
|
144
144
|
stopReason: StopReason;
|
|
145
145
|
errorMessage?: string;
|
|
146
|
-
errorKind?: "length_empty";
|
|
146
|
+
errorKind?: "length_empty" | "degenerate" | "walltime_cutoff";
|
|
147
147
|
partialFinalized?: true;
|
|
148
148
|
repetition?: {
|
|
149
149
|
cut?: RepetitionEvent;
|