@sema-agent/core 5.7.0 → 5.8.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 +37 -0
- package/dist/agents/cascade.d.ts +1 -1
- package/dist/agents/subagent.d.ts +4 -7
- package/dist/agents/subagent.js +10 -19
- 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/openai.js +22 -33
- 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/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 +2 -8
- package/dist/core/runner/assemble-result.js +15 -16
- package/dist/core/runner/prepare-task.d.ts +26 -6
- package/dist/core/runner/prepare-task.js +203 -141
- package/dist/core/runner/runtask.d.ts +0 -2
- package/dist/core/runner/runtask.js +200 -244
- 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.d.ts +2 -0
- package/dist/core/task-registry.js +9 -1
- package/dist/core/tool-errors.js +10 -2
- package/dist/core/trace.d.ts +1 -8
- package/dist/core/types.d.ts +24 -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 +0 -7
- package/dist/engine/harness/agent-harness.js +13 -53
- package/dist/engine/harness/types.d.ts +2 -15
- package/dist/engine/llm/types.d.ts +1 -2
- package/dist/engine/loop/agent-loop.d.ts +1 -1
- package/dist/engine/loop/agent-loop.js +5 -171
- package/dist/engine/loop/types.d.ts +0 -18
- package/dist/index.d.ts +10 -5
- package/dist/index.js +8 -4
- 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/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/package.json +1 -4
- 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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
1
|
+
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
|
|
@@ -36,6 +36,37 @@ function subtreeHasFiles(dir) {
|
|
|
36
36
|
}
|
|
37
37
|
return false;
|
|
38
38
|
}
|
|
39
|
+
function pruneFilelessDirTree(dir) {
|
|
40
|
+
let entries;
|
|
41
|
+
try {
|
|
42
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return !existsSync(dir);
|
|
46
|
+
}
|
|
47
|
+
for (const e of entries) {
|
|
48
|
+
if (!e.isDirectory())
|
|
49
|
+
return false;
|
|
50
|
+
if (!pruneFilelessDirTree(join(dir, e.name)))
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
rmdirSync(dir);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function tryAdoptByRename(fromDir, toDir) {
|
|
62
|
+
try {
|
|
63
|
+
renameSync(fromDir, toDir);
|
|
64
|
+
return { ok: true };
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
return { ok: false, code: err.code, error: err };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
39
70
|
function migrateKeyedPartition(m) {
|
|
40
71
|
const disclose = (code, message) => {
|
|
41
72
|
try {
|
|
@@ -52,36 +83,26 @@ function migrateKeyedPartition(m) {
|
|
|
52
83
|
return;
|
|
53
84
|
if (!existsSync(m.fromDir))
|
|
54
85
|
return;
|
|
55
|
-
if (existsSync(m.toDir)) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
rmSync(m.toDir, { recursive: true });
|
|
62
|
-
}
|
|
63
|
-
catch (err) {
|
|
64
|
-
const code = err.code;
|
|
65
|
-
disclose("memory.partition_adopt_failed", `could not clear the empty directory scaffolding at ${m.toDir} before adopting ${m.fromDir} (${code ?? String(err)}): ` +
|
|
66
|
-
`this session proceeds on ${m.toDir}; ${m.fromDir} still holds the prior memory — move it by hand.`);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
86
|
+
if (existsSync(m.toDir) && subtreeHasFiles(m.toDir)) {
|
|
87
|
+
disclose("memory.partition_split", splitText);
|
|
88
|
+
return;
|
|
69
89
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
90
|
+
ensureDirExists(dirname(m.toDir));
|
|
91
|
+
let outcome = tryAdoptByRename(m.fromDir, m.toDir);
|
|
92
|
+
if (!outcome.ok && (outcome.code === "EEXIST" || outcome.code === "ENOTEMPTY") && !subtreeHasFiles(m.toDir) && pruneFilelessDirTree(m.toDir)) {
|
|
93
|
+
outcome = tryAdoptByRename(m.fromDir, m.toDir);
|
|
94
|
+
}
|
|
95
|
+
if (outcome.ok)
|
|
96
|
+
return;
|
|
97
|
+
const { code, error } = outcome;
|
|
98
|
+
if ((code === "ENOENT" || code === "EEXIST" || code === "ENOTEMPTY") && existsSync(m.toDir)) {
|
|
99
|
+
if (!existsSync(m.fromDir))
|
|
80
100
|
return;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
`${m.fromDir} still holds the prior memory — move it by hand.`);
|
|
101
|
+
disclose("memory.partition_split", splitText);
|
|
102
|
+
return;
|
|
84
103
|
}
|
|
104
|
+
disclose("memory.partition_adopt_failed", `could not adopt the memory partition ${m.fromDir} → ${m.toDir} (${code ?? String(error)}): this session proceeds on ${m.toDir}; ` +
|
|
105
|
+
`${m.fromDir} still holds the prior memory — move it by hand.`);
|
|
85
106
|
}
|
|
86
107
|
catch {
|
|
87
108
|
}
|
|
@@ -338,8 +359,13 @@ function sleepSync(ms) {
|
|
|
338
359
|
}
|
|
339
360
|
const LOCK_STALE_MS = 1_500;
|
|
340
361
|
const LOCK_WAIT_CAP_MS = 3_000;
|
|
341
|
-
|
|
342
|
-
|
|
362
|
+
const LOCK_SPIN_PAUSE_MS = 5;
|
|
363
|
+
const MAX_FAIL_OPEN_DEADLINE_ROUNDS = 3;
|
|
364
|
+
export function acquireSidecarLock(lockDir, opts = {}) {
|
|
365
|
+
const waitCapMs = opts.waitCapMs ?? LOCK_WAIT_CAP_MS;
|
|
366
|
+
const deadline = Date.now() + waitCapMs;
|
|
367
|
+
const mintToken = () => `${process.pid}-${Math.random().toString(36).slice(2, 10)}`;
|
|
368
|
+
let deadlineRounds = 0;
|
|
343
369
|
const stealOnce = () => {
|
|
344
370
|
const tomb = `${lockDir}.stale-${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
|
|
345
371
|
try {
|
|
@@ -354,7 +380,7 @@ function acquireSidecarLock(lockDir, opts = {}) {
|
|
|
354
380
|
for (;;) {
|
|
355
381
|
try {
|
|
356
382
|
mkdirSync(lockDir);
|
|
357
|
-
const token =
|
|
383
|
+
const token = mintToken();
|
|
358
384
|
let fd;
|
|
359
385
|
try {
|
|
360
386
|
fd = openSync(join(lockDir, "owner"), "w");
|
|
@@ -374,25 +400,24 @@ function acquireSidecarLock(lockDir, opts = {}) {
|
|
|
374
400
|
return token;
|
|
375
401
|
}
|
|
376
402
|
catch {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
continue;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
catch {
|
|
385
|
-
continue;
|
|
386
|
-
}
|
|
387
|
-
if (Date.now() > deadline) {
|
|
388
|
-
if (opts.onDeadline === "throw") {
|
|
389
|
-
throw new Error(`sidecar lock wait timed out (${LOCK_WAIT_CAP_MS}ms) at ${lockDir} — refusing to proceed without the lock (fail-closed sidecar)`);
|
|
390
|
-
}
|
|
403
|
+
}
|
|
404
|
+
try {
|
|
405
|
+
const age = Date.now() - statSync(lockDir).mtimeMs;
|
|
406
|
+
if (age > LOCK_STALE_MS)
|
|
391
407
|
stealOnce();
|
|
392
|
-
|
|
408
|
+
}
|
|
409
|
+
catch {
|
|
410
|
+
}
|
|
411
|
+
if (Date.now() > deadline) {
|
|
412
|
+
if (opts.onDeadline === "throw") {
|
|
413
|
+
throw new Error(`sidecar lock wait timed out (${waitCapMs}ms) at ${lockDir} — refusing to proceed without the lock (fail-closed sidecar)`);
|
|
393
414
|
}
|
|
394
|
-
|
|
415
|
+
deadlineRounds += 1;
|
|
416
|
+
if (deadlineRounds > MAX_FAIL_OPEN_DEADLINE_ROUNDS)
|
|
417
|
+
return mintToken();
|
|
418
|
+
stealOnce();
|
|
395
419
|
}
|
|
420
|
+
sleepSync(LOCK_SPIN_PAUSE_MS);
|
|
396
421
|
}
|
|
397
422
|
}
|
|
398
423
|
function rollForwardSidecar(file, journal) {
|
|
@@ -30,14 +30,6 @@ export interface Stats {
|
|
|
30
30
|
}>;
|
|
31
31
|
};
|
|
32
32
|
mechanisms?: {
|
|
33
|
-
finalizeInjected?: true;
|
|
34
|
-
nudgesSent?: number;
|
|
35
|
-
capShrinks?: number;
|
|
36
|
-
callCutoffs?: number;
|
|
37
|
-
toolClamps?: number;
|
|
38
|
-
toolCuts?: number;
|
|
39
|
-
toolCutKills?: number;
|
|
40
|
-
pendingCutTools?: number;
|
|
41
33
|
finalVerifyInjected?: true;
|
|
42
34
|
finalVerifyInjections?: number;
|
|
43
35
|
attachmentsInjected?: number;
|
|
@@ -60,6 +52,7 @@ export interface Stats {
|
|
|
60
52
|
compactionMicroUsd: number;
|
|
61
53
|
};
|
|
62
54
|
}
|
|
55
|
+
export type BudgetAxis = "tokens" | "cost";
|
|
63
56
|
export interface ResultFlags {
|
|
64
57
|
threw: unknown;
|
|
65
58
|
model?: string;
|
|
@@ -70,6 +63,7 @@ export interface ResultFlags {
|
|
|
70
63
|
abortedForTurns: boolean;
|
|
71
64
|
abortedLive?: boolean;
|
|
72
65
|
budgetHit?: "exceeded" | "precall";
|
|
66
|
+
budgetAxis?: BudgetAxis;
|
|
73
67
|
blockedReason?: string;
|
|
74
68
|
conflict?: boolean;
|
|
75
69
|
outputInvalid?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isDegenerateCutMessage
|
|
1
|
+
import { isDegenerateCutMessage } from "../../brain/terminal-cause.js";
|
|
2
2
|
import { extractErrorCode, stripErrorCodePrefix } from "../../brain/errors.js";
|
|
3
3
|
export function errorCodeOf(err) {
|
|
4
4
|
let cur = err;
|
|
@@ -54,7 +54,6 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
|
|
|
54
54
|
let checkpointGate;
|
|
55
55
|
let workspaceRestoreMode;
|
|
56
56
|
const isDegenerate = final?.stopReason === "error" && isDegenerateCutMessage(final);
|
|
57
|
-
const isWalltimeCutoff = final?.stopReason === "error" && isWalltimeCutMessage(final);
|
|
58
57
|
if (flags.outputInvalid) {
|
|
59
58
|
status = "failed";
|
|
60
59
|
errorCode = "output.invalid";
|
|
@@ -66,19 +65,15 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
|
|
|
66
65
|
errorMessage = final?.errorMessage;
|
|
67
66
|
salvagedOutput = text.trim() || undefined;
|
|
68
67
|
}
|
|
69
|
-
else if (isWalltimeCutoff) {
|
|
70
|
-
status = "timeout";
|
|
71
|
-
errorCode = "limit.timeout";
|
|
72
|
-
errorMessage = final?.errorMessage;
|
|
73
|
-
salvagedOutput = text.trim() || undefined;
|
|
74
|
-
}
|
|
75
68
|
else if (flags.budgetHit) {
|
|
76
69
|
status = "failed";
|
|
77
|
-
errorCode = flags.
|
|
70
|
+
errorCode = flags.budgetAxis === "tokens" ? "limits.max_tokens_exceeded" : "limits.max_cost_exceeded";
|
|
71
|
+
const axisName = flags.budgetAxis === "tokens" ? "limits.maxTokens" : "limits.maxCostUsd";
|
|
78
72
|
errorMessage =
|
|
79
73
|
flags.budgetHit === "precall"
|
|
80
|
-
?
|
|
81
|
-
:
|
|
74
|
+
? `the estimated cost of the first call already exceeds ${axisName}; the task was not started`
|
|
75
|
+
: `cumulative usage exceeded ${axisName}`;
|
|
76
|
+
salvagedOutput = text.trim() || undefined;
|
|
82
77
|
}
|
|
83
78
|
else if (flags.suspendLoop) {
|
|
84
79
|
status = "failed";
|
|
@@ -86,15 +81,17 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
|
|
|
86
81
|
errorMessage = "task suspended too many times (resume/restart loop) — exceeded the suspend limit";
|
|
87
82
|
}
|
|
88
83
|
else if (flags.threw) {
|
|
89
|
-
status =
|
|
84
|
+
status = "failed";
|
|
90
85
|
errorMessage = flags.threw instanceof Error ? flags.threw.message : String(flags.threw);
|
|
91
86
|
errorCode = flags.abortedForTimeout
|
|
92
|
-
? "
|
|
87
|
+
? "limits.max_walltime_exceeded"
|
|
93
88
|
: flags.abortedForTurns
|
|
94
|
-
? "
|
|
89
|
+
? "limits.max_turns_exceeded"
|
|
95
90
|
: flags.conflict
|
|
96
91
|
? "conflict"
|
|
97
92
|
: errorCodeOf(flags.threw);
|
|
93
|
+
if (flags.abortedForTimeout || flags.abortedForTurns)
|
|
94
|
+
salvagedOutput = text.trim() || undefined;
|
|
98
95
|
}
|
|
99
96
|
else if (flags.blockedReason) {
|
|
100
97
|
status = "blocked";
|
|
@@ -114,9 +111,11 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
|
|
|
114
111
|
workspaceRestoreMode = flags.reviewRef.restoreMode;
|
|
115
112
|
}
|
|
116
113
|
else if (flags.abortedLive || final?.stopReason === "aborted") {
|
|
117
|
-
status =
|
|
118
|
-
errorCode = flags.abortedForTimeout ? "
|
|
114
|
+
status = "failed";
|
|
115
|
+
errorCode = flags.abortedForTimeout ? "limits.max_walltime_exceeded" : flags.abortedForTurns ? "limits.max_turns_exceeded" : undefined;
|
|
119
116
|
errorMessage = final?.errorMessage ?? (flags.abortedForTurns ? "max turns exceeded" : "run aborted");
|
|
117
|
+
if (flags.abortedForTimeout || flags.abortedForTurns)
|
|
118
|
+
salvagedOutput = text.trim() || undefined;
|
|
120
119
|
}
|
|
121
120
|
else if (!final) {
|
|
122
121
|
status = "failed";
|
|
@@ -8,7 +8,6 @@ import type { SessionStore } from "../session.js";
|
|
|
8
8
|
import { SubagentRetainLedger } from "../../agents/retain-ledger.js";
|
|
9
9
|
import type { OnAsk, ToolPolicy } from "../tool-policy.js";
|
|
10
10
|
import { type ActiveSkillFrame } from "./active-skill-scope.js";
|
|
11
|
-
import { type CutKillRegistry } from "./cut-kill.js";
|
|
12
11
|
import type { SessionPermissionRules } from "../session-policy-store.js";
|
|
13
12
|
import { CacheBreakDetector, type ToolFingerprintInput } from "../cache-break-detector.js";
|
|
14
13
|
import { type BrainCallGuardrailRef } from "../../brain/timeout.js";
|
|
@@ -19,10 +18,23 @@ import type { TaskNotificationPayload } from "../task-notification.js";
|
|
|
19
18
|
import { type CwdRef } from "../../tools/fs/index.js";
|
|
20
19
|
import { type WorkflowSizeGuideline } from "../../orchestration/workflow-size-guideline.js";
|
|
21
20
|
import type { Runner } from "./runtask.js";
|
|
22
|
-
import { type CheckpointGate, type CheckpointState, type CheckpointToken, type ResourceLedger, type ResourceLimitReason } from "../checkpoint-store.js";
|
|
21
|
+
import { type CheckpointGate, type CheckpointState, type CheckpointToken, type ResourceLedger, type PlatformLimitReason, type ResourceLimitReason } from "../checkpoint-store.js";
|
|
23
22
|
import type { ActiveWorktreeSession, AgentMessage, AgentTool, ExecutionEnv } from "../../internal/harness.js";
|
|
24
|
-
import type { NestedUsageAccum, RunnerDeps, TaskEvent, TaskResult, TaskSpec, ToolActivity, ToolEffect } from "../types.js";
|
|
23
|
+
import type { NestedUsageAccum, RunnerDeps, TaskEvent, TaskLimits, TaskResult, TaskSpec, ToolActivity, ToolEffect } from "../types.js";
|
|
25
24
|
import type { RepairBundle } from "../../agents/repair-loop.js";
|
|
25
|
+
export declare function resolveTaskLimits(limits: TaskLimits | undefined): TaskLimits | undefined;
|
|
26
|
+
export declare const ENV_LIFETIME_SUSPEND_MARGIN_MS = 60000;
|
|
27
|
+
export declare const USAGE_WINDOW_REAP_MARGIN_MS: number;
|
|
28
|
+
export interface UsageGovernance {
|
|
29
|
+
readonly key: string;
|
|
30
|
+
check(now: number): Promise<number | undefined>;
|
|
31
|
+
commit(cumulativeTokens: number, now: number): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export declare function resolveEnvLifetimeExpiry(env: ExecutionEnv, observedAt: number | undefined): {
|
|
34
|
+
expiresAt: number;
|
|
35
|
+
} | {
|
|
36
|
+
unanchored: true;
|
|
37
|
+
} | undefined;
|
|
26
38
|
export declare const DEFAULT_IRREVERSIBLE_SCOPE = "irreversible";
|
|
27
39
|
export declare function checkpointScopeOf(spec: {
|
|
28
40
|
durableApproval?: {
|
|
@@ -132,9 +144,17 @@ export interface Prepared {
|
|
|
132
144
|
turns: number;
|
|
133
145
|
walltimeMs: number;
|
|
134
146
|
}) => Promise<boolean>;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
147
|
+
suspendForPlatformLimit?: (reason: PlatformLimitReason, sliceSpend: {
|
|
148
|
+
costMicroUsd: number;
|
|
149
|
+
tokens: number;
|
|
150
|
+
turns: number;
|
|
151
|
+
walltimeMs: number;
|
|
152
|
+
}, hint?: {
|
|
153
|
+
resumeAfterMs: number;
|
|
154
|
+
}) => Promise<boolean>;
|
|
155
|
+
envLifetimeSuspendAt?: number;
|
|
156
|
+
usageGovernance?: UsageGovernance;
|
|
157
|
+
callIssuedAtRef: {
|
|
138
158
|
current?: number;
|
|
139
159
|
};
|
|
140
160
|
brainCallGuardrailRef: BrainCallGuardrailRef;
|