@botbotgo/agent-harness 0.0.298 → 0.0.300

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 (166) hide show
  1. package/README.md +78 -38
  2. package/README.zh.md +80 -31
  3. package/dist/acp.d.ts +3 -0
  4. package/dist/acp.js +10 -2
  5. package/dist/api.d.ts +14 -2
  6. package/dist/api.js +19 -3
  7. package/dist/cli.d.ts +18 -1
  8. package/dist/cli.js +1408 -319
  9. package/dist/client/acp.d.ts +9 -3
  10. package/dist/client/acp.js +55 -1
  11. package/dist/client/in-process.d.ts +5 -2
  12. package/dist/client/in-process.js +4 -6
  13. package/dist/client/index.d.ts +1 -1
  14. package/dist/client/types.d.ts +6 -5
  15. package/dist/config/agents/direct.yaml +7 -17
  16. package/dist/config/agents/orchestra.yaml +9 -65
  17. package/dist/config/catalogs/embedding-models.yaml +1 -1
  18. package/dist/config/catalogs/stores.yaml +1 -1
  19. package/dist/config/knowledge/knowledge-runtime.yaml +36 -2
  20. package/dist/config/knowledge/procedural-memory-runtime.yaml +78 -0
  21. package/dist/config/{catalogs/models.yaml → models.yaml} +2 -2
  22. package/dist/config/prompts/direct-system.md +16 -0
  23. package/dist/config/prompts/orchestra-system.md +62 -0
  24. package/dist/config/prompts/routing-system.md +14 -0
  25. package/dist/config/runtime/runtime-memory.yaml +39 -5
  26. package/dist/config/runtime/workspace.yaml +7 -16
  27. package/dist/contracts/runtime.d.ts +242 -1
  28. package/dist/contracts/workspace.d.ts +2 -0
  29. package/dist/index.d.ts +5 -3
  30. package/dist/index.js +2 -1
  31. package/dist/init-project.js +178 -33
  32. package/dist/knowledge/contracts.d.ts +5 -0
  33. package/dist/knowledge/module.d.ts +5 -0
  34. package/dist/knowledge/module.js +340 -18
  35. package/dist/package-version.d.ts +1 -1
  36. package/dist/package-version.js +1 -1
  37. package/dist/persistence/file-store.d.ts +5 -1
  38. package/dist/persistence/file-store.js +16 -0
  39. package/dist/persistence/sqlite-store.d.ts +4 -1
  40. package/dist/persistence/sqlite-store.js +88 -14
  41. package/dist/persistence/types.d.ts +4 -1
  42. package/dist/procedural/config.d.ts +63 -0
  43. package/dist/procedural/config.js +125 -0
  44. package/dist/procedural/index.d.ts +2 -0
  45. package/dist/procedural/index.js +1 -0
  46. package/dist/protocol/ag-ui/http.d.ts +3 -0
  47. package/dist/protocol/ag-ui/http.js +10 -0
  48. package/dist/request-events.d.ts +63 -0
  49. package/dist/request-events.js +400 -0
  50. package/dist/resource/isolation.js +11 -0
  51. package/dist/resource/resource-impl.d.ts +1 -0
  52. package/dist/resource/resource-impl.js +103 -12
  53. package/dist/resources/init-templates/agent-context/deep-research.md +5 -0
  54. package/dist/resources/init-templates/prompts/research-analyst-basic.md +1 -0
  55. package/dist/resources/init-templates/prompts/research-analyst-web-search.md +1 -0
  56. package/dist/resources/init-templates/prompts/research-host-deep-research-basic.md +1 -0
  57. package/dist/resources/init-templates/prompts/research-host-deep-research-web-search.md +1 -0
  58. package/dist/resources/init-templates/prompts/research-host-single-agent-basic.md +1 -0
  59. package/dist/resources/init-templates/prompts/research-host-single-agent-web-search.md +1 -0
  60. package/dist/resources/prompts/runtime/browser-capability-disclaimer-recovery.md +1 -0
  61. package/dist/resources/prompts/runtime/default-subagent.md +2 -0
  62. package/dist/resources/prompts/runtime/durable-memory-context.md +7 -0
  63. package/dist/resources/prompts/runtime/execution-with-tool-evidence-retry.md +1 -0
  64. package/dist/resources/prompts/runtime/execution-with-tool-evidence.md +1 -0
  65. package/dist/resources/prompts/runtime/invalid-tool-selection-recovery.md +1 -0
  66. package/dist/resources/prompts/runtime/memory-manager.md +31 -0
  67. package/dist/resources/prompts/runtime/memory-mutation-reconciliation.md +22 -0
  68. package/dist/resources/prompts/runtime/slash-command-skill.md +6 -0
  69. package/dist/resources/prompts/runtime/strict-tool-json.md +1 -0
  70. package/dist/resources/prompts/runtime/workspace-boundary-guidance.md +3 -0
  71. package/dist/resources/prompts/runtime/workspace-relative-path.md +1 -0
  72. package/dist/resources/prompts/runtime/write-todos-descriptive-content.md +1 -0
  73. package/dist/resources/prompts/runtime/write-todos-full-entry.md +1 -0
  74. package/dist/resources/prompts/runtime/write-todos-non-empty-initial-list.md +1 -0
  75. package/dist/resources/tools/_runtime_tool_helpers.mjs +152 -0
  76. package/dist/resources/tools/cancel_request.mjs +21 -0
  77. package/dist/resources/tools/fetch_url.mjs +23 -0
  78. package/dist/resources/tools/http_request.mjs +30 -0
  79. package/dist/resources/tools/inspect_approvals.mjs +27 -0
  80. package/dist/resources/tools/inspect_artifacts.mjs +21 -0
  81. package/dist/resources/tools/inspect_events.mjs +21 -0
  82. package/dist/resources/tools/inspect_requests.mjs +27 -0
  83. package/dist/resources/tools/inspect_sessions.mjs +21 -0
  84. package/dist/resources/tools/list_files.mjs +27 -0
  85. package/dist/resources/tools/read_artifact.mjs +22 -0
  86. package/dist/resources/tools/request_approval.mjs +27 -0
  87. package/dist/resources/tools/run_command.mjs +21 -0
  88. package/dist/resources/tools/schedule_task.mjs +76 -0
  89. package/dist/resources/tools/search_files.mjs +47 -0
  90. package/dist/resources/tools/send_message.mjs +23 -0
  91. package/dist/runtime/adapter/direct-builtin-utility.d.ts +1 -0
  92. package/dist/runtime/adapter/direct-builtin-utility.js +90 -0
  93. package/dist/runtime/adapter/flow/execution-context.d.ts +1 -1
  94. package/dist/runtime/adapter/flow/execution-context.js +1 -1
  95. package/dist/runtime/adapter/flow/invocation-flow.d.ts +1 -0
  96. package/dist/runtime/adapter/flow/invocation-flow.js +9 -1
  97. package/dist/runtime/adapter/flow/invoke-runtime.d.ts +1 -1
  98. package/dist/runtime/adapter/flow/stream-runtime.d.ts +5 -1
  99. package/dist/runtime/adapter/flow/stream-runtime.js +556 -35
  100. package/dist/runtime/adapter/invocation-result.js +3 -2
  101. package/dist/runtime/adapter/local-tool-invocation.d.ts +1 -1
  102. package/dist/runtime/adapter/local-tool-invocation.js +28 -4
  103. package/dist/runtime/adapter/middleware-assembly.js +3 -1
  104. package/dist/runtime/adapter/model/invocation-request.d.ts +4 -1
  105. package/dist/runtime/adapter/model/invocation-request.js +138 -16
  106. package/dist/runtime/adapter/model/message-assembly.js +2 -6
  107. package/dist/runtime/adapter/model/model-providers.js +103 -5
  108. package/dist/runtime/adapter/resilience.js +17 -2
  109. package/dist/runtime/adapter/runtime-adapter-support.d.ts +11 -7
  110. package/dist/runtime/adapter/runtime-adapter-support.js +39 -5
  111. package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +63 -1
  112. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +193 -21
  113. package/dist/runtime/adapter/tool/tool-arguments.d.ts +3 -1
  114. package/dist/runtime/adapter/tool/tool-arguments.js +52 -17
  115. package/dist/runtime/adapter/tool-resolution.d.ts +1 -0
  116. package/dist/runtime/adapter/tool-resolution.js +4 -2
  117. package/dist/runtime/agent-runtime-adapter.d.ts +27 -0
  118. package/dist/runtime/agent-runtime-adapter.js +163 -11
  119. package/dist/runtime/harness/events/event-bus.d.ts +1 -0
  120. package/dist/runtime/harness/events/event-bus.js +3 -0
  121. package/dist/runtime/harness/events/event-sink.d.ts +3 -0
  122. package/dist/runtime/harness/events/event-sink.js +16 -7
  123. package/dist/runtime/harness/events/streaming.d.ts +18 -1
  124. package/dist/runtime/harness/events/streaming.js +23 -10
  125. package/dist/runtime/harness/run/inspection.js +26 -5
  126. package/dist/runtime/harness/run/stream-run.d.ts +13 -4
  127. package/dist/runtime/harness/run/stream-run.js +448 -4
  128. package/dist/runtime/harness/run/surface-semantics.js +7 -34
  129. package/dist/runtime/harness/system/runtime-memory-manager.d.ts +3 -0
  130. package/dist/runtime/harness/system/runtime-memory-manager.js +384 -69
  131. package/dist/runtime/harness/system/runtime-memory-policy.d.ts +20 -1
  132. package/dist/runtime/harness/system/runtime-memory-policy.js +65 -17
  133. package/dist/runtime/harness/system/runtime-memory-records.js +100 -0
  134. package/dist/runtime/harness/system/runtime-memory-sync.js +2 -2
  135. package/dist/runtime/harness/system/store.d.ts +4 -0
  136. package/dist/runtime/harness/system/store.js +153 -0
  137. package/dist/runtime/harness.d.ts +9 -1
  138. package/dist/runtime/harness.js +141 -7
  139. package/dist/runtime/maintenance/sqlite-checkpoint-saver.d.ts +8 -3
  140. package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +152 -53
  141. package/dist/runtime/parsing/output-parsing.d.ts +10 -2
  142. package/dist/runtime/parsing/output-parsing.js +223 -16
  143. package/dist/runtime/parsing/stream-event-parsing.d.ts +7 -0
  144. package/dist/runtime/parsing/stream-event-parsing.js +51 -1
  145. package/dist/runtime/scheduling/system-schedule-manager.d.ts +41 -0
  146. package/dist/runtime/scheduling/system-schedule-manager.js +532 -0
  147. package/dist/runtime/support/embedding-models.d.ts +1 -1
  148. package/dist/runtime/support/embedding-models.js +5 -2
  149. package/dist/runtime/support/runtime-factories.js +1 -1
  150. package/dist/runtime/support/runtime-layout.d.ts +3 -0
  151. package/dist/runtime/support/runtime-layout.js +10 -1
  152. package/dist/runtime/support/runtime-prompts.d.ts +30 -0
  153. package/dist/runtime/support/runtime-prompts.js +55 -0
  154. package/dist/runtime/support/vector-stores.d.ts +1 -1
  155. package/dist/runtime/support/vector-stores.js +5 -2
  156. package/dist/upstream-events.js +8 -7
  157. package/dist/utils/bundled-text.d.ts +3 -0
  158. package/dist/utils/bundled-text.js +25 -0
  159. package/dist/utils/id.js +3 -2
  160. package/dist/workspace/agent-binding-compiler.js +53 -13
  161. package/dist/workspace/object-loader.js +64 -2
  162. package/dist/workspace/support/workspace-ref-utils.d.ts +2 -1
  163. package/dist/workspace/support/workspace-ref-utils.js +24 -5
  164. package/dist/workspace/yaml-object-reader.d.ts +1 -0
  165. package/dist/workspace/yaml-object-reader.js +95 -17
  166. package/package.json +11 -5
