@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
|
@@ -10,13 +10,6 @@ export function createTimestamp() {
|
|
|
10
10
|
export function toSession(storage) {
|
|
11
11
|
return new StoredSession(storage);
|
|
12
12
|
}
|
|
13
|
-
export function getFileSystemResultOrThrow(result, message) {
|
|
14
|
-
if (!result.ok) {
|
|
15
|
-
const code = result.error.code === "not_found" ? "not_found" : "storage";
|
|
16
|
-
throw new SessionError(code, `${message}: ${result.error.message}`, result.error);
|
|
17
|
-
}
|
|
18
|
-
return result.value;
|
|
19
|
-
}
|
|
20
13
|
function rerootIfHeadless(storage, entries) {
|
|
21
14
|
const head = entries[0];
|
|
22
15
|
if (head === undefined || head.parentId === null)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { Runner, runTask
|
|
1
|
+
export { Runner, runTask } from "./core/runner/runtask.js";
|
|
2
|
+
export { resolveTaskLimits } from "./core/runner/prepare-task.js";
|
|
3
|
+
export type { BudgetAxis } from "./core/runner/assemble-result.js";
|
|
2
4
|
export { SESSION_LOG_DIGEST_SCHEME, sessionEntryDigest, sessionLogDigest, sessionLogDigestsComparable, } from "./engine/session/log-digest.js";
|
|
3
5
|
export type { ResumeTaskConfig } from "./core/runner/runtask.js";
|
|
4
6
|
export { defineTool } from "./core/tools.js";
|
|
@@ -75,7 +77,10 @@ export { HAND_TOOL_EFFECTS, bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW,
|
|
|
75
77
|
export { classifyCompoundReadonlyDetailed, formatOutOfRootReadApprovalOption, type BashReadonlyRootBoundary, type CompoundReadonlyVerdict, } from "./tools/fs/index.js";
|
|
76
78
|
export { resolveBashTimeoutCaps } from "./tools/fs/index.js";
|
|
77
79
|
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, type ToolResultStore, type ToolResultSlice, } from "./core/tool-result-store.js";
|
|
78
|
-
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION,
|
|
80
|
+
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingTokens, winnerFromOutcome, validatePendingSteer, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, type RiskDescriptor, type CheckpointStore, type CheckpointSummary, type Checkpoint, type CheckpointToken, type CheckpointGate, type CheckpointState, type SerializedCheckpointState, type CheckpointFaultMode, type PendingAction, type ResumeOutcome, type ResolvedOutcome, type ReopenReason, type ResolveExpectation, type SafetyAxis, type ResourceLedger, type ResourceLimitReason, type PlatformLimitReason, } from "./core/checkpoint-store.js";
|
|
81
|
+
export { InMemoryUsageWindowStore, GLOBAL_USAGE_KEY, EMPTY_USAGE_WINDOW_RECORD, chargeUsageRecord, readUsageRecord, usageRetryAfterMs, resolveUsageWindows, type UsageWindow, type UsageWindowStore, type UsageWindowReading, type UsageWindowRecord, type UsageSlot, type UsageBucketRow, } from "./core/usage-window-store.js";
|
|
82
|
+
export { FileUsageWindowStore } from "./stores/file/usage-window-store.js";
|
|
83
|
+
export { ENV_LIFETIME_SUSPEND_MARGIN_MS, USAGE_WINDOW_REAP_MARGIN_MS } from "./core/runner/prepare-task.js";
|
|
79
84
|
export { InMemoryFileSnapshotStore, DEFAULT_SNAPSHOT_BOUNDS } from "./core/file-snapshot-store.js";
|
|
80
85
|
export { captureManifest, applyManifest } from "./core/file-snapshot-store.js";
|
|
81
86
|
export type { FileSnapshotStore, FileSnapshotResult, FileSnapshotError, FileSnapshotBounds } from "./core/file-snapshot-store.js";
|
|
@@ -86,7 +91,7 @@ export { brainToRuntime } from "./core/runtime.js";
|
|
|
86
91
|
export { createSensitivePathPolicy, RECOMMENDED_SENSITIVE_PATTERNS } from "./core/sensitive-path-policy.js";
|
|
87
92
|
export { createFsWriteGatePolicy, type FsWriteGatePolicyOptions } from "./core/fs-write-gate-policy.js";
|
|
88
93
|
export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
|
|
89
|
-
export { DEFAULT_SUBAGENT_TOOL_NAME
|
|
94
|
+
export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
|
|
90
95
|
export { renderTaskNotificationXml, taskNotificationDedupKey, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, } from "./core/task-notification.js";
|
|
91
96
|
export { TaskRegistry, defaultTaskRegistry, createTaskOutputTool, createTaskStopTool, type SemaTaskType, type SemaTaskStatus, type SemaTaskHandle, type ParkedClaimTicket, type TaskAccess, type UnifiedTaskOutput, type TaskRetrievalStatus, type StopSource, type RegisterMonitorInput, type MonitorTimers, MONITOR_BATCH_WINDOW_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_MAX_TIMEOUT_MS, MONITOR_MAX_BATCHES_PER_MINUTE, canAccessWorkflowRun, DURABLE_AGENT_HANDLE_RE, } from "./core/task-registry.js";
|
|
92
97
|
export { InMemoryMailboxStore, type MailboxStore, type MailboxMessage, type MailboxLease } from "./core/mailbox-store.js";
|
|
@@ -108,7 +113,7 @@ export type { SchedulerCapability, SchedulerErrorCode, ScheduledIntent, Schedule
|
|
|
108
113
|
export { createSchedulerTools, type SchedulerToolContext, SCHEDULE_WAKEUP_TOOL_NAME, AUTONOMOUS_LOOP_SENTINEL, AUTONOMOUS_LOOP_DYNAMIC_SENTINEL, } from "./tools/scheduler-tools.js";
|
|
109
114
|
export { resolveAutonomousLoopPrompt, AUTONOMOUS_LOOP_PREAMBLE, AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT, type AutonomousLoopPromptOptions, } from "./tools/loop-tick.js";
|
|
110
115
|
export { tightenTaskSpec, TaskSpecTightenError } from "./core/tighten-task-spec.js";
|
|
111
|
-
export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, type ToolPolicyNameSets, type NamedToolPolicy, type ToolPolicy, type ToolCallRequest, type PermissionResult, type DecisionReason, type OnAsk, type AskOutcome, type ResolvedAsk, type AskRequest, } from "./core/tool-policy.js";
|
|
116
|
+
export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, type ToolPolicyNameSets, type NamedToolPolicy, type ToolPolicy, type ToolCallRequest, type PermissionResult, type DecisionReason, type OnAsk, type AskOutcome, type ResolvedAsk, type AskRequest, type AskDelegationProvenance, } from "./core/tool-policy.js";
|
|
112
117
|
export { parseAutoModeResponse, createAutoModeDecider, type AutoModeVerdict, type AutoModeDecider, type AutoModeDeciderOptions, type AutoModeClassifyFn, type AutoModeClassifyInput, } from "./core/auto-mode.js";
|
|
113
118
|
export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, type AutoModeRules, type BuildAutoModePromptOptions, type AutoModeWindowOptions, } from "./core/auto-mode-prompt.js";
|
|
114
119
|
export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
|
|
@@ -146,7 +151,7 @@ export { runSpec, type RunSpecOptions, type RunSpecResult, type RunSpecOracleRep
|
|
|
146
151
|
export { isSelfOrchestrationActive, workflowsCapability, selfOrchestrationFailClosedReason, type WorkflowScriptRunner, type WorkflowMeta, type WorkflowPrimitives, } from "./orchestration/workflow-script-runner.js";
|
|
147
152
|
export { devWorkflowScriptRunner } from "./orchestration/dev-vm-script-runner.js";
|
|
148
153
|
export { parseWorkflowMeta, splitWorkflowMeta, WorkflowScriptError, workflowScriptReadsClockOrRandom } from "./orchestration/workflow-meta.js";
|
|
149
|
-
export { assertWorkflowSandboxConformance, assertWorkflowPrimitivesWiring } from "./orchestration/workflow-sandbox-conformance.js";
|
|
154
|
+
export { assertWorkflowSandboxConformance, assertWorkflowPrimitivesWiring, assertWorkflowDeterminism } from "./orchestration/workflow-sandbox-conformance.js";
|
|
150
155
|
export { WorkflowModelNotAllowedError, type WorkflowAgentSpec } from "./orchestration/workflow-governance.js";
|
|
151
156
|
export { WorkflowMaxAgentsError, WorkflowResultTooLargeError } from "./orchestration/workflow.js";
|
|
152
157
|
export { createFileWorkflowScriptStore, mergeWorkflowArgs, type WorkflowScriptStore, type NamedWorkflowResolution, type NamedWorkflowListing, } from "./orchestration/workflow-script-store.js";
|
|
@@ -179,7 +184,7 @@ export { MemoryRosterStore, FileRosterStore, type RosterStore, type RosterEntry,
|
|
|
179
184
|
export { CONFIG_CATALOG_VERSION, describeConfigCatalog, resolveEffectiveConfig, type ConfigKnob, type ConfigOverrideDeclaration, type ConfigProvenance, type EffectiveConfigField, } from "./config/catalog.js";
|
|
180
185
|
export { normalizeAgentName } from "./core/task-registry.js";
|
|
181
186
|
export { COORDINATOR_ROLE_PROMPT, TEAMMATE_COMMUNICATION_ADDENDUM, TEAMMATE_TASK_LIST_ADDENDUM } from "./prompts/coordinator.js";
|
|
182
|
-
export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE,
|
|
187
|
+
export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE, agentWhenToUseText, FORK_DIRECTIVE_FRAME, SUBAGENT_SYSTEM_NOTE, type SubagentToolOptions, type SubagentSpawnContext, type SubagentSteerHandle, type SubagentStep, type SubagentEditedFile, } from "./agents/subagent.js";
|
|
183
188
|
export { getSessionRetainLedger, releaseSessionRetainLedger, } from "./agents/retain-ledger.js";
|
|
184
189
|
export { createSendMessageTool, SEND_MESSAGE_TOOL_NAME, type SendMessageToolOptions } from "./agents/send-message-tool.js";
|
|
185
190
|
export { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME, type AgentTranscriptToolOptions, } from "./agents/agent-transcript-tool.js";
|
|
@@ -190,6 +195,7 @@ export { createTaskServer, type TaskServerOptions, type TaskRequestBody, } from
|
|
|
190
195
|
export { clearStaleToolResults, COMPACTABLE_TOOLS, editBudget, type ContextEditOptions, } from "./core/context-edit.js";
|
|
191
196
|
export { createOpenAIBrain, type OpenAIBrainConfig } from "./brain/openai.js";
|
|
192
197
|
export { createAnthropicBrain, type AnthropicBrainConfig } from "./brain/anthropic.js";
|
|
198
|
+
export { createOpenResponsesBrain, type OpenResponsesBrainConfig } from "./brain/open-responses.js";
|
|
193
199
|
export { FABLE_5_COMPAT, fable5Model } from "./brain/model-presets.js";
|
|
194
200
|
export { createFailoverBrain } from "./brain/failover.js";
|
|
195
201
|
export { createRoutingBrain, type RoutingBrainOptions } from "./brain/routing.js";
|
|
@@ -200,7 +206,7 @@ export { retryBackoffMs, parseRetryAfter } from "./brain/retry.js";
|
|
|
200
206
|
export { type BrainTimeoutConfig } from "./brain/timeout.js";
|
|
201
207
|
export { createAssistantMessageEventStream } from "./internal/llm.js";
|
|
202
208
|
export type { AssistantMessage, AssistantMessageEvent, CompleteSimpleFn, Context, DocumentContent, ImageContent, Message, StopReason, StreamFn, TextContent, ThinkingContent, ToolCall, ToolResultMessage, Usage, UserMessage, } from "./internal/llm.js";
|
|
203
|
-
export type { AgentDefinition, BeforeWriteHook, BeforeWriteRequest, BeforeWriteResult, HandsBandOptions, Brain, BrainStatus, BrainStatusPhase, ImageInput, McpElicitRequest, McpElicitResponse, McpServerSpec, A2aServerSpec, OnElicit, Model, ModelRef, ProjectMemoryLoad, RunnerDeps, RuntimeCaps, BackgroundChildEvent, SkillManifest, SkillSpec, TaskEvent, TaskEventIdentity, ToolActivity, TaskResult, RemoteEnvFailureNote, TaskSpec, TaskStatus, TaskStream, CompactOutcome, ThinkingLevel, ToolExecuteContext, ToolReturn, ToolSpec, ToolEffect, WorkflowGovernanceBaseline, } from "./core/types.js";
|
|
209
|
+
export type { AgentDefinition, BeforeWriteHook, BeforeWriteRequest, BeforeWriteResult, HandsBandOptions, Brain, BrainStatus, BrainStatusPhase, ImageInput, McpElicitRequest, McpElicitResponse, McpServerSpec, A2aServerSpec, OnElicit, Model, ModelRef, ProjectMemoryLoad, RunnerDeps, RuntimeCaps, BackgroundChildEvent, SkillManifest, SkillSpec, TaskEvent, TaskEventIdentity, ToolActivity, TaskLimits, TaskResult, RemoteEnvFailureNote, TaskSpec, TaskStatus, TaskStream, CompactOutcome, ThinkingLevel, ToolExecuteContext, ToolReturn, ToolSpec, ToolEffect, WorkflowGovernanceBaseline, } from "./core/types.js";
|
|
204
210
|
export { Type } from "typebox";
|
|
205
211
|
export type { TSchema, Static } from "typebox";
|
|
206
212
|
export { explainPromptAssembly, describeDefaultPack, type DefaultPackDescription, type ExplainInput } from "./prompt-assembly/explain.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { Runner, runTask
|
|
1
|
+
export { Runner, runTask } from "./core/runner/runtask.js";
|
|
2
|
+
export { resolveTaskLimits } from "./core/runner/prepare-task.js";
|
|
2
3
|
export { SESSION_LOG_DIGEST_SCHEME, sessionEntryDigest, sessionLogDigest, sessionLogDigestsComparable, } from "./engine/session/log-digest.js";
|
|
3
4
|
export { defineTool } from "./core/tools.js";
|
|
4
5
|
export { SKILL_TOOL_NAME } from "./core/runner/synthetic-tools.js";
|
|
@@ -64,7 +65,10 @@ export { HAND_TOOL_EFFECTS, bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW,
|
|
|
64
65
|
export { classifyCompoundReadonlyDetailed, formatOutOfRootReadApprovalOption, } from "./tools/fs/index.js";
|
|
65
66
|
export { resolveBashTimeoutCaps } from "./tools/fs/index.js";
|
|
66
67
|
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, } from "./core/tool-result-store.js";
|
|
67
|
-
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION,
|
|
68
|
+
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingTokens, winnerFromOutcome, validatePendingSteer, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, } from "./core/checkpoint-store.js";
|
|
69
|
+
export { InMemoryUsageWindowStore, GLOBAL_USAGE_KEY, EMPTY_USAGE_WINDOW_RECORD, chargeUsageRecord, readUsageRecord, usageRetryAfterMs, resolveUsageWindows, } from "./core/usage-window-store.js";
|
|
70
|
+
export { FileUsageWindowStore } from "./stores/file/usage-window-store.js";
|
|
71
|
+
export { ENV_LIFETIME_SUSPEND_MARGIN_MS, USAGE_WINDOW_REAP_MARGIN_MS } from "./core/runner/prepare-task.js";
|
|
68
72
|
export { InMemoryFileSnapshotStore, DEFAULT_SNAPSHOT_BOUNDS } from "./core/file-snapshot-store.js";
|
|
69
73
|
export { captureManifest, applyManifest } from "./core/file-snapshot-store.js";
|
|
70
74
|
export { FileStorageBackend, FileSessionRepo, FileCheckpointStore, FileMemoryStore, FileToolResultStore, FileSessionPolicyStore, FileFileSnapshotStore, FileWorkflowJournalStore, MAX_JOURNAL_RESULT_BYTES, oversizeJournalResult, resolveDataRoot, sanitizeScope, sanitizePathComponent, createFileConsolidationLock, atomicWriteFile, writeThenLink, ensureDir, readJsonlRecords, AppendLog, } from "./stores/file/index.js";
|
|
@@ -74,7 +78,7 @@ export { brainToRuntime } from "./core/runtime.js";
|
|
|
74
78
|
export { createSensitivePathPolicy, RECOMMENDED_SENSITIVE_PATTERNS } from "./core/sensitive-path-policy.js";
|
|
75
79
|
export { createFsWriteGatePolicy } from "./core/fs-write-gate-policy.js";
|
|
76
80
|
export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
|
|
77
|
-
export { DEFAULT_SUBAGENT_TOOL_NAME
|
|
81
|
+
export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
|
|
78
82
|
export { renderTaskNotificationXml, taskNotificationDedupKey, SystemInjectionQueue, } from "./core/task-notification.js";
|
|
79
83
|
export { TaskRegistry, defaultTaskRegistry, createTaskOutputTool, createTaskStopTool, MONITOR_BATCH_WINDOW_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_MAX_TIMEOUT_MS, MONITOR_MAX_BATCHES_PER_MINUTE, canAccessWorkflowRun, DURABLE_AGENT_HANDLE_RE, } from "./core/task-registry.js";
|
|
80
84
|
export { InMemoryMailboxStore } from "./core/mailbox-store.js";
|
|
@@ -131,7 +135,7 @@ export { runSpec } from "./orchestration/run-spec.js";
|
|
|
131
135
|
export { isSelfOrchestrationActive, workflowsCapability, selfOrchestrationFailClosedReason, } from "./orchestration/workflow-script-runner.js";
|
|
132
136
|
export { devWorkflowScriptRunner } from "./orchestration/dev-vm-script-runner.js";
|
|
133
137
|
export { parseWorkflowMeta, splitWorkflowMeta, WorkflowScriptError, workflowScriptReadsClockOrRandom } from "./orchestration/workflow-meta.js";
|
|
134
|
-
export { assertWorkflowSandboxConformance, assertWorkflowPrimitivesWiring } from "./orchestration/workflow-sandbox-conformance.js";
|
|
138
|
+
export { assertWorkflowSandboxConformance, assertWorkflowPrimitivesWiring, assertWorkflowDeterminism } from "./orchestration/workflow-sandbox-conformance.js";
|
|
135
139
|
export { WorkflowModelNotAllowedError } from "./orchestration/workflow-governance.js";
|
|
136
140
|
export { WorkflowMaxAgentsError, WorkflowResultTooLargeError } from "./orchestration/workflow.js";
|
|
137
141
|
export { createFileWorkflowScriptStore, mergeWorkflowArgs, } from "./orchestration/workflow-script-store.js";
|
|
@@ -162,7 +166,7 @@ export { MemoryRosterStore, FileRosterStore } from "./agents/roster-store.js";
|
|
|
162
166
|
export { CONFIG_CATALOG_VERSION, describeConfigCatalog, resolveEffectiveConfig, } from "./config/catalog.js";
|
|
163
167
|
export { normalizeAgentName } from "./core/task-registry.js";
|
|
164
168
|
export { COORDINATOR_ROLE_PROMPT, TEAMMATE_COMMUNICATION_ADDENDUM, TEAMMATE_TASK_LIST_ADDENDUM } from "./prompts/coordinator.js";
|
|
165
|
-
export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE,
|
|
169
|
+
export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE, agentWhenToUseText, FORK_DIRECTIVE_FRAME, SUBAGENT_SYSTEM_NOTE, } from "./agents/subagent.js";
|
|
166
170
|
export { getSessionRetainLedger, releaseSessionRetainLedger, } from "./agents/retain-ledger.js";
|
|
167
171
|
export { createSendMessageTool, SEND_MESSAGE_TOOL_NAME } from "./agents/send-message-tool.js";
|
|
168
172
|
export { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME, } from "./agents/agent-transcript-tool.js";
|
|
@@ -173,6 +177,7 @@ export { createTaskServer, } from "./server/http.js";
|
|
|
173
177
|
export { clearStaleToolResults, COMPACTABLE_TOOLS, editBudget, } from "./core/context-edit.js";
|
|
174
178
|
export { createOpenAIBrain } from "./brain/openai.js";
|
|
175
179
|
export { createAnthropicBrain } from "./brain/anthropic.js";
|
|
180
|
+
export { createOpenResponsesBrain } from "./brain/open-responses.js";
|
|
176
181
|
export { FABLE_5_COMPAT, fable5Model } from "./brain/model-presets.js";
|
|
177
182
|
export { createFailoverBrain } from "./brain/failover.js";
|
|
178
183
|
export { createRoutingBrain } from "./brain/routing.js";
|
package/dist/internal/llm.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { createAssistantMessageEventStream, stripEngineMetadata } from "../engine/llm/index.js";
|
|
2
|
-
export type { AnthropicMessagesCompat, AssistantMessage, AssistantMessageDiagnostic, AssistantMessageEvent, CompleteSimpleFn, Context, DocumentContent, ImageContent, Message, Model, ResilienceOptions, SimpleStreamOptions, StallTimeouts, StopReason, StreamFn, TextContent, ThinkingContent, Tool, ToolCall, ToolResultMessage, Usage, UserMessage, } from "../engine/llm/index.js";
|
|
2
|
+
export type { AnthropicMessagesCompat, OpenAICompletionsCompat, OpenAIResponsesCompat, AssistantMessage, AssistantMessageDiagnostic, AssistantMessageEvent, CompleteSimpleFn, Context, DocumentContent, ImageContent, Message, Model, ResilienceOptions, SimpleStreamOptions, StallTimeouts, StopReason, StreamFn, TextContent, ThinkingContent, Tool, ToolCall, ToolResultMessage, Usage, UserMessage, } from "../engine/llm/index.js";
|
|
@@ -148,16 +148,12 @@ export async function runGoal(runner, spec) {
|
|
|
148
148
|
if (result.status === "blocked")
|
|
149
149
|
return mk("blocked", iteration, { result });
|
|
150
150
|
if (result.status === "failed") {
|
|
151
|
-
if (result.errorCode
|
|
151
|
+
if (result.errorCode !== undefined && result.errorCode.startsWith("limits.max_")) {
|
|
152
152
|
lastFeedback = TIMEOUT_FEEDBACK;
|
|
153
153
|
continue;
|
|
154
154
|
}
|
|
155
155
|
return mk("failed", iteration, { result, errorCode: result.errorCode });
|
|
156
156
|
}
|
|
157
|
-
if (result.status === "timeout") {
|
|
158
|
-
lastFeedback = TIMEOUT_FEEDBACK;
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
157
|
const gate1 = hasOutputSchema ? result.structuredOutput !== undefined : doneRef.declared === true;
|
|
162
158
|
if (!gate1) {
|
|
163
159
|
lastFeedback = NOT_DECLARED_FEEDBACK;
|
|
@@ -38,7 +38,7 @@ export interface WorkflowLimits {
|
|
|
38
38
|
maxScriptChars?: number;
|
|
39
39
|
maxAgents?: number;
|
|
40
40
|
totalTimeoutMs?: number;
|
|
41
|
-
|
|
41
|
+
perAgentMaxWalltimeMs?: number;
|
|
42
42
|
childMaxCostUsd?: number;
|
|
43
43
|
childMaxTokens?: number;
|
|
44
44
|
childMaxTurns?: number;
|
|
@@ -17,7 +17,6 @@ const DEFAULTS = {
|
|
|
17
17
|
maxScriptChars: 100_000,
|
|
18
18
|
maxAgents: 50,
|
|
19
19
|
totalTimeoutMs: 600_000,
|
|
20
|
-
perAgentTimeoutSec: 300,
|
|
21
20
|
maxResultChars: 100_000,
|
|
22
21
|
maxLogChars: 10_000,
|
|
23
22
|
};
|
|
@@ -141,7 +140,7 @@ export async function createRunWorkflowTool(d) {
|
|
|
141
140
|
const lim = d.limits ?? {};
|
|
142
141
|
const maxScriptChars = lim.maxScriptChars ?? DEFAULTS.maxScriptChars;
|
|
143
142
|
const childCaps = {
|
|
144
|
-
|
|
143
|
+
perAgentMaxWalltimeMs: lim.perAgentMaxWalltimeMs,
|
|
145
144
|
childMaxCostUsd: lim.childMaxCostUsd,
|
|
146
145
|
childMaxTokens: lim.childMaxTokens,
|
|
147
146
|
childMaxTurns: lim.childMaxTurns,
|
|
@@ -13,20 +13,20 @@ export interface WorkflowAgentSpec {
|
|
|
13
13
|
images?: ImageInput[];
|
|
14
14
|
limits?: {
|
|
15
15
|
maxTurns?: number;
|
|
16
|
-
|
|
16
|
+
maxWalltimeMs?: number;
|
|
17
|
+
maxTokens?: number;
|
|
18
|
+
maxCostUsd?: number;
|
|
17
19
|
};
|
|
18
|
-
maxCostUsd?: number;
|
|
19
|
-
maxTokens?: number;
|
|
20
20
|
}
|
|
21
|
-
export declare const WHITELIST_KEYS: readonly ["objective", "modelName", "thinking", "systemPrompt", "images", "limits"
|
|
21
|
+
export declare const WHITELIST_KEYS: readonly ["objective", "modelName", "thinking", "systemPrompt", "images", "limits"];
|
|
22
22
|
export interface WorkflowChildCaps {
|
|
23
|
-
|
|
23
|
+
perAgentMaxWalltimeMs?: number;
|
|
24
24
|
childMaxCostUsd?: number;
|
|
25
25
|
childMaxTokens?: number;
|
|
26
26
|
childMaxTurns?: number;
|
|
27
27
|
}
|
|
28
28
|
export interface ResourceClampNote {
|
|
29
|
-
field: "maxCostUsd" | "maxTokens" | "
|
|
29
|
+
field: "maxCostUsd" | "maxTokens" | "maxWalltimeMs" | "maxTurns";
|
|
30
30
|
requested: number | undefined;
|
|
31
31
|
applied: number;
|
|
32
32
|
}
|
|
@@ -17,8 +17,6 @@ export const WHITELIST_KEYS = [
|
|
|
17
17
|
"systemPrompt",
|
|
18
18
|
"images",
|
|
19
19
|
"limits",
|
|
20
|
-
"maxCostUsd",
|
|
21
|
-
"maxTokens",
|
|
22
20
|
];
|
|
23
21
|
const VALID_THINKING = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
24
22
|
export function resolveModelName(name, allowlist, models) {
|
|
@@ -91,36 +89,26 @@ function pickWhitelist(scriptSpec) {
|
|
|
91
89
|
}
|
|
92
90
|
if (s.limits !== undefined) {
|
|
93
91
|
if (typeof s.limits !== "object" || s.limits === null || Array.isArray(s.limits)) {
|
|
94
|
-
throw new WorkflowScriptError("agent(spec): `limits` must be an object { maxTurns?,
|
|
92
|
+
throw new WorkflowScriptError("agent(spec): `limits` must be an object { maxTurns?, maxWalltimeMs?, maxTokens?, maxCostUsd? }");
|
|
95
93
|
}
|
|
96
94
|
const l = s.limits;
|
|
97
95
|
const limits = {};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
96
|
+
const readAxis = (field, what) => {
|
|
97
|
+
const raw = l[field];
|
|
98
|
+
if (raw === undefined)
|
|
99
|
+
return;
|
|
100
|
+
if (typeof raw !== "number" || !Number.isFinite(raw))
|
|
101
|
+
throw new WorkflowScriptError(`agent(spec): \`limits.${field}\` must be a number`);
|
|
102
|
+
if (raw <= 0)
|
|
103
|
+
throw new WorkflowScriptError(NON_POSITIVE_LIMIT_MSG(field, what));
|
|
104
|
+
limits[field] = raw;
|
|
105
|
+
};
|
|
106
|
+
readAxis("maxTurns", "turn cap");
|
|
107
|
+
readAxis("maxWalltimeMs", "wall-clock window");
|
|
108
|
+
readAxis("maxTokens", "token budget");
|
|
109
|
+
readAxis("maxCostUsd", "spend ceiling");
|
|
112
110
|
safe.limits = limits;
|
|
113
111
|
}
|
|
114
|
-
if (s.maxCostUsd !== undefined) {
|
|
115
|
-
if (typeof s.maxCostUsd !== "number" || !Number.isFinite(s.maxCostUsd))
|
|
116
|
-
throw new WorkflowScriptError("agent(spec): `maxCostUsd` must be a number");
|
|
117
|
-
safe.maxCostUsd = s.maxCostUsd;
|
|
118
|
-
}
|
|
119
|
-
if (s.maxTokens !== undefined) {
|
|
120
|
-
if (typeof s.maxTokens !== "number" || !Number.isFinite(s.maxTokens))
|
|
121
|
-
throw new WorkflowScriptError("agent(spec): `maxTokens` must be a number");
|
|
122
|
-
safe.maxTokens = s.maxTokens;
|
|
123
|
-
}
|
|
124
112
|
let modelName;
|
|
125
113
|
if (s.modelName !== undefined) {
|
|
126
114
|
if (typeof s.modelName !== "string")
|
|
@@ -131,37 +119,35 @@ function pickWhitelist(scriptSpec) {
|
|
|
131
119
|
}
|
|
132
120
|
function clampResourceLimits(safe, base, caps) {
|
|
133
121
|
const notes = [];
|
|
134
|
-
const requestedCost = safe.maxCostUsd;
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
if (cost !== requestedCost)
|
|
138
|
-
notes.push({ field: "maxCostUsd", requested: requestedCost, applied: cost });
|
|
139
|
-
safe.maxCostUsd = cost;
|
|
140
|
-
}
|
|
141
|
-
const requestedTokens = safe.maxTokens;
|
|
142
|
-
const tokens = minDefined(safe.maxTokens, base.maxTokens, caps?.childMaxTokens);
|
|
143
|
-
if (tokens !== undefined) {
|
|
144
|
-
if (tokens !== requestedTokens)
|
|
145
|
-
notes.push({ field: "maxTokens", requested: requestedTokens, applied: tokens });
|
|
146
|
-
safe.maxTokens = tokens;
|
|
147
|
-
}
|
|
148
|
-
const requestedTimeoutSec = safe.limits?.timeoutSec;
|
|
122
|
+
const requestedCost = safe.limits?.maxCostUsd;
|
|
123
|
+
const requestedTokens = safe.limits?.maxTokens;
|
|
124
|
+
const requestedWalltimeMs = safe.limits?.maxWalltimeMs;
|
|
149
125
|
const requestedMaxTurns = safe.limits?.maxTurns;
|
|
150
|
-
const
|
|
126
|
+
const cost = minDefined(safe.limits?.maxCostUsd, base.limits?.maxCostUsd, caps?.childMaxCostUsd);
|
|
127
|
+
const tokens = minDefined(safe.limits?.maxTokens, base.limits?.maxTokens, caps?.childMaxTokens);
|
|
128
|
+
const maxWalltimeMs = minPositiveDefined(safe.limits?.maxWalltimeMs, base.limits?.maxWalltimeMs, caps?.perAgentMaxWalltimeMs);
|
|
151
129
|
const maxTurns = minPositiveDefined(safe.limits?.maxTurns, base.limits?.maxTurns, caps?.childMaxTurns);
|
|
152
|
-
if (
|
|
153
|
-
notes.push({ field: "
|
|
130
|
+
if (cost !== undefined && cost !== requestedCost)
|
|
131
|
+
notes.push({ field: "maxCostUsd", requested: requestedCost, applied: cost });
|
|
132
|
+
if (tokens !== undefined && tokens !== requestedTokens)
|
|
133
|
+
notes.push({ field: "maxTokens", requested: requestedTokens, applied: tokens });
|
|
134
|
+
if (maxWalltimeMs !== undefined && maxWalltimeMs !== requestedWalltimeMs) {
|
|
135
|
+
notes.push({ field: "maxWalltimeMs", requested: requestedWalltimeMs, applied: maxWalltimeMs });
|
|
154
136
|
}
|
|
155
137
|
if (maxTurns !== undefined && maxTurns !== requestedMaxTurns) {
|
|
156
138
|
notes.push({ field: "maxTurns", requested: requestedMaxTurns, applied: maxTurns });
|
|
157
139
|
}
|
|
158
140
|
const baseOtherLimits = { ...base.limits };
|
|
159
141
|
delete baseOtherLimits.maxTurns;
|
|
160
|
-
delete baseOtherLimits.
|
|
142
|
+
delete baseOtherLimits.maxWalltimeMs;
|
|
143
|
+
delete baseOtherLimits.maxTokens;
|
|
144
|
+
delete baseOtherLimits.maxCostUsd;
|
|
161
145
|
const rebuilt = {
|
|
162
146
|
...baseOtherLimits,
|
|
163
147
|
...(maxTurns !== undefined ? { maxTurns } : {}),
|
|
164
|
-
...(
|
|
148
|
+
...(maxWalltimeMs !== undefined ? { maxWalltimeMs } : {}),
|
|
149
|
+
...(tokens !== undefined ? { maxTokens: tokens } : {}),
|
|
150
|
+
...(cost !== undefined ? { maxCostUsd: cost } : {}),
|
|
165
151
|
};
|
|
166
152
|
if (base.limits !== undefined || Object.keys(rebuilt).length > 0)
|
|
167
153
|
safe.limits = rebuilt;
|
|
@@ -222,6 +222,14 @@ function normalizeWorkflowHardCap(name, v) {
|
|
|
222
222
|
}
|
|
223
223
|
return v;
|
|
224
224
|
}
|
|
225
|
+
function normalizeWorkflowStallMs(v) {
|
|
226
|
+
if (v === undefined)
|
|
227
|
+
return WORKFLOW_AGENT_STALL_MS;
|
|
228
|
+
if (!Number.isFinite(v)) {
|
|
229
|
+
throw new Error(`runWorkflow: stallMs must be a finite number of milliseconds (got ${v}); 0 or a negative value is the documented explicit "off", not NaN/Infinity`);
|
|
230
|
+
}
|
|
231
|
+
return v;
|
|
232
|
+
}
|
|
225
233
|
function createSemaphore(max) {
|
|
226
234
|
let active = 0;
|
|
227
235
|
const waiters = [];
|
|
@@ -307,12 +315,13 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
|
|
|
307
315
|
const maxAgents = normalizeWorkflowHardCap("maxAgents", opts.maxAgents);
|
|
308
316
|
const maxLogChars = normalizeWorkflowHardCap("maxLogChars", opts.maxLogChars);
|
|
309
317
|
const maxResultChars = normalizeWorkflowHardCap("maxResultChars", opts.maxResultChars);
|
|
310
|
-
const
|
|
311
|
-
const
|
|
312
|
-
const
|
|
318
|
+
const totalTimeoutMs = normalizeWorkflowHardCap("totalTimeoutMs", opts.totalTimeoutMs);
|
|
319
|
+
const stallMs = normalizeWorkflowStallMs(opts.stallMs);
|
|
320
|
+
const agentMaxRetries = normalizeWorkflowHardCap("agentMaxRetries", opts.agentMaxRetries) ?? WORKFLOW_AGENT_MAX_RETRIES;
|
|
321
|
+
const throttleBackoffMs = normalizeWorkflowHardCap("throttleBackoffMs", opts.throttleBackoffMs) ?? WORKFLOW_AGENT_THROTTLE_BACKOFF_MS;
|
|
313
322
|
const timers = opts.timers ?? REAL_WORKFLOW_TIMERS;
|
|
314
323
|
const cancelController = new AbortController();
|
|
315
|
-
const timeoutController =
|
|
324
|
+
const timeoutController = totalTimeoutMs !== undefined ? new AbortController() : undefined;
|
|
316
325
|
const signalSources = [cancelController.signal];
|
|
317
326
|
if (opts.signal)
|
|
318
327
|
signalSources.push(opts.signal);
|
|
@@ -375,7 +384,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
|
|
|
375
384
|
};
|
|
376
385
|
markWorkflowActive(runId, scope);
|
|
377
386
|
if (timeoutController) {
|
|
378
|
-
timeoutTimer = setTimeout(() => timeoutController.abort(new Error("workflow total timeout")),
|
|
387
|
+
timeoutTimer = setTimeout(() => timeoutController.abort(new Error("workflow total timeout")), totalTimeoutMs);
|
|
379
388
|
timeoutTimer.unref?.();
|
|
380
389
|
}
|
|
381
390
|
emit({ type: "run_start", runId, scope, ts: t0 });
|
|
@@ -13,9 +13,8 @@ export const EVENT_PROMPT_REGISTRY = new Map([
|
|
|
13
13
|
{ kind: "skills_listing", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", defaultPolicy: "on", rendererRef: "turn-attachments.ts#renderSkillsListingDelta" },
|
|
14
14
|
{ kind: "mcp_instructions", carrier: "message.user-prefix", trust: "external", dedupe: "replace-by-key", defaultPolicy: "off", rendererRef: "turn-attachments.ts#renderMcpInstructionsDelta" },
|
|
15
15
|
{ kind: "mcp_dropped_tools", carrier: "message.user-prefix", trust: "external", dedupe: "replace-by-key", defaultPolicy: "off", rendererRef: "turn-attachments.ts#renderMcpDroppedTools" },
|
|
16
|
-
{ kind: "
|
|
17
|
-
{ kind: "
|
|
18
|
-
{ kind: "deadline_finalize", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#buildFinalizeText" },
|
|
16
|
+
{ kind: "limit_approach_converge", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#limitApproachFrames" },
|
|
17
|
+
{ kind: "limit_approach_deliver", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#limitApproachFrames" },
|
|
19
18
|
{ kind: "final_verification", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#final-verification" },
|
|
20
19
|
].map((e) => [e.kind, e]));
|
|
21
20
|
export function eventDefaultOn(kind) {
|
|
@@ -20,6 +20,9 @@ export async function acquireCcLock(target, opts) {
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
for (let attempt = 0;; attempt++) {
|
|
23
|
+
if (attempt >= RETRIES) {
|
|
24
|
+
throw new Error(`cc lockfile: could not acquire ${lockPath} after ${RETRIES} retries`);
|
|
25
|
+
}
|
|
23
26
|
try {
|
|
24
27
|
mkdirSync(lockPath);
|
|
25
28
|
writeFileSync(ownerPath, nonce);
|
|
@@ -60,21 +63,16 @@ export async function acquireCcLock(target, opts) {
|
|
|
60
63
|
const st = statSync(lockPath);
|
|
61
64
|
if (Date.now() - st.mtimeMs > staleMs) {
|
|
62
65
|
const st2 = statSync(lockPath);
|
|
63
|
-
if (st2.mtimeMs
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
if (st2.mtimeMs === st.mtimeMs) {
|
|
67
|
+
try {
|
|
68
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
}
|
|
69
72
|
}
|
|
70
|
-
continue;
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
catch {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
if (attempt >= RETRIES) {
|
|
77
|
-
throw new Error(`cc lockfile: could not acquire ${lockPath} after ${RETRIES} retries (held and fresh)`);
|
|
78
76
|
}
|
|
79
77
|
const backoff = Math.min(MAX_TIMEOUT_MS, MIN_TIMEOUT_MS * 2 ** attempt);
|
|
80
78
|
await sleep(backoff / 2 + Math.random() * (backoff / 2));
|
|
@@ -3,6 +3,7 @@ import { join, resolve } from "node:path";
|
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { atomicWriteFile, canonicalStoreKey } from "../file/fs-atomic.js";
|
|
5
5
|
import { withCcLock } from "./lockfile.js";
|
|
6
|
+
const INBOX_FILE_EXT = ".json";
|
|
6
7
|
export function sanitizeCcAgentName(name) {
|
|
7
8
|
return name.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
|
|
8
9
|
}
|
|
@@ -23,10 +24,8 @@ export function createCcFileMailboxStore(opts) {
|
|
|
23
24
|
throw new Error(`CcFileMailboxStore: CC inbox files carry no tenant axis — scope:"default" only (D-1); got ${JSON.stringify(scope)}`);
|
|
24
25
|
}
|
|
25
26
|
};
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
return join(inboxDir, `${sanitizeCcAgentName(name)}.json`);
|
|
29
|
-
};
|
|
27
|
+
const leaseKey = (handle) => sanitizeCcAgentName(opts.agentNameOf?.(handle) ?? handle);
|
|
28
|
+
const inboxPath = (handle) => join(inboxDir, `${leaseKey(handle)}${INBOX_FILE_EXT}`);
|
|
30
29
|
const discloseCorrupt = (path, reason) => {
|
|
31
30
|
try {
|
|
32
31
|
opts.onCorruptRead?.({ path, reason });
|
|
@@ -98,6 +97,42 @@ export function createCcFileMailboxStore(opts) {
|
|
|
98
97
|
const saveBox = (path, box) => {
|
|
99
98
|
atomicWriteFile(inboxDir, path, JSON.stringify(box, null, 2));
|
|
100
99
|
};
|
|
100
|
+
const isColderThan = (box, now, maxAgeMs) => {
|
|
101
|
+
if (box.length === 0)
|
|
102
|
+
return false;
|
|
103
|
+
const newest = box.reduce((acc, e) => {
|
|
104
|
+
const t = typeof e.timestamp === "string" ? Date.parse(e.timestamp) : Number.NaN;
|
|
105
|
+
return Number.isFinite(t) ? Math.max(acc, t) : Number.POSITIVE_INFINITY;
|
|
106
|
+
}, 0);
|
|
107
|
+
return newest !== Number.POSITIVE_INFINITY && now - newest > maxAgeMs;
|
|
108
|
+
};
|
|
109
|
+
const sweepColdBoxes = async (now, maxAgeMs) => {
|
|
110
|
+
let dropped = 0;
|
|
111
|
+
for (const f of readdirSync(inboxDir)) {
|
|
112
|
+
if (!f.endsWith(INBOX_FILE_EXT))
|
|
113
|
+
continue;
|
|
114
|
+
const path = join(inboxDir, f);
|
|
115
|
+
const boxKey = f.slice(0, -INBOX_FILE_EXT.length);
|
|
116
|
+
const preNotes = deferredNotes();
|
|
117
|
+
if (!isColderThan(loadBox(path, preNotes.note), now, maxAgeMs)) {
|
|
118
|
+
preNotes.flush();
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const notes = deferredNotes();
|
|
122
|
+
const swept = await withCcLock(path, () => {
|
|
123
|
+
if (!isColderThan(loadBox(path, notes.note), now, maxAgeMs))
|
|
124
|
+
return false;
|
|
125
|
+
leases.delete(boxKey);
|
|
126
|
+
rmSync(path, { force: true });
|
|
127
|
+
return true;
|
|
128
|
+
}).finally(() => {
|
|
129
|
+
notes.flush();
|
|
130
|
+
});
|
|
131
|
+
if (swept)
|
|
132
|
+
dropped += 1;
|
|
133
|
+
}
|
|
134
|
+
return dropped;
|
|
135
|
+
};
|
|
101
136
|
return {
|
|
102
137
|
append: (scope, handle, msg) => {
|
|
103
138
|
requireDefaultScope(scope);
|
|
@@ -124,11 +159,12 @@ export function createCcFileMailboxStore(opts) {
|
|
|
124
159
|
claimLease: (scope, handle, owner, ttlMs, now) => {
|
|
125
160
|
requireDefaultScope(scope);
|
|
126
161
|
const t = now ?? opts.now?.() ?? Date.now();
|
|
127
|
-
const key =
|
|
162
|
+
const key = leaseKey(handle);
|
|
163
|
+
const path = inboxPath(handle);
|
|
128
164
|
const held = leases.get(key);
|
|
129
165
|
if (held !== undefined && held.expiresAt > t && held.owner !== owner)
|
|
130
166
|
return Promise.resolve(null);
|
|
131
|
-
const box = loadBox(
|
|
167
|
+
const box = loadBox(path, discloseCorrupt);
|
|
132
168
|
const maxSeq = box.length;
|
|
133
169
|
const pending = box
|
|
134
170
|
.map((e, i) => ({ e, seq: i + 1 }))
|
|
@@ -147,7 +183,7 @@ export function createCcFileMailboxStore(opts) {
|
|
|
147
183
|
ack: (scope, handle, owner, upToSeq) => {
|
|
148
184
|
requireDefaultScope(scope);
|
|
149
185
|
const path = inboxPath(handle);
|
|
150
|
-
const held = leases.get(
|
|
186
|
+
const held = leases.get(leaseKey(handle));
|
|
151
187
|
if (held === undefined || held.owner !== owner)
|
|
152
188
|
return Promise.resolve();
|
|
153
189
|
if (!existsSync(path))
|
|
@@ -165,14 +201,14 @@ export function createCcFileMailboxStore(opts) {
|
|
|
165
201
|
if (changed)
|
|
166
202
|
saveBox(path, box);
|
|
167
203
|
if (held.maxSeq <= upToSeq)
|
|
168
|
-
leases.delete(
|
|
204
|
+
leases.delete(leaseKey(handle));
|
|
169
205
|
}).finally(() => {
|
|
170
206
|
notes.flush();
|
|
171
207
|
});
|
|
172
208
|
},
|
|
173
209
|
releaseLease: (scope, handle, owner) => {
|
|
174
210
|
requireDefaultScope(scope);
|
|
175
|
-
const key =
|
|
211
|
+
const key = leaseKey(handle);
|
|
176
212
|
const held = leases.get(key);
|
|
177
213
|
if (held !== undefined && held.owner === owner)
|
|
178
214
|
leases.delete(key);
|
|
@@ -185,42 +221,17 @@ export function createCcFileMailboxStore(opts) {
|
|
|
185
221
|
drop: (scope, handle) => {
|
|
186
222
|
requireDefaultScope(scope);
|
|
187
223
|
const path = inboxPath(handle);
|
|
188
|
-
leases.delete(
|
|
189
|
-
|
|
224
|
+
leases.delete(leaseKey(handle));
|
|
225
|
+
return withCcLock(path, () => {
|
|
190
226
|
rmSync(path, { force: true });
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
catch {
|
|
194
|
-
}
|
|
195
|
-
return Promise.resolve();
|
|
227
|
+
});
|
|
196
228
|
},
|
|
197
229
|
reap: (scope, now, reapOpts) => {
|
|
198
230
|
requireDefaultScope(scope);
|
|
199
231
|
const maxAgeMs = reapOpts?.maxAgeMs;
|
|
200
232
|
if (maxAgeMs === undefined || !existsSync(inboxDir))
|
|
201
233
|
return Promise.resolve(0);
|
|
202
|
-
|
|
203
|
-
for (const f of readdirSync(inboxDir)) {
|
|
204
|
-
if (!f.endsWith(".json"))
|
|
205
|
-
continue;
|
|
206
|
-
const path = join(inboxDir, f);
|
|
207
|
-
const box = loadBox(path, discloseCorrupt);
|
|
208
|
-
const newest = box.reduce((acc, e) => {
|
|
209
|
-
const t = typeof e.timestamp === "string" ? Date.parse(e.timestamp) : Number.NaN;
|
|
210
|
-
return Number.isFinite(t) ? Math.max(acc, t) : Number.POSITIVE_INFINITY;
|
|
211
|
-
}, 0);
|
|
212
|
-
if (box.length > 0 && newest !== Number.POSITIVE_INFINITY && now - newest > maxAgeMs) {
|
|
213
|
-
leases.delete(path);
|
|
214
|
-
try {
|
|
215
|
-
rmSync(path, { force: true });
|
|
216
|
-
rmSync(`${path}.lock`, { recursive: true, force: true });
|
|
217
|
-
dropped += 1;
|
|
218
|
-
}
|
|
219
|
-
catch {
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return Promise.resolve(dropped);
|
|
234
|
+
return sweepColdBoxes(now, maxAgeMs);
|
|
224
235
|
},
|
|
225
236
|
};
|
|
226
237
|
}
|
|
@@ -7,6 +7,7 @@ import { type FileCheckpointStoreOptions } from "./checkpoint-store.js";
|
|
|
7
7
|
import type { SessionPolicyStore } from "../../core/session-policy-store.js";
|
|
8
8
|
import type { FileSnapshotStore } from "../../core/file-snapshot-store.js";
|
|
9
9
|
import type { WorkflowJournalStore } from "../../core/workflow-journal-store.js";
|
|
10
|
+
import type { UsageWindowStore } from "../../core/usage-window-store.js";
|
|
10
11
|
export { FileCheckpointStore, type FileCheckpointStoreOptions } from "./checkpoint-store.js";
|
|
11
12
|
export { FileMemoryStore } from "./memory-store.js";
|
|
12
13
|
export { FileSessionRepo, type FileSessionRepoOptions } from "./session-store.js";
|
|
@@ -14,6 +15,7 @@ export { FileToolResultStore } from "./tool-result-store.js";
|
|
|
14
15
|
export { FileSessionPolicyStore, type FileSessionPolicyStoreOptions, type SessionPolicyCorruptReadInfo } from "./session-policy-store.js";
|
|
15
16
|
export { FileFileSnapshotStore, type FileFileSnapshotStoreOptions } from "./file-snapshot-store.js";
|
|
16
17
|
export { FileWorkflowJournalStore, MAX_JOURNAL_RESULT_BYTES, oversizeJournalResult } from "./workflow-journal-store.js";
|
|
18
|
+
export { FileUsageWindowStore } from "./usage-window-store.js";
|
|
17
19
|
export { resolveDataRoot, sanitizeScope, sanitizePathComponent, createFileConsolidationLock } from "./fs-atomic.js";
|
|
18
20
|
export { atomicWriteFile, writeThenLink, ensureDir, readJsonlRecords, AppendLog } from "./fs-atomic.js";
|
|
19
21
|
export interface FileStorageBackendOptions {
|
|
@@ -40,6 +42,7 @@ export declare class FileStorageBackend {
|
|
|
40
42
|
readonly sessionPolicyStore: SessionPolicyStore;
|
|
41
43
|
readonly fileSnapshotStore: FileSnapshotStore;
|
|
42
44
|
readonly workflowJournalStore: WorkflowJournalStore;
|
|
45
|
+
readonly usageWindowStore: UsageWindowStore;
|
|
43
46
|
readonly consolidationLock: (scope: string) => (() => void) | undefined;
|
|
44
47
|
private readonly lock;
|
|
45
48
|
private readonly fileCheckpoints;
|