@vpxa/kb 0.1.1
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/LICENSE +21 -0
- package/README.md +1140 -0
- package/bin/kb.mjs +10 -0
- package/package.json +67 -0
- package/packages/analyzers/dist/blast-radius-analyzer.d.ts +23 -0
- package/packages/analyzers/dist/blast-radius-analyzer.js +114 -0
- package/packages/analyzers/dist/dependency-analyzer.d.ts +29 -0
- package/packages/analyzers/dist/dependency-analyzer.js +425 -0
- package/packages/analyzers/dist/diagram-generator.d.ts +13 -0
- package/packages/analyzers/dist/diagram-generator.js +86 -0
- package/packages/analyzers/dist/entry-point-analyzer.d.ts +19 -0
- package/packages/analyzers/dist/entry-point-analyzer.js +239 -0
- package/packages/analyzers/dist/index.d.ts +14 -0
- package/packages/analyzers/dist/index.js +23 -0
- package/packages/analyzers/dist/knowledge-producer.d.ts +32 -0
- package/packages/analyzers/dist/knowledge-producer.js +113 -0
- package/packages/analyzers/dist/pattern-analyzer.d.ts +12 -0
- package/packages/analyzers/dist/pattern-analyzer.js +359 -0
- package/packages/analyzers/dist/regex-call-graph.d.ts +17 -0
- package/packages/analyzers/dist/regex-call-graph.js +428 -0
- package/packages/analyzers/dist/structure-analyzer.d.ts +11 -0
- package/packages/analyzers/dist/structure-analyzer.js +258 -0
- package/packages/analyzers/dist/symbol-analyzer.d.ts +10 -0
- package/packages/analyzers/dist/symbol-analyzer.js +442 -0
- package/packages/analyzers/dist/ts-call-graph.d.ts +27 -0
- package/packages/analyzers/dist/ts-call-graph.js +160 -0
- package/packages/analyzers/dist/types.d.ts +98 -0
- package/packages/analyzers/dist/types.js +1 -0
- package/packages/chunker/dist/call-graph-extractor.d.ts +22 -0
- package/packages/chunker/dist/call-graph-extractor.js +90 -0
- package/packages/chunker/dist/chunker-factory.d.ts +7 -0
- package/packages/chunker/dist/chunker-factory.js +36 -0
- package/packages/chunker/dist/chunker.interface.d.ts +10 -0
- package/packages/chunker/dist/chunker.interface.js +1 -0
- package/packages/chunker/dist/code-chunker.d.ts +14 -0
- package/packages/chunker/dist/code-chunker.js +134 -0
- package/packages/chunker/dist/generic-chunker.d.ts +12 -0
- package/packages/chunker/dist/generic-chunker.js +72 -0
- package/packages/chunker/dist/index.d.ts +8 -0
- package/packages/chunker/dist/index.js +21 -0
- package/packages/chunker/dist/markdown-chunker.d.ts +14 -0
- package/packages/chunker/dist/markdown-chunker.js +122 -0
- package/packages/chunker/dist/treesitter-chunker.d.ts +47 -0
- package/packages/chunker/dist/treesitter-chunker.js +234 -0
- package/packages/cli/dist/commands/analyze.d.ts +3 -0
- package/packages/cli/dist/commands/analyze.js +112 -0
- package/packages/cli/dist/commands/context-cmds.d.ts +3 -0
- package/packages/cli/dist/commands/context-cmds.js +155 -0
- package/packages/cli/dist/commands/environment.d.ts +3 -0
- package/packages/cli/dist/commands/environment.js +204 -0
- package/packages/cli/dist/commands/execution.d.ts +3 -0
- package/packages/cli/dist/commands/execution.js +137 -0
- package/packages/cli/dist/commands/graph.d.ts +3 -0
- package/packages/cli/dist/commands/graph.js +81 -0
- package/packages/cli/dist/commands/init.d.ts +8 -0
- package/packages/cli/dist/commands/init.js +87 -0
- package/packages/cli/dist/commands/knowledge.d.ts +3 -0
- package/packages/cli/dist/commands/knowledge.js +139 -0
- package/packages/cli/dist/commands/search.d.ts +3 -0
- package/packages/cli/dist/commands/search.js +267 -0
- package/packages/cli/dist/commands/system.d.ts +3 -0
- package/packages/cli/dist/commands/system.js +241 -0
- package/packages/cli/dist/commands/workspace.d.ts +3 -0
- package/packages/cli/dist/commands/workspace.js +388 -0
- package/packages/cli/dist/context.d.ts +5 -0
- package/packages/cli/dist/context.js +14 -0
- package/packages/cli/dist/helpers.d.ts +52 -0
- package/packages/cli/dist/helpers.js +458 -0
- package/packages/cli/dist/index.d.ts +8 -0
- package/packages/cli/dist/index.js +69 -0
- package/packages/cli/dist/kb-init.d.ts +57 -0
- package/packages/cli/dist/kb-init.js +82 -0
- package/packages/cli/dist/types.d.ts +7 -0
- package/packages/cli/dist/types.js +1 -0
- package/packages/core/dist/constants.d.ts +49 -0
- package/packages/core/dist/constants.js +43 -0
- package/packages/core/dist/content-detector.d.ts +9 -0
- package/packages/core/dist/content-detector.js +79 -0
- package/packages/core/dist/errors.d.ts +18 -0
- package/packages/core/dist/errors.js +40 -0
- package/packages/core/dist/index.d.ts +6 -0
- package/packages/core/dist/index.js +9 -0
- package/packages/core/dist/logger.d.ts +9 -0
- package/packages/core/dist/logger.js +34 -0
- package/packages/core/dist/types.d.ts +108 -0
- package/packages/core/dist/types.js +1 -0
- package/packages/embeddings/dist/embedder.interface.d.ts +24 -0
- package/packages/embeddings/dist/embedder.interface.js +1 -0
- package/packages/embeddings/dist/index.d.ts +3 -0
- package/packages/embeddings/dist/index.js +5 -0
- package/packages/embeddings/dist/onnx-embedder.d.ts +24 -0
- package/packages/embeddings/dist/onnx-embedder.js +82 -0
- package/packages/indexer/dist/file-hasher.d.ts +11 -0
- package/packages/indexer/dist/file-hasher.js +13 -0
- package/packages/indexer/dist/filesystem-crawler.d.ts +27 -0
- package/packages/indexer/dist/filesystem-crawler.js +125 -0
- package/packages/indexer/dist/graph-extractor.d.ts +22 -0
- package/packages/indexer/dist/graph-extractor.js +111 -0
- package/packages/indexer/dist/incremental-indexer.d.ts +47 -0
- package/packages/indexer/dist/incremental-indexer.js +278 -0
- package/packages/indexer/dist/index.d.ts +5 -0
- package/packages/indexer/dist/index.js +14 -0
- package/packages/server/dist/api.d.ts +8 -0
- package/packages/server/dist/api.js +9 -0
- package/packages/server/dist/config.d.ts +3 -0
- package/packages/server/dist/config.js +75 -0
- package/packages/server/dist/curated-manager.d.ts +86 -0
- package/packages/server/dist/curated-manager.js +357 -0
- package/packages/server/dist/index.d.ts +2 -0
- package/packages/server/dist/index.js +134 -0
- package/packages/server/dist/replay-interceptor.d.ts +11 -0
- package/packages/server/dist/replay-interceptor.js +38 -0
- package/packages/server/dist/resources/resources.d.ts +4 -0
- package/packages/server/dist/resources/resources.js +40 -0
- package/packages/server/dist/server.d.ts +21 -0
- package/packages/server/dist/server.js +247 -0
- package/packages/server/dist/tools/analyze.tools.d.ts +11 -0
- package/packages/server/dist/tools/analyze.tools.js +288 -0
- package/packages/server/dist/tools/forge.tools.d.ts +12 -0
- package/packages/server/dist/tools/forge.tools.js +501 -0
- package/packages/server/dist/tools/forget.tool.d.ts +4 -0
- package/packages/server/dist/tools/forget.tool.js +43 -0
- package/packages/server/dist/tools/graph.tool.d.ts +4 -0
- package/packages/server/dist/tools/graph.tool.js +110 -0
- package/packages/server/dist/tools/list.tool.d.ts +4 -0
- package/packages/server/dist/tools/list.tool.js +56 -0
- package/packages/server/dist/tools/lookup.tool.d.ts +4 -0
- package/packages/server/dist/tools/lookup.tool.js +53 -0
- package/packages/server/dist/tools/onboard.tool.d.ts +5 -0
- package/packages/server/dist/tools/onboard.tool.js +112 -0
- package/packages/server/dist/tools/produce.tool.d.ts +3 -0
- package/packages/server/dist/tools/produce.tool.js +74 -0
- package/packages/server/dist/tools/read.tool.d.ts +4 -0
- package/packages/server/dist/tools/read.tool.js +49 -0
- package/packages/server/dist/tools/reindex.tool.d.ts +7 -0
- package/packages/server/dist/tools/reindex.tool.js +70 -0
- package/packages/server/dist/tools/remember.tool.d.ts +4 -0
- package/packages/server/dist/tools/remember.tool.js +45 -0
- package/packages/server/dist/tools/replay.tool.d.ts +3 -0
- package/packages/server/dist/tools/replay.tool.js +89 -0
- package/packages/server/dist/tools/search.tool.d.ts +5 -0
- package/packages/server/dist/tools/search.tool.js +331 -0
- package/packages/server/dist/tools/status.tool.d.ts +4 -0
- package/packages/server/dist/tools/status.tool.js +68 -0
- package/packages/server/dist/tools/toolkit.tools.d.ts +35 -0
- package/packages/server/dist/tools/toolkit.tools.js +1674 -0
- package/packages/server/dist/tools/update.tool.d.ts +4 -0
- package/packages/server/dist/tools/update.tool.js +42 -0
- package/packages/server/dist/tools/utility.tools.d.ts +15 -0
- package/packages/server/dist/tools/utility.tools.js +461 -0
- package/packages/store/dist/graph-store.interface.d.ts +104 -0
- package/packages/store/dist/graph-store.interface.js +1 -0
- package/packages/store/dist/index.d.ts +6 -0
- package/packages/store/dist/index.js +9 -0
- package/packages/store/dist/lance-store.d.ts +32 -0
- package/packages/store/dist/lance-store.js +258 -0
- package/packages/store/dist/sqlite-graph-store.d.ts +43 -0
- package/packages/store/dist/sqlite-graph-store.js +374 -0
- package/packages/store/dist/store-factory.d.ts +9 -0
- package/packages/store/dist/store-factory.js +14 -0
- package/packages/store/dist/store.interface.d.ts +48 -0
- package/packages/store/dist/store.interface.js +1 -0
- package/packages/tools/dist/batch.d.ts +21 -0
- package/packages/tools/dist/batch.js +45 -0
- package/packages/tools/dist/changelog.d.ts +34 -0
- package/packages/tools/dist/changelog.js +112 -0
- package/packages/tools/dist/check.d.ts +26 -0
- package/packages/tools/dist/check.js +59 -0
- package/packages/tools/dist/checkpoint.d.ts +17 -0
- package/packages/tools/dist/checkpoint.js +43 -0
- package/packages/tools/dist/codemod.d.ts +37 -0
- package/packages/tools/dist/codemod.js +69 -0
- package/packages/tools/dist/compact.d.ts +41 -0
- package/packages/tools/dist/compact.js +60 -0
- package/packages/tools/dist/data-transform.d.ts +10 -0
- package/packages/tools/dist/data-transform.js +124 -0
- package/packages/tools/dist/dead-symbols.d.ts +21 -0
- package/packages/tools/dist/dead-symbols.js +71 -0
- package/packages/tools/dist/delegate.d.ts +34 -0
- package/packages/tools/dist/delegate.js +130 -0
- package/packages/tools/dist/diff-parse.d.ts +26 -0
- package/packages/tools/dist/diff-parse.js +153 -0
- package/packages/tools/dist/digest.d.ts +53 -0
- package/packages/tools/dist/digest.js +242 -0
- package/packages/tools/dist/encode.d.ts +14 -0
- package/packages/tools/dist/encode.js +46 -0
- package/packages/tools/dist/env-info.d.ts +28 -0
- package/packages/tools/dist/env-info.js +58 -0
- package/packages/tools/dist/eval.d.ts +13 -0
- package/packages/tools/dist/eval.js +79 -0
- package/packages/tools/dist/evidence-map.d.ts +79 -0
- package/packages/tools/dist/evidence-map.js +203 -0
- package/packages/tools/dist/file-summary.d.ts +32 -0
- package/packages/tools/dist/file-summary.js +106 -0
- package/packages/tools/dist/file-walk.d.ts +4 -0
- package/packages/tools/dist/file-walk.js +75 -0
- package/packages/tools/dist/find-examples.d.ts +25 -0
- package/packages/tools/dist/find-examples.js +48 -0
- package/packages/tools/dist/find.d.ts +47 -0
- package/packages/tools/dist/find.js +120 -0
- package/packages/tools/dist/forge-classify.d.ts +44 -0
- package/packages/tools/dist/forge-classify.js +319 -0
- package/packages/tools/dist/forge-ground.d.ts +64 -0
- package/packages/tools/dist/forge-ground.js +184 -0
- package/packages/tools/dist/git-context.d.ts +22 -0
- package/packages/tools/dist/git-context.js +46 -0
- package/packages/tools/dist/graph-query.d.ts +89 -0
- package/packages/tools/dist/graph-query.js +194 -0
- package/packages/tools/dist/health.d.ts +14 -0
- package/packages/tools/dist/health.js +118 -0
- package/packages/tools/dist/http-request.d.ts +23 -0
- package/packages/tools/dist/http-request.js +58 -0
- package/packages/tools/dist/index.d.ts +49 -0
- package/packages/tools/dist/index.js +273 -0
- package/packages/tools/dist/lane.d.ts +39 -0
- package/packages/tools/dist/lane.js +227 -0
- package/packages/tools/dist/measure.d.ts +38 -0
- package/packages/tools/dist/measure.js +119 -0
- package/packages/tools/dist/onboard.d.ts +41 -0
- package/packages/tools/dist/onboard.js +1139 -0
- package/packages/tools/dist/parse-output.d.ts +80 -0
- package/packages/tools/dist/parse-output.js +158 -0
- package/packages/tools/dist/process-manager.d.ts +18 -0
- package/packages/tools/dist/process-manager.js +69 -0
- package/packages/tools/dist/queue.d.ts +38 -0
- package/packages/tools/dist/queue.js +126 -0
- package/packages/tools/dist/regex-test.d.ts +31 -0
- package/packages/tools/dist/regex-test.js +39 -0
- package/packages/tools/dist/rename.d.ts +29 -0
- package/packages/tools/dist/rename.js +70 -0
- package/packages/tools/dist/replay.d.ts +56 -0
- package/packages/tools/dist/replay.js +108 -0
- package/packages/tools/dist/schema-validate.d.ts +23 -0
- package/packages/tools/dist/schema-validate.js +141 -0
- package/packages/tools/dist/scope-map.d.ts +52 -0
- package/packages/tools/dist/scope-map.js +72 -0
- package/packages/tools/dist/snippet.d.ts +34 -0
- package/packages/tools/dist/snippet.js +80 -0
- package/packages/tools/dist/stash.d.ts +12 -0
- package/packages/tools/dist/stash.js +60 -0
- package/packages/tools/dist/stratum-card.d.ts +31 -0
- package/packages/tools/dist/stratum-card.js +239 -0
- package/packages/tools/dist/symbol.d.ts +28 -0
- package/packages/tools/dist/symbol.js +87 -0
- package/packages/tools/dist/test-run.d.ts +23 -0
- package/packages/tools/dist/test-run.js +55 -0
- package/packages/tools/dist/text-utils.d.ts +16 -0
- package/packages/tools/dist/text-utils.js +31 -0
- package/packages/tools/dist/time-utils.d.ts +18 -0
- package/packages/tools/dist/time-utils.js +135 -0
- package/packages/tools/dist/trace.d.ts +24 -0
- package/packages/tools/dist/trace.js +114 -0
- package/packages/tools/dist/truncation.d.ts +22 -0
- package/packages/tools/dist/truncation.js +45 -0
- package/packages/tools/dist/watch.d.ts +30 -0
- package/packages/tools/dist/watch.js +61 -0
- package/packages/tools/dist/web-fetch.d.ts +45 -0
- package/packages/tools/dist/web-fetch.js +249 -0
- package/packages/tools/dist/web-search.d.ts +23 -0
- package/packages/tools/dist/web-search.js +46 -0
- package/packages/tools/dist/workset.d.ts +45 -0
- package/packages/tools/dist/workset.js +77 -0
- package/packages/tui/dist/App.d.ts +8 -0
- package/packages/tui/dist/App.js +52659 -0
- package/packages/tui/dist/index.d.ts +19 -0
- package/packages/tui/dist/index.js +54742 -0
- package/packages/tui/dist/panels/CuratedPanel.d.ts +8 -0
- package/packages/tui/dist/panels/CuratedPanel.js +34452 -0
- package/packages/tui/dist/panels/LogPanel.d.ts +3 -0
- package/packages/tui/dist/panels/LogPanel.js +51894 -0
- package/packages/tui/dist/panels/SearchPanel.d.ts +10 -0
- package/packages/tui/dist/panels/SearchPanel.js +34985 -0
- package/packages/tui/dist/panels/StatusPanel.d.ts +8 -0
- package/packages/tui/dist/panels/StatusPanel.js +34465 -0
- package/skills/knowledge-base/SKILL.md +316 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replay — append-only audit trail of tool/CLI invocations.
|
|
3
|
+
*
|
|
4
|
+
* Captures tool name, arguments (redacted), duration, and result summary
|
|
5
|
+
* to `.kb-state/replay.jsonl`. Used by `kb replay` CLI, `kb_replay_list` MCP,
|
|
6
|
+
* and the TUI log panel.
|
|
7
|
+
*/
|
|
8
|
+
export interface ReplayEntry {
|
|
9
|
+
/** ISO timestamp */
|
|
10
|
+
ts: string;
|
|
11
|
+
/** Source: 'mcp' | 'cli' */
|
|
12
|
+
source: 'mcp' | 'cli';
|
|
13
|
+
/** Tool or command name */
|
|
14
|
+
tool: string;
|
|
15
|
+
/** Redacted input summary (first 200 chars of JSON) */
|
|
16
|
+
input: string;
|
|
17
|
+
/** Duration in milliseconds */
|
|
18
|
+
durationMs: number;
|
|
19
|
+
/** Result status */
|
|
20
|
+
status: 'ok' | 'error';
|
|
21
|
+
/** Short result summary (first 200 chars) */
|
|
22
|
+
output: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ReplayOptions {
|
|
25
|
+
/** Max entries to return (default: 20) */
|
|
26
|
+
last?: number;
|
|
27
|
+
/** Filter by tool name */
|
|
28
|
+
tool?: string;
|
|
29
|
+
/** Filter by source */
|
|
30
|
+
source?: 'mcp' | 'cli';
|
|
31
|
+
/** Filter entries after this ISO timestamp */
|
|
32
|
+
since?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Append a replay entry to the audit log.
|
|
36
|
+
* Creates the `.kb-state/` directory if it doesn't exist.
|
|
37
|
+
*/
|
|
38
|
+
export declare function replayAppend(entry: ReplayEntry): void;
|
|
39
|
+
/**
|
|
40
|
+
* Read replay entries with optional filters.
|
|
41
|
+
*/
|
|
42
|
+
export declare function replayList(opts?: ReplayOptions): ReplayEntry[];
|
|
43
|
+
/**
|
|
44
|
+
* Trim the replay log to MAX_ENTRIES, keeping the most recent.
|
|
45
|
+
*/
|
|
46
|
+
export declare function replayTrim(): number;
|
|
47
|
+
/**
|
|
48
|
+
* Clear the entire replay log.
|
|
49
|
+
*/
|
|
50
|
+
export declare function replayClear(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Helper: create a replay entry from a tool invocation.
|
|
53
|
+
* Use as a wrapper around tool execution.
|
|
54
|
+
*/
|
|
55
|
+
export declare function replayCapture(source: 'mcp' | 'cli', tool: string, input: unknown, fn: () => Promise<unknown>): Promise<unknown>;
|
|
56
|
+
//# sourceMappingURL=replay.d.ts.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { appendFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
const MAX_ENTRIES = 5e3;
|
|
4
|
+
const SUMMARY_LEN = 200;
|
|
5
|
+
function getReplayPath() {
|
|
6
|
+
return resolve(process.cwd(), ".kb-state", "replay.jsonl");
|
|
7
|
+
}
|
|
8
|
+
function truncate(s, maxLen) {
|
|
9
|
+
if (s.length <= maxLen) return s;
|
|
10
|
+
return `${s.slice(0, maxLen - 1)}\u2026`;
|
|
11
|
+
}
|
|
12
|
+
function replayAppend(entry) {
|
|
13
|
+
const p = getReplayPath();
|
|
14
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
15
|
+
const safe = {
|
|
16
|
+
...entry,
|
|
17
|
+
input: truncate(entry.input, SUMMARY_LEN),
|
|
18
|
+
output: truncate(entry.output, SUMMARY_LEN)
|
|
19
|
+
};
|
|
20
|
+
appendFileSync(p, `${JSON.stringify(safe)}
|
|
21
|
+
`, "utf-8");
|
|
22
|
+
}
|
|
23
|
+
function replayList(opts = {}) {
|
|
24
|
+
const p = getReplayPath();
|
|
25
|
+
let raw;
|
|
26
|
+
try {
|
|
27
|
+
raw = readFileSync(p, "utf-8");
|
|
28
|
+
} catch {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
const lines = raw.trim().split("\n").filter(Boolean);
|
|
32
|
+
let entries = [];
|
|
33
|
+
for (const line of lines) {
|
|
34
|
+
try {
|
|
35
|
+
entries.push(JSON.parse(line));
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (opts.tool) {
|
|
40
|
+
entries = entries.filter((e) => e.tool === opts.tool);
|
|
41
|
+
}
|
|
42
|
+
if (opts.source) {
|
|
43
|
+
entries = entries.filter((e) => e.source === opts.source);
|
|
44
|
+
}
|
|
45
|
+
if (opts.since) {
|
|
46
|
+
const since = opts.since;
|
|
47
|
+
entries = entries.filter((e) => e.ts >= since);
|
|
48
|
+
}
|
|
49
|
+
const last = opts.last ?? 20;
|
|
50
|
+
return entries.slice(-last);
|
|
51
|
+
}
|
|
52
|
+
function replayTrim() {
|
|
53
|
+
const p = getReplayPath();
|
|
54
|
+
let raw;
|
|
55
|
+
try {
|
|
56
|
+
raw = readFileSync(p, "utf-8");
|
|
57
|
+
} catch {
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
const lines = raw.trim().split("\n").filter(Boolean);
|
|
61
|
+
if (lines.length <= MAX_ENTRIES) return 0;
|
|
62
|
+
const trimmed = lines.length - MAX_ENTRIES;
|
|
63
|
+
const kept = lines.slice(-MAX_ENTRIES);
|
|
64
|
+
writeFileSync(p, `${kept.join("\n")}
|
|
65
|
+
`, "utf-8");
|
|
66
|
+
return trimmed;
|
|
67
|
+
}
|
|
68
|
+
function replayClear() {
|
|
69
|
+
const p = getReplayPath();
|
|
70
|
+
try {
|
|
71
|
+
writeFileSync(p, "", "utf-8");
|
|
72
|
+
} catch {
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function replayCapture(source, tool, input, fn) {
|
|
76
|
+
const start = Date.now();
|
|
77
|
+
return fn().then((result) => {
|
|
78
|
+
replayAppend({
|
|
79
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
80
|
+
source,
|
|
81
|
+
tool,
|
|
82
|
+
input: typeof input === "string" ? input : JSON.stringify(input),
|
|
83
|
+
durationMs: Date.now() - start,
|
|
84
|
+
status: "ok",
|
|
85
|
+
output: typeof result === "string" ? result : JSON.stringify(result ?? "")
|
|
86
|
+
});
|
|
87
|
+
return result;
|
|
88
|
+
}).catch((err) => {
|
|
89
|
+
replayAppend({
|
|
90
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
91
|
+
source,
|
|
92
|
+
tool,
|
|
93
|
+
input: typeof input === "string" ? input : JSON.stringify(input),
|
|
94
|
+
durationMs: Date.now() - start,
|
|
95
|
+
status: "error",
|
|
96
|
+
output: err instanceof Error ? err.message : String(err)
|
|
97
|
+
});
|
|
98
|
+
throw err;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
replayAppend,
|
|
103
|
+
replayCapture,
|
|
104
|
+
replayClear,
|
|
105
|
+
replayList,
|
|
106
|
+
replayTrim
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=replay.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kb_schema_validate — Validate data against a JSON Schema (core subset).
|
|
3
|
+
*
|
|
4
|
+
* Supports: type, required, properties, additionalProperties, items,
|
|
5
|
+
* enum, const, pattern, minimum, maximum, minLength, maxLength,
|
|
6
|
+
* minItems, maxItems.
|
|
7
|
+
*/
|
|
8
|
+
export interface SchemaValidateOptions {
|
|
9
|
+
data: unknown;
|
|
10
|
+
schema: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
export interface ValidationError {
|
|
13
|
+
path: string;
|
|
14
|
+
message: string;
|
|
15
|
+
expected?: string;
|
|
16
|
+
received?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface SchemaValidateResult {
|
|
19
|
+
valid: boolean;
|
|
20
|
+
errors: ValidationError[];
|
|
21
|
+
}
|
|
22
|
+
export declare function schemaValidate(options: SchemaValidateOptions): SchemaValidateResult;
|
|
23
|
+
//# sourceMappingURL=schema-validate.d.ts.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
function schemaValidate(options) {
|
|
2
|
+
const errors = [];
|
|
3
|
+
validateNode(options.data, options.schema, "$", errors);
|
|
4
|
+
return { valid: errors.length === 0, errors };
|
|
5
|
+
}
|
|
6
|
+
function validateNode(data, schema, path, errors) {
|
|
7
|
+
if ("type" in schema) {
|
|
8
|
+
const expected = schema.type;
|
|
9
|
+
if (!checkType(data, expected)) {
|
|
10
|
+
errors.push({
|
|
11
|
+
path,
|
|
12
|
+
message: `Expected type "${expected}"`,
|
|
13
|
+
expected,
|
|
14
|
+
received: getType(data)
|
|
15
|
+
});
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if ("enum" in schema) {
|
|
20
|
+
const allowed = schema.enum;
|
|
21
|
+
if (!allowed.some((v) => JSON.stringify(v) === JSON.stringify(data))) {
|
|
22
|
+
errors.push({
|
|
23
|
+
path,
|
|
24
|
+
message: `Must be one of: ${JSON.stringify(allowed)}`,
|
|
25
|
+
received: JSON.stringify(data)
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if ("const" in schema) {
|
|
30
|
+
if (JSON.stringify(data) !== JSON.stringify(schema.const)) {
|
|
31
|
+
errors.push({
|
|
32
|
+
path,
|
|
33
|
+
message: `Must equal ${JSON.stringify(schema.const)}`,
|
|
34
|
+
received: JSON.stringify(data)
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (typeof data === "string") {
|
|
39
|
+
if ("minLength" in schema && data.length < schema.minLength) {
|
|
40
|
+
errors.push({
|
|
41
|
+
path,
|
|
42
|
+
message: `String too short (min: ${schema.minLength})`,
|
|
43
|
+
received: `length ${data.length}`
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if ("maxLength" in schema && data.length > schema.maxLength) {
|
|
47
|
+
errors.push({
|
|
48
|
+
path,
|
|
49
|
+
message: `String too long (max: ${schema.maxLength})`,
|
|
50
|
+
received: `length ${data.length}`
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if ("pattern" in schema && !new RegExp(schema.pattern).test(data)) {
|
|
54
|
+
errors.push({ path, message: `Does not match pattern: ${schema.pattern}` });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (typeof data === "number") {
|
|
58
|
+
if ("minimum" in schema && data < schema.minimum) {
|
|
59
|
+
errors.push({ path, message: `Below minimum (${schema.minimum})`, received: String(data) });
|
|
60
|
+
}
|
|
61
|
+
if ("maximum" in schema && data > schema.maximum) {
|
|
62
|
+
errors.push({ path, message: `Above maximum (${schema.maximum})`, received: String(data) });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (Array.isArray(data)) {
|
|
66
|
+
if ("minItems" in schema && data.length < schema.minItems) {
|
|
67
|
+
errors.push({
|
|
68
|
+
path,
|
|
69
|
+
message: `Too few items (min: ${schema.minItems})`,
|
|
70
|
+
received: `length ${data.length}`
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if ("maxItems" in schema && data.length > schema.maxItems) {
|
|
74
|
+
errors.push({
|
|
75
|
+
path,
|
|
76
|
+
message: `Too many items (max: ${schema.maxItems})`,
|
|
77
|
+
received: `length ${data.length}`
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if ("items" in schema) {
|
|
81
|
+
for (let i = 0; i < data.length; i++) {
|
|
82
|
+
validateNode(data[i], schema.items, `${path}[${i}]`, errors);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
87
|
+
const obj = data;
|
|
88
|
+
if ("required" in schema) {
|
|
89
|
+
for (const key of schema.required) {
|
|
90
|
+
if (!(key in obj)) {
|
|
91
|
+
errors.push({ path: `${path}.${key}`, message: "Required property missing" });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if ("properties" in schema) {
|
|
96
|
+
const props = schema.properties;
|
|
97
|
+
for (const [key, propSchema] of Object.entries(props)) {
|
|
98
|
+
if (key in obj) {
|
|
99
|
+
validateNode(obj[key], propSchema, `${path}.${key}`, errors);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if ("additionalProperties" in schema && schema.additionalProperties === false) {
|
|
104
|
+
const defined = Object.keys(schema.properties ?? {});
|
|
105
|
+
for (const key of Object.keys(obj)) {
|
|
106
|
+
if (!defined.includes(key)) {
|
|
107
|
+
errors.push({ path: `${path}.${key}`, message: "Additional property not allowed" });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function checkType(data, type) {
|
|
114
|
+
switch (type) {
|
|
115
|
+
case "string":
|
|
116
|
+
return typeof data === "string";
|
|
117
|
+
case "number":
|
|
118
|
+
return typeof data === "number" && !Number.isNaN(data);
|
|
119
|
+
case "integer":
|
|
120
|
+
return typeof data === "number" && Number.isInteger(data);
|
|
121
|
+
case "boolean":
|
|
122
|
+
return typeof data === "boolean";
|
|
123
|
+
case "null":
|
|
124
|
+
return data === null;
|
|
125
|
+
case "array":
|
|
126
|
+
return Array.isArray(data);
|
|
127
|
+
case "object":
|
|
128
|
+
return data !== null && typeof data === "object" && !Array.isArray(data);
|
|
129
|
+
default:
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function getType(data) {
|
|
134
|
+
if (data === null) return "null";
|
|
135
|
+
if (Array.isArray(data)) return "array";
|
|
136
|
+
return typeof data;
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
schemaValidate
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=schema-validate.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kb_scope_map — Task-scoped reading plan generator.
|
|
3
|
+
*
|
|
4
|
+
* Given a task description, searches the KB to identify which files
|
|
5
|
+
* and sections are relevant, then produces a prioritized reading plan
|
|
6
|
+
* with estimated token counts.
|
|
7
|
+
*/
|
|
8
|
+
import type { IEmbedder } from '@kb/embeddings';
|
|
9
|
+
import type { IKnowledgeStore } from '@kb/store';
|
|
10
|
+
export interface ScopeMapOptions {
|
|
11
|
+
/** Description of the task to scope */
|
|
12
|
+
task: string;
|
|
13
|
+
/** Maximum number of files to include (default: 15) */
|
|
14
|
+
maxFiles?: number;
|
|
15
|
+
/** Group results by directory (default: true) */
|
|
16
|
+
groupByDirectory?: boolean;
|
|
17
|
+
/** Filter by content type */
|
|
18
|
+
contentType?: string;
|
|
19
|
+
/** Filter by origin */
|
|
20
|
+
origin?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ScopeMapEntry {
|
|
23
|
+
/** File path */
|
|
24
|
+
path: string;
|
|
25
|
+
/** Why this file is relevant (derived from matched chunks) */
|
|
26
|
+
reason: string;
|
|
27
|
+
/** Estimated token count (chars / 4 approximation) */
|
|
28
|
+
estimatedTokens: number;
|
|
29
|
+
/** Relevance score (0-1) */
|
|
30
|
+
relevance: number;
|
|
31
|
+
/** Line ranges to focus on */
|
|
32
|
+
focusRanges: Array<{
|
|
33
|
+
start: number;
|
|
34
|
+
end: number;
|
|
35
|
+
heading?: string;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
export interface ScopeMapResult {
|
|
39
|
+
/** The task that was analyzed */
|
|
40
|
+
task: string;
|
|
41
|
+
/** Prioritized file list */
|
|
42
|
+
files: ScopeMapEntry[];
|
|
43
|
+
/** Total estimated tokens across all files */
|
|
44
|
+
totalEstimatedTokens: number;
|
|
45
|
+
/** Suggested reading order (file paths) */
|
|
46
|
+
readingOrder: string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generate a task-scoped reading plan.
|
|
50
|
+
*/
|
|
51
|
+
export declare function scopeMap(embedder: IEmbedder, store: IKnowledgeStore, options: ScopeMapOptions): Promise<ScopeMapResult>;
|
|
52
|
+
//# sourceMappingURL=scope-map.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
function estimateTokens(text) {
|
|
2
|
+
return Math.ceil(text.length / 4);
|
|
3
|
+
}
|
|
4
|
+
async function scopeMap(embedder, store, options) {
|
|
5
|
+
const { task, maxFiles = 15, contentType, origin } = options;
|
|
6
|
+
const queryVector = await embedder.embed(task);
|
|
7
|
+
const searchOpts = {
|
|
8
|
+
limit: maxFiles * 3,
|
|
9
|
+
// Over-fetch to group by file
|
|
10
|
+
contentType,
|
|
11
|
+
origin
|
|
12
|
+
};
|
|
13
|
+
const results = await store.search(queryVector, searchOpts);
|
|
14
|
+
const fileMap = /* @__PURE__ */ new Map();
|
|
15
|
+
for (const result of results) {
|
|
16
|
+
const path = result.record.sourcePath;
|
|
17
|
+
const existing = fileMap.get(path);
|
|
18
|
+
if (existing) {
|
|
19
|
+
existing.chunks.push(result);
|
|
20
|
+
existing.totalChars += result.record.content.length;
|
|
21
|
+
existing.maxScore = Math.max(existing.maxScore, result.score);
|
|
22
|
+
} else {
|
|
23
|
+
fileMap.set(path, {
|
|
24
|
+
chunks: [result],
|
|
25
|
+
totalChars: result.record.content.length,
|
|
26
|
+
maxScore: result.score
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const entries = [...fileMap.entries()].sort(([, a], [, b]) => b.maxScore - a.maxScore).slice(0, maxFiles).map(([path, { chunks, maxScore }]) => {
|
|
31
|
+
const focusRanges = chunks.sort((a, b) => a.record.startLine - b.record.startLine).map((c) => ({
|
|
32
|
+
start: c.record.startLine,
|
|
33
|
+
end: c.record.endLine,
|
|
34
|
+
heading: c.record.headingPath
|
|
35
|
+
}));
|
|
36
|
+
const topChunk = chunks.sort((a, b) => b.score - a.score)[0];
|
|
37
|
+
const reason = topChunk.record.headingPath ? `Matches: ${topChunk.record.headingPath}` : `Contains relevant ${topChunk.record.contentType} content`;
|
|
38
|
+
return {
|
|
39
|
+
path,
|
|
40
|
+
reason,
|
|
41
|
+
estimatedTokens: 0,
|
|
42
|
+
// computed below from actual content
|
|
43
|
+
relevance: maxScore,
|
|
44
|
+
focusRanges
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
for (const entry of entries) {
|
|
48
|
+
const fileChunks = fileMap.get(entry.path);
|
|
49
|
+
if (fileChunks) {
|
|
50
|
+
entry.estimatedTokens = estimateTokens(
|
|
51
|
+
fileChunks.chunks.map((c) => c.record.content).join("")
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const totalEstimatedTokens = entries.reduce((sum, e) => sum + e.estimatedTokens, 0);
|
|
56
|
+
const readingOrder = [...entries].sort((a, b) => {
|
|
57
|
+
const aIsConfig = a.path.includes("config") || a.path.includes("types") ? -1 : 0;
|
|
58
|
+
const bIsConfig = b.path.includes("config") || b.path.includes("types") ? -1 : 0;
|
|
59
|
+
if (aIsConfig !== bIsConfig) return aIsConfig - bIsConfig;
|
|
60
|
+
return b.relevance - a.relevance;
|
|
61
|
+
}).map((e) => e.path);
|
|
62
|
+
return {
|
|
63
|
+
task,
|
|
64
|
+
files: entries,
|
|
65
|
+
totalEstimatedTokens,
|
|
66
|
+
readingOrder
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
scopeMap
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=scope-map.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kb_snippet — Persistent code template storage with search.
|
|
3
|
+
*/
|
|
4
|
+
export interface Snippet {
|
|
5
|
+
name: string;
|
|
6
|
+
language: string;
|
|
7
|
+
code: string;
|
|
8
|
+
tags: string[];
|
|
9
|
+
created: string;
|
|
10
|
+
updated: string;
|
|
11
|
+
}
|
|
12
|
+
export type SnippetAction = 'save' | 'get' | 'list' | 'search' | 'delete';
|
|
13
|
+
export interface SnippetOptions {
|
|
14
|
+
action: SnippetAction;
|
|
15
|
+
name?: string;
|
|
16
|
+
language?: string;
|
|
17
|
+
code?: string;
|
|
18
|
+
tags?: string[];
|
|
19
|
+
query?: string;
|
|
20
|
+
}
|
|
21
|
+
export type SnippetResult = Snippet | {
|
|
22
|
+
snippets: SnippetSummary[];
|
|
23
|
+
} | {
|
|
24
|
+
deleted: boolean;
|
|
25
|
+
};
|
|
26
|
+
interface SnippetSummary {
|
|
27
|
+
name: string;
|
|
28
|
+
language: string;
|
|
29
|
+
tags: string[];
|
|
30
|
+
updated: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function snippet(options: SnippetOptions): SnippetResult;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=snippet.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
existsSync,
|
|
3
|
+
mkdirSync,
|
|
4
|
+
readdirSync,
|
|
5
|
+
readFileSync,
|
|
6
|
+
unlinkSync,
|
|
7
|
+
writeFileSync
|
|
8
|
+
} from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
const SNIPPETS_DIR = () => join(process.cwd(), ".kb-state", "snippets");
|
|
11
|
+
function ensureDir() {
|
|
12
|
+
const dir = SNIPPETS_DIR();
|
|
13
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
14
|
+
return dir;
|
|
15
|
+
}
|
|
16
|
+
function safeName(name) {
|
|
17
|
+
const safe = name.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
18
|
+
if (!safe) throw new Error("Invalid snippet name");
|
|
19
|
+
return safe;
|
|
20
|
+
}
|
|
21
|
+
function snippet(options) {
|
|
22
|
+
switch (options.action) {
|
|
23
|
+
case "save": {
|
|
24
|
+
if (!options.name || !options.code) throw new Error("name and code required for save");
|
|
25
|
+
const dir = ensureDir();
|
|
26
|
+
const name = safeName(options.name);
|
|
27
|
+
const filePath = join(dir, `${name}.json`);
|
|
28
|
+
const existing = existsSync(filePath) ? JSON.parse(readFileSync(filePath, "utf8")) : null;
|
|
29
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
30
|
+
const entry = {
|
|
31
|
+
name: options.name,
|
|
32
|
+
language: options.language ?? "text",
|
|
33
|
+
code: options.code,
|
|
34
|
+
tags: options.tags ?? [],
|
|
35
|
+
created: existing?.created ?? now,
|
|
36
|
+
updated: now
|
|
37
|
+
};
|
|
38
|
+
writeFileSync(filePath, JSON.stringify(entry, null, 2));
|
|
39
|
+
return entry;
|
|
40
|
+
}
|
|
41
|
+
case "get": {
|
|
42
|
+
if (!options.name) throw new Error("name required for get");
|
|
43
|
+
const filePath = join(SNIPPETS_DIR(), `${safeName(options.name)}.json`);
|
|
44
|
+
if (!existsSync(filePath)) throw new Error(`Snippet not found: ${options.name}`);
|
|
45
|
+
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
46
|
+
}
|
|
47
|
+
case "list": {
|
|
48
|
+
const dir = ensureDir();
|
|
49
|
+
const files = readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
50
|
+
const snippets = files.map((f) => {
|
|
51
|
+
const data = JSON.parse(readFileSync(join(dir, f), "utf8"));
|
|
52
|
+
return { name: data.name, language: data.language, tags: data.tags, updated: data.updated };
|
|
53
|
+
});
|
|
54
|
+
return { snippets };
|
|
55
|
+
}
|
|
56
|
+
case "search": {
|
|
57
|
+
if (!options.query) throw new Error("query required for search");
|
|
58
|
+
const q = options.query.toLowerCase();
|
|
59
|
+
const dir = ensureDir();
|
|
60
|
+
const files = readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
61
|
+
const snippets = files.map((f) => JSON.parse(readFileSync(join(dir, f), "utf8"))).filter(
|
|
62
|
+
(s) => s.name.toLowerCase().includes(q) || s.tags.some((t) => t.toLowerCase().includes(q)) || s.language.toLowerCase().includes(q) || s.code.toLowerCase().includes(q)
|
|
63
|
+
).map((s) => ({ name: s.name, language: s.language, tags: s.tags, updated: s.updated }));
|
|
64
|
+
return { snippets };
|
|
65
|
+
}
|
|
66
|
+
case "delete": {
|
|
67
|
+
if (!options.name) throw new Error("name required for delete");
|
|
68
|
+
const filePath = join(SNIPPETS_DIR(), `${safeName(options.name)}.json`);
|
|
69
|
+
if (!existsSync(filePath)) return { deleted: false };
|
|
70
|
+
unlinkSync(filePath);
|
|
71
|
+
return { deleted: true };
|
|
72
|
+
}
|
|
73
|
+
default:
|
|
74
|
+
throw new Error(`Unknown action: ${options.action}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
snippet
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=snippet.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface StashEntry {
|
|
2
|
+
key: string;
|
|
3
|
+
value: unknown;
|
|
4
|
+
type: string;
|
|
5
|
+
storedAt: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function stashSet(key: string, value: unknown, cwd?: string): StashEntry;
|
|
8
|
+
export declare function stashGet(key: string, cwd?: string): StashEntry | undefined;
|
|
9
|
+
export declare function stashList(cwd?: string): StashEntry[];
|
|
10
|
+
export declare function stashDelete(key: string, cwd?: string): boolean;
|
|
11
|
+
export declare function stashClear(cwd?: string): number;
|
|
12
|
+
//# sourceMappingURL=stash.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
const STASH_DIR = ".kb-state";
|
|
4
|
+
const STASH_FILE = "stash.json";
|
|
5
|
+
function stashPath(cwd) {
|
|
6
|
+
const root = cwd ?? process.cwd();
|
|
7
|
+
return resolve(root, STASH_DIR, STASH_FILE);
|
|
8
|
+
}
|
|
9
|
+
function loadStash(cwd) {
|
|
10
|
+
const path = stashPath(cwd);
|
|
11
|
+
if (!existsSync(path)) return {};
|
|
12
|
+
const raw = readFileSync(path, "utf-8");
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
}
|
|
15
|
+
function saveStash(data, cwd) {
|
|
16
|
+
const path = stashPath(cwd);
|
|
17
|
+
const dir = dirname(path);
|
|
18
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
19
|
+
writeFileSync(path, `${JSON.stringify(data, null, 2)}
|
|
20
|
+
`, "utf-8");
|
|
21
|
+
}
|
|
22
|
+
function stashSet(key, value, cwd) {
|
|
23
|
+
const stash = loadStash(cwd);
|
|
24
|
+
const entry = {
|
|
25
|
+
key,
|
|
26
|
+
value,
|
|
27
|
+
type: typeof value,
|
|
28
|
+
storedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
29
|
+
};
|
|
30
|
+
stash[key] = entry;
|
|
31
|
+
saveStash(stash, cwd);
|
|
32
|
+
return entry;
|
|
33
|
+
}
|
|
34
|
+
function stashGet(key, cwd) {
|
|
35
|
+
return loadStash(cwd)[key];
|
|
36
|
+
}
|
|
37
|
+
function stashList(cwd) {
|
|
38
|
+
return Object.values(loadStash(cwd));
|
|
39
|
+
}
|
|
40
|
+
function stashDelete(key, cwd) {
|
|
41
|
+
const stash = loadStash(cwd);
|
|
42
|
+
if (!(key in stash)) return false;
|
|
43
|
+
delete stash[key];
|
|
44
|
+
saveStash(stash, cwd);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
function stashClear(cwd) {
|
|
48
|
+
const stash = loadStash(cwd);
|
|
49
|
+
const count = Object.keys(stash).length;
|
|
50
|
+
saveStash({}, cwd);
|
|
51
|
+
return count;
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
stashClear,
|
|
55
|
+
stashDelete,
|
|
56
|
+
stashGet,
|
|
57
|
+
stashList,
|
|
58
|
+
stashSet
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=stash.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kb_stratum_card — STRATUM T1/T2 context card generator.
|
|
3
|
+
*
|
|
4
|
+
* Generates compact context cards from files. T1 = structural metadata only
|
|
5
|
+
* (~100 tokens/file). T2 = T1 + compressed content (~300 tokens/file).
|
|
6
|
+
* Uses file-summary for structure and embedder for T2 content scoring.
|
|
7
|
+
*/
|
|
8
|
+
import type { IEmbedder } from '@kb/embeddings';
|
|
9
|
+
export interface StratumCardOptions {
|
|
10
|
+
files: string[];
|
|
11
|
+
query: string;
|
|
12
|
+
tier?: 'T1' | 'T2';
|
|
13
|
+
maxContentChars?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface StratumCard {
|
|
16
|
+
path: string;
|
|
17
|
+
tier: 'T1' | 'T2';
|
|
18
|
+
card: string;
|
|
19
|
+
unknowns: string[];
|
|
20
|
+
riskTier: 'low' | 'medium' | 'high';
|
|
21
|
+
tokenEstimate: number;
|
|
22
|
+
originalTokenEstimate: number;
|
|
23
|
+
}
|
|
24
|
+
export interface StratumCardResult {
|
|
25
|
+
cards: StratumCard[];
|
|
26
|
+
totalTokenEstimate: number;
|
|
27
|
+
totalOriginalTokenEstimate: number;
|
|
28
|
+
compressionRatio: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function stratumCard(embedder: IEmbedder, options: StratumCardOptions): Promise<StratumCardResult>;
|
|
31
|
+
//# sourceMappingURL=stratum-card.d.ts.map
|