claude-mem-opencode 0.0.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 (59) hide show
  1. package/README.md +391 -0
  2. package/dist/bundle/claude-mem-opencode.js +542 -0
  3. package/dist/bundle/index.d.ts +13 -0
  4. package/dist/bundle/index.d.ts.map +1 -0
  5. package/dist/bundle/index.js.map +1 -0
  6. package/dist/bundle/package.json +10 -0
  7. package/dist/bundle/skill/SKILL.md +118 -0
  8. package/dist/bundle/skill/operations/search.md +178 -0
  9. package/dist/bundle/skill/operations/timeline.md +269 -0
  10. package/dist/bundle/skill/operations/workflow.md +375 -0
  11. package/dist/cli.d.ts +6 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +164 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/integration/context-injector.d.ts +19 -0
  16. package/dist/integration/context-injector.d.ts.map +1 -0
  17. package/dist/integration/context-injector.js +47 -0
  18. package/dist/integration/context-injector.js.map +1 -0
  19. package/dist/integration/event-listeners.d.ts +41 -0
  20. package/dist/integration/event-listeners.d.ts.map +1 -0
  21. package/dist/integration/event-listeners.js +156 -0
  22. package/dist/integration/event-listeners.js.map +1 -0
  23. package/dist/integration/index.d.ts +66 -0
  24. package/dist/integration/index.d.ts.map +1 -0
  25. package/dist/integration/index.js +127 -0
  26. package/dist/integration/index.js.map +1 -0
  27. package/dist/integration/session-mapper.d.ts +39 -0
  28. package/dist/integration/session-mapper.d.ts.map +1 -0
  29. package/dist/integration/session-mapper.js +63 -0
  30. package/dist/integration/session-mapper.js.map +1 -0
  31. package/dist/integration/test.d.ts +6 -0
  32. package/dist/integration/test.d.ts.map +1 -0
  33. package/dist/integration/test.js +73 -0
  34. package/dist/integration/test.js.map +1 -0
  35. package/dist/integration/utils/logger.d.ts +15 -0
  36. package/dist/integration/utils/logger.d.ts.map +1 -0
  37. package/dist/integration/utils/logger.js +26 -0
  38. package/dist/integration/utils/logger.js.map +1 -0
  39. package/dist/integration/utils/privacy.d.ts +32 -0
  40. package/dist/integration/utils/privacy.d.ts.map +1 -0
  41. package/dist/integration/utils/privacy.js +62 -0
  42. package/dist/integration/utils/privacy.js.map +1 -0
  43. package/dist/integration/utils/project-name.d.ts +16 -0
  44. package/dist/integration/utils/project-name.d.ts.map +1 -0
  45. package/dist/integration/utils/project-name.js +28 -0
  46. package/dist/integration/utils/project-name.js.map +1 -0
  47. package/dist/integration/version-checker.d.ts +52 -0
  48. package/dist/integration/version-checker.d.ts.map +1 -0
  49. package/dist/integration/version-checker.js +121 -0
  50. package/dist/integration/version-checker.js.map +1 -0
  51. package/dist/integration/worker-client.d.ts +94 -0
  52. package/dist/integration/worker-client.d.ts.map +1 -0
  53. package/dist/integration/worker-client.js +188 -0
  54. package/dist/integration/worker-client.js.map +1 -0
  55. package/dist/test.d.ts +6 -0
  56. package/dist/test.d.ts.map +1 -0
  57. package/dist/test.js +73 -0
  58. package/dist/test.js.map +1 -0
  59. package/package.json +69 -0
