@botbotgo/agent-harness 0.0.96 → 0.0.98

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.
Files changed (103) hide show
  1. package/dist/api.d.ts +5 -5
  2. package/dist/contracts/core.d.ts +9 -0
  3. package/dist/contracts/core.js +1 -0
  4. package/dist/contracts/runtime.d.ts +421 -0
  5. package/dist/contracts/runtime.js +1 -0
  6. package/dist/contracts/types.d.ts +3 -653
  7. package/dist/contracts/types.js +3 -1
  8. package/dist/contracts/workspace.d.ts +229 -0
  9. package/dist/contracts/workspace.js +1 -0
  10. package/dist/package-version.d.ts +1 -1
  11. package/dist/package-version.js +1 -1
  12. package/dist/runtime/adapter/compat/deepagent-compat.d.ts +16 -0
  13. package/dist/runtime/adapter/compat/deepagent-compat.js +45 -0
  14. package/dist/runtime/adapter/compat/openai-compatible.d.ts +2 -0
  15. package/dist/runtime/adapter/compat/openai-compatible.js +43 -0
  16. package/dist/runtime/adapter/index.d.ts +15 -0
  17. package/dist/runtime/adapter/index.js +15 -0
  18. package/dist/runtime/{langgraph-profiles.d.ts → adapter/langgraph/profiles.d.ts} +1 -1
  19. package/dist/runtime/adapter/model/invocation-request.d.ts +10 -0
  20. package/dist/runtime/adapter/model/invocation-request.js +46 -0
  21. package/dist/runtime/adapter/model/message-assembly.d.ts +6 -0
  22. package/dist/runtime/adapter/model/message-assembly.js +21 -0
  23. package/dist/runtime/adapter/model/model-providers.d.ts +2 -0
  24. package/dist/runtime/adapter/model/model-providers.js +27 -0
  25. package/dist/runtime/adapter/resilience.d.ts +12 -0
  26. package/dist/runtime/adapter/resilience.js +60 -0
  27. package/dist/runtime/{declared-middleware.d.ts → adapter/tool/declared-middleware.d.ts} +1 -1
  28. package/dist/runtime/adapter/tool/interrupt-policy.d.ts +8 -0
  29. package/dist/runtime/adapter/tool/interrupt-policy.js +34 -0
  30. package/dist/runtime/adapter/tool/provider-tool.d.ts +2 -0
  31. package/dist/runtime/adapter/tool/provider-tool.js +25 -0
  32. package/dist/runtime/adapter/tool/resolved-tool.d.ts +18 -0
  33. package/dist/runtime/adapter/tool/resolved-tool.js +62 -0
  34. package/dist/runtime/adapter/tool/tool-arguments.d.ts +7 -0
  35. package/dist/runtime/adapter/tool/tool-arguments.js +87 -0
  36. package/dist/runtime/{tool-hitl.d.ts → adapter/tool/tool-hitl.d.ts} +2 -2
  37. package/dist/runtime/adapter/tool/tool-name-mapping.d.ts +13 -0
  38. package/dist/runtime/adapter/tool/tool-name-mapping.js +101 -0
  39. package/dist/runtime/agent-runtime-adapter.d.ts +5 -20
  40. package/dist/runtime/agent-runtime-adapter.js +33 -536
  41. package/dist/runtime/checkpoint-maintenance.d.ts +1 -45
  42. package/dist/runtime/checkpoint-maintenance.js +1 -259
  43. package/dist/runtime/file-checkpoint-saver.d.ts +1 -20
  44. package/dist/runtime/file-checkpoint-saver.js +1 -106
  45. package/dist/runtime/{event-bus.d.ts → harness/events/event-bus.d.ts} +1 -1
  46. package/dist/runtime/{event-sink.d.ts → harness/events/event-sink.d.ts} +1 -1
  47. package/dist/runtime/{event-sink.js → harness/events/event-sink.js} +1 -1
  48. package/dist/runtime/harness/events/events.d.ts +23 -0
  49. package/dist/runtime/harness/events/events.js +61 -0
  50. package/dist/runtime/harness/events/streaming.d.ts +19 -0
  51. package/dist/runtime/harness/events/streaming.js +96 -0
  52. package/dist/runtime/harness/index.d.ts +16 -0
  53. package/dist/runtime/harness/index.js +16 -0
  54. package/dist/runtime/harness/run/helpers.d.ts +33 -0
  55. package/dist/runtime/harness/run/helpers.js +74 -0
  56. package/dist/runtime/harness/run/resources.d.ts +7 -0
  57. package/dist/runtime/harness/run/resources.js +58 -0
  58. package/dist/runtime/harness/run/resume.d.ts +6 -0
  59. package/dist/runtime/harness/run/resume.js +56 -0
  60. package/dist/runtime/harness/run/routing.d.ts +12 -0
  61. package/dist/runtime/harness/run/routing.js +47 -0
  62. package/dist/runtime/harness/run/run-lifecycle.d.ts +37 -0
  63. package/dist/runtime/harness/run/run-lifecycle.js +109 -0
  64. package/dist/runtime/harness/run/run-queue.d.ts +17 -0
  65. package/dist/runtime/harness/run/run-queue.js +43 -0
  66. package/dist/runtime/{health-monitor.d.ts → harness/system/health-monitor.d.ts} +3 -3
  67. package/dist/runtime/{health-monitor.js → harness/system/health-monitor.js} +2 -2
  68. package/dist/runtime/{inventory.d.ts → harness/system/inventory.d.ts} +2 -2
  69. package/dist/runtime/{inventory.js → harness/system/inventory.js} +4 -4
  70. package/dist/runtime/{policy-engine.d.ts → harness/system/policy-engine.d.ts} +1 -1
  71. package/dist/runtime/{policy-engine.js → harness/system/policy-engine.js} +1 -1
  72. package/dist/runtime/{skill-requirements.d.ts → harness/system/skill-requirements.d.ts} +1 -1
  73. package/dist/runtime/{skill-requirements.js → harness/system/skill-requirements.js} +1 -1
  74. package/dist/runtime/{thread-memory-sync.d.ts → harness/system/thread-memory-sync.d.ts} +2 -2
  75. package/dist/runtime/{thread-memory-sync.js → harness/system/thread-memory-sync.js} +1 -1
  76. package/dist/runtime/harness.d.ts +2 -8
  77. package/dist/runtime/harness.js +143 -493
  78. package/dist/runtime/index.d.ts +7 -7
  79. package/dist/runtime/index.js +7 -7
  80. package/dist/runtime/maintenance/checkpoint-maintenance.d.ts +45 -0
  81. package/dist/runtime/maintenance/checkpoint-maintenance.js +259 -0
  82. package/dist/runtime/maintenance/file-checkpoint-saver.d.ts +20 -0
  83. package/dist/runtime/maintenance/file-checkpoint-saver.js +106 -0
  84. package/dist/runtime/maintenance/index.d.ts +4 -0
  85. package/dist/runtime/maintenance/index.js +4 -0
  86. package/dist/runtime/{runtime-record-maintenance.d.ts → maintenance/runtime-record-maintenance.d.ts} +1 -1
  87. package/dist/runtime/{runtime-record-maintenance.js → maintenance/runtime-record-maintenance.js} +2 -2
  88. package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.d.ts +9 -0
  89. package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.js +39 -0
  90. package/dist/runtime/sqlite-maintained-checkpoint-saver.d.ts +1 -9
  91. package/dist/runtime/sqlite-maintained-checkpoint-saver.js +1 -39
  92. package/dist/runtime/support/harness-support.d.ts +4 -4
  93. package/dist/runtime/support/runtime-factories.d.ts +1 -1
  94. package/dist/runtime/support/runtime-factories.js +1 -1
  95. package/package.json +4 -4
  96. /package/dist/runtime/{langgraph-presets.d.ts → adapter/langgraph/presets.d.ts} +0 -0
  97. /package/dist/runtime/{langgraph-presets.js → adapter/langgraph/presets.js} +0 -0
  98. /package/dist/runtime/{langgraph-profiles.js → adapter/langgraph/profiles.js} +0 -0
  99. /package/dist/runtime/{declared-middleware.js → adapter/tool/declared-middleware.js} +0 -0
  100. /package/dist/runtime/{tool-hitl.js → adapter/tool/tool-hitl.js} +0 -0
  101. /package/dist/runtime/{event-bus.js → harness/events/event-bus.js} +0 -0
  102. /package/dist/runtime/{store.d.ts → harness/system/store.d.ts} +0 -0
  103. /package/dist/runtime/{store.js → harness/system/store.js} +0 -0
