@cavelang/cli 0.27.3 → 0.29.0
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/Authors.md +5 -0
- package/License.md +6 -0
- package/README.md +122 -24
- package/dist/internal/act/action.d.ts +69 -0
- package/dist/internal/act/action.d.ts.map +1 -0
- package/dist/internal/act/action.js +201 -0
- package/dist/internal/act/action.js.map +1 -0
- package/dist/internal/act/declare.d.ts +102 -0
- package/dist/internal/act/declare.d.ts.map +1 -0
- package/dist/internal/act/declare.js +270 -0
- package/dist/internal/act/declare.js.map +1 -0
- package/dist/internal/act/engine.d.ts +103 -0
- package/dist/internal/act/engine.d.ts.map +1 -0
- package/dist/internal/act/engine.js +298 -0
- package/dist/internal/act/engine.js.map +1 -0
- package/dist/internal/act/index.d.ts +27 -0
- package/dist/internal/act/index.d.ts.map +1 -0
- package/dist/internal/act/index.js +25 -0
- package/dist/internal/act/index.js.map +1 -0
- package/dist/internal/automate/automation.d.ts +78 -0
- package/dist/internal/automate/automation.d.ts.map +1 -0
- package/dist/internal/automate/automation.js +135 -0
- package/dist/internal/automate/automation.js.map +1 -0
- package/dist/internal/automate/declare.d.ts +84 -0
- package/dist/internal/automate/declare.d.ts.map +1 -0
- package/dist/internal/automate/declare.js +233 -0
- package/dist/internal/automate/declare.js.map +1 -0
- package/dist/internal/automate/engine.d.ts +125 -0
- package/dist/internal/automate/engine.d.ts.map +1 -0
- package/dist/internal/automate/engine.js +388 -0
- package/dist/internal/automate/engine.js.map +1 -0
- package/dist/internal/automate/index.d.ts +28 -0
- package/dist/internal/automate/index.d.ts.map +1 -0
- package/dist/internal/automate/index.js +26 -0
- package/dist/internal/automate/index.js.map +1 -0
- package/dist/internal/automate/main.d.ts +26 -0
- package/dist/internal/automate/main.d.ts.map +1 -0
- package/dist/internal/automate/main.js +298 -0
- package/dist/internal/automate/main.js.map +1 -0
- package/dist/internal/connect/index.d.ts +26 -0
- package/dist/internal/connect/index.d.ts.map +1 -0
- package/dist/internal/connect/index.js +24 -0
- package/dist/internal/connect/index.js.map +1 -0
- package/dist/internal/connect/main.d.ts +23 -0
- package/dist/internal/connect/main.d.ts.map +1 -0
- package/dist/internal/connect/main.js +330 -0
- package/dist/internal/connect/main.js.map +1 -0
- package/dist/internal/connect/run.d.ts +85 -0
- package/dist/internal/connect/run.d.ts.map +1 -0
- package/dist/internal/connect/run.js +242 -0
- package/dist/internal/connect/run.js.map +1 -0
- package/dist/internal/connect/source.d.ts +44 -0
- package/dist/internal/connect/source.d.ts.map +1 -0
- package/dist/internal/connect/source.js +215 -0
- package/dist/internal/connect/source.js.map +1 -0
- package/dist/internal/connect/template.d.ts +69 -0
- package/dist/internal/connect/template.d.ts.map +1 -0
- package/dist/internal/connect/template.js +221 -0
- package/dist/internal/connect/template.js.map +1 -0
- package/dist/internal/eval/index.d.ts +28 -0
- package/dist/internal/eval/index.d.ts.map +1 -0
- package/dist/internal/eval/index.js +27 -0
- package/dist/internal/eval/index.js.map +1 -0
- package/dist/internal/eval/judge.d.ts +30 -0
- package/dist/internal/eval/judge.d.ts.map +1 -0
- package/dist/internal/eval/judge.js +101 -0
- package/dist/internal/eval/judge.js.map +1 -0
- package/dist/internal/eval/loop.d.ts +64 -0
- package/dist/internal/eval/loop.d.ts.map +1 -0
- package/dist/internal/eval/loop.js +123 -0
- package/dist/internal/eval/loop.js.map +1 -0
- package/dist/internal/eval/main.d.ts +17 -0
- package/dist/internal/eval/main.d.ts.map +1 -0
- package/dist/internal/eval/main.js +236 -0
- package/dist/internal/eval/main.js.map +1 -0
- package/dist/internal/eval/queries.d.ts +74 -0
- package/dist/internal/eval/queries.d.ts.map +1 -0
- package/dist/internal/eval/queries.js +161 -0
- package/dist/internal/eval/queries.js.map +1 -0
- package/dist/internal/eval/run.d.ts +143 -0
- package/dist/internal/eval/run.d.ts.map +1 -0
- package/dist/internal/eval/run.js +376 -0
- package/dist/internal/eval/run.js.map +1 -0
- package/dist/internal/eval/score.d.ts +81 -0
- package/dist/internal/eval/score.d.ts.map +1 -0
- package/dist/internal/eval/score.js +126 -0
- package/dist/internal/eval/score.js.map +1 -0
- package/dist/internal/eval/suite.d.ts +66 -0
- package/dist/internal/eval/suite.d.ts.map +1 -0
- package/dist/internal/eval/suite.js +130 -0
- package/dist/internal/eval/suite.js.map +1 -0
- package/dist/internal/ingest/context.d.ts +20 -0
- package/dist/internal/ingest/context.d.ts.map +1 -0
- package/dist/internal/ingest/context.js +59 -0
- package/dist/internal/ingest/context.js.map +1 -0
- package/dist/internal/ingest/files.d.ts +46 -0
- package/dist/internal/ingest/files.d.ts.map +1 -0
- package/dist/internal/ingest/files.js +115 -0
- package/dist/internal/ingest/files.js.map +1 -0
- package/dist/internal/ingest/index.d.ts +31 -0
- package/dist/internal/ingest/index.d.ts.map +1 -0
- package/dist/internal/ingest/index.js +29 -0
- package/dist/internal/ingest/index.js.map +1 -0
- package/dist/internal/ingest/main.d.ts +12 -0
- package/dist/internal/ingest/main.d.ts.map +1 -0
- package/dist/internal/ingest/main.js +180 -0
- package/dist/internal/ingest/main.js.map +1 -0
- package/dist/internal/ingest/prompt.d.ts +32 -0
- package/dist/internal/ingest/prompt.d.ts.map +1 -0
- package/dist/internal/ingest/prompt.js +75 -0
- package/dist/internal/ingest/prompt.js.map +1 -0
- package/dist/internal/ingest/run.d.ts +142 -0
- package/dist/internal/ingest/run.d.ts.map +1 -0
- package/dist/internal/ingest/run.js +350 -0
- package/dist/internal/ingest/run.js.map +1 -0
- package/dist/internal/ingest/web.d.ts +48 -0
- package/dist/internal/ingest/web.d.ts.map +1 -0
- package/dist/internal/ingest/web.js +140 -0
- package/dist/internal/ingest/web.js.map +1 -0
- package/dist/internal/loop/demo.d.ts +22 -0
- package/dist/internal/loop/demo.d.ts.map +1 -0
- package/dist/internal/loop/demo.js +67 -0
- package/dist/internal/loop/demo.js.map +1 -0
- package/dist/internal/loop/index.d.ts +20 -0
- package/dist/internal/loop/index.d.ts.map +1 -0
- package/dist/internal/loop/index.js +17 -0
- package/dist/internal/loop/index.js.map +1 -0
- package/dist/internal/loop/llm.d.ts +99 -0
- package/dist/internal/loop/llm.d.ts.map +1 -0
- package/dist/internal/loop/llm.js +231 -0
- package/dist/internal/loop/llm.js.map +1 -0
- package/dist/internal/loop/reconstruct.d.ts +87 -0
- package/dist/internal/loop/reconstruct.d.ts.map +1 -0
- package/dist/internal/loop/reconstruct.js +157 -0
- package/dist/internal/loop/reconstruct.js.map +1 -0
- package/dist/internal/loop/sqlite.d.ts +13 -0
- package/dist/internal/loop/sqlite.d.ts.map +1 -0
- package/dist/internal/loop/sqlite.js +33 -0
- package/dist/internal/loop/sqlite.js.map +1 -0
- package/dist/internal/loop/store.d.ts +50 -0
- package/dist/internal/loop/store.d.ts.map +1 -0
- package/dist/internal/loop/store.js +100 -0
- package/dist/internal/loop/store.js.map +1 -0
- package/dist/internal/mcp/bin.d.ts +7 -0
- package/dist/internal/mcp/bin.d.ts.map +1 -0
- package/dist/internal/mcp/bin.js +8 -0
- package/dist/internal/mcp/bin.js.map +1 -0
- package/dist/internal/mcp/index.d.ts +25 -0
- package/dist/internal/mcp/index.d.ts.map +1 -0
- package/dist/internal/mcp/index.js +23 -0
- package/dist/internal/mcp/index.js.map +1 -0
- package/dist/internal/mcp/main.d.ts +23 -0
- package/dist/internal/mcp/main.d.ts.map +1 -0
- package/dist/internal/mcp/main.js +156 -0
- package/dist/internal/mcp/main.js.map +1 -0
- package/dist/internal/mcp/server.d.ts +92 -0
- package/dist/internal/mcp/server.d.ts.map +1 -0
- package/dist/internal/mcp/server.js +251 -0
- package/dist/internal/mcp/server.js.map +1 -0
- package/dist/internal/mcp/tools.d.ts +91 -0
- package/dist/internal/mcp/tools.d.ts.map +1 -0
- package/dist/internal/mcp/tools.js +584 -0
- package/dist/internal/mcp/tools.js.map +1 -0
- package/dist/internal/rules/declare.d.ts +58 -0
- package/dist/internal/rules/declare.d.ts.map +1 -0
- package/dist/internal/rules/declare.js +152 -0
- package/dist/internal/rules/declare.js.map +1 -0
- package/dist/internal/rules/engine.d.ts +125 -0
- package/dist/internal/rules/engine.d.ts.map +1 -0
- package/dist/internal/rules/engine.js +575 -0
- package/dist/internal/rules/engine.js.map +1 -0
- package/dist/internal/rules/index.d.ts +23 -0
- package/dist/internal/rules/index.d.ts.map +1 -0
- package/dist/internal/rules/index.js +21 -0
- package/dist/internal/rules/index.js.map +1 -0
- package/dist/internal/rules/rule.d.ts +88 -0
- package/dist/internal/rules/rule.d.ts.map +1 -0
- package/dist/internal/rules/rule.js +221 -0
- package/dist/internal/rules/rule.js.map +1 -0
- package/dist/internal/shape/check.d.ts +118 -0
- package/dist/internal/shape/check.d.ts.map +1 -0
- package/dist/internal/shape/check.js +331 -0
- package/dist/internal/shape/check.js.map +1 -0
- package/dist/internal/shape/client.d.ts +31 -0
- package/dist/internal/shape/client.d.ts.map +1 -0
- package/dist/internal/shape/client.js +170 -0
- package/dist/internal/shape/client.js.map +1 -0
- package/dist/internal/shape/gate.d.ts +33 -0
- package/dist/internal/shape/gate.d.ts.map +1 -0
- package/dist/internal/shape/gate.js +0 -0
- package/dist/internal/shape/gate.js.map +1 -0
- package/dist/internal/shape/index.d.ts +27 -0
- package/dist/internal/shape/index.d.ts.map +1 -0
- package/dist/internal/shape/index.js +23 -0
- package/dist/internal/shape/index.js.map +1 -0
- package/dist/internal/shape/suggest.d.ts +82 -0
- package/dist/internal/shape/suggest.d.ts.map +1 -0
- package/dist/internal/shape/suggest.js +374 -0
- package/dist/internal/shape/suggest.js.map +1 -0
- package/dist/internal/sync/index.d.ts +22 -0
- package/dist/internal/sync/index.d.ts.map +1 -0
- package/dist/internal/sync/index.js +21 -0
- package/dist/internal/sync/index.js.map +1 -0
- package/dist/internal/sync/sync.d.ts +95 -0
- package/dist/internal/sync/sync.d.ts.map +1 -0
- package/dist/internal/sync/sync.js +342 -0
- package/dist/internal/sync/sync.js.map +1 -0
- package/dist/internal/view/api.d.ts +196 -0
- package/dist/internal/view/api.d.ts.map +1 -0
- package/dist/internal/view/api.js +189 -0
- package/dist/internal/view/api.js.map +1 -0
- package/dist/internal/view/index.d.ts +33 -0
- package/dist/internal/view/index.d.ts.map +1 -0
- package/dist/internal/view/index.js +30 -0
- package/dist/internal/view/index.js.map +1 -0
- package/dist/internal/view/main.d.ts +11 -0
- package/dist/internal/view/main.d.ts.map +1 -0
- package/dist/internal/view/main.js +98 -0
- package/dist/internal/view/main.js.map +1 -0
- package/dist/internal/view/page.d.ts +14 -0
- package/dist/internal/view/page.d.ts.map +1 -0
- package/dist/internal/view/page.js +370 -0
- package/dist/internal/view/page.js.map +1 -0
- package/dist/internal/view/report.d.ts +52 -0
- package/dist/internal/view/report.d.ts.map +1 -0
- package/dist/internal/view/report.js +367 -0
- package/dist/internal/view/report.js.map +1 -0
- package/dist/internal/view/scope.d.ts +11 -0
- package/dist/internal/view/scope.d.ts.map +1 -0
- package/dist/internal/view/scope.js +41 -0
- package/dist/internal/view/scope.js.map +1 -0
- package/dist/internal/view/server.d.ts +35 -0
- package/dist/internal/view/server.d.ts.map +1 -0
- package/dist/internal/view/server.js +141 -0
- package/dist/internal/view/server.js.map +1 -0
- package/dist/src/act.d.ts +3 -0
- package/dist/src/act.d.ts.map +1 -0
- package/dist/src/act.js +3 -0
- package/dist/src/act.js.map +1 -0
- package/dist/src/automate.d.ts +3 -0
- package/dist/src/automate.d.ts.map +1 -0
- package/dist/src/automate.js +3 -0
- package/dist/src/automate.js.map +1 -0
- package/dist/src/cli.d.ts +24 -17
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +416 -109
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands.d.ts +104 -0
- package/dist/src/commands.d.ts.map +1 -0
- package/dist/src/commands.js +33 -0
- package/dist/src/commands.js.map +1 -0
- package/dist/src/connect.d.ts +3 -0
- package/dist/src/connect.d.ts.map +1 -0
- package/dist/src/connect.js +3 -0
- package/dist/src/connect.js.map +1 -0
- package/dist/src/dispatch.d.ts +14 -0
- package/dist/src/dispatch.d.ts.map +1 -0
- package/dist/src/dispatch.js +116 -0
- package/dist/src/dispatch.js.map +1 -0
- package/dist/src/doctor.d.ts +45 -0
- package/dist/src/doctor.d.ts.map +1 -0
- package/dist/src/doctor.js +284 -0
- package/dist/src/doctor.js.map +1 -0
- package/dist/src/eval.d.ts +3 -0
- package/dist/src/eval.d.ts.map +1 -0
- package/dist/src/eval.js +3 -0
- package/dist/src/eval.js.map +1 -0
- package/dist/src/index.d.ts +9 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/ingest.d.ts +3 -0
- package/dist/src/ingest.d.ts.map +1 -0
- package/dist/src/ingest.js +3 -0
- package/dist/src/ingest.js.map +1 -0
- package/dist/src/loop.d.ts +3 -0
- package/dist/src/loop.d.ts.map +1 -0
- package/dist/src/loop.js +3 -0
- package/dist/src/loop.js.map +1 -0
- package/dist/src/main.d.ts +1 -1
- package/dist/src/main.d.ts.map +1 -1
- package/dist/src/main.js +3 -75
- package/dist/src/main.js.map +1 -1
- package/dist/src/mcp.d.ts +3 -0
- package/dist/src/mcp.d.ts.map +1 -0
- package/dist/src/mcp.js +3 -0
- package/dist/src/mcp.js.map +1 -0
- package/dist/src/rules.d.ts +3 -0
- package/dist/src/rules.d.ts.map +1 -0
- package/dist/src/rules.js +3 -0
- package/dist/src/rules.js.map +1 -0
- package/dist/src/shape.d.ts +3 -0
- package/dist/src/shape.d.ts.map +1 -0
- package/dist/src/shape.js +3 -0
- package/dist/src/shape.js.map +1 -0
- package/dist/src/sync.d.ts +3 -0
- package/dist/src/sync.d.ts.map +1 -0
- package/dist/src/sync.js +3 -0
- package/dist/src/sync.js.map +1 -0
- package/dist/src/view.d.ts +3 -0
- package/dist/src/view.d.ts.map +1 -0
- package/dist/src/view.js +3 -0
- package/dist/src/view.js.map +1 -0
- package/package.json +81 -21
- package/src/act.ts +2 -0
- package/src/automate.ts +2 -0
- package/src/cli.ts +423 -104
- package/src/commands.ts +48 -0
- package/src/connect.ts +2 -0
- package/src/dispatch.ts +141 -0
- package/src/doctor.ts +370 -0
- package/src/eval.ts +2 -0
- package/src/index.ts +9 -2
- package/src/ingest.ts +2 -0
- package/src/loop.ts +2 -0
- package/src/main.ts +3 -66
- package/src/mcp.ts +2 -0
- package/src/rules.ts +2 -0
- package/src/shape.ts +2 -0
- package/src/sync.ts +2 -0
- package/src/view.ts +2 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runnable demo (spec §18): the multi-hop recovery pattern central to the
|
|
3
|
+
* active-reconstruction thesis (spec §11.3).
|
|
4
|
+
*
|
|
5
|
+
* Starting from the single cue `reject-valid-tokens` — the *symptom* — the
|
|
6
|
+
* loop must travel edges that only exist as inverse reads:
|
|
7
|
+
*
|
|
8
|
+
* 1. `reject-valid-tokens` ← CAUSED-BY — `token-expiry` (inverse CAUSE)
|
|
9
|
+
* 2. `token-expiry` ← PART-OF — `topic/auth-hardening` (inverse CONTAINS)
|
|
10
|
+
* 3. topic expansion → `auth/middleware`, and with it the bug, the broken
|
|
11
|
+
* check and the fix.
|
|
12
|
+
*
|
|
13
|
+
* ```
|
|
14
|
+
* pnpm --filter @cavelang/cli/loop demo
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import { emitClaim } from '@cavelang/canonical';
|
|
18
|
+
import { posix, win32 } from 'node:path';
|
|
19
|
+
import { fileURLToPath } from 'node:url';
|
|
20
|
+
import { memoryStoreOfText } from "./store.js";
|
|
21
|
+
import { heuristicPolicy, reconstruct } from "./reconstruct.js";
|
|
22
|
+
export const knowledge = `
|
|
23
|
+
auth/middleware HAS bug: token-expiry #security #topic:auth-hardening
|
|
24
|
+
token-expiry CAUSE reject-valid-tokens
|
|
25
|
+
expiry-check USES \`<\`
|
|
26
|
+
expiry-check NEEDS \`<=\`
|
|
27
|
+
\`<=\` FIX token-expiry @auth.ts:42
|
|
28
|
+
auth/middleware NEEDS test: boundary-cases @ 70%
|
|
29
|
+
topic/auth-hardening CONTAINS token-expiry
|
|
30
|
+
topic/auth-hardening CONTAINS auth/middleware
|
|
31
|
+
topic/auth-hardening CONTAINS expiry-check
|
|
32
|
+
deploy VIA github-actions
|
|
33
|
+
unrelated/service USES postgres
|
|
34
|
+
`;
|
|
35
|
+
export const run = () => {
|
|
36
|
+
const store = memoryStoreOfText(knowledge);
|
|
37
|
+
const { claims, trace } = reconstruct(store, heuristicPolicy({ maxSteps: 12 }), ['reject-valid-tokens']);
|
|
38
|
+
const lines = [];
|
|
39
|
+
lines.push('cave-loop demo — multi-hop recovery from the symptom cue');
|
|
40
|
+
lines.push('');
|
|
41
|
+
lines.push('trace:');
|
|
42
|
+
for (const step of trace) {
|
|
43
|
+
const edges = step.edges
|
|
44
|
+
.map(edge => `${edge.rel ?? `${edge.verb}(un-named reverse)`} → ${edge.to}`)
|
|
45
|
+
.join(', ');
|
|
46
|
+
lines.push(` ${step.step}. expand ${step.cue.entity} (score ${step.cue.score.toFixed(2)})` +
|
|
47
|
+
`${edges === '' ? '' : ` — ${edges}`}`);
|
|
48
|
+
}
|
|
49
|
+
lines.push('');
|
|
50
|
+
lines.push('reconstructed claims:');
|
|
51
|
+
for (const claim of claims) {
|
|
52
|
+
lines.push(` ${emitClaim(claim)}`);
|
|
53
|
+
}
|
|
54
|
+
return { lines };
|
|
55
|
+
};
|
|
56
|
+
export const isDirectInvocation = (moduleUrl, entryPath, platform = process.platform) => {
|
|
57
|
+
if (entryPath === undefined)
|
|
58
|
+
return false;
|
|
59
|
+
const path = platform === 'win32' ? win32 : posix;
|
|
60
|
+
const modulePath = fileURLToPath(moduleUrl, { windows: platform === 'win32' });
|
|
61
|
+
return path.resolve(modulePath) === path.resolve(entryPath);
|
|
62
|
+
};
|
|
63
|
+
const invokedDirectly = isDirectInvocation(import.meta.url, process.argv[1]);
|
|
64
|
+
if (invokedDirectly) {
|
|
65
|
+
console.log(run().lines.join('\n'));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=demo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../../src/demo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@cavelang/cli/loop` — cave-loop, the active-reconstruction agent layer over the
|
|
3
|
+
* CAVE graph (spec §18, non-normative).
|
|
4
|
+
*
|
|
5
|
+
* The agent layer is deliberately outside the language specification:
|
|
6
|
+
* reconstruction is a *policy* over the graph. This package provides the
|
|
7
|
+
* injectable `CaveStore` and `Policy` interfaces, an in-memory store and a
|
|
8
|
+
* SQLite adapter, a deterministic heuristic policy (the eval baseline), the
|
|
9
|
+
* LLM-driven policy over any shell-agent command template (spec §18)
|
|
10
|
+
* and a runnable multi-hop recovery demo.
|
|
11
|
+
*/
|
|
12
|
+
export * as Demo from './demo.ts';
|
|
13
|
+
export type { CaveStore, Edge } from './store.ts';
|
|
14
|
+
export { memoryStore, memoryStoreOfText } from './store.ts';
|
|
15
|
+
export { sqliteStore } from './sqlite.ts';
|
|
16
|
+
export { heuristicPolicy, reconstruct, reconstructAsync } from './reconstruct.ts';
|
|
17
|
+
export type { AsyncPolicy, Cue, HeuristicOptions, Policy, Reconstruction, State, Step } from './reconstruct.ts';
|
|
18
|
+
export { llmPolicy, parseSelection, selectPrompt, shellComplete, stopToken } from './llm.ts';
|
|
19
|
+
export type { Complete, LlmOptions, ShellCompleteOptions } from './llm.ts';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACjF,YAAY,EAAE,WAAW,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAC/G,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAC5F,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@cavelang/cli/loop` — cave-loop, the active-reconstruction agent layer over the
|
|
3
|
+
* CAVE graph (spec §18, non-normative).
|
|
4
|
+
*
|
|
5
|
+
* The agent layer is deliberately outside the language specification:
|
|
6
|
+
* reconstruction is a *policy* over the graph. This package provides the
|
|
7
|
+
* injectable `CaveStore` and `Policy` interfaces, an in-memory store and a
|
|
8
|
+
* SQLite adapter, a deterministic heuristic policy (the eval baseline), the
|
|
9
|
+
* LLM-driven policy over any shell-agent command template (spec §18)
|
|
10
|
+
* and a runnable multi-hop recovery demo.
|
|
11
|
+
*/
|
|
12
|
+
export * as Demo from "./demo.js";
|
|
13
|
+
export { memoryStore, memoryStoreOfText } from "./store.js";
|
|
14
|
+
export { sqliteStore } from "./sqlite.js";
|
|
15
|
+
export { heuristicPolicy, reconstruct, reconstructAsync } from "./reconstruct.js";
|
|
16
|
+
export { llmPolicy, parseSelection, selectPrompt, shellComplete, stopToken } from "./llm.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAEjC,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAEjF,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM-driven policy (spec §18) — the model makes the
|
|
3
|
+
* select/stop decisions; the loop stays unchanged.
|
|
4
|
+
*
|
|
5
|
+
* The deterministic heuristic in `reconstruct.ts` spends no tokens and is
|
|
6
|
+
* the eval baseline (`cave eval` runs it when no agent is given); this
|
|
7
|
+
* policy spends one completion per step and should earn its cost by
|
|
8
|
+
* reading the claims. Design decisions:
|
|
9
|
+
*
|
|
10
|
+
* - **One completion per step.** The sketch this file grew from asked the
|
|
11
|
+
* model twice per step (select, then "are we done?"). Both decisions fit
|
|
12
|
+
* one prompt: the model replies with the next cue to expand *or* `STOP`,
|
|
13
|
+
* and the loop already treats an `undefined` selection as the stop
|
|
14
|
+
* signal. `done` then only enforces the hard budgets, for free.
|
|
15
|
+
* - **Scoring stays local.** Models are better spent on select/stop than
|
|
16
|
+
* on per-edge arithmetic; `score` is the same parent × confidence ×
|
|
17
|
+
* decay the heuristic uses, so the scores shown in the prompt mean the
|
|
18
|
+
* same thing in both policies.
|
|
19
|
+
* - **Claims render as canonical CAVE text** (`emitClaim`) — compact,
|
|
20
|
+
* line-oriented, and exactly the notation the model knows from the spec
|
|
21
|
+
* card and the MCP server instructions.
|
|
22
|
+
* - **Replies parse leniently, and degrade to the heuristic.** An answer
|
|
23
|
+
* that names no frontier cue and never says stop expands the strongest
|
|
24
|
+
* cue instead of silently ending the reconstruction — the budgets bound
|
|
25
|
+
* the damage, and the result stays useful.
|
|
26
|
+
*
|
|
27
|
+
* The model itself stays out-of-band (spec §19.5): `shellComplete` adapts
|
|
28
|
+
* any shell-agent command template — the same `--agent` contract
|
|
29
|
+
* `cave ingest` and `cave eval` use — into a `Complete`, so no LLM SDK
|
|
30
|
+
* ever becomes a dependency of this package.
|
|
31
|
+
*/
|
|
32
|
+
import type { AsyncPolicy, Cue, State } from './reconstruct.ts';
|
|
33
|
+
/** Minimal completion function the policy needs: prompt in, reply out. */
|
|
34
|
+
export type Complete = (prompt: string) => Promise<string>;
|
|
35
|
+
export type LlmOptions = {
|
|
36
|
+
/** What the reconstruction should answer — shown to the model each step. */
|
|
37
|
+
readonly query?: string;
|
|
38
|
+
/** Extra guidance appended to every step prompt. */
|
|
39
|
+
readonly instructions?: string;
|
|
40
|
+
/** Hard step budget — and completion budget, one per step (default 16). */
|
|
41
|
+
readonly maxSteps?: number;
|
|
42
|
+
/** Stop once this many claims are collected (default ∞). */
|
|
43
|
+
readonly maxClaims?: number;
|
|
44
|
+
/** Per-hop decay of the local edge score (default 0.8). */
|
|
45
|
+
readonly decay?: number;
|
|
46
|
+
/** Strongest frontier cues offered to the model per step (default 16). */
|
|
47
|
+
readonly maxCues?: number;
|
|
48
|
+
};
|
|
49
|
+
/** The reply that ends the reconstruction. */
|
|
50
|
+
export declare const stopToken = "STOP";
|
|
51
|
+
/**
|
|
52
|
+
* The single per-step prompt: the query, the claims collected so far as
|
|
53
|
+
* canonical CAVE lines, the strongest frontier cues with their scores, and
|
|
54
|
+
* the reply protocol. Exported for tests and for adapter authors who want
|
|
55
|
+
* the same rendering under a different transport.
|
|
56
|
+
*/
|
|
57
|
+
export declare const selectPrompt: (state: State, options?: LlmOptions) => string;
|
|
58
|
+
/**
|
|
59
|
+
* Decides what the model asked for. In order:
|
|
60
|
+
*
|
|
61
|
+
* 1. the trimmed reply, its last non-empty line, or either with list
|
|
62
|
+
* markers/quotes stripped, is exactly a frontier entity → that cue;
|
|
63
|
+
* 2. the reply's first word is the stop token (any case) → stop;
|
|
64
|
+
* 3. the earliest frontier entity mentioned anywhere in the reply → that
|
|
65
|
+
* cue (ties at one position go to the longer name; occurrences inside
|
|
66
|
+
* larger words don't count);
|
|
67
|
+
* 4. the stop token appears as a word anywhere → stop;
|
|
68
|
+
* 5. otherwise the strongest cue — an unparseable reply degrades to the
|
|
69
|
+
* heuristic instead of silently ending the reconstruction.
|
|
70
|
+
*/
|
|
71
|
+
export declare const parseSelection: (reply: string, frontier: readonly Cue[]) => undefined | Cue;
|
|
72
|
+
/**
|
|
73
|
+
* The LLM-driven `AsyncPolicy` (spec §18): the model reads the collected
|
|
74
|
+
* claims and the scored frontier, and answers with the next cue or
|
|
75
|
+
* `STOP`; budgets stay local and completions cost one per step. Errors
|
|
76
|
+
* from `complete` propagate — a failing agent must look like a failure,
|
|
77
|
+
* not like a decision to stop.
|
|
78
|
+
*/
|
|
79
|
+
export declare const llmPolicy: (complete: Complete, options?: LlmOptions) => AsyncPolicy;
|
|
80
|
+
export type ShellCompleteOptions = {
|
|
81
|
+
/** Seconds before the agent process is killed (default 120). */
|
|
82
|
+
readonly timeoutSeconds?: number;
|
|
83
|
+
/** Working directory the agent runs in (default: the process cwd). */
|
|
84
|
+
readonly cwd?: string;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* A `Complete` from a shell-agent command template — the same contract as
|
|
88
|
+
* `cave ingest --agent` and `cave eval --agent`: the prompt is piped to
|
|
89
|
+
* stdin and substituted for `{prompt-file}` (written to a temporary file,
|
|
90
|
+
* substituted shell-quoted) when the template names it; stdout is the
|
|
91
|
+
* model's reply; stderr passes through; a non-zero exit, spawn failure or
|
|
92
|
+
* timeout rejects.
|
|
93
|
+
*
|
|
94
|
+
* ```ts
|
|
95
|
+
* const policy = llmPolicy(shellComplete(`claude -p`), { query })
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export declare const shellComplete: (template: string, options?: ShellCompleteOptions) => Complete;
|
|
99
|
+
//# sourceMappingURL=llm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/llm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAE/D,0EAA0E;AAC1E,MAAM,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;AAE1D,MAAM,MAAM,UAAU,GAAG;IACvB,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,oDAAoD;IACpD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,8CAA8C;AAC9C,eAAO,MAAM,SAAS,SAAS,CAAA;AAQ/B;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,KAAK,EAAE,UAAS,UAAe,KAAG,MAiBrE,CAAA;AA4BD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,EAAE,UAAU,SAAS,GAAG,EAAE,KAAG,SAAS,GAAG,GAiCpF,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GAAI,UAAU,QAAQ,EAAE,UAAS,UAAe,KAAG,WAkBxE,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,gEAAgE;IAChE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC,sEAAsE;IACtE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,EAAE,UAAS,oBAAyB,KAAG,QAwDpF,CAAA"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM-driven policy (spec §18) — the model makes the
|
|
3
|
+
* select/stop decisions; the loop stays unchanged.
|
|
4
|
+
*
|
|
5
|
+
* The deterministic heuristic in `reconstruct.ts` spends no tokens and is
|
|
6
|
+
* the eval baseline (`cave eval` runs it when no agent is given); this
|
|
7
|
+
* policy spends one completion per step and should earn its cost by
|
|
8
|
+
* reading the claims. Design decisions:
|
|
9
|
+
*
|
|
10
|
+
* - **One completion per step.** The sketch this file grew from asked the
|
|
11
|
+
* model twice per step (select, then "are we done?"). Both decisions fit
|
|
12
|
+
* one prompt: the model replies with the next cue to expand *or* `STOP`,
|
|
13
|
+
* and the loop already treats an `undefined` selection as the stop
|
|
14
|
+
* signal. `done` then only enforces the hard budgets, for free.
|
|
15
|
+
* - **Scoring stays local.** Models are better spent on select/stop than
|
|
16
|
+
* on per-edge arithmetic; `score` is the same parent × confidence ×
|
|
17
|
+
* decay the heuristic uses, so the scores shown in the prompt mean the
|
|
18
|
+
* same thing in both policies.
|
|
19
|
+
* - **Claims render as canonical CAVE text** (`emitClaim`) — compact,
|
|
20
|
+
* line-oriented, and exactly the notation the model knows from the spec
|
|
21
|
+
* card and the MCP server instructions.
|
|
22
|
+
* - **Replies parse leniently, and degrade to the heuristic.** An answer
|
|
23
|
+
* that names no frontier cue and never says stop expands the strongest
|
|
24
|
+
* cue instead of silently ending the reconstruction — the budgets bound
|
|
25
|
+
* the damage, and the result stays useful.
|
|
26
|
+
*
|
|
27
|
+
* The model itself stays out-of-band (spec §19.5): `shellComplete` adapts
|
|
28
|
+
* any shell-agent command template — the same `--agent` contract
|
|
29
|
+
* `cave ingest` and `cave eval` use — into a `Complete`, so no LLM SDK
|
|
30
|
+
* ever becomes a dependency of this package.
|
|
31
|
+
*/
|
|
32
|
+
import { spawn } from 'node:child_process';
|
|
33
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
34
|
+
import { tmpdir } from 'node:os';
|
|
35
|
+
import { join } from 'node:path';
|
|
36
|
+
import { emitClaim } from '@cavelang/canonical';
|
|
37
|
+
/** The reply that ends the reconstruction. */
|
|
38
|
+
export const stopToken = 'STOP';
|
|
39
|
+
const defaultMaxCues = 16;
|
|
40
|
+
/** Strongest first; stable sort keeps FIFO order on ties, like the heuristic. */
|
|
41
|
+
const strongestFirst = (frontier) => [...frontier].sort((a, b) => b.score - a.score);
|
|
42
|
+
/**
|
|
43
|
+
* The single per-step prompt: the query, the claims collected so far as
|
|
44
|
+
* canonical CAVE lines, the strongest frontier cues with their scores, and
|
|
45
|
+
* the reply protocol. Exported for tests and for adapter authors who want
|
|
46
|
+
* the same rendering under a different transport.
|
|
47
|
+
*/
|
|
48
|
+
export const selectPrompt = (state, options = {}) => {
|
|
49
|
+
const cues = strongestFirst(state.frontier).slice(0, options.maxCues ?? defaultMaxCues);
|
|
50
|
+
return [
|
|
51
|
+
'You are driving memory reconstruction over a CAVE claim graph, one step at a time.',
|
|
52
|
+
...options.query === undefined ? [] : ['', `Query: ${options.query}`],
|
|
53
|
+
'',
|
|
54
|
+
'Claims collected so far (canonical CAVE):',
|
|
55
|
+
...state.collected.length === 0 ? ['(none yet)'] : state.collected.map(claim => emitClaim(claim)),
|
|
56
|
+
'',
|
|
57
|
+
'Frontier cues (entity @ score); expanding a cue collects its claims and its neighbors:',
|
|
58
|
+
...cues.map(cue => `${cue.entity} @ ${cue.score.toFixed(2)}`),
|
|
59
|
+
...options.instructions === undefined ? [] : ['', options.instructions],
|
|
60
|
+
'',
|
|
61
|
+
'Reply with exactly one line: the name of the single frontier cue to expand next, ' +
|
|
62
|
+
`or ${stopToken} when the collected claims already answer the query ` +
|
|
63
|
+
'(or nothing on the frontier would help).'
|
|
64
|
+
].join('\n');
|
|
65
|
+
};
|
|
66
|
+
/** List markers, punctuation, quotes and backticks around a model's answer. */
|
|
67
|
+
const stripped = (line) => line.trim()
|
|
68
|
+
.replace(/^[-*\d.)\s]+/, '')
|
|
69
|
+
.replace(/[.!,;:]+$/, '')
|
|
70
|
+
.replace(/^[`'"]+|[`'"]+$/g, '')
|
|
71
|
+
.trim();
|
|
72
|
+
const wordChar = /[A-Za-z0-9_/-]/;
|
|
73
|
+
/** First occurrence of `entity` in `reply` not embedded in a larger word. */
|
|
74
|
+
const mentionAt = (reply, entity) => {
|
|
75
|
+
for (let from = 0;;) {
|
|
76
|
+
const index = reply.indexOf(entity, from);
|
|
77
|
+
if (index === -1) {
|
|
78
|
+
return -1;
|
|
79
|
+
}
|
|
80
|
+
const before = index === 0 ? undefined : reply[index - 1];
|
|
81
|
+
const after = index + entity.length >= reply.length ? undefined : reply[index + entity.length];
|
|
82
|
+
if ((before === undefined || !wordChar.test(before)) && (after === undefined || !wordChar.test(after))) {
|
|
83
|
+
return index;
|
|
84
|
+
}
|
|
85
|
+
from = index + 1;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Decides what the model asked for. In order:
|
|
90
|
+
*
|
|
91
|
+
* 1. the trimmed reply, its last non-empty line, or either with list
|
|
92
|
+
* markers/quotes stripped, is exactly a frontier entity → that cue;
|
|
93
|
+
* 2. the reply's first word is the stop token (any case) → stop;
|
|
94
|
+
* 3. the earliest frontier entity mentioned anywhere in the reply → that
|
|
95
|
+
* cue (ties at one position go to the longer name; occurrences inside
|
|
96
|
+
* larger words don't count);
|
|
97
|
+
* 4. the stop token appears as a word anywhere → stop;
|
|
98
|
+
* 5. otherwise the strongest cue — an unparseable reply degrades to the
|
|
99
|
+
* heuristic instead of silently ending the reconstruction.
|
|
100
|
+
*/
|
|
101
|
+
export const parseSelection = (reply, frontier) => {
|
|
102
|
+
if (frontier.length === 0) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const byEntity = new Map(frontier.map(cue => [cue.entity, cue]));
|
|
106
|
+
const lastLine = reply.split('\n').map(line => line.trim()).filter(line => line !== '').at(-1) ?? '';
|
|
107
|
+
for (const candidate of [reply.trim(), lastLine, stripped(lastLine), stripped(reply)]) {
|
|
108
|
+
const exact = byEntity.get(candidate);
|
|
109
|
+
if (exact !== undefined) {
|
|
110
|
+
return exact;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (new RegExp(`^${stopToken}\\b`, 'i').test(reply.trim())) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
let mentioned;
|
|
117
|
+
for (const cue of frontier) {
|
|
118
|
+
const at = mentionAt(reply, cue.entity);
|
|
119
|
+
if (at === -1) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (mentioned === undefined || at < mentioned.at ||
|
|
123
|
+
(at === mentioned.at && cue.entity.length > mentioned.cue.entity.length)) {
|
|
124
|
+
mentioned = { cue, at };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (mentioned !== undefined) {
|
|
128
|
+
return mentioned.cue;
|
|
129
|
+
}
|
|
130
|
+
if (new RegExp(`\\b${stopToken}\\b`, 'i').test(reply)) {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
return strongestFirst(frontier)[0];
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* The LLM-driven `AsyncPolicy` (spec §18): the model reads the collected
|
|
137
|
+
* claims and the scored frontier, and answers with the next cue or
|
|
138
|
+
* `STOP`; budgets stay local and completions cost one per step. Errors
|
|
139
|
+
* from `complete` propagate — a failing agent must look like a failure,
|
|
140
|
+
* not like a decision to stop.
|
|
141
|
+
*/
|
|
142
|
+
export const llmPolicy = (complete, options = {}) => {
|
|
143
|
+
const decay = options.decay ?? 0.8;
|
|
144
|
+
const maxSteps = options.maxSteps ?? 16;
|
|
145
|
+
const maxClaims = options.maxClaims ?? Number.POSITIVE_INFINITY;
|
|
146
|
+
return {
|
|
147
|
+
async select(state) {
|
|
148
|
+
if (state.frontier.length === 0) {
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
return parseSelection(await complete(selectPrompt(state, options)), state.frontier);
|
|
152
|
+
},
|
|
153
|
+
async score(edge, from) {
|
|
154
|
+
return from.score * edge.conf * decay;
|
|
155
|
+
},
|
|
156
|
+
async done(state) {
|
|
157
|
+
return state.steps >= maxSteps || state.collected.length >= maxClaims;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* A `Complete` from a shell-agent command template — the same contract as
|
|
163
|
+
* `cave ingest --agent` and `cave eval --agent`: the prompt is piped to
|
|
164
|
+
* stdin and substituted for `{prompt-file}` (written to a temporary file,
|
|
165
|
+
* substituted shell-quoted) when the template names it; stdout is the
|
|
166
|
+
* model's reply; stderr passes through; a non-zero exit, spawn failure or
|
|
167
|
+
* timeout rejects.
|
|
168
|
+
*
|
|
169
|
+
* ```ts
|
|
170
|
+
* const policy = llmPolicy(shellComplete(`claude -p`), { query })
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
export const shellComplete = (template, options = {}) => {
|
|
174
|
+
const timeoutSeconds = options.timeoutSeconds ?? 120;
|
|
175
|
+
return prompt => new Promise((resolvePromise, rejectPromise) => {
|
|
176
|
+
let dir;
|
|
177
|
+
let command = template;
|
|
178
|
+
if (template.includes('{prompt-file}')) {
|
|
179
|
+
dir = mkdtempSync(join(tmpdir(), 'cave-loop-'));
|
|
180
|
+
const file = join(dir, 'prompt.md');
|
|
181
|
+
writeFileSync(file, prompt);
|
|
182
|
+
// Quoted like ingest's substitutions — one argument, never re-parsed.
|
|
183
|
+
command = template.replaceAll('{prompt-file}', `'${file.replaceAll("'", `'\\''`)}'`);
|
|
184
|
+
}
|
|
185
|
+
let settled = false;
|
|
186
|
+
const settle = (finish) => {
|
|
187
|
+
if (!settled) {
|
|
188
|
+
settled = true;
|
|
189
|
+
if (dir !== undefined) {
|
|
190
|
+
rmSync(dir, { recursive: true, force: true });
|
|
191
|
+
}
|
|
192
|
+
// Grandchildren of a killed shell can inherit the stdio pipes;
|
|
193
|
+
// dropping our end releases the event loop from waiting on them.
|
|
194
|
+
child.stdout.destroy();
|
|
195
|
+
child.stdin.destroy();
|
|
196
|
+
finish();
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
const child = spawn(command, {
|
|
200
|
+
shell: true,
|
|
201
|
+
timeout: timeoutSeconds * 1000,
|
|
202
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
203
|
+
...options.cwd === undefined ? {} : { cwd: options.cwd }
|
|
204
|
+
});
|
|
205
|
+
let stdout = '';
|
|
206
|
+
child.stdout.on('data', chunk => {
|
|
207
|
+
stdout += String(chunk);
|
|
208
|
+
});
|
|
209
|
+
child.on('error', error => settle(() => rejectPromise(new Error(`agent failed: ${error.message}`))));
|
|
210
|
+
// A killed shell can leave grandchildren holding the stdio pipes open,
|
|
211
|
+
// so the signal path settles on `exit` — waiting for `close` would wait
|
|
212
|
+
// for processes the timeout was meant to cut loose.
|
|
213
|
+
child.on('exit', (_code, signal) => {
|
|
214
|
+
if (signal !== null) {
|
|
215
|
+
settle(() => rejectPromise(new Error(`agent killed by ${signal} after ${timeoutSeconds}s`)));
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
child.on('close', code => settle(() => {
|
|
219
|
+
if (code === 0) {
|
|
220
|
+
resolvePromise(stdout);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
rejectPromise(new Error(`agent exited with ${code}`));
|
|
224
|
+
}
|
|
225
|
+
}));
|
|
226
|
+
child.stdin.on('error', () => { });
|
|
227
|
+
child.stdin.write(prompt);
|
|
228
|
+
child.stdin.end();
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
//# sourceMappingURL=llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/llm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reconstruction loop (spec §18, §11.3) — Ji et al.'s Algorithm 1
|
|
3
|
+
* (*Memory is Reconstructed, Not Retrieved*, 2026) as a functional loop
|
|
4
|
+
* over the CAVE graph:
|
|
5
|
+
*
|
|
6
|
+
* - **Cues** are entities used as query anchors;
|
|
7
|
+
* - **route**: expanding a cue collects its claims (content) and pushes
|
|
8
|
+
* scored neighbors — forward edges, named inverse edges, and topic
|
|
9
|
+
* containment in both directions (ϕτ→e and ϕv→(c,g)) — onto the
|
|
10
|
+
* frontier;
|
|
11
|
+
* - **select / stop** are policy decisions, injected — the loop itself is
|
|
12
|
+
* deliberately outside the language (spec §18).
|
|
13
|
+
*
|
|
14
|
+
* The loop comes in two shapes sharing one step core: `reconstruct` for
|
|
15
|
+
* synchronous policies (the deterministic heuristic), `reconstructAsync`
|
|
16
|
+
* for policies that await a model between steps (`llmPolicy`).
|
|
17
|
+
*/
|
|
18
|
+
import { Claim } from '@cavelang/core';
|
|
19
|
+
import type { CaveStore, Edge } from './store.ts';
|
|
20
|
+
/** A scored frontier entry. */
|
|
21
|
+
export type Cue = {
|
|
22
|
+
readonly entity: string;
|
|
23
|
+
readonly score: number;
|
|
24
|
+
readonly depth: number;
|
|
25
|
+
};
|
|
26
|
+
export type State = {
|
|
27
|
+
readonly frontier: readonly Cue[];
|
|
28
|
+
readonly visited: ReadonlySet<string>;
|
|
29
|
+
readonly collected: readonly Claim.t[];
|
|
30
|
+
readonly steps: number;
|
|
31
|
+
};
|
|
32
|
+
/** Injectable policy: select the next cue, score neighbors, decide to stop. */
|
|
33
|
+
export type Policy = {
|
|
34
|
+
/** Next cue to expand, `undefined` to stop. Must pick from `state.frontier`. */
|
|
35
|
+
select(state: State): undefined | Cue;
|
|
36
|
+
/** Frontier score of a neighbor reached via `edge` from `from`. */
|
|
37
|
+
score(edge: Edge, from: Cue): number;
|
|
38
|
+
/** Stop condition, checked before every step. */
|
|
39
|
+
done(state: State): boolean;
|
|
40
|
+
};
|
|
41
|
+
/** Async twin of `Policy` for LLM-backed implementations (`llmPolicy`). */
|
|
42
|
+
export type AsyncPolicy = {
|
|
43
|
+
select(state: State): Promise<undefined | Cue>;
|
|
44
|
+
score(edge: Edge, from: Cue): Promise<number>;
|
|
45
|
+
done(state: State): Promise<boolean>;
|
|
46
|
+
};
|
|
47
|
+
export type Step = {
|
|
48
|
+
readonly step: number;
|
|
49
|
+
readonly cue: Cue;
|
|
50
|
+
readonly edges: readonly Edge[];
|
|
51
|
+
readonly collected: number;
|
|
52
|
+
};
|
|
53
|
+
export type Reconstruction = {
|
|
54
|
+
/** Deduplicated claims, in discovery order. */
|
|
55
|
+
readonly claims: readonly Claim.t[];
|
|
56
|
+
readonly trace: readonly Step[];
|
|
57
|
+
readonly state: State;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Runs the loop from seed entities until the policy stops or the frontier
|
|
61
|
+
* empties. Pure given its inputs — same store + policy + seeds, same
|
|
62
|
+
* reconstruction.
|
|
63
|
+
*/
|
|
64
|
+
export declare const reconstruct: (store: CaveStore, policy: Policy, seeds: readonly string[]) => Reconstruction;
|
|
65
|
+
/**
|
|
66
|
+
* The async twin of `reconstruct`, for policies that await a model between
|
|
67
|
+
* steps (spec §18): same algorithm, same trace, decisions awaited.
|
|
68
|
+
*/
|
|
69
|
+
export declare const reconstructAsync: (store: CaveStore, policy: AsyncPolicy, seeds: readonly string[]) => Promise<Reconstruction>;
|
|
70
|
+
export type HeuristicOptions = {
|
|
71
|
+
/** Per-hop score decay (default 0.8). */
|
|
72
|
+
readonly decay?: number;
|
|
73
|
+
/** Hard step budget (default 16). */
|
|
74
|
+
readonly maxSteps?: number;
|
|
75
|
+
/** Cues scoring below this are never selected (default 0.05). */
|
|
76
|
+
readonly minScore?: number;
|
|
77
|
+
/** Stop once this many claims are collected (default ∞). */
|
|
78
|
+
readonly maxClaims?: number;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Deterministic heuristic policy for dependency-free testing (spec §18):
|
|
82
|
+
* greedy best-first by score (FIFO tiebreak), score = parent score ×
|
|
83
|
+
* edge confidence × decay, hard budgets for steps and claims. Also the
|
|
84
|
+
* eval baseline the LLM policy is measured against (spec §18).
|
|
85
|
+
*/
|
|
86
|
+
export declare const heuristicPolicy: (options?: HeuristicOptions) => Policy;
|
|
87
|
+
//# sourceMappingURL=reconstruct.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconstruct.d.ts","sourceRoot":"","sources":["../../src/reconstruct.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,KAAK,EAAO,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEjD,+BAA+B;AAC/B,MAAM,MAAM,GAAG,GAAG;IAChB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,EAAE,CAAA;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC,EAAE,CAAA;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,+EAA+E;AAC/E,MAAM,MAAM,MAAM,GAAG;IACnB,gFAAgF;IAChF,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,GAAG,CAAA;IACrC,mEAAmE;IACnE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,GAAG,MAAM,CAAA;IACpC,iDAAiD;IACjD,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAA;CAC5B,CAAA;AAED,2EAA2E;AAC3E,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,SAAS,GAAG,GAAG,CAAC,CAAA;IAC9C,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7C,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IACjB,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,CAAC,EAAE,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CACtB,CAAA;AA0FD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,SAAS,EAAE,QAAQ,MAAM,EAAE,OAAO,SAAS,MAAM,EAAE,KAAG,cAWxF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAC3B,OAAO,SAAS,EAChB,QAAQ,WAAW,EACnB,OAAO,SAAS,MAAM,EAAE,KACvB,OAAO,CAAC,cAAc,CAexB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,UAAS,gBAAqB,KAAG,MAyBhE,CAAA"}
|