@opvs-ai/cli 0.23.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +73 -0
  2. package/claude-plugin/.claude-plugin/marketplace.json +14 -0
  3. package/claude-plugin/.claude-plugin/plugin.json +9 -0
  4. package/claude-plugin/.mcp.json +8 -0
  5. package/claude-plugin/README.md +24 -0
  6. package/claude-plugin/hooks/hooks.json +50 -0
  7. package/claude-plugin/skills/remember/SKILL.md +31 -0
  8. package/claude-plugin/skills/remember/scripts/remember.mjs +121 -0
  9. package/dist/.build-stamp.json +4 -4
  10. package/dist/commands/code-graph.d.ts +17 -0
  11. package/dist/commands/code-graph.js +64 -0
  12. package/dist/commands/code-graph.js.map +1 -0
  13. package/dist/commands/code.d.ts +13 -3
  14. package/dist/commands/code.js +191 -3
  15. package/dist/commands/code.js.map +1 -1
  16. package/dist/commands/memory-capture.d.ts +76 -0
  17. package/dist/commands/memory-capture.js +562 -0
  18. package/dist/commands/memory-capture.js.map +1 -0
  19. package/dist/commands/memory-hook.js +13 -4
  20. package/dist/commands/memory-hook.js.map +1 -1
  21. package/dist/commands/memory-install.d.ts +17 -0
  22. package/dist/commands/memory-install.js +349 -0
  23. package/dist/commands/memory-install.js.map +1 -0
  24. package/dist/commands/memory-lessons.d.ts +8 -0
  25. package/dist/commands/memory-lessons.js +135 -0
  26. package/dist/commands/memory-lessons.js.map +1 -0
  27. package/dist/commands/memory.js +6 -0
  28. package/dist/commands/memory.js.map +1 -1
  29. package/dist/commands/orgChart.d.ts +3 -0
  30. package/dist/commands/orgChart.js +88 -0
  31. package/dist/commands/orgChart.js.map +1 -0
  32. package/dist/commands/tasks.js +45 -3
  33. package/dist/commands/tasks.js.map +1 -1
  34. package/dist/index.js +4 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/lib/redact.d.ts +16 -0
  37. package/dist/lib/redact.js +92 -0
  38. package/dist/lib/redact.js.map +1 -0
  39. package/package.json +3 -1
  40. package/runtime-plugins/cline/opvs-memory.ts +99 -0
  41. package/runtime-plugins/opencode/opvs-memory.ts +94 -0
