@botbotgo/agent-harness 0.0.290 → 0.0.291

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 (134) hide show
  1. package/README.md +20 -20
  2. package/README.zh.md +14 -14
  3. package/dist/acp.d.ts +5 -5
  4. package/dist/acp.js +3 -3
  5. package/dist/api.d.ts +20 -21
  6. package/dist/api.js +38 -50
  7. package/dist/cli.js +47 -43
  8. package/dist/config/agents/orchestra.yaml +3 -3
  9. package/dist/config/knowledge/knowledge-runtime.yaml +4 -4
  10. package/dist/config/runtime/runtime-memory.yaml +7 -7
  11. package/dist/config/runtime/workspace.yaml +7 -7
  12. package/dist/contracts/core.d.ts +1 -1
  13. package/dist/contracts/runtime.d.ts +35 -40
  14. package/dist/contracts/workspace.d.ts +2 -2
  15. package/dist/flow/build-flow-graph.js +20 -33
  16. package/dist/flow/export-sequence-mermaid.js +4 -4
  17. package/dist/flow/types.d.ts +2 -2
  18. package/dist/index.d.ts +4 -4
  19. package/dist/index.js +1 -1
  20. package/dist/init-project.js +10 -10
  21. package/dist/knowledge/module.js +37 -45
  22. package/dist/mcp.d.ts +9 -9
  23. package/dist/mcp.js +6 -6
  24. package/dist/package-version.d.ts +1 -1
  25. package/dist/package-version.js +1 -1
  26. package/dist/persistence/file-store.d.ts +69 -69
  27. package/dist/persistence/file-store.js +224 -221
  28. package/dist/persistence/sqlite-request-context-store.d.ts +22 -0
  29. package/dist/persistence/sqlite-request-context-store.js +64 -0
  30. package/dist/persistence/sqlite-request-queue-store.d.ts +41 -0
  31. package/dist/persistence/sqlite-request-queue-store.js +120 -0
  32. package/dist/persistence/sqlite-store.d.ts +72 -72
  33. package/dist/persistence/sqlite-store.js +361 -361
  34. package/dist/persistence/types.d.ts +84 -84
  35. package/dist/protocol/a2a/http.js +79 -74
  36. package/dist/protocol/ag-ui/http.d.ts +7 -7
  37. package/dist/protocol/ag-ui/http.js +20 -20
  38. package/dist/resource/resource-impl.js +1 -1
  39. package/dist/runtime/adapter/compat/deepagent-compat.d.ts +2 -2
  40. package/dist/runtime/adapter/flow/invocation-flow.d.ts +6 -5
  41. package/dist/runtime/adapter/flow/invocation-flow.js +6 -5
  42. package/dist/runtime/adapter/flow/stream-runtime.d.ts +3 -3
  43. package/dist/runtime/adapter/flow/stream-runtime.js +5 -4
  44. package/dist/runtime/adapter/invocation-result.d.ts +6 -5
  45. package/dist/runtime/adapter/invocation-result.js +5 -4
  46. package/dist/runtime/adapter/middleware-assembly.js +3 -2
  47. package/dist/runtime/adapter/tool/tool-hitl.js +1 -1
  48. package/dist/runtime/adapter/upstream-configurable-keys.d.ts +2 -0
  49. package/dist/runtime/adapter/upstream-configurable-keys.js +2 -0
  50. package/dist/runtime/agent-runtime-adapter.d.ts +11 -8
  51. package/dist/runtime/agent-runtime-adapter.js +36 -32
  52. package/dist/runtime/harness/events/events.d.ts +8 -8
  53. package/dist/runtime/harness/events/events.js +25 -19
  54. package/dist/runtime/harness/events/listener-runtime.d.ts +5 -4
  55. package/dist/runtime/harness/events/listener-runtime.js +7 -3
  56. package/dist/runtime/harness/events/runtime-event-operations.d.ts +7 -7
  57. package/dist/runtime/harness/events/runtime-event-operations.js +5 -5
  58. package/dist/runtime/harness/events/streaming.d.ts +8 -7
  59. package/dist/runtime/harness/events/streaming.js +20 -19
  60. package/dist/runtime/harness/events/timeline.js +6 -6
  61. package/dist/runtime/harness/index.d.ts +1 -1
  62. package/dist/runtime/harness/index.js +1 -1
  63. package/dist/runtime/harness/run/helpers.d.ts +14 -11
  64. package/dist/runtime/harness/run/helpers.js +10 -7
  65. package/dist/runtime/harness/run/inspection.d.ts +3 -2
  66. package/dist/runtime/harness/run/inspection.js +7 -7
  67. package/dist/runtime/harness/run/operator-overview.d.ts +2 -2
  68. package/dist/runtime/harness/run/operator-overview.js +18 -17
  69. package/dist/runtime/harness/run/queue-diagnostics.js +6 -6
  70. package/dist/runtime/harness/run/recovery.d.ts +15 -15
  71. package/dist/runtime/harness/run/recovery.js +53 -50
  72. package/dist/runtime/harness/run/resources.d.ts +2 -2
  73. package/dist/runtime/harness/run/resources.js +8 -8
  74. package/dist/runtime/harness/run/resume.d.ts +3 -3
  75. package/dist/runtime/harness/run/resume.js +4 -4
  76. package/dist/runtime/harness/run/routing.d.ts +4 -4
  77. package/dist/runtime/harness/run/routing.js +8 -8
  78. package/dist/runtime/harness/run/run-lifecycle.d.ts +12 -12
  79. package/dist/runtime/harness/run/run-lifecycle.js +26 -26
  80. package/dist/runtime/harness/run/run-operations.d.ts +45 -45
  81. package/dist/runtime/harness/run/run-operations.js +79 -78
  82. package/dist/runtime/harness/run/run-queue.d.ts +8 -8
  83. package/dist/runtime/harness/run/run-queue.js +16 -16
  84. package/dist/runtime/harness/run/run-slot-acquisition.d.ts +32 -32
  85. package/dist/runtime/harness/run/run-slot-acquisition.js +41 -41
  86. package/dist/runtime/harness/run/{thread-records.d.ts → session-records.d.ts} +6 -13
  87. package/dist/runtime/harness/run/{thread-records.js → session-records.js} +14 -60
  88. package/dist/runtime/harness/run/start-run.d.ts +36 -36
  89. package/dist/runtime/harness/run/start-run.js +55 -36
  90. package/dist/runtime/harness/run/startup-runtime.d.ts +9 -9
  91. package/dist/runtime/harness/run/startup-runtime.js +22 -20
  92. package/dist/runtime/harness/run/stream-run.d.ts +18 -18
  93. package/dist/runtime/harness/run/stream-run.js +52 -52
  94. package/dist/runtime/harness/runtime-defaults.d.ts +2 -2
  95. package/dist/runtime/harness/runtime-defaults.js +7 -7
  96. package/dist/runtime/harness/system/health-monitor.d.ts +3 -3
  97. package/dist/runtime/harness/system/health-monitor.js +18 -18
  98. package/dist/runtime/harness/system/mem0-ingestion-sync.d.ts +6 -6
  99. package/dist/runtime/harness/system/mem0-ingestion-sync.js +36 -27
  100. package/dist/runtime/harness/system/runtime-memory-candidates.js +2 -2
  101. package/dist/runtime/harness/system/runtime-memory-manager.d.ts +13 -13
  102. package/dist/runtime/harness/system/runtime-memory-manager.js +41 -38
  103. package/dist/runtime/harness/system/runtime-memory-policy.d.ts +1 -1
  104. package/dist/runtime/harness/system/runtime-memory-policy.js +1 -1
  105. package/dist/runtime/harness/system/runtime-memory-records.d.ts +4 -2
  106. package/dist/runtime/harness/system/runtime-memory-records.js +21 -8
  107. package/dist/runtime/harness/system/runtime-memory-sync.d.ts +6 -6
  108. package/dist/runtime/harness/system/runtime-memory-sync.js +47 -44
  109. package/dist/runtime/harness/system/{thread-memory-sync.d.ts → session-memory-sync.d.ts} +7 -7
  110. package/dist/runtime/harness/system/{thread-memory-sync.js → session-memory-sync.js} +28 -28
  111. package/dist/runtime/harness.d.ts +33 -45
  112. package/dist/runtime/harness.js +273 -291
  113. package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -2
  114. package/dist/runtime/maintenance/file-checkpoint-saver.d.ts +1 -1
  115. package/dist/runtime/maintenance/file-checkpoint-saver.js +6 -6
  116. package/dist/runtime/maintenance/runtime-record-maintenance.d.ts +1 -1
  117. package/dist/runtime/maintenance/runtime-record-maintenance.js +33 -33
  118. package/dist/runtime/maintenance/sqlite-checkpoint-saver.d.ts +1 -1
  119. package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +30 -10
  120. package/dist/runtime/support/harness-support.d.ts +2 -2
  121. package/dist/runtime/support/harness-support.js +7 -7
  122. package/dist/runtime/support/runtime-adapter-options.d.ts +2 -2
  123. package/dist/runtime/support/runtime-adapter-options.js +3 -3
  124. package/dist/runtime/support/runtime-factories.d.ts +2 -2
  125. package/dist/runtime/support/runtime-factories.js +10 -10
  126. package/dist/workspace/agent-binding-compiler.js +3 -3
  127. package/dist/workspace/object-loader.js +1 -1
  128. package/dist/workspace/support/workspace-ref-utils.d.ts +4 -3
  129. package/dist/workspace/support/workspace-ref-utils.js +5 -4
  130. package/package.json +1 -1
  131. package/dist/persistence/sqlite-run-context-store.d.ts +0 -22
  132. package/dist/persistence/sqlite-run-context-store.js +0 -64
  133. package/dist/persistence/sqlite-run-queue-store.d.ts +0 -41
  134. package/dist/persistence/sqlite-run-queue-store.js +0 -120
