mem-os-python 1.6.27__py3-none-any.whl

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 (253) hide show
  1. mem_os_python-1.6.27.dist-info/METADATA +1032 -0
  2. mem_os_python-1.6.27.dist-info/RECORD +253 -0
  3. mem_os_python-1.6.27.dist-info/WHEEL +4 -0
  4. mem_os_python-1.6.27.dist-info/entry_points.txt +2 -0
  5. mem_os_python-1.6.27.dist-info/licenses/LICENSE +21 -0
  6. memos/__init__.py +16 -0
  7. memos/_js/adapters/anthropic.d.ts +279 -0
  8. memos/_js/adapters/anthropic.d.ts.map +1 -0
  9. memos/_js/adapters/anthropic.js +348 -0
  10. memos/_js/adapters/anthropic.js.map +1 -0
  11. memos/_js/adapters/base.d.ts +10 -0
  12. memos/_js/adapters/base.d.ts.map +1 -0
  13. memos/_js/adapters/base.js +2 -0
  14. memos/_js/adapters/base.js.map +1 -0
  15. memos/_js/adapters/openai.d.ts +264 -0
  16. memos/_js/adapters/openai.d.ts.map +1 -0
  17. memos/_js/adapters/openai.js +342 -0
  18. memos/_js/adapters/openai.js.map +1 -0
  19. memos/_js/apps/explorer.d.ts +244 -0
  20. memos/_js/apps/explorer.d.ts.map +1 -0
  21. memos/_js/apps/explorer.js +738 -0
  22. memos/_js/apps/explorer.js.map +1 -0
  23. memos/_js/citations.d.ts +65 -0
  24. memos/_js/citations.d.ts.map +1 -0
  25. memos/_js/citations.js +143 -0
  26. memos/_js/citations.js.map +1 -0
  27. memos/_js/cli-browse.d.ts +3 -0
  28. memos/_js/cli-browse.d.ts.map +1 -0
  29. memos/_js/cli-browse.js +129 -0
  30. memos/_js/cli-browse.js.map +1 -0
  31. memos/_js/cli-completion.d.ts +31 -0
  32. memos/_js/cli-completion.d.ts.map +1 -0
  33. memos/_js/cli-completion.js +340 -0
  34. memos/_js/cli-completion.js.map +1 -0
  35. memos/_js/cli-help.d.ts +18 -0
  36. memos/_js/cli-help.d.ts.map +1 -0
  37. memos/_js/cli-help.js +357 -0
  38. memos/_js/cli-help.js.map +1 -0
  39. memos/_js/cli.d.ts +28 -0
  40. memos/_js/cli.d.ts.map +1 -0
  41. memos/_js/cli.js +2880 -0
  42. memos/_js/cli.js.map +1 -0
  43. memos/_js/compression.d.ts +25 -0
  44. memos/_js/compression.d.ts.map +1 -0
  45. memos/_js/compression.js +319 -0
  46. memos/_js/compression.js.map +1 -0
  47. memos/_js/confidence-machine.d.ts +99 -0
  48. memos/_js/confidence-machine.d.ts.map +1 -0
  49. memos/_js/confidence-machine.js +222 -0
  50. memos/_js/confidence-machine.js.map +1 -0
  51. memos/_js/context-pack.d.ts +506 -0
  52. memos/_js/context-pack.d.ts.map +1 -0
  53. memos/_js/context-pack.js +1435 -0
  54. memos/_js/context-pack.js.map +1 -0
  55. memos/_js/contradictions.d.ts +160 -0
  56. memos/_js/contradictions.d.ts.map +1 -0
  57. memos/_js/contradictions.js +255 -0
  58. memos/_js/contradictions.js.map +1 -0
  59. memos/_js/dashboard.d.ts +30 -0
  60. memos/_js/dashboard.d.ts.map +1 -0
  61. memos/_js/dashboard.js +302 -0
  62. memos/_js/dashboard.js.map +1 -0
  63. memos/_js/ebbinghaus.d.ts +29 -0
  64. memos/_js/ebbinghaus.d.ts.map +1 -0
  65. memos/_js/ebbinghaus.js +32 -0
  66. memos/_js/ebbinghaus.js.map +1 -0
  67. memos/_js/embedding-queue.d.ts +190 -0
  68. memos/_js/embedding-queue.d.ts.map +1 -0
  69. memos/_js/embedding-queue.js +316 -0
  70. memos/_js/embedding-queue.js.map +1 -0
  71. memos/_js/embeddings.d.ts +187 -0
  72. memos/_js/embeddings.d.ts.map +1 -0
  73. memos/_js/embeddings.js +633 -0
  74. memos/_js/embeddings.js.map +1 -0
  75. memos/_js/entity-extraction.d.ts +54 -0
  76. memos/_js/entity-extraction.d.ts.map +1 -0
  77. memos/_js/entity-extraction.js +325 -0
  78. memos/_js/entity-extraction.js.map +1 -0
  79. memos/_js/entity-index.d.ts +93 -0
  80. memos/_js/entity-index.d.ts.map +1 -0
  81. memos/_js/entity-index.js +165 -0
  82. memos/_js/entity-index.js.map +1 -0
  83. memos/_js/event-memory.d.ts +147 -0
  84. memos/_js/event-memory.d.ts.map +1 -0
  85. memos/_js/event-memory.js +290 -0
  86. memos/_js/event-memory.js.map +1 -0
  87. memos/_js/external-import.d.ts +98 -0
  88. memos/_js/external-import.d.ts.map +1 -0
  89. memos/_js/external-import.js +669 -0
  90. memos/_js/external-import.js.map +1 -0
  91. memos/_js/fidelity.d.ts +367 -0
  92. memos/_js/fidelity.d.ts.map +1 -0
  93. memos/_js/fidelity.js +911 -0
  94. memos/_js/fidelity.js.map +1 -0
  95. memos/_js/graph-expansion.d.ts +119 -0
  96. memos/_js/graph-expansion.d.ts.map +1 -0
  97. memos/_js/graph-expansion.js +213 -0
  98. memos/_js/graph-expansion.js.map +1 -0
  99. memos/_js/graph-mermaid.d.ts +13 -0
  100. memos/_js/graph-mermaid.d.ts.map +1 -0
  101. memos/_js/graph-mermaid.js +32 -0
  102. memos/_js/graph-mermaid.js.map +1 -0
  103. memos/_js/graph.d.ts +170 -0
  104. memos/_js/graph.d.ts.map +1 -0
  105. memos/_js/graph.js +482 -0
  106. memos/_js/graph.js.map +1 -0
  107. memos/_js/harness.d.ts +63 -0
  108. memos/_js/harness.d.ts.map +1 -0
  109. memos/_js/harness.js +93 -0
  110. memos/_js/harness.js.map +1 -0
  111. memos/_js/importance.d.ts +118 -0
  112. memos/_js/importance.d.ts.map +1 -0
  113. memos/_js/importance.js +144 -0
  114. memos/_js/importance.js.map +1 -0
  115. memos/_js/index.d.ts +51 -0
  116. memos/_js/index.d.ts.map +1 -0
  117. memos/_js/index.js +53 -0
  118. memos/_js/index.js.map +1 -0
  119. memos/_js/mcp.d.ts +58 -0
  120. memos/_js/mcp.d.ts.map +1 -0
  121. memos/_js/mcp.js +1853 -0
  122. memos/_js/mcp.js.map +1 -0
  123. memos/_js/memory.d.ts +1762 -0
  124. memos/_js/memory.d.ts.map +1 -0
  125. memos/_js/memory.js +6283 -0
  126. memos/_js/memory.js.map +1 -0
  127. memos/_js/procedural.d.ts +74 -0
  128. memos/_js/procedural.d.ts.map +1 -0
  129. memos/_js/procedural.js +125 -0
  130. memos/_js/procedural.js.map +1 -0
  131. memos/_js/project-config.d.ts +68 -0
  132. memos/_js/project-config.d.ts.map +1 -0
  133. memos/_js/project-config.js +59 -0
  134. memos/_js/project-config.js.map +1 -0
  135. memos/_js/proof-of-forgetting.d.ts +57 -0
  136. memos/_js/proof-of-forgetting.d.ts.map +1 -0
  137. memos/_js/proof-of-forgetting.js +80 -0
  138. memos/_js/proof-of-forgetting.js.map +1 -0
  139. memos/_js/provenance.d.ts +122 -0
  140. memos/_js/provenance.d.ts.map +1 -0
  141. memos/_js/provenance.js +182 -0
  142. memos/_js/provenance.js.map +1 -0
  143. memos/_js/quarantine-commands.d.ts +23 -0
  144. memos/_js/quarantine-commands.d.ts.map +1 -0
  145. memos/_js/quarantine-commands.js +42 -0
  146. memos/_js/quarantine-commands.js.map +1 -0
  147. memos/_js/quarantine.d.ts +120 -0
  148. memos/_js/quarantine.d.ts.map +1 -0
  149. memos/_js/quarantine.js +873 -0
  150. memos/_js/quarantine.js.map +1 -0
  151. memos/_js/redact.d.ts +12 -0
  152. memos/_js/redact.d.ts.map +1 -0
  153. memos/_js/redact.js +26 -0
  154. memos/_js/redact.js.map +1 -0
  155. memos/_js/repl.d.ts +57 -0
  156. memos/_js/repl.d.ts.map +1 -0
  157. memos/_js/repl.js +295 -0
  158. memos/_js/repl.js.map +1 -0
  159. memos/_js/rerank-local.d.ts +61 -0
  160. memos/_js/rerank-local.d.ts.map +1 -0
  161. memos/_js/rerank-local.js +210 -0
  162. memos/_js/rerank-local.js.map +1 -0
  163. memos/_js/retain-filter.d.ts +98 -0
  164. memos/_js/retain-filter.d.ts.map +1 -0
  165. memos/_js/retain-filter.js +232 -0
  166. memos/_js/retain-filter.js.map +1 -0
  167. memos/_js/retrieval.d.ts +265 -0
  168. memos/_js/retrieval.d.ts.map +1 -0
  169. memos/_js/retrieval.js +1018 -0
  170. memos/_js/retrieval.js.map +1 -0
  171. memos/_js/revert.d.ts +77 -0
  172. memos/_js/revert.d.ts.map +1 -0
  173. memos/_js/revert.js +252 -0
  174. memos/_js/revert.js.map +1 -0
  175. memos/_js/scope.d.ts +30 -0
  176. memos/_js/scope.d.ts.map +1 -0
  177. memos/_js/scope.js +71 -0
  178. memos/_js/scope.js.map +1 -0
  179. memos/_js/semantic-screen.d.ts +152 -0
  180. memos/_js/semantic-screen.d.ts.map +1 -0
  181. memos/_js/semantic-screen.js +290 -0
  182. memos/_js/semantic-screen.js.map +1 -0
  183. memos/_js/session-hooks.d.ts +127 -0
  184. memos/_js/session-hooks.d.ts.map +1 -0
  185. memos/_js/session-hooks.js +482 -0
  186. memos/_js/session-hooks.js.map +1 -0
  187. memos/_js/storage/sqlite.d.ts +427 -0
  188. memos/_js/storage/sqlite.d.ts.map +1 -0
  189. memos/_js/storage/sqlite.js +2428 -0
  190. memos/_js/storage/sqlite.js.map +1 -0
  191. memos/_js/sync.d.ts +213 -0
  192. memos/_js/sync.d.ts.map +1 -0
  193. memos/_js/sync.js +389 -0
  194. memos/_js/sync.js.map +1 -0
  195. memos/_js/tamper-log.d.ts +98 -0
  196. memos/_js/tamper-log.d.ts.map +1 -0
  197. memos/_js/tamper-log.js +327 -0
  198. memos/_js/tamper-log.js.map +1 -0
  199. memos/_js/temporal.d.ts +92 -0
  200. memos/_js/temporal.d.ts.map +1 -0
  201. memos/_js/temporal.js +536 -0
  202. memos/_js/temporal.js.map +1 -0
  203. memos/_js/time-travel.d.ts +38 -0
  204. memos/_js/time-travel.d.ts.map +1 -0
  205. memos/_js/time-travel.js +46 -0
  206. memos/_js/time-travel.js.map +1 -0
  207. memos/_js/timestamp-format.d.ts +18 -0
  208. memos/_js/timestamp-format.d.ts.map +1 -0
  209. memos/_js/timestamp-format.js +52 -0
  210. memos/_js/timestamp-format.js.map +1 -0
  211. memos/_js/triple-extraction.d.ts +31 -0
  212. memos/_js/triple-extraction.d.ts.map +1 -0
  213. memos/_js/triple-extraction.js +116 -0
  214. memos/_js/triple-extraction.js.map +1 -0
  215. memos/_js/types.d.ts +2474 -0
  216. memos/_js/types.d.ts.map +1 -0
  217. memos/_js/types.js +20 -0
  218. memos/_js/types.js.map +1 -0
  219. memos/_js/updater.d.ts +95 -0
  220. memos/_js/updater.d.ts.map +1 -0
  221. memos/_js/updater.js +268 -0
  222. memos/_js/updater.js.map +1 -0
  223. memos/_js/version.d.ts +17 -0
  224. memos/_js/version.d.ts.map +1 -0
  225. memos/_js/version.js +34 -0
  226. memos/_js/version.js.map +1 -0
  227. memos/_js/vision/clip-query-cache.d.ts +58 -0
  228. memos/_js/vision/clip-query-cache.d.ts.map +1 -0
  229. memos/_js/vision/clip-query-cache.js +79 -0
  230. memos/_js/vision/clip-query-cache.js.map +1 -0
  231. memos/_js/vision/clip.d.ts +113 -0
  232. memos/_js/vision/clip.d.ts.map +1 -0
  233. memos/_js/vision/clip.js +224 -0
  234. memos/_js/vision/clip.js.map +1 -0
  235. memos/_js/vision/fake-clip.d.ts +55 -0
  236. memos/_js/vision/fake-clip.d.ts.map +1 -0
  237. memos/_js/vision/fake-clip.js +122 -0
  238. memos/_js/vision/fake-clip.js.map +1 -0
  239. memos/_js/vision/index.d.ts +15 -0
  240. memos/_js/vision/index.d.ts.map +1 -0
  241. memos/_js/vision/index.js +13 -0
  242. memos/_js/vision/index.js.map +1 -0
  243. memos/_js/vision/store.d.ts +137 -0
  244. memos/_js/vision/store.d.ts.map +1 -0
  245. memos/_js/vision/store.js +383 -0
  246. memos/_js/vision/store.js.map +1 -0
  247. memos/adapters/__init__.py +0 -0
  248. memos/adapters/crewai.py +385 -0
  249. memos/adapters/langchain.py +301 -0
  250. memos/adapters/ollama.py +396 -0
  251. memos/server/__init__.py +0 -0
  252. memos/server/main.py +547 -0
  253. memos/server/routes.py +360 -0
