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
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.indexNewMessages = indexNewMessages;
4
+ exports.indexNewMessagesWithOptions = indexNewMessagesWithOptions;
5
+ exports.reindexSession = reindexSession;
6
+ const database_1 = require("./database");
7
+ const chunker_1 = require("./chunker");
8
+ const embedder_1 = require("./embedder");
9
+ const session_to_md_1 = require("./session-to-md");
10
+ // ---------------------------------------------------------------------------
11
+ // Core indexer (accepts an already-open DB)
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Incrementally indexes new messages from a session into the vector DB.
15
+ *
16
+ * Only messages that have not been previously indexed are processed:
17
+ * - We store the last indexed message ID in sessions_meta.
18
+ * - On each call, we filter to messages that come AFTER that ID.
19
+ * - Each new message is converted to markdown, chunked, embedded and stored.
20
+ *
21
+ * @param db Already-open database connection (caller manages lifecycle)
22
+ * @param session Session metadata (id, title, directory)
23
+ * @param messages All messages in the session
24
+ * @param source Which tool produced the session ("opencode" | "claude-code")
25
+ * @param options Optional overrides for API key / model
26
+ */
27
+ async function indexNewMessages(db, session, messages, source = "opencode", options = {}) {
28
+ if (messages.length === 0) {
29
+ return { indexed: 0, skipped: 0 };
30
+ }
31
+ const sessionId = session.id;
32
+ const sessionTitle = session.title ?? sessionId;
33
+ const project = session.directory ?? "";
34
+ // Load or initialise the session meta record
35
+ const meta = (0, database_1.getSessionMeta)(db, sessionId);
36
+ const lastIndexedId = meta?.last_indexed_message_id ?? null;
37
+ // Filter to only messages after the last indexed one
38
+ let newMessages;
39
+ if (lastIndexedId === null) {
40
+ newMessages = messages;
41
+ }
42
+ else {
43
+ const lastIdx = messages.findIndex((m) => m.info.id === lastIndexedId);
44
+ newMessages = lastIdx === -1 ? messages : messages.slice(lastIdx + 1);
45
+ }
46
+ if (newMessages.length === 0) {
47
+ return { indexed: 0, skipped: messages.length };
48
+ }
49
+ const embedder = (0, embedder_1.createEmbedder)({
50
+ apiKey: options.openAiApiKey,
51
+ model: options.embeddingModel,
52
+ });
53
+ let totalChunksIndexed = 0;
54
+ for (const msg of newMessages) {
55
+ const md = (0, session_to_md_1.messageToMarkdown)(msg);
56
+ if (!md.trim())
57
+ continue;
58
+ const msgUrl = `session://${sessionId}#${msg.info.id}`;
59
+ const chunks = (0, chunker_1.chunkMarkdown)(md, {
60
+ sessionId,
61
+ sessionTitle,
62
+ project,
63
+ baseUrl: msgUrl,
64
+ });
65
+ if (chunks.length === 0)
66
+ continue;
67
+ const texts = chunks.map((c) => c.content);
68
+ const embeddings = await embedder.embedBatch(texts);
69
+ (0, database_1.insertChunks)(db, chunks, embeddings);
70
+ totalChunksIndexed += chunks.length;
71
+ }
72
+ void totalChunksIndexed;
73
+ // Update session meta with the last message we processed
74
+ const lastMsg = newMessages[newMessages.length - 1];
75
+ (0, database_1.upsertSessionMeta)(db, {
76
+ session_id: sessionId,
77
+ session_title: sessionTitle,
78
+ project,
79
+ source,
80
+ last_indexed_message_id: lastMsg.info.id,
81
+ updated_at: Date.now(),
82
+ });
83
+ return { indexed: newMessages.length, skipped: messages.length - newMessages.length };
84
+ }
85
+ // ---------------------------------------------------------------------------
86
+ // Convenience wrappers (open+close their own DB connection)
87
+ // ---------------------------------------------------------------------------
88
+ /**
89
+ * Convenience wrapper that opens its own DB connection.
90
+ * Used by the OpenCode indexer-cli and by tests.
91
+ */
92
+ async function indexNewMessagesWithOptions(session, messages, source = "opencode", options = {}) {
93
+ if (messages.length === 0)
94
+ return { indexed: 0, skipped: 0 };
95
+ const dbPath = (0, database_1.resolveDbPath)(options.dbPath);
96
+ const db = (0, database_1.openDatabase)({ dbPath });
97
+ try {
98
+ return await indexNewMessages(db, session, messages, source, options);
99
+ }
100
+ finally {
101
+ db.close();
102
+ }
103
+ }
104
+ /**
105
+ * Re-indexes all messages in a session from scratch.
106
+ * Useful for repairing a corrupted or stale index.
107
+ */
108
+ async function reindexSession(session, messages, options = {}) {
109
+ const dbPath = (0, database_1.resolveDbPath)(options.dbPath);
110
+ const db = (0, database_1.openDatabase)({ dbPath });
111
+ try {
112
+ // Reset the last_indexed_message_id so all messages are treated as new
113
+ const existing = (0, database_1.getSessionMeta)(db, session.id);
114
+ (0, database_1.upsertSessionMeta)(db, {
115
+ session_id: session.id,
116
+ session_title: session.title ?? session.id,
117
+ project: session.directory ?? "",
118
+ source: existing?.source ?? "opencode",
119
+ last_indexed_message_id: null,
120
+ updated_at: Date.now(),
121
+ });
122
+ const result = await indexNewMessages(db, session, messages, existing?.source ?? "opencode", options);
123
+ return { indexed: result.indexed };
124
+ }
125
+ finally {
126
+ db.close();
127
+ }
128
+ }
129
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/indexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { SessionInfo, FullMessage } from "./types";
2
+ /**
3
+ * Converts an OpenCode session + its messages (as returned by the SDK) into
4
+ * a single markdown string suitable for chunking and embedding.
5
+ *
6
+ * @param session Session metadata from client.session.get()
7
+ * @param messages Messages array from client.session.messages()
8
+ */
9
+ export declare function sessionToMarkdown(session: SessionInfo, messages: FullMessage[]): string;
10
+ /**
11
+ * Converts a single message to markdown (used for incremental indexing of
12
+ * individual new messages rather than the full session).
13
+ */
14
+ export declare function messageToMarkdown(msg: FullMessage): string;
15
+ //# sourceMappingURL=session-to-md.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-to-md.d.ts","sourceRoot":"","sources":["../../src/session-to-md.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAe,MAAM,SAAS,CAAC;AAwHrE;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,WAAW,EAAE,GACtB,MAAM,CAgCR;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAE1D"}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sessionToMarkdown = sessionToMarkdown;
4
+ exports.messageToMarkdown = messageToMarkdown;
5
+ // ---------------------------------------------------------------------------
6
+ // Part renderers
7
+ // ---------------------------------------------------------------------------
8
+ function renderToolPart(part) {
9
+ const lines = [];
10
+ const name = part.toolName ?? "unknown";
11
+ lines.push(`**Tool: ${name}**`);
12
+ lines.push("");
13
+ if (part.args !== undefined) {
14
+ lines.push("**Input:**");
15
+ lines.push("```json");
16
+ lines.push(JSON.stringify(part.args, null, 2));
17
+ lines.push("```");
18
+ lines.push("");
19
+ }
20
+ if (part.state === "result" && part.result !== undefined) {
21
+ const result = part.result;
22
+ const resultStr = typeof result === "string"
23
+ ? result
24
+ : JSON.stringify(result, null, 2);
25
+ lines.push("**Output:**");
26
+ // Only wrap in code block if not already markdown-formatted
27
+ if (typeof result === "string" && !result.startsWith("```")) {
28
+ lines.push("```");
29
+ lines.push(resultStr);
30
+ lines.push("```");
31
+ }
32
+ else {
33
+ lines.push(resultStr);
34
+ }
35
+ lines.push("");
36
+ }
37
+ return lines.join("\n");
38
+ }
39
+ function renderFilePart(part) {
40
+ if (part.filename) {
41
+ return `**File:** \`${part.filename}\`\n`;
42
+ }
43
+ return "";
44
+ }
45
+ function renderPart(part) {
46
+ switch (part.type) {
47
+ case "text":
48
+ return (part.text ?? "").trim();
49
+ case "tool-invocation":
50
+ return renderToolPart(part);
51
+ case "file":
52
+ return renderFilePart(part);
53
+ // Internal bookkeeping — skip silently
54
+ case "step-start":
55
+ case "step-finish":
56
+ case "reasoning":
57
+ return "";
58
+ default:
59
+ // Unknown part type — try to render text if present
60
+ if (part.text)
61
+ return part.text.trim();
62
+ return "";
63
+ }
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Message renderer
67
+ // ---------------------------------------------------------------------------
68
+ function formatDuration(msg) {
69
+ const { created, completed } = msg.info.time ?? {};
70
+ if (created && completed) {
71
+ const secs = ((completed - created) / 1000).toFixed(1);
72
+ return `${secs}s`;
73
+ }
74
+ return "";
75
+ }
76
+ function renderMessageHeading(msg) {
77
+ const { role, agent, modelID } = msg.info;
78
+ if (role === "user") {
79
+ return "## User";
80
+ }
81
+ // Assistant: include agent + model + duration where available
82
+ const parts = [];
83
+ if (agent)
84
+ parts.push(agent);
85
+ if (modelID)
86
+ parts.push(modelID);
87
+ const duration = formatDuration(msg);
88
+ if (duration)
89
+ parts.push(duration);
90
+ const suffix = parts.length > 0 ? ` (${parts.join(" · ")})` : "";
91
+ return `## Assistant${suffix}`;
92
+ }
93
+ function renderMessage(msg) {
94
+ const heading = renderMessageHeading(msg);
95
+ const bodyParts = msg.parts
96
+ .map(renderPart)
97
+ .filter((s) => s.trim().length > 0);
98
+ if (bodyParts.length === 0)
99
+ return "";
100
+ return [heading, "", bodyParts.join("\n\n"), ""].join("\n");
101
+ }
102
+ // ---------------------------------------------------------------------------
103
+ // Session renderer
104
+ // ---------------------------------------------------------------------------
105
+ /**
106
+ * Converts an OpenCode session + its messages (as returned by the SDK) into
107
+ * a single markdown string suitable for chunking and embedding.
108
+ *
109
+ * @param session Session metadata from client.session.get()
110
+ * @param messages Messages array from client.session.messages()
111
+ */
112
+ function sessionToMarkdown(session, messages) {
113
+ const title = session.title ?? session.id;
114
+ const directory = session.directory ?? "";
115
+ const created = messages[0]?.info.time?.created;
116
+ const updated = messages[messages.length - 1]?.info.time?.completed
117
+ ?? messages[messages.length - 1]?.info.time?.created;
118
+ const header = [
119
+ `# ${title}`,
120
+ "",
121
+ `**Session ID:** ${session.id}`,
122
+ directory ? `**Project:** ${directory}` : null,
123
+ created
124
+ ? `**Created:** ${new Date(created).toLocaleString()}`
125
+ : null,
126
+ updated
127
+ ? `**Updated:** ${new Date(updated).toLocaleString()}`
128
+ : null,
129
+ "",
130
+ "---",
131
+ "",
132
+ ]
133
+ .filter((l) => l !== null)
134
+ .join("\n");
135
+ const body = messages
136
+ .map(renderMessage)
137
+ .filter((s) => s.trim().length > 0)
138
+ .join("\n---\n\n");
139
+ return header + body;
140
+ }
141
+ /**
142
+ * Converts a single message to markdown (used for incremental indexing of
143
+ * individual new messages rather than the full session).
144
+ */
145
+ function messageToMarkdown(msg) {
146
+ return renderMessage(msg);
147
+ }
148
+ //# sourceMappingURL=session-to-md.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-to-md.js","sourceRoot":"","sources":["../../src/session-to-md.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Parses a Claude Code JSONL transcript into the FullMessage[] format used
3
+ * by the indexer.
4
+ *
5
+ * Transcript format observations:
6
+ * - Each line is a JSON object with a `type` field
7
+ * - `type: "file-history-snapshot"` — internal snapshot, skip
8
+ * - `type: "user"` with `isMeta: true` — local command caveat, skip
9
+ * - `type: "user"` with array `content` of `tool_result` — tool output, keep
10
+ * - `type: "user"` with string `content` — regular user message, keep
11
+ * (but skip /command messages and login stdout noise)
12
+ * - `type: "assistant"` — may appear multiple times with the same `message.id`
13
+ * (streaming chunks); we keep the LAST entry per message.id
14
+ * - `isApiErrorMessage: true` — skip
15
+ * - Assistant `content` blocks of type "thinking" — skip (internal reasoning)
16
+ * - Assistant `content` blocks of type "tool_use" — keep (tool call)
17
+ * - User `content` array with `tool_result` — keep (tool output)
18
+ */
19
+ import type { FullMessage } from "./types";
20
+ /**
21
+ * Parses a Claude Code JSONL transcript file into FullMessage[].
22
+ *
23
+ * Deduplicates streaming assistant chunks (same message.id → keep last),
24
+ * and pairs tool_use calls with their tool_result responses.
25
+ */
26
+ export declare function parseTranscript(transcriptPath: string): FullMessage[];
27
+ /**
28
+ * Derives a session title from the transcript messages.
29
+ * Uses the first meaningful user message text, truncated to 60 chars.
30
+ */
31
+ export declare function deriveSessionTitle(messages: FullMessage[]): string;
32
+ //# sourceMappingURL=transcript-to-messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-to-messages.d.ts","sourceRoot":"","sources":["../../src/transcript-to-messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,SAAS,CAAC;AAgKxD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,EAAE,CAgGrE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAWlE"}
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ /**
3
+ * Parses a Claude Code JSONL transcript into the FullMessage[] format used
4
+ * by the indexer.
5
+ *
6
+ * Transcript format observations:
7
+ * - Each line is a JSON object with a `type` field
8
+ * - `type: "file-history-snapshot"` — internal snapshot, skip
9
+ * - `type: "user"` with `isMeta: true` — local command caveat, skip
10
+ * - `type: "user"` with array `content` of `tool_result` — tool output, keep
11
+ * - `type: "user"` with string `content` — regular user message, keep
12
+ * (but skip /command messages and login stdout noise)
13
+ * - `type: "assistant"` — may appear multiple times with the same `message.id`
14
+ * (streaming chunks); we keep the LAST entry per message.id
15
+ * - `isApiErrorMessage: true` — skip
16
+ * - Assistant `content` blocks of type "thinking" — skip (internal reasoning)
17
+ * - Assistant `content` blocks of type "tool_use" — keep (tool call)
18
+ * - User `content` array with `tool_result` — keep (tool output)
19
+ */
20
+ var __importDefault = (this && this.__importDefault) || function (mod) {
21
+ return (mod && mod.__esModule) ? mod : { "default": mod };
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.parseTranscript = parseTranscript;
25
+ exports.deriveSessionTitle = deriveSessionTitle;
26
+ const fs_1 = __importDefault(require("fs"));
27
+ // ---------------------------------------------------------------------------
28
+ // Converters
29
+ // ---------------------------------------------------------------------------
30
+ function convertUserMessage(line) {
31
+ const content = line.message.content;
32
+ // Skip meta messages (local command caveats, /login stdout, etc.)
33
+ if (line.isMeta)
34
+ return null;
35
+ // Skip API error messages
36
+ if (line.isApiErrorMessage)
37
+ return null;
38
+ const parts = [];
39
+ if (typeof content === "string") {
40
+ const text = content.trim();
41
+ // Skip empty, slash-commands, and local-command XML noise
42
+ if (!text)
43
+ return null;
44
+ if (text.startsWith("<local-command") || text.startsWith("<command-name>"))
45
+ return null;
46
+ parts.push({ type: "text", text });
47
+ }
48
+ else if (Array.isArray(content)) {
49
+ // Tool results
50
+ for (const block of content) {
51
+ if (block.type === "tool_result") {
52
+ const resultText = typeof block.content === "string" ? block.content : "";
53
+ parts.push({
54
+ type: "tool-invocation",
55
+ toolName: "tool_result",
56
+ toolCallId: block.tool_use_id,
57
+ state: "result",
58
+ result: resultText || (block.is_error ? "(error)" : "(no output)"),
59
+ });
60
+ }
61
+ }
62
+ }
63
+ if (parts.length === 0)
64
+ return null;
65
+ return {
66
+ info: {
67
+ id: line.uuid,
68
+ role: "user",
69
+ time: { created: new Date(line.timestamp).getTime() },
70
+ },
71
+ parts,
72
+ };
73
+ }
74
+ function convertAssistantMessage(line) {
75
+ if (line.isApiErrorMessage)
76
+ return null;
77
+ const parts = [];
78
+ for (const block of line.message.content) {
79
+ switch (block.type) {
80
+ case "text":
81
+ if (block.text?.trim()) {
82
+ parts.push({ type: "text", text: block.text.trim() });
83
+ }
84
+ break;
85
+ case "tool_use":
86
+ parts.push({
87
+ type: "tool-invocation",
88
+ toolName: block.name ?? "unknown",
89
+ toolCallId: block.id,
90
+ state: "call",
91
+ args: block.input,
92
+ });
93
+ break;
94
+ case "thinking":
95
+ // Skip internal reasoning — not useful to index
96
+ break;
97
+ }
98
+ }
99
+ if (parts.length === 0)
100
+ return null;
101
+ return {
102
+ info: {
103
+ id: line.uuid,
104
+ role: "assistant",
105
+ modelID: line.message.model,
106
+ time: { created: new Date(line.timestamp).getTime() },
107
+ },
108
+ parts,
109
+ };
110
+ }
111
+ // ---------------------------------------------------------------------------
112
+ // Public API
113
+ // ---------------------------------------------------------------------------
114
+ /**
115
+ * Parses a Claude Code JSONL transcript file into FullMessage[].
116
+ *
117
+ * Deduplicates streaming assistant chunks (same message.id → keep last),
118
+ * and pairs tool_use calls with their tool_result responses.
119
+ */
120
+ function parseTranscript(transcriptPath) {
121
+ const raw = fs_1.default.readFileSync(transcriptPath, "utf8");
122
+ const lines = raw.split("\n").filter((l) => l.trim());
123
+ // First pass: collect all lines, deduplicate assistant messages by message.id
124
+ // (streaming sends partial chunks — we want only the final complete message)
125
+ const assistantByMsgId = new Map();
126
+ const orderedEntries = [];
127
+ const seenUuids = new Set();
128
+ for (const raw of lines) {
129
+ let line;
130
+ try {
131
+ line = JSON.parse(raw);
132
+ }
133
+ catch {
134
+ continue;
135
+ }
136
+ if (line.type === "file-history-snapshot")
137
+ continue;
138
+ if (line.type === "assistant") {
139
+ const al = line;
140
+ const msgId = al.message?.id;
141
+ if (msgId) {
142
+ // Always overwrite — last chunk wins (most complete content)
143
+ assistantByMsgId.set(msgId, al);
144
+ // Track insertion order by uuid (first occurrence)
145
+ if (!seenUuids.has(al.uuid)) {
146
+ seenUuids.add(al.uuid);
147
+ orderedEntries.push({ uuid: al.uuid, line });
148
+ }
149
+ }
150
+ continue;
151
+ }
152
+ if (line.type === "user" || line.type === "system") {
153
+ const ul = line;
154
+ if (!seenUuids.has(ul.uuid)) {
155
+ seenUuids.add(ul.uuid);
156
+ orderedEntries.push({ uuid: ul.uuid, line });
157
+ }
158
+ }
159
+ }
160
+ // Second pass: resolve assistant lines to their final (deduplicated) version
161
+ // and pair tool_use with tool_result
162
+ const messages = [];
163
+ // Build a map: tool_use_id → tool result text (from user tool_result messages)
164
+ const toolResults = new Map();
165
+ for (const { line } of orderedEntries) {
166
+ if (line.type !== "user")
167
+ continue;
168
+ const ul = line;
169
+ if (Array.isArray(ul.message.content)) {
170
+ for (const block of ul.message.content) {
171
+ if (block.type === "tool_result") {
172
+ toolResults.set(block.tool_use_id, block.content ?? "");
173
+ }
174
+ }
175
+ }
176
+ }
177
+ for (const { line } of orderedEntries) {
178
+ if (line.type === "assistant") {
179
+ const al = line;
180
+ const msgId = al.message?.id;
181
+ // Use the final (deduplicated) version
182
+ const finalLine = msgId ? (assistantByMsgId.get(msgId) ?? al) : al;
183
+ // Enrich tool_use blocks with their results
184
+ const enriched = {
185
+ ...finalLine,
186
+ message: {
187
+ ...finalLine.message,
188
+ content: finalLine.message.content.map((block) => {
189
+ if (block.type === "tool_use" && block.id && toolResults.has(block.id)) {
190
+ // We'll render the result separately via tool_result user messages
191
+ // Just keep the call here
192
+ }
193
+ return block;
194
+ }),
195
+ },
196
+ };
197
+ const msg = convertAssistantMessage(enriched);
198
+ if (msg)
199
+ messages.push(msg);
200
+ }
201
+ else if (line.type === "user") {
202
+ const ul = line;
203
+ // Skip tool_result-only messages (already captured in assistant context)
204
+ // but DO include them so the indexer can see what tools returned
205
+ const msg = convertUserMessage(ul);
206
+ if (msg)
207
+ messages.push(msg);
208
+ }
209
+ }
210
+ return messages;
211
+ }
212
+ /**
213
+ * Derives a session title from the transcript messages.
214
+ * Uses the first meaningful user message text, truncated to 60 chars.
215
+ */
216
+ function deriveSessionTitle(messages) {
217
+ for (const msg of messages) {
218
+ if (msg.info.role !== "user")
219
+ continue;
220
+ for (const part of msg.parts) {
221
+ if (part.type === "text" && part.text) {
222
+ const title = part.text.replace(/\s+/g, " ").trim().slice(0, 60);
223
+ if (title)
224
+ return title;
225
+ }
226
+ }
227
+ }
228
+ return "Claude Code Session";
229
+ }
230
+ //# sourceMappingURL=transcript-to-messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-to-messages.js","sourceRoot":"","sources":["../../src/transcript-to-messages.ts"],"names":[],"mappings":"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"}