@vortex-os/memory-extended 0.5.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/README.md +244 -0
- package/dist/consolidate/index.d.ts +7 -0
- package/dist/consolidate/index.d.ts.map +1 -0
- package/dist/consolidate/index.js +4 -0
- package/dist/consolidate/index.js.map +1 -0
- package/dist/consolidate/proposer.d.ts +43 -0
- package/dist/consolidate/proposer.d.ts.map +1 -0
- package/dist/consolidate/proposer.js +276 -0
- package/dist/consolidate/proposer.js.map +1 -0
- package/dist/consolidate/query.d.ts +32 -0
- package/dist/consolidate/query.d.ts.map +1 -0
- package/dist/consolidate/query.js +40 -0
- package/dist/consolidate/query.js.map +1 -0
- package/dist/consolidate/store.d.ts +21 -0
- package/dist/consolidate/store.d.ts.map +1 -0
- package/dist/consolidate/store.js +91 -0
- package/dist/consolidate/store.js.map +1 -0
- package/dist/consolidate/types.d.ts +68 -0
- package/dist/consolidate/types.d.ts.map +1 -0
- package/dist/consolidate/types.js +2 -0
- package/dist/consolidate/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/frontmatter.d.ts +6 -0
- package/dist/internal/frontmatter.d.ts.map +1 -0
- package/dist/internal/frontmatter.js +38 -0
- package/dist/internal/frontmatter.js.map +1 -0
- package/dist/internal/proactive-curator-helpers.d.ts +171 -0
- package/dist/internal/proactive-curator-helpers.d.ts.map +1 -0
- package/dist/internal/proactive-curator-helpers.js +162 -0
- package/dist/internal/proactive-curator-helpers.js.map +1 -0
- package/dist/mcp/document-tools.d.ts +144 -0
- package/dist/mcp/document-tools.d.ts.map +1 -0
- package/dist/mcp/document-tools.js +319 -0
- package/dist/mcp/document-tools.js.map +1 -0
- package/dist/mcp/index.d.ts +34 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +29 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/install.d.ts +72 -0
- package/dist/mcp/install.d.ts.map +1 -0
- package/dist/mcp/install.js +92 -0
- package/dist/mcp/install.js.map +1 -0
- package/dist/mcp/memory-tools.d.ts +101 -0
- package/dist/mcp/memory-tools.d.ts.map +1 -0
- package/dist/mcp/memory-tools.js +105 -0
- package/dist/mcp/memory-tools.js.map +1 -0
- package/dist/mcp/recall-tool.d.ts +52 -0
- package/dist/mcp/recall-tool.d.ts.map +1 -0
- package/dist/mcp/recall-tool.js +60 -0
- package/dist/mcp/recall-tool.js.map +1 -0
- package/dist/mcp/server.d.ts +32 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +113 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/recall/engine.d.ts +38 -0
- package/dist/recall/engine.d.ts.map +1 -0
- package/dist/recall/engine.js +113 -0
- package/dist/recall/engine.js.map +1 -0
- package/dist/recall/index.d.ts +22 -0
- package/dist/recall/index.d.ts.map +1 -0
- package/dist/recall/index.js +20 -0
- package/dist/recall/index.js.map +1 -0
- package/dist/recall/intent.d.ts +24 -0
- package/dist/recall/intent.d.ts.map +1 -0
- package/dist/recall/intent.js +95 -0
- package/dist/recall/intent.js.map +1 -0
- package/dist/recall/render.d.ts +11 -0
- package/dist/recall/render.d.ts.map +1 -0
- package/dist/recall/render.js +23 -0
- package/dist/recall/render.js.map +1 -0
- package/dist/recall/types.d.ts +72 -0
- package/dist/recall/types.d.ts.map +1 -0
- package/dist/recall/types.js +2 -0
- package/dist/recall/types.js.map +1 -0
- package/dist/sessionArchive/adapters/claude-code.d.ts +3 -0
- package/dist/sessionArchive/adapters/claude-code.d.ts.map +1 -0
- package/dist/sessionArchive/adapters/claude-code.js +276 -0
- package/dist/sessionArchive/adapters/claude-code.js.map +1 -0
- package/dist/sessionArchive/adapters/claude-desktop.d.ts +3 -0
- package/dist/sessionArchive/adapters/claude-desktop.d.ts.map +1 -0
- package/dist/sessionArchive/adapters/claude-desktop.js +234 -0
- package/dist/sessionArchive/adapters/claude-desktop.js.map +1 -0
- package/dist/sessionArchive/adapters/codex.d.ts +3 -0
- package/dist/sessionArchive/adapters/codex.d.ts.map +1 -0
- package/dist/sessionArchive/adapters/codex.js +322 -0
- package/dist/sessionArchive/adapters/codex.js.map +1 -0
- package/dist/sessionArchive/adapters/gemini.d.ts +3 -0
- package/dist/sessionArchive/adapters/gemini.d.ts.map +1 -0
- package/dist/sessionArchive/adapters/gemini.js +248 -0
- package/dist/sessionArchive/adapters/gemini.js.map +1 -0
- package/dist/sessionArchive/adapters/index.d.ts +5 -0
- package/dist/sessionArchive/adapters/index.d.ts.map +1 -0
- package/dist/sessionArchive/adapters/index.js +5 -0
- package/dist/sessionArchive/adapters/index.js.map +1 -0
- package/dist/sessionArchive/index.d.ts +9 -0
- package/dist/sessionArchive/index.d.ts.map +1 -0
- package/dist/sessionArchive/index.js +6 -0
- package/dist/sessionArchive/index.js.map +1 -0
- package/dist/sessionArchive/ingest.d.ts +68 -0
- package/dist/sessionArchive/ingest.d.ts.map +1 -0
- package/dist/sessionArchive/ingest.js +134 -0
- package/dist/sessionArchive/ingest.js.map +1 -0
- package/dist/sessionArchive/normalize.d.ts +15 -0
- package/dist/sessionArchive/normalize.d.ts.map +1 -0
- package/dist/sessionArchive/normalize.js +40 -0
- package/dist/sessionArchive/normalize.js.map +1 -0
- package/dist/sessionArchive/store.d.ts +118 -0
- package/dist/sessionArchive/store.d.ts.map +1 -0
- package/dist/sessionArchive/store.js +491 -0
- package/dist/sessionArchive/store.js.map +1 -0
- package/dist/sessionArchive/types.d.ts +124 -0
- package/dist/sessionArchive/types.d.ts.map +1 -0
- package/dist/sessionArchive/types.js +24 -0
- package/dist/sessionArchive/types.js.map +1 -0
- package/dist/sqlite/drift.d.ts +22 -0
- package/dist/sqlite/drift.d.ts.map +1 -0
- package/dist/sqlite/drift.js +69 -0
- package/dist/sqlite/drift.js.map +1 -0
- package/dist/sqlite/index.d.ts +22 -0
- package/dist/sqlite/index.d.ts.map +1 -0
- package/dist/sqlite/index.js +4 -0
- package/dist/sqlite/index.js.map +1 -0
- package/dist/sqlite/rebuild.d.ts +32 -0
- package/dist/sqlite/rebuild.d.ts.map +1 -0
- package/dist/sqlite/rebuild.js +80 -0
- package/dist/sqlite/rebuild.js.map +1 -0
- package/dist/sqlite/schema.d.ts +15 -0
- package/dist/sqlite/schema.d.ts.map +1 -0
- package/dist/sqlite/schema.js +41 -0
- package/dist/sqlite/schema.js.map +1 -0
- package/dist/sqlite/store.d.ts +49 -0
- package/dist/sqlite/store.d.ts.map +1 -0
- package/dist/sqlite/store.js +179 -0
- package/dist/sqlite/store.js.map +1 -0
- package/dist/sqlite/types.d.ts +57 -0
- package/dist/sqlite/types.d.ts.map +1 -0
- package/dist/sqlite/types.js +2 -0
- package/dist/sqlite/types.js.map +1 -0
- package/dist/vector/backend-brute.d.ts +38 -0
- package/dist/vector/backend-brute.d.ts.map +1 -0
- package/dist/vector/backend-brute.js +112 -0
- package/dist/vector/backend-brute.js.map +1 -0
- package/dist/vector/embedder.d.ts +59 -0
- package/dist/vector/embedder.d.ts.map +1 -0
- package/dist/vector/embedder.js +47 -0
- package/dist/vector/embedder.js.map +1 -0
- package/dist/vector/index.d.ts +24 -0
- package/dist/vector/index.d.ts.map +1 -0
- package/dist/vector/index.js +7 -0
- package/dist/vector/index.js.map +1 -0
- package/dist/vector/math.d.ts +21 -0
- package/dist/vector/math.d.ts.map +1 -0
- package/dist/vector/math.js +34 -0
- package/dist/vector/math.js.map +1 -0
- package/dist/vector/schema.d.ts +14 -0
- package/dist/vector/schema.d.ts.map +1 -0
- package/dist/vector/schema.js +24 -0
- package/dist/vector/schema.js.map +1 -0
- package/dist/vector/segment.d.ts +65 -0
- package/dist/vector/segment.d.ts.map +1 -0
- package/dist/vector/segment.js +72 -0
- package/dist/vector/segment.js.map +1 -0
- package/dist/vector/session.d.ts +90 -0
- package/dist/vector/session.d.ts.map +1 -0
- package/dist/vector/session.js +242 -0
- package/dist/vector/session.js.map +1 -0
- package/dist/vector/store.d.ts +69 -0
- package/dist/vector/store.d.ts.map +1 -0
- package/dist/vector/store.js +131 -0
- package/dist/vector/store.js.map +1 -0
- package/dist/vector/types.d.ts +109 -0
- package/dist/vector/types.d.ts.map +1 -0
- package/dist/vector/types.js +24 -0
- package/dist/vector/types.js.map +1 -0
- package/package.json +96 -0
- package/scripts/mcp-stdio.mjs +143 -0
- package/scripts/rebuild-memory-sqlite.mjs +39 -0
- package/scripts/rebuild-memory-vector.mjs +64 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { RECALL_TOOL_NAME, recallToolDefinition, runRecall } from "./recall-tool.js";
|
|
2
|
+
import { GET_MEMORY_TOOL_NAME, LIST_MEMORIES_TOOL_NAME, getMemoryToolDefinition, listMemoriesToolDefinition, runGetMemory, runListMemories, } from "./memory-tools.js";
|
|
3
|
+
import { SUGGEST_DOCUMENT_TOOL_NAME, WRITE_DOCUMENT_TOOL_NAME, DECLINE_DOCUMENT_TOOL_NAME, suggestDocumentToolDefinition, writeDocumentToolDefinition, declineDocumentToolDefinition, runSuggestDocument, runWriteDocument, runDeclineDocument, } from "./document-tools.js";
|
|
4
|
+
/**
|
|
5
|
+
* The MCP SDK (`@modelcontextprotocol/sdk`) is an OPTIONAL dependency of
|
|
6
|
+
* memory-extended — only consumers who run the MCP server need it, exactly as
|
|
7
|
+
* `@huggingface/transformers` is optional for those who run the local embedder.
|
|
8
|
+
* So the SDK is loaded at runtime via dynamic import (a runtime-resolved
|
|
9
|
+
* specifier keeps tsc from requiring its types at build time), and the server
|
|
10
|
+
* is returned typed loosely. Hosts that never call this never pay for the SDK.
|
|
11
|
+
*
|
|
12
|
+
* Returns the connected-but-not-transported `Server` instance; the caller
|
|
13
|
+
* attaches a transport (stdio for slice 1) with `await server.connect(t)`.
|
|
14
|
+
*/
|
|
15
|
+
export async function createRecallServer(options) {
|
|
16
|
+
const sdk = await loadMcpSdk();
|
|
17
|
+
const server = new sdk.Server({ name: options.name ?? "vortex-mcp-recall", version: options.version ?? "0.1.0" }, { capabilities: { tools: {} } });
|
|
18
|
+
server.setRequestHandler(sdk.ListToolsRequestSchema, async () => ({
|
|
19
|
+
tools: [
|
|
20
|
+
recallToolDefinition,
|
|
21
|
+
listMemoriesToolDefinition,
|
|
22
|
+
getMemoryToolDefinition,
|
|
23
|
+
suggestDocumentToolDefinition,
|
|
24
|
+
writeDocumentToolDefinition,
|
|
25
|
+
declineDocumentToolDefinition,
|
|
26
|
+
],
|
|
27
|
+
}));
|
|
28
|
+
server.setRequestHandler(sdk.CallToolRequestSchema, async (request) => {
|
|
29
|
+
const name = request.params.name;
|
|
30
|
+
const raw = (request.params.arguments ?? {});
|
|
31
|
+
const str = (v) => (typeof v === "string" ? v : undefined);
|
|
32
|
+
const num = (v) => (typeof v === "number" ? v : undefined);
|
|
33
|
+
try {
|
|
34
|
+
if (name === RECALL_TOOL_NAME) {
|
|
35
|
+
const source = raw.source === "memory" || raw.source === "session-archive" ? raw.source : undefined;
|
|
36
|
+
const result = await runRecall({ query: str(raw.query) ?? "", k: num(raw.k), source }, { embed: options.embed, dbPath: options.dbPath, defaultK: options.defaultK });
|
|
37
|
+
return jsonResult({ query: result.query, count: result.hits.length, hits: result.hits });
|
|
38
|
+
}
|
|
39
|
+
if (name === LIST_MEMORIES_TOOL_NAME) {
|
|
40
|
+
const result = await runListMemories({ type: str(raw.type), tag: str(raw.tag), privacy: str(raw.privacy), limit: num(raw.limit) }, { dbPath: options.dbPath });
|
|
41
|
+
return jsonResult(result);
|
|
42
|
+
}
|
|
43
|
+
if (name === GET_MEMORY_TOOL_NAME) {
|
|
44
|
+
const result = await runGetMemory({ id: str(raw.id) ?? "" }, { dbPath: options.dbPath });
|
|
45
|
+
return jsonResult(result);
|
|
46
|
+
}
|
|
47
|
+
// ── document tools (slice 4): require dataDir ─────────────────────
|
|
48
|
+
if (name === SUGGEST_DOCUMENT_TOOL_NAME ||
|
|
49
|
+
name === WRITE_DOCUMENT_TOOL_NAME ||
|
|
50
|
+
name === DECLINE_DOCUMENT_TOOL_NAME) {
|
|
51
|
+
if (!options.dataDir) {
|
|
52
|
+
return {
|
|
53
|
+
content: [{ type: "text", text: `${name} unavailable: server started without a data dir` }],
|
|
54
|
+
isError: true,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const strArr = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : undefined;
|
|
58
|
+
const docArgs = {
|
|
59
|
+
topic: str(raw.topic) ?? "",
|
|
60
|
+
name: str(raw.name) ?? "",
|
|
61
|
+
title: str(raw.title),
|
|
62
|
+
content: str(raw.content) ?? "",
|
|
63
|
+
description: str(raw.description),
|
|
64
|
+
tags: strArr(raw.tags),
|
|
65
|
+
};
|
|
66
|
+
const deps = { cwd: options.dataDir };
|
|
67
|
+
if (name === SUGGEST_DOCUMENT_TOOL_NAME)
|
|
68
|
+
return jsonResult(await runSuggestDocument(docArgs, deps));
|
|
69
|
+
if (name === WRITE_DOCUMENT_TOOL_NAME)
|
|
70
|
+
return jsonResult(await runWriteDocument(docArgs, deps));
|
|
71
|
+
return jsonResult(await runDeclineDocument({ topic: docArgs.topic, name: docArgs.name }, deps));
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
75
|
+
isError: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
return {
|
|
80
|
+
content: [{ type: "text", text: `${name} failed: ${err.message}` }],
|
|
81
|
+
isError: true,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return server;
|
|
86
|
+
}
|
|
87
|
+
/** Wrap a structured payload as an MCP text-content result (pretty JSON). */
|
|
88
|
+
function jsonResult(payload) {
|
|
89
|
+
return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
|
|
90
|
+
}
|
|
91
|
+
async function loadMcpSdk() {
|
|
92
|
+
const serverSpecifier = "@modelcontextprotocol/sdk/server/index.js";
|
|
93
|
+
const typesSpecifier = "@modelcontextprotocol/sdk/types.js";
|
|
94
|
+
try {
|
|
95
|
+
const [serverMod, typesMod] = await Promise.all([
|
|
96
|
+
import(serverSpecifier),
|
|
97
|
+
import(typesSpecifier),
|
|
98
|
+
]);
|
|
99
|
+
return {
|
|
100
|
+
Server: serverMod.Server,
|
|
101
|
+
ListToolsRequestSchema: typesMod
|
|
102
|
+
.ListToolsRequestSchema,
|
|
103
|
+
CallToolRequestSchema: typesMod
|
|
104
|
+
.CallToolRequestSchema,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
throw new Error(`createRecallServer: failed to load "@modelcontextprotocol/sdk". ` +
|
|
109
|
+
`It ships as an optional dependency of @vortex-os/memory-extended; if it is missing, ` +
|
|
110
|
+
`run \`npm install @modelcontextprotocol/sdk\`. Original error: ${e.message}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { MemorySqliteStore } from "../sqlite/store.js";
|
|
2
|
+
import type { MemoryVectorStore } from "../vector/store.js";
|
|
3
|
+
import type { EmbedFn } from "../vector/types.js";
|
|
4
|
+
import type { SessionChunkStore } from "../vector/session.js";
|
|
5
|
+
import type { RecallParams, RecallResult } from "./types.js";
|
|
6
|
+
/** Dependencies the recall engine needs the host to supply. */
|
|
7
|
+
export interface RecallDeps {
|
|
8
|
+
readonly sqlite: MemorySqliteStore;
|
|
9
|
+
readonly vector: MemoryVectorStore;
|
|
10
|
+
readonly embed: EmbedFn;
|
|
11
|
+
/**
|
|
12
|
+
* Optional — hydrates `session-archive` hits with timestamp + excerpt.
|
|
13
|
+
* Without it, session hits are dropped (graceful degradation), so a host
|
|
14
|
+
* that has not vectorized sessions still gets memory recall.
|
|
15
|
+
*/
|
|
16
|
+
readonly sessionChunks?: SessionChunkStore;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Two-stage hybrid recall (operator decision 5 / 2026-05-29). Returns
|
|
20
|
+
* structured {@link RecallResult} data — never a pre-rendered report. The
|
|
21
|
+
* caller decides whether to list the hits (explicit `/recall`) or phrase
|
|
22
|
+
* one in conversation (ambient use).
|
|
23
|
+
*
|
|
24
|
+
* Pipeline:
|
|
25
|
+
* 1. **Parse intent** — pull obvious filters (type / tag / date) out of the
|
|
26
|
+
* query (regex, no LLM).
|
|
27
|
+
* 2. **Hard filter (loose)** — if filters were found, restrict candidates
|
|
28
|
+
* via SQLite. *But* if that leaves fewer than `k` candidates, the
|
|
29
|
+
* filter is dropped and the semantic stage runs over the whole corpus.
|
|
30
|
+
* This is the safeguard against the over-narrowing risk: a guessed
|
|
31
|
+
* filter never costs you a relevant-but-unfiltered memory.
|
|
32
|
+
* 3. **Semantic rerank** — embed the (filter-stripped) query text and ask
|
|
33
|
+
* the vector store for the closest candidates.
|
|
34
|
+
* 4. **Hydrate** — join vector hits back to their memory rows for name,
|
|
35
|
+
* description, tags, and a body excerpt.
|
|
36
|
+
*/
|
|
37
|
+
export declare function recall(params: RecallParams, deps: RecallDeps): Promise<RecallResult>;
|
|
38
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/recall/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAmB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,OAAO,KAAK,EAAa,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAExE,+DAA+D;AAC/D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;CAC5C;AAKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAmD1F"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { parseIntent } from "./intent.js";
|
|
2
|
+
const DEFAULT_K = 5;
|
|
3
|
+
const EXCERPT_CHARS = 280;
|
|
4
|
+
/**
|
|
5
|
+
* Two-stage hybrid recall (operator decision 5 / 2026-05-29). Returns
|
|
6
|
+
* structured {@link RecallResult} data — never a pre-rendered report. The
|
|
7
|
+
* caller decides whether to list the hits (explicit `/recall`) or phrase
|
|
8
|
+
* one in conversation (ambient use).
|
|
9
|
+
*
|
|
10
|
+
* Pipeline:
|
|
11
|
+
* 1. **Parse intent** — pull obvious filters (type / tag / date) out of the
|
|
12
|
+
* query (regex, no LLM).
|
|
13
|
+
* 2. **Hard filter (loose)** — if filters were found, restrict candidates
|
|
14
|
+
* via SQLite. *But* if that leaves fewer than `k` candidates, the
|
|
15
|
+
* filter is dropped and the semantic stage runs over the whole corpus.
|
|
16
|
+
* This is the safeguard against the over-narrowing risk: a guessed
|
|
17
|
+
* filter never costs you a relevant-but-unfiltered memory.
|
|
18
|
+
* 3. **Semantic rerank** — embed the (filter-stripped) query text and ask
|
|
19
|
+
* the vector store for the closest candidates.
|
|
20
|
+
* 4. **Hydrate** — join vector hits back to their memory rows for name,
|
|
21
|
+
* description, tags, and a body excerpt.
|
|
22
|
+
*/
|
|
23
|
+
export async function recall(params, deps) {
|
|
24
|
+
const { sqlite, vector, embed } = deps;
|
|
25
|
+
const k = params.k ?? DEFAULT_K;
|
|
26
|
+
const intent = parseIntent(params.query);
|
|
27
|
+
const corpusSize = vector.count(params.source);
|
|
28
|
+
let appliedFilters = {};
|
|
29
|
+
let ids;
|
|
30
|
+
let hardFilterCandidates = corpusSize;
|
|
31
|
+
let hardFilterDropped = false;
|
|
32
|
+
const hasFilters = hasAnyFilter(intent.filters);
|
|
33
|
+
if (hasFilters && !params.noHardFilter) {
|
|
34
|
+
const filtered = sqlite.query(intent.filters);
|
|
35
|
+
if (filtered.length < k) {
|
|
36
|
+
// Too narrow — drop it. Searching the full corpus is safer than
|
|
37
|
+
// excluding a relevant memory the guessed filter happened to miss.
|
|
38
|
+
hardFilterDropped = true;
|
|
39
|
+
hardFilterCandidates = corpusSize;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
appliedFilters = intent.filters;
|
|
43
|
+
ids = new Set(filtered.map((r) => r.id));
|
|
44
|
+
hardFilterCandidates = filtered.length;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const vectorHits = await vector.search(intent.semanticText, embed, {
|
|
48
|
+
k,
|
|
49
|
+
source: params.source,
|
|
50
|
+
ids,
|
|
51
|
+
});
|
|
52
|
+
const hits = [];
|
|
53
|
+
for (const vh of vectorHits) {
|
|
54
|
+
if (vh.source === "session-archive") {
|
|
55
|
+
const chunk = deps.sessionChunks?.getById(vh.id);
|
|
56
|
+
if (!chunk)
|
|
57
|
+
continue; // no session-chunk metadata (not hydratable) — skip
|
|
58
|
+
hits.push(toSessionHit(chunk, vh.score));
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const row = sqlite.getById(vh.id);
|
|
62
|
+
if (!row)
|
|
63
|
+
continue; // vector exists but memory was deleted — drift; skip
|
|
64
|
+
hits.push(toHit(row, vh.source, vh.score));
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
query: params.query,
|
|
68
|
+
intent,
|
|
69
|
+
stage: { appliedFilters, hardFilterCandidates, hardFilterDropped, corpusSize },
|
|
70
|
+
hits,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function hasAnyFilter(q) {
|
|
74
|
+
return Boolean((q.type && q.type.length) ||
|
|
75
|
+
(q.tags && q.tags.length) ||
|
|
76
|
+
(q.privacy && q.privacy.length) ||
|
|
77
|
+
q.updatedSinceMs !== undefined);
|
|
78
|
+
}
|
|
79
|
+
function toHit(row, source, score) {
|
|
80
|
+
return {
|
|
81
|
+
id: row.id,
|
|
82
|
+
source,
|
|
83
|
+
score,
|
|
84
|
+
name: row.name,
|
|
85
|
+
description: row.description,
|
|
86
|
+
type: row.type,
|
|
87
|
+
updated: row.updated,
|
|
88
|
+
tags: row.tags,
|
|
89
|
+
excerpt: excerpt(row.body),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function excerpt(body) {
|
|
93
|
+
const collapsed = body.replace(/\s+/g, " ").trim();
|
|
94
|
+
return collapsed.length <= EXCERPT_CHARS
|
|
95
|
+
? collapsed
|
|
96
|
+
: `${collapsed.slice(0, EXCERPT_CHARS).trimEnd()}…`;
|
|
97
|
+
}
|
|
98
|
+
/** Hydrate a session-archive hit from its chunk metadata row. */
|
|
99
|
+
function toSessionHit(chunk, score) {
|
|
100
|
+
const day = chunk.startedAt ? chunk.startedAt.slice(0, 10) : null;
|
|
101
|
+
return {
|
|
102
|
+
id: chunk.id,
|
|
103
|
+
source: "session-archive",
|
|
104
|
+
score,
|
|
105
|
+
name: `${chunk.host} session${day ? ` (${day})` : ""} · part ${chunk.chunkIdx + 1}`,
|
|
106
|
+
description: "",
|
|
107
|
+
type: "session",
|
|
108
|
+
updated: chunk.startedAt,
|
|
109
|
+
tags: [chunk.host],
|
|
110
|
+
excerpt: chunk.excerpt,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/recall/engine.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAgB1C,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,MAAoB,EAAE,IAAgB;IACjE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IACvC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,SAAS,CAAC;IAChC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAE/C,IAAI,cAAc,GAAgB,EAAE,CAAC;IACrC,IAAI,GAAoC,CAAC;IACzC,IAAI,oBAAoB,GAAG,UAAU,CAAC;IACtC,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAE9B,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,UAAU,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,gEAAgE;YAChE,mEAAmE;YACnE,iBAAiB,GAAG,IAAI,CAAC;YACzB,oBAAoB,GAAG,UAAU,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC;YAChC,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACzC,oBAAoB,GAAG,QAAQ,CAAC,MAAM,CAAC;QACzC,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,EAAE;QACjE,CAAC;QACD,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,GAAG;KACJ,CAAC,CAAC;IAEH,MAAM,IAAI,GAAgB,EAAE,CAAC;IAC7B,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC5B,IAAI,EAAE,CAAC,MAAM,KAAK,iBAAiB,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACjD,IAAI,CAAC,KAAK;gBAAE,SAAS,CAAC,oDAAoD;YAC1E,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YACzC,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,SAAS,CAAC,qDAAqD;QACzE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM;QACN,KAAK,EAAE,EAAE,cAAc,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,UAAU,EAAE;QAC9E,IAAI;KACL,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,CAAc;IAClC,OAAO,OAAO,CACZ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACvB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACzB,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QAC/B,CAAC,CAAC,cAAc,KAAK,SAAS,CACjC,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,GAAc,EAAE,MAA2B,EAAE,KAAa;IACvE,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM;QACN,KAAK;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;KAC3B,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,OAAO,SAAS,CAAC,MAAM,IAAI,aAAa;QACtC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC;AACxD,CAAC;AAED,iEAAiE;AACjE,SAAS,YAAY,CAAC,KAAsB,EAAE,KAAa;IACzD,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClE,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,iBAAiB;QACzB,KAAK;QACL,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,CAAC,QAAQ,GAAG,CAAC,EAAE;QACnF,WAAW,EAAE,EAAE;QACf,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,KAAK,CAAC,SAAS;QACxB,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;QAClB,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `recall` namespace — two-stage hybrid retrieval (Phase 11c, 2026-05-29).
|
|
3
|
+
*
|
|
4
|
+
* The module exports the *engine* and pure helpers; the `/recall` slash
|
|
5
|
+
* command is defined in the host plugin (`session-rituals`), mirroring how
|
|
6
|
+
* `/curate` is defined there over the `proactive-curator` module. This
|
|
7
|
+
* keeps the module free of any slash-commands dependency.
|
|
8
|
+
*
|
|
9
|
+
* Surfaces:
|
|
10
|
+
* - {@link recall} — the engine. Returns structured {@link RecallResult}
|
|
11
|
+
* data — the "callable tool surface" for ambient, in-conversation use
|
|
12
|
+
* (the host phrases a hit as prose). Decision 5: the engine never
|
|
13
|
+
* formats a report itself.
|
|
14
|
+
* - {@link renderRecallHits} — optional compact list render for the
|
|
15
|
+
* explicit `/recall` surface.
|
|
16
|
+
*/
|
|
17
|
+
export { recall } from "./engine.js";
|
|
18
|
+
export type { RecallDeps } from "./engine.js";
|
|
19
|
+
export { parseIntent } from "./intent.js";
|
|
20
|
+
export { renderRecallHits } from "./render.js";
|
|
21
|
+
export type { ParsedIntent, RecallHit, RecallParams, RecallResult, RecallStageInfo, } from "./types.js";
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recall/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EACV,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `recall` namespace — two-stage hybrid retrieval (Phase 11c, 2026-05-29).
|
|
3
|
+
*
|
|
4
|
+
* The module exports the *engine* and pure helpers; the `/recall` slash
|
|
5
|
+
* command is defined in the host plugin (`session-rituals`), mirroring how
|
|
6
|
+
* `/curate` is defined there over the `proactive-curator` module. This
|
|
7
|
+
* keeps the module free of any slash-commands dependency.
|
|
8
|
+
*
|
|
9
|
+
* Surfaces:
|
|
10
|
+
* - {@link recall} — the engine. Returns structured {@link RecallResult}
|
|
11
|
+
* data — the "callable tool surface" for ambient, in-conversation use
|
|
12
|
+
* (the host phrases a hit as prose). Decision 5: the engine never
|
|
13
|
+
* formats a report itself.
|
|
14
|
+
* - {@link renderRecallHits} — optional compact list render for the
|
|
15
|
+
* explicit `/recall` surface.
|
|
16
|
+
*/
|
|
17
|
+
export { recall } from "./engine.js";
|
|
18
|
+
export { parseIntent } from "./intent.js";
|
|
19
|
+
export { renderRecallHits } from "./render.js";
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/recall/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ParsedIntent } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parse obvious structured filters out of a natural-language query
|
|
4
|
+
* (operator decision 4 / 2026-05-29). Deliberately conservative — it only
|
|
5
|
+
* recognizes filters the user clearly intended, because the heavy lifting
|
|
6
|
+
* is the semantic stage, not this. Over-eager parsing would wrongly narrow
|
|
7
|
+
* the candidate set; the engine additionally drops the filter if it leaves
|
|
8
|
+
* too few candidates (see engine docs).
|
|
9
|
+
*
|
|
10
|
+
* Recognized today (rule-based, no LLM — that is a later slot):
|
|
11
|
+
* - `type:feedback` / `type=feedback` → type filter
|
|
12
|
+
* - `tag:priming` / `#priming` → tag filter
|
|
13
|
+
* - `2026-05` / `2026-05-12` → updatedSince that date
|
|
14
|
+
* - Korean month `5월` → updatedSince that month
|
|
15
|
+
* (current year) — only when no explicit ISO date was given
|
|
16
|
+
*
|
|
17
|
+
* Date parsing deliberately omits bare English month words: "may" / "march"
|
|
18
|
+
* collide with the modal verb and the imperative, and a wrong date filter
|
|
19
|
+
* is exactly the over-narrowing the operator flagged in decision 4. English
|
|
20
|
+
* callers use ISO dates (`2026-05`) for date intent. Everything recognized
|
|
21
|
+
* is stripped from the query to form `semanticText`, which gets embedded.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseIntent(query: string, now?: Date): ParsedIntent;
|
|
24
|
+
//# sourceMappingURL=intent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/recall/intent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,YAAY,CAuD/E"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse obvious structured filters out of a natural-language query
|
|
3
|
+
* (operator decision 4 / 2026-05-29). Deliberately conservative — it only
|
|
4
|
+
* recognizes filters the user clearly intended, because the heavy lifting
|
|
5
|
+
* is the semantic stage, not this. Over-eager parsing would wrongly narrow
|
|
6
|
+
* the candidate set; the engine additionally drops the filter if it leaves
|
|
7
|
+
* too few candidates (see engine docs).
|
|
8
|
+
*
|
|
9
|
+
* Recognized today (rule-based, no LLM — that is a later slot):
|
|
10
|
+
* - `type:feedback` / `type=feedback` → type filter
|
|
11
|
+
* - `tag:priming` / `#priming` → tag filter
|
|
12
|
+
* - `2026-05` / `2026-05-12` → updatedSince that date
|
|
13
|
+
* - Korean month `5월` → updatedSince that month
|
|
14
|
+
* (current year) — only when no explicit ISO date was given
|
|
15
|
+
*
|
|
16
|
+
* Date parsing deliberately omits bare English month words: "may" / "march"
|
|
17
|
+
* collide with the modal verb and the imperative, and a wrong date filter
|
|
18
|
+
* is exactly the over-narrowing the operator flagged in decision 4. English
|
|
19
|
+
* callers use ISO dates (`2026-05`) for date intent. Everything recognized
|
|
20
|
+
* is stripped from the query to form `semanticText`, which gets embedded.
|
|
21
|
+
*/
|
|
22
|
+
export function parseIntent(query, now = new Date()) {
|
|
23
|
+
const notes = [];
|
|
24
|
+
const types = [];
|
|
25
|
+
const tags = [];
|
|
26
|
+
let updatedSinceMs;
|
|
27
|
+
let remaining = query;
|
|
28
|
+
// key:value / key=value for type and tag (also #tag)
|
|
29
|
+
remaining = remaining.replace(/\b(type)[:=]("[^"]+"|\S+)/gi, (_m, _k, v) => {
|
|
30
|
+
const val = unquote(v);
|
|
31
|
+
types.push(val);
|
|
32
|
+
notes.push(`type=${val}`);
|
|
33
|
+
return " ";
|
|
34
|
+
});
|
|
35
|
+
remaining = remaining.replace(/\b(tag)[:=]("[^"]+"|\S+)/gi, (_m, _k, v) => {
|
|
36
|
+
const val = unquote(v);
|
|
37
|
+
tags.push(val);
|
|
38
|
+
notes.push(`tag=${val}`);
|
|
39
|
+
return " ";
|
|
40
|
+
});
|
|
41
|
+
remaining = remaining.replace(/(^|\s)#([\p{L}\p{N}_-]+)/gu, (_m, lead, v) => {
|
|
42
|
+
tags.push(v);
|
|
43
|
+
notes.push(`tag=${v}`);
|
|
44
|
+
return lead;
|
|
45
|
+
});
|
|
46
|
+
// Explicit ISO date (YYYY-MM-DD or YYYY-MM) takes precedence over month words.
|
|
47
|
+
const iso = remaining.match(/\b(\d{4})-(\d{2})(?:-(\d{2}))?\b/);
|
|
48
|
+
if (iso) {
|
|
49
|
+
const y = Number(iso[1]);
|
|
50
|
+
const mo = Number(iso[2]);
|
|
51
|
+
const d = iso[3] ? Number(iso[3]) : 1;
|
|
52
|
+
updatedSinceMs = Date.UTC(y, mo - 1, d);
|
|
53
|
+
notes.push(`updatedSince=${iso[0]}`);
|
|
54
|
+
remaining = remaining.replace(iso[0], " ");
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const monthIdx = matchMonth(remaining);
|
|
58
|
+
if (monthIdx) {
|
|
59
|
+
const y = now.getUTCFullYear();
|
|
60
|
+
updatedSinceMs = Date.UTC(y, monthIdx.index, 1);
|
|
61
|
+
notes.push(`updatedSince=${y}-${String(monthIdx.index + 1).padStart(2, "0")} (from "${monthIdx.token}")`);
|
|
62
|
+
remaining = remaining.replace(monthIdx.token, " ");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const filters = {};
|
|
66
|
+
if (types.length > 0)
|
|
67
|
+
filters.type = dedupe(types);
|
|
68
|
+
if (tags.length > 0)
|
|
69
|
+
filters.tags = dedupe(tags);
|
|
70
|
+
if (updatedSinceMs !== undefined)
|
|
71
|
+
filters.updatedSinceMs = updatedSinceMs;
|
|
72
|
+
return {
|
|
73
|
+
filters,
|
|
74
|
+
semanticText: remaining.replace(/\s+/g, " ").trim() || query.trim(),
|
|
75
|
+
notes,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function unquote(s) {
|
|
79
|
+
return s.replace(/^"(.*)"$/, "$1");
|
|
80
|
+
}
|
|
81
|
+
function dedupe(xs) {
|
|
82
|
+
return [...new Set(xs)];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Match a Korean `N월` month reference (1–12), not preceded by another
|
|
86
|
+
* digit so "15월" does not match "5월". Returns the 0-based month index and
|
|
87
|
+
* the matched token to strip.
|
|
88
|
+
*/
|
|
89
|
+
function matchMonth(s) {
|
|
90
|
+
const hit = s.match(/(?<!\d)(1[0-2]|[1-9])월/);
|
|
91
|
+
if (!hit)
|
|
92
|
+
return null;
|
|
93
|
+
return { index: Number(hit[1]) - 1, token: hit[0] };
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/recall/intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RecallResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Render hits as a compact text list — for the *explicit* `/recall` surface
|
|
4
|
+
* or any host that wants a report. Ambient, in-conversation use should
|
|
5
|
+
* *not* call this; it should read the structured hits and phrase them
|
|
6
|
+
* naturally (operator decision 5). Offered as a convenience, not the
|
|
7
|
+
* mandatory output path. Pure function of the result — no slash-commands
|
|
8
|
+
* dependency, so it stays inside the module.
|
|
9
|
+
*/
|
|
10
|
+
export declare function renderRecallHits(result: RecallResult): string;
|
|
11
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/recall/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAO7D"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render hits as a compact text list — for the *explicit* `/recall` surface
|
|
3
|
+
* or any host that wants a report. Ambient, in-conversation use should
|
|
4
|
+
* *not* call this; it should read the structured hits and phrase them
|
|
5
|
+
* naturally (operator decision 5). Offered as a convenience, not the
|
|
6
|
+
* mandatory output path. Pure function of the result — no slash-commands
|
|
7
|
+
* dependency, so it stays inside the module.
|
|
8
|
+
*/
|
|
9
|
+
export function renderRecallHits(result) {
|
|
10
|
+
if (result.hits.length === 0) {
|
|
11
|
+
return `No memories matched "${result.query}".`;
|
|
12
|
+
}
|
|
13
|
+
const lines = result.hits.map((h, i) => formatHit(h, i + 1));
|
|
14
|
+
const header = `${result.hits.length} match${result.hits.length === 1 ? "" : "es"} for "${result.query}":`;
|
|
15
|
+
return [header, ...lines].join("\n");
|
|
16
|
+
}
|
|
17
|
+
function formatHit(h, rank) {
|
|
18
|
+
const pct = `${Math.round(h.score * 100)}%`;
|
|
19
|
+
const when = h.updated ? ` · ${h.updated}` : "";
|
|
20
|
+
const tags = h.tags.length ? ` · #${h.tags.slice(0, 4).join(" #")}` : "";
|
|
21
|
+
return `${rank}. [${pct}] ${h.name} (${h.type}${when})${tags}\n ${h.description || h.excerpt}`;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/recall/render.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,wBAAwB,MAAM,CAAC,KAAK,IAAI,CAAC;IAClD,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,SAAS,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,MAAM,CAAC,KAAK,IAAI,CAAC;IAC3G,OAAO,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,SAAS,CAAC,CAAY,EAAE,IAAY;IAC3C,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC;IAC5C,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,OAAO,GAAG,IAAI,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,QAAQ,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;AACnG,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { MemoryQuery } from "../sqlite/types.js";
|
|
2
|
+
import type { VectorSource } from "../vector/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* `recall` namespace types — two-stage hybrid retrieval over memories
|
|
5
|
+
* (Phase 11c, 2026-05-29).
|
|
6
|
+
*
|
|
7
|
+
* Design intent (operator decision 5): the engine returns *data*, not a
|
|
8
|
+
* formatted report. The same hits feed two surfaces — an explicit
|
|
9
|
+
* `/recall` command (which may render a compact list) and ambient,
|
|
10
|
+
* in-conversation use where the host weaves a hit into natural prose
|
|
11
|
+
* ("you designed something similar in project A a few days ago — reuse
|
|
12
|
+
* it?"). The engine deliberately does not decide which; it hands back
|
|
13
|
+
* structured hits and lets the host phrase them.
|
|
14
|
+
*/
|
|
15
|
+
/** Filters parsed out of a natural-language query (loose, regex-based). */
|
|
16
|
+
export interface ParsedIntent {
|
|
17
|
+
/** SQLite hard-filter derived from the query, if any obvious filters were found. */
|
|
18
|
+
readonly filters: MemoryQuery;
|
|
19
|
+
/** The query with recognized filter tokens stripped — used for embedding. */
|
|
20
|
+
readonly semanticText: string;
|
|
21
|
+
/** Human-readable note of what was parsed (diagnostics / transparency). */
|
|
22
|
+
readonly notes: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
/** One recall result. Carries enough for both a list render and prose phrasing. */
|
|
25
|
+
export interface RecallHit {
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly source: VectorSource;
|
|
28
|
+
/** Cosine similarity to the query (1 = identical direction). */
|
|
29
|
+
readonly score: number;
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly description: string;
|
|
32
|
+
readonly type: string;
|
|
33
|
+
readonly updated: string | null;
|
|
34
|
+
readonly tags: readonly string[];
|
|
35
|
+
/** A short body excerpt (first ~280 chars, whitespace-collapsed). */
|
|
36
|
+
readonly excerpt: string;
|
|
37
|
+
}
|
|
38
|
+
/** Inputs to a recall run. */
|
|
39
|
+
export interface RecallParams {
|
|
40
|
+
/** Natural-language query. */
|
|
41
|
+
readonly query: string;
|
|
42
|
+
/** Max hits. Default 5. */
|
|
43
|
+
readonly k?: number;
|
|
44
|
+
/** Restrict to one corpus. Omit to search all (currently only `memory`). */
|
|
45
|
+
readonly source?: VectorSource;
|
|
46
|
+
/**
|
|
47
|
+
* Force-disable the SQLite hard-filter even when intent parsing finds
|
|
48
|
+
* filters. Default behavior keeps the filter *loose* (see engine docs):
|
|
49
|
+
* if the filter would leave fewer than `k` candidates, it is dropped and
|
|
50
|
+
* the semantic stage runs over the full corpus instead.
|
|
51
|
+
*/
|
|
52
|
+
readonly noHardFilter?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/** What the two-stage pipeline actually did — surfaced for transparency. */
|
|
55
|
+
export interface RecallStageInfo {
|
|
56
|
+
/** Filters applied as a hard pre-filter (empty if none / dropped). */
|
|
57
|
+
readonly appliedFilters: MemoryQuery;
|
|
58
|
+
/** Candidate count after the hard-filter stage (before semantic rerank). */
|
|
59
|
+
readonly hardFilterCandidates: number;
|
|
60
|
+
/** Whether the hard-filter was dropped for being too narrow. */
|
|
61
|
+
readonly hardFilterDropped: boolean;
|
|
62
|
+
/** Total vectors in the searched corpus. */
|
|
63
|
+
readonly corpusSize: number;
|
|
64
|
+
}
|
|
65
|
+
/** Result of a recall run — structured data, never a pre-rendered report. */
|
|
66
|
+
export interface RecallResult {
|
|
67
|
+
readonly query: string;
|
|
68
|
+
readonly intent: ParsedIntent;
|
|
69
|
+
readonly stage: RecallStageInfo;
|
|
70
|
+
readonly hits: readonly RecallHit[];
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/recall/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;;;;GAWG;AAEH,2EAA2E;AAC3E,MAAM,WAAW,YAAY;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,mFAAmF;AACnF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,8BAA8B;AAC9B,MAAM,WAAW,YAAY;IAC3B,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,4EAA4E;IAC5E,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,gEAAgE;IAChE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,4CAA4C;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;CACrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/recall/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../src/sessionArchive/adapters/claude-code.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAIV,iBAAiB,EAGlB,MAAM,aAAa,CAAC;AAoCrB,eAAO,MAAM,iBAAiB,EAAE,iBA4C/B,CAAC"}
|