code-session-memory 0.3.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.
Files changed (52) hide show
  1. package/README.md +290 -0
  2. package/dist/mcp/index.d.ts +15 -0
  3. package/dist/mcp/index.d.ts.map +1 -0
  4. package/dist/mcp/index.js +140 -0
  5. package/dist/mcp/index.js.map +1 -0
  6. package/dist/mcp/server.d.ts +60 -0
  7. package/dist/mcp/server.d.ts.map +1 -0
  8. package/dist/mcp/server.js +192 -0
  9. package/dist/mcp/server.js.map +1 -0
  10. package/dist/src/chunker.d.ts +18 -0
  11. package/dist/src/chunker.d.ts.map +1 -0
  12. package/dist/src/chunker.js +149 -0
  13. package/dist/src/chunker.js.map +1 -0
  14. package/dist/src/cli.d.ts +11 -0
  15. package/dist/src/cli.d.ts.map +1 -0
  16. package/dist/src/cli.js +514 -0
  17. package/dist/src/cli.js.map +1 -0
  18. package/dist/src/database.d.ts +50 -0
  19. package/dist/src/database.d.ts.map +1 -0
  20. package/dist/src/database.js +238 -0
  21. package/dist/src/database.js.map +1 -0
  22. package/dist/src/embedder.d.ts +19 -0
  23. package/dist/src/embedder.d.ts.map +1 -0
  24. package/dist/src/embedder.js +80 -0
  25. package/dist/src/embedder.js.map +1 -0
  26. package/dist/src/indexer-cli-claude.d.ts +14 -0
  27. package/dist/src/indexer-cli-claude.d.ts.map +1 -0
  28. package/dist/src/indexer-cli-claude.js +67 -0
  29. package/dist/src/indexer-cli-claude.js.map +1 -0
  30. package/dist/src/indexer-cli.d.ts +16 -0
  31. package/dist/src/indexer-cli.d.ts.map +1 -0
  32. package/dist/src/indexer-cli.js +53 -0
  33. package/dist/src/indexer-cli.js.map +1 -0
  34. package/dist/src/indexer.d.ts +44 -0
  35. package/dist/src/indexer.d.ts.map +1 -0
  36. package/dist/src/indexer.js +129 -0
  37. package/dist/src/indexer.js.map +1 -0
  38. package/dist/src/session-to-md.d.ts +15 -0
  39. package/dist/src/session-to-md.d.ts.map +1 -0
  40. package/dist/src/session-to-md.js +148 -0
  41. package/dist/src/session-to-md.js.map +1 -0
  42. package/dist/src/transcript-to-messages.d.ts +32 -0
  43. package/dist/src/transcript-to-messages.d.ts.map +1 -0
  44. package/dist/src/transcript-to-messages.js +230 -0
  45. package/dist/src/transcript-to-messages.js.map +1 -0
  46. package/dist/src/types.d.ts +91 -0
  47. package/dist/src/types.d.ts.map +1 -0
  48. package/dist/src/types.js +3 -0
  49. package/dist/src/types.js.map +1 -0
  50. package/package.json +59 -0
  51. package/plugin/memory.ts +42 -0
  52. package/skill/memory.md +61 -0