@@ -55,8 +55,8 @@ function resolveSqliteCheckpointPath(binding) {
55
55
  if (kind !== "SqliteSaver") {
56
56
  return null;
57
57
  }
58
- const configuredPath = typeof config.path === "string" ? String(config.path) : resolveRuntimeCheckpointerPath(binding.harnessRuntime.runRoot, "checkpoints.sqlite");
59
- return path.isAbsolute(configuredPath) ? configuredPath : path.join(binding.harnessRuntime.runRoot, configuredPath);
58
+ const configuredPath = typeof config.path === "string" ? String(config.path) : resolveRuntimeCheckpointerPath(binding.harnessRuntime.runtimeRoot, "checkpoints.sqlite");
59
+ return path.isAbsolute(configuredPath) ? configuredPath : path.join(binding.harnessRuntime.runtimeRoot, configuredPath);
60
60
  }
61
61
  export function discoverCheckpointMaintenanceTargets(workspace) {
62
62
  const deduped = new Map();
@@ -15,6 +15,6 @@ export declare class FileCheckpointSaver extends MemorySaver {
15
15
  list(config: MemorySaverConfig, options?: MemorySaverListOptions): AsyncGenerator<import("@langchain/langgraph").CheckpointTuple, void, unknown>;
16
16
  put(config: MemorySaverConfig, checkpoint: MemorySaverPutCheckpoint, metadata: MemorySaverPutMetadata): MemorySaverPutResult;
17
17
  putWrites(config: MemorySaverConfig, writes: MemorySaverPutWrites, taskId: string): Promise<void>;
18
- deleteThread(threadId: string): Promise<void>;
18
+ deleteSession(sessionId: string): Promise<void>;
19
19
  }
20
20
  export { FileCheckpointSaver as FileCheckpointer };
@@ -29,15 +29,15 @@ function decodeBinary(value) {
29
29
  }
30
30
  return value;
31
31
  }
