@ephemushroom/opencode-claude-mem 0.4.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +313 -48
- package/dist/build-tui-bridge.d.ts +1 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.js +743 -0
- package/dist/file-context.d.ts +17 -0
- package/dist/index.js +2677 -2129
- package/dist/memory-options.d.ts +12 -0
- package/dist/memory-session.d.ts +22 -0
- package/dist/memory-turn.d.ts +10 -0
- package/dist/memory-worker.d.ts +21 -0
- package/dist/package-server.d.ts +7 -0
- package/dist/package-server.js +10 -0
- package/dist/package-tui.d.ts +6 -0
- package/dist/package-tui.js +8 -0
- package/dist/shared.d.ts +14 -0
- package/dist/sidebar-model.d.ts +50 -0
- package/dist/tui-registration.d.ts +7 -0
- package/dist/tui.d.ts +0 -36
- package/dist/tui.js +83 -36
- package/dist/v2.d.ts +22 -0
- package/dist/v2.js +5133 -0
- package/dist/worker-client.d.ts +9 -6
- package/package.json +27 -11
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface InjectionOptions {
|
|
2
|
+
readonly enabled: boolean;
|
|
3
|
+
readonly limit: number;
|
|
4
|
+
readonly maxChars: number;
|
|
5
|
+
readonly timeoutMs: number;
|
|
6
|
+
}
|
|
7
|
+
export interface MemoryOptions {
|
|
8
|
+
readonly semanticInjection: InjectionOptions;
|
|
9
|
+
readonly fileContext: InjectionOptions;
|
|
10
|
+
}
|
|
11
|
+
export declare function parseMemoryOptions(options: unknown, env: Readonly<Record<string, string | undefined>>, settings: unknown): MemoryOptions;
|
|
12
|
+
export declare function resolveMemoryOptions(options: unknown): MemoryOptions;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { MemoryOptions } from './memory-options';
|
|
2
|
+
import type { MemoryTurn } from './memory-turn';
|
|
3
|
+
import { MemoryWorker } from './memory-worker';
|
|
4
|
+
export declare class MemorySessions {
|
|
5
|
+
private readonly sessions;
|
|
6
|
+
private readonly deleted;
|
|
7
|
+
private readonly options;
|
|
8
|
+
private readonly worker;
|
|
9
|
+
constructor(options: MemoryOptions, worker?: typeof MemoryWorker);
|
|
10
|
+
private state;
|
|
11
|
+
select(session: string, turn: MemoryTurn): boolean;
|
|
12
|
+
hasTurn(session: string): boolean;
|
|
13
|
+
hasMessage(session: string, id: string): boolean;
|
|
14
|
+
isDeleted(session: string): boolean;
|
|
15
|
+
canCapture(session: string): boolean;
|
|
16
|
+
register(session: string, project: string): Promise<boolean>;
|
|
17
|
+
semantic(session: string, project: string): Promise<string>;
|
|
18
|
+
context(session: string, project: string): Promise<string | null>;
|
|
19
|
+
invalidate(session: string): void;
|
|
20
|
+
delete(session: string): void;
|
|
21
|
+
clear(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface MemoryTurn {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly text: string;
|
|
4
|
+
readonly capture: boolean;
|
|
5
|
+
readonly semantic: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function memoryTurn(id: string, text: string, media?: boolean): MemoryTurn;
|
|
8
|
+
/** Only consumed session context, never the admission/inbox list. */
|
|
9
|
+
export declare function deliveredTurn(messages: readonly unknown[]): MemoryTurn | undefined;
|
|
10
|
+
export declare function resumedV1Turn(messages: unknown): MemoryTurn | undefined;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { InjectionOptions } from './memory-options';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
declare const fileResponse: z.ZodObject<{
|
|
4
|
+
observations: z.ZodArray<z.ZodObject<{
|
|
5
|
+
id: z.ZodNumber;
|
|
6
|
+
title: z.ZodNullable<z.ZodString>;
|
|
7
|
+
type: z.ZodString;
|
|
8
|
+
created_at_epoch: z.ZodNumber;
|
|
9
|
+
memory_session_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
10
|
+
}, z.core.$strip>>;
|
|
11
|
+
count: z.ZodNumber;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
export type FileObservation = z.infer<typeof fileResponse>['observations'][number];
|
|
14
|
+
export declare class MemoryWorker {
|
|
15
|
+
private static readonly baseUrl;
|
|
16
|
+
private static json;
|
|
17
|
+
static save(input: unknown, project: string): Promise<string>;
|
|
18
|
+
static semantic(prompt: string, project: string, options: InjectionOptions): Promise<string>;
|
|
19
|
+
static byFile(paths: readonly string[], project: string, options: InjectionOptions): Promise<readonly FileObservation[]>;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ClaudeMemPlugin } from './index';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
id: string;
|
|
4
|
+
server: import("@opencode-ai/plugin").Plugin;
|
|
5
|
+
setup: (context: import("@opencode-ai/plugin-v2/promise/plugin").Context) => Promise<import("@opencode-ai/plugin-v2/promise/plugin").Cleanup | void> | import("@opencode-ai/plugin-v2/promise/plugin").Cleanup | void;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/package-server.ts
|
|
3
|
+
import v1 from "./index";
|
|
4
|
+
import v2 from "./v2";
|
|
5
|
+
import { ClaudeMemPlugin } from "./index";
|
|
6
|
+
var package_server_default = { id: v2.id, server: v1.server, setup: v2.setup };
|
|
7
|
+
export {
|
|
8
|
+
ClaudeMemPlugin,
|
|
9
|
+
package_server_default as default
|
|
10
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
id: string;
|
|
3
|
+
tui: (api: any) => Promise<void>;
|
|
4
|
+
setup: (context: import("@opencode-ai/plugin-v2/tui/context").Context) => Promise<import("@opencode-ai/plugin-v2/tui/plugin").Cleanup | void> | import("@opencode-ai/plugin-v2/tui/plugin").Cleanup | void;
|
|
5
|
+
};
|
|
6
|
+
export default _default;
|
package/dist/shared.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const MAX_OBSERVATION_BYTES: number;
|
|
2
|
+
export declare const MAX_TAG_REPLACEMENTS = 100;
|
|
3
|
+
export declare const META_TOOLS: Set<string>;
|
|
4
|
+
export declare function stripTaggedContent(text: string): string;
|
|
5
|
+
export declare function sanitizeObservationValue(value: unknown): unknown;
|
|
6
|
+
export declare function truncateUtf8Bytes(text: string, maxBytes: number): string;
|
|
7
|
+
export declare function shouldSkipObservationTool(toolName: string): boolean;
|
|
8
|
+
export declare function normalizeToolOutput(output: unknown): string;
|
|
9
|
+
/**
|
|
10
|
+
* Extract text content from message parts.
|
|
11
|
+
* Parts can be TextPart, ToolCallPart, etc. We only want text.
|
|
12
|
+
* Skips synthetic/ignored parts to match what is shown to the user.
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractTextFromParts(parts: any[]): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export declare const POLL_INTERVAL_MS = 5000;
|
|
2
|
+
export declare const OBSERVATION_TYPE_ICONS: Record<string, string>;
|
|
3
|
+
export interface MemSidebarView {
|
|
4
|
+
readonly healthy: boolean;
|
|
5
|
+
readonly project: string;
|
|
6
|
+
readonly observations: number | null;
|
|
7
|
+
readonly sessions: number | null;
|
|
8
|
+
readonly summaries: number | null;
|
|
9
|
+
readonly queueDepth: number | null;
|
|
10
|
+
readonly isProcessing: boolean;
|
|
11
|
+
readonly recentSummaries: readonly {
|
|
12
|
+
id: number;
|
|
13
|
+
request: string;
|
|
14
|
+
}[];
|
|
15
|
+
readonly recentObservations: readonly {
|
|
16
|
+
id: number;
|
|
17
|
+
type: string;
|
|
18
|
+
title: string;
|
|
19
|
+
}[];
|
|
20
|
+
}
|
|
21
|
+
export interface ViewNode {
|
|
22
|
+
readonly kind: 'box' | 'text';
|
|
23
|
+
readonly props: Record<string, unknown>;
|
|
24
|
+
readonly children?: readonly ViewNode[];
|
|
25
|
+
readonly text?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface Theme {
|
|
28
|
+
readonly text: unknown;
|
|
29
|
+
readonly textMuted: unknown;
|
|
30
|
+
readonly info: unknown;
|
|
31
|
+
readonly success: unknown;
|
|
32
|
+
readonly warning: unknown;
|
|
33
|
+
readonly error: unknown;
|
|
34
|
+
readonly borderSubtle: unknown;
|
|
35
|
+
}
|
|
36
|
+
export declare function box(props: Record<string, unknown>, children: readonly ViewNode[]): ViewNode;
|
|
37
|
+
export declare function text(props: Record<string, unknown>, value: string): ViewNode;
|
|
38
|
+
export declare function decodeEntities(value: string): string;
|
|
39
|
+
export declare function truncate(value: string): string;
|
|
40
|
+
export declare function formatCount(value: number | null): string;
|
|
41
|
+
export declare function summaryLine(view: MemSidebarView): {
|
|
42
|
+
label: string;
|
|
43
|
+
tone: 'ok' | 'warn' | 'err';
|
|
44
|
+
};
|
|
45
|
+
export declare function toneColor(tone: 'ok' | 'warn' | 'err', theme: Theme): unknown;
|
|
46
|
+
export declare function bulletRow(icon: string, iconColor: unknown, label: string, theme: Theme): ViewNode;
|
|
47
|
+
export declare function expandedRows(view: MemSidebarView, theme: Theme): ViewNode[];
|
|
48
|
+
export declare function buildMemNodes(view: MemSidebarView, theme: Theme, collapsed: boolean, onToggle: () => void): ViewNode[];
|
|
49
|
+
export declare function viewKey(view: MemSidebarView): string;
|
|
50
|
+
export declare function readMemView(project: string, collapsed: boolean): Promise<MemSidebarView>;
|
|
@@ -7,3 +7,10 @@ export type TuiRegistrationResult = 'added' | 'already-present' | 'no-server-ent
|
|
|
7
7
|
* target instead of being replaced by a regular file.
|
|
8
8
|
*/
|
|
9
9
|
export declare function ensureTuiPluginEntry(): TuiRegistrationResult;
|
|
10
|
+
/**
|
|
11
|
+
* V2 self-heal: register the V2 CLI entry in `~/.config/opencode/cli.json`
|
|
12
|
+
* (the V2 CLI/TUI config file) so the Memory sidebar loads in the V2 TUI
|
|
13
|
+
* without manual configuration. The CLI writes strict JSON (2-space indent),
|
|
14
|
+
* so a comment-bearing file is left untouched ('malformed').
|
|
15
|
+
*/
|
|
16
|
+
export declare function ensureCliPluginEntry(): TuiRegistrationResult;
|
package/dist/tui.d.ts
CHANGED
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
export interface MemSidebarView {
|
|
2
|
-
readonly healthy: boolean;
|
|
3
|
-
readonly project: string;
|
|
4
|
-
readonly observations: number | null;
|
|
5
|
-
readonly sessions: number | null;
|
|
6
|
-
readonly summaries: number | null;
|
|
7
|
-
readonly queueDepth: number | null;
|
|
8
|
-
readonly isProcessing: boolean;
|
|
9
|
-
readonly recentSummaries: readonly {
|
|
10
|
-
id: number;
|
|
11
|
-
request: string;
|
|
12
|
-
}[];
|
|
13
|
-
readonly recentObservations: readonly {
|
|
14
|
-
id: number;
|
|
15
|
-
type: string;
|
|
16
|
-
title: string;
|
|
17
|
-
}[];
|
|
18
|
-
}
|
|
19
|
-
interface ViewNode {
|
|
20
|
-
readonly kind: 'box' | 'text';
|
|
21
|
-
readonly props: Record<string, unknown>;
|
|
22
|
-
readonly children?: readonly ViewNode[];
|
|
23
|
-
readonly text?: string;
|
|
24
|
-
}
|
|
25
|
-
interface Theme {
|
|
26
|
-
readonly text: string;
|
|
27
|
-
readonly textMuted: string;
|
|
28
|
-
readonly info: string;
|
|
29
|
-
readonly success: string;
|
|
30
|
-
readonly warning: string;
|
|
31
|
-
readonly error: string;
|
|
32
|
-
readonly borderSubtle: string;
|
|
33
|
-
}
|
|
34
|
-
export declare function buildMemNodes(view: MemSidebarView, theme: Theme, collapsed: boolean, onToggle: () => void): ViewNode[];
|
|
35
|
-
export declare function viewKey(view: MemSidebarView): string;
|
|
36
|
-
export declare function readMemView(project: string, collapsed: boolean): Promise<MemSidebarView>;
|
|
37
1
|
declare const tuiModule: {
|
|
38
2
|
id: string;
|
|
39
3
|
tui: (api: any) => Promise<void>;
|
package/dist/tui.js
CHANGED
|
@@ -1,12 +1,51 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var __require = import.meta.require;
|
|
3
|
-
|
|
4
2
|
// src/worker-client.ts
|
|
5
3
|
import { existsSync, readFileSync } from "fs";
|
|
6
4
|
import { homedir } from "os";
|
|
7
5
|
import { join } from "path";
|
|
8
6
|
import { spawn } from "child_process";
|
|
7
|
+
|
|
8
|
+
// src/shared.ts
|
|
9
|
+
var MAX_OBSERVATION_BYTES = 24 * 1024;
|
|
10
|
+
var META_TOOLS = new Set([
|
|
11
|
+
"askuserquestion",
|
|
12
|
+
"getmcpresource",
|
|
13
|
+
"listmcpresourcestool",
|
|
14
|
+
"listmcptools",
|
|
15
|
+
"mem-get-observations",
|
|
16
|
+
"mem-search",
|
|
17
|
+
"mem-timeline",
|
|
18
|
+
"skill",
|
|
19
|
+
"slashcommand",
|
|
20
|
+
"todowrite"
|
|
21
|
+
]);
|
|
22
|
+
function stripTaggedContent(text) {
|
|
23
|
+
let result = "";
|
|
24
|
+
let offset = 0;
|
|
25
|
+
const stack = [];
|
|
26
|
+
for (const match of text.matchAll(/<(\/?)(private|claude-mem-context)\b[^>]*>/gi)) {
|
|
27
|
+
if (stack.length === 0) {
|
|
28
|
+
result += text.slice(offset, match.index);
|
|
29
|
+
}
|
|
30
|
+
const name = match[2].toLowerCase();
|
|
31
|
+
if (match[1] === "/") {
|
|
32
|
+
if (stack.at(-1) === name) {
|
|
33
|
+
stack.pop();
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
stack.push(name);
|
|
37
|
+
}
|
|
38
|
+
offset = match.index + match[0].length;
|
|
39
|
+
}
|
|
40
|
+
if (stack.length === 0) {
|
|
41
|
+
result += text.slice(offset);
|
|
42
|
+
}
|
|
43
|
+
return result.trim();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/worker-client.ts
|
|
9
47
|
var HEALTH_TIMEOUT_MS = 1000;
|
|
48
|
+
var WRITE_TIMEOUT_MS = 1e4;
|
|
10
49
|
var AUTOSTART_POLL_INTERVAL_MS = 500;
|
|
11
50
|
var AUTOSTART_POLL_MAX_ATTEMPTS = 16;
|
|
12
51
|
var DEFAULT_WORKER_HOST = "127.0.0.1";
|
|
@@ -92,14 +131,14 @@ function extractTextContent(value) {
|
|
|
92
131
|
return content.trim() || null;
|
|
93
132
|
}
|
|
94
133
|
if (Array.isArray(content)) {
|
|
95
|
-
const
|
|
134
|
+
const text = content.map((part) => {
|
|
96
135
|
if (!isRecord(part) || part["type"] !== "text" || typeof part["text"] !== "string") {
|
|
97
136
|
return "";
|
|
98
137
|
}
|
|
99
138
|
return part["text"];
|
|
100
139
|
}).filter(Boolean).join(`
|
|
101
140
|
`).trim();
|
|
102
|
-
return
|
|
141
|
+
return text || null;
|
|
103
142
|
}
|
|
104
143
|
const text = JSON.stringify(value, null, 2);
|
|
105
144
|
return text === "{}" || text === "null" ? null : text;
|
|
@@ -110,20 +149,17 @@ class WorkerClient {
|
|
|
110
149
|
static autoStartPromise = null;
|
|
111
150
|
static async isHealthy() {
|
|
112
151
|
try {
|
|
113
|
-
const controller = new AbortController;
|
|
114
|
-
const timeoutId = setTimeout(() => controller.abort(), HEALTH_TIMEOUT_MS);
|
|
115
152
|
const response = await fetch(`${this.BASE_URL}/api/health`, {
|
|
116
|
-
signal:
|
|
153
|
+
signal: AbortSignal.timeout(HEALTH_TIMEOUT_MS)
|
|
117
154
|
});
|
|
118
|
-
clearTimeout(timeoutId);
|
|
119
155
|
return response.ok;
|
|
120
156
|
} catch {
|
|
121
157
|
return false;
|
|
122
158
|
}
|
|
123
159
|
}
|
|
124
160
|
static async ensureRunning() {
|
|
125
|
-
|
|
126
|
-
return
|
|
161
|
+
await this.tryAutoStart();
|
|
162
|
+
return this.isHealthy();
|
|
127
163
|
}
|
|
128
164
|
static tryAutoStart() {
|
|
129
165
|
if (!this.autoStartPromise) {
|
|
@@ -191,6 +227,7 @@ class WorkerClient {
|
|
|
191
227
|
try {
|
|
192
228
|
const response = await fetch(`${this.BASE_URL}/api/sessions/init`, {
|
|
193
229
|
method: "POST",
|
|
230
|
+
signal: AbortSignal.timeout(WRITE_TIMEOUT_MS),
|
|
194
231
|
headers: { "Content-Type": "application/json" },
|
|
195
232
|
body: JSON.stringify({
|
|
196
233
|
contentSessionId,
|
|
@@ -202,15 +239,25 @@ class WorkerClient {
|
|
|
202
239
|
if (!response.ok) {
|
|
203
240
|
return null;
|
|
204
241
|
}
|
|
205
|
-
|
|
242
|
+
const value = await response.json();
|
|
243
|
+
if (!isRecord(value) || typeof value.sessionDbId !== "number" || typeof value.promptNumber !== "number" || !Number.isFinite(value.sessionDbId) || !Number.isFinite(value.promptNumber)) {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
sessionDbId: value.sessionDbId,
|
|
248
|
+
promptNumber: value.promptNumber,
|
|
249
|
+
skipped: value.skipped === true,
|
|
250
|
+
reason: typeof value.reason === "string" ? value.reason : undefined
|
|
251
|
+
};
|
|
206
252
|
} catch {
|
|
207
253
|
return null;
|
|
208
254
|
}
|
|
209
255
|
}
|
|
210
|
-
static async sendObservation(contentSessionId, toolName, toolInput, toolResponse, cwd) {
|
|
256
|
+
static async sendObservation(contentSessionId, toolName, toolInput, toolResponse, cwd, toolUseId) {
|
|
211
257
|
try {
|
|
212
|
-
await fetch(`${this.BASE_URL}/api/sessions/observations`, {
|
|
258
|
+
const response = await fetch(`${this.BASE_URL}/api/sessions/observations`, {
|
|
213
259
|
method: "POST",
|
|
260
|
+
signal: AbortSignal.timeout(WRITE_TIMEOUT_MS),
|
|
214
261
|
headers: { "Content-Type": "application/json" },
|
|
215
262
|
body: JSON.stringify({
|
|
216
263
|
contentSessionId,
|
|
@@ -218,37 +265,38 @@ class WorkerClient {
|
|
|
218
265
|
tool_input: toolInput,
|
|
219
266
|
tool_response: toolResponse,
|
|
220
267
|
cwd,
|
|
221
|
-
platformSource: PLATFORM_SOURCE
|
|
268
|
+
platformSource: PLATFORM_SOURCE,
|
|
269
|
+
tool_use_id: toolUseId
|
|
222
270
|
})
|
|
223
271
|
});
|
|
224
|
-
|
|
272
|
+
return response.ok;
|
|
273
|
+
} catch {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
225
276
|
}
|
|
226
|
-
static async summarize(contentSessionId, lastUserMessage, lastAssistantMessage) {
|
|
277
|
+
static async summarize(contentSessionId, lastUserMessage, lastAssistantMessage, metadata = {}) {
|
|
227
278
|
try {
|
|
228
|
-
await fetch(`${this.BASE_URL}/api/sessions/summarize`, {
|
|
279
|
+
const response = await fetch(`${this.BASE_URL}/api/sessions/summarize`, {
|
|
229
280
|
method: "POST",
|
|
281
|
+
signal: AbortSignal.timeout(WRITE_TIMEOUT_MS),
|
|
230
282
|
headers: { "Content-Type": "application/json" },
|
|
231
283
|
body: JSON.stringify({
|
|
232
284
|
contentSessionId,
|
|
233
|
-
last_user_message: lastUserMessage,
|
|
234
|
-
last_assistant_message: lastAssistantMessage,
|
|
235
|
-
platformSource: PLATFORM_SOURCE
|
|
285
|
+
last_user_message: stripTaggedContent(lastUserMessage),
|
|
286
|
+
last_assistant_message: stripTaggedContent(lastAssistantMessage),
|
|
287
|
+
platformSource: PLATFORM_SOURCE,
|
|
288
|
+
observedModel: metadata.observedModel,
|
|
289
|
+
observedBilling: metadata.observedBilling
|
|
236
290
|
})
|
|
237
291
|
});
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
await fetch(`${this.BASE_URL}/api/sessions/complete`, {
|
|
243
|
-
method: "POST",
|
|
244
|
-
headers: { "Content-Type": "application/json" },
|
|
245
|
-
body: JSON.stringify({ contentSessionId, platformSource: PLATFORM_SOURCE })
|
|
246
|
-
});
|
|
247
|
-
} catch {}
|
|
292
|
+
return response.ok;
|
|
293
|
+
} catch {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
248
296
|
}
|
|
249
297
|
static async getContext(project) {
|
|
250
298
|
try {
|
|
251
|
-
const response = await fetch(`${this.BASE_URL}/api/context/inject?project=${encodeURIComponent(project)}
|
|
299
|
+
const response = await fetch(`${this.BASE_URL}/api/context/inject?project=${encodeURIComponent(project)}`, { signal: AbortSignal.timeout(2000) });
|
|
252
300
|
if (!response.ok) {
|
|
253
301
|
return null;
|
|
254
302
|
}
|
|
@@ -399,7 +447,7 @@ class WorkerClient {
|
|
|
399
447
|
}
|
|
400
448
|
}
|
|
401
449
|
|
|
402
|
-
// src/
|
|
450
|
+
// src/sidebar-model.ts
|
|
403
451
|
var POLL_INTERVAL_MS = 5000;
|
|
404
452
|
var LABEL_MAX = 40;
|
|
405
453
|
var RECENT_SUMMARIES = 3;
|
|
@@ -537,6 +585,8 @@ async function readMemView(project, collapsed) {
|
|
|
537
585
|
recentObservations
|
|
538
586
|
};
|
|
539
587
|
}
|
|
588
|
+
|
|
589
|
+
// src/tui.ts
|
|
540
590
|
async function loadSolidCore() {
|
|
541
591
|
try {
|
|
542
592
|
const mod = await import("solid-js");
|
|
@@ -652,8 +702,5 @@ var tuiModule = {
|
|
|
652
702
|
};
|
|
653
703
|
var tui_default = tuiModule;
|
|
654
704
|
export {
|
|
655
|
-
|
|
656
|
-
readMemView,
|
|
657
|
-
tui_default as default,
|
|
658
|
-
buildMemNodes
|
|
705
|
+
tui_default as default
|
|
659
706
|
};
|
package/dist/v2.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode V2 plugin for Claude-Mem.
|
|
3
|
+
*
|
|
4
|
+
* V2 is a breaking API change from V1 — plugins are `Plugin.define({ id,
|
|
5
|
+
* setup })` modules with a server-like context instead of a `{ server }`
|
|
6
|
+
* module of hook handlers. This entrypoint is published under the package's
|
|
7
|
+
* `./v2` export; V1 users keep loading the default export (see src/index.ts).
|
|
8
|
+
* Both entrypoints are thin adapters over the same WorkerClient + shared
|
|
9
|
+
* helpers, so V1 and V2 can coexist and talk to the same Claude-Mem worker.
|
|
10
|
+
*
|
|
11
|
+
* V2 API mapping (vs V1):
|
|
12
|
+
* - `experimental.chat.system.transform` → `ctx.session.hook('context')` (push
|
|
13
|
+
* a SystemPart into `event.system`)
|
|
14
|
+
* - `tool.execute.after` → `ctx.tool.hook('execute.after')`
|
|
15
|
+
* - `tool` definitions → `ctx.tool.transform((tools) => tools.add(...))`
|
|
16
|
+
* - `event` lifecycle → `ctx.event.subscribe()` stream
|
|
17
|
+
* - Assistant text capture uses `session.text.ended` events (the event carries
|
|
18
|
+
* the complete text — no debounced re-fetch needed like V1's message.updated)
|
|
19
|
+
* - Summarization fires on `session.execution.succeeded` (V1's session.idle)
|
|
20
|
+
*/
|
|
21
|
+
declare const _default: import("@opencode-ai/plugin-v2/promise/plugin").Plugin;
|
|
22
|
+
export default _default;
|