@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.
- package/README.md +3 -1234
- package/README.zh.md +3 -1191
- package/dist/acp.js +1 -1
- package/dist/api.js +1 -404
- package/dist/benchmark/checkpoint-resume-cost-benchmark.js +1 -55
- package/dist/benchmark/deepagent-local-model-benchmark.js +2 -35
- package/dist/benchmark/upstream-runtime-ab-benchmark.js +1 -179
- package/dist/cli/chat-interactive.js +25 -244
- package/dist/cli/chat-rendering.js +6 -100
- package/dist/cli/chat-stream.js +23 -512
- package/dist/cli/chat-ui.js +21 -199
- package/dist/cli/chat-workspace.js +2 -210
- package/dist/cli/main.js +21 -428
- package/dist/cli/managed-service-commands.js +9 -63
- package/dist/cli/managed-service.js +2 -137
- package/dist/cli/options-init-chat.js +1 -108
- package/dist/cli/options-runtime.js +1 -158
- package/dist/cli/options-serve.js +1 -282
- package/dist/cli/options.js +2 -19
- package/dist/cli/process-guards.js +1 -139
- package/dist/cli/request-tree.js +7 -296
- package/dist/cli/runtime-commands.js +12 -258
- package/dist/cli/runtime-output.js +16 -155
- package/dist/cli/server-commands.js +16 -270
- package/dist/cli/workspace.js +1 -67
- package/dist/cli.js +1 -7
- package/dist/client/acp.js +1 -1
- package/dist/client/in-process.js +1 -67
- package/dist/client/index.js +1 -2
- package/dist/client/types.js +0 -1
- package/dist/client.js +1 -1
- package/dist/contracts/core.js +1 -1
- package/dist/contracts/runtime-evaluation.js +0 -1
- package/dist/contracts/runtime-memory.js +0 -1
- package/dist/contracts/runtime-observability.js +0 -1
- package/dist/contracts/runtime-requests.js +0 -1
- package/dist/contracts/runtime-scheduling.js +0 -1
- package/dist/contracts/runtime.js +1 -27
- package/dist/contracts/types.js +1 -3
- package/dist/contracts/workspace.js +0 -1
- package/dist/flow/build-flow-graph.js +1 -50
- package/dist/flow/export-mermaid.js +2 -464
- package/dist/flow/export-sequence-mermaid.js +2 -325
- package/dist/flow/flow-graph-normalization.js +1 -214
- package/dist/flow/flow-graph-runtime.js +1 -107
- package/dist/flow/flow-graph-upstream.js +1 -494
- package/dist/flow/index.js +1 -3
- package/dist/flow/types.js +0 -1
- package/dist/index.js +1 -5
- package/dist/init-project.js +1 -1
- package/dist/knowledge/config.js +1 -32
- package/dist/knowledge/contracts.js +0 -1
- package/dist/knowledge/index.js +1 -2
- package/dist/knowledge/module.js +12 -909
- package/dist/knowledge/procedural/config.js +1 -125
- package/dist/knowledge/procedural/index.js +1 -2
- package/dist/knowledge/procedural/manager.js +9 -345
- package/dist/mcp.js +1 -2
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -2
- package/dist/persistence/file-store.js +3 -758
- package/dist/persistence/sqlite-request-context-store.js +5 -54
- package/dist/persistence/sqlite-request-queue-store.js +10 -108
- package/dist/persistence/sqlite-runtime.js +1 -86
- package/dist/persistence/sqlite-store.js +62 -810
- package/dist/persistence/types.js +0 -1
- package/dist/projections/presentation.js +37 -206
- package/dist/projections/request-events.js +2 -502
- package/dist/projections/upstream-events.js +1 -201
- package/dist/protocol/a2a/http-discovery.js +1 -178
- package/dist/protocol/a2a/http-rpc.js +6 -622
- package/dist/protocol/a2a/http.js +1 -138
- package/dist/protocol/a2a/task-state.js +3 -317
- package/dist/protocol/acp/client.js +8 -294
- package/dist/protocol/acp/harness-client.js +1 -218
- package/dist/protocol/acp/http.js +5 -130
- package/dist/protocol/acp/server.js +1 -310
- package/dist/protocol/acp/stdio.js +2 -69
- package/dist/protocol/ag-ui/http.js +3 -378
- package/dist/protocol/mcp/server.js +1 -428
- package/dist/resource/backend/workspace-scoped-backend.js +1 -319
- package/dist/resource/isolation.js +1 -237
- package/dist/resource/mcp/tool-support.js +3 -296
- package/dist/resource/mcp-tool-support.js +1 -2
- package/dist/resource/providers/resource-provider.js +1 -215
- package/dist/resource/resource-impl.js +1 -3
- package/dist/resource/resource-types.js +0 -1
- package/dist/resource/resource.js +1 -1
- package/dist/resource/sources.js +1 -247
- package/dist/resource/tools/function-tool-resolver.js +2 -272
- package/dist/runtime/adapter/compat/deepagent-compat.js +1 -29
- package/dist/runtime/adapter/compat/openai-compatible.js +1 -55
- package/dist/runtime/adapter/direct-builtin-utility.js +2 -90
- package/dist/runtime/adapter/flow/execution-context.js +1 -71
- package/dist/runtime/adapter/flow/invocation-flow.js +8 -425
- package/dist/runtime/adapter/flow/invoke-runtime.js +1 -20
- package/dist/runtime/adapter/flow/stream-runtime.js +11 -1395
- package/dist/runtime/adapter/invocation-result.js +2 -473
- package/dist/runtime/adapter/local-tool-invocation.js +6 -638
- package/dist/runtime/adapter/middleware/context-hygiene.js +1 -83
- package/dist/runtime/adapter/middleware-assembly.js +5 -477
- package/dist/runtime/adapter/model/invocation-request.js +3 -183
- package/dist/runtime/adapter/model/message-assembly.js +1 -28
- package/dist/runtime/adapter/model/model-providers.js +23 -1115
- package/dist/runtime/adapter/model/prompted-json-tool-call-capture.js +1 -40
- package/dist/runtime/adapter/model/prompted-json-tool-policy.js +1 -22
- package/dist/runtime/adapter/resilience.js +1 -104
- package/dist/runtime/adapter/runtime-adapter-support.js +3 -141
- package/dist/runtime/adapter/runtime-shell.js +5 -166
- package/dist/runtime/adapter/stream-event-projection.js +2 -622
- package/dist/runtime/adapter/stream-text-consumption.js +1 -18
- package/dist/runtime/adapter/terminal-status.js +2 -67
- package/dist/runtime/adapter/tool/builtin-middleware-tools.js +6 -627
- package/dist/runtime/adapter/tool/declared-middleware.js +1 -154
- package/dist/runtime/adapter/tool/interrupt-policy.js +1 -34
- package/dist/runtime/adapter/tool/provider-tool.js +1 -25
- package/dist/runtime/adapter/tool/resolved-tool.js +1 -225
- package/dist/runtime/adapter/tool/tool-arguments.js +3 -486
- package/dist/runtime/adapter/tool/tool-hitl.js +1 -346
- package/dist/runtime/adapter/tool/tool-name-mapping.js +1 -128
- package/dist/runtime/adapter/tool/tool-output-artifacts.js +2 -88
- package/dist/runtime/adapter/tool/tool-replay.js +1 -37
- package/dist/runtime/adapter/tool-resolution.js +1 -86
- package/dist/runtime/adapter/upstream-configurable-keys.js +1 -2
- package/dist/runtime/agent-runtime-adapter.js +60 -2338
- package/dist/runtime/agent-runtime-assembly.js +7 -249
- package/dist/runtime/env/runtime-env.js +1 -62
- package/dist/runtime/harness/background-runtime.js +1 -8
- package/dist/runtime/harness/bindings.js +1 -58
- package/dist/runtime/harness/events/event-bus.js +1 -16
- package/dist/runtime/harness/events/event-sink.js +1 -61
- package/dist/runtime/harness/events/events.js +1 -80
- package/dist/runtime/harness/events/listener-runtime.js +1 -13
- package/dist/runtime/harness/events/runtime-event-operations.js +1 -9
- package/dist/runtime/harness/events/streaming.js +1 -100
- package/dist/runtime/harness/events/timeline.js +1 -52
- package/dist/runtime/harness/public-shapes.js +1 -186
- package/dist/runtime/harness/run/artifact-paths.js +1 -15
- package/dist/runtime/harness/run/governance.js +1 -295
- package/dist/runtime/harness/run/helpers.js +1 -71
- package/dist/runtime/harness/run/inspection.js +1 -409
- package/dist/runtime/harness/run/operator-overview.js +1 -80
- package/dist/runtime/harness/run/queue-diagnostics.js +1 -15
- package/dist/runtime/harness/run/recovery.js +1 -162
- package/dist/runtime/harness/run/resources.js +1 -60
- package/dist/runtime/harness/run/resume.js +1 -56
- package/dist/runtime/harness/run/routing.js +1 -48
- package/dist/runtime/harness/run/run-lifecycle.js +1 -66
- package/dist/runtime/harness/run/run-operations.js +1 -217
- package/dist/runtime/harness/run/run-queue.js +1 -43
- package/dist/runtime/harness/run/run-slot-acquisition.js +1 -157
- package/dist/runtime/harness/run/session-records.js +1 -97
- package/dist/runtime/harness/run/start-run.js +1 -120
- package/dist/runtime/harness/run/startup-runtime.js +1 -69
- package/dist/runtime/harness/run/stream-run.js +8 -1418
- package/dist/runtime/harness/run/surface-semantics.js +1 -79
- package/dist/runtime/harness/runtime-defaults.js +1 -39
- package/dist/runtime/harness/system/boundary-analysis.js +1 -234
- package/dist/runtime/harness/system/health-monitor.js +1 -258
- package/dist/runtime/harness/system/inventory.js +1 -129
- package/dist/runtime/harness/system/mem0-ingestion-sync.js +5 -345
- package/dist/runtime/harness/system/policy-engine.js +1 -175
- package/dist/runtime/harness/system/runtime-memory-candidates.js +4 -110
- package/dist/runtime/harness/system/runtime-memory-consolidation.js +1 -51
- package/dist/runtime/harness/system/runtime-memory-manager.js +10 -693
- package/dist/runtime/harness/system/runtime-memory-policy.js +1 -155
- package/dist/runtime/harness/system/runtime-memory-records.js +11 -577
- package/dist/runtime/harness/system/runtime-memory-sync.js +5 -206
- package/dist/runtime/harness/system/session-memory-sync.js +3 -113
- package/dist/runtime/harness/system/skill-requirements.js +1 -112
- package/dist/runtime/harness/system/store.js +9 -365
- package/dist/runtime/harness/tool-gateway/index.js +1 -2
- package/dist/runtime/harness/tool-gateway/policy.js +1 -45
- package/dist/runtime/harness/tool-gateway/validation.js +1 -176
- package/dist/runtime/harness/tool-schema.js +1 -3
- package/dist/runtime/harness.js +3 -1490
- package/dist/runtime/index.js +1 -3
- package/dist/runtime/layout/runtime-layout.js +1 -31
- package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -178
- package/dist/runtime/maintenance/file-checkpoint-saver.js +1 -106
- package/dist/runtime/maintenance/runtime-record-maintenance.js +2 -169
- package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +4 -289
- package/dist/runtime/parsing/output-content.js +10 -550
- package/dist/runtime/parsing/output-parsing.js +1 -4
- package/dist/runtime/parsing/output-recovery.js +3 -213
- package/dist/runtime/parsing/output-tool-args.js +7 -663
- package/dist/runtime/parsing/stream-event-parsing.js +3 -362
- package/dist/runtime/prompts/runtime-prompts.js +4 -73
- package/dist/runtime/scheduling/system-schedule-manager.js +11 -532
- package/dist/runtime/skills/skill-metadata.js +1 -197
- package/dist/runtime/startup-tracing.js +2 -37
- package/dist/runtime/support/compiled-binding.js +1 -290
- package/dist/runtime/support/embedding-models.js +1 -118
- package/dist/runtime/support/harness-support.js +5 -137
- package/dist/runtime/support/llamaindex.js +1 -108
- package/dist/runtime/support/runtime-adapter-options.js +1 -29
- package/dist/runtime/support/runtime-factories.js +1 -51
- package/dist/runtime/support/vector-stores.js +9 -270
- package/dist/scaffold/init-project.js +54 -233
- package/dist/tooling/extensions.js +1 -311
- package/dist/tooling/module-loader.js +1 -55
- package/dist/tools.js +1 -176
- package/dist/utils/agent-display.js +1 -18
- package/dist/utils/bundled-text.js +4 -39
- package/dist/utils/compiled-binding.js +1 -33
- package/dist/utils/fs.js +2 -45
- package/dist/utils/id.js +1 -9
- package/dist/utils/message-content.js +1 -30
- package/dist/utils/object.js +1 -6
- package/dist/workspace/agent-binding-compiler.js +3 -613
- package/dist/workspace/compile.js +1 -472
- package/dist/workspace/framework-contract-validation.js +2 -322
- package/dist/workspace/index.js +1 -1
- package/dist/workspace/object-loader-paths.js +1 -71
- package/dist/workspace/object-loader-readers.js +1 -187
- package/dist/workspace/object-loader.js +1 -754
- package/dist/workspace/resource-compilers.js +1 -374
- package/dist/workspace/support/agent-capabilities.js +1 -37
- package/dist/workspace/support/agent-execution-config.js +1 -44
- package/dist/workspace/support/discovery.js +1 -147
- package/dist/workspace/support/source-collectors.js +1 -30
- package/dist/workspace/support/source-protocols.js +2 -192
- package/dist/workspace/support/workspace-ref-utils.js +1 -362
- package/dist/workspace/tool-hydration.js +1 -280
- package/dist/workspace/validate.js +1 -99
- package/dist/workspace/yaml-object-reader.js +1 -285
- package/package.json +7 -3
package/dist/runtime/index.js
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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};
|