@ephemushroom/opencode-claude-mem 0.6.2 → 0.7.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.
@@ -2,101 +2,56 @@ export interface WorkerEndpoint {
2
2
  readonly host: string;
3
3
  readonly port: number;
4
4
  }
5
- export type AutoStartResult = 'already-running' | 'started' | 'no-bun' | 'spawn-failed' | 'timeout' | 'skipped';
6
- export type SearchOrder = 'date_desc' | 'date_asc' | 'relevance';
7
- export interface SearchOptions {
8
- readonly query?: string;
9
- readonly limit?: number;
10
- readonly project?: string;
11
- readonly platformSource?: string;
12
- readonly type?: string;
13
- readonly obs_type?: string;
14
- readonly dateStart?: string;
15
- readonly dateEnd?: string;
16
- readonly offset?: number;
17
- readonly orderBy?: SearchOrder;
5
+ export interface ProjectCounts {
6
+ readonly observations: number;
7
+ readonly summaries: number;
8
+ readonly sessions: number;
18
9
  }
19
- export interface ObservedMetadata {
20
- readonly observedModel?: string;
21
- readonly observedBilling?: string;
22
- }
23
- export declare function parseWorkerEndpoint(env: Record<string, string | undefined>, rawSettings: string | null): WorkerEndpoint;
24
- export declare function buildSearchParams(options: SearchOptions): URLSearchParams;
10
+ type JsonRecord = Record<string, unknown>;
11
+ export declare function isRecord(value: unknown): value is JsonRecord;
12
+ /** claude-mem's data directory, which holds its settings.json: the environment, else ~/.claude-mem. */
13
+ export declare function dataDirectory(env: Record<string, string | undefined>, home: string): string;
14
+ /**
15
+ * The port a Worker uses when none is configured: 37700 plus the user id's last two
16
+ * digits, or on Windows (no user id) a number derived from the data directory.
17
+ */
18
+ export declare function defaultWorkerPort(dataDir: string, platform?: NodeJS.Platform, uid?: number | null): number;
19
+ export declare function parseWorkerEndpoint(env: Record<string, string | undefined>, rawSettings: string | null, fallbackPort?: number): WorkerEndpoint;
20
+ /** True for this machine: localhost, *.localhost, ::1 and 127.0.0.0/8. */
21
+ export declare function isLoopbackHost(host: string): boolean;
22
+ /** An IPv6 host needs brackets inside a URL. */
23
+ export declare function workerUrl(endpoint: WorkerEndpoint): string;
24
+ /**
25
+ * The header a Worker with `CLAUDE_MEM_LOCAL_API_TOKEN` requires on everything but its
26
+ * health check. The token is read from the settings file only, and is sent only to a
27
+ * Worker on this machine.
28
+ */
29
+ export declare function tokenHeaders(baseUrl: string, rawSettings: string | null): Record<string, string>;
30
+ /**
31
+ * The Worker's SQLite database: CLAUDE_MEM_DATA_DIR from env, then settings, then
32
+ * ~/.claude-mem. Null when the Worker is not on this machine, because a local file would
33
+ * then describe a different store.
34
+ */
35
+ export declare function resolveDatabasePath(env: Record<string, string | undefined>, rawSettings: string | null, home: string): string | null;
36
+ /** Read-only per-project counts; null on a missing, locked or unexpected database. */
37
+ export declare function readProjectCounts(path: string, project: string): Promise<ProjectCounts | null>;
38
+ /** A claude-mem setting: the environment first, then the data directory's settings.json. */
39
+ export declare function readWorkerSetting(key: string): string | null;
40
+ export declare function getWorkerEndpoint(): WorkerEndpoint;
25
41
  export declare function getWorkerBaseUrl(): string;
42
+ /** Headers for a request to `baseUrl`: the local token when that Worker needs one. */
43
+ export declare function workerHeaders(baseUrl?: string): Record<string, string>;
26
44
  export declare class WorkerClient {
27
45
  private static readonly BASE_URL;
28
- /** Per-process guard so multiple OpenCode windows don't all spawn workers. */
29
- private static autoStartPromise;
30
- /**
31
- * Check if the worker is healthy
32
- */
33
- static isHealthy(): Promise<boolean>;
34
- /**
35
- * Ensure the worker is running. If healthy, returns true. Otherwise tries
36
- * to spawn it via `bunx claude-mem start` in the background and resolves
37
- * once the worker reports healthy or the timeout is reached.
38
- *
39
- * Idempotent + serialised within the process via `autoStartPromise`.
40
- */
41
- static ensureRunning(): Promise<boolean>;
42
- /**
43
- * Try to auto-start the Claude-Mem worker via `bunx claude-mem start`.
44
- *
45
- * Behaviour:
46
- * - If the worker is already healthy, returns 'already-running' immediately.
47
- * - If `bun` is not on PATH, returns 'no-bun' without attempting to spawn.
48
- * - Otherwise spawns a detached `bunx claude-mem start` process and polls
49
- * /api/health for ~8 seconds. Returns 'started' on success, 'timeout' on
50
- * failure to come up, 'spawn-failed' if the spawn itself errored.
51
- *
52
- * Concurrent calls share the same in-flight promise.
53
- */
54
- static tryAutoStart(): Promise<AutoStartResult>;
55
- private static runAutoStart;
56
- /**
57
- * Locate the `bun` executable. Prefers Bun's own runtime detector when the
58
- * plugin is loaded inside Bun (which OpenCode currently is), then falls back
59
- * to PATH probing via `process.env.PATH`.
60
- */
61
- private static findBun;
62
- /**
63
- * Initialize a session
64
- */
65
- static sessionInit(contentSessionId: string, project: string, prompt: string): Promise<{
66
- sessionDbId: number;
67
- promptNumber: number;
68
- skipped?: boolean;
69
- reason?: string;
70
- } | null>;
71
- /**
72
- * Send observation
73
- */
74
- static sendObservation(contentSessionId: string, toolName: string, toolInput: unknown, toolResponse: unknown, cwd: string, toolUseId?: string): Promise<boolean>;
46
+ private static readonly SUPPORTED;
47
+ private static readonly DATABASE_PATH;
48
+ private static get;
75
49
  /**
76
- * Trigger summarization
50
+ * Per-project counts, read from the Worker's database in read-only mode. The Worker's
51
+ * HTTP API only reports global totals. Null when the database is remote, missing,
52
+ * locked or of an unknown schema; the sidebar then falls back to the global totals.
77
53
  */
78
- static summarize(contentSessionId: string, lastUserMessage: string, lastAssistantMessage: string, metadata?: ObservedMetadata): Promise<boolean>;
79
- /**
80
- * Get pre-formatted context for system prompt injection.
81
- * Uses /api/context/inject which returns rich markdown with observations + session summaries.
82
- */
83
- static getContext(project: string): Promise<string | null>;
84
- /**
85
- * Timeline: get chronological context around an observation anchor or query.
86
- * Mirrors the upstream MCP `timeline` tool (GET /api/timeline).
87
- */
88
- static timeline(options: {
89
- project: string;
90
- anchor?: number;
91
- query?: string;
92
- depthBefore?: number;
93
- depthAfter?: number;
94
- }): Promise<string>;
95
- /**
96
- * Fetch full observation details by IDs.
97
- * Mirrors the upstream MCP `get_observations` tool (POST /api/observations/batch).
98
- */
99
- static getObservations(ids: number[], project?: string): Promise<string>;
54
+ static getProjectCounts(project: string): Promise<ProjectCounts | null>;
100
55
  /**
101
56
  * Fetch worker + database stats plus processing status for the sidebar view.
102
57
  * Combines GET /api/stats and GET /api/processing-status; null when offline.
@@ -118,6 +73,7 @@ export declare class WorkerClient {
118
73
  static getRecentSummaries(project: string, limit: number): Promise<{
119
74
  id: number;
120
75
  request: string;
76
+ at: number | null;
121
77
  }[]>;
122
78
  /**
123
79
  * Recent observations for the sidebar (GET /api/observations).
@@ -126,6 +82,12 @@ export declare class WorkerClient {
126
82
  id: number;
127
83
  type: string;
128
84
  title: string;
85
+ at: number | null;
129
86
  }[]>;
130
- static search(options: SearchOptions): Promise<string>;
87
+ /**
88
+ * One observation (GET /api/observation/:id) or session summary (GET /api/session/:id)
89
+ * for the detail dialog; null when missing or offline.
90
+ */
91
+ static getDetail(kind: 'summary' | 'observation', id: number): Promise<Record<string, unknown> | null>;
131
92
  }
93
+ export {};
@@ -0,0 +1,46 @@
1
+ export type WorkerState =
2
+ /** `version` is null when the Worker answered without a readable version. */
3
+ {
4
+ readonly status: 'running';
5
+ readonly version: string | null;
6
+ }
7
+ /** No launcher: claude-mem is not installed on this machine. */
8
+ | {
9
+ readonly status: 'missing';
10
+ }
11
+ /** Not running, and this machine is told not to start it (or it runs elsewhere). */
12
+ | {
13
+ readonly status: 'disabled';
14
+ }
15
+ /** The launcher ran, and the port still does not answer. */
16
+ | {
17
+ readonly status: 'failed';
18
+ };
19
+ export interface WorkerStartDeps {
20
+ /** Null only when the connection was refused, meaning no Worker holds the port. */
21
+ readonly probe: () => Promise<{
22
+ version: string | null;
23
+ } | null>;
24
+ readonly disabled: () => boolean;
25
+ readonly launcher: () => string | null;
26
+ /** Resolves false when the launcher could not be spawned. */
27
+ readonly start: (launcher: string) => Promise<boolean>;
28
+ readonly waitMs: number;
29
+ readonly pollMs: number;
30
+ }
31
+ /**
32
+ * True for a refused connection, however the runtime reports it: Bun sets
33
+ * `code: 'ConnectionRefused'`, Node keeps ECONNREFUSED on `cause` or nested `errors`.
34
+ */
35
+ export declare function isConnectionRefused(error: unknown, seen?: Set<unknown>): boolean;
36
+ /** Where `npx claude-mem install` places the launcher (claude-mem's install-launcher.ts). */
37
+ export declare function launcherPath(platform: NodeJS.Platform, env: Record<string, string | undefined>, home: string): string;
38
+ /**
39
+ * claude-mem's own switches for "do not start a Worker here": an explicit Worker URL,
40
+ * `CLAUDE_MEM_WORKER_AUTOSTART=false`, or a Worker host that is another machine.
41
+ */
42
+ export declare function autostartDisabled(read: (key: string) => string | null, host?: string): boolean;
43
+ /** The Worker as it is now, without starting anything. */
44
+ export declare function workerState(deps?: WorkerStartDeps): Promise<WorkerState>;
45
+ /** One start at a time per process; every caller during it gets the same answer. */
46
+ export declare function ensureWorker(deps?: WorkerStartDeps): Promise<WorkerState>;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * One namespace for every tool: a direct tool call sees `claude_mem_<name>`, Code Mode
3
+ * sees `tools.claude_mem.<name>` under a single catalog entry with this description.
4
+ */
5
+ export declare const TOOL_NAMESPACE: {
6
+ readonly name: "claude_mem";
7
+ readonly description: "claude-mem memory beyond search. work_state_write / work_state_read are your canonical to-do list and working state for this project: use them instead of any built-in to-do tool. save_memory records a durable note. dumb_search is a one-call lookup; get_tool_uses fetches raw tool I/O; the corpus tools build and query knowledge corpora.";
8
+ };
9
+ export interface WorkerTool {
10
+ /** Without the namespace: `save_memory`, not `claude_mem_save_memory`. */
11
+ readonly name: string;
12
+ readonly description: string;
13
+ readonly input: Record<string, unknown>;
14
+ readonly options: {
15
+ readonly namespace: string;
16
+ readonly pinned?: true;
17
+ };
18
+ /** `context.signal` aborts when the session stops; the request is dropped with it. */
19
+ readonly execute: (input: unknown, context?: {
20
+ readonly signal?: AbortSignal;
21
+ }) => Promise<{
22
+ content: string;
23
+ }>;
24
+ }
25
+ export interface WorkerToolOptions {
26
+ /** The session's checkout: the Worker derives the project from it. */
27
+ readonly directory: string;
28
+ readonly baseUrl?: string;
29
+ /** Starts the Worker after a refused connection; resolves true when it answers. */
30
+ readonly startWorker?: () => Promise<boolean>;
31
+ readonly corpusIdleTimeoutMs?: number;
32
+ }
33
+ export declare function createWorkerTools(options: WorkerToolOptions): WorkerTool[];
package/package.json CHANGED
@@ -1,25 +1,15 @@
1
1
  {
2
2
  "name": "@ephemushroom/opencode-claude-mem",
3
- "version": "0.6.2",
4
- "description": "OpenCode plugin for Claude-Mem persistent memory system",
5
- "main": "./dist/package-server.js",
6
- "types": "./dist/package-server.d.ts",
3
+ "version": "0.7.1",
4
+ "description": "Claude-Mem for OpenCode: capture through the official claude-mem plugin, memory tools and the Memory sidebar in one package",
7
5
  "type": "module",
8
6
  "files": [
9
7
  "dist"
10
8
  ],
11
9
  "exports": {
12
- ".": {
13
- "types": "./dist/package-server.d.ts",
14
- "import": "./dist/package-server.js"
15
- },
16
- "./v2": {
17
- "types": "./dist/v2.d.ts",
18
- "import": "./dist/v2.js"
19
- },
20
10
  "./server": {
21
- "types": "./dist/package-server.d.ts",
22
- "import": "./dist/package-server.js"
11
+ "types": "./dist/server.d.ts",
12
+ "import": "./dist/server.js"
23
13
  },
24
14
  "./tui": {
25
15
  "types": "./dist/package-tui.d.ts",
@@ -31,7 +21,7 @@
31
21
  }
32
22
  },
33
23
  "scripts": {
34
- "build": "bun build src/index.ts --outfile dist/index.js --target bun --format esm && bun build src/v2.ts --outfile dist/v2.js --target bun --format esm && bun build src/tui.ts --outfile dist/tui.js --target bun --format esm --external @opentui/solid --external solid-js && bun build src/cli.ts --outfile dist/cli.js --target bun --format esm --external @opentui/solid --external solid-js && bun build src/package-server.ts --outdir dist --target bun --format esm --external '*' && bun src/build-tui-bridge.ts && tsc -p tsconfig.build.json --emitDeclarationOnly",
24
+ "build": "bun build src/server.ts --outfile dist/server.js --target bun --format esm && bun build src/tui.ts --outfile dist/tui.js --target bun --format esm --external @opentui/solid --external solid-js && bun build src/cli.ts --outfile dist/cli.js --target bun --format esm --external @opentui/solid --external solid-js && bun src/build-tui-bridge.ts && tsc -p tsconfig.build.json --emitDeclarationOnly",
35
25
  "dev": "tsc --watch",
36
26
  "clean": "rm -rf dist",
37
27
  "lint": "oxlint",
@@ -61,19 +51,16 @@
61
51
  "access": "public"
62
52
  },
63
53
  "dependencies": {
64
- "@opentui/solid": "0.5.10"
54
+ "@opentui/solid": "0.8.1"
65
55
  },
66
56
  "devDependencies": {
67
- "@opencode-ai/plugin": "^1.14.41",
68
- "@opencode-ai/plugin-v2": "npm:@opencode-ai/plugin@0.0.0-beta-19151",
69
- "@opencode-ai/theme": "^0.0.0-next-17030",
70
- "@opencode/plugin": "2.0.16",
71
- "@opencode/theme": "2.0.16",
72
- "@opentui/core": "0.5.10",
57
+ "@opencode/plugin": "2.2.7",
58
+ "@opencode/theme": "2.2.7",
59
+ "@opentui/core": "0.8.1",
73
60
  "@types/bun": "latest",
74
61
  "oxfmt": "^0.33.0",
75
62
  "oxlint": "^1.63.0",
76
- "solid-js": "1.9.14",
63
+ "solid-js": "1.9.17",
77
64
  "typescript": "^5.9.3",
78
65
  "zod": "4.1.8"
79
66
  }
@@ -1,17 +0,0 @@
1
- import type { InjectionOptions } from './memory-options';
2
- import { MemoryWorker } from './memory-worker';
3
- export declare class FileContext {
4
- private readonly sessions;
5
- private readonly options;
6
- private readonly worker;
7
- constructor(options: InjectionOptions, worker?: typeof MemoryWorker);
8
- read(session: string, input: {
9
- readonly tool: string;
10
- readonly args: unknown;
11
- }, location: {
12
- readonly directory: string;
13
- readonly project: string;
14
- }): Promise<string>;
15
- delete(session: string): void;
16
- clear(): void;
17
- }
package/dist/index.d.ts DELETED
@@ -1,20 +0,0 @@
1
- import { type Plugin } from '@opencode-ai/plugin';
2
- /**
3
- * OpenCode Plugin for Claude-Mem
4
- *
5
- * Hooks used:
6
- * - `event` — session lifecycle (session.created, session.idle, session.compacted,
7
- * session.deleted, message.updated, file.edited)
8
- * - `tool.execute.after` — capture tool observations
9
- * - `experimental.chat.system.transform` — inject memory context into system prompt
10
- * - `experimental.session.compacting` — preserve memory context during compaction
11
- * - `chat.message` — session init with real user prompt
12
- *
13
- * Memory context is automatically injected into every conversation via system prompt.
14
- * No manual commands needed - the plugin works transparently in the background.
15
- */
16
- export declare const ClaudeMemPlugin: Plugin;
17
- declare const _default: {
18
- server: Plugin;
19
- };
20
- export default _default;