@@ -36,6 +36,7 @@ import { createRuntimeMemoryManager, RuntimeMemoryFormationSync, readRuntimeMemo
36
36
  import { readRuntimeMemoryMaintenanceConfig, readRuntimeMemoryPolicyConfig, resolveMemoryNamespace, } from "./harness/system/runtime-memory-policy.js";
37
37
  import { resolveRuntimeAdapterOptions } from "./support/runtime-adapter-options.js";
38
38
  import { resolveKnowledgeStorePath } from "./support/runtime-layout.js";
39
+ import { SystemScheduleManager } from "./scheduling/system-schedule-manager.js";
39
40
  import { initializeHarnessRuntime, reclaimExpiredClaimedRequests as reclaimHarnessExpiredClaimedRequests, recoverStartupRequests as recoverHarnessStartupRequests, isStaleRunningRequest as isHarnessStaleRunningRequest, } from "./harness/run/startup-runtime.js";
40
41
  import { traceStartupStage } from "./startup-tracing.js";
41
42
  import { normalizeProcessExecutablePath } from "./support/runtime-env.js";
@@ -72,6 +73,14 @@ function toPublicRequestResultShape(result) {
72
73
  }
73
74
  function toPublicHarnessStreamItem(item) {
74
75
  switch (item.type) {
76
+ case "commentary":
77
+ return {
78
+ type: "commentary",
79
+ sessionId: item.sessionId,
80
+ requestId: item.requestId,
81
+ agentId: item.agentId,
82
+ content: item.content,
83
+ };
75
84
  case "content":
76
85
  return {
77
86
  type: "content",
@@ -98,6 +107,14 @@ function toPublicHarnessStreamItem(item) {
98
107
  output: item.output,
99
108
  ...(item.isError !== undefined ? { isError: item.isError } : {}),
100
109
  };
110
+ case "plan-state":
111
+ return {
112
+ type: "plan-state",
113
+ sessionId: item.sessionId,
114
+ requestId: item.requestId,
115
+ agentId: item.agentId,
116
+ planState: item.planState,
117
+ };
101
118
  case "upstream-event":
102
119
  return {
103
120
  type: "upstream-event",
@@ -200,6 +217,7 @@ export class AgentHarnessRuntime {
200
217
  runtimeMemoryFormationSync;
201
218
  unregisterRuntimeMemoryFormationSync;
202
219
  resolvedRuntimeAdapterOptions;
220
+ scheduleManager;
203
221
  healthMonitor;
204
222
  recoveryConfig;
205
223
  concurrencyConfig;
@@ -252,6 +270,40 @@ export class AgentHarnessRuntime {
252
270
  acquireRequestSlot: (sessionId, requestId, activeState, priority) => this.acquireRequestSlot(sessionId, requestId, activeState, priority),
253
271
  };
254
272
  }
273
+ buildFunctionToolContext(input) {
274
+ return {
275
+ runtime: {
276
+ sessions: {
277
+ list: (filter) => this.listSessions(filter),
278
+ get: (sessionId) => this.getSession(sessionId),
279
+ },
280
+ requests: {
281
+ list: (filter) => this.listRequests(filter),
282
+ get: (requestId) => this.getRequest(requestId),
283
+ cancel: (options) => this.cancelRequest(options),
284
+ },
285
+ approvals: {
286
+ list: (filter) => this.listApprovals(filter),
287
+ get: (approvalId) => this.getApproval(approvalId),
288
+ },
289
+ events: {
290
+ list: (sessionId, requestId) => this.listRequestEvents(sessionId, requestId),
291
+ },
292
+ artifacts: {
293
+ list: (sessionId, requestId) => this.listRequestArtifacts(sessionId, requestId),
294
+ read: (sessionId, requestId, artifactPath) => this.readRequestArtifact(sessionId, requestId, artifactPath),
295
+ },
296
+ schedules: {
297
+ manage: (options) => this.manageSchedule(options),
298
+ },
299
+ current: {
300
+ ...(input.sessionId ? { sessionId: input.sessionId } : {}),
301
+ ...(input.requestId ? { requestId: input.requestId } : {}),
302
+ ...(input.binding ? { agentId: input.binding.agent.id } : {}),
303
+ },
304
+ },
305
+ };
306
+ }
255
307
  constructor(workspace, runtimeAdapterOptions = {}) {
256
308
  this.workspace = workspace;
257
309
  this.runtimeAdapterOptions = runtimeAdapterOptions;
@@ -260,6 +312,10 @@ export class AgentHarnessRuntime {
260
312
  this.defaultRuntimeEntryBinding = this.runtimeEntryBindings[0];
261
313
  this.defaultRuntimeRootValue = this.defaultRuntimeEntryBinding?.harnessRuntime.runtimeRoot ?? `${this.workspace.workspaceRoot}/.agent`;
262
314
  const runtimeRoot = this.defaultRuntimeRoot();
315
+ this.scheduleManager = new SystemScheduleManager({
316
+ workspaceRoot: this.workspace.workspaceRoot,
317
+ runtimeRoot,
318
+ });
263
319
  this.persistence = new SqlitePersistence(runtimeRoot);
264
320
  const defaultStoreConfig = this.defaultRuntimeEntryBinding?.harnessRuntime.store;
265
321
  this.defaultStore = resolveStoreFromConfig(this.stores, defaultStoreConfig, runtimeRoot) ?? new SqliteBackedStore(resolveKnowledgeStorePath(runtimeRoot));
@@ -273,7 +329,11 @@ export class AgentHarnessRuntime {
273
329
  readRuntimeMemoryMaintenanceConfig(this.defaultRuntimeEntryBinding?.harnessRuntime.runtimeMemory) ?? null;
274
330
  this.resolvedRuntimeAdapterOptions = resolveRuntimeAdapterOptions({
275
331
  workspace,
276
- runtimeAdapterOptions,
332
+ runtimeAdapterOptions: {
333
+ ...runtimeAdapterOptions,
334
+ scheduleManager: runtimeAdapterOptions.scheduleManager ?? this.scheduleManager,
335
+ functionToolContextResolver: runtimeAdapterOptions.functionToolContextResolver ?? ((input) => this.buildFunctionToolContext(input)),
336
+ },
277
337
  checkpointers: this.checkpointers,
278
338
  stores: this.stores,
279
339
  defaultStore: this.defaultStore,
@@ -406,6 +466,22 @@ export class AgentHarnessRuntime {
406
466
  const healthConfig = readHealthMonitorConfig(workspace);
407
467
  this.healthMonitor = healthConfig.enabled ? this.createHealthMonitor() : null;
408
468
  }
469
+ async manageSchedule(input) {
470
+ return this.scheduleManager.manageSchedule(input);
471
+ }
472
+ async getSchedule(scheduleId) {
473
+ return this.scheduleManager.getSchedule(scheduleId);
474
+ }
475
+ async runScheduledTask(scheduleId) {
476
+ const schedule = await this.scheduleManager.getSchedule(scheduleId);
477
+ if (!schedule) {
478
+ throw new Error(`Unknown schedule '${scheduleId}'.`);
479
+ }
480
+ return this.run({
481
+ ...(schedule.agentId ? { agentId: schedule.agentId } : {}),
482
+ input: schedule.instruction,
483
+ });
484
+ }
409
485
  createHealthMonitor() {
410
486
  return new HealthMonitor({
411
487
  workspace: this.workspace,
@@ -512,6 +588,7 @@ export class AgentHarnessRuntime {
512
588
  return this.knowledgeModule.memorize({
513
589
  records: input.records,
514
590
  storeCandidateLog: true,
591
+ forceStore: true,
515
592
  }, {
516
593
  sessionId: input.sessionId,
517
594
  requestId: input.requestId,
@@ -572,6 +649,9 @@ export class AgentHarnessRuntime {
572
649
  const request = await this.persistence.getRequest(requestId);
573
650
  return request ? buildRequestInspectionRecord(this.persistence, request) : null;
574
651
  }
652
+ async getRequestPlanState(sessionId, requestId) {
653
+ return this.persistence.getRequestPlanState(sessionId, requestId);
654
+ }
575
655
  async getSessionSummary(sessionId) {
576
656
  const session = await this.persistence.getSession(sessionId);
577
657
  return session
@@ -916,14 +996,15 @@ export class AgentHarnessRuntime {
916
996
  }
917
997
  async invokeWithHistory(binding, input, sessionId, requestId, resumePayload, priorHistory, options = {}) {
918
998
  const history = priorHistory ?? await this.loadPriorHistory(sessionId, requestId);
919
- const memoryContext = options.memoryContext ?? await this.buildRuntimeMemoryContext(binding, sessionId, input);
999
+ const memoryRecall = options.memoryRecall ?? await this.buildRuntimeMemoryContext(binding, sessionId, input);
920
1000
  const startedAt = Date.now();
921
1001
  try {
922
1002
  const result = await this.runtimeAdapter.invoke(binding, input, sessionId, requestId, resumePayload, history, {
923
1003
  ...options,
924
- ...(memoryContext ? { memoryContext } : {}),
1004
+ ...(memoryRecall?.prompt ? { memoryContext: memoryRecall.prompt } : {}),
925
1005
  });
926
1006
  await this.persistRuntimeMemoryCandidates(binding, sessionId, requestId, result.metadata?.memoryCandidates);
1007
+ await this.persistRequestPlanState(sessionId, requestId, result.metadata?.executedToolResults);
927
1008
  this.recordLlmSuccess(startedAt);
928
1009
  return result;
929
1010
  }
@@ -948,8 +1029,14 @@ export class AgentHarnessRuntime {
948
1029
  return path.basename(workspaceRoot) || "default";
949
1030
  }
950
1031
  async buildRuntimeMemoryContext(binding, sessionId, input) {
951
- const query = typeof input === "string" ? input : JSON.stringify(input ?? "");
952
- return this.knowledgeModule.buildPromptContext({
1032
+ if (!this.runtimeMemoryPolicy) {
1033
+ return undefined;
1034
+ }
1035
+ const query = extractMessageText(input ?? "").trim();
1036
+ if (!query) {
1037
+ return undefined;
1038
+ }
1039
+ const promptRecall = await this.knowledgeModule.buildPromptRecall({
953
1040
  query,
954
1041
  topK: this.runtimeMemoryPolicy?.retrieval.maxPromptMemories ?? 8,
955
1042
  }, {
@@ -957,6 +1044,13 @@ export class AgentHarnessRuntime {
957
1044
  agentId: binding.agent.id,
958
1045
  workspaceId: this.getWorkspaceId(binding),
959
1046
  });
1047
+ if (!promptRecall.context?.trim()) {
1048
+ return undefined;
1049
+ }
1050
+ return {
1051
+ prompt: promptRecall.context,
1052
+ items: promptRecall.items,
1053
+ };
960
1054
  }
961
1055
  async persistRuntimeMemoryCandidates(binding, sessionId, requestId, value) {
962
1056
  if (!Array.isArray(value) || value.length === 0) {
@@ -979,6 +1073,42 @@ export class AgentHarnessRuntime {
979
1073
  recordedAt: new Date().toISOString(),
980
1074
  }, { storeCandidateLog: true });
981
1075
  }
1076
+ async persistRequestPlanState(sessionId, requestId, value) {
1077
+ if (!Array.isArray(value) || value.length === 0) {
1078
+ return;
1079
+ }
1080
+ const executedToolResults = value
1081
+ .filter((item) => typeof item === "object" && item !== null);
1082
+ let typedSummary = null;
1083
+ for (const latest of [...executedToolResults].reverse()) {
1084
+ const summary = typeof latest.output === "object" && latest.output !== null
1085
+ ? latest.output.summary
1086
+ : undefined;
1087
+ if (!summary || typeof summary !== "object" || summary === null) {
1088
+ continue;
1089
+ }
1090
+ const candidate = summary;
1091
+ if (!Array.isArray(candidate.items) || !candidate.summary || typeof candidate.summary !== "object") {
1092
+ continue;
1093
+ }
1094
+ typedSummary = candidate;
1095
+ break;
1096
+ }
1097
+ if (!typedSummary) {
1098
+ return;
1099
+ }
1100
+ const items = typedSummary.items;
1101
+ const summary = typedSummary.summary;
1102
+ const current = await this.persistence.getRequestPlanState(sessionId, requestId);
1103
+ await this.persistence.saveRequestPlanState(sessionId, requestId, {
1104
+ sessionId,
1105
+ requestId,
1106
+ version: (current?.version ?? 0) + 1,
1107
+ updatedAt: new Date().toISOString(),
1108
+ items,
1109
+ summary,
1110
+ });
1111
+ }
982
1112
  async resolvePersistedRequestPriority(sessionId, requestId) {
983
1113
  const persisted = await this.persistence.getRequestInput(sessionId, requestId);
984
1114
  return normalizeRequestPriority(persisted?.priority);
@@ -1154,7 +1284,7 @@ export class AgentHarnessRuntime {
1154
1284
  input: options.input,
1155
1285
  invocation: {
1156
1286
  ...invocation,
1157
- memoryContext: await this.buildRuntimeMemoryContext(binding, sessionId, options.input),
1287
+ memoryRecall: await this.buildRuntimeMemoryContext(binding, sessionId, options.input),
1158
1288
  },
1159
1289
  sessionId,
1160
1290
  requestId,
@@ -1164,7 +1294,10 @@ export class AgentHarnessRuntime {
1164
1294
  releaseRequestSlotPromise,
1165
1295
  getBinding: (agentId) => getWorkspaceBinding(this.workspace, agentId),
1166
1296
  loadPriorHistory: (sessionId, requestId) => this.loadPriorHistory(sessionId, requestId),
1167
- stream: (binding, message, sessionId, priorHistory, streamOptions) => this.runtimeAdapter.stream(binding, message, sessionId, priorHistory, streamOptions),
1297
+ stream: (binding, message, sessionId, priorHistory, streamOptions) => this.runtimeAdapter.stream(binding, message, sessionId, priorHistory, {
1298
+ ...streamOptions,
1299
+ profiling: true,
1300
+ }),
1168
1301
  invokeWithHistory: (binding, input, sessionId, requestId) => this.invokeWithHistory(binding, input, sessionId, requestId),
1169
1302
  emit: (sessionId, requestId, sequence, eventType, payload) => this.emit(sessionId, requestId, sequence, eventType, payload),
1170
1303
  setRequestStateAndEmit: (sessionId, requestId, sequence, state, stateOptions) => this.setRequestStateAndEmit(sessionId, requestId, sequence, state, stateOptions),
@@ -1236,6 +1369,7 @@ export class AgentHarnessRuntime {
1236
1369
  }
1237
1370
  this.closed = true;
1238
1371
  await this.healthMonitor?.stop();
1372
+ await this.eventBus.drain();
1239
1373
  this.unregisterSessionMemorySync();
1240
1374
  this.unregisterRuntimeMemorySync();
1241
1375
  this.unregisterMem0IngestionSync();
@@ -8,17 +8,22 @@ type MemorySaverPutResult = ReturnType<MemorySaver["put"]>;
8
8
  export declare class SqliteCheckpointSaver extends MemorySaver {
9
9
  readonly filePath: string;
10
10
  private client;
11
- private loaded;
11
+ private readonly savers;
12
12
  private initialized;
13
13
  private initialization;
14
14
  private operationChain;
15
+ private legacyDefaultRow;
15
16
  constructor(filePath: string);
16
17
  private runSerialized;
17
18
  private getClient;
19
+ private executeWithBusyRetry;
18
20
  private ensureInitialized;
21
+ private getStateKey;
19
22
  private loadStateRow;
20
- private ensureLoaded;
21
- private persist;
23
+ private loadLegacyDefaultRow;
24
+ private loadSaver;
25
+ private ensureLoadedState;
26
+ private persistState;
22
27
  getTuple(config: MemorySaverConfig): Promise<import("@langchain/langgraph").CheckpointTuple | undefined>;
23
28
  list(config: MemorySaverConfig, options?: MemorySaverListOptions): AsyncGenerator<import("@langchain/langgraph").CheckpointTuple, void, unknown>;
24
29
  put(config: MemorySaverConfig, checkpoint: MemorySaverPutCheckpoint, metadata: MemorySaverPutMetadata): MemorySaverPutResult;
@@ -5,6 +5,8 @@ import { createClient } from "@libsql/client";
5
5
  import { UPSTREAM_SESSION_CONFIG_KEY } from "../adapter/upstream-configurable-keys.js";
6
6
  const CHECKPOINT_TABLE = "checkpoint_state";
7
7
  const DEFAULT_STATE_KEY = "default";
8
+ const SQLITE_BUSY_RETRY_ATTEMPTS = 30;
9
+ const SQLITE_BUSY_RETRY_DELAY_MS = 100;
8
10
  function normalizeCheckpointConfig(config) {
9
11
  if (!config?.configurable) {
10
12
  return config;
@@ -52,28 +54,70 @@ function decodeBinary(value) {
52
54
  }
53
55
  return value;
54
56
  }
55
- function pruneSessionEntries(record, sessionId) {
56
- for (const key of Object.keys(record)) {
57
- if (key.includes(sessionId)) {
58
- delete record[key];
59
- continue;
60
- }
61
- const value = record[key];
62
- if (typeof value === "object" && value && !Array.isArray(value)) {
63
- pruneSessionEntries(value, sessionId);
64
- if (Object.keys(value).length === 0) {
65
- delete record[key];
66
- }
67
- }
57
+ function parseWriteScopeKey(key) {
58
+ try {
59
+ const parsed = JSON.parse(key);
60
+ return Array.isArray(parsed) && typeof parsed[0] === "string" ? parsed[0] : undefined;
61
+ }
62
+ catch {
63
+ return undefined;
64
+ }
65
+ }
66
+ function extractScopedStorage(storage, stateKey) {
67
+ if (stateKey === DEFAULT_STATE_KEY) {
68
+ return structuredClone(storage);
69
+ }
70
+ const scoped = storage[stateKey];
71
+ return scoped === undefined ? {} : { [stateKey]: structuredClone(scoped) };
72
+ }
73
+ function extractScopedWrites(writes, stateKey) {
74
+ if (stateKey === DEFAULT_STATE_KEY) {
75
+ return structuredClone(writes);
68
76
  }
77
+ return Object.fromEntries(Object.entries(writes)
78
+ .filter(([key]) => parseWriteScopeKey(key) === stateKey)
79
+ .map(([key, value]) => [key, structuredClone(value)]));
80
+ }
81
+ function createIsolatedMemorySaver(storage, writes) {
82
+ const saver = new MemorySaver();
83
+ const typed = saver;
84
+ typed.storage = storage;
85
+ typed.writes = writes;
86
+ return saver;
87
+ }
88
+ function serializeSaverState(saver) {
89
+ const typed = saver;
90
+ return {
91
+ storage: structuredClone(typed.storage ?? {}),
92
+ writes: structuredClone(typed.writes ?? {}),
93
+ };
94
+ }
95
+ function collectErrorMessages(error) {
96
+ const messages = [];
97
+ let current = error;
98
+ while (current instanceof Error) {
99
+ messages.push(current.message);
100
+ current = current.cause;
101
+ }
102
+ if (typeof current === "string" && current.length > 0) {
103
+ messages.push(current);
104
+ }
105
+ return messages;
106
+ }
107
+ function isSqliteBusyError(error) {
108
+ return collectErrorMessages(error).some((message) => /SQLITE_BUSY|database is locked/i.test(message));
109
+ }
110
+ function sleep(ms) {
111
+ return new Promise((resolve) => setTimeout(resolve, ms));
69
112
  }
70
113
  export class SqliteCheckpointSaver extends MemorySaver {
71
114
  filePath;
72
115
  client = null;
73
- loaded = false;
116
+ savers = new Map();
74
117
  initialized = false;
75
118
  initialization = null;
76
119
  operationChain = Promise.resolve();
120
+ legacyDefaultRow;
77
121
  constructor(filePath) {
78
122
  super();
79
123
  this.filePath = filePath;
@@ -90,6 +134,19 @@ export class SqliteCheckpointSaver extends MemorySaver {
90
134
  }
91
135
  return this.client;
92
136
  }
137
+ async executeWithBusyRetry(operation) {
138
+ for (let attempt = 0;; attempt += 1) {
139
+ try {
140
+ return await operation();
141
+ }
142
+ catch (error) {
143
+ if (!isSqliteBusyError(error) || attempt >= SQLITE_BUSY_RETRY_ATTEMPTS) {
144
+ throw error;
145
+ }
146
+ await sleep(Math.min(SQLITE_BUSY_RETRY_DELAY_MS * (attempt + 1), 1_000));
147
+ }
148
+ }
149
+ }
93
150
  async ensureInitialized() {
94
151
  if (this.initialized) {
95
152
  return;
@@ -100,97 +157,139 @@ export class SqliteCheckpointSaver extends MemorySaver {
100
157
  }
101
158
  this.initialization = (async () => {
102
159
  const client = await this.getClient();
103
- await client.execute("PRAGMA journal_mode=WAL");
104
- await client.execute("PRAGMA foreign_keys=ON");
105
- await client.execute("PRAGMA busy_timeout=5000");
106
- await client.execute(`
160
+ await this.executeWithBusyRetry(() => client.execute("PRAGMA journal_mode=WAL"));
161
+ await this.executeWithBusyRetry(() => client.execute("PRAGMA foreign_keys=ON"));
162
+ await this.executeWithBusyRetry(() => client.execute("PRAGMA busy_timeout=5000"));
163
+ await this.executeWithBusyRetry(() => client.execute(`
107
164
  CREATE TABLE IF NOT EXISTS ${CHECKPOINT_TABLE} (
108
165
  state_key TEXT PRIMARY KEY,
109
166
  state_json TEXT NOT NULL,
110
167
  updated_at TEXT NOT NULL
111
168
  )
112
- `);
169
+ `));
113
170
  this.initialized = true;
114
171
  this.initialization = null;
115
172
  })();
116
173
  await this.initialization;
117
174
  }
118
- async loadStateRow() {
175
+ getStateKey(config) {
176
+ const normalized = normalizeCheckpointConfig(config);
177
+ const sessionId = normalized?.configurable?.[UPSTREAM_SESSION_CONFIG_KEY];
178
+ return typeof sessionId === "string" && sessionId.length > 0 ? sessionId : DEFAULT_STATE_KEY;
179
+ }
180
+ async loadStateRow(stateKey) {
119
181
  await this.ensureInitialized();
120
182
  const client = await this.getClient();
121
- const result = await client.execute({
183
+ const result = await this.executeWithBusyRetry(() => client.execute({
122
184
  sql: `SELECT state_json, updated_at FROM ${CHECKPOINT_TABLE} WHERE state_key = ?`,
123
- args: [DEFAULT_STATE_KEY],
124
- });
185
+ args: [stateKey],
186
+ }));
125
187
  return result.rows[0] ?? null;
126
188
  }
127
- async ensureLoaded() {
128
- if (this.loaded) {
129
- return;
189
+ async loadLegacyDefaultRow() {
190
+ if (this.legacyDefaultRow !== undefined) {
191
+ return this.legacyDefaultRow;
130
192
  }
131
- const row = await this.loadStateRow();
193
+ this.legacyDefaultRow = await this.loadStateRow(DEFAULT_STATE_KEY);
194
+ return this.legacyDefaultRow;
195
+ }
196
+ async loadSaver(stateKey) {
197
+ if (this.savers.has(stateKey)) {
198
+ return this.savers.get(stateKey);
199
+ }
200
+ let storage = {};
201
+ let writes = {};
202
+ const row = await this.loadStateRow(stateKey);
132
203
  if (row) {
133
204
  const parsed = JSON.parse(row.state_json);
134
- this.storage = decodeBinary(parsed.storage ?? {});
135
- this.writes = decodeBinary(parsed.writes ?? {});
205
+ storage = extractScopedStorage(decodeBinary(parsed.storage ?? {}), stateKey);
206
+ writes = extractScopedWrites(decodeBinary(parsed.writes ?? {}), stateKey);
136
207
  }
137
- else {
138
- this.storage = {};
139
- this.writes = {};
208
+ else if (stateKey !== DEFAULT_STATE_KEY) {
209
+ const legacyRow = await this.loadLegacyDefaultRow();
210
+ if (legacyRow) {
211
+ const parsed = JSON.parse(legacyRow.state_json);
212
+ storage = extractScopedStorage(decodeBinary(parsed.storage ?? {}), stateKey);
213
+ writes = extractScopedWrites(decodeBinary(parsed.writes ?? {}), stateKey);
214
+ }
140
215
  }
141
- this.loaded = true;
216
+ const saver = createIsolatedMemorySaver(storage, writes);
217
+ this.savers.set(stateKey, saver);
218
+ return saver;
219
+ }
220
+ async ensureLoadedState(config) {
221
+ const stateKey = this.getStateKey(config);
222
+ return { stateKey, saver: await this.loadSaver(stateKey) };
142
223
  }
143
- async persist() {
224
+ async persistState(stateKey, saver) {
144
225
  await this.ensureInitialized();
145
226
  const client = await this.getClient();
227
+ const snapshot = serializeSaverState(saver);
228
+ const scopedStorage = snapshot.storage;
229
+ const scopedWrites = snapshot.writes;
230
+ if (stateKey !== DEFAULT_STATE_KEY &&
231
+ Object.keys(scopedStorage).length === 0 &&
232
+ Object.keys(scopedWrites).length === 0) {
233
+ await this.executeWithBusyRetry(() => client.execute({
234
+ sql: `DELETE FROM ${CHECKPOINT_TABLE} WHERE state_key = ?`,
235
+ args: [stateKey],
236
+ }));
237
+ this.savers.delete(stateKey);
238
+ return;
239
+ }
146
240
  const now = new Date().toISOString();
147
241
  const payload = JSON.stringify({
148
- storage: this.storage,
149
- writes: this.writes,
242
+ storage: scopedStorage,
243
+ writes: scopedWrites,
150
244
  }, (_key, value) => encodeBinary(value));
151
- await client.execute({
245
+ await this.executeWithBusyRetry(() => client.execute({
152
246
  sql: `INSERT INTO ${CHECKPOINT_TABLE} (state_key, state_json, updated_at)
153
247
  VALUES (?, ?, ?)
154
248
  ON CONFLICT(state_key) DO UPDATE SET
155
249
  state_json = excluded.state_json,
156
250
  updated_at = excluded.updated_at`,
157
- args: [DEFAULT_STATE_KEY, payload, now],
158
- });
251
+ args: [stateKey, payload, now],
252
+ }));
159
253
  }
160
254
  async getTuple(config) {
161
255
  return this.runSerialized(async () => {
162
- await this.ensureLoaded();
163
- return super.getTuple(normalizeCheckpointConfig(config));
256
+ const { saver } = await this.ensureLoadedState(config);
257
+ return saver.getTuple(normalizeCheckpointConfig(config));
164
258
  });
165
259
  }
166
260
  async *list(config, options) {
167
- await this.ensureLoaded();
168
- for await (const item of super.list(normalizeCheckpointConfig(config), options)) {
261
+ const { saver } = await this.ensureLoadedState(config);
262
+ for await (const item of saver.list(normalizeCheckpointConfig(config), options)) {
169
263
  yield item;
170
264
  }
171
265
  }
172
266
  async put(config, checkpoint, metadata) {
173
267
  return this.runSerialized(async () => {
174
- await this.ensureLoaded();
175
- const result = await super.put(normalizeCheckpointConfig(config), checkpoint, metadata);
176
- await this.persist();
268
+ const { stateKey, saver } = await this.ensureLoadedState(config);
269
+ const result = await saver.put(normalizeCheckpointConfig(config), checkpoint, metadata);
270
+ await this.persistState(stateKey, saver);
177
271
  return result;
178
272
  });
179
273
  }
180
274
  async putWrites(config, writes, taskId) {
181
275
  return this.runSerialized(async () => {
182
- await this.ensureLoaded();
183
- const result = await super.putWrites(normalizeCheckpointConfig(config), writes, taskId);
184
- await this.persist();
276
+ const { stateKey, saver } = await this.ensureLoadedState(config);
277
+ const result = await saver.putWrites(normalizeCheckpointConfig(config), writes, taskId);
278
+ await this.persistState(stateKey, saver);
185
279
  return result;
186
280
  });
187
281
  }
188
282
  async deleteSession(sessionId) {
189
283
  return this.runSerialized(async () => {
190
- await this.ensureLoaded();
191
- pruneSessionEntries(this.storage, sessionId);
192
- pruneSessionEntries(this.writes, sessionId);
193
- await this.persist();
284
+ const { saver } = await this.ensureLoadedState({
285
+ configurable: {
286
+ [UPSTREAM_SESSION_CONFIG_KEY]: sessionId,
287
+ },
288
+ });
289
+ const typed = saver;
290
+ typed.storage = {};
291
+ typed.writes = {};
292
+ await this.persistState(sessionId, saver);
194
293
  });
195
294
  }
196
295
  }
@@ -1,9 +1,12 @@
1
+ import { BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION } from "../support/runtime-prompts.js";
2
+ export { BROWSER_CAPABILITY_DISCLAIMER_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, STRICT_TOOL_JSON_INSTRUCTION, WORKSPACE_RELATIVE_PATH_INSTRUCTION, WRITE_TODOS_DESCRIPTIVE_CONTENT_INSTRUCTION, WRITE_TODOS_FULL_ENTRY_INSTRUCTION, WRITE_TODOS_NON_EMPTY_INITIAL_LIST_INSTRUCTION, };
1
3
  export declare function sanitizeVisibleText(value: string): string;
2
4
  export declare function tryParseJson(value: string): unknown | null;
3
5
  export declare function salvageToolArgs(value: unknown): Record<string, unknown> | null;
4
6
  export declare function isLikelyToolArgsObject(value: unknown): boolean;
5
7
  export declare function readTextContent(value: unknown): string;
6
8
  export declare function hasToolCalls(value: unknown): boolean;
9
+ export declare function containsLikelySkillDocument(value: unknown): boolean;
7
10
  export declare function extractToolFallbackContext(value: unknown): string;
8
11
  export declare function extractVisibleOutput(value: unknown): string;
9
12
  export declare function extractOutputContent(value: unknown): unknown;
@@ -12,9 +15,14 @@ export declare function extractEmptyAssistantMessageFailure(value: unknown): str
12
15
  export declare function isToolCallParseFailure(error: unknown): boolean;
13
16
  export declare function isToolCallValidationFailure(error: unknown): boolean;
14
17
  export declare function isToolCallRecoveryFailure(error: unknown): boolean;
15
- export declare const STRICT_TOOL_JSON_INSTRUCTION = "When calling tools, return only the tool call itself. The arguments must be a pure JSON object with no explanatory text before or after it.";
16
- export declare const WRITE_TODOS_FULL_ENTRY_INSTRUCTION = "When calling write_todos, every todo item must include both content and status. Do not send status-only updates. Retry by resending the full todo entry with the original content preserved.";
18
+ export declare function isWorkspacePathScopeFailure(error: unknown): boolean;
19
+ export declare function isRepairableWriteTodosPlaceholderFailure(error: unknown): boolean;
20
+ export declare function isRetrySafeInvalidToolSelectionError(value: unknown): boolean;
21
+ export declare function shouldValidateExecutionWithoutToolEvidence(request: unknown): boolean;
22
+ export declare function resolveExecutionWithoutToolEvidenceInstruction(request: unknown, result: unknown): string | null;
23
+ export declare function resolveExecutionWithoutToolEvidenceTextInstruction(request: unknown, assistantText: string, toolCallEvidence?: boolean): string | null;
17
24
  export declare function isRepairableWriteTodosContentFailure(error: unknown): boolean;
25
+ export declare function isRepairableWriteTodosEmptyFailure(error: unknown): boolean;
18
26
  export declare function resolveToolCallRecoveryInstruction(error: unknown): string | null;
19
27
  export declare function appendToolRecoveryInstruction(input: unknown, instruction: string): unknown;
20
28
  export declare function wrapResolvedModel<T>(value: T): T;