@botbotgo/agent-harness 0.0.475 → 0.0.476

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 (227) hide show
  1. package/README.md +3 -1234
  2. package/README.zh.md +3 -1191
  3. package/dist/acp.js +1 -1
  4. package/dist/api.js +1 -404
  5. package/dist/benchmark/checkpoint-resume-cost-benchmark.js +1 -55
  6. package/dist/benchmark/deepagent-local-model-benchmark.js +2 -35
  7. package/dist/benchmark/upstream-runtime-ab-benchmark.js +1 -179
  8. package/dist/cli/chat-interactive.js +25 -244
  9. package/dist/cli/chat-rendering.js +6 -100
  10. package/dist/cli/chat-stream.js +23 -512
  11. package/dist/cli/chat-ui.js +21 -199
  12. package/dist/cli/chat-workspace.js +2 -210
  13. package/dist/cli/main.js +21 -428
  14. package/dist/cli/managed-service-commands.js +9 -63
  15. package/dist/cli/managed-service.js +2 -137
  16. package/dist/cli/options-init-chat.js +1 -108
  17. package/dist/cli/options-runtime.js +1 -158
  18. package/dist/cli/options-serve.js +1 -282
  19. package/dist/cli/options.js +2 -19
  20. package/dist/cli/process-guards.js +1 -139
  21. package/dist/cli/request-tree.js +7 -296
  22. package/dist/cli/runtime-commands.js +12 -258
  23. package/dist/cli/runtime-output.js +16 -155
  24. package/dist/cli/server-commands.js +16 -270
  25. package/dist/cli/workspace.js +1 -67
  26. package/dist/cli.js +1 -7
  27. package/dist/client/acp.js +1 -1
  28. package/dist/client/in-process.js +1 -67
  29. package/dist/client/index.js +1 -2
  30. package/dist/client/types.js +0 -1
  31. package/dist/client.js +1 -1
  32. package/dist/contracts/core.js +1 -1
  33. package/dist/contracts/runtime-evaluation.js +0 -1
  34. package/dist/contracts/runtime-memory.js +0 -1
  35. package/dist/contracts/runtime-observability.js +0 -1
  36. package/dist/contracts/runtime-requests.js +0 -1
  37. package/dist/contracts/runtime-scheduling.js +0 -1
  38. package/dist/contracts/runtime.js +1 -27
  39. package/dist/contracts/types.js +1 -3
  40. package/dist/contracts/workspace.js +0 -1
  41. package/dist/flow/build-flow-graph.js +1 -50
  42. package/dist/flow/export-mermaid.js +2 -464
  43. package/dist/flow/export-sequence-mermaid.js +2 -325
  44. package/dist/flow/flow-graph-normalization.js +1 -214
  45. package/dist/flow/flow-graph-runtime.js +1 -107
  46. package/dist/flow/flow-graph-upstream.js +1 -494
  47. package/dist/flow/index.js +1 -3
  48. package/dist/flow/types.js +0 -1
  49. package/dist/index.js +1 -5
  50. package/dist/init-project.js +1 -1
  51. package/dist/knowledge/config.js +1 -32
  52. package/dist/knowledge/contracts.js +0 -1
  53. package/dist/knowledge/index.js +1 -2
  54. package/dist/knowledge/module.js +12 -909
  55. package/dist/knowledge/procedural/config.js +1 -125
  56. package/dist/knowledge/procedural/index.js +1 -2
  57. package/dist/knowledge/procedural/manager.js +9 -345
  58. package/dist/mcp.js +1 -2
  59. package/dist/package-version.d.ts +1 -1
  60. package/dist/package-version.js +1 -2
  61. package/dist/persistence/file-store.js +3 -758
  62. package/dist/persistence/sqlite-request-context-store.js +5 -54
  63. package/dist/persistence/sqlite-request-queue-store.js +10 -108
  64. package/dist/persistence/sqlite-runtime.js +1 -86
  65. package/dist/persistence/sqlite-store.js +62 -810
  66. package/dist/persistence/types.js +0 -1
  67. package/dist/projections/presentation.js +37 -206
  68. package/dist/projections/request-events.js +2 -502
  69. package/dist/projections/upstream-events.js +1 -201
  70. package/dist/protocol/a2a/http-discovery.js +1 -178
  71. package/dist/protocol/a2a/http-rpc.js +6 -622
  72. package/dist/protocol/a2a/http.js +1 -138
  73. package/dist/protocol/a2a/task-state.js +3 -317
  74. package/dist/protocol/acp/client.js +8 -294
  75. package/dist/protocol/acp/harness-client.js +1 -218
  76. package/dist/protocol/acp/http.js +5 -130
  77. package/dist/protocol/acp/server.js +1 -310
  78. package/dist/protocol/acp/stdio.js +2 -69
  79. package/dist/protocol/ag-ui/http.js +3 -378
  80. package/dist/protocol/mcp/server.js +1 -428
  81. package/dist/resource/backend/workspace-scoped-backend.js +1 -319
  82. package/dist/resource/isolation.js +1 -237
  83. package/dist/resource/mcp/tool-support.js +3 -296
  84. package/dist/resource/mcp-tool-support.js +1 -2
  85. package/dist/resource/providers/resource-provider.js +1 -215
  86. package/dist/resource/resource-impl.js +1 -3
  87. package/dist/resource/resource-types.js +0 -1
  88. package/dist/resource/resource.js +1 -1
  89. package/dist/resource/sources.js +1 -247
  90. package/dist/resource/tools/function-tool-resolver.js +2 -272
  91. package/dist/runtime/adapter/compat/deepagent-compat.js +1 -29
  92. package/dist/runtime/adapter/compat/openai-compatible.js +1 -55
  93. package/dist/runtime/adapter/direct-builtin-utility.js +2 -90
  94. package/dist/runtime/adapter/flow/execution-context.js +1 -71
  95. package/dist/runtime/adapter/flow/invocation-flow.js +8 -425
  96. package/dist/runtime/adapter/flow/invoke-runtime.js +1 -20
  97. package/dist/runtime/adapter/flow/stream-runtime.js +11 -1395
  98. package/dist/runtime/adapter/invocation-result.js +2 -473
  99. package/dist/runtime/adapter/local-tool-invocation.js +6 -638
  100. package/dist/runtime/adapter/middleware/context-hygiene.js +1 -83
  101. package/dist/runtime/adapter/middleware-assembly.js +5 -477
  102. package/dist/runtime/adapter/model/invocation-request.js +3 -183
  103. package/dist/runtime/adapter/model/message-assembly.js +1 -28
  104. package/dist/runtime/adapter/model/model-providers.js +23 -1115
  105. package/dist/runtime/adapter/model/prompted-json-tool-call-capture.js +1 -40
  106. package/dist/runtime/adapter/model/prompted-json-tool-policy.js +1 -22
  107. package/dist/runtime/adapter/resilience.js +1 -104
  108. package/dist/runtime/adapter/runtime-adapter-support.js +3 -141
  109. package/dist/runtime/adapter/runtime-shell.js +5 -166
  110. package/dist/runtime/adapter/stream-event-projection.js +2 -622
  111. package/dist/runtime/adapter/stream-text-consumption.js +1 -18
  112. package/dist/runtime/adapter/terminal-status.js +2 -67
  113. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +6 -627
  114. package/dist/runtime/adapter/tool/declared-middleware.js +1 -154
  115. package/dist/runtime/adapter/tool/interrupt-policy.js +1 -34
  116. package/dist/runtime/adapter/tool/provider-tool.js +1 -25
  117. package/dist/runtime/adapter/tool/resolved-tool.js +1 -225
  118. package/dist/runtime/adapter/tool/tool-arguments.js +3 -486
  119. package/dist/runtime/adapter/tool/tool-hitl.js +1 -346
  120. package/dist/runtime/adapter/tool/tool-name-mapping.js +1 -128
  121. package/dist/runtime/adapter/tool/tool-output-artifacts.js +2 -88
  122. package/dist/runtime/adapter/tool/tool-replay.js +1 -37
  123. package/dist/runtime/adapter/tool-resolution.js +1 -86
  124. package/dist/runtime/adapter/upstream-configurable-keys.js +1 -2
  125. package/dist/runtime/agent-runtime-adapter.js +60 -2338
  126. package/dist/runtime/agent-runtime-assembly.js +7 -249
  127. package/dist/runtime/env/runtime-env.js +1 -62
  128. package/dist/runtime/harness/background-runtime.js +1 -8
  129. package/dist/runtime/harness/bindings.js +1 -58
  130. package/dist/runtime/harness/events/event-bus.js +1 -16
  131. package/dist/runtime/harness/events/event-sink.js +1 -61
  132. package/dist/runtime/harness/events/events.js +1 -80
  133. package/dist/runtime/harness/events/listener-runtime.js +1 -13
  134. package/dist/runtime/harness/events/runtime-event-operations.js +1 -9
  135. package/dist/runtime/harness/events/streaming.js +1 -100
  136. package/dist/runtime/harness/events/timeline.js +1 -52
  137. package/dist/runtime/harness/public-shapes.js +1 -186
  138. package/dist/runtime/harness/run/artifact-paths.js +1 -15
  139. package/dist/runtime/harness/run/governance.js +1 -295
  140. package/dist/runtime/harness/run/helpers.js +1 -71
  141. package/dist/runtime/harness/run/inspection.js +1 -409
  142. package/dist/runtime/harness/run/operator-overview.js +1 -80
  143. package/dist/runtime/harness/run/queue-diagnostics.js +1 -15
  144. package/dist/runtime/harness/run/recovery.js +1 -162
  145. package/dist/runtime/harness/run/resources.js +1 -60
  146. package/dist/runtime/harness/run/resume.js +1 -56
  147. package/dist/runtime/harness/run/routing.js +1 -48
  148. package/dist/runtime/harness/run/run-lifecycle.js +1 -66
  149. package/dist/runtime/harness/run/run-operations.js +1 -217
  150. package/dist/runtime/harness/run/run-queue.js +1 -43
  151. package/dist/runtime/harness/run/run-slot-acquisition.js +1 -157
  152. package/dist/runtime/harness/run/session-records.js +1 -97
  153. package/dist/runtime/harness/run/start-run.js +1 -120
  154. package/dist/runtime/harness/run/startup-runtime.js +1 -69
  155. package/dist/runtime/harness/run/stream-run.js +8 -1418
  156. package/dist/runtime/harness/run/surface-semantics.js +1 -79
  157. package/dist/runtime/harness/runtime-defaults.js +1 -39
  158. package/dist/runtime/harness/system/boundary-analysis.js +1 -234
  159. package/dist/runtime/harness/system/health-monitor.js +1 -258
  160. package/dist/runtime/harness/system/inventory.js +1 -129
  161. package/dist/runtime/harness/system/mem0-ingestion-sync.js +5 -345
  162. package/dist/runtime/harness/system/policy-engine.js +1 -175
  163. package/dist/runtime/harness/system/runtime-memory-candidates.js +4 -110
  164. package/dist/runtime/harness/system/runtime-memory-consolidation.js +1 -51
  165. package/dist/runtime/harness/system/runtime-memory-manager.js +10 -693
  166. package/dist/runtime/harness/system/runtime-memory-policy.js +1 -155
  167. package/dist/runtime/harness/system/runtime-memory-records.js +11 -577
  168. package/dist/runtime/harness/system/runtime-memory-sync.js +5 -206
  169. package/dist/runtime/harness/system/session-memory-sync.js +3 -113
  170. package/dist/runtime/harness/system/skill-requirements.js +1 -112
  171. package/dist/runtime/harness/system/store.js +9 -365
  172. package/dist/runtime/harness/tool-gateway/index.js +1 -2
  173. package/dist/runtime/harness/tool-gateway/policy.js +1 -45
  174. package/dist/runtime/harness/tool-gateway/validation.js +1 -176
  175. package/dist/runtime/harness/tool-schema.js +1 -3
  176. package/dist/runtime/harness.js +3 -1490
  177. package/dist/runtime/index.js +1 -3
  178. package/dist/runtime/layout/runtime-layout.js +1 -31
  179. package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -178
  180. package/dist/runtime/maintenance/file-checkpoint-saver.js +1 -106
  181. package/dist/runtime/maintenance/runtime-record-maintenance.js +2 -169
  182. package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +4 -289
  183. package/dist/runtime/parsing/output-content.js +10 -550
  184. package/dist/runtime/parsing/output-parsing.js +1 -4
  185. package/dist/runtime/parsing/output-recovery.js +3 -213
  186. package/dist/runtime/parsing/output-tool-args.js +7 -663
  187. package/dist/runtime/parsing/stream-event-parsing.js +3 -362
  188. package/dist/runtime/prompts/runtime-prompts.js +4 -73
  189. package/dist/runtime/scheduling/system-schedule-manager.js +11 -532
  190. package/dist/runtime/skills/skill-metadata.js +1 -197
  191. package/dist/runtime/startup-tracing.js +2 -37
  192. package/dist/runtime/support/compiled-binding.js +1 -290
  193. package/dist/runtime/support/embedding-models.js +1 -118
  194. package/dist/runtime/support/harness-support.js +5 -137
  195. package/dist/runtime/support/llamaindex.js +1 -108
  196. package/dist/runtime/support/runtime-adapter-options.js +1 -29
  197. package/dist/runtime/support/runtime-factories.js +1 -51
  198. package/dist/runtime/support/vector-stores.js +9 -270
  199. package/dist/scaffold/init-project.js +54 -233
  200. package/dist/tooling/extensions.js +1 -311
  201. package/dist/tooling/module-loader.js +1 -55
  202. package/dist/tools.js +1 -176
  203. package/dist/utils/agent-display.js +1 -18
  204. package/dist/utils/bundled-text.js +4 -39
  205. package/dist/utils/compiled-binding.js +1 -33
  206. package/dist/utils/fs.js +2 -45
  207. package/dist/utils/id.js +1 -9
  208. package/dist/utils/message-content.js +1 -30
  209. package/dist/utils/object.js +1 -6
  210. package/dist/workspace/agent-binding-compiler.js +3 -613
  211. package/dist/workspace/compile.js +1 -472
  212. package/dist/workspace/framework-contract-validation.js +2 -322
  213. package/dist/workspace/index.js +1 -1
  214. package/dist/workspace/object-loader-paths.js +1 -71
  215. package/dist/workspace/object-loader-readers.js +1 -187
  216. package/dist/workspace/object-loader.js +1 -754
  217. package/dist/workspace/resource-compilers.js +1 -374
  218. package/dist/workspace/support/agent-capabilities.js +1 -37
  219. package/dist/workspace/support/agent-execution-config.js +1 -44
  220. package/dist/workspace/support/discovery.js +1 -147
  221. package/dist/workspace/support/source-collectors.js +1 -30
  222. package/dist/workspace/support/source-protocols.js +2 -192
  223. package/dist/workspace/support/workspace-ref-utils.js +1 -362
  224. package/dist/workspace/tool-hydration.js +1 -280
  225. package/dist/workspace/validate.js +1 -99
  226. package/dist/workspace/yaml-object-reader.js +1 -285
  227. package/package.json +7 -3