32
- function pruneThreadEntries(record, threadId) {
32
+ function pruneSessionEntries(record, sessionId) {
33
33
  for (const key of Object.keys(record)) {
34
- if (key.includes(threadId)) {
34
+ if (key.includes(sessionId)) {
35
35
  delete record[key];
36
36
  continue;
37
37
  }
38
38
  const value = record[key];
39
39
  if (typeof value === "object" && value && !Array.isArray(value)) {
40
- pruneThreadEntries(value, threadId);
40
+ pruneSessionEntries(value, sessionId);
41
41
  if (Object.keys(value).length === 0) {
42
42
  delete record[key];
43
43
  }
@@ -96,10 +96,10 @@ export class FileCheckpointSaver extends MemorySaver {
96
96
  await this.persist();
97
97
  return result;
98
98
  }
99
- async deleteThread(threadId) {
99
+ async deleteSession(sessionId) {
100
100
  await this.ensureLoaded();
101
- pruneThreadEntries(this.storage, threadId);
102
- pruneThreadEntries(this.writes, threadId);
101
+ pruneSessionEntries(this.storage, sessionId);
102
+ pruneSessionEntries(this.writes, sessionId);
103
103
  await this.persist();
104
104
  }
105
105
  }
@@ -26,7 +26,7 @@ export type RuntimeRecordMaintenanceLoopStatus = {
26
26
  export declare function readRuntimeRecordMaintenanceConfig(workspace: WorkspaceBundle): RuntimeRecordMaintenanceConfig | null;
27
27
  export declare function discoverRuntimeRecordMaintenanceTargets(workspace: WorkspaceBundle): RuntimeRecordMaintenanceTarget[];
28
28
  export declare function maintainSqliteRuntimeRecords(dbPath: string, config: RuntimeRecordMaintenanceConfig, nowMs?: number): Promise<{
29
- deletedThreadCount: number;
29
+ deletedSessionCount: number;
30
30
  }>;
31
31
  export declare class RuntimeRecordMaintenanceLoop {
32
32
  private readonly targets;
@@ -46,68 +46,68 @@ export function readRuntimeRecordMaintenanceConfig(workspace) {
46
46
  return config;
47
47
  }
48
48
  export function discoverRuntimeRecordMaintenanceTargets(workspace) {
49
- const runRoots = new Set();
49
+ const runtimeRoots = new Set();
50
50
  for (const binding of workspace.bindings.values()) {
51
- runRoots.add(binding.harnessRuntime.runRoot);
51
+ runtimeRoots.add(binding.harnessRuntime.runtimeRoot);
52
52
  }
53
- return Array.from(runRoots.values()).map((runRoot) => ({
54
- dbPath: resolveRuntimeSqlitePath(runRoot),
53
+ return Array.from(runtimeRoots.values()).map((runtimeRoot) => ({
54
+ dbPath: resolveRuntimeSqlitePath(runtimeRoot),
55
55
  }));
56
56
  }
57
57
  export async function maintainSqliteRuntimeRecords(dbPath, config, nowMs = Date.now()) {
58
58
  if (!(await fileExists(dbPath))) {
59
- return { deletedThreadCount: 0 };
59
+ return { deletedSessionCount: 0 };
60
60
  }
61
61
  const client = createClient({ url: `file:${dbPath}` });
62
62
  const cutoffIso = new Date(nowMs - (config.policies.maxAgeSeconds ?? 0) * 1000).toISOString();
63
- const runRoot = path.dirname(dbPath);
63
+ const runtimeRoot = path.dirname(dbPath);
64
64
  const result = await client.execute({
65
- sql: `SELECT thread_id
66
- FROM threads
65
+ sql: `SELECT session_id
66
+ FROM sessions
67
67
  WHERE status IN ('completed', 'failed')
68
68
  AND updated_at <= ?
69
- ORDER BY updated_at ASC, thread_id ASC
69
+ ORDER BY updated_at ASC, session_id ASC
70
70
  LIMIT ?`,
71
71
  args: [cutoffIso, config.sqlite.sweepBatchSize],
72
72
  });
73
73
  const rows = result.rows.map((row) => row);
74
74
  if (rows.length === 0) {
75
- return { deletedThreadCount: 0 };
75
+ return { deletedSessionCount: 0 };
76
76
  }
77
- let deletedThreadCount = 0;
77
+ let deletedSessionCount = 0;
78
78
  for (const row of rows) {
79
- const threadId = row.thread_id;
79
+ const sessionId = row.session_id;
80
80
  const artifacts = await client.execute({
81
- sql: `SELECT run_id, path FROM artifacts WHERE thread_id = ?`,
82
- args: [threadId],
81
+ sql: `SELECT request_id, path FROM artifacts WHERE session_id = ?`,
82
+ args: [sessionId],
83
83
  });
84
84
  for (const artifact of artifacts.rows) {
85
- const runId = String(artifact.run_id ?? "");
85
+ const requestId = String(artifact.request_id ?? "");
86
86
  const artifactPath = String(artifact.path ?? "");
87
- if (runId && artifactPath) {
88
- await rm(path.join(runRoot, "threads", threadId, "runs", runId, artifactPath), { force: true });
87
+ if (requestId && artifactPath) {
88
+ await rm(path.join(runtimeRoot, "sessions", sessionId, "requests", requestId, artifactPath), { force: true });
89
89
  }
90
90
  }
91
91
  await client.batch([
92
- "DELETE FROM artifacts WHERE thread_id = ?",
93
- "DELETE FROM approvals WHERE thread_id = ?",
94
- "DELETE FROM events WHERE thread_id = ?",
95
- "DELETE FROM run_inspection WHERE thread_id = ?",
96
- "DELETE FROM run_queue WHERE thread_id = ?",
97
- "DELETE FROM run_requests WHERE thread_id = ?",
98
- "DELETE FROM recovery_intents WHERE thread_id = ?",
99
- "DELETE FROM thread_messages WHERE thread_id = ?",
100
- "DELETE FROM run_control WHERE run_id IN (SELECT run_id FROM runs WHERE thread_id = ?)",
101
- "DELETE FROM runs WHERE thread_id = ?",
102
- "DELETE FROM threads WHERE thread_id = ?",
103
- ].map((sql) => ({ sql, args: [threadId] })), "write");
104
- await rm(path.join(runRoot, "threads", threadId), { recursive: true, force: true });
105
- deletedThreadCount += 1;
92
+ "DELETE FROM artifacts WHERE session_id = ?",
93
+ "DELETE FROM approvals WHERE session_id = ?",
94
+ "DELETE FROM events WHERE session_id = ?",
95
+ "DELETE FROM request_inspection WHERE session_id = ?",
96
+ "DELETE FROM request_queue WHERE session_id = ?",
97
+ "DELETE FROM request_inputs WHERE session_id = ?",
98
+ "DELETE FROM recovery_intents WHERE session_id = ?",
99
+ "DELETE FROM session_messages WHERE session_id = ?",
100
+ "DELETE FROM request_control WHERE request_id IN (SELECT request_id FROM requests WHERE session_id = ?)",
101
+ "DELETE FROM requests WHERE session_id = ?",
102
+ "DELETE FROM sessions WHERE session_id = ?",
103
+ ].map((sql) => ({ sql, args: [sessionId] })), "write");
104
+ await rm(path.join(runtimeRoot, "sessions", sessionId), { recursive: true, force: true });
105
+ deletedSessionCount += 1;
106
106
  }
107
- if (deletedThreadCount > 0 && config.sqlite.vacuum) {
107
+ if (deletedSessionCount > 0 && config.sqlite.vacuum) {
108
108
  await client.execute("VACUUM");
109
109
  }
110
- return { deletedThreadCount };
110
+ return { deletedSessionCount };
111
111
  }
112
112
  export class RuntimeRecordMaintenanceLoop {
113
113
  targets;
@@ -23,6 +23,6 @@ export declare class SqliteCheckpointSaver extends MemorySaver {
23
23
  list(config: MemorySaverConfig, options?: MemorySaverListOptions): AsyncGenerator<import("@langchain/langgraph").CheckpointTuple, void, unknown>;
24
24
  put(config: MemorySaverConfig, checkpoint: MemorySaverPutCheckpoint, metadata: MemorySaverPutMetadata): MemorySaverPutResult;
25
25
  putWrites(config: MemorySaverConfig, writes: MemorySaverPutWrites, taskId: string): Promise<void>;
26
- deleteThread(threadId: string): Promise<void>;
26
+ deleteSession(sessionId: string): Promise<void>;
27
27
  }
28
28
  export { SqliteCheckpointSaver as SqliteSaver };
@@ -2,8 +2,28 @@ import { mkdirSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { MemorySaver } from "@langchain/langgraph";
4
4
  import { createClient } from "@libsql/client";
5
+ import { UPSTREAM_SESSION_CONFIG_KEY } from "../adapter/upstream-configurable-keys.js";
5
6
  const CHECKPOINT_TABLE = "checkpoint_state";
6
7
  const DEFAULT_STATE_KEY = "default";
8
+ function normalizeCheckpointConfig(config) {
9
+ if (!config?.configurable) {
10
+ return config;
11
+ }
12
+ if (UPSTREAM_SESSION_CONFIG_KEY in config.configurable) {
13
+ return config;
14
+ }
15
+ const sessionId = config.configurable.session_id;
16
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
17
+ return config;
18
+ }
19
+ return {
20
+ ...config,
21
+ configurable: {
22
+ ...config.configurable,
23
+ [UPSTREAM_SESSION_CONFIG_KEY]: sessionId,
24
+ },
25
+ };
26
+ }
7
27
  function encodeBinary(value) {
8
28
  if (value instanceof Uint8Array) {
9
29
  return {
@@ -32,15 +52,15 @@ function decodeBinary(value) {
32
52
  }
33
53
  return value;
34
54
  }
35
- function pruneThreadEntries(record, threadId) {
55
+ function pruneSessionEntries(record, sessionId) {
36
56
  for (const key of Object.keys(record)) {
37
- if (key.includes(threadId)) {
57
+ if (key.includes(sessionId)) {
38
58
  delete record[key];
39
59
  continue;
40
60
  }
41
61
  const value = record[key];
42
62
  if (typeof value === "object" && value && !Array.isArray(value)) {
43
- pruneThreadEntries(value, threadId);
63
+ pruneSessionEntries(value, sessionId);
44
64
  if (Object.keys(value).length === 0) {
45
65
  delete record[key];
46
66
  }
@@ -140,19 +160,19 @@ export class SqliteCheckpointSaver extends MemorySaver {
140
160
  async getTuple(config) {
141
161
  return this.runSerialized(async () => {
142
162
  await this.ensureLoaded();
143
- return super.getTuple(config);
163
+ return super.getTuple(normalizeCheckpointConfig(config));
144
164
  });
145
165
  }
146
166
  async *list(config, options) {
147
167
  await this.ensureLoaded();
148
- for await (const item of super.list(config, options)) {
168
+ for await (const item of super.list(normalizeCheckpointConfig(config), options)) {
149
169
  yield item;
150
170
  }
151
171
  }
152
172
  async put(config, checkpoint, metadata) {
153
173
  return this.runSerialized(async () => {
154
174
  await this.ensureLoaded();
155
- const result = await super.put(config, checkpoint, metadata);
175
+ const result = await super.put(normalizeCheckpointConfig(config), checkpoint, metadata);
156
176
  await this.persist();
157
177
  return result;
158
178
  });
@@ -160,16 +180,16 @@ export class SqliteCheckpointSaver extends MemorySaver {
160
180
  async putWrites(config, writes, taskId) {
161
181
  return this.runSerialized(async () => {
162
182
  await this.ensureLoaded();
163
- const result = await super.putWrites(config, writes, taskId);
183
+ const result = await super.putWrites(normalizeCheckpointConfig(config), writes, taskId);
164
184
  await this.persist();
165
185
  return result;
166
186
  });
167
187
  }
168
- async deleteThread(threadId) {
188
+ async deleteSession(sessionId) {
169
189
  return this.runSerialized(async () => {
170
190
  await this.ensureLoaded();
171
- pruneThreadEntries(this.storage, threadId);
172
- pruneThreadEntries(this.writes, threadId);
191
+ pruneSessionEntries(this.storage, sessionId);
192
+ pruneSessionEntries(this.writes, sessionId);
173
193
  await this.persist();
174
194
  });
175
195
  }
@@ -7,8 +7,8 @@ export declare function parseInterruptContent(content: string): {
7
7
  allowedDecisions?: Array<"approve" | "edit" | "reject">;
8
8
  inputPreview?: Record<string, unknown>;
9
9
  };
10
- export declare function createHarnessEvent(threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>, source?: HarnessEvent["source"]): HarnessEvent;
11
- export declare function createPendingApproval(threadId: string, runId: string, checkpointRef: string, input: string, interruptContent?: string): InternalApprovalRecord;
10
+ export declare function createHarnessEvent(sessionId: string, requestId: string, sequence: number, eventType: string, payload: Record<string, unknown>, source?: HarnessEvent["source"]): HarnessEvent;
11
+ export declare function createPendingApproval(sessionId: string, requestId: string, checkpointRef: string, input: string, interruptContent?: string): InternalApprovalRecord;
12
12
  export declare function inferRoutingBindings(workspace: WorkspaceBundle): {
13
13
  primaryBinding: import("../../contracts/workspace.js").CompiledAgentBinding;
14
14
  runtimeEntryBindings: import("../../contracts/workspace.js").CompiledAgentBinding[];
@@ -54,28 +54,28 @@ export function parseInterruptContent(content) {
54
54
  return {};
55
55
  }
56
56
  }
57
- export function createHarnessEvent(threadId, runId, sequence, eventType, payload, source = "runtime") {
57
+ export function createHarnessEvent(sessionId, requestId, sequence, eventType, payload, source = "runtime") {
58
58
  return {
59
59
  eventId: `evt-${String(sequence).padStart(6, "0")}`,
60
60
  eventType,
61
61
  timestamp: new Date().toISOString(),
62
- sessionId: threadId,
63
- requestId: runId,
62
+ sessionId,
63
+ requestId,
64
64
  sequence,
65
65
  source,
66
66
  payload,
67
67
  };
68
68
  }
69
- export function createPendingApproval(threadId, runId, checkpointRef, input, interruptContent) {
69
+ export function createPendingApproval(sessionId, requestId, checkpointRef, input, interruptContent) {
70
70
  const requestedAt = new Date().toISOString();
71
71
  const interrupt = interruptContent ? parseInterruptContent(interruptContent) : {};
72
72
  const approvalId = `approval-${createPersistentId()}`;
73
73
  return {
74
74
  approvalId,
75
75
  pendingActionId: approvalId,
76
- sessionId: threadId,
77
- requestId: runId,
78
- toolCallId: interrupt.toolId ?? `tool-${runId}`,
76
+ sessionId,
77
+ requestId,
78
+ toolCallId: interrupt.toolId ?? `tool-${requestId}`,
79
79
  toolName: interrupt.toolName ?? "write_file",
80
80
  status: "pending",
81
81
  requestedAt,
@@ -3,7 +3,7 @@ import type { StoreLike } from "../harness/system/store.js";
3
3
  export declare function createBindingStoreResolver(input: {
4
4
  stores: Map<string, StoreLike>;
5
5
  defaultStore: StoreLike;
6
- getDefaultRunRoot: () => string;
6
+ getDefaultRuntimeRoot: () => string;
7
7
  }): (binding?: CompiledAgentBinding) => StoreLike;
8
8
  export declare function resolveRuntimeAdapterOptions(input: {
9
9
  workspace: WorkspaceBundle;
@@ -13,5 +13,5 @@ export declare function resolveRuntimeAdapterOptions(input: {
13
13
  defaultStore: StoreLike;
14
14
  embeddingModels: Map<string, unknown>;
15
15
  vectorStores: Map<string, unknown>;
16
- getDefaultRunRoot: () => string;
16
+ getDefaultRuntimeRoot: () => string;
17
17
  }): RuntimeAdapterOptions;
@@ -2,15 +2,15 @@ import { createResourceBackendResolver, createResourceToolResolver } from "../..
2
2
  import { resolveCheckpointer, resolveEmbeddingModel, resolveStore, resolveVectorStore, } from "../harness/run/resources.js";
3
3
  import { getBindingStoreConfig } from "./compiled-binding.js";
4
4
  export function createBindingStoreResolver(input) {
5
- return (binding) => resolveStore(input.stores, input.defaultStore, input.getDefaultRunRoot(), (currentBinding) => currentBinding ? getBindingStoreConfig(currentBinding) : undefined, binding);
5
+ return (binding) => resolveStore(input.stores, input.defaultStore, input.getDefaultRuntimeRoot(), (currentBinding) => currentBinding ? getBindingStoreConfig(currentBinding) : undefined, binding);
6
6
  }
7
7
  export function resolveRuntimeAdapterOptions(input) {
8
- const { workspace, runtimeAdapterOptions, checkpointers, stores, defaultStore, embeddingModels, vectorStores, getDefaultRunRoot, } = input;
8
+ const { workspace, runtimeAdapterOptions, checkpointers, stores, defaultStore, embeddingModels, vectorStores, getDefaultRuntimeRoot, } = input;
9
9
  const storeResolver = runtimeAdapterOptions.storeResolver ??
10
10
  createBindingStoreResolver({
11
11
  stores,
12
12
  defaultStore,
13
- getDefaultRunRoot,
13
+ getDefaultRuntimeRoot,
14
14
  });
15
15
  return {
16
16
  ...runtimeAdapterOptions,
@@ -1,3 +1,3 @@
1
1
  import { type StoreLike } from "../harness/system/store.js";
2
- export declare function createStoreForConfig(storeConfig: Record<string, unknown>, runRoot: string): StoreLike;
3
- export declare function createCheckpointerForConfig(checkpointerConfig: Record<string, unknown> | boolean, runRoot: string): unknown;
2
+ export declare function createStoreForConfig(storeConfig: Record<string, unknown>, runtimeRoot: string): StoreLike;
3
+ export declare function createCheckpointerForConfig(checkpointerConfig: Record<string, unknown> | boolean, runtimeRoot: string): unknown;
@@ -4,16 +4,16 @@ import { FileCheckpointSaver } from "../maintenance/file-checkpoint-saver.js";
4
4
  import { SqliteCheckpointSaver } from "../maintenance/sqlite-checkpoint-saver.js";
5
5
  import { createInMemoryStore, FileBackedStore, SqliteBackedStore } from "../harness/system/store.js";
6
6
  import { resolveKnowledgeFileStorePath, resolveKnowledgeStorePath, resolveRuntimeCheckpointerPath, } from "./runtime-layout.js";
7
- export function createStoreForConfig(storeConfig, runRoot) {
7
+ export function createStoreForConfig(storeConfig, runtimeRoot) {
8
8
  const kind = typeof storeConfig.kind === "string" ? storeConfig.kind : "FileStore";
9
9
  switch (kind) {
10
10
  case "FileStore": {
11
- const configuredPath = typeof storeConfig.path === "string" ? storeConfig.path : resolveKnowledgeFileStorePath(runRoot, "records.json");
12
- return new FileBackedStore(path.isAbsolute(configuredPath) ? configuredPath : path.join(runRoot, configuredPath));
11
+ const configuredPath = typeof storeConfig.path === "string" ? storeConfig.path : resolveKnowledgeFileStorePath(runtimeRoot, "records.json");
12
+ return new FileBackedStore(path.isAbsolute(configuredPath) ? configuredPath : path.join(runtimeRoot, configuredPath));
13
13
  }
14
14
  case "SqliteStore": {
15
- const configuredPath = typeof storeConfig.path === "string" ? storeConfig.path : resolveKnowledgeStorePath(runRoot, "records.sqlite");
16
- return new SqliteBackedStore(path.isAbsolute(configuredPath) ? configuredPath : path.join(runRoot, configuredPath));
15
+ const configuredPath = typeof storeConfig.path === "string" ? storeConfig.path : resolveKnowledgeStorePath(runtimeRoot, "records.sqlite");
16
+ return new SqliteBackedStore(path.isAbsolute(configuredPath) ? configuredPath : path.join(runtimeRoot, configuredPath));
17
17
  }
18
18
  case "InMemoryStore":
19
19
  return createInMemoryStore();
@@ -25,7 +25,7 @@ export function createStoreForConfig(storeConfig, runRoot) {
25
25
  throw new Error(`Unsupported store kind ${String(kind)}`);
26
26
  }
27
27
  }
28
- export function createCheckpointerForConfig(checkpointerConfig, runRoot) {
28
+ export function createCheckpointerForConfig(checkpointerConfig, runtimeRoot) {
29
29
  if (typeof checkpointerConfig === "boolean") {
30
30
  return checkpointerConfig;
31
31
  }
@@ -36,14 +36,14 @@ export function createCheckpointerForConfig(checkpointerConfig, runRoot) {
36
36
  case "SqliteSaver": {
37
37
  const configuredPath = typeof checkpointerConfig.path === "string"
38
38
  ? String(checkpointerConfig.path)
39
- : resolveRuntimeCheckpointerPath(runRoot, "checkpoints.sqlite");
40
- return new SqliteCheckpointSaver(path.isAbsolute(configuredPath) ? configuredPath : path.join(runRoot, configuredPath));
39
+ : resolveRuntimeCheckpointerPath(runtimeRoot, "checkpoints.sqlite");
40
+ return new SqliteCheckpointSaver(path.isAbsolute(configuredPath) ? configuredPath : path.join(runtimeRoot, configuredPath));
41
41
  }
42
42
  case "FileCheckpointer": {
43
43
  const configuredPath = typeof checkpointerConfig.path === "string"
44
44
  ? String(checkpointerConfig.path)
45
- : resolveRuntimeCheckpointerPath(runRoot, "checkpoints.json");
46
- return new FileCheckpointSaver(path.isAbsolute(configuredPath) ? configuredPath : path.join(runRoot, configuredPath));
45
+ : resolveRuntimeCheckpointerPath(runtimeRoot, "checkpoints.json");
46
+ return new FileCheckpointSaver(path.isAbsolute(configuredPath) ? configuredPath : path.join(runtimeRoot, configuredPath));
47
47
  }
48
48
  default:
49
49
  throw new Error(`Unsupported checkpointer kind ${String(kind)}`);
@@ -361,8 +361,8 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
361
361
  const compiledFilesystemConfig = agent.executionMode === "langchain-v1"
362
362
  ? mergeConfigObjects(runtimeFilesystemDefaults, getAgentExecutionObject(agent, "filesystem", { executionMode: "langchain-v1" }))
363
363
  : undefined;
364
- const runRoot = typeof agent.runRoot === "string" && agent.runRoot.trim().length > 0
365
- ? (path.isAbsolute(agent.runRoot) ? agent.runRoot : path.resolve(runtimeStorage.dataRoot, agent.runRoot))
364
+ const runtimeRoot = typeof agent.runtimeRoot === "string" && agent.runtimeRoot.trim().length > 0
365
+ ? (path.isAbsolute(agent.runtimeRoot) ? agent.runtimeRoot : path.resolve(runtimeStorage.dataRoot, agent.runtimeRoot))
366
366
  : runtimeStorage.dataRoot;
367
367
  const base = {
368
368
  agent,
@@ -370,7 +370,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
370
370
  applicationRoot: runtimeStorage.applicationRoot,
371
371
  dataRoot: runtimeStorage.dataRoot,
372
372
  runtimeProfile: runtimeStorage.runtimeProfile,
373
- runRoot,
373
+ runtimeRoot,
374
374
  workspaceRoot: runtimeStorage.applicationRoot,
375
375
  capabilities: inferAgentCapabilities(agent),
376
376
  resilience,
@@ -515,7 +515,7 @@ export function parseAgentItem(item, sourcePath) {
515
515
  : { delegation: true, memory: true }),
516
516
  description: String(normalizedItem.description ?? ""),
517
517
  modelRef: readExecutionValue(normalizedItem, "modelRef", readSingleRef) ?? "",
518
- runRoot: typeof runtime?.runRoot === "string" ? runtime.runRoot : undefined,
518
+ runtimeRoot: typeof runtime?.runtimeRoot === "string" ? runtime.runtimeRoot : undefined,
519
519
  applicationRoot: typeof runtime?.applicationRoot === "string" ? runtime.applicationRoot : undefined,
520
520
  dataRoot: typeof runtime?.dataRoot === "string" ? runtime.dataRoot : undefined,
521
521
  runtimeProfile: typeof runtime?.profile === "string" ? runtime.profile : undefined,
@@ -9,12 +9,12 @@ export type RoutingRule = {
9
9
  maxLength?: number;
10
10
  minLines?: number;
11
11
  maxLines?: number;
12
- hasThreadId?: boolean;
12
+ hasSessionId?: boolean;
13
13
  caseSensitive?: boolean;
14
14
  };
15
15
  export type RecoveryConfig = {
16
16
  enabled: boolean;
17
- resumeResumingRunsOnStartup: boolean;
17
+ resumeResumingRequestsOnStartup: boolean;
18
18
  maxRecoveryAttempts: number;
19
19
  };
20
20
  export type ConcurrencyConfig = {
@@ -52,7 +52,8 @@ export declare function getResilienceConfig(refs: Map<string, WorkspaceObject |
52
52
  export declare function getRoutingDefaultAgentId(refs: Map<string, WorkspaceObject | ParsedAgentObject>): string | undefined;
53
53
  export declare function getRoutingRules(refs: Map<string, WorkspaceObject | ParsedAgentObject>): RoutingRule[];
54
54
  export declare function matchRoutingRule(input: string, rule: RoutingRule, options?: {
55
- threadId?: string;
55
+ sessionId?: string;
56
+ legacySessionId?: string;
56
57
  }): boolean;
57
58
  export declare function resolvePromptValue(promptConfig: unknown): string | undefined;
58
59
  export declare function resolveRefId(ref: string): string;
@@ -91,8 +91,8 @@ export function getRecoveryConfig(refs) {
91
91
  : 3;
92
92
  return {
93
93
  enabled: recovery.enabled !== false,
94
- resumeResumingRunsOnStartup: typeof recovery.resumeResumingRunsOnStartup === "boolean"
95
- ? recovery.resumeResumingRunsOnStartup
94
+ resumeResumingRequestsOnStartup: typeof recovery.resumeResumingRequestsOnStartup === "boolean"
95
+ ? recovery.resumeResumingRequestsOnStartup
96
96
  : true,
97
97
  maxRecoveryAttempts,
98
98
  };
@@ -223,7 +223,7 @@ export function getRoutingRules(refs) {
223
223
  maxLength: toPositiveNumber(typed.maxLength),
224
224
  minLines: toPositiveNumber(typed.minLines),
225
225
  maxLines: toPositiveNumber(typed.maxLines),
226
- hasThreadId: typeof typed.hasThreadId === "boolean" ? typed.hasThreadId : undefined,
226
+ hasSessionId: typeof typed.hasSessionId === "boolean" ? typed.hasSessionId : undefined,
227
227
  caseSensitive: typed.caseSensitive === true,
228
228
  }];
229
229
  });
@@ -233,7 +233,8 @@ export function matchRoutingRule(input, rule, options = {}) {
233
233
  const source = rule.caseSensitive ? text : text.toLowerCase();
234
234
  const lineCount = text ? text.split(/\n+/).length : 0;
235
235
  const normalize = (value) => (rule.caseSensitive ? value : value.toLowerCase());
236
- if (rule.hasThreadId !== undefined && rule.hasThreadId !== Boolean(options.threadId)) {
236
+ const sessionId = options.sessionId ?? options.legacySessionId;
237
+ if (rule.hasSessionId !== undefined && rule.hasSessionId !== Boolean(sessionId)) {
237
238
  return false;
238
239
  }
239
240
  if (rule.minLength !== undefined && text.length < rule.minLength) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.290",
3
+ "version": "0.0.291",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,22 +0,0 @@
1
- import type { InValue } from "@libsql/client";
2
- import type { TranscriptMessage } from "../contracts/types.js";
3
- import type { PersistedRunRequest, RecoveryIntent } from "./types.js";
4
- type SqlRow = Record<string, unknown>;
5
- type SqliteRunContextStoreDb = {
6
- execute(sql: string, args?: InValue[]): Promise<void>;
7
- selectOne(sql: string, args?: InValue[]): Promise<SqlRow | null>;
8
- selectAll(sql: string, args?: InValue[]): Promise<SqlRow[]>;
9
- };
10
- export declare class SqliteRunContextStore {
11
- private readonly db;
12
- constructor(db: SqliteRunContextStoreDb);
13
- saveRunRequest(threadId: string, runId: string, request: PersistedRunRequest): Promise<void>;
14
- getRunRequest(threadId: string, runId: string): Promise<PersistedRunRequest | null>;
15
- clearRunRequest(threadId: string, runId: string): Promise<void>;
16
- appendThreadMessage(threadId: string, message: TranscriptMessage): Promise<void>;
17
- listThreadMessages(threadId: string, limit?: number): Promise<TranscriptMessage[]>;
18
- saveRecoveryIntent(threadId: string, runId: string, intent: RecoveryIntent): Promise<void>;
19
- getRecoveryIntent(threadId: string, runId: string): Promise<RecoveryIntent | null>;
20
- clearRecoveryIntent(threadId: string, runId: string): Promise<void>;
21
- }
22
- export {};
@@ -1,64 +0,0 @@
1
- function asString(value) {
2
- return typeof value === "string" ? value : String(value ?? "");
3
- }
4
- function parseJson(value) {
5
- return JSON.parse(asString(value));
6
- }
7
- function nowIso() {
8
- return new Date(Date.now()).toISOString();
9
- }
10
- export class SqliteRunContextStore {
11
- db;
12
- constructor(db) {
13
- this.db = db;
14
- }
15
- async saveRunRequest(threadId, runId, request) {
16
- await this.db.execute(`INSERT OR REPLACE INTO run_requests
17
- (run_id, thread_id, request_json, saved_at)
18
- VALUES (?, ?, ?, ?)`, [runId, threadId, JSON.stringify(request), request.savedAt]);
19
- }
20
- async getRunRequest(threadId, runId) {
21
- const row = await this.db.selectOne("SELECT request_json FROM run_requests WHERE thread_id = ? AND run_id = ?", [threadId, runId]);
22
- return row ? parseJson(row.request_json) : null;
23
- }
24
- async clearRunRequest(threadId, runId) {
25
- await this.db.execute("DELETE FROM run_requests WHERE thread_id = ? AND run_id = ?", [threadId, runId]);
26
- }
27
- async appendThreadMessage(threadId, message) {
28
- await this.db.execute(`INSERT INTO thread_messages
29
- (thread_id, role, content_json, run_id, created_at)
30
- VALUES (?, ?, ?, ?, ?)`, [threadId, message.role, JSON.stringify(message.content), message.requestId ?? message.runId, message.createdAt]);
31
- }
32
- async listThreadMessages(threadId, limit = 12) {
33
- const rows = await this.db.selectAll(`SELECT role, content_json, run_id, created_at
34
- FROM (
35
- SELECT role, content_json, run_id, created_at, id
36
- FROM thread_messages
37
- WHERE thread_id = ?
38
- ORDER BY created_at DESC, id DESC
39
- LIMIT ?
40
- ) recent
41
- ORDER BY created_at ASC, id ASC`, [threadId, limit]);
42
- return rows.map((row) => ({
43
- role: asString(row.role),
44
- content: parseJson(row.content_json),
45
- requestId: asString(row.run_id),
46
- createdAt: asString(row.created_at),
47
- }));
48
- }
49
- async saveRecoveryIntent(threadId, runId, intent) {
50
- const savedAt = typeof intent.savedAt === "string"
51
- ? (intent.savedAt)
52
- : nowIso();
53
- await this.db.execute(`INSERT OR REPLACE INTO recovery_intents
54
- (run_id, thread_id, intent_json, saved_at)
55
- VALUES (?, ?, ?, ?)`, [runId, threadId, JSON.stringify(intent), savedAt]);
56
- }
57
- async getRecoveryIntent(threadId, runId) {
58
- const row = await this.db.selectOne("SELECT intent_json FROM recovery_intents WHERE thread_id = ? AND run_id = ?", [threadId, runId]);
59
- return row ? parseJson(row.intent_json) : null;
60
- }
61
- async clearRecoveryIntent(threadId, runId) {
62
- await this.db.execute("DELETE FROM recovery_intents WHERE thread_id = ? AND run_id = ?", [threadId, runId]);
63
- }
64
- }
@@ -1,41 +0,0 @@
1
- import type { InValue } from "@libsql/client";
2
- import type { PersistedRunControlRecord, PersistedRunQueueRecord } from "./types.js";
3
- type SqlRow = Record<string, unknown>;
4
- type SqliteRunQueueStoreDb = {
5
- execute(sql: string, args?: InValue[]): Promise<void>;
6
- selectOne(sql: string, args?: InValue[]): Promise<SqlRow | null>;
7
- selectAll(sql: string, args?: InValue[]): Promise<SqlRow[]>;
8
- };
9
- export declare class SqliteRunQueueStore {
10
- private readonly db;
11
- constructor(db: SqliteRunQueueStoreDb);
12
- private mapQueuedRun;
13
- private mapRunControl;
14
- enqueueRun(input: {
15
- threadId: string;
16
- runId: string;
17
- priority?: number;
18
- queueKey?: string | null;
19
- availableAt?: string;
20
- }): Promise<void>;
21
- getQueuedRun(runId: string): Promise<PersistedRunQueueRecord | null>;
22
- claimQueuedRun(input: {
23
- threadId: string;
24
- runId: string;
25
- workerId: string;
26
- claimedAt?: string;
27
- leaseExpiresAt: string;
28
- }): Promise<PersistedRunQueueRecord>;
29
- renewRunLease(input: {
30
- runId: string;
31
- workerId: string;
32
- heartbeatAt?: string;
33
- leaseExpiresAt: string;
34
- }): Promise<void>;
35
- releaseRunClaim(runId: string): Promise<void>;
36
- listExpiredClaimedRuns(cutoffIso: string): Promise<PersistedRunQueueRecord[]>;
37
- getRunControl(runId: string): Promise<PersistedRunControlRecord | null>;
38
- requestRunCancel(runId: string, reason?: string): Promise<PersistedRunControlRecord>;
39
- clearRunCancel(runId: string): Promise<void>;
40
- }
41
- export {};