package/README.md ADDED
@@ -0,0 +1,290 @@
1
+ # code-session-memory
2
+
3
+ Automatic vector memory for [OpenCode](https://opencode.ai) and [Claude Code](https://claude.ai/code) sessions — shared across both tools.
4
+
5
+ Every time the AI agent finishes its turn, `code-session-memory` automatically indexes the new messages into a local [sqlite-vec](https://github.com/asg017/sqlite-vec) vector database. Past sessions become semantically searchable — both by the AI agent (via the MCP server) and by you. Sessions from both OpenCode and Claude Code are stored in the **same database**, so memory is shared across tools.
6
+
7
+ ## How it works
8
+
9
+ ```
10
+ OpenCode (session.idle event) Claude Code (Stop hook)
11
+ │ │
12
+ │ fetches messages via REST API │ reads JSONL transcript
13
+ ▼ ▼
14
+ session-to-md transcript-to-messages
15
+ │ │
16
+ └───────────────┬───────────────────────┘
17
+
18
+ chunker → heading-aware chunks (≤1000 tokens, 10% overlap)
19
+
20
+
21
+ embedder → OpenAI text-embedding-3-large (3072 dims)
22
+
23
+
24
+ sqlite-vec DB → ~/.local/share/code-session-memory/sessions.db
25
+
26
+
27
+ MCP server → query_sessions / get_session_chunks tools
28
+ ```
29
+
30
+ Only **new messages** are indexed on each turn — previously indexed messages are skipped (tracked via `sessions_meta` table). This makes each indexing pass fast, even in long sessions.
31
+
32
+ ## Installation
33
+
34
+ ### Prerequisites
35
+
36
+ - Node.js ≥ 18
37
+ - An OpenAI API key (for `text-embedding-3-large`)
38
+ - OpenCode and/or Claude Code installed
39
+
40
+ ### Install
41
+
42
+ ```bash
43
+ npx code-session-memory install
44
+ ```
45
+
46
+ The `install` command sets up everything for both tools in one shot:
47
+
48
+ **OpenCode:**
49
+ 1. Copies the plugin to `~/.config/opencode/plugins/code-session-memory.ts`
50
+ 2. Copies the skill to `~/.config/opencode/skills/code-session-memory.md`
51
+ 3. Writes the MCP server entry into `~/.config/opencode/opencode.json`
52
+
53
+ **Claude Code:**
54
+ 1. Writes a `Stop` hook to `~/.claude/settings.json` (fires after each agent turn)
55
+ 2. Injects the skill into `~/.claude/CLAUDE.md` (with idempotent markers)
56
+ 3. Registers the MCP server via `claude mcp add`
57
+
58
+ **Both tools share:**
59
+ - The same database at `~/.local/share/code-session-memory/sessions.db`
60
+ - The same MCP server for querying past sessions
61
+
62
+ Then **restart OpenCode / Claude Code** to activate.
63
+
64
+ ### Set your API key
65
+
66
+ ```bash
67
+ export OPENAI_API_KEY=sk-...
68
+ ```
69
+
70
+ Add this to your shell profile (`.bashrc`, `.zshrc`, etc.) so it's always available.
71
+
72
+ ## Usage
73
+
74
+ Once installed, memory indexing is **fully automatic**. No further action needed — sessions are indexed as you use OpenCode or Claude Code.
75
+
76
+ ### Verify installation
77
+
78
+ ```bash
79
+ npx code-session-memory status
80
+ ```
81
+
82
+ Output:
83
+ ```
84
+ code-session-memory status
85
+
86
+ Database ~/.local/share/code-session-memory/sessions.db ✓
87
+ Indexed chunks: 1842
88
+ Sessions tracked: 47
89
+
90
+ OpenCode
91
+ Plugin ~/.config/opencode/plugins/code-session-memory.ts ✓
92
+ Skill ~/.config/opencode/skills/code-session-memory.md ✓
93
+ MCP server /path/to/dist/mcp/index.js ✓
94
+ MCP config ~/.config/opencode/opencode.json ✓
95
+
96
+ Claude Code
97
+ Stop hook ~/.claude/settings.json ✓
98
+ Skill ~/.claude/CLAUDE.md ✓
99
+ MCP server /path/to/dist/mcp/index.js ✓
100
+ ```
101
+
102
+ ### MCP tools
103
+
104
+ The agent can use two MCP tools (and will automatically via the installed skill):
105
+
106
+ #### `query_sessions`
107
+
108
+ Semantic search across all indexed sessions.
109
+
110
+ | Parameter | Type | Required | Description |
111
+ |---|---|---|---|
112
+ | `queryText` | string | yes | Natural language query |
113
+ | `project` | string | no | Filter by project directory path |
114
+ | `source` | string | no | Filter by tool: `"opencode"` or `"claude-code"` |
115
+ | `limit` | number | no | Max results (default: 5) |
116
+
117
+ Example result:
118
+ ```
119
+ Result 1:
120
+ Content: [Session: Add dark mode toggle > User]
121
+
122
+ How can I implement a dark mode toggle using CSS variables?
123
+ Distance: 0.1823
124
+ URL: session://ses_abc123#msg_def456
125
+ Section: User
126
+ Chunk: 1 of 1
127
+ ---
128
+ ```
129
+
130
+ #### `get_session_chunks`
131
+
132
+ Retrieve the full ordered content of a specific session message. Use the `session://ses_xxx#msg_yyy` URL from `query_sessions` results.
133
+
134
+ | Parameter | Type | Required | Description |
135
+ |---|---|---|---|
136
+ | `sessionUrl` | string | yes | URL from `query_sessions` result |
137
+ | `startIndex` | number | no | First chunk index (0-based) |
138
+ | `endIndex` | number | no | Last chunk index (0-based, inclusive) |
139
+
140
+ ### Asking the agent about past sessions
141
+
142
+ The installed skill teaches the agent when and how to use these tools. Example prompts:
143
+
144
+ ```
145
+ How did we implement the authentication middleware last week?
146
+ Have we discussed this error before?
147
+ What was our decision about the database schema?
148
+ Show me how we solved the TypeScript config issue.
149
+ ```
150
+
151
+ ## Configuration
152
+
153
+ ### Environment variables
154
+
155
+ | Variable | Default | Description |
156
+ |---|---|---|
157
+ | `OPENAI_API_KEY` | — | **Required.** Used for embedding generation. |
158
+ | `OPENCODE_MEMORY_DB_PATH` | `~/.local/share/code-session-memory/sessions.db` | Override the database path. |
159
+ | `OPENCODE_CONFIG_DIR` | `~/.config/opencode` | Override the OpenCode config directory. |
160
+ | `OPENAI_MODEL` | `text-embedding-3-large` | Override the embedding model. |
161
+
162
+ ### Database path
163
+
164
+ The default database path works on both **macOS** and **Linux**. On macOS, `~/.local/share` is used for cross-platform consistency (rather than `~/Library/Application Support`).
165
+
166
+ To change it:
167
+ ```bash
168
+ export OPENCODE_MEMORY_DB_PATH=/custom/path/sessions.db
169
+ npx code-session-memory install
170
+ ```
171
+
172
+ ## Project structure
173
+
174
+ ```
175
+ code-session-memory/
176
+ ├── src/
177
+ │ ├── types.ts # Shared TypeScript types
178
+ │ ├── database.ts # SQLite-vec: init, insert, query
179
+ │ ├── chunker.ts # Heading-aware markdown chunker
180
+ │ ├── embedder.ts # OpenAI embeddings (batched)
181
+ │ ├── session-to-md.ts # OpenCode SDK messages → markdown
182
+ │ ├── transcript-to-messages.ts # Claude Code JSONL transcript parser
183
+ │ ├── indexer.ts # Orchestrator: incremental indexing
184
+ │ ├── indexer-cli.ts # Node.js subprocess (called by OpenCode plugin)
185
+ │ ├── indexer-cli-claude.ts # Node.js subprocess (called by Claude Code hook)
186
+ │ └── cli.ts # install / status / uninstall commands
187
+ ├── mcp/
188
+ │ ├── server.ts # MCP query handlers (testable, injected deps)
189
+ │ └── index.ts # MCP stdio server entry point
190
+ ├── plugin/
191
+ │ └── memory.ts # OpenCode plugin (session.idle hook)
192
+ ├── skill/
193
+ │ └── memory.md # Skill instructions (injected into both tools)
194
+ └── tests/
195
+ ├── chunker.test.ts
196
+ ├── database.test.ts
197
+ ├── embedder.test.ts
198
+ ├── indexer.test.ts
199
+ ├── mcp-server.test.ts
200
+ └── session-to-md.test.ts
201
+ ```
202
+
203
+ ## Development
204
+
205
+ ```bash
206
+ # Install dependencies
207
+ npm install
208
+
209
+ # Build
210
+ npm run build
211
+
212
+ # Run tests
213
+ npm test
214
+
215
+ # Watch mode
216
+ npm run test:watch
217
+
218
+ # Coverage report
219
+ npm run test:coverage
220
+ ```
221
+
222
+ ### Running tests
223
+
224
+ Tests use [Vitest](https://vitest.dev) and run without any external dependencies:
225
+ - No real OpenAI API calls — the embedder is mocked
226
+ - No real DB files — SQLite uses in-memory databases (`:memory:`) for unit tests
227
+ - Indexer tests use a temp directory on disk
228
+
229
+ ```
230
+ ✓ tests/chunker.test.ts (15 tests)
231
+ ✓ tests/mcp-server.test.ts (13 tests)
232
+ ✓ tests/session-to-md.test.ts (18 tests)
233
+ ✓ tests/embedder.test.ts (9 tests)
234
+ ✓ tests/database.test.ts (25 tests)
235
+ ✓ tests/indexer.test.ts (8 tests)
236
+ Tests 88 passed
237
+ ```
238
+
239
+ ## Uninstall
240
+
241
+ ```bash
242
+ npx code-session-memory uninstall
243
+ ```
244
+
245
+ This removes the plugin, hooks, and skill files for both tools. The database is **not** removed automatically.
246
+
247
+ To also remove the database:
248
+ ```bash
249
+ rm ~/.local/share/code-session-memory/sessions.db
250
+ ```
251
+
252
+ ## Architecture notes
253
+
254
+ ### Incremental indexing
255
+
256
+ The plugin/hook fires on every agent turn. To avoid re-processing the entire session history each time, the indexer:
257
+
258
+ 1. Reads `last_indexed_message_id` from the `sessions_meta` table
259
+ 2. Skips all messages up to and including that ID
260
+ 3. Processes only the new messages
261
+ 4. Updates `last_indexed_message_id` after success
262
+
263
+ This makes each indexing pass O(new messages) rather than O(all messages).
264
+
265
+ ### Why a Node.js subprocess?
266
+
267
+ OpenCode plugins run inside **Bun**, but `better-sqlite3` and `sqlite-vec` are native Node.js addons that don't load under Bun. The plugin therefore spawns a Node.js subprocess (`indexer-cli.js`) to handle all database operations. The Claude Code hook calls a similar subprocess (`indexer-cli-claude.js`) which reads the transcript JSONL from disk.
268
+
269
+ ### Claude Code transcript parsing
270
+
271
+ Claude Code writes a JSONL transcript after each session turn. The parser (`transcript-to-messages.ts`) handles:
272
+ - Deduplicating streaming `assistant` chunks (keeps the last entry per `message.id`)
273
+ - Skipping internal `thinking` blocks, metadata entries, and error messages
274
+ - Converting `tool_use` / `tool_result` entries to readable markdown
275
+
276
+ ### Chunking strategy
277
+
278
+ - Heading-aware splitting — headings define semantic boundaries
279
+ - Max 1000 whitespace-tokenized words per chunk
280
+ - Sections below 150 words are merged with adjacent sections
281
+ - Sections above 1000 words are split with 10% overlap
282
+ - Each chunk gets a `[Session: Title > Section]` breadcrumb prefix injected before embedding, improving retrieval precision
283
+
284
+ ### MCP server
285
+
286
+ The MCP server uses **stdio transport** — the simplest and most reliable transport for local use. It opens and closes the SQLite connection on each query (no persistent connection), making it safe to run alongside the indexer. The `query_sessions` tool accepts an optional `source` parameter to filter results to a specific tool.
287
+
288
+ ## License
289
+
290
+ MIT
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * code-session-memory MCP server (stdio transport).
4
+ *
5
+ * Exposes two tools:
6
+ * - query_sessions — semantic search across indexed sessions (OpenCode + Claude Code)
7
+ * - get_session_chunks — retrieve ordered chunks for a specific session URL
8
+ *
9
+ * Environment variables:
10
+ * OPENAI_API_KEY — required for embedding generation
11
+ * OPENAI_MODEL — embedding model (default: text-embedding-3-large)
12
+ * OPENCODE_MEMORY_DB_PATH — path to the sqlite-vec DB
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../mcp/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * code-session-memory MCP server (stdio transport).
5
+ *
6
+ * Exposes two tools:
7
+ * - query_sessions — semantic search across indexed sessions (OpenCode + Claude Code)
8
+ * - get_session_chunks — retrieve ordered chunks for a specific session URL
9
+ *
10
+ * Environment variables:
11
+ * OPENAI_API_KEY — required for embedding generation
12
+ * OPENAI_MODEL — embedding model (default: text-embedding-3-large)
13
+ * OPENCODE_MEMORY_DB_PATH — path to the sqlite-vec DB
14
+ */
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ var __importDefault = (this && this.__importDefault) || function (mod) {
49
+ return (mod && mod.__esModule) ? mod : { "default": mod };
50
+ };
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
53
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
54
+ const zod_1 = require("zod");
55
+ const openai_1 = require("openai");
56
+ const sqliteVec = __importStar(require("sqlite-vec"));
57
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
58
+ const fs_1 = __importDefault(require("fs"));
59
+ const database_1 = require("../src/database");
60
+ const server_1 = require("./server");
61
+ // ---------------------------------------------------------------------------
62
+ // Configuration
63
+ // ---------------------------------------------------------------------------
64
+ const dbPath = (0, database_1.resolveDbPath)();
65
+ const openAiApiKey = process.env.OPENAI_API_KEY;
66
+ const openAiModel = process.env.OPENAI_MODEL ?? "text-embedding-3-large";
67
+ if (!openAiApiKey) {
68
+ console.error("Error: OPENAI_API_KEY environment variable is required.");
69
+ process.exit(1);
70
+ }
71
+ if (!fs_1.default.existsSync(dbPath)) {
72
+ console.error(`Error: Database not found at ${dbPath}.\nRun "npx code-session-memory install" first.`);
73
+ process.exit(1);
74
+ }
75
+ // ---------------------------------------------------------------------------
76
+ // Embedding function
77
+ // ---------------------------------------------------------------------------
78
+ const openai = new openai_1.OpenAI({ apiKey: openAiApiKey });
79
+ async function createEmbedding(text) {
80
+ const MAX_CHARS = 8191 * 4;
81
+ const input = text.length > MAX_CHARS ? text.slice(0, MAX_CHARS) : text;
82
+ const response = await openai.embeddings.create({ model: openAiModel, input });
83
+ const embedding = response.data?.[0]?.embedding;
84
+ if (!embedding)
85
+ throw new Error("No embedding returned from OpenAI API");
86
+ return embedding;
87
+ }
88
+ // ---------------------------------------------------------------------------
89
+ // SQLite provider + tool handlers
90
+ // ---------------------------------------------------------------------------
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ const provider = (0, server_1.createSqliteProvider)({
93
+ dbPath,
94
+ sqliteVec: sqliteVec,
95
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
96
+ Database: better_sqlite3_1.default,
97
+ fs: fs_1.default,
98
+ });
99
+ const { querySessionsHandler, getSessionChunksHandler } = (0, server_1.createToolHandlers)({
100
+ createEmbedding,
101
+ querySessions: provider.querySessions,
102
+ getSessionChunks: provider.getSessionChunks,
103
+ });
104
+ // ---------------------------------------------------------------------------
105
+ // MCP server
106
+ // ---------------------------------------------------------------------------
107
+ const server = new mcp_js_1.McpServer({
108
+ name: "code-session-memory",
109
+ version: "0.3.0",
110
+ });
111
+ // Zod schemas defined separately to avoid type instantiation depth issues
112
+ const querySessionsSchema = {
113
+ queryText: zod_1.z.string().min(1).describe("Natural language description of what you are looking for."),
114
+ project: zod_1.z.string().optional().describe("Filter results to a specific project directory path (e.g. '/Users/me/myproject'). Optional."),
115
+ source: zod_1.z.enum(["opencode", "claude-code"]).optional().describe("Filter results by tool source: 'opencode' or 'claude-code'. Optional — omit to search across both."),
116
+ limit: zod_1.z.number().int().min(1).optional().describe("Maximum number of results to return. Defaults to 5."),
117
+ };
118
+ const getSessionChunksSchema = {
119
+ sessionUrl: zod_1.z.string().min(1).describe("The session message URL from a query_sessions result (e.g. 'session://ses_xxx#msg_yyy')."),
120
+ startIndex: zod_1.z.number().int().min(0).optional().describe("First chunk index to retrieve (0-based, inclusive). Optional."),
121
+ endIndex: zod_1.z.number().int().min(0).optional().describe("Last chunk index to retrieve (0-based, inclusive). Optional."),
122
+ };
123
+ // Cast server to any to avoid deep MCP SDK Zod type instantiation (TS2589)
124
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
125
+ const serverAny = server;
126
+ serverAny.tool("query_sessions", "Semantically search across all indexed sessions stored in the vector database. Returns the most relevant chunks from past sessions. Sessions from both OpenCode and Claude Code are indexed into the same shared database.", querySessionsSchema, async (args) => querySessionsHandler({ ...args, limit: args.limit ?? 5 }));
127
+ serverAny.tool("get_session_chunks", "Retrieve the ordered content chunks for a specific session message. Use the URL from query_sessions results (e.g. 'session://ses_xxx#msg_yyy') to get the full context around a match.", getSessionChunksSchema, async (args) => getSessionChunksHandler(args));
128
+ // ---------------------------------------------------------------------------
129
+ // Start
130
+ // ---------------------------------------------------------------------------
131
+ async function main() {
132
+ const transport = new stdio_js_1.StdioServerTransport();
133
+ await server.connect(transport);
134
+ console.error(`code-session-memory MCP server running (DB: ${dbPath})`);
135
+ }
136
+ main().catch((err) => {
137
+ console.error("Failed to start MCP server:", err);
138
+ process.exit(1);
139
+ });
140
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../mcp/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * MCP query handlers for opencode-memory.
3
+ *
4
+ * Adapted from doc2vec/mcp/src/server.ts — simplified to:
5
+ * - SQLite-vec only (no Qdrant)
6
+ * - Fixed single DB path (no multi-DB resolution)
7
+ * - Two tools: query_sessions + get_session_chunks
8
+ */
9
+ import type { QueryResult } from "../src/types";
10
+ export type { QueryResult };
11
+ type SqliteVecModule = {
12
+ load: (db: SqliteDatabase) => void;
13
+ };
14
+ type SqliteDatabase = {
15
+ prepare: (sql: string) => SqliteStatement;
16
+ close: () => void;
17
+ };
18
+ type SqliteStatement = {
19
+ all: (...params: unknown[]) => unknown[];
20
+ };
21
+ type FsModule = {
22
+ existsSync: (p: string) => boolean;
23
+ };
24
+ export declare function createSqliteProvider(deps: {
25
+ dbPath: string;
26
+ sqliteVec: SqliteVecModule;
27
+ Database: new (path: string) => SqliteDatabase;
28
+ fs: FsModule;
29
+ }): {
30
+ querySessions: (queryEmbedding: number[], topK?: number, projectFilter?: string, sourceFilter?: string) => Promise<QueryResult[]>;
31
+ getSessionChunks: (url: string, startIndex?: number, endIndex?: number) => Promise<QueryResult[]>;
32
+ };
33
+ export declare function createToolHandlers(deps: {
34
+ createEmbedding: (text: string) => Promise<number[]>;
35
+ querySessions: (embedding: number[], topK: number, project?: string, source?: string) => Promise<QueryResult[]>;
36
+ getSessionChunks: (url: string, startIndex?: number, endIndex?: number) => Promise<QueryResult[]>;
37
+ }): {
38
+ querySessionsHandler: (args: {
39
+ queryText: string;
40
+ project?: string;
41
+ source?: string;
42
+ limit?: number;
43
+ }) => Promise<{
44
+ content: {
45
+ type: "text";
46
+ text: string;
47
+ }[];
48
+ }>;
49
+ getSessionChunksHandler: (args: {
50
+ sessionUrl: string;
51
+ startIndex?: number;
52
+ endIndex?: number;
53
+ }) => Promise<{
54
+ content: {
55
+ type: "text";
56
+ text: string;
57
+ }[];
58
+ }>;
59
+ };
60
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD,YAAY,EAAE,WAAW,EAAE,CAAC;AAM5B,KAAK,eAAe,GAAG;IAAE,IAAI,EAAE,CAAC,EAAE,EAAE,cAAc,KAAK,IAAI,CAAA;CAAE,CAAC;AAC9D,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,eAAe,CAAC;IAC1C,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AACF,KAAK,eAAe,GAAG;IACrB,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC;CAC1C,CAAC;AACF,KAAK,QAAQ,GAAG;IAAE,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;CAAE,CAAC;AAMvD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,eAAe,CAAC;IAC3B,QAAQ,EAAE,KAAK,IAAI,EAAE,MAAM,KAAK,cAAc,CAAC;IAC/C,EAAE,EAAE,QAAQ,CAAC;CACd;oCAsBmB,MAAM,EAAE,iCAER,MAAM,iBACP,MAAM,KACpB,OAAO,CAAC,WAAW,EAAE,CAAC;4BA0ClB,MAAM,eACE,MAAM,aACR,MAAM,KAChB,OAAO,CAAC,WAAW,EAAE,CAAC;EAwB1B;AAMD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACrD,aAAa,EAAE,CACb,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,KACZ,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5B,gBAAgB,EAAE,CAChB,GAAG,EAAE,MAAM,EACX,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;CAC7B;iCAK2C;QACxC,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB;;;;;;oCAuD4C;QAC3C,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;;;;;;EAwDF"}