@@ -1,3 +1 @@
1
- export { EventBus } from "./harness/events/event-bus.js";
2
- export { createRuntimeEventSink, RuntimeEventSinkImpl } from "./harness/events/event-sink.js";
3
- export { AgentHarnessRuntime } from "./harness.js";
1
+ import{EventBus as n}from"./harness/events/event-bus.js";import{createRuntimeEventSink as m,RuntimeEventSinkImpl as o}from"./harness/events/event-sink.js";import{AgentHarnessRuntime as p}from"./harness.js";export{p as AgentHarnessRuntime,n as EventBus,o as RuntimeEventSinkImpl,m as createRuntimeEventSink};
@@ -1,31 +1 @@
1
- import path from "node:path";
2
- export function resolveRuntimeRoot(dataRoot) {
3
- return path.join(dataRoot, "runtime");
4
- }
5
- export function resolveRuntimeArtifactsRoot(dataRoot) {
6
- return path.join(resolveRuntimeRoot(dataRoot), "artifacts");
7
- }
8
- export function resolveRuntimeSqlitePath(dataRoot) {
9
- return path.join(resolveRuntimeRoot(dataRoot), "runtime.sqlite");
10
- }
11
- export function resolveRuntimeCheckpointerPath(dataRoot, fileName = "checkpoints.json") {
12
- return path.join(resolveRuntimeRoot(dataRoot), fileName);
13
- }
14
- export function resolveKnowledgeRoot(dataRoot) {
15
- return path.join(dataRoot, "knowledge");
16
- }
17
- export function resolveKnowledgeStorePath(dataRoot, fileName = "knowledge.sqlite") {
18
- return path.join(resolveKnowledgeRoot(dataRoot), fileName);
19
- }
20
- export function resolveKnowledgeFileStorePath(dataRoot, fileName = "records.json") {
21
- return path.join(resolveKnowledgeRoot(dataRoot), fileName);
22
- }
23
- export function resolveProceduralMemoryStorePath(dataRoot, fileName = "procedural-memory.sqlite") {
24
- return path.join(resolveKnowledgeRoot(dataRoot), fileName);
25
- }
26
- export function resolveProceduralMemoryVectorStorePath(dataRoot, fileName = "procedural-vectors.sqlite") {
27
- return path.join(resolveKnowledgeRoot(dataRoot), fileName);
28
- }
29
- export function resolveProceduralMemoryStatePath(dataRoot, fileName = "procedural-memory-state.json") {
30
- return path.join(resolveKnowledgeRoot(dataRoot), fileName);
31
- }
1
+ import r from"node:path";function n(e){return r.join(e,"runtime")}function u(e){return r.join(n(e),"artifacts")}function l(e){return r.join(n(e),"runtime.sqlite")}function c(e,o="checkpoints.json"){return r.join(n(e),o)}function t(e){return r.join(e,"knowledge")}function s(e,o="knowledge.sqlite"){return r.join(t(e),o)}function a(e,o="records.json"){return r.join(t(e),o)}function p(e,o="procedural-memory.sqlite"){return r.join(t(e),o)}function m(e,o="procedural-vectors.sqlite"){return r.join(t(e),o)}function f(e,o="procedural-memory-state.json"){return r.join(t(e),o)}export{a as resolveKnowledgeFileStorePath,t as resolveKnowledgeRoot,s as resolveKnowledgeStorePath,f as resolveProceduralMemoryStatePath,p as resolveProceduralMemoryStorePath,m as resolveProceduralMemoryVectorStorePath,u as resolveRuntimeArtifactsRoot,c as resolveRuntimeCheckpointerPath,n as resolveRuntimeRoot,l as resolveRuntimeSqlitePath};
@@ -1,183 +1,7 @@
1
- import path from "node:path";
2
- import { stat } from "node:fs/promises";
3
- import { createClient } from "@libsql/client";
4
- import { fileExists } from "../../utils/fs.js";
5
- import { resolveRuntimeCheckpointerPath } from "../layout/runtime-layout.js";
6
- import { getRuntimeDefaults } from "../../workspace/support/workspace-ref-utils.js";
7
- function asObject(value) {
8
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
9
- }
10
- function readPositiveNumber(value, label, allowUndefined = true) {
11
- if (value === undefined && allowUndefined) {
12
- return undefined;
13
- }
14
- if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
15
- throw new Error(`${label} must be a positive number`);
16
- }
17
- return value;
18
- }
19
- export function readCheckpointMaintenanceConfig(workspace) {
20
- const runtimeDefaults = getRuntimeDefaults(workspace.refs);
21
- const maintenance = asObject(runtimeDefaults?.maintenance);
22
- const checkpoints = asObject(maintenance?.checkpoints);
23
- if (!checkpoints || checkpoints.enabled !== true) {
24
- return null;
25
- }
26
- const schedule = asObject(checkpoints.schedule);
27
- const policies = asObject(checkpoints.policies);
28
- const sqlite = asObject(checkpoints.sqlite);
29
- const config = {
30
- enabled: true,
31
- schedule: {
32
- intervalSeconds: readPositiveNumber(schedule?.intervalSeconds, "runtime.maintenance.checkpoints.schedule.intervalSeconds") ?? 3600,
33
- runOnStartup: schedule?.runOnStartup !== false,
34
- },
35
- policies: {
36
- maxAgeSeconds: readPositiveNumber(policies?.maxAgeSeconds, "runtime.maintenance.checkpoints.policies.maxAgeSeconds"),
37
- maxBytes: readPositiveNumber(policies?.maxBytes, "runtime.maintenance.checkpoints.policies.maxBytes"),
38
- },
39
- sqlite: {
40
- sweepBatchSize: readPositiveNumber(sqlite?.sweepBatchSize, "runtime.maintenance.checkpoints.sqlite.sweepBatchSize") ?? 200,
41
- vacuum: sqlite?.vacuum === true,
42
- },
43
- };
44
- if (config.policies.maxAgeSeconds === undefined && config.policies.maxBytes === undefined) {
45
- throw new Error("runtime.maintenance.checkpoints.enabled requires at least one cleanup policy");
46
- }
47
- return config;
48
- }
49
- function resolveSqliteCheckpointPath(binding) {
50
- const config = binding.harnessRuntime.checkpointer;
51
- if (!config || typeof config === "boolean") {
52
- return null;
53
- }
54
- const kind = typeof config.kind === "string" ? config.kind : "FileCheckpointer";
55
- if (kind !== "SqliteSaver") {
56
- return null;
57
- }
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
- }
61
- export function discoverCheckpointMaintenanceTargets(workspace) {
62
- const deduped = new Map();
63
- for (const binding of workspace.bindings.values()) {
64
- const dbPath = resolveSqliteCheckpointPath(binding);
65
- if (!dbPath) {
66
- continue;
67
- }
68
- deduped.set(dbPath, {
69
- agentId: binding.agent.id,
70
- dbPath,
71
- });
72
- }
73
- return Array.from(deduped.values());
74
- }
75
- export function maintainSqliteCheckpoints(dbPath, config, nowMs = Date.now()) {
76
- return maintainSqliteCheckpointsInternal(dbPath, config, nowMs);
77
- }
78
- async function maintainSqliteCheckpointsInternal(dbPath, config, nowMs) {
79
- if (!(await fileExists(dbPath))) {
80
- return { deletedCount: 0 };
81
- }
82
- const client = createClient({ url: `file:${dbPath}` });
83
- await client.execute("PRAGMA journal_mode=WAL");
84
- await client.execute("PRAGMA foreign_keys=ON");
85
- await client.execute("PRAGMA busy_timeout=5000");
86
- await client.execute(`
1
+ import d from"node:path";import{stat as y}from"node:fs/promises";import{createClient as k}from"@libsql/client";import{fileExists as x}from"../../utils/fs.js";import{resolveRuntimeCheckpointerPath as w}from"../layout/runtime-layout.js";import{getRuntimeDefaults as A}from"../../workspace/support/workspace-ref-utils.js";function c(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:void 0}function l(t,e,i=!0){if(!(t===void 0&&i)){if(typeof t!="number"||!Number.isFinite(t)||t<=0)throw new Error(`${e} must be a positive number`);return t}}function B(t){const e=A(t.refs),i=c(e?.maintenance),n=c(i?.checkpoints);if(!n||n.enabled!==!0)return null;const a=c(n.schedule),r=c(n.policies),o=c(n.sqlite),s={enabled:!0,schedule:{intervalSeconds:l(a?.intervalSeconds,"runtime.maintenance.checkpoints.schedule.intervalSeconds")??3600,runOnStartup:a?.runOnStartup!==!1},policies:{maxAgeSeconds:l(r?.maxAgeSeconds,"runtime.maintenance.checkpoints.policies.maxAgeSeconds"),maxBytes:l(r?.maxBytes,"runtime.maintenance.checkpoints.policies.maxBytes")},sqlite:{sweepBatchSize:l(o?.sweepBatchSize,"runtime.maintenance.checkpoints.sqlite.sweepBatchSize")??200,vacuum:o?.vacuum===!0}};if(s.policies.maxAgeSeconds===void 0&&s.policies.maxBytes===void 0)throw new Error("runtime.maintenance.checkpoints.enabled requires at least one cleanup policy");return s}function E(t){const e=t.harnessRuntime.checkpointer;if(!e||typeof e=="boolean"||(typeof e.kind=="string"?e.kind:"FileCheckpointer")!=="SqliteSaver")return null;const n=typeof e.path=="string"?String(e.path):w(t.harnessRuntime.runtimeRoot,"checkpoints.sqlite");return d.isAbsolute(n)?n:d.join(t.harnessRuntime.runtimeRoot,n)}function F(t){const e=new Map;for(const i of t.bindings.values()){const n=E(i);n&&e.set(n,{agentId:i.agent.id,dbPath:n})}return Array.from(e.values())}function C(t,e,i=Date.now()){return v(t,e,i)}async function v(t,e,i){if(!await x(t))return{deletedCount:0};const n=k({url:`file:${t}`});await n.execute("PRAGMA journal_mode=WAL"),await n.execute("PRAGMA foreign_keys=ON"),await n.execute("PRAGMA busy_timeout=5000"),await n.execute(`
87
2
  CREATE TABLE IF NOT EXISTS checkpoint_state (
88
3
  state_key TEXT PRIMARY KEY,
89
4
  state_json TEXT NOT NULL,
90
5
  updated_at TEXT NOT NULL
91
6
  )
92
- `);
93
- const result = await client.execute("SELECT state_key, updated_at FROM checkpoint_state");
94
- if (result.rows.length === 0) {
95
- return { deletedCount: 0 };
96
- }
97
- const stats = await stat(dbPath).catch(() => null);
98
- const maxAgeMs = config.policies.maxAgeSeconds ? config.policies.maxAgeSeconds * 1000 : null;
99
- const maxBytes = config.policies.maxBytes ?? null;
100
- const sweepBatchSize = Math.max(1, config.sqlite.sweepBatchSize);
101
- let deletedCount = 0;
102
- for (const row of result.rows.slice(0, sweepBatchSize)) {
103
- const stateKey = typeof row.state_key === "string" ? row.state_key : "";
104
- const updatedAtMs = typeof row.updated_at === "string" ? Date.parse(row.updated_at) : NaN;
105
- const exceededAge = maxAgeMs !== null && Number.isFinite(updatedAtMs) && nowMs - updatedAtMs > maxAgeMs;
106
- const exceededBytes = maxBytes !== null && stats !== null && stats.size > maxBytes;
107
- if (!exceededAge && !exceededBytes) {
108
- continue;
109
- }
110
- await client.execute({
111
- sql: "DELETE FROM checkpoint_state WHERE state_key = ?",
112
- args: [stateKey],
113
- });
114
- deletedCount += 1;
115
- }
116
- if (deletedCount > 0 && config.sqlite.vacuum) {
117
- await client.execute("VACUUM");
118
- }
119
- void path.dirname(dbPath);
120
- return { deletedCount };
121
- }
122
- export class CheckpointMaintenanceLoop {
123
- targets;
124
- config;
125
- timer = null;
126
- running = false;
127
- status = {
128
- consecutiveFailures: 0,
129
- };
130
- constructor(targets, config) {
131
- this.targets = targets;
132
- this.config = config;
133
- }
134
- async runOnce(nowMs = Date.now()) {
135
- this.status = {
136
- ...this.status,
137
- lastStartedAt: new Date(nowMs).toISOString(),
138
- };
139
- try {
140
- for (const target of this.targets) {
141
- await maintainSqliteCheckpoints(target.dbPath, this.config, nowMs);
142
- }
143
- this.status = {
144
- ...this.status,
145
- lastCompletedAt: new Date(nowMs).toISOString(),
146
- consecutiveFailures: 0,
147
- lastError: undefined,
148
- };
149
- }
150
- catch (error) {
151
- this.status = {
152
- ...this.status,
153
- lastFailedAt: new Date(nowMs).toISOString(),
154
- consecutiveFailures: this.status.consecutiveFailures + 1,
155
- lastError: error instanceof Error ? error.message : String(error),
156
- };
157
- throw error;
158
- }
159
- }
160
- getStatus() {
161
- return { ...this.status };
162
- }
163
- async start() {
164
- if (this.running) {
165
- return;
166
- }
167
- this.running = true;
168
- if (this.config.schedule.runOnStartup) {
169
- await this.runOnce();
170
- }
171
- this.timer = setInterval(() => {
172
- void this.runOnce();
173
- }, this.config.schedule.intervalSeconds * 1000);
174
- this.timer.unref?.();
175
- }
176
- async stop() {
177
- if (this.timer) {
178
- clearInterval(this.timer);
179
- this.timer = null;
180
- }
181
- this.running = false;
182
- }
183
- }
7
+ `);const a=await n.execute("SELECT state_key, updated_at FROM checkpoint_state");if(a.rows.length===0)return{deletedCount:0};const r=await y(t).catch(()=>null),o=e.policies.maxAgeSeconds?e.policies.maxAgeSeconds*1e3:null,s=e.policies.maxBytes??null,m=Math.max(1,e.sqlite.sweepBatchSize);let p=0;for(const u of a.rows.slice(0,m)){const f=typeof u.state_key=="string"?u.state_key:"",h=typeof u.updated_at=="string"?Date.parse(u.updated_at):NaN,g=o!==null&&Number.isFinite(h)&&i-h>o,S=s!==null&&r!==null&&r.size>s;!g&&!S||(await n.execute({sql:"DELETE FROM checkpoint_state WHERE state_key = ?",args:[f]}),p+=1)}return p>0&&e.sqlite.vacuum&&await n.execute("VACUUM"),d.dirname(t),{deletedCount:p}}class M{targets;config;timer=null;running=!1;status={consecutiveFailures:0};constructor(e,i){this.targets=e,this.config=i}async runOnce(e=Date.now()){this.status={...this.status,lastStartedAt:new Date(e).toISOString()};try{for(const i of this.targets)await C(i.dbPath,this.config,e);this.status={...this.status,lastCompletedAt:new Date(e).toISOString(),consecutiveFailures:0,lastError:void 0}}catch(i){throw this.status={...this.status,lastFailedAt:new Date(e).toISOString(),consecutiveFailures:this.status.consecutiveFailures+1,lastError:i instanceof Error?i.message:String(i)},i}}getStatus(){return{...this.status}}async start(){this.running||(this.running=!0,this.config.schedule.runOnStartup&&await this.runOnce(),this.timer=setInterval(()=>{this.runOnce()},this.config.schedule.intervalSeconds*1e3),this.timer.unref?.())}async stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.running=!1}}export{M as CheckpointMaintenanceLoop,F as discoverCheckpointMaintenanceTargets,C as maintainSqliteCheckpoints,B as readCheckpointMaintenanceConfig};
@@ -1,106 +1 @@
1
- import { mkdir, readFile, writeFile } from "node:fs/promises";
2
- import path from "node:path";
3
- import { MemorySaver } from "@langchain/langgraph";
4
- function encodeBinary(value) {
5
- if (value instanceof Uint8Array) {
6
- return {
7
- __type: "Uint8Array",
8
- data: Array.from(value),
9
- };
10
- }
11
- if (Array.isArray(value)) {
12
- return value.map((item) => encodeBinary(item));
13
- }
14
- if (typeof value === "object" && value) {
15
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, encodeBinary(entry)]));
16
- }
17
- return value;
18
- }
19
- function decodeBinary(value) {
20
- if (Array.isArray(value)) {
21
- return value.map((item) => decodeBinary(item));
22
- }
23
- if (typeof value === "object" && value) {
24
- const typed = value;
25
- if (typed.__type === "Uint8Array" && Array.isArray(typed.data)) {
26
- return new Uint8Array(typed.data.map((item) => Number(item)));
27
- }
28
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, decodeBinary(entry)]));
29
- }
30
- return value;
31
- }
32
- function pruneSessionEntries(record, sessionId) {
33
- for (const key of Object.keys(record)) {
34
- if (key.includes(sessionId)) {
35
- delete record[key];
36
- continue;
37
- }
38
- const value = record[key];
39
- if (typeof value === "object" && value && !Array.isArray(value)) {
40
- pruneSessionEntries(value, sessionId);
41
- if (Object.keys(value).length === 0) {
42
- delete record[key];
43
- }
44
- }
45
- }
46
- }
47
- export class FileCheckpointSaver extends MemorySaver {
48
- filePath;
49
- loaded = false;
50
- constructor(filePath) {
51
- super();
52
- this.filePath = filePath;
53
- }
54
- async ensureLoaded() {
55
- if (this.loaded) {
56
- return;
57
- }
58
- try {
59
- const raw = await readFile(this.filePath, "utf8");
60
- const parsed = JSON.parse(raw);
61
- this.storage = decodeBinary(parsed.storage ?? {});
62
- this.writes = decodeBinary(parsed.writes ?? {});
63
- }
64
- catch {
65
- this.storage = {};
66
- this.writes = {};
67
- }
68
- this.loaded = true;
69
- }
70
- async persist() {
71
- await mkdir(path.dirname(this.filePath), { recursive: true });
72
- await writeFile(this.filePath, JSON.stringify({
73
- storage: this.storage,
74
- writes: this.writes,
75
- }, (_, value) => encodeBinary(value), 2), "utf8");
76
- }
77
- async getTuple(config) {
78
- await this.ensureLoaded();
79
- return super.getTuple(config);
80
- }
81
- async *list(config, options) {
82
- await this.ensureLoaded();
83
- for await (const item of super.list(config, options)) {
84
- yield item;
85
- }
86
- }
87
- async put(config, checkpoint, metadata) {
88
- await this.ensureLoaded();
89
- const result = await super.put(config, checkpoint, metadata);
90
- await this.persist();
91
- return result;
92
- }
93
- async putWrites(config, writes, taskId) {
94
- await this.ensureLoaded();
95
- const result = await super.putWrites(config, writes, taskId);
96
- await this.persist();
97
- return result;
98
- }
99
- async deleteSession(sessionId) {
100
- await this.ensureLoaded();
101
- pruneSessionEntries(this.storage, sessionId);
102
- pruneSessionEntries(this.writes, sessionId);
103
- await this.persist();
104
- }
105
- }
106
- export { FileCheckpointSaver as FileCheckpointer };
1
+ import{mkdir as c,readFile as p,writeFile as f}from"node:fs/promises";import y from"node:path";import{MemorySaver as h}from"@langchain/langgraph";function n(e){return e instanceof Uint8Array?{__type:"Uint8Array",data:Array.from(e)}:Array.isArray(e)?e.map(t=>n(t)):typeof e=="object"&&e?Object.fromEntries(Object.entries(e).map(([t,r])=>[t,n(r)])):e}function s(e){if(Array.isArray(e))return e.map(t=>s(t));if(typeof e=="object"&&e){const t=e;return t.__type==="Uint8Array"&&Array.isArray(t.data)?new Uint8Array(t.data.map(r=>Number(r))):Object.fromEntries(Object.entries(e).map(([r,i])=>[r,s(i)]))}return e}function o(e,t){for(const r of Object.keys(e)){if(r.includes(t)){delete e[r];continue}const i=e[r];typeof i=="object"&&i&&!Array.isArray(i)&&(o(i,t),Object.keys(i).length===0&&delete e[r])}}class u extends h{filePath;loaded=!1;constructor(t){super(),this.filePath=t}async ensureLoaded(){if(!this.loaded){try{const t=await p(this.filePath,"utf8"),r=JSON.parse(t);this.storage=s(r.storage??{}),this.writes=s(r.writes??{})}catch{this.storage={},this.writes={}}this.loaded=!0}}async persist(){await c(y.dirname(this.filePath),{recursive:!0}),await f(this.filePath,JSON.stringify({storage:this.storage,writes:this.writes},(t,r)=>n(r),2),"utf8")}async getTuple(t){return await this.ensureLoaded(),super.getTuple(t)}async*list(t,r){await this.ensureLoaded();for await(const i of super.list(t,r))yield i}async put(t,r,i){await this.ensureLoaded();const a=await super.put(t,r,i);return await this.persist(),a}async putWrites(t,r,i){await this.ensureLoaded();const a=await super.putWrites(t,r,i);return await this.persist(),a}async deleteSession(t){await this.ensureLoaded(),o(this.storage,t),o(this.writes,t),await this.persist()}}export{u as FileCheckpointSaver,u as FileCheckpointer};
@@ -1,173 +1,6 @@
1
- import path from "node:path";
2
- import { rm } from "node:fs/promises";
3
- import { createClient } from "@libsql/client";
4
- import { fileExists } from "../../utils/fs.js";
5
- import { resolveRuntimeSqlitePath } from "../layout/runtime-layout.js";
6
- import { getRuntimeDefaults } from "../../workspace/support/workspace-ref-utils.js";
7
- function asObject(value) {
8
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
9
- }
10
- function readPositiveNumber(value, label, allowUndefined = true) {
11
- if (value === undefined && allowUndefined) {
12
- return undefined;
13
- }
14
- if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
15
- throw new Error(`${label} must be a positive number`);
16
- }
17
- return value;
18
- }
19
- export function readRuntimeRecordMaintenanceConfig(workspace) {
20
- const runtimeDefaults = getRuntimeDefaults(workspace.refs);
21
- const maintenance = asObject(runtimeDefaults?.maintenance);
22
- const records = asObject(maintenance?.records);
23
- if (!records || records.enabled !== true) {
24
- return null;
25
- }
26
- const schedule = asObject(records.schedule);
27
- const policies = asObject(records.policies);
28
- const sqlite = asObject(records.sqlite);
29
- const config = {
30
- enabled: true,
31
- schedule: {
32
- intervalSeconds: readPositiveNumber(schedule?.intervalSeconds, "runtime.maintenance.records.schedule.intervalSeconds") ?? 3600,
33
- runOnStartup: schedule?.runOnStartup !== false,
34
- },
35
- policies: {
36
- maxAgeSeconds: readPositiveNumber(policies?.maxAgeSeconds, "runtime.maintenance.records.policies.maxAgeSeconds"),
37
- },
38
- sqlite: {
39
- sweepBatchSize: readPositiveNumber(sqlite?.sweepBatchSize, "runtime.maintenance.records.sqlite.sweepBatchSize") ?? 100,
40
- vacuum: sqlite?.vacuum === true,
41
- },
42
- };
43
- if (config.policies.maxAgeSeconds === undefined) {
44
- throw new Error("runtime.maintenance.records.enabled requires at least one cleanup policy");
45
- }
46
- return config;
47
- }
48
- export function discoverRuntimeRecordMaintenanceTargets(workspace) {
49
- const runtimeRoots = new Set();
50
- for (const binding of workspace.bindings.values()) {
51
- runtimeRoots.add(binding.harnessRuntime.runtimeRoot);
52
- }
53
- return Array.from(runtimeRoots.values()).map((runtimeRoot) => ({
54
- dbPath: resolveRuntimeSqlitePath(runtimeRoot),
55
- }));
56
- }
57
- export async function maintainSqliteRuntimeRecords(dbPath, config, nowMs = Date.now()) {
58
- if (!(await fileExists(dbPath))) {
59
- return { deletedSessionCount: 0 };
60
- }
61
- const client = createClient({ url: `file:${dbPath}` });
62
- const cutoffIso = new Date(nowMs - (config.policies.maxAgeSeconds ?? 0) * 1000).toISOString();
63
- const runtimeRoot = path.dirname(dbPath);
64
- const result = await client.execute({
65
- sql: `SELECT session_id
1
+ import f from"node:path";import{rm as R}from"node:fs/promises";import{createClient as g}from"@libsql/client";import{fileExists as w}from"../../utils/fs.js";import{resolveRuntimeSqlitePath as _}from"../layout/runtime-layout.js";import{getRuntimeDefaults as O}from"../../workspace/support/workspace-ref-utils.js";function r(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0}function m(e,s,t=!0){if(!(e===void 0&&t)){if(typeof e!="number"||!Number.isFinite(e)||e<=0)throw new Error(`${s} must be a positive number`);return e}}function A(e){const s=O(e.refs),t=r(s?.maintenance),i=r(t?.records);if(!i||i.enabled!==!0)return null;const o=r(i.schedule),a=r(i.policies),d=r(i.sqlite),n={enabled:!0,schedule:{intervalSeconds:m(o?.intervalSeconds,"runtime.maintenance.records.schedule.intervalSeconds")??3600,runOnStartup:o?.runOnStartup!==!1},policies:{maxAgeSeconds:m(a?.maxAgeSeconds,"runtime.maintenance.records.policies.maxAgeSeconds")},sqlite:{sweepBatchSize:m(d?.sweepBatchSize,"runtime.maintenance.records.sqlite.sweepBatchSize")??100,vacuum:d?.vacuum===!0}};if(n.policies.maxAgeSeconds===void 0)throw new Error("runtime.maintenance.records.enabled requires at least one cleanup policy");return n}function H(e){const s=new Set;for(const t of e.bindings.values())s.add(t.harnessRuntime.runtimeRoot);return Array.from(s.values()).map(t=>({dbPath:_(t)}))}async function q(e,s,t=Date.now()){if(!await w(e))return{deletedSessionCount:0};const i=g({url:`file:${e}`}),o=new Date(t-(s.policies.maxAgeSeconds??0)*1e3).toISOString(),a=f.dirname(e),n=(await i.execute({sql:`SELECT session_id
66
2
  FROM sessions
67
3
  WHERE status IN ('completed', 'failed')
68
4
  AND updated_at <= ?
69
5
  ORDER BY updated_at ASC, session_id ASC
70
- LIMIT ?`,
71
- args: [cutoffIso, config.sqlite.sweepBatchSize],
72
- });
73
- const rows = result.rows.map((row) => row);
74
- if (rows.length === 0) {
75
- return { deletedSessionCount: 0 };
76
- }
77
- let deletedSessionCount = 0;
78
- for (const row of rows) {
79
- const sessionId = row.session_id;
80
- const artifacts = await client.execute({
81
- sql: `SELECT request_id, path FROM artifacts WHERE session_id = ?`,
82
- args: [sessionId],
83
- });
84
- for (const artifact of artifacts.rows) {
85
- const requestId = String(artifact.request_id ?? "");
86
- const artifactPath = String(artifact.path ?? "");
87
- if (requestId && artifactPath) {
88
- await rm(path.join(runtimeRoot, "sessions", sessionId, "requests", requestId, artifactPath), { force: true });
89
- }
90
- }
91
- await client.batch([
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
- }
107
- if (deletedSessionCount > 0 && config.sqlite.vacuum) {
108
- await client.execute("VACUUM");
109
- }
110
- return { deletedSessionCount };
111
- }
112
- export class RuntimeRecordMaintenanceLoop {
113
- targets;
114
- config;
115
- timer = null;
116
- running = false;
117
- status = {
118
- consecutiveFailures: 0,
119
- };
120
- constructor(targets, config) {
121
- this.targets = targets;
122
- this.config = config;
123
- }
124
- async runOnce(nowMs = Date.now()) {
125
- this.status = {
126
- ...this.status,
127
- lastStartedAt: new Date(nowMs).toISOString(),
128
- };
129
- try {
130
- for (const target of this.targets) {
131
- await maintainSqliteRuntimeRecords(target.dbPath, this.config, nowMs);
132
- }
133
- this.status = {
134
- ...this.status,
135
- lastCompletedAt: new Date(nowMs).toISOString(),
136
- consecutiveFailures: 0,
137
- lastError: undefined,
138
- };
139
- }
140
- catch (error) {
141
- this.status = {
142
- ...this.status,
143
- lastFailedAt: new Date(nowMs).toISOString(),
144
- consecutiveFailures: this.status.consecutiveFailures + 1,
145
- lastError: error instanceof Error ? error.message : String(error),
146
- };
147
- throw error;
148
- }
149
- }
150
- getStatus() {
151
- return { ...this.status };
152
- }
153
- async start() {
154
- if (this.running) {
155
- return;
156
- }
157
- this.running = true;
158
- if (this.config.schedule.runOnStartup) {
159
- await this.runOnce();
160
- }
161
- this.timer = setInterval(() => {
162
- void this.runOnce();
163
- }, this.config.schedule.intervalSeconds * 1000);
164
- this.timer.unref?.();
165
- }
166
- async stop() {
167
- if (this.timer) {
168
- clearInterval(this.timer);
169
- this.timer = null;
170
- }
171
- this.running = false;
172
- }
173
- }
6
+ LIMIT ?`,args:[o,s.sqlite.sweepBatchSize]})).rows.map(l=>l);if(n.length===0)return{deletedSessionCount:0};let E=0;for(const l of n){const u=l.session_id,S=await i.execute({sql:"SELECT request_id, path FROM artifacts WHERE session_id = ?",args:[u]});for(const c of S.rows){const h=String(c.request_id??""),p=String(c.path??"");h&&p&&await R(f.join(a,"sessions",u,"requests",h,p),{force:!0})}await i.batch(["DELETE FROM artifacts WHERE session_id = ?","DELETE FROM approvals WHERE session_id = ?","DELETE FROM events WHERE session_id = ?","DELETE FROM request_inspection WHERE session_id = ?","DELETE FROM request_queue WHERE session_id = ?","DELETE FROM request_inputs WHERE session_id = ?","DELETE FROM recovery_intents WHERE session_id = ?","DELETE FROM session_messages WHERE session_id = ?","DELETE FROM request_control WHERE request_id IN (SELECT request_id FROM requests WHERE session_id = ?)","DELETE FROM requests WHERE session_id = ?","DELETE FROM sessions WHERE session_id = ?"].map(c=>({sql:c,args:[u]})),"write"),await R(f.join(a,"sessions",u),{recursive:!0,force:!0}),E+=1}return E>0&&s.sqlite.vacuum&&await i.execute("VACUUM"),{deletedSessionCount:E}}class W{targets;config;timer=null;running=!1;status={consecutiveFailures:0};constructor(s,t){this.targets=s,this.config=t}async runOnce(s=Date.now()){this.status={...this.status,lastStartedAt:new Date(s).toISOString()};try{for(const t of this.targets)await q(t.dbPath,this.config,s);this.status={...this.status,lastCompletedAt:new Date(s).toISOString(),consecutiveFailures:0,lastError:void 0}}catch(t){throw this.status={...this.status,lastFailedAt:new Date(s).toISOString(),consecutiveFailures:this.status.consecutiveFailures+1,lastError:t instanceof Error?t.message:String(t)},t}}getStatus(){return{...this.status}}async start(){this.running||(this.running=!0,this.config.schedule.runOnStartup&&await this.runOnce(),this.timer=setInterval(()=>{this.runOnce()},this.config.schedule.intervalSeconds*1e3),this.timer.unref?.())}async stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.running=!1}}export{W as RuntimeRecordMaintenanceLoop,H as discoverRuntimeRecordMaintenanceTargets,q as maintainSqliteRuntimeRecords,A as readRuntimeRecordMaintenanceConfig};