@@ -0,0 +1,542 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/integration/worker-client.ts
21
+ class WorkerClient {
22
+ baseUrl;
23
+ timeout = 30000;
24
+ constructor(portOrUrl = 37777) {
25
+ if (typeof portOrUrl === "string") {
26
+ this.baseUrl = portOrUrl;
27
+ } else {
28
+ this.baseUrl = `http://127.0.0.1:${portOrUrl}`;
29
+ }
30
+ }
31
+ getPort() {
32
+ const match = this.baseUrl.match(/:(\d+)$/);
33
+ return match ? parseInt(match[1]) : 37777;
34
+ }
35
+ getWorkerUrl() {
36
+ return this.baseUrl;
37
+ }
38
+ async checkHealth() {
39
+ try {
40
+ const response = await fetch(`${this.baseUrl}/api/health`, {
41
+ signal: AbortSignal.timeout(5000)
42
+ });
43
+ const data = await response.json();
44
+ return data;
45
+ } catch (error) {
46
+ console.log("[WORKER_CLIENT] Health check failed:", error);
47
+ return { status: "error", version: "unknown" };
48
+ }
49
+ }
50
+ async healthCheck() {
51
+ const result = await this.checkHealth();
52
+ return result.status === "ok" || result.status === undefined;
53
+ }
54
+ async waitForReady(timeoutMs = 30000) {
55
+ const start = Date.now();
56
+ while (Date.now() - start < timeoutMs) {
57
+ const ready = await this.readinessCheck();
58
+ if (ready)
59
+ return true;
60
+ await new Promise((resolve) => setTimeout(resolve, 500));
61
+ }
62
+ return false;
63
+ }
64
+ async readinessCheck() {
65
+ try {
66
+ const response = await fetch(`${this.baseUrl}/api/readiness`);
67
+ return response.ok;
68
+ } catch {
69
+ return false;
70
+ }
71
+ }
72
+ async initSession(request) {
73
+ const response = await fetch(`${this.baseUrl}/api/sessions/init`, {
74
+ method: "POST",
75
+ headers: { "Content-Type": "application/json" },
76
+ body: JSON.stringify(request),
77
+ signal: AbortSignal.timeout(this.timeout)
78
+ });
79
+ if (!response.ok) {
80
+ throw new Error(`Session init failed: ${response.status} ${response.statusText}`);
81
+ }
82
+ return response.json();
83
+ }
84
+ async addObservation(request) {
85
+ const response = await fetch(`${this.baseUrl}/api/sessions/observations`, {
86
+ method: "POST",
87
+ headers: { "Content-Type": "application/json" },
88
+ body: JSON.stringify(request),
89
+ signal: AbortSignal.timeout(this.timeout)
90
+ });
91
+ if (!response.ok) {
92
+ throw new Error(`Observation add failed: ${response.status} ${response.statusText}`);
93
+ }
94
+ }
95
+ async completeSession(sessionDbId) {
96
+ const response = await fetch(`${this.baseUrl}/sessions/${sessionDbId}/complete`, {
97
+ method: "POST",
98
+ signal: AbortSignal.timeout(this.timeout)
99
+ });
100
+ if (!response.ok) {
101
+ throw new Error(`Session complete failed: ${response.status} ${response.statusText}`);
102
+ }
103
+ }
104
+ async getProjectContext(project) {
105
+ const url = `${this.baseUrl}/api/context/inject?project=${encodeURIComponent(project)}`;
106
+ const response = await fetch(url, {
107
+ signal: AbortSignal.timeout(this.timeout)
108
+ });
109
+ if (!response.ok) {
110
+ throw new Error(`Context fetch failed: ${response.status} ${response.statusText}`);
111
+ }
112
+ return response.text();
113
+ }
114
+ async search(query, options) {
115
+ const params = new URLSearchParams({
116
+ q: query,
117
+ limit: String(options?.limit ?? 10)
118
+ });
119
+ if (options?.type)
120
+ params.append("type", options.type);
121
+ if (options?.project)
122
+ params.append("project", options.project);
123
+ const response = await fetch(`${this.baseUrl}/api/search?${params}`, {
124
+ signal: AbortSignal.timeout(this.timeout)
125
+ });
126
+ if (!response.ok) {
127
+ throw new Error(`Search failed: ${response.status} ${response.statusText}`);
128
+ }
129
+ return response.json();
130
+ }
131
+ async searchMemories(params) {
132
+ return this.search(params.query, {
133
+ type: params.type,
134
+ limit: params.limit
135
+ });
136
+ }
137
+ async getObservations(ids) {
138
+ const response = await fetch(`${this.baseUrl}/api/observations/batch`, {
139
+ method: "POST",
140
+ headers: { "Content-Type": "application/json" },
141
+ body: JSON.stringify({ ids }),
142
+ signal: AbortSignal.timeout(this.timeout)
143
+ });
144
+ if (!response.ok) {
145
+ throw new Error(`Get observations failed: ${response.status} ${response.statusText}`);
146
+ }
147
+ return response.json();
148
+ }
149
+ async getTimeline(sessionDbId, observationId, window = 5) {
150
+ const response = await fetch(`${this.baseUrl}/api/timeline?session=${sessionDbId}&observation=${observationId}&window=${window}`, {
151
+ signal: AbortSignal.timeout(this.timeout)
152
+ });
153
+ if (!response.ok) {
154
+ throw new Error(`Timeline fetch failed: ${response.status} ${response.statusText}`);
155
+ }
156
+ return response.json();
157
+ }
158
+ }
159
+
160
+ // src/integration/session-mapper.ts
161
+ class SessionMapper {
162
+ mapping = new Map;
163
+ mapOpenCodeToClaudeMem(openCodeSessionId, claudeMemSessionId) {
164
+ this.mapping.set(openCodeSessionId, claudeMemSessionId);
165
+ console.log(`[SESSION_MAPPER] Mapped ${openCodeSessionId} → ${claudeMemSessionId}`);
166
+ }
167
+ getClaudeMemSessionId(openCodeSessionId) {
168
+ return this.mapping.get(openCodeSessionId);
169
+ }
170
+ getOpenCodeSessionId(claudeMemSessionId) {
171
+ for (const [openCodeId, claudeMemId] of this.mapping.entries()) {
172
+ if (claudeMemId === claudeMemSessionId) {
173
+ return openCodeId;
174
+ }
175
+ }
176
+ return;
177
+ }
178
+ unmapSession(openCodeSessionId) {
179
+ this.mapping.delete(openCodeSessionId);
180
+ console.log(`[SESSION_MAPPER] Unmapped ${openCodeSessionId}`);
181
+ }
182
+ getAllMappings() {
183
+ return new Map(this.mapping);
184
+ }
185
+ hasSession(openCodeSessionId) {
186
+ return this.mapping.has(openCodeSessionId);
187
+ }
188
+ size() {
189
+ return this.mapping.size;
190
+ }
191
+ clear() {
192
+ this.mapping.clear();
193
+ console.log("[SESSION_MAPPER] Cleared all mappings");
194
+ }
195
+ }
196
+
197
+ // src/integration/utils/project-name.ts
198
+ import path from "path";
199
+
200
+ class ProjectNameExtractor {
201
+ extract(directory) {
202
+ const baseName = path.basename(directory);
203
+ if (baseName.startsWith(".")) {
204
+ const parent = path.dirname(directory);
205
+ return path.basename(parent);
206
+ }
207
+ return baseName;
208
+ }
209
+ getCurrentProject() {
210
+ return this.extract(process.cwd());
211
+ }
212
+ }
213
+
214
+ // src/integration/utils/privacy.ts
215
+ class PrivacyTagStripper {
216
+ PRIVATE_TAG_REGEX = /<private>[\s\S]*?<\/private>/gi;
217
+ CONTEXT_TAG_REGEX = /<claude-mem-context>[\s\S]*?<\/claude-mem-context>/gi;
218
+ stripFromText(text) {
219
+ if (!text)
220
+ return text;
221
+ return text.replace(this.PRIVATE_TAG_REGEX, "[private content removed]").replace(this.CONTEXT_TAG_REGEX, "[system context removed]");
222
+ }
223
+ stripFromJson(obj) {
224
+ if (typeof obj === "string") {
225
+ return this.stripFromText(obj);
226
+ }
227
+ if (Array.isArray(obj)) {
228
+ return obj.map((item) => this.stripFromJson(item));
229
+ }
230
+ if (obj !== null && typeof obj === "object") {
231
+ const result = {};
232
+ for (const [key, value] of Object.entries(obj)) {
233
+ result[key] = this.stripFromJson(value);
234
+ }
235
+ return result;
236
+ }
237
+ return obj;
238
+ }
239
+ isFullyPrivate(text) {
240
+ const stripped = this.stripFromText(text);
241
+ return stripped.trim().length === 0;
242
+ }
243
+ hasPrivacyTags(text) {
244
+ return this.PRIVATE_TAG_REGEX.test(text) || this.CONTEXT_TAG_REGEX.test(text);
245
+ }
246
+ countPrivacyTags(text) {
247
+ const privateMatches = text.match(this.PRIVATE_TAG_REGEX);
248
+ const contextMatches = text.match(this.CONTEXT_TAG_REGEX);
249
+ return {
250
+ private: privateMatches ? privateMatches.length : 0,
251
+ context: contextMatches ? contextMatches.length : 0
252
+ };
253
+ }
254
+ }
255
+
256
+ // src/integration/event-listeners.ts
257
+ var Bus = null;
258
+ var Session = null;
259
+ var MessageV2 = null;
260
+ try {
261
+ const busModule = await import("@/bus");
262
+ Bus = busModule.Bus;
263
+ const sessionModule = await import("@/session");
264
+ Session = sessionModule.Session;
265
+ MessageV2 = sessionModule.MessageV2;
266
+ } catch (error) {
267
+ console.log("[EVENT_LISTENERS] OpenCode APIs not available - running in standalone mode");
268
+ }
269
+
270
+ class EventListeners {
271
+ workerClient;
272
+ sessionMapper;
273
+ projectNameExtractor;
274
+ privacyStripper;
275
+ promptNumberTracker = new Map;
276
+ constructor(workerClient) {
277
+ this.workerClient = workerClient;
278
+ this.sessionMapper = new SessionMapper;
279
+ this.projectNameExtractor = new ProjectNameExtractor;
280
+ this.privacyStripper = new PrivacyTagStripper;
281
+ }
282
+ async initialize() {
283
+ if (!Bus || !Session || !MessageV2) {
284
+ console.log("[EVENT_LISTENERS] OpenCode APIs not available - event listeners will be initialized via manual calls");
285
+ return;
286
+ }
287
+ console.log("[EVENT_LISTENERS] Initializing OpenCode event listeners...");
288
+ Bus.subscribe(Session.Event.Created, this.handleSessionCreated.bind(this));
289
+ Bus.subscribe(MessageV2.Event.PartUpdated, this.handleMessagePartUpdated.bind(this));
290
+ Bus.subscribe(Session.Event.Updated, this.handleSessionUpdated.bind(this));
291
+ console.log("[EVENT_LISTENERS] Subscribed to OpenCode Bus events");
292
+ }
293
+ async handleSessionCreated(event) {
294
+ const { info } = event.properties;
295
+ const project = this.projectNameExtractor.extract(info.directory);
296
+ const openCodeSessionId = info.id;
297
+ const title = info.title || "New session";
298
+ console.log(`[EVENT_LISTENERS] Session created: ${openCodeSessionId}`);
299
+ try {
300
+ const response = await this.workerClient.initSession({
301
+ contentSessionId: openCodeSessionId,
302
+ project,
303
+ prompt: title
304
+ });
305
+ if (response.skipped) {
306
+ console.log(`[EVENT_LISTENERS] Session marked as private: ${openCodeSessionId}`);
307
+ console.log(`[EVENT_LISTENERS] Reason: ${response.reason}`);
308
+ return;
309
+ }
310
+ this.sessionMapper.mapOpenCodeToClaudeMem(openCodeSessionId, response.sessionDbId);
311
+ this.promptNumberTracker.set(openCodeSessionId, response.promptNumber);
312
+ console.log(`[EVENT_LISTENERS] Mapped ${openCodeSessionId} → ${response.sessionDbId}`);
313
+ console.log(`[EVENT_LISTENERS] Project: ${project}, Prompt #${response.promptNumber}`);
314
+ } catch (error) {
315
+ console.error(`[EVENT_LISTENERS] Failed to initialize session ${openCodeSessionId}:`, error);
316
+ }
317
+ }
318
+ async handleMessagePartUpdated(event) {
319
+ const { part } = event.properties;
320
+ if (part.type !== "tool_call") {
321
+ return;
322
+ }
323
+ const toolName = part.name;
324
+ const toolArgs = part.args;
325
+ const toolResult = part.result || "";
326
+ const sessionId = part.sessionID;
327
+ const cwd = part.cwd || process.cwd();
328
+ const claudeMemSessionId = this.sessionMapper.getClaudeMemSessionId(sessionId);
329
+ if (!claudeMemSessionId) {
330
+ console.log(`[EVENT_LISTENERS] No claude-mem session for: ${sessionId}`);
331
+ return;
332
+ }
333
+ const promptNumber = this.getPromptNumber(sessionId);
334
+ console.log(`[EVENT_LISTENERS] Tool usage: ${sessionId} - ${toolName}`);
335
+ try {
336
+ const strippedArgs = this.privacyStripper.stripFromJson(toolArgs);
337
+ const strippedResult = this.privacyStripper.stripFromText(toolResult);
338
+ await this.workerClient.addObservation({
339
+ sessionDbId: claudeMemSessionId,
340
+ promptNumber,
341
+ toolName,
342
+ toolInput: strippedArgs,
343
+ toolOutput: strippedResult,
344
+ cwd,
345
+ timestamp: Date.now()
346
+ });
347
+ console.log(`[EVENT_LISTENERS] Added observation: ${claudeMemSessionId} - ${toolName}`);
348
+ } catch (error) {
349
+ console.error(`[EVENT_LISTENERS] Failed to add observation:`, error);
350
+ }
351
+ }
352
+ async handleSessionUpdated(event) {
353
+ const { info } = event.properties;
354
+ if (!info.time.archived) {
355
+ return;
356
+ }
357
+ const openCodeSessionId = info.id;
358
+ console.log(`[EVENT_LISTENERS] Session archived: ${openCodeSessionId}`);
359
+ const claudeMemSessionId = this.sessionMapper.getClaudeMemSessionId(openCodeSessionId);
360
+ if (!claudeMemSessionId) {
361
+ console.log(`[EVENT_LISTENERS] No claude-mem session for: ${openCodeSessionId}`);
362
+ return;
363
+ }
364
+ try {
365
+ await this.workerClient.completeSession(claudeMemSessionId);
366
+ console.log(`[EVENT_LISTENERS] Completed session: ${claudeMemSessionId}`);
367
+ this.sessionMapper.unmapSession(openCodeSessionId);
368
+ this.promptNumberTracker.delete(openCodeSessionId);
369
+ } catch (error) {
370
+ console.error(`[EVENT_LISTENERS] Failed to complete session:`, error);
371
+ }
372
+ }
373
+ getPromptNumber(sessionId) {
374
+ return this.promptNumberTracker.get(sessionId) ?? 1;
375
+ }
376
+ incrementPromptNumber(sessionId) {
377
+ const current = this.promptNumberTracker.get(sessionId) ?? 1;
378
+ this.promptNumberTracker.set(sessionId, current + 1);
379
+ }
380
+ }
381
+
382
+ // src/integration/context-injector.ts
383
+ class ContextInjector {
384
+ workerClient;
385
+ projectNameExtractor;
386
+ constructor(workerClient) {
387
+ this.workerClient = workerClient;
388
+ this.projectNameExtractor = new ProjectNameExtractor;
389
+ }
390
+ async injectContext(project) {
391
+ try {
392
+ const context = await this.workerClient.getProjectContext(project);
393
+ if (!context || !context.trim()) {
394
+ console.log(`[CONTEXT_INJECTOR] No memory context available for project: ${project}`);
395
+ return "";
396
+ }
397
+ console.log(`[CONTEXT_INJECTOR] Injected memory context for project: ${project} (${context.length} chars)`);
398
+ return context;
399
+ } catch (error) {
400
+ console.warn(`[CONTEXT_INJECTOR] Failed to inject memory context for project: ${project}`, error);
401
+ return "";
402
+ }
403
+ }
404
+ async getSystemPromptAddition(project) {
405
+ const context = await this.injectContext(project);
406
+ if (!context)
407
+ return "";
408
+ return `
409
+ ## Relevant Context from Past Sessions
410
+
411
+ ${context}
412
+
413
+ ---
414
+ `;
415
+ }
416
+ }
417
+
418
+ // src/integration/utils/logger.ts
419
+ var LogLevel;
420
+ ((LogLevel2) => {
421
+ LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
422
+ LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
423
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
424
+ LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
425
+ })(LogLevel ||= {});
426
+
427
+ class Logger {
428
+ context;
429
+ constructor(context) {
430
+ this.context = context;
431
+ }
432
+ debug(message, ...args) {
433
+ console.log(`[${this.context}] [DEBUG] ${message}`, ...args);
434
+ }
435
+ info(message, ...args) {
436
+ console.log(`[${this.context}] [INFO] ${message}`, ...args);
437
+ }
438
+ warn(message, ...args) {
439
+ console.warn(`[${this.context}] [WARN] ${message}`, ...args);
440
+ }
441
+ error(message, ...args) {
442
+ console.error(`[${this.context}] [ERROR] ${message}`, ...args);
443
+ }
444
+ }
445
+
446
+ // src/integration/index.ts
447
+ class ClaudeMemIntegration {
448
+ workerClient;
449
+ eventListeners;
450
+ contextInjector;
451
+ projectNameExtractor;
452
+ logger;
453
+ initialized = false;
454
+ memoryAvailable = false;
455
+ constructor(workerUrl = "http://localhost:37777") {
456
+ this.workerClient = new WorkerClient(workerUrl.includes("localhost") ? parseInt(workerUrl.split(":")[1] || "37777") : 37777);
457
+ this.eventListeners = new EventListeners(this.workerClient);
458
+ this.contextInjector = new ContextInjector(this.workerClient);
459
+ this.projectNameExtractor = new ProjectNameExtractor;
460
+ this.logger = new Logger("CLAUDE_MEM");
461
+ }
462
+ async initialize() {
463
+ if (this.initialized) {
464
+ console.log("[CLAUDE_MEM] Integration already initialized");
465
+ return;
466
+ }
467
+ try {
468
+ console.log("[CLAUDE_MEM] Initializing claude-mem integration...");
469
+ console.log(`[CLAUDE_MEM] Worker port: ${this.workerClient.getPort() || "37777"}`);
470
+ const ready = await this.workerClient.waitForReady(30000);
471
+ if (!ready) {
472
+ throw new Error("Worker service not ready after 30s. Is worker running?");
473
+ }
474
+ console.log("[CLAUDE_MEM] Worker service is ready");
475
+ await this.eventListeners.initialize();
476
+ this.initialized = true;
477
+ this.memoryAvailable = true;
478
+ console.log("[CLAUDE_MEM] Integration initialized successfully");
479
+ console.log("[CLAUDE_MEM] Project:", this.projectNameExtractor.getCurrentProject());
480
+ } catch (error) {
481
+ console.error("[CLAUDE_MEM] Initialization failed:", error);
482
+ console.warn("[CLAUDE_MEM] Continuing anyway, but expect potential issues");
483
+ this.memoryAvailable = false;
484
+ }
485
+ }
486
+ async getStatus() {
487
+ const workerReady = this.memoryAvailable && await this.workerClient.healthCheck();
488
+ return {
489
+ initialized: this.initialized,
490
+ workerReady,
491
+ currentProject: this.projectNameExtractor.getCurrentProject(),
492
+ workerUrl: `http://localhost:${this.workerClient.getPort() || "37777"}`
493
+ };
494
+ }
495
+ async getProjectContext(project) {
496
+ if (!this.memoryAvailable) {
497
+ this.logger.warn("Memory features are not available");
498
+ return null;
499
+ }
500
+ const projectToUse = project || this.projectNameExtractor.getCurrentProject();
501
+ return this.contextInjector.injectContext(projectToUse);
502
+ }
503
+ async searchMemory(query, options) {
504
+ if (!this.memoryAvailable) {
505
+ this.logger.warn("Memory features are not available");
506
+ throw new Error("Memory features not available");
507
+ }
508
+ return this.workerClient.search(query, options);
509
+ }
510
+ async shutdown() {
511
+ this.logger.info("Shutting down integration");
512
+ this.initialized = false;
513
+ this.memoryAvailable = false;
514
+ }
515
+ getWorkerClient() {
516
+ return this.workerClient;
517
+ }
518
+ getEventListeners() {
519
+ return this.eventListeners;
520
+ }
521
+ getContextInjector() {
522
+ return this.contextInjector;
523
+ }
524
+ isMemoryAvailable() {
525
+ return this.memoryAvailable;
526
+ }
527
+ }
528
+ var defaultInstance = new ClaudeMemIntegration;
529
+ var integration_default = ClaudeMemIntegration;
530
+ export {
531
+ defaultInstance,
532
+ integration_default as default,
533
+ WorkerClient,
534
+ SessionMapper,
535
+ ProjectNameExtractor,
536
+ PrivacyTagStripper,
537
+ Logger,
538
+ LogLevel,
539
+ EventListeners,
540
+ ContextInjector,
541
+ ClaudeMemIntegration
542
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Bundle entry point for OpenCode
3
+ * This file is bundled with all dependencies
4
+ */
5
+ export { default, ClaudeMemIntegration, defaultInstance } from '../integration/index.js';
6
+ export { WorkerClient } from '../integration/worker-client.js';
7
+ export { EventListeners } from '../integration/event-listeners.js';
8
+ export { ContextInjector } from '../integration/context-injector.js';
9
+ export { Logger, LogLevel } from '../integration/utils/logger.js';
10
+ export { ProjectNameExtractor } from '../integration/utils/project-name.js';
11
+ export { PrivacyTagStripper } from '../integration/utils/privacy.js';
12
+ export { SessionMapper } from '../integration/session-mapper.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bundle/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACpE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bundle/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACpE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA"}
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "claude-mem-opencode-bundle",
3
+ "version": "0.0.1",
4
+ "description": "OpenCode integration for claude-mem (bundled)",
5
+ "main": "./claude-mem-opencode.js",
6
+ "files": [
7
+ "claude-mem-opencode.js",
8
+ "skill/"
9
+ ]
10
+ }
@@ -0,0 +1,118 @@
1
+ # opencode-mem Memory Search
2
+
3
+ Automatically search your coding history using natural language queries.
4
+
5
+ ## Description
6
+
7
+ The opencode-mem memory search skill helps you find relevant information from your past coding sessions. It searches compressed memories stored by claude-mem and returns relevant context.
8
+
9
+ ## Capabilities
10
+
11
+ - **Natural Language Search**: Search using plain English queries
12
+ - **Type-Based Filtering**: Filter by tool type (bash, code, file, web, grep)
13
+ - **Context Retrieval**: Get compressed context for your project
14
+ - **Token Efficiency**: ~10x more efficient than storing full outputs
15
+
16
+ ## Usage
17
+
18
+ ### Basic Search
19
+
20
+ Simply ask a question about your past work:
21
+
22
+ - "What did we do yesterday?"
23
+ - "Show me all bash commands we used"
24
+ - "What files did we modify for the login feature?"
25
+ - "Find code related to authentication"
26
+
27
+ The skill will automatically search your memories and return relevant results.
28
+
29
+ ### Type Filtering
30
+
31
+ You can filter results by tool type:
32
+
33
+ - "Show me only bash commands"
34
+ - "What file operations did we do?"
35
+ - "Find web fetches related to API"
36
+ - "Show code-related observations"
37
+
38
+ ### Timeline Context
39
+
40
+ Get context from a specific timeframe:
41
+
42
+ - "Give me context from the last session"
43
+ - "What was the context before we added OAuth?"
44
+ - "Show me the last 3 sessions about authentication"
45
+
46
+ ## Examples
47
+
48
+ ### Searching for Feature Work
49
+
50
+ **User**: "What did we do for the authentication feature?"
51
+
52
+ **Skill**: Searches memories for "authentication", returns:
53
+ - Created AuthContext.ts
54
+ - Added login route to router
55
+ - Implemented JWT token validation
56
+ - Updated user model with password hashing
57
+
58
+ ### Finding Commands
59
+
60
+ **User**: "How did we set up the database?"
61
+
62
+ **Skill**: Searches for "database setup", returns bash commands:
63
+ - `npm install prisma @prisma/client`
64
+ - `npx prisma init`
65
+ - `npx prisma migrate dev`
66
+ - `npm install pg`
67
+
68
+ ### Context Retrieval
69
+
70
+ **User**: "What's the context for this project?"
71
+
72
+ **Skill**: Gets project context, returns compressed memories from current project.
73
+
74
+ ## How It Works
75
+
76
+ 1. You ask a question
77
+ 2. Skill analyzes the query
78
+ 3. Searches compressed memories via claude-mem API
79
+ 4. Returns relevant observations (tool usage, files modified, etc.)
80
+ 5. Provides ~10x token efficiency vs. full context
81
+
82
+ ## Prerequisites
83
+
84
+ - opencode-mem must be installed
85
+ - claude-mem worker must be running
86
+ - Memories must have been captured in previous sessions
87
+
88
+ ## Error Handling
89
+
90
+ If the skill encounters errors:
91
+
92
+ - **Worker not available**: "Memory features are not available - start claude-mem worker"
93
+ - **No memories found**: "No memories match your search query"
94
+ - **Invalid query**: "Please provide a search query"
95
+
96
+ ## Best Practices
97
+
98
+ 1. **Be specific**: "authentication API" vs "stuff about auth"
99
+ 2. **Use project context**: "In the user service, what did we do?"
100
+ 3. **Filter by type**: "Show me bash commands for deployment"
101
+ 4. **Check context first**: "What's the current project context?"
102
+
103
+ ## Integration
104
+
105
+ The skill is automatically invoked when:
106
+ - You ask questions about past work
107
+ - You search for specific features or implementations
108
+ - You request context about a project
109
+
110
+ ## Version
111
+
112
+ opencode-mem v1.0.0
113
+
114
+ ## See Also
115
+
116
+ - [Search Operation](./operations/search.md) - Detailed search operations
117
+ - [Timeline Operation](./operations/timeline.md) - Timeline context operations
118
+ - [Workflow Operation](./operations/workflow.md) - 3-layer workflow pattern