@@ -0,0 +1,16 @@
1
+ export * from "./events/event-bus.js";
2
+ export * from "./events/event-sink.js";
3
+ export * from "./events/events.js";
4
+ export * from "./system/health-monitor.js";
5
+ export * from "./run/helpers.js";
6
+ export * from "./system/inventory.js";
7
+ export * from "./system/policy-engine.js";
8
+ export * from "./run/resources.js";
9
+ export * from "./run/resume.js";
10
+ export * from "./run/routing.js";
11
+ export * from "./run/run-lifecycle.js";
12
+ export * from "./run/run-queue.js";
13
+ export * from "./system/skill-requirements.js";
14
+ export * from "./system/store.js";
15
+ export * from "./events/streaming.js";
16
+ export * from "./system/thread-memory-sync.js";
@@ -0,0 +1,33 @@
1
+ import type { ApprovalRecord, HarnessEvent, InternalApprovalRecord, InvocationEnvelope, RunListeners, RunOptions, RunResult, RunStartOptions, MessageContent } from "../../../contracts/types.js";
2
+ export declare function toPublicApprovalRecord(approval: InternalApprovalRecord): ApprovalRecord;
3
+ export declare function normalizeInvocationEnvelope(options: RunStartOptions): {
4
+ context?: Record<string, unknown>;
5
+ state?: Record<string, unknown>;
6
+ files?: Record<string, unknown>;
7
+ invocation?: InvocationEnvelope;
8
+ };
9
+ export declare function isTerminalRunState(state: RunResult["state"]): boolean;
10
+ export declare function buildPersistedRunRequest(input: MessageContent, invocation: {
11
+ context?: Record<string, unknown>;
12
+ state?: Record<string, unknown>;
13
+ files?: Record<string, unknown>;
14
+ invocation?: InvocationEnvelope;
15
+ }, priority?: number): {
16
+ input: MessageContent;
17
+ priority?: number;
18
+ invocation?: InvocationEnvelope;
19
+ savedAt: string;
20
+ };
21
+ export declare function normalizeRunPriority(priority?: number): number;
22
+ export declare function resolveRunListeners(options: RunOptions): RunListeners | undefined;
23
+ export declare function mergeRunResultOutput(result: RunResult, streamedOutput: string): RunResult;
24
+ export declare function createFallbackRunResultFromLatestEvent(input: {
25
+ latestEvent: HarnessEvent;
26
+ currentState: RunResult["state"];
27
+ latestRunId: string;
28
+ entryAgentId: string;
29
+ latestAgentId?: string;
30
+ approvalId?: string;
31
+ pendingActionId?: string;
32
+ output: string;
33
+ }): RunResult;
@@ -0,0 +1,74 @@
1
+ import { normalizeMessageContent } from "../../../utils/message-content.js";
2
+ export function toPublicApprovalRecord(approval) {
3
+ const { toolCallId: _toolCallId, checkpointRef: _checkpointRef, eventRefs: _eventRefs, ...publicApproval } = approval;
4
+ return publicApproval;
5
+ }
6
+ export function normalizeInvocationEnvelope(options) {
7
+ const invocation = options.invocation;
8
+ return {
9
+ context: invocation?.context,
10
+ state: invocation?.inputs,
11
+ files: invocation?.attachments,
12
+ invocation,
13
+ };
14
+ }
15
+ export function isTerminalRunState(state) {
16
+ return state === "completed" || state === "failed";
17
+ }
18
+ export function buildPersistedRunRequest(input, invocation, priority) {
19
+ const envelope = invocation.invocation ?? {
20
+ ...(invocation.context ? { context: invocation.context } : {}),
21
+ ...(invocation.state ? { inputs: invocation.state } : {}),
22
+ ...(invocation.files ? { attachments: invocation.files } : {}),
23
+ };
24
+ return {
25
+ input: normalizeMessageContent(input),
26
+ priority: Number.isFinite(priority) ? Math.trunc(priority) : undefined,
27
+ invocation: envelope && Object.keys(envelope).length > 0
28
+ ? {
29
+ ...(envelope.context ? { context: envelope.context } : {}),
30
+ ...(envelope.inputs ? { inputs: envelope.inputs } : {}),
31
+ ...(envelope.attachments ? { attachments: envelope.attachments } : {}),
32
+ ...(envelope.capabilities ? { capabilities: envelope.capabilities } : {}),
33
+ }
34
+ : undefined,
35
+ savedAt: new Date().toISOString(),
36
+ };
37
+ }
38
+ export function normalizeRunPriority(priority) {
39
+ if (!Number.isFinite(priority)) {
40
+ return 0;
41
+ }
42
+ return Math.trunc(priority);
43
+ }
44
+ export function resolveRunListeners(options) {
45
+ const runtimeListeners = "runtimeListeners" in options ? options.runtimeListeners : undefined;
46
+ const frontendListeners = "frontendListeners" in options ? options.frontendListeners : undefined;
47
+ const listeners = options.listeners;
48
+ if (!listeners && !runtimeListeners && !frontendListeners) {
49
+ return undefined;
50
+ }
51
+ return {
52
+ ...(runtimeListeners ?? {}),
53
+ ...(frontendListeners ?? {}),
54
+ ...(listeners ?? {}),
55
+ };
56
+ }
57
+ export function mergeRunResultOutput(result, streamedOutput) {
58
+ return {
59
+ ...result,
60
+ output: result.output || streamedOutput,
61
+ finalMessageText: result.finalMessageText ?? result.output ?? streamedOutput,
62
+ };
63
+ }
64
+ export function createFallbackRunResultFromLatestEvent(input) {
65
+ return {
66
+ threadId: input.latestEvent.threadId,
67
+ runId: input.latestRunId,
68
+ agentId: input.latestAgentId ?? input.entryAgentId,
69
+ state: input.currentState,
70
+ output: input.output,
71
+ approvalId: input.approvalId,
72
+ pendingActionId: input.pendingActionId,
73
+ };
74
+ }
@@ -0,0 +1,7 @@
1
+ import type { CompiledAgentBinding, RuntimeAdapterOptions, WorkspaceBundle } from "../../../contracts/types.js";
2
+ import type { StoreLike } from "../system/store.js";
3
+ export declare function resolveStoreFromConfig(stores: Map<string, StoreLike>, storeConfig: Record<string, unknown> | undefined, runRoot: string): StoreLike | undefined;
4
+ export declare function resolveStore(stores: Map<string, StoreLike>, defaultStore: StoreLike, defaultRunRoot: string, getBindingStoreConfig: (binding?: CompiledAgentBinding) => Record<string, unknown> | undefined, binding?: CompiledAgentBinding): StoreLike;
5
+ export declare function resolveEmbeddingModel(workspace: WorkspaceBundle, embeddingModels: Map<string, unknown>, embeddingModelRef: string | undefined, runtimeAdapterOptions: RuntimeAdapterOptions): Promise<unknown>;
6
+ export declare function resolveVectorStore(workspace: WorkspaceBundle, vectorStores: Map<string, unknown>, vectorStoreRef: string | undefined, runtimeAdapterOptions: RuntimeAdapterOptions): Promise<unknown>;
7
+ export declare function resolveCheckpointer(checkpointers: Map<string, unknown>, binding: CompiledAgentBinding): unknown;
@@ -0,0 +1,58 @@
1
+ import { createCheckpointerForConfig, createStoreForConfig } from "../../support/runtime-factories.js";
2
+ import { resolveCompiledEmbeddingModel, resolveCompiledEmbeddingModelRef } from "../../support/embedding-models.js";
3
+ import { resolveCompiledVectorStore, resolveCompiledVectorStoreRef } from "../../support/vector-stores.js";
4
+ export function resolveStoreFromConfig(stores, storeConfig, runRoot) {
5
+ const cacheKey = storeConfig ? JSON.stringify(storeConfig) : undefined;
6
+ if (!storeConfig || !cacheKey) {
7
+ return undefined;
8
+ }
9
+ const existing = stores.get(cacheKey);
10
+ if (existing) {
11
+ return existing;
12
+ }
13
+ const created = createStoreForConfig(storeConfig, runRoot);
14
+ stores.set(cacheKey, created);
15
+ return created;
16
+ }
17
+ export function resolveStore(stores, defaultStore, defaultRunRoot, getBindingStoreConfig, binding) {
18
+ const storeConfig = getBindingStoreConfig(binding);
19
+ return resolveStoreFromConfig(stores, storeConfig, binding?.harnessRuntime.runRoot ?? defaultRunRoot) ?? defaultStore;
20
+ }
21
+ export async function resolveEmbeddingModel(workspace, embeddingModels, embeddingModelRef, runtimeAdapterOptions) {
22
+ const compiled = resolveCompiledEmbeddingModelRef(workspace, embeddingModelRef);
23
+ const existing = embeddingModels.get(compiled.id);
24
+ if (existing) {
25
+ return existing;
26
+ }
27
+ const resolved = await resolveCompiledEmbeddingModel(compiled, runtimeAdapterOptions.embeddingModelResolver);
28
+ embeddingModels.set(compiled.id, resolved);
29
+ return resolved;
30
+ }
31
+ export async function resolveVectorStore(workspace, vectorStores, vectorStoreRef, runtimeAdapterOptions) {
32
+ const compiled = resolveCompiledVectorStoreRef(workspace, vectorStoreRef);
33
+ const existing = vectorStores.get(compiled.id);
34
+ if (existing) {
35
+ return existing;
36
+ }
37
+ const resolved = await resolveCompiledVectorStore(workspace, compiled, {
38
+ embeddingModelResolver: runtimeAdapterOptions.embeddingModelResolver,
39
+ vectorStoreResolver: runtimeAdapterOptions.vectorStoreResolver,
40
+ });
41
+ vectorStores.set(compiled.id, resolved);
42
+ return resolved;
43
+ }
44
+ export function resolveCheckpointer(checkpointers, binding) {
45
+ const key = `${binding.harnessRuntime.runRoot}:${JSON.stringify(binding.harnessRuntime.checkpointer ?? { kind: "FileCheckpointer", path: "checkpoints.json" })}`;
46
+ const existing = checkpointers.get(key);
47
+ if (existing) {
48
+ return existing;
49
+ }
50
+ const resolvedConfig = binding.harnessRuntime.checkpointer ?? { kind: "FileCheckpointer", path: "checkpoints.json" };
51
+ if (typeof resolvedConfig === "boolean") {
52
+ checkpointers.set(key, resolvedConfig);
53
+ return resolvedConfig;
54
+ }
55
+ const saver = createCheckpointerForConfig(resolvedConfig, binding.harnessRuntime.runRoot);
56
+ checkpointers.set(key, saver);
57
+ return saver;
58
+ }
@@ -0,0 +1,6 @@
1
+ import type { InternalApprovalRecord, ResumeOptions, ThreadSummary, WorkspaceBundle } from "../../../contracts/types.js";
2
+ import type { RuntimePersistence } from "../../../persistence/types.js";
3
+ type ResumePersistence = Pick<RuntimePersistence, "getApproval" | "getRunApprovals">;
4
+ export declare function resolveApprovalRecord(persistence: ResumePersistence, options: ResumeOptions, thread: ThreadSummary): Promise<InternalApprovalRecord>;
5
+ export declare function buildResumePayload(binding: WorkspaceBundle["bindings"] extends Map<string, infer T> ? T : never, approval: InternalApprovalRecord, options: ResumeOptions): unknown;
6
+ export {};
@@ -0,0 +1,56 @@
1
+ import { isDeepAgentBinding } from "../../support/compiled-binding.js";
2
+ export async function resolveApprovalRecord(persistence, options, thread) {
3
+ if (options.approvalId) {
4
+ const approval = await persistence.getApproval(options.approvalId);
5
+ if (!approval) {
6
+ throw new Error(`Unknown approval ${options.approvalId}`);
7
+ }
8
+ return approval;
9
+ }
10
+ const runId = options.runId ?? thread.latestRunId;
11
+ const approvals = await persistence.getRunApprovals(options.threadId ?? thread.threadId, runId);
12
+ const approval = approvals
13
+ .filter((candidate) => candidate.status === "pending")
14
+ .sort((left, right) => right.requestedAt.localeCompare(left.requestedAt))[0];
15
+ if (!approval) {
16
+ throw new Error(`No pending approval for run ${runId}`);
17
+ }
18
+ return approval;
19
+ }
20
+ export function buildResumePayload(binding, approval, options) {
21
+ if (!isDeepAgentBinding(binding)) {
22
+ return options.decision === "edit" && options.editedInput
23
+ ? { decision: "edit", editedInput: options.editedInput }
24
+ : (options.decision ?? "approve");
25
+ }
26
+ const decisionType = options.decision ?? "approve";
27
+ if (decisionType === "edit" && options.editedInput) {
28
+ return {
29
+ decisions: [
30
+ {
31
+ type: "edit",
32
+ editedAction: {
33
+ name: approval.toolName,
34
+ args: options.editedInput,
35
+ },
36
+ },
37
+ ],
38
+ };
39
+ }
40
+ if (decisionType === "reject") {
41
+ return {
42
+ decisions: [
43
+ {
44
+ type: "reject",
45
+ },
46
+ ],
47
+ };
48
+ }
49
+ return {
50
+ decisions: [
51
+ {
52
+ type: "approve",
53
+ },
54
+ ],
55
+ };
56
+ }
@@ -0,0 +1,12 @@
1
+ import { type MessageContent, type ThreadSummary, type TranscriptMessage, type WorkspaceBundle } from "../../../contracts/types.js";
2
+ export declare function heuristicHostRoute(workspace: WorkspaceBundle, input: MessageContent): string;
3
+ export declare function getDefaultHostAgentId(workspace: WorkspaceBundle, preferredHostAgentId: string): string;
4
+ export declare function buildRoutingInput(input: MessageContent, history?: TranscriptMessage[]): string;
5
+ export declare function resolveSelectedAgentId(options: {
6
+ workspace: WorkspaceBundle;
7
+ input: MessageContent;
8
+ requestedAgentId?: string;
9
+ threadId?: string;
10
+ preferredHostAgentId: string;
11
+ getThreadSummary: (threadId: string) => Promise<ThreadSummary | null>;
12
+ }): Promise<string>;
@@ -0,0 +1,47 @@
1
+ import { AUTO_AGENT_ID } from "../../../contracts/types.js";
2
+ import { extractMessageText } from "../../../utils/message-content.js";
3
+ import { heuristicRoute, inferRoutingBindings } from "../../support/harness-support.js";
4
+ import { isRuntimeEntryBinding } from "../../support/runtime-entry.js";
5
+ export function heuristicHostRoute(workspace, input) {
6
+ const { primaryBinding, secondaryBinding } = inferRoutingBindings(workspace);
7
+ return heuristicRoute(extractMessageText(input), primaryBinding, secondaryBinding);
8
+ }
9
+ export function getDefaultHostAgentId(workspace, preferredHostAgentId) {
10
+ const preferredBinding = workspace.bindings.get(preferredHostAgentId);
11
+ if (preferredBinding && isRuntimeEntryBinding(preferredBinding)) {
12
+ return preferredBinding.agent.id;
13
+ }
14
+ return heuristicHostRoute(workspace, "");
15
+ }
16
+ export function buildRoutingInput(input, history = []) {
17
+ const inputText = extractMessageText(input);
18
+ const priorHistory = history.filter((message) => extractMessageText(message.content).trim());
19
+ if (priorHistory.length === 0) {
20
+ return inputText;
21
+ }
22
+ const recentTurns = priorHistory.slice(-6).map((message) => {
23
+ const role = message.role === "assistant" ? "assistant" : "user";
24
+ const compact = extractMessageText(message.content).replace(/\s+/g, " ").trim();
25
+ return `${role}: ${compact.slice(0, 240)}`;
26
+ });
27
+ return [
28
+ "Recent conversation context:",
29
+ ...recentTurns,
30
+ "",
31
+ `Current user request: ${inputText}`,
32
+ ].join("\n");
33
+ }
34
+ export async function resolveSelectedAgentId(options) {
35
+ const { workspace, input, requestedAgentId, threadId, preferredHostAgentId, getThreadSummary } = options;
36
+ if (!requestedAgentId || requestedAgentId === AUTO_AGENT_ID) {
37
+ if (threadId) {
38
+ const thread = await getThreadSummary(threadId);
39
+ const threadBinding = thread ? workspace.bindings.get(thread.agentId) : undefined;
40
+ if (thread?.agentId && threadBinding && isRuntimeEntryBinding(threadBinding)) {
41
+ return thread.agentId;
42
+ }
43
+ }
44
+ return getDefaultHostAgentId(workspace, preferredHostAgentId);
45
+ }
46
+ return requestedAgentId;
47
+ }
@@ -0,0 +1,37 @@
1
+ import type { HarnessEvent, InternalApprovalRecord, MessageContent, RunResult } from "../../../contracts/types.js";
2
+ import type { RuntimePersistence } from "../../../persistence/types.js";
3
+ type LifecyclePersistence = Pick<RuntimePersistence, "appendThreadMessage" | "getRunApprovals" | "resolveApproval" | "releaseRunClaim" | "clearRunCancel" | "clearRunRequest" | "getRunMeta">;
4
+ type LifecycleRuntime<TBinding> = {
5
+ persistence: LifecyclePersistence;
6
+ emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>, source?: HarnessEvent["source"]) => Promise<HarnessEvent>;
7
+ setRunStateAndEmit: (threadId: string, runId: string, sequence: number, state: RunResult["state"], options: {
8
+ previousState: string | null;
9
+ checkpointRef?: string | null;
10
+ error?: string;
11
+ }) => Promise<HarnessEvent>;
12
+ requestApprovalAndEmit: (threadId: string, runId: string, input: MessageContent, interruptContent: string | undefined, checkpointRef: string, sequence: number) => Promise<{
13
+ approval: InternalApprovalRecord;
14
+ event: HarnessEvent;
15
+ }>;
16
+ synthesizeFinalResult: (binding: TBinding, input: MessageContent, actual: RunResult) => Promise<{
17
+ output: string;
18
+ finalMessageText?: string;
19
+ modelId: string;
20
+ } | null | undefined>;
21
+ reviewRunResult: (binding: TBinding, input: MessageContent, actual: RunResult) => Promise<{
22
+ modelId: string;
23
+ assessment: string;
24
+ } | null | undefined>;
25
+ };
26
+ export declare function appendAssistantMessage(persistence: Pick<RuntimePersistence, "appendThreadMessage">, threadId: string, runId: string, content?: string): Promise<void>;
27
+ export declare function checkpointRefForState(threadId: string, runId: string, state: RunResult["state"]): string | null;
28
+ export declare function expirePendingApprovals(runtime: Pick<LifecycleRuntime<never>, "persistence" | "emit">, threadId: string, runId: string): Promise<void>;
29
+ export declare function finalizeCancelledRun(runtime: Pick<LifecycleRuntime<never>, "persistence" | "emit" | "setRunStateAndEmit">, threadId: string, runId: string, previousState: RunResult["state"] | null, reason?: string): Promise<RunResult>;
30
+ export declare function synthesizeCompletedRun<TBinding>(runtime: Pick<LifecycleRuntime<TBinding>, "synthesizeFinalResult">, binding: TBinding, input: MessageContent, actual: RunResult): Promise<RunResult>;
31
+ export declare function reviewCompletedRun<TBinding>(runtime: Pick<LifecycleRuntime<TBinding>, "reviewRunResult" | "emit">, binding: TBinding, threadId: string, runId: string, input: MessageContent, actual: RunResult): Promise<void>;
32
+ export declare function finalizeContinuedRun<TBinding>(runtime: LifecycleRuntime<TBinding>, binding: TBinding, threadId: string, runId: string, input: MessageContent, actual: RunResult, options: {
33
+ previousState: RunResult["state"] | null;
34
+ stateSequence: number;
35
+ approvalSequence?: number;
36
+ }): Promise<RunResult>;
37
+ export {};
@@ -0,0 +1,109 @@
1
+ export async function appendAssistantMessage(persistence, threadId, runId, content) {
2
+ if (!content) {
3
+ return;
4
+ }
5
+ await persistence.appendThreadMessage(threadId, {
6
+ role: "assistant",
7
+ content,
8
+ runId,
9
+ createdAt: new Date().toISOString(),
10
+ });
11
+ }
12
+ export function checkpointRefForState(threadId, runId, state) {
13
+ return state === "waiting_for_approval" ? `checkpoints/${threadId}/${runId}/cp-1` : null;
14
+ }
15
+ export async function expirePendingApprovals(runtime, threadId, runId) {
16
+ const approvals = await runtime.persistence.getRunApprovals(threadId, runId);
17
+ for (const approval of approvals) {
18
+ if (approval.status !== "pending") {
19
+ continue;
20
+ }
21
+ await runtime.persistence.resolveApproval(threadId, runId, approval.approvalId, "expired");
22
+ await runtime.emit(threadId, runId, 6, "approval.resolved", {
23
+ approvalId: approval.approvalId,
24
+ pendingActionId: approval.pendingActionId,
25
+ decision: "cancel",
26
+ toolName: approval.toolName,
27
+ });
28
+ }
29
+ }
30
+ export async function finalizeCancelledRun(runtime, threadId, runId, previousState, reason) {
31
+ await expirePendingApprovals(runtime, threadId, runId);
32
+ await runtime.persistence.releaseRunClaim(runId);
33
+ await runtime.persistence.clearRunCancel(runId);
34
+ await runtime.persistence.clearRunRequest(threadId, runId);
35
+ await runtime.setRunStateAndEmit(threadId, runId, 104, "cancelled", {
36
+ previousState,
37
+ ...(reason ? { error: reason } : {}),
38
+ });
39
+ const runMeta = await runtime.persistence.getRunMeta(threadId, runId);
40
+ return {
41
+ threadId,
42
+ runId,
43
+ agentId: runMeta.agentId,
44
+ state: "cancelled",
45
+ output: reason ? `cancelled: ${reason}` : "cancelled",
46
+ };
47
+ }
48
+ export async function synthesizeCompletedRun(runtime, binding, input, actual) {
49
+ try {
50
+ const synthesized = await runtime.synthesizeFinalResult(binding, input, actual);
51
+ if (!synthesized) {
52
+ return actual;
53
+ }
54
+ return {
55
+ ...actual,
56
+ output: synthesized.output,
57
+ finalMessageText: synthesized.finalMessageText,
58
+ metadata: {
59
+ ...(typeof actual.metadata === "object" && actual.metadata ? actual.metadata : {}),
60
+ finalSynthesis: {
61
+ modelId: synthesized.modelId,
62
+ },
63
+ },
64
+ };
65
+ }
66
+ catch {
67
+ return actual;
68
+ }
69
+ }
70
+ export async function reviewCompletedRun(runtime, binding, threadId, runId, input, actual) {
71
+ try {
72
+ const review = await runtime.reviewRunResult(binding, input, actual);
73
+ if (!review) {
74
+ return;
75
+ }
76
+ await runtime.emit(threadId, runId, 7, "run.reviewed", {
77
+ modelId: review.modelId,
78
+ assessment: review.assessment,
79
+ });
80
+ }
81
+ catch {
82
+ // Review is advisory; do not fail the completed run if the review pass fails.
83
+ }
84
+ }
85
+ export async function finalizeContinuedRun(runtime, binding, threadId, runId, input, actual, options) {
86
+ let approval;
87
+ const finalizedActual = actual.state === "completed"
88
+ ? await synthesizeCompletedRun(runtime, binding, input, actual)
89
+ : actual;
90
+ await appendAssistantMessage(runtime.persistence, threadId, runId, finalizedActual.output);
91
+ const checkpointRef = checkpointRefForState(threadId, runId, actual.state);
92
+ await runtime.setRunStateAndEmit(threadId, runId, options.stateSequence, finalizedActual.state, {
93
+ previousState: options.previousState,
94
+ checkpointRef,
95
+ });
96
+ if (finalizedActual.state === "waiting_for_approval" && options.approvalSequence) {
97
+ approval = (await runtime.requestApprovalAndEmit(threadId, runId, input, finalizedActual.interruptContent, checkpointRef, options.approvalSequence)).approval;
98
+ }
99
+ if (finalizedActual.state === "completed") {
100
+ await reviewCompletedRun(runtime, binding, threadId, runId, input, finalizedActual);
101
+ }
102
+ return {
103
+ ...finalizedActual,
104
+ threadId,
105
+ runId,
106
+ approvalId: approval?.approvalId ?? finalizedActual.approvalId,
107
+ pendingActionId: approval?.pendingActionId ?? finalizedActual.pendingActionId,
108
+ };
109
+ }
@@ -0,0 +1,17 @@
1
+ export type PendingRunSlot = {
2
+ threadId?: string;
3
+ runId?: string;
4
+ priority: number;
5
+ insertionOrder: number;
6
+ activate: () => void | Promise<void>;
7
+ abort: () => void;
8
+ };
9
+ export type QueuePositionChange = {
10
+ threadId: string;
11
+ runId: string;
12
+ priority: number;
13
+ queuePosition: number;
14
+ };
15
+ export declare function enqueuePendingRunSlot(pendingRunSlots: PendingRunSlot[], entry: Omit<PendingRunSlot, "insertionOrder">, insertionOrder: number): QueuePositionChange[];
16
+ export declare function shiftNextPendingRunSlot(pendingRunSlots: PendingRunSlot[]): PendingRunSlot | undefined;
17
+ export declare function dropPendingRunSlot(pendingRunSlots: PendingRunSlot[], runId: string): boolean;
@@ -0,0 +1,43 @@
1
+ export function enqueuePendingRunSlot(pendingRunSlots, entry, insertionOrder) {
2
+ const previousPositions = new Map(pendingRunSlots
3
+ .filter((candidate) => Boolean(candidate.threadId && candidate.runId))
4
+ .map((candidate, index) => [candidate.runId, index + 1]));
5
+ pendingRunSlots.push({
6
+ ...entry,
7
+ insertionOrder,
8
+ });
9
+ pendingRunSlots.sort((left, right) => {
10
+ if (right.priority !== left.priority) {
11
+ return right.priority - left.priority;
12
+ }
13
+ return left.insertionOrder - right.insertionOrder;
14
+ });
15
+ return pendingRunSlots.flatMap((candidate, index) => {
16
+ if (!candidate.threadId || !candidate.runId) {
17
+ return [];
18
+ }
19
+ const previousPosition = previousPositions.get(candidate.runId);
20
+ const queuePosition = index + 1;
21
+ if (previousPosition === undefined || previousPosition === queuePosition) {
22
+ return [];
23
+ }
24
+ return [{
25
+ threadId: candidate.threadId,
26
+ runId: candidate.runId,
27
+ priority: candidate.priority,
28
+ queuePosition,
29
+ }];
30
+ });
31
+ }
32
+ export function shiftNextPendingRunSlot(pendingRunSlots) {
33
+ return pendingRunSlots.shift();
34
+ }
35
+ export function dropPendingRunSlot(pendingRunSlots, runId) {
36
+ const index = pendingRunSlots.findIndex((entry) => entry.runId === runId);
37
+ if (index < 0) {
38
+ return false;
39
+ }
40
+ const [entry] = pendingRunSlots.splice(index, 1);
41
+ entry?.abort();
42
+ return true;
43
+ }
@@ -1,6 +1,6 @@
1
- import type { RuntimeHealthSnapshot, WorkspaceBundle } from "../contracts/types.js";
2
- import type { RuntimePersistence } from "../persistence/types.js";
3
- import type { MaintenanceLoopStatus } from "./checkpoint-maintenance.js";
1
+ import type { RuntimeHealthSnapshot, WorkspaceBundle } from "../../../contracts/types.js";
2
+ import type { RuntimePersistence } from "../../../persistence/types.js";
3
+ import type { MaintenanceLoopStatus } from "../../maintenance/checkpoint-maintenance.js";
4
4
  type HealthMonitorConfig = {
5
5
  enabled: boolean;
6
6
  evaluateIntervalSeconds: number;
@@ -1,7 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { readdir, stat } from "node:fs/promises";
3
- import { getRuntimeDefaults } from "../workspace/support/workspace-ref-utils.js";
4
- import { discoverCheckpointMaintenanceTargets } from "./checkpoint-maintenance.js";
3
+ import { getRuntimeDefaults } from "../../../workspace/support/workspace-ref-utils.js";
4
+ import { discoverCheckpointMaintenanceTargets } from "../../maintenance/checkpoint-maintenance.js";
5
5
  const DEFAULT_HEALTH_CONFIG = {
6
6
  enabled: false,
7
7
  evaluateIntervalSeconds: 30,
@@ -1,5 +1,5 @@
1
- import type { CompiledAgentBinding, WorkspaceBundle } from "../contracts/types.js";
2
- import type { OpenClawSkillMetadata } from "./support/skill-metadata.js";
1
+ import type { CompiledAgentBinding, WorkspaceBundle } from "../../../contracts/types.js";
2
+ import type { OpenClawSkillMetadata } from "../../support/skill-metadata.js";
3
3
  import { type RequirementAssessmentOptions, type SkillRequirementAssessment } from "./skill-requirements.js";
4
4
  export type InventoryToolRecord = {
5
5
  name: string;
@@ -1,8 +1,8 @@
1
- import { readSkillMetadata } from "./support/skill-metadata.js";
2
- import { getBindingPrimaryTools } from "./support/compiled-binding.js";
1
+ import { readSkillMetadata } from "../../support/skill-metadata.js";
2
+ import { getBindingPrimaryTools } from "../../support/compiled-binding.js";
3
3
  import { assessSkillRequirements, } from "./skill-requirements.js";
4
- import { createRuntimeEnv } from "./support/runtime-env.js";
5
- import { isRuntimeEntryBinding } from "./support/runtime-entry.js";
4
+ import { createRuntimeEnv } from "../../support/runtime-env.js";
5
+ import { isRuntimeEntryBinding } from "../../support/runtime-entry.js";
6
6
  function listHostBindings(workspace) {
7
7
  return Array.from(workspace.bindings.values()).filter((binding) => isRuntimeEntryBinding(binding));
8
8
  }
@@ -1,4 +1,4 @@
1
- import type { CompiledAgentBinding } from "../contracts/types.js";
1
+ import type { CompiledAgentBinding } from "../../../contracts/types.js";
2
2
  export type PolicyEngineDecision = {
3
3
  allowed: boolean;
4
4
  reasons: string[];
@@ -1,4 +1,4 @@
1
- import { getPolicyEvaluators } from "../extensions.js";
1
+ import { getPolicyEvaluators } from "../../../extensions.js";
2
2
  export class PolicyEngine {
3
3
  evaluate(binding) {
4
4
  const reasons = [];
@@ -1,4 +1,4 @@
1
- import type { OpenClawSkillMetadata, SkillMetadata } from "./support/skill-metadata.js";
1
+ import type { OpenClawSkillMetadata, SkillMetadata } from "../../support/skill-metadata.js";
2
2
  export type RequirementStatus = "satisfied" | "missing" | "unknown";
3
3
  export type RequirementCheckRecord = {
4
4
  name: string;
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { existsSync } from "node:fs";
3
- import { augmentExecutablePath } from "./support/runtime-env.js";
3
+ import { augmentExecutablePath } from "../../support/runtime-env.js";
4
4
  function dedupe(items) {
5
5
  return Array.from(new Set(items.filter(Boolean)));
6
6
  }
@@ -1,5 +1,5 @@
1
- import type { HarnessEvent, HarnessEventProjection } from "../contracts/types.js";
2
- import type { RuntimePersistence } from "../persistence/types.js";
1
+ import type { HarnessEvent, HarnessEventProjection } from "../../../contracts/types.js";
2
+ import type { RuntimePersistence } from "../../../persistence/types.js";
3
3
  export declare class ThreadMemorySync implements HarnessEventProjection {
4
4
  private readonly persistence;
5
5
  private readonly store?;
@@ -1,4 +1,4 @@
1
- import { extractMessageText } from "../utils/message-content.js";
1
+ import { extractMessageText } from "../../../utils/message-content.js";
2
2
  function excerpt(message) {
3
3
  if (!message?.content) {
4
4
  return "(none)";