@@ -0,0 +1,562 @@
1
+ /** Opt-in, local-first session capture for supported coding runtimes. */
2
+ import { createHash } from "node:crypto";
3
+ import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync, } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import { basename, dirname, join } from "node:path";
6
+ import { createInterface } from "node:readline/promises";
7
+ import { getConfigPath, getEffectiveConfig } from "@opvs-ai/core";
8
+ import { sanitizeAllowed, } from "../lib/redact.js";
9
+ const INGEST_SCOPE = "memory:ingest";
10
+ const STATE_VERSION = 1;
11
+ const MAX_STDIN_BYTES = 2 * 1024 * 1024;
12
+ function statePath() {
13
+ return join(dirname(getConfigPath()), "memory-capture.json");
14
+ }
15
+ export function loadCaptureState() {
16
+ try {
17
+ const parsed = JSON.parse(readFileSync(statePath(), "utf8"));
18
+ if (parsed.version !== STATE_VERSION ||
19
+ parsed.enabled !== true ||
20
+ typeof parsed.token !== "string" ||
21
+ !parsed.token ||
22
+ typeof parsed.api_url !== "string") {
23
+ return null;
24
+ }
25
+ return {
26
+ version: STATE_VERSION,
27
+ enabled: true,
28
+ token: parsed.token,
29
+ api_url: parsed.api_url,
30
+ brand_id: typeof parsed.brand_id === "number" ? parsed.brand_id : null,
31
+ codex_files: parsed.codex_files ?? {},
32
+ };
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ export function saveCaptureState(state) {
39
+ const path = statePath();
40
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
41
+ writeFileSync(path, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
42
+ chmodSync(path, 0o600);
43
+ }
44
+ function removeCaptureState() {
45
+ rmSync(statePath(), { force: true });
46
+ }
47
+ export function disableCapture() {
48
+ removeCaptureState();
49
+ }
50
+ export function deterministicEventId(runtime, sessionId, eventIndex, rawLine) {
51
+ return createHash("sha256")
52
+ .update(runtime)
53
+ .update("\0")
54
+ .update(sessionId)
55
+ .update("\0")
56
+ .update(String(eventIndex))
57
+ .update("\0")
58
+ .update(rawLine)
59
+ .digest("hex");
60
+ }
61
+ function stableIndex(rawLine, supplied) {
62
+ if (typeof supplied === "number" && Number.isSafeInteger(supplied) && supplied >= 0) {
63
+ return supplied;
64
+ }
65
+ return Number.parseInt(createHash("sha256").update(rawLine).digest("hex").slice(0, 12), 16);
66
+ }
67
+ function event(runtime, sessionId, index, rawLine, kind, fidelity, allowlisted, timestamp, redact) {
68
+ const cleaned = sanitizeAllowed(allowlisted, redact);
69
+ return {
70
+ id: deterministicEventId(runtime, sessionId, index, rawLine),
71
+ kind,
72
+ index,
73
+ fidelity,
74
+ content_state: cleaned.contentState,
75
+ ...(typeof timestamp === "string" ? { timestamp } : {}),
76
+ data: cleaned.value,
77
+ };
78
+ }
79
+ function asObject(value) {
80
+ return value && typeof value === "object" && !Array.isArray(value)
81
+ ? value
82
+ : {};
83
+ }
84
+ /** Map one Claude hook input. No field not named here can leave the machine. */
85
+ export function buildClaudeEvents(hook, input, options = {}) {
86
+ const rawLine = options.rawLine ?? JSON.stringify(input);
87
+ const redact = options.redact !== false;
88
+ const sessionId = typeof input.session_id === "string" && input.session_id
89
+ ? input.session_id
90
+ : "unknown";
91
+ const baseIndex = stableIndex(rawLine, input.event_index);
92
+ const timestamp = input.timestamp;
93
+ let events;
94
+ if (hook === "post-tool") {
95
+ const common = {
96
+ tool_name: typeof input.tool_name === "string" ? input.tool_name : "unknown",
97
+ tool_use_id: typeof input.tool_use_id === "string" ? input.tool_use_id : undefined,
98
+ };
99
+ events = [
100
+ event("claude_code", sessionId, baseIndex * 2, rawLine, "action", "seen", { ...common, tool_input: input.tool_input ?? {} }, timestamp, redact),
101
+ event("claude_code", sessionId, baseIndex * 2 + 1, rawLine, "observation", "seen", { ...common, tool_response: input.tool_response ?? {} }, timestamp, redact),
102
+ ];
103
+ }
104
+ else if (hook === "stop") {
105
+ events = [
106
+ event("claude_code", sessionId, baseIndex, rawLine, "message", "seen", {
107
+ role: "assistant",
108
+ content: typeof input.last_assistant_message === "string"
109
+ ? input.last_assistant_message
110
+ : "",
111
+ }, timestamp, redact),
112
+ ];
113
+ }
114
+ else {
115
+ events = [
116
+ event("claude_code", sessionId, baseIndex, rawLine, "session.completed", "seen", { reason: typeof input.reason === "string" ? input.reason : "other" }, timestamp, redact),
117
+ ];
118
+ }
119
+ return { runtime: "claude_code", session_id: sessionId, events };
120
+ }
121
+ function presentFields(input, fields) {
122
+ return Object.fromEntries(fields.flatMap((field) => (Object.prototype.hasOwnProperty.call(input, field) ? [[field, input[field]]] : [])));
123
+ }
124
+ /** Map Cursor hook input conservatively; every semantic mapping is inferred. */
125
+ export function buildCursorEvents(hook, input, options = {}) {
126
+ const sessionId = typeof input.conversation_id === "string" && input.conversation_id
127
+ ? input.conversation_id
128
+ : null;
129
+ if (!sessionId)
130
+ return null;
131
+ const expectedEvent = {
132
+ "post-tool": "postToolUse",
133
+ stop: "stop",
134
+ "session-end": "sessionEnd",
135
+ }[hook];
136
+ if (typeof input.hook_event_name === "string" && input.hook_event_name !== expectedEvent) {
137
+ return null;
138
+ }
139
+ const rawLine = options.rawLine ?? JSON.stringify(input);
140
+ const redact = options.redact !== false;
141
+ const baseIndex = stableIndex(rawLine, input.event_index);
142
+ const timestamp = input.timestamp;
143
+ let events;
144
+ if (hook === "post-tool") {
145
+ const tool = presentFields(input, ["tool_name"]);
146
+ events = [
147
+ event("cursor", sessionId, baseIndex * 2, rawLine, "action", "guessed", { ...tool, ...presentFields(input, ["tool_input"]) }, timestamp, redact),
148
+ event("cursor", sessionId, baseIndex * 2 + 1, rawLine, "observation", "guessed", {
149
+ ...tool,
150
+ ...(Object.prototype.hasOwnProperty.call(input, "tool_output")
151
+ ? { tool_response: input.tool_output }
152
+ : {}),
153
+ }, timestamp, redact),
154
+ ];
155
+ }
156
+ else if (hook === "stop") {
157
+ const content = firstString([input], ["last_assistant_message", "assistant_message", "assistantMessage", "assistant_text", "assistantText"]);
158
+ events = content
159
+ ? [event("cursor", sessionId, baseIndex, rawLine, "message", "guessed", { role: "assistant", content }, timestamp, redact)]
160
+ : [];
161
+ }
162
+ else {
163
+ events = [
164
+ event("cursor", sessionId, baseIndex, rawLine, "session.completed", "guessed", presentFields(input, ["reason"]), timestamp, redact),
165
+ ];
166
+ }
167
+ return { runtime: "cursor", session_id: sessionId, events };
168
+ }
169
+ function firstValue(input, fields) {
170
+ for (const field of fields) {
171
+ if (Object.prototype.hasOwnProperty.call(input, field))
172
+ return input[field];
173
+ }
174
+ return undefined;
175
+ }
176
+ function firstString(inputs, fields) {
177
+ for (const input of inputs) {
178
+ for (const field of fields) {
179
+ const value = input[field];
180
+ if (typeof value === "string" && value)
181
+ return value;
182
+ }
183
+ }
184
+ return null;
185
+ }
186
+ /** Map an OpenCode or Cline hook conservatively; their semantics are inferred. */
187
+ export function buildPluginRuntimeEvent(runtime, hook, input, options = {}) {
188
+ const properties = asObject(input.properties);
189
+ const context = asObject(input.context);
190
+ const sessionId = runtime === "opencode"
191
+ ? firstString([input, properties], ["sessionID"])
192
+ : firstString([input, context], ["taskId", "taskID", "runId", "runID"]);
193
+ if (!sessionId)
194
+ return null;
195
+ const rawLine = options.rawLine ?? JSON.stringify(input);
196
+ const redact = options.redact !== false;
197
+ const index = stableIndex(rawLine, input.event_index);
198
+ const timestamp = firstValue(input, ["timestamp", "time"]);
199
+ const toolName = firstValue(input, ["tool", "toolName", "tool_name"]);
200
+ const toolUseId = firstValue(input, ["callID", "callId", "toolUseId", "tool_use_id"]);
201
+ const toolInput = firstValue(input, ["args", "input", "toolInput", "tool_input"]);
202
+ const toolOutput = firstValue(input, ["output", "result", "toolOutput", "tool_response"]);
203
+ let events;
204
+ if (hook === "post-tool") {
205
+ const common = {
206
+ ...(typeof toolName === "string" ? { tool_name: toolName } : {}),
207
+ ...(typeof toolUseId === "string" ? { tool_use_id: toolUseId } : {}),
208
+ };
209
+ events = [
210
+ event(runtime, sessionId, index * 2, rawLine, "action", "guessed", { ...common, ...(toolInput !== undefined ? { tool_input: toolInput } : {}) }, timestamp, redact),
211
+ event(runtime, sessionId, index * 2 + 1, rawLine, "observation", "guessed", { ...common, ...(toolOutput !== undefined ? { tool_response: toolOutput } : {}) }, timestamp, redact),
212
+ ];
213
+ }
214
+ else if (hook === "stop") {
215
+ const content = firstString([input, properties, context], ["last_assistant_message", "assistant_message", "assistantMessage", "assistant_text", "assistantText"]);
216
+ events = content
217
+ ? [event(runtime, sessionId, index, rawLine, "message", "guessed", { role: "assistant", content }, timestamp, redact)]
218
+ : [];
219
+ }
220
+ else {
221
+ events = [event(runtime, sessionId, index, rawLine, "session.completed", "guessed", {
222
+ reason: typeof input.reason === "string"
223
+ ? input.reason
224
+ : typeof input.type === "string" ? input.type : "other",
225
+ }, timestamp, redact)];
226
+ }
227
+ return {
228
+ runtime,
229
+ session_id: sessionId,
230
+ events,
231
+ };
232
+ }
233
+ function textParts(content) {
234
+ if (typeof content === "string")
235
+ return content;
236
+ if (!Array.isArray(content))
237
+ return "";
238
+ return content
239
+ .flatMap((part) => {
240
+ const obj = asObject(part);
241
+ const type = obj.type;
242
+ if (type === "input_text" || type === "output_text" || type === "text") {
243
+ return typeof obj.text === "string" ? [obj.text] : [];
244
+ }
245
+ return [];
246
+ })
247
+ .join("\n");
248
+ }
249
+ /** Map one Codex session JSONL line using only documented message/tool fields. */
250
+ export function buildCodexEvent(sessionId, lineIndex, rawLine, redact = true) {
251
+ let parsed;
252
+ try {
253
+ parsed = asObject(JSON.parse(rawLine));
254
+ }
255
+ catch {
256
+ return null;
257
+ }
258
+ const payload = asObject(parsed.payload);
259
+ const outerType = typeof parsed.type === "string" ? parsed.type : "";
260
+ const innerType = typeof payload.type === "string" ? payload.type : outerType;
261
+ const timestamp = parsed.timestamp ?? payload.timestamp;
262
+ if (outerType === "session_meta") {
263
+ return event("codex", sessionId, lineIndex, rawLine, "session.started", "seen", {
264
+ runtime: "codex",
265
+ model: typeof payload.model === "string" ? payload.model : undefined,
266
+ }, timestamp, redact);
267
+ }
268
+ if (innerType === "function_call" || innerType === "custom_tool_call") {
269
+ return event("codex", sessionId, lineIndex, rawLine, "action", "seen", {
270
+ tool_name: typeof payload.name === "string" ? payload.name : "unknown",
271
+ tool_use_id: payload.call_id,
272
+ tool_input: payload.arguments ?? payload.input ?? {},
273
+ }, timestamp, redact);
274
+ }
275
+ if (innerType === "function_call_output" || innerType === "custom_tool_call_output") {
276
+ return event("codex", sessionId, lineIndex, rawLine, "observation", "seen", {
277
+ tool_use_id: payload.call_id,
278
+ tool_response: payload.output ?? "",
279
+ }, timestamp, redact);
280
+ }
281
+ if (innerType === "error" || outerType === "error") {
282
+ return event("codex", sessionId, lineIndex, rawLine, "error", "seen", { message: payload.message ?? parsed.message ?? "Codex session error" }, timestamp, redact);
283
+ }
284
+ if (innerType === "turn_aborted" || innerType === "task_complete") {
285
+ return event("codex", sessionId, lineIndex, rawLine, "session.completed", "guessed", { reason: innerType }, timestamp, redact);
286
+ }
287
+ const role = typeof payload.role === "string"
288
+ ? payload.role
289
+ : innerType === "agent_message" ? "assistant" : "unknown";
290
+ const content = textParts(payload.content) ||
291
+ (typeof payload.message === "string" ? payload.message : "");
292
+ if (content) {
293
+ return event("codex", sessionId, lineIndex, rawLine, "message", innerType === "message" || innerType === "agent_message" ? "seen" : "guessed", { role, content }, timestamp, redact);
294
+ }
295
+ return null;
296
+ }
297
+ export async function sendCapture(state, payload, fetchImpl = fetch) {
298
+ if (!payload.events.length)
299
+ return;
300
+ const base = state.api_url.replace(/\/+$/, "");
301
+ const headers = {
302
+ Authorization: `Bearer ${state.token}`,
303
+ "Content-Type": "application/json",
304
+ };
305
+ if (state.brand_id !== null)
306
+ headers["X-Brand-ID"] = String(state.brand_id);
307
+ const response = await fetchImpl(`${base}/api/v1/memory/ingest`, {
308
+ method: "POST",
309
+ headers,
310
+ body: JSON.stringify(payload),
311
+ });
312
+ if (!response.ok)
313
+ throw new Error(`ingest returned HTTP ${response.status}`);
314
+ }
315
+ async function readStdin() {
316
+ const chunks = [];
317
+ let length = 0;
318
+ for await (const chunk of process.stdin) {
319
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
320
+ length += buffer.length;
321
+ if (length > MAX_STDIN_BYTES)
322
+ throw new Error("hook input exceeds 2 MiB");
323
+ chunks.push(buffer);
324
+ }
325
+ return Buffer.concat(chunks).toString("utf8");
326
+ }
327
+ const AGENT_HOOK_DEPENDENCIES = {
328
+ loadState: loadCaptureState,
329
+ send: sendCapture,
330
+ readInput: readStdin,
331
+ };
332
+ function isClaudeHookInput(hook, input) {
333
+ if (typeof input.session_id !== "string" || !input.session_id)
334
+ return false;
335
+ if (hook === "post-tool") {
336
+ return typeof input.tool_name === "string" && (Object.prototype.hasOwnProperty.call(input, "tool_input") ||
337
+ Object.prototype.hasOwnProperty.call(input, "tool_response"));
338
+ }
339
+ if (hook === "stop")
340
+ return typeof input.last_assistant_message === "string";
341
+ return typeof input.reason === "string";
342
+ }
343
+ export async function runAgentHook(hook, dependencies = {}, options = {}) {
344
+ const deps = { ...AGENT_HOOK_DEPENDENCIES, ...dependencies };
345
+ const state = deps.loadState();
346
+ if (!state)
347
+ return;
348
+ const raw = await deps.readInput();
349
+ let input;
350
+ try {
351
+ input = asObject(JSON.parse(raw));
352
+ }
353
+ catch {
354
+ return;
355
+ }
356
+ const payload = options.runtime
357
+ ? buildPluginRuntimeEvent(options.runtime, hook, input, { rawLine: raw })
358
+ : typeof input.conversation_id === "string"
359
+ ? buildCursorEvents(hook, input, { rawLine: raw })
360
+ : isClaudeHookInput(hook, input)
361
+ ? buildClaudeEvents(hook, input, { rawLine: raw })
362
+ : null;
363
+ if (!payload?.events.length)
364
+ return;
365
+ await deps.send(state, payload);
366
+ }
367
+ function jsonlFiles(root) {
368
+ if (!existsSync(root))
369
+ return [];
370
+ const found = [];
371
+ const walk = (dir) => {
372
+ let entries;
373
+ try {
374
+ entries = readdirSync(dir, { withFileTypes: true });
375
+ }
376
+ catch {
377
+ return;
378
+ }
379
+ for (const entry of entries) {
380
+ const path = join(dir, entry.name);
381
+ if (entry.isDirectory())
382
+ walk(path);
383
+ else if (entry.isFile() && entry.name.endsWith(".jsonl"))
384
+ found.push(path);
385
+ }
386
+ };
387
+ walk(root);
388
+ return found;
389
+ }
390
+ /** Find only the rollout belonging to this Codex thread. */
391
+ export function codexRolloutForThread(root, threadId) {
392
+ if (!/^[A-Za-z0-9_-]+$/.test(threadId))
393
+ return null;
394
+ let newest = null;
395
+ for (const path of jsonlFiles(root)) {
396
+ const name = basename(path);
397
+ if (!name.startsWith("rollout-") || !name.endsWith(`-${threadId}.jsonl`))
398
+ continue;
399
+ let mtime;
400
+ try {
401
+ mtime = statSync(path).mtimeMs;
402
+ }
403
+ catch {
404
+ continue;
405
+ }
406
+ if (!newest || mtime > newest.mtime)
407
+ newest = { path, mtime };
408
+ }
409
+ return newest?.path ?? null;
410
+ }
411
+ function threadIdFromNotify(raw) {
412
+ let value;
413
+ try {
414
+ value = JSON.parse(raw);
415
+ }
416
+ catch {
417
+ return null;
418
+ }
419
+ const find = (candidate) => {
420
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate))
421
+ return null;
422
+ const input = candidate;
423
+ for (const key of ["thread-id", "thread_id", "session_id"]) {
424
+ if (typeof input[key] === "string" && input[key])
425
+ return input[key];
426
+ }
427
+ for (const key of ["payload", "input", "hook_input"]) {
428
+ const nested = find(input[key]);
429
+ if (nested)
430
+ return nested;
431
+ }
432
+ return null;
433
+ };
434
+ return find(value);
435
+ }
436
+ const CODEX_NOTIFY_DEPENDENCIES = {
437
+ loadState: loadCaptureState,
438
+ saveState: saveCaptureState,
439
+ send: sendCapture,
440
+ readInput: () => process.stdin.isTTY ? Promise.resolve("") : readStdin(),
441
+ codexHome: () => process.env.CODEX_HOME || join(homedir(), ".codex"),
442
+ };
443
+ export async function runCodexNotify(payload, dependencies = {}) {
444
+ const deps = { ...CODEX_NOTIFY_DEPENDENCIES, ...dependencies };
445
+ const rawInput = payload ?? await deps.readInput();
446
+ const threadId = threadIdFromNotify(rawInput);
447
+ if (!threadId)
448
+ return;
449
+ const state = deps.loadState();
450
+ if (!state)
451
+ return;
452
+ const path = codexRolloutForThread(join(deps.codexHome(), "sessions"), threadId);
453
+ if (!path)
454
+ return;
455
+ const raw = readFileSync(path, "utf8");
456
+ const lines = raw.split(/\r?\n/);
457
+ // A writer may be between chunks when notify fires. Never advance past an
458
+ // incomplete JSONL record; the next notification will see the whole line.
459
+ lines.pop();
460
+ const previous = state.codex_files[path] ?? 0;
461
+ const start = previous <= lines.length ? previous : 0;
462
+ const events = lines
463
+ .slice(start)
464
+ .map((line, offset) => buildCodexEvent(threadId, start + offset, line))
465
+ .filter((item) => item !== null);
466
+ await deps.send(state, { runtime: "codex", session_id: threadId, events });
467
+ state.codex_files[path] = lines.length;
468
+ deps.saveState(state);
469
+ }
470
+ async function verifyIngestOnlyToken(token, apiUrl, brandId, fetchImpl = fetch) {
471
+ const headers = { Authorization: `Bearer ${token}` };
472
+ if (brandId !== null)
473
+ headers["X-Brand-ID"] = String(brandId);
474
+ const response = await fetchImpl(`${apiUrl.replace(/\/+$/, "")}/api/v1/auth/me`, { headers });
475
+ if (!response.ok)
476
+ throw new Error(`token check returned HTTP ${response.status}`);
477
+ const body = asObject(await response.json());
478
+ const tokenInfo = asObject(body.token);
479
+ const scopes = Array.isArray(tokenInfo.scopes)
480
+ ? tokenInfo.scopes.filter((scope) => typeof scope === "string")
481
+ : [];
482
+ if (scopes.length !== 1 || scopes[0] !== INGEST_SCOPE) {
483
+ throw new Error(`capture requires a PAT whose only scope is ${INGEST_SCOPE}`);
484
+ }
485
+ }
486
+ async function promptForToken() {
487
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
488
+ try {
489
+ return (await rl.question(`Memory-only PAT (${INGEST_SCOPE}): `)).trim();
490
+ }
491
+ finally {
492
+ rl.close();
493
+ }
494
+ }
495
+ export async function enableCapture(workspace, suppliedToken, fetchImpl = fetch) {
496
+ const cfg = getEffectiveConfig(workspace);
497
+ const token = (suppliedToken ?? process.env.OPVS_MEMORY_INGEST_TOKEN ?? await promptForToken()).trim();
498
+ if (!token)
499
+ throw new Error("a memory-only PAT is required");
500
+ const brandId = typeof cfg.brand_id === "number" ? cfg.brand_id : null;
501
+ await verifyIngestOnlyToken(token, cfg.api_url, brandId, fetchImpl);
502
+ saveCaptureState({
503
+ version: STATE_VERSION,
504
+ enabled: true,
505
+ token,
506
+ api_url: cfg.api_url,
507
+ brand_id: brandId,
508
+ codex_files: {},
509
+ });
510
+ }
511
+ async function runHookSafely(action) {
512
+ try {
513
+ await action();
514
+ }
515
+ catch (error) {
516
+ const message = error instanceof Error ? error.message : "unknown capture error";
517
+ process.stderr.write(`Memory capture skipped: ${message}\n`);
518
+ }
519
+ }
520
+ function pluginRuntime(value) {
521
+ if (value === undefined || value === "cline" || value === "opencode")
522
+ return value;
523
+ throw new Error(`unsupported hook runtime '${value}' (expected opencode or cline)`);
524
+ }
525
+ /** Add `hook ...` and `capture on|off` below an existing memory command. */
526
+ export function registerCaptureHooks(memory) {
527
+ const hook = memory.commands.find((command) => command.name() === "hook")
528
+ ?? memory.command("hook").description("Receive a local agent session hook");
529
+ hook.command("post-tool").description("Capture a runtime post-tool event")
530
+ .option("--runtime <runtime>", "Input runtime (opencode or cline)")
531
+ .action((opts) => runHookSafely(() => (runAgentHook("post-tool", {}, { runtime: pluginRuntime(opts.runtime) }))));
532
+ hook.command("stop").description("Capture a runtime stop event")
533
+ .option("--runtime <runtime>", "Input runtime (opencode or cline)")
534
+ .action((opts) => runHookSafely(() => (runAgentHook("stop", {}, { runtime: pluginRuntime(opts.runtime) }))));
535
+ hook.command("session-end").description("Capture a runtime session-end event")
536
+ .option("--runtime <runtime>", "Input runtime (opencode or cline)")
537
+ .action((opts) => runHookSafely(() => (runAgentHook("session-end", {}, { runtime: pluginRuntime(opts.runtime) }))));
538
+ hook.command("codex-notify [payload]").description("Capture new lines from this Codex thread")
539
+ .action((payload) => runHookSafely(() => runCodexNotify(payload)));
540
+ const capture = memory.command("capture").description("Manage opt-in local session capture");
541
+ capture.command("on")
542
+ .description(`Enable capture with a PAT scoped only to ${INGEST_SCOPE}`)
543
+ .option("--token <pat>", "Dedicated PAT (or set OPVS_MEMORY_INGEST_TOKEN)")
544
+ .action(async (opts) => {
545
+ try {
546
+ await enableCapture(memory.parent?.opts().workspace, opts.token);
547
+ console.log("Memory capture enabled. Claude Code hooks activate with the plugin; " +
548
+ 'for Codex set notify = ["opvs", "memory", "hook", "codex-notify"] in user config.toml.');
549
+ }
550
+ catch (error) {
551
+ console.error(error instanceof Error ? error.message : String(error));
552
+ process.exitCode = 1;
553
+ }
554
+ });
555
+ capture.command("off")
556
+ .description("Disable capture and remove the dedicated local PAT")
557
+ .action(() => {
558
+ disableCapture();
559
+ console.log("Memory capture disabled and its local PAT removed.");
560
+ });
561
+ }
562
+ //# sourceMappingURL=memory-capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-capture.js","sourceRoot":"","sources":["../../src/commands/memory-capture.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Claude Code memory hooks.
2
+ * Claude Code and Codex memory hooks.
3
3
  *
4
4
  * SessionStart is deliberately fail-open: a missing login, an unavailable
5
5
  * gateway, malformed hook input, or an unexpected response must never stop a
@@ -97,9 +97,18 @@ function searchParams(cwd, deps) {
97
97
  export async function runSessionStartHook(dependencies = {}, budget = MEMORY_CONTEXT_CHAR_BUDGET) {
98
98
  const deps = { ...DEFAULT_DEPENDENCIES, ...dependencies };
99
99
  try {
100
- const input = JSON.parse(await deps.readInput());
100
+ const parsed = JSON.parse(await deps.readInput());
101
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
102
+ return;
103
+ const input = parsed;
101
104
  if (typeof input.cwd !== "string" || input.cwd.length === 0)
102
105
  return;
106
+ // Both runtimes may provide a session/thread id. Reading it defensively
107
+ // here keeps unknown future fields harmless; SessionStart lookup only
108
+ // needs cwd today.
109
+ const sessionId = input.session_id ?? input.thread_id ?? input["thread-id"];
110
+ if (sessionId !== undefined && typeof sessionId !== "string")
111
+ return;
103
112
  const params = searchParams(input.cwd, deps);
104
113
  const workspace = process.env.OPVS_WORKSPACE;
105
114
  const cfg = deps.getConfig(workspace);
@@ -119,9 +128,9 @@ export async function runSessionStartHook(dependencies = {}, budget = MEMORY_CON
119
128
  export function registerMemoryHooks(memory) {
120
129
  memory
121
130
  .command("hook")
122
- .description("Claude Code memory hooks")
131
+ .description("Agent runtime memory hooks")
123
132
  .command("session-start")
124
- .description("Print relevant memories for a Claude Code SessionStart hook")
133
+ .description("Print relevant memories for a SessionStart hook")
125
134
  .action(async () => {
126
135
  await runSessionStartHook();
127
136
  });