@@ -0,0 +1,482 @@
1
+ /**
2
+ * Session hooks — automatic fact extraction at session end.
3
+ *
4
+ * Claude Code and OpenCode can run a hook when a session ends. This module
5
+ * provides:
6
+ *
7
+ * - `parseClaudeTranscript()` / `parseClaudeTranscriptText()`: convert a
8
+ * Claude Code JSONL transcript into `ConversationMessage[]` for
9
+ * `MemOS.extractFacts()`.
10
+ * - `parsePlainTranscript()`: convert `User:`/`Assistant:` plain-text
11
+ * transcripts.
12
+ * - `parseTranscriptFile()`: try Claude JSONL first, fall back to
13
+ * plain text when it yields nothing (used by both `extract-facts`
14
+ * and `session-hook`).
15
+ * - `findOpenCodeSessionMessages()`: load an ended OpenCode session's
16
+ * messages from OpenCode's data dir (backs `--opencode-session`).
17
+ * - `session-hook` (in the CLI): the hook entrypoint — reads hook JSON
18
+ * from stdin (Claude Code SessionEnd format) or `--opencode-session`,
19
+ * extracts the transcript, and stores durable facts via
20
+ * `extractFacts({ autoStore: true })`.
21
+ * - `claudeCodeHookConfig()` / `openCodePluginSource()`: setup artifacts.
22
+ *
23
+ * The hook feeds the existing extraction/storage path — it never drops or
24
+ * rewrites memories, it only calls `extractFacts` with `autoStore: true`.
25
+ *
26
+ * @module @memos/session-hooks
27
+ */
28
+ import { readFileSync, existsSync, readdirSync } from "node:fs";
29
+ import { join } from "node:path";
30
+ import Database from "better-sqlite3";
31
+ /**
32
+ * Parse a Claude Code JSONL transcript into conversation messages.
33
+ *
34
+ * Each line is a JSON object with `type` ("user" | "assistant") and a
35
+ * `message` object containing `role` and `content` (string or array of
36
+ * content blocks). Only text content is extracted; tool calls/results
37
+ * are skipped.
38
+ */
39
+ export function parseClaudeTranscript(transcriptPath) {
40
+ if (!existsSync(transcriptPath)) {
41
+ throw new Error(`transcript not found: ${transcriptPath}`);
42
+ }
43
+ return parseClaudeTranscriptText(readFileSync(transcriptPath, "utf-8"));
44
+ }
45
+ /**
46
+ * Parse Claude Code JSONL transcript text into conversation messages.
47
+ * Malformed lines are skipped. Returns an empty array when no line
48
+ * yields a message — callers that want a plain-text fallback should use
49
+ * `parseTranscriptFile()` instead of treating this as an error.
50
+ */
51
+ export function parseClaudeTranscriptText(text) {
52
+ const messages = [];
53
+ const lines = text.split("\n");
54
+ for (const line of lines) {
55
+ const trimmed = line.trim();
56
+ if (!trimmed)
57
+ continue;
58
+ let entry;
59
+ try {
60
+ entry = JSON.parse(trimmed);
61
+ }
62
+ catch {
63
+ continue; // skip malformed lines
64
+ }
65
+ // Claude Code transcript format: { type: "user"|"assistant", message: { role, content } }
66
+ const msg = entry.message;
67
+ if (!msg || typeof msg !== "object")
68
+ continue;
69
+ const role = msg.role;
70
+ if (role !== "user" && role !== "assistant" && role !== "system")
71
+ continue;
72
+ const text = extractTextContent(msg.content);
73
+ if (!text)
74
+ continue;
75
+ messages.push({ role, content: text });
76
+ }
77
+ return messages;
78
+ }
79
+ /**
80
+ * Parse a transcript file of unknown format.
81
+ *
82
+ * Tries Claude Code JSONL first; when that yields no messages but the
83
+ * file is non-empty, falls back to plain-text parsing (`User:` /
84
+ * `Assistant:` prefixes). This is the entrypoint both `extract-facts`
85
+ * and `session-hook` use — previously the fallback was dead code
86
+ * because the JSONL parser returned `[]` instead of throwing.
87
+ */
88
+ export function parseTranscriptFile(transcriptPath) {
89
+ if (!existsSync(transcriptPath)) {
90
+ throw new Error(`transcript not found: ${transcriptPath}`);
91
+ }
92
+ const raw = readFileSync(transcriptPath, "utf-8");
93
+ if (!raw.trim())
94
+ return [];
95
+ const claude = parseClaudeTranscriptText(raw);
96
+ if (claude.length > 0)
97
+ return claude;
98
+ return parsePlainTranscript(raw);
99
+ }
100
+ /** Extract plain text from Claude Code content (string or block array). */
101
+ function extractTextContent(content) {
102
+ if (typeof content === "string")
103
+ return content.trim();
104
+ if (!Array.isArray(content))
105
+ return "";
106
+ const parts = [];
107
+ for (const block of content) {
108
+ if (block &&
109
+ typeof block === "object" &&
110
+ block.type === "text" &&
111
+ typeof block.text === "string") {
112
+ parts.push(block.text);
113
+ }
114
+ }
115
+ return parts.join("\n").trim();
116
+ }
117
+ /**
118
+ * Parse a plain-text or markdown transcript into conversation messages.
119
+ * Lines starting with "User:" / "Human:" become user messages;
120
+ * "Assistant:" / "Claude:" become assistant messages.
121
+ */
122
+ export function parsePlainTranscript(text) {
123
+ const messages = [];
124
+ const lines = text.split("\n");
125
+ let currentRole = null;
126
+ let currentText = [];
127
+ const flush = () => {
128
+ const content = currentText.join("\n").trim();
129
+ if (currentRole && content) {
130
+ messages.push({ role: currentRole, content });
131
+ }
132
+ currentText = [];
133
+ };
134
+ for (const line of lines) {
135
+ const userMatch = /^(user|human)\s*:/i.exec(line);
136
+ const assistantMatch = /^(assistant|claude|ai)\s*:/i.exec(line);
137
+ if (userMatch) {
138
+ flush();
139
+ currentRole = "user";
140
+ currentText.push(line.slice(userMatch[0].length).trim());
141
+ }
142
+ else if (assistantMatch) {
143
+ flush();
144
+ currentRole = "assistant";
145
+ currentText.push(line.slice(assistantMatch[0].length).trim());
146
+ }
147
+ else if (currentRole) {
148
+ currentText.push(line);
149
+ }
150
+ }
151
+ flush();
152
+ return messages;
153
+ }
154
+ /**
155
+ * Candidate OpenCode data directories, in priority order.
156
+ *
157
+ * OpenCode resolves its data dir as `$XDG_DATA_HOME/opencode`, falling
158
+ * back to the platform default (`~/.local/share/opencode` on Linux,
159
+ * `~/Library/Application Support/opencode` on macOS). There is no
160
+ * `OPENCODE_DATA_DIR` env var in OpenCode itself — honor the real
161
+ * `XDG_DATA_HOME` override here instead.
162
+ */
163
+ export function openCodeDataDirs() {
164
+ const dirs = [];
165
+ const xdg = process.env.XDG_DATA_HOME;
166
+ if (xdg)
167
+ dirs.push(join(xdg, "opencode"));
168
+ const home = process.env.HOME ?? "";
169
+ if (process.platform === "darwin") {
170
+ dirs.push(join(home, "Library", "Application Support", "opencode"));
171
+ }
172
+ else if (process.platform === "win32" && process.env.LOCALAPPDATA) {
173
+ dirs.push(join(process.env.LOCALAPPDATA, "opencode"));
174
+ }
175
+ else {
176
+ dirs.push(join(home, ".local", "share", "opencode"));
177
+ }
178
+ return dirs;
179
+ }
180
+ /**
181
+ * Load the user/assistant messages of an OpenCode session.
182
+ *
183
+ * Current OpenCode persists sessions in SQLite at
184
+ * `<dataDir>/opencode.db` (tables `session`, `message`, `part`; message
185
+ * rows carry `session_id` plus a JSON `data` column with `role` and
186
+ * `time.created`, part rows carry `message_id` plus a JSON `data`
187
+ * column where `type: "text"` parts hold the visible text in
188
+ * `data.text`). Older installs used JSON files at
189
+ * `<dataDir>/storage/message/<sessionId>/<messageId>.json` and
190
+ * `<dataDir>/storage/part/<messageId>/<partId>.json` — tried as a
191
+ * fallback when the database is absent or unreadable.
192
+ *
193
+ * Returns an empty array when the session cannot be found — the caller
194
+ * (session-hook) treats that as fail-open, not an error.
195
+ *
196
+ * @param sessionId The OpenCode session ID (from the `session.deleted` event).
197
+ * @param dataDir Override the data directory (e.g. in tests). When
198
+ * omitted, `openCodeDataDirs()` is searched in order.
199
+ */
200
+ export function findOpenCodeSessionMessages(sessionId, dataDir) {
201
+ const dirs = dataDir ? [dataDir] : openCodeDataDirs();
202
+ for (const dir of dirs) {
203
+ const messages = readOpenCodeSession(dir, sessionId);
204
+ if (messages.length > 0)
205
+ return messages;
206
+ }
207
+ return [];
208
+ }
209
+ /**
210
+ * Read one OpenCode data dir: SQLite first, legacy JSON fallback.
211
+ * Never throws — any unreadable layout yields [].
212
+ */
213
+ function readOpenCodeSession(dataDir, sessionId) {
214
+ const fromDb = readOpenCodeSessionSqlite(dataDir, sessionId);
215
+ if (fromDb.length > 0)
216
+ return fromDb;
217
+ return readOpenCodeSessionLegacyJson(dataDir, sessionId);
218
+ }
219
+ /** Parse a JSON blob that may be the row itself or nested under `data`. */
220
+ function openCodeJsonField(parsed, field) {
221
+ if (parsed && typeof parsed === "object") {
222
+ const obj = parsed;
223
+ if (field in obj)
224
+ return obj[field];
225
+ const data = obj.data;
226
+ if (data && typeof data === "object" && field in data) {
227
+ return data[field];
228
+ }
229
+ }
230
+ return undefined;
231
+ }
232
+ /**
233
+ * Read an OpenCode session from `<dataDir>/opencode.db` (SQLite).
234
+ *
235
+ * Opened read-only with `fileMustExist` so we never create an empty
236
+ * database at OpenCode's path, and never disturb a running OpenCode
237
+ * instance's WAL.
238
+ */
239
+ function readOpenCodeSessionSqlite(dataDir, sessionId) {
240
+ const candidates = [join(dataDir, "opencode.db")];
241
+ try {
242
+ for (const file of readdirSync(dataDir)) {
243
+ // Channel-specific databases: opencode-<channel>.db
244
+ if (/^opencode-.+\.db$/.test(file))
245
+ candidates.push(join(dataDir, file));
246
+ }
247
+ }
248
+ catch {
249
+ return []; // data dir unreadable — fall through to legacy JSON
250
+ }
251
+ for (const dbPath of candidates) {
252
+ if (!existsSync(dbPath))
253
+ continue;
254
+ let db = null;
255
+ try {
256
+ db = new Database(dbPath, { readonly: true, fileMustExist: true });
257
+ const tables = new Set(db
258
+ .prepare("SELECT name FROM sqlite_master WHERE type = 'table'")
259
+ .all().map((r) => r.name));
260
+ if (!tables.has("message") || !tables.has("part"))
261
+ continue;
262
+ const headers = [];
263
+ const rows = db
264
+ .prepare("SELECT id, data FROM message WHERE session_id = ?")
265
+ .all(sessionId);
266
+ for (const row of rows) {
267
+ try {
268
+ const parsed = JSON.parse(row.data);
269
+ const role = openCodeJsonField(parsed, "role");
270
+ if (role !== "user" && role !== "assistant")
271
+ continue;
272
+ const time = openCodeJsonField(parsed, "time");
273
+ const created = time && typeof time.created === "number" ? time.created : 0;
274
+ headers.push({ role, created, messageId: row.id });
275
+ }
276
+ catch {
277
+ continue; // skip unreadable message rows
278
+ }
279
+ }
280
+ headers.sort((a, b) => a.created - b.created || (a.messageId < b.messageId ? -1 : 1));
281
+ const partStmt = db.prepare("SELECT data FROM part WHERE message_id = ?");
282
+ const messages = [];
283
+ for (const header of headers) {
284
+ const texts = [];
285
+ try {
286
+ const parts = partStmt.all(header.messageId);
287
+ for (const part of parts) {
288
+ try {
289
+ const parsed = JSON.parse(part.data);
290
+ if (openCodeJsonField(parsed, "type") === "text" &&
291
+ typeof openCodeJsonField(parsed, "text") === "string") {
292
+ const text = openCodeJsonField(parsed, "text").trim();
293
+ if (text)
294
+ texts.push(text);
295
+ }
296
+ }
297
+ catch {
298
+ continue; // skip unreadable part rows
299
+ }
300
+ }
301
+ }
302
+ catch {
303
+ continue; // skip messages whose parts can't be read
304
+ }
305
+ const text = texts.join("\n").trim();
306
+ if (text)
307
+ messages.push({ role: header.role, content: text });
308
+ }
309
+ if (messages.length > 0)
310
+ return messages;
311
+ }
312
+ catch {
313
+ continue; // locked/corrupt db — try the next candidate
314
+ }
315
+ finally {
316
+ try {
317
+ db?.close();
318
+ }
319
+ catch {
320
+ // ignore close errors on a read-only handle
321
+ }
322
+ }
323
+ }
324
+ return [];
325
+ }
326
+ /**
327
+ * Read an OpenCode session from the legacy JSON layout:
328
+ * `<dataDir>/storage/message/<sessionId>/<messageId>.json` and
329
+ * `<dataDir>/storage/part/<messageId>/<partId>.json`.
330
+ */
331
+ function readOpenCodeSessionLegacyJson(dataDir, sessionId) {
332
+ const messageDir = join(dataDir, "storage", "message", sessionId);
333
+ if (!existsSync(messageDir))
334
+ return [];
335
+ let files;
336
+ try {
337
+ files = readdirSync(messageDir);
338
+ }
339
+ catch {
340
+ return [];
341
+ }
342
+ const headers = [];
343
+ for (const file of files) {
344
+ if (!file.endsWith(".json"))
345
+ continue;
346
+ try {
347
+ const parsed = JSON.parse(readFileSync(join(messageDir, file), "utf-8"));
348
+ const role = openCodeJsonField(parsed, "role");
349
+ if (role !== "user" && role !== "assistant")
350
+ continue;
351
+ const time = openCodeJsonField(parsed, "time");
352
+ const created = time && typeof time.created === "number" ? time.created : 0;
353
+ const messageId = openCodeJsonField(parsed, "id") ?? file.replace(/\.json$/, "");
354
+ headers.push({ role, created, messageId });
355
+ }
356
+ catch {
357
+ continue; // skip unreadable message files
358
+ }
359
+ }
360
+ headers.sort((a, b) => a.created - b.created || (a.messageId < b.messageId ? -1 : 1));
361
+ const messages = [];
362
+ for (const header of headers) {
363
+ const text = readOpenCodePartsLegacy(dataDir, header.messageId);
364
+ if (text)
365
+ messages.push({ role: header.role, content: text });
366
+ }
367
+ return messages;
368
+ }
369
+ /** Concatenate the text parts of an OpenCode message (legacy JSON layout). */
370
+ function readOpenCodePartsLegacy(dataDir, messageId) {
371
+ const partDir = join(dataDir, "storage", "part", messageId);
372
+ if (!existsSync(partDir))
373
+ return "";
374
+ let files;
375
+ try {
376
+ files = readdirSync(partDir);
377
+ }
378
+ catch {
379
+ return "";
380
+ }
381
+ const texts = [];
382
+ for (const file of files) {
383
+ if (!file.endsWith(".json"))
384
+ continue;
385
+ try {
386
+ const parsed = JSON.parse(readFileSync(join(partDir, file), "utf-8"));
387
+ if (openCodeJsonField(parsed, "type") !== "text")
388
+ continue;
389
+ const text = openCodeJsonField(parsed, "text");
390
+ if (typeof text === "string" && text.trim())
391
+ texts.push(text.trim());
392
+ }
393
+ catch {
394
+ continue; // skip unreadable parts
395
+ }
396
+ }
397
+ return texts.join("\n").trim();
398
+ }
399
+ /**
400
+ * Generate the Claude Code SessionEnd hook configuration.
401
+ * Add to `.claude/settings.json` (project) or `~/.claude/settings.json` (user).
402
+ */
403
+ export function claudeCodeHookConfig(memosBin = "memos") {
404
+ return {
405
+ hooks: {
406
+ SessionEnd: [
407
+ {
408
+ hooks: [
409
+ {
410
+ type: "command",
411
+ command: `${memosBin} session-hook`,
412
+ },
413
+ ],
414
+ },
415
+ ],
416
+ },
417
+ };
418
+ }
419
+ /**
420
+ * Generate an OpenCode plugin that runs fact extraction on session end.
421
+ * Save as `.opencode/plugins/memos-session-hook.ts` (or .js).
422
+ */
423
+ export function openCodePluginSource(memosBin = "memos") {
424
+ return `/**
425
+ * MemOS session hook for OpenCode.
426
+ * Extracts durable facts when a session ends.
427
+ *
428
+ * Install: save as .opencode/plugins/memos-session-hook.ts
429
+ * and add "./plugins" (or the file) to the "plugin" array in opencode.json.
430
+ */
431
+ export const MemosSessionHook = async ({ $ }) => {
432
+ return {
433
+ "session.deleted": async (event) => {
434
+ try {
435
+ // event.sessionID identifies the ended session; the transcript
436
+ // is available via the OpenCode session API or export.
437
+ await $\`${memosBin} session-hook --opencode-session \${event.sessionID}\`;
438
+ } catch {
439
+ // Never break session teardown — hooks must be fail-open.
440
+ }
441
+ },
442
+ };
443
+ };
444
+ `;
445
+ }
446
+ /**
447
+ * Format hook setup instructions for a target harness.
448
+ */
449
+ export function sessionHookInstructions(target, memosBin = "memos") {
450
+ const config = JSON.stringify(claudeCodeHookConfig(memosBin), null, 2);
451
+ switch (target) {
452
+ case "claude-code":
453
+ case "claude":
454
+ case "claudecode":
455
+ return [
456
+ "MemOS session hook — Claude Code:",
457
+ "",
458
+ "Add to .claude/settings.json (project) or ~/.claude/settings.json (user):",
459
+ "",
460
+ config,
461
+ "",
462
+ "When a session ends, the hook runs `memos session-hook`, which reads",
463
+ "the session transcript and stores durable facts via extractFacts().",
464
+ "Set MEMOS_SKIP_SESSION_HOOK=1 to opt out for a single session.",
465
+ ].join("\n");
466
+ case "opencode":
467
+ return [
468
+ "MemOS session hook — OpenCode:",
469
+ "",
470
+ "1. Save this plugin as .opencode/plugins/memos-session-hook.ts:",
471
+ "",
472
+ openCodePluginSource(memosBin),
473
+ "2. Add the plugin to opencode.json:",
474
+ ' { "plugin": ["./plugins/memos-session-hook.ts"] }',
475
+ "",
476
+ "On session end, the plugin runs fact extraction via the memos CLI.",
477
+ ].join("\n");
478
+ default:
479
+ return `Unknown target: ${target}. Supported: claude-code, opencode.`;
480
+ }
481
+ }
482
+ //# sourceMappingURL=session-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-hooks.js","sourceRoot":"","sources":["../src/session-hooks.ts"],"names":[],"mappings":"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"}