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.
- mem_os_python-1.6.27.dist-info/METADATA +1032 -0
- mem_os_python-1.6.27.dist-info/RECORD +253 -0
- mem_os_python-1.6.27.dist-info/WHEEL +4 -0
- mem_os_python-1.6.27.dist-info/entry_points.txt +2 -0
- mem_os_python-1.6.27.dist-info/licenses/LICENSE +21 -0
- memos/__init__.py +16 -0
- memos/_js/adapters/anthropic.d.ts +279 -0
- memos/_js/adapters/anthropic.d.ts.map +1 -0
- memos/_js/adapters/anthropic.js +348 -0
- memos/_js/adapters/anthropic.js.map +1 -0
- memos/_js/adapters/base.d.ts +10 -0
- memos/_js/adapters/base.d.ts.map +1 -0
- memos/_js/adapters/base.js +2 -0
- memos/_js/adapters/base.js.map +1 -0
- memos/_js/adapters/openai.d.ts +264 -0
- memos/_js/adapters/openai.d.ts.map +1 -0
- memos/_js/adapters/openai.js +342 -0
- memos/_js/adapters/openai.js.map +1 -0
- memos/_js/apps/explorer.d.ts +244 -0
- memos/_js/apps/explorer.d.ts.map +1 -0
- memos/_js/apps/explorer.js +738 -0
- memos/_js/apps/explorer.js.map +1 -0
- memos/_js/citations.d.ts +65 -0
- memos/_js/citations.d.ts.map +1 -0
- memos/_js/citations.js +143 -0
- memos/_js/citations.js.map +1 -0
- memos/_js/cli-browse.d.ts +3 -0
- memos/_js/cli-browse.d.ts.map +1 -0
- memos/_js/cli-browse.js +129 -0
- memos/_js/cli-browse.js.map +1 -0
- memos/_js/cli-completion.d.ts +31 -0
- memos/_js/cli-completion.d.ts.map +1 -0
- memos/_js/cli-completion.js +340 -0
- memos/_js/cli-completion.js.map +1 -0
- memos/_js/cli-help.d.ts +18 -0
- memos/_js/cli-help.d.ts.map +1 -0
- memos/_js/cli-help.js +357 -0
- memos/_js/cli-help.js.map +1 -0
- memos/_js/cli.d.ts +28 -0
- memos/_js/cli.d.ts.map +1 -0
- memos/_js/cli.js +2880 -0
- memos/_js/cli.js.map +1 -0
- memos/_js/compression.d.ts +25 -0
- memos/_js/compression.d.ts.map +1 -0
- memos/_js/compression.js +319 -0
- memos/_js/compression.js.map +1 -0
- memos/_js/confidence-machine.d.ts +99 -0
- memos/_js/confidence-machine.d.ts.map +1 -0
- memos/_js/confidence-machine.js +222 -0
- memos/_js/confidence-machine.js.map +1 -0
- memos/_js/context-pack.d.ts +506 -0
- memos/_js/context-pack.d.ts.map +1 -0
- memos/_js/context-pack.js +1435 -0
- memos/_js/context-pack.js.map +1 -0
- memos/_js/contradictions.d.ts +160 -0
- memos/_js/contradictions.d.ts.map +1 -0
- memos/_js/contradictions.js +255 -0
- memos/_js/contradictions.js.map +1 -0
- memos/_js/dashboard.d.ts +30 -0
- memos/_js/dashboard.d.ts.map +1 -0
- memos/_js/dashboard.js +302 -0
- memos/_js/dashboard.js.map +1 -0
- memos/_js/ebbinghaus.d.ts +29 -0
- memos/_js/ebbinghaus.d.ts.map +1 -0
- memos/_js/ebbinghaus.js +32 -0
- memos/_js/ebbinghaus.js.map +1 -0
- memos/_js/embedding-queue.d.ts +190 -0
- memos/_js/embedding-queue.d.ts.map +1 -0
- memos/_js/embedding-queue.js +316 -0
- memos/_js/embedding-queue.js.map +1 -0
- memos/_js/embeddings.d.ts +187 -0
- memos/_js/embeddings.d.ts.map +1 -0
- memos/_js/embeddings.js +633 -0
- memos/_js/embeddings.js.map +1 -0
- memos/_js/entity-extraction.d.ts +54 -0
- memos/_js/entity-extraction.d.ts.map +1 -0
- memos/_js/entity-extraction.js +325 -0
- memos/_js/entity-extraction.js.map +1 -0
- memos/_js/entity-index.d.ts +93 -0
- memos/_js/entity-index.d.ts.map +1 -0
- memos/_js/entity-index.js +165 -0
- memos/_js/entity-index.js.map +1 -0
- memos/_js/event-memory.d.ts +147 -0
- memos/_js/event-memory.d.ts.map +1 -0
- memos/_js/event-memory.js +290 -0
- memos/_js/event-memory.js.map +1 -0
- memos/_js/external-import.d.ts +98 -0
- memos/_js/external-import.d.ts.map +1 -0
- memos/_js/external-import.js +669 -0
- memos/_js/external-import.js.map +1 -0
- memos/_js/fidelity.d.ts +367 -0
- memos/_js/fidelity.d.ts.map +1 -0
- memos/_js/fidelity.js +911 -0
- memos/_js/fidelity.js.map +1 -0
- memos/_js/graph-expansion.d.ts +119 -0
- memos/_js/graph-expansion.d.ts.map +1 -0
- memos/_js/graph-expansion.js +213 -0
- memos/_js/graph-expansion.js.map +1 -0
- memos/_js/graph-mermaid.d.ts +13 -0
- memos/_js/graph-mermaid.d.ts.map +1 -0
- memos/_js/graph-mermaid.js +32 -0
- memos/_js/graph-mermaid.js.map +1 -0
- memos/_js/graph.d.ts +170 -0
- memos/_js/graph.d.ts.map +1 -0
- memos/_js/graph.js +482 -0
- memos/_js/graph.js.map +1 -0
- memos/_js/harness.d.ts +63 -0
- memos/_js/harness.d.ts.map +1 -0
- memos/_js/harness.js +93 -0
- memos/_js/harness.js.map +1 -0
- memos/_js/importance.d.ts +118 -0
- memos/_js/importance.d.ts.map +1 -0
- memos/_js/importance.js +144 -0
- memos/_js/importance.js.map +1 -0
- memos/_js/index.d.ts +51 -0
- memos/_js/index.d.ts.map +1 -0
- memos/_js/index.js +53 -0
- memos/_js/index.js.map +1 -0
- memos/_js/mcp.d.ts +58 -0
- memos/_js/mcp.d.ts.map +1 -0
- memos/_js/mcp.js +1853 -0
- memos/_js/mcp.js.map +1 -0
- memos/_js/memory.d.ts +1762 -0
- memos/_js/memory.d.ts.map +1 -0
- memos/_js/memory.js +6283 -0
- memos/_js/memory.js.map +1 -0
- memos/_js/procedural.d.ts +74 -0
- memos/_js/procedural.d.ts.map +1 -0
- memos/_js/procedural.js +125 -0
- memos/_js/procedural.js.map +1 -0
- memos/_js/project-config.d.ts +68 -0
- memos/_js/project-config.d.ts.map +1 -0
- memos/_js/project-config.js +59 -0
- memos/_js/project-config.js.map +1 -0
- memos/_js/proof-of-forgetting.d.ts +57 -0
- memos/_js/proof-of-forgetting.d.ts.map +1 -0
- memos/_js/proof-of-forgetting.js +80 -0
- memos/_js/proof-of-forgetting.js.map +1 -0
- memos/_js/provenance.d.ts +122 -0
- memos/_js/provenance.d.ts.map +1 -0
- memos/_js/provenance.js +182 -0
- memos/_js/provenance.js.map +1 -0
- memos/_js/quarantine-commands.d.ts +23 -0
- memos/_js/quarantine-commands.d.ts.map +1 -0
- memos/_js/quarantine-commands.js +42 -0
- memos/_js/quarantine-commands.js.map +1 -0
- memos/_js/quarantine.d.ts +120 -0
- memos/_js/quarantine.d.ts.map +1 -0
- memos/_js/quarantine.js +873 -0
- memos/_js/quarantine.js.map +1 -0
- memos/_js/redact.d.ts +12 -0
- memos/_js/redact.d.ts.map +1 -0
- memos/_js/redact.js +26 -0
- memos/_js/redact.js.map +1 -0
- memos/_js/repl.d.ts +57 -0
- memos/_js/repl.d.ts.map +1 -0
- memos/_js/repl.js +295 -0
- memos/_js/repl.js.map +1 -0
- memos/_js/rerank-local.d.ts +61 -0
- memos/_js/rerank-local.d.ts.map +1 -0
- memos/_js/rerank-local.js +210 -0
- memos/_js/rerank-local.js.map +1 -0
- memos/_js/retain-filter.d.ts +98 -0
- memos/_js/retain-filter.d.ts.map +1 -0
- memos/_js/retain-filter.js +232 -0
- memos/_js/retain-filter.js.map +1 -0
- memos/_js/retrieval.d.ts +265 -0
- memos/_js/retrieval.d.ts.map +1 -0
- memos/_js/retrieval.js +1018 -0
- memos/_js/retrieval.js.map +1 -0
- memos/_js/revert.d.ts +77 -0
- memos/_js/revert.d.ts.map +1 -0
- memos/_js/revert.js +252 -0
- memos/_js/revert.js.map +1 -0
- memos/_js/scope.d.ts +30 -0
- memos/_js/scope.d.ts.map +1 -0
- memos/_js/scope.js +71 -0
- memos/_js/scope.js.map +1 -0
- memos/_js/semantic-screen.d.ts +152 -0
- memos/_js/semantic-screen.d.ts.map +1 -0
- memos/_js/semantic-screen.js +290 -0
- memos/_js/semantic-screen.js.map +1 -0
- memos/_js/session-hooks.d.ts +127 -0
- memos/_js/session-hooks.d.ts.map +1 -0
- memos/_js/session-hooks.js +482 -0
- memos/_js/session-hooks.js.map +1 -0
- memos/_js/storage/sqlite.d.ts +427 -0
- memos/_js/storage/sqlite.d.ts.map +1 -0
- memos/_js/storage/sqlite.js +2428 -0
- memos/_js/storage/sqlite.js.map +1 -0
- memos/_js/sync.d.ts +213 -0
- memos/_js/sync.d.ts.map +1 -0
- memos/_js/sync.js +389 -0
- memos/_js/sync.js.map +1 -0
- memos/_js/tamper-log.d.ts +98 -0
- memos/_js/tamper-log.d.ts.map +1 -0
- memos/_js/tamper-log.js +327 -0
- memos/_js/tamper-log.js.map +1 -0
- memos/_js/temporal.d.ts +92 -0
- memos/_js/temporal.d.ts.map +1 -0
- memos/_js/temporal.js +536 -0
- memos/_js/temporal.js.map +1 -0
- memos/_js/time-travel.d.ts +38 -0
- memos/_js/time-travel.d.ts.map +1 -0
- memos/_js/time-travel.js +46 -0
- memos/_js/time-travel.js.map +1 -0
- memos/_js/timestamp-format.d.ts +18 -0
- memos/_js/timestamp-format.d.ts.map +1 -0
- memos/_js/timestamp-format.js +52 -0
- memos/_js/timestamp-format.js.map +1 -0
- memos/_js/triple-extraction.d.ts +31 -0
- memos/_js/triple-extraction.d.ts.map +1 -0
- memos/_js/triple-extraction.js +116 -0
- memos/_js/triple-extraction.js.map +1 -0
- memos/_js/types.d.ts +2474 -0
- memos/_js/types.d.ts.map +1 -0
- memos/_js/types.js +20 -0
- memos/_js/types.js.map +1 -0
- memos/_js/updater.d.ts +95 -0
- memos/_js/updater.d.ts.map +1 -0
- memos/_js/updater.js +268 -0
- memos/_js/updater.js.map +1 -0
- memos/_js/version.d.ts +17 -0
- memos/_js/version.d.ts.map +1 -0
- memos/_js/version.js +34 -0
- memos/_js/version.js.map +1 -0
- memos/_js/vision/clip-query-cache.d.ts +58 -0
- memos/_js/vision/clip-query-cache.d.ts.map +1 -0
- memos/_js/vision/clip-query-cache.js +79 -0
- memos/_js/vision/clip-query-cache.js.map +1 -0
- memos/_js/vision/clip.d.ts +113 -0
- memos/_js/vision/clip.d.ts.map +1 -0
- memos/_js/vision/clip.js +224 -0
- memos/_js/vision/clip.js.map +1 -0
- memos/_js/vision/fake-clip.d.ts +55 -0
- memos/_js/vision/fake-clip.d.ts.map +1 -0
- memos/_js/vision/fake-clip.js +122 -0
- memos/_js/vision/fake-clip.js.map +1 -0
- memos/_js/vision/index.d.ts +15 -0
- memos/_js/vision/index.d.ts.map +1 -0
- memos/_js/vision/index.js +13 -0
- memos/_js/vision/index.js.map +1 -0
- memos/_js/vision/store.d.ts +137 -0
- memos/_js/vision/store.d.ts.map +1 -0
- memos/_js/vision/store.js +383 -0
- memos/_js/vision/store.js.map +1 -0
- memos/adapters/__init__.py +0 -0
- memos/adapters/crewai.py +385 -0
- memos/adapters/langchain.py +301 -0
- memos/adapters/ollama.py +396 -0
- memos/server/__init__.py +0 -0
- memos/server/main.py +547 -0
- 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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"}
|