opencode-supermemory 2.0.1 → 2.0.2
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 +39 -9
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.js +78 -27
- package/dist/services/client.d.ts +4 -1
- package/dist/services/client.d.ts.map +1 -1
- package/dist/services/tags.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -199,28 +199,34 @@ Create `~/.config/opencode/supermemory.jsonc`:
|
|
|
199
199
|
{
|
|
200
200
|
// API key (can also use SUPERMEMORY_API_KEY env var)
|
|
201
201
|
"apiKey": "sm_...",
|
|
202
|
-
|
|
202
|
+
|
|
203
203
|
// Min similarity for memory retrieval (0-1)
|
|
204
204
|
"similarityThreshold": 0.6,
|
|
205
|
-
|
|
205
|
+
|
|
206
206
|
// Max memories injected per request
|
|
207
207
|
"maxMemories": 5,
|
|
208
|
-
|
|
208
|
+
|
|
209
209
|
// Max project memories listed
|
|
210
210
|
"maxProjectMemories": 10,
|
|
211
|
-
|
|
211
|
+
|
|
212
212
|
// Max profile facts injected
|
|
213
213
|
"maxProfileItems": 5,
|
|
214
|
-
|
|
214
|
+
|
|
215
215
|
// Include user profile in context
|
|
216
216
|
"injectProfile": true,
|
|
217
|
-
|
|
218
|
-
// Prefix for container tags
|
|
217
|
+
|
|
218
|
+
// Prefix for container tags (used when userContainerTag/projectContainerTag not set)
|
|
219
219
|
"containerTagPrefix": "opencode",
|
|
220
|
-
|
|
220
|
+
|
|
221
|
+
// Optional: Set exact user container tag (overrides auto-generated tag)
|
|
222
|
+
"userContainerTag": "my-custom-user-tag",
|
|
223
|
+
|
|
224
|
+
// Optional: Set exact project container tag (overrides auto-generated tag)
|
|
225
|
+
"projectContainerTag": "my-project-tag",
|
|
226
|
+
|
|
221
227
|
// Extra keyword patterns for memory detection (regex)
|
|
222
228
|
"keywordPatterns": ["log\\s+this", "write\\s+down"],
|
|
223
|
-
|
|
229
|
+
|
|
224
230
|
// Context usage ratio that triggers compaction (0-1)
|
|
225
231
|
"compactionThreshold": 0.80
|
|
226
232
|
}
|
|
@@ -228,6 +234,30 @@ Create `~/.config/opencode/supermemory.jsonc`:
|
|
|
228
234
|
|
|
229
235
|
All fields optional. Env var `SUPERMEMORY_API_KEY` takes precedence over config file.
|
|
230
236
|
|
|
237
|
+
### Container Tag Selection
|
|
238
|
+
|
|
239
|
+
By default, container tags are auto-generated using `containerTagPrefix` plus a hash:
|
|
240
|
+
- User tag: `{prefix}_user_{hash(git_email)}`
|
|
241
|
+
- Project tag: `{prefix}_project_{hash(directory)}`
|
|
242
|
+
|
|
243
|
+
You can override this by specifying exact container tags:
|
|
244
|
+
|
|
245
|
+
```jsonc
|
|
246
|
+
{
|
|
247
|
+
// Use a specific container tag for user memories
|
|
248
|
+
"userContainerTag": "my-team-workspace",
|
|
249
|
+
|
|
250
|
+
// Use a specific container tag for project memories
|
|
251
|
+
"projectContainerTag": "my-awesome-project"
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
This is useful when you want to:
|
|
256
|
+
- Share memories across team members (same `userContainerTag`)
|
|
257
|
+
- Sync memories between different machines for the same project
|
|
258
|
+
- Organize memories using your own naming scheme
|
|
259
|
+
- Integrate with existing Supermemory container tags from other tools
|
|
260
|
+
|
|
231
261
|
## Usage with Oh My OpenCode
|
|
232
262
|
|
|
233
263
|
If you're using [Oh My OpenCode](https://github.com/code-yeongyu/oh-my-opencode), disable its built-in auto-compact hook to let supermemory handle context compaction:
|
package/dist/config.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare const CONFIG: {
|
|
|
6
6
|
maxProfileItems: number;
|
|
7
7
|
injectProfile: boolean;
|
|
8
8
|
containerTagPrefix: string;
|
|
9
|
+
userContainerTag: string | undefined;
|
|
10
|
+
projectContainerTag: string | undefined;
|
|
9
11
|
filterPrompt: string;
|
|
10
12
|
keywordPatterns: string[];
|
|
11
13
|
compactionThreshold: number;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAmGA,eAAO,MAAM,mBAAmB,oBAAc,CAAC;AAE/C,eAAO,MAAM,MAAM;;;;;;;;;;;;CAelB,CAAC;AAEF,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
|
package/dist/index.js
CHANGED
|
@@ -13773,6 +13773,8 @@ var CONFIG = {
|
|
|
13773
13773
|
maxProfileItems: fileConfig.maxProfileItems ?? DEFAULTS.maxProfileItems,
|
|
13774
13774
|
injectProfile: fileConfig.injectProfile ?? DEFAULTS.injectProfile,
|
|
13775
13775
|
containerTagPrefix: fileConfig.containerTagPrefix ?? DEFAULTS.containerTagPrefix,
|
|
13776
|
+
userContainerTag: fileConfig.userContainerTag,
|
|
13777
|
+
projectContainerTag: fileConfig.projectContainerTag,
|
|
13776
13778
|
filterPrompt: fileConfig.filterPrompt ?? DEFAULTS.filterPrompt,
|
|
13777
13779
|
keywordPatterns: [
|
|
13778
13780
|
...DEFAULT_KEYWORD_PATTERNS,
|
|
@@ -13801,8 +13803,8 @@ function log(message, data) {
|
|
|
13801
13803
|
}
|
|
13802
13804
|
|
|
13803
13805
|
// src/services/client.ts
|
|
13804
|
-
var SUPERMEMORY_API_URL = "https://api.supermemory.ai";
|
|
13805
13806
|
var TIMEOUT_MS = 30000;
|
|
13807
|
+
var MAX_CONVERSATION_CHARS = 1e5;
|
|
13806
13808
|
function withTimeout(promise2, ms) {
|
|
13807
13809
|
return Promise.race([
|
|
13808
13810
|
promise2,
|
|
@@ -13812,6 +13814,19 @@ function withTimeout(promise2, ms) {
|
|
|
13812
13814
|
|
|
13813
13815
|
class SupermemoryClient {
|
|
13814
13816
|
client = null;
|
|
13817
|
+
formatConversationMessage(message) {
|
|
13818
|
+
const content = typeof message.content === "string" ? message.content : message.content.map((part) => part.type === "text" ? part.text : `[image] ${part.imageUrl.url}`).join(`
|
|
13819
|
+
`);
|
|
13820
|
+
const trimmed = content.trim();
|
|
13821
|
+
if (trimmed.length === 0) {
|
|
13822
|
+
return `[${message.role}]`;
|
|
13823
|
+
}
|
|
13824
|
+
return `[${message.role}] ${trimmed}`;
|
|
13825
|
+
}
|
|
13826
|
+
formatConversationTranscript(messages) {
|
|
13827
|
+
return messages.map((message, idx) => `${idx + 1}. ${this.formatConversationMessage(message)}`).join(`
|
|
13828
|
+
`);
|
|
13829
|
+
}
|
|
13815
13830
|
getClient() {
|
|
13816
13831
|
if (!this.client) {
|
|
13817
13832
|
if (!isConfigured()) {
|
|
@@ -13904,34 +13919,64 @@ class SupermemoryClient {
|
|
|
13904
13919
|
}
|
|
13905
13920
|
}
|
|
13906
13921
|
async ingestConversation(conversationId, messages, containerTags, metadata) {
|
|
13907
|
-
log("ingestConversation: start", {
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13922
|
+
log("ingestConversation: start", {
|
|
13923
|
+
conversationId,
|
|
13924
|
+
messageCount: messages.length,
|
|
13925
|
+
containerTags
|
|
13926
|
+
});
|
|
13927
|
+
if (messages.length === 0) {
|
|
13928
|
+
return { success: false, error: "No messages to ingest" };
|
|
13929
|
+
}
|
|
13930
|
+
const uniqueTags = [...new Set(containerTags)].filter((tag) => tag.length > 0);
|
|
13931
|
+
if (uniqueTags.length === 0) {
|
|
13932
|
+
return { success: false, error: "At least one containerTag is required" };
|
|
13933
|
+
}
|
|
13934
|
+
const transcript = this.formatConversationTranscript(messages);
|
|
13935
|
+
const rawContent = `[Conversation ${conversationId}]
|
|
13936
|
+
${transcript}`;
|
|
13937
|
+
const content = rawContent.length > MAX_CONVERSATION_CHARS ? `${rawContent.slice(0, MAX_CONVERSATION_CHARS)}
|
|
13938
|
+
...[truncated]` : rawContent;
|
|
13939
|
+
const ingestMetadata = {
|
|
13940
|
+
type: "conversation",
|
|
13941
|
+
conversationId,
|
|
13942
|
+
messageCount: messages.length,
|
|
13943
|
+
originalContainerTags: uniqueTags,
|
|
13944
|
+
...metadata
|
|
13945
|
+
};
|
|
13946
|
+
const savedIds = [];
|
|
13947
|
+
let firstError = null;
|
|
13948
|
+
for (const tag of uniqueTags) {
|
|
13949
|
+
const result = await this.addMemory(content, tag, ingestMetadata);
|
|
13950
|
+
if (result.success) {
|
|
13951
|
+
savedIds.push(result.id);
|
|
13952
|
+
} else if (!firstError) {
|
|
13953
|
+
firstError = result.error || "Failed to store conversation";
|
|
13926
13954
|
}
|
|
13927
|
-
const result = await response.json();
|
|
13928
|
-
log("ingestConversation: success", { conversationId, status: result.status });
|
|
13929
|
-
return { success: true, ...result };
|
|
13930
|
-
} catch (error45) {
|
|
13931
|
-
const errorMessage = error45 instanceof Error ? error45.message : String(error45);
|
|
13932
|
-
log("ingestConversation: error", { error: errorMessage });
|
|
13933
|
-
return { success: false, error: errorMessage };
|
|
13934
13955
|
}
|
|
13956
|
+
if (savedIds.length === 0) {
|
|
13957
|
+
log("ingestConversation: error", { conversationId, error: firstError });
|
|
13958
|
+
return {
|
|
13959
|
+
success: false,
|
|
13960
|
+
error: firstError || "Failed to ingest conversation"
|
|
13961
|
+
};
|
|
13962
|
+
}
|
|
13963
|
+
const status = savedIds.length === uniqueTags.length ? "stored" : "partial";
|
|
13964
|
+
const response = {
|
|
13965
|
+
id: savedIds[0],
|
|
13966
|
+
conversationId,
|
|
13967
|
+
status
|
|
13968
|
+
};
|
|
13969
|
+
log("ingestConversation: success", {
|
|
13970
|
+
conversationId,
|
|
13971
|
+
status,
|
|
13972
|
+
storedCount: savedIds.length,
|
|
13973
|
+
requestedCount: uniqueTags.length
|
|
13974
|
+
});
|
|
13975
|
+
return {
|
|
13976
|
+
success: true,
|
|
13977
|
+
...response,
|
|
13978
|
+
storedMemoryIds: savedIds
|
|
13979
|
+
};
|
|
13935
13980
|
}
|
|
13936
13981
|
}
|
|
13937
13982
|
var supermemoryClient = new SupermemoryClient;
|
|
@@ -13998,6 +14043,9 @@ function getGitEmail() {
|
|
|
13998
14043
|
}
|
|
13999
14044
|
}
|
|
14000
14045
|
function getUserTag() {
|
|
14046
|
+
if (CONFIG.userContainerTag) {
|
|
14047
|
+
return CONFIG.userContainerTag;
|
|
14048
|
+
}
|
|
14001
14049
|
const email3 = getGitEmail();
|
|
14002
14050
|
if (email3) {
|
|
14003
14051
|
return `${CONFIG.containerTagPrefix}_user_${sha256(email3)}`;
|
|
@@ -14006,6 +14054,9 @@ function getUserTag() {
|
|
|
14006
14054
|
return `${CONFIG.containerTagPrefix}_user_${sha256(fallback)}`;
|
|
14007
14055
|
}
|
|
14008
14056
|
function getProjectTag(directory) {
|
|
14057
|
+
if (CONFIG.projectContainerTag) {
|
|
14058
|
+
return CONFIG.projectContainerTag;
|
|
14059
|
+
}
|
|
14009
14060
|
return `${CONFIG.containerTagPrefix}_project_${sha256(directory)}`;
|
|
14010
14061
|
}
|
|
14011
14062
|
function getTags(directory) {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import Supermemory from "supermemory";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ConversationMessage, MemoryType } from "../types/index.js";
|
|
3
3
|
export declare class SupermemoryClient {
|
|
4
4
|
private client;
|
|
5
|
+
private formatConversationMessage;
|
|
6
|
+
private formatConversationTranscript;
|
|
5
7
|
private getClient;
|
|
6
8
|
searchMemories(query: string, containerTag: string): Promise<{
|
|
7
9
|
results: Array<Supermemory.Search.SearchMemoriesResponse.Result>;
|
|
@@ -65,6 +67,7 @@ export declare class SupermemoryClient {
|
|
|
65
67
|
success: false;
|
|
66
68
|
error: string;
|
|
67
69
|
} | {
|
|
70
|
+
storedMemoryIds: string[];
|
|
68
71
|
id: string;
|
|
69
72
|
conversationId: string;
|
|
70
73
|
status: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/services/client.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,aAAa,CAAC;AAGtC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/services/client.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,aAAa,CAAC;AAGtC,OAAO,KAAK,EAEV,mBAAmB,EACnB,UAAU,EACX,MAAM,mBAAmB,CAAC;AAc3B,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAA4B;IAE1C,OAAO,CAAC,yBAAyB;IAmBjC,OAAO,CAAC,4BAA4B;IAMpC,OAAO,CAAC,SAAS;IAcX,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;;;;;;;;;;;;;IAsBlD,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;;;;;;;;;;IAmB/C,SAAS,CACb,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,UAAU,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE;;;;;;;;;IAqBnE,YAAY,CAAC,QAAQ,EAAE,MAAM;;;;;;;IAgB7B,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,SAAK;;;;;;;;;;;;;;;IAqB7C,kBAAkB,CACtB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,aAAa,EAAE,MAAM,EAAE,EACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;;;;;;;;;;;CA0EvD;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/services/tags.ts"],"names":[],"mappings":"AAQA,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAO3C;AAED,wBAAgB,UAAU,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/services/tags.ts"],"names":[],"mappings":"AAQA,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAO3C;AAED,wBAAgB,UAAU,IAAI,MAAM,CAanC;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAK5E"}
|