memory-search-plugin 0.10.0 → 1.2.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/gateway-client.ts +45 -64
- package/identity.ts +28 -88
- package/index.js +135 -268
- package/index.ts +149 -319
- package/openclaw.plugin.json +13 -16
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,101 +1,57 @@
|
|
|
1
|
-
// index.ts
|
|
2
1
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
3
2
|
|
|
4
|
-
// gateway-client.ts
|
|
5
|
-
function createGatewayClient(config) {
|
|
6
|
-
const baseUrl = config.gatewayUrl.replace(/\/+$/, "");
|
|
7
|
-
const token = config.gatewayToken || "";
|
|
8
|
-
const authHeaders = token ? { Authorization: `Bearer ${token}` } : {};
|
|
9
|
-
return {
|
|
10
|
-
async callGatewaySearch(options) {
|
|
11
|
-
const url = `${baseUrl}/api/memory/search`;
|
|
12
|
-
const response = await fetch(url, {
|
|
13
|
-
method: "POST",
|
|
14
|
-
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
15
|
-
body: JSON.stringify(options)
|
|
16
|
-
});
|
|
17
|
-
if (!response.ok) {
|
|
18
|
-
const errorBody = await response.text().catch(() => "");
|
|
19
|
-
throw new Error(
|
|
20
|
-
`Gateway search failed: ${response.status} ${response.statusText} ${errorBody}`
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
return response.json();
|
|
24
|
-
},
|
|
25
|
-
async callGatewayGet(options) {
|
|
26
|
-
const url = `${baseUrl}/api/memory/get`;
|
|
27
|
-
const response = await fetch(url, {
|
|
28
|
-
method: "POST",
|
|
29
|
-
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
30
|
-
body: JSON.stringify(options)
|
|
31
|
-
});
|
|
32
|
-
if (!response.ok) {
|
|
33
|
-
const errorBody = await response.text().catch(() => "");
|
|
34
|
-
throw new Error(
|
|
35
|
-
`Gateway get failed: ${response.status} ${response.statusText} ${errorBody}`
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
return response.json();
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
3
|
// identity.ts
|
|
44
|
-
function
|
|
4
|
+
function resolveIdentity(params) {
|
|
45
5
|
const testScene = process.env.MEMORY_GATEWAY_TEST_SCENE;
|
|
46
6
|
if (testScene) {
|
|
47
|
-
|
|
7
|
+
return {
|
|
48
8
|
scene: testScene,
|
|
49
|
-
|
|
9
|
+
sender_id: process.env.MEMORY_GATEWAY_TEST_USER_ID || "test_user",
|
|
10
|
+
owner_id: process.env.MEMORY_GATEWAY_TEST_OWNER_ID || "test_owner",
|
|
50
11
|
group_id: process.env.MEMORY_GATEWAY_TEST_GROUP_ID || null
|
|
51
12
|
};
|
|
52
|
-
console.log("[memory-search-plugin] TEST MODE identity:", JSON.stringify(result));
|
|
53
|
-
return result;
|
|
54
13
|
}
|
|
55
|
-
const
|
|
14
|
+
const senderId = params.sender_id?.trim() || "unknown";
|
|
15
|
+
const ownerId = params.owner_id?.trim() || "";
|
|
56
16
|
const convType = (params.conversation_type || "direct").trim().toLowerCase();
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
};
|
|
17
|
+
const groupId = params.group_id?.trim() || null;
|
|
18
|
+
if (!ownerId) {
|
|
19
|
+
console.warn(
|
|
20
|
+
"[identity] owner_id is empty — LLM failed to extract from UntrustedContext. owner queries will be skipped to prevent cross-user leak."
|
|
21
|
+
);
|
|
63
22
|
}
|
|
64
|
-
if (
|
|
65
|
-
|
|
23
|
+
if (convType === "group") {
|
|
24
|
+
if (!groupId) {
|
|
25
|
+
console.warn("[identity] group scene but group_id is empty");
|
|
26
|
+
}
|
|
27
|
+
return { scene: "group", sender_id: senderId, owner_id: ownerId, group_id: groupId };
|
|
66
28
|
}
|
|
67
|
-
return { scene: "
|
|
29
|
+
return { scene: "owner", sender_id: senderId, owner_id: ownerId, group_id: null };
|
|
68
30
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
|
|
31
|
+
|
|
32
|
+
// gateway-client.ts
|
|
33
|
+
function createGatewayClient(config) {
|
|
34
|
+
const baseUrl = config.gatewayUrl.replace(/\/+$/, "");
|
|
35
|
+
const headers = {
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
...config.gatewayToken ? { Authorization: `Bearer ${config.gatewayToken}` } : {}
|
|
38
|
+
};
|
|
39
|
+
async function post(path, body) {
|
|
40
|
+
const resp = await fetch(`${baseUrl}${path}`, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers,
|
|
43
|
+
body: JSON.stringify(body)
|
|
44
|
+
});
|
|
45
|
+
if (!resp.ok) {
|
|
46
|
+
const text = await resp.text().catch(() => "");
|
|
47
|
+
throw new Error(`Gateway ${path} failed: ${resp.status} ${text}`);
|
|
85
48
|
}
|
|
86
|
-
return
|
|
49
|
+
return resp.json();
|
|
87
50
|
}
|
|
88
|
-
return {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (!token) return false;
|
|
93
|
-
const ownerUserId = token.split("-").pop() || "";
|
|
94
|
-
return ownerUserId !== "" && ownerUserId === userId;
|
|
95
|
-
}
|
|
96
|
-
function extractAgentId(sessionKey) {
|
|
97
|
-
const parts = (sessionKey || "").split(":");
|
|
98
|
-
return parts.length >= 2 ? parts[1] : "main";
|
|
51
|
+
return {
|
|
52
|
+
callGatewaySearch: (opts) => post("/api/memory/search", opts),
|
|
53
|
+
callGatewayGet: (opts) => post("/api/memory/get", opts)
|
|
54
|
+
};
|
|
99
55
|
}
|
|
100
56
|
|
|
101
57
|
// index.ts
|
|
@@ -103,90 +59,58 @@ var buildPromptSection = ({
|
|
|
103
59
|
availableTools,
|
|
104
60
|
citationsMode
|
|
105
61
|
}) => {
|
|
106
|
-
const
|
|
107
|
-
const
|
|
108
|
-
if (!
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
const lines = ["## Memory Recall", toolGuidance];
|
|
118
|
-
lines.push(
|
|
119
|
-
"**Context extraction:** When calling memory_search or memory_get, you MUST fill in the agent_id, sender_id, conversation_type, and group_id parameters by extracting them from the UntrustedContext section in this conversation. Look for lines like `agent_id: xxx`, `sender_id: xxx`, `conversation_type: xxx`, `group_id: xxx`. If a field is not present, omit it."
|
|
120
|
-
);
|
|
121
|
-
if (citationsMode === "off") {
|
|
122
|
-
lines.push(
|
|
123
|
-
"Citations are disabled: do not mention file paths or line numbers in replies unless the user explicitly asks."
|
|
124
|
-
);
|
|
125
|
-
} else {
|
|
126
|
-
lines.push(
|
|
127
|
-
"Citations: include Source: <path#line> when it helps the user verify memory snippets."
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
lines.push("");
|
|
62
|
+
const hasSearch = availableTools.has("memory_search");
|
|
63
|
+
const hasGet = availableTools.has("memory_get");
|
|
64
|
+
if (!hasSearch && !hasGet) return [];
|
|
65
|
+
const lines = [
|
|
66
|
+
"## Memory Recall",
|
|
67
|
+
"Before answering anything about prior work, decisions, dates, people, preferences, or todos: run memory_search for semantic search. If low confidence after search, say you checked.",
|
|
68
|
+
"",
|
|
69
|
+
"**Context extraction:** When calling memory_search or memory_get, you MUST extract the following from the UntrustedContext section and pass as parameters: `owner_id`, `sender_id`, `agent_id`, `conversation_type`, `group_id`. Look for lines like `owner_id: xxx`, `sender_id: xxx`, etc. If a field is not present, omit it. Do NOT invent or guess values — only use what is explicitly stated in UntrustedContext.",
|
|
70
|
+
""
|
|
71
|
+
];
|
|
131
72
|
return lines;
|
|
132
73
|
};
|
|
133
|
-
|
|
134
|
-
const normalized = path.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
135
|
-
return normalized === "MEMORY.md" || normalized.startsWith("memory/") || normalized.endsWith("/MEMORY.md") || normalized.includes("/memory/");
|
|
136
|
-
}
|
|
137
|
-
function formatSearchResults(results) {
|
|
138
|
-
if (results.length === 0) {
|
|
139
|
-
return "No relevant memories found.";
|
|
140
|
-
}
|
|
141
|
-
return results.map((r, i) => {
|
|
142
|
-
let sourceDesc = r.memory_type;
|
|
143
|
-
if (r.memory_type === "peer" && r.peer_id) {
|
|
144
|
-
sourceDesc = `peer/${r.peer_id}`;
|
|
145
|
-
} else if (r.memory_type === "group" && r.group_id) {
|
|
146
|
-
sourceDesc = `group/${r.group_id}`;
|
|
147
|
-
} else if (r.memory_type === "knowledge" && r.kb_id) {
|
|
148
|
-
sourceDesc = `knowledge/${r.kb_id}`;
|
|
149
|
-
}
|
|
150
|
-
const filePart = r.source_file ? ` | ${r.source_file}` : "";
|
|
151
|
-
const header = `[${i + 1}] (${sourceDesc}, score: ${r.score.toFixed(2)}${filePart})`;
|
|
152
|
-
return `${header}
|
|
153
|
-
${r.content}`;
|
|
154
|
-
}).join("\n\n");
|
|
155
|
-
}
|
|
74
|
+
|
|
156
75
|
var index_default = definePluginEntry({
|
|
157
76
|
id: "memory-search-plugin",
|
|
158
77
|
name: "Memory Search Plugin",
|
|
159
|
-
description: "
|
|
78
|
+
description: "Memory search and retrieval with owner_id-based isolation",
|
|
160
79
|
kind: "memory",
|
|
80
|
+
|
|
161
81
|
register(api) {
|
|
162
|
-
const gatewayUrl = api.pluginConfig?.gatewayUrl || "
|
|
163
|
-
const gatewayToken = api.pluginConfig?.gatewayToken || "";
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
82
|
+
const gatewayUrl = api.pluginConfig?.gatewayUrl || process.env.MEMORY_GATEWAY_URL || "";
|
|
83
|
+
const gatewayToken = api.pluginConfig?.gatewayToken || process.env.MEMORY_GATEWAY_TOKEN || "";
|
|
84
|
+
const config = { gatewayUrl, gatewayToken };
|
|
85
|
+
if (!config.gatewayUrl) {
|
|
86
|
+
console.warn("[memory-search-plugin] MEMORY_GATEWAY_URL not set, plugin disabled");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
console.log("[memory-search-plugin] gatewayUrl:", gatewayUrl);
|
|
90
|
+
const gateway = createGatewayClient(config);
|
|
91
|
+
|
|
168
92
|
api.registerMemoryPromptSection(buildPromptSection);
|
|
93
|
+
|
|
169
94
|
api.registerTool(
|
|
170
95
|
(ctx) => {
|
|
171
|
-
const fallbackIdentity = ctx.sessionKey ? resolveIdentity(ctx.sessionKey) : null;
|
|
172
|
-
const fallbackAgentId = ctx.sessionKey ? extractAgentId(ctx.sessionKey) : null;
|
|
173
96
|
return {
|
|
174
97
|
name: "memory_search",
|
|
175
|
-
description: "Semantically search
|
|
98
|
+
description: "Semantically search memories. Extract owner_id, sender_id, agent_id, conversation_type, group_id from UntrustedContext.",
|
|
176
99
|
parameters: {
|
|
177
100
|
type: "object",
|
|
178
101
|
properties: {
|
|
179
|
-
query: {
|
|
102
|
+
query: { type: "string", description: "The search query" },
|
|
103
|
+
owner_id: {
|
|
180
104
|
type: "string",
|
|
181
|
-
description: "The
|
|
105
|
+
description: "The owner_id from UntrustedContext (agent owner's user_id, always present)"
|
|
182
106
|
},
|
|
183
|
-
|
|
107
|
+
sender_id: {
|
|
184
108
|
type: "string",
|
|
185
|
-
description: "The
|
|
109
|
+
description: "The sender_id from UntrustedContext (current message sender)"
|
|
186
110
|
},
|
|
187
|
-
|
|
111
|
+
agent_id: {
|
|
188
112
|
type: "string",
|
|
189
|
-
description: "The
|
|
113
|
+
description: "The agent_id from UntrustedContext"
|
|
190
114
|
},
|
|
191
115
|
conversation_type: {
|
|
192
116
|
type: "string",
|
|
@@ -194,15 +118,15 @@ var index_default = definePluginEntry({
|
|
|
194
118
|
},
|
|
195
119
|
group_id: {
|
|
196
120
|
type: "string",
|
|
197
|
-
description: "The group_id from UntrustedContext (only
|
|
121
|
+
description: "The group_id from UntrustedContext (only in group chats)"
|
|
198
122
|
},
|
|
199
123
|
maxResults: {
|
|
200
124
|
type: "number",
|
|
201
|
-
description: "
|
|
125
|
+
description: "Max results (default 20)"
|
|
202
126
|
},
|
|
203
127
|
minScore: {
|
|
204
128
|
type: "number",
|
|
205
|
-
description: "
|
|
129
|
+
description: "Min similarity score 0-1 (default 0.3)"
|
|
206
130
|
}
|
|
207
131
|
},
|
|
208
132
|
required: ["query"]
|
|
@@ -214,51 +138,35 @@ var index_default = definePluginEntry({
|
|
|
214
138
|
content: [{ type: "text", text: "No query provided." }]
|
|
215
139
|
};
|
|
216
140
|
}
|
|
217
|
-
const
|
|
218
|
-
const identity = params.sender_id || params.conversation_type || params.group_id ? resolveIdentityFromParams({
|
|
141
|
+
const identity = resolveIdentity({
|
|
219
142
|
sender_id: params.sender_id,
|
|
143
|
+
owner_id: params.owner_id,
|
|
220
144
|
conversation_type: params.conversation_type,
|
|
221
145
|
group_id: params.group_id
|
|
222
|
-
})
|
|
146
|
+
});
|
|
147
|
+
const agentId = params.agent_id?.trim() || "main";
|
|
223
148
|
console.log(
|
|
224
|
-
`[memory-search
|
|
149
|
+
`[memory-search] search: agent=${agentId} scene=${identity.scene} sender=${identity.sender_id} owner=${identity.owner_id} group=${identity.group_id}`
|
|
225
150
|
);
|
|
226
151
|
try {
|
|
227
152
|
const data = await gateway.callGatewaySearch({
|
|
153
|
+
owner_id: identity.owner_id,
|
|
154
|
+
sender_id: identity.sender_id,
|
|
228
155
|
agent_id: agentId,
|
|
229
|
-
user_id: identity.user_id,
|
|
230
156
|
query,
|
|
231
157
|
scene: identity.scene,
|
|
232
158
|
group_id: identity.group_id,
|
|
233
|
-
release_name: releaseName || undefined,
|
|
234
159
|
limit: params.maxResults || 20,
|
|
235
160
|
threshold: params.minScore || 0.3
|
|
236
161
|
});
|
|
237
|
-
const text =
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
scene: data.scene,
|
|
244
|
-
steps: data.steps
|
|
245
|
-
}
|
|
246
|
-
};
|
|
162
|
+
const text = data.results.length === 0 ? "No relevant memories found." : data.results.map((r, i) => {
|
|
163
|
+
const tag = r.memory_type === "group" && r.group_id ? `group/${r.group_id}` : r.memory_type === "knowledge" && r.kb_id ? `knowledge/${r.kb_id}` : r.memory_type;
|
|
164
|
+
return `[${i + 1}] (${tag}, score: ${r.score.toFixed(2)})
|
|
165
|
+
${r.content}`;
|
|
166
|
+
}).join("\n\n");
|
|
167
|
+
return { content: [{ type: "text", text }] };
|
|
247
168
|
} catch (err) {
|
|
248
|
-
console.error("[memory-search
|
|
249
|
-
try {
|
|
250
|
-
const fallbackTool = api.runtime?.tools?.createMemorySearchTool({
|
|
251
|
-
config: ctx.config,
|
|
252
|
-
agentSessionKey: ctx.sessionKey
|
|
253
|
-
});
|
|
254
|
-
if (fallbackTool) {
|
|
255
|
-
console.warn(
|
|
256
|
-
"[memory-search-plugin] falling back to local memory_search"
|
|
257
|
-
);
|
|
258
|
-
return await fallbackTool.execute(toolCallId, { query, maxResults: params.maxResults, minScore: params.minScore });
|
|
259
|
-
}
|
|
260
|
-
} catch {
|
|
261
|
-
}
|
|
169
|
+
console.error("[memory-search] search failed:", err.message);
|
|
262
170
|
return {
|
|
263
171
|
content: [
|
|
264
172
|
{
|
|
@@ -273,125 +181,92 @@ var index_default = definePluginEntry({
|
|
|
273
181
|
},
|
|
274
182
|
{ names: ["memory_search"] }
|
|
275
183
|
);
|
|
184
|
+
|
|
276
185
|
api.registerTool(
|
|
277
186
|
(ctx) => {
|
|
278
|
-
const fallbackIdentity = ctx.sessionKey ? resolveIdentity(ctx.sessionKey) : null;
|
|
279
|
-
const fallbackAgentId = ctx.sessionKey ? extractAgentId(ctx.sessionKey) : null;
|
|
280
187
|
return {
|
|
281
188
|
name: "memory_get",
|
|
282
|
-
description: "
|
|
189
|
+
description: "Search raw chat messages by keyword. Queries the original message log, not the extracted facts. Extract owner_id, sender_id, agent_id, conversation_type, group_id from UntrustedContext.",
|
|
283
190
|
parameters: {
|
|
284
191
|
type: "object",
|
|
285
192
|
properties: {
|
|
286
|
-
|
|
193
|
+
keyword: {
|
|
287
194
|
type: "string",
|
|
288
|
-
description: "
|
|
195
|
+
description: "Keyword to search in chat messages"
|
|
289
196
|
},
|
|
290
|
-
|
|
197
|
+
owner_id: {
|
|
291
198
|
type: "string",
|
|
292
|
-
description: "The
|
|
199
|
+
description: "The owner_id from UntrustedContext"
|
|
293
200
|
},
|
|
294
201
|
sender_id: {
|
|
295
202
|
type: "string",
|
|
296
203
|
description: "The sender_id from UntrustedContext"
|
|
297
204
|
},
|
|
205
|
+
agent_id: {
|
|
206
|
+
type: "string",
|
|
207
|
+
description: "The agent_id from UntrustedContext"
|
|
208
|
+
},
|
|
298
209
|
conversation_type: {
|
|
299
210
|
type: "string",
|
|
300
211
|
description: "The conversation_type from UntrustedContext: 'direct' or 'group'"
|
|
301
212
|
},
|
|
302
213
|
group_id: {
|
|
303
214
|
type: "string",
|
|
304
|
-
description: "The group_id from UntrustedContext (only
|
|
215
|
+
description: "The group_id from UntrustedContext (only in group chats)"
|
|
305
216
|
},
|
|
306
|
-
|
|
217
|
+
limit: {
|
|
307
218
|
type: "number",
|
|
308
|
-
description: "
|
|
309
|
-
},
|
|
310
|
-
lines: {
|
|
311
|
-
type: "number",
|
|
312
|
-
description: "Number of lines to read"
|
|
219
|
+
description: "Max messages to return (default 20)"
|
|
313
220
|
}
|
|
314
221
|
},
|
|
315
|
-
required: ["
|
|
222
|
+
required: ["keyword"]
|
|
316
223
|
},
|
|
317
224
|
async execute(toolCallId, params) {
|
|
318
|
-
const
|
|
319
|
-
if (!
|
|
225
|
+
const keyword = params.keyword || "";
|
|
226
|
+
if (!keyword) {
|
|
320
227
|
return {
|
|
321
|
-
content: [{ type: "text", text: "No
|
|
228
|
+
content: [{ type: "text", text: "No keyword provided." }]
|
|
322
229
|
};
|
|
323
230
|
}
|
|
324
|
-
|
|
231
|
+
const identity = resolveIdentity({
|
|
232
|
+
sender_id: params.sender_id,
|
|
233
|
+
owner_id: params.owner_id,
|
|
234
|
+
conversation_type: params.conversation_type,
|
|
235
|
+
group_id: params.group_id
|
|
236
|
+
});
|
|
237
|
+
const agentId = params.agent_id?.trim() || "main";
|
|
238
|
+
console.log(
|
|
239
|
+
`[memory-search] get: keyword="${keyword}" agent=${agentId} scene=${identity.scene} owner=${identity.owner_id} group=${identity.group_id}`
|
|
240
|
+
);
|
|
325
241
|
try {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
242
|
+
const data = await gateway.callGatewayGet({
|
|
243
|
+
owner_id: identity.owner_id,
|
|
244
|
+
sender_id: identity.sender_id,
|
|
245
|
+
agent_id: agentId,
|
|
246
|
+
keyword,
|
|
247
|
+
scene: identity.scene,
|
|
248
|
+
group_id: identity.group_id,
|
|
249
|
+
limit: params.limit || 20
|
|
329
250
|
});
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
if (isMemoryPath(path)) {
|
|
333
|
-
const agentId = params.agent_id?.trim() || fallbackAgentId || "main";
|
|
334
|
-
const identity = params.sender_id || params.conversation_type || params.group_id ? resolveIdentityFromParams({
|
|
335
|
-
sender_id: params.sender_id,
|
|
336
|
-
conversation_type: params.conversation_type,
|
|
337
|
-
group_id: params.group_id
|
|
338
|
-
}) : fallbackIdentity || resolveIdentityFromParams({});
|
|
339
|
-
console.log(
|
|
340
|
-
`[memory-search-plugin] get: path=${path} agent_id=${agentId} scene=${identity.scene} user_id=${identity.user_id} release_name=${releaseName} (source=${params.sender_id ? "llm_params" : "fallback"})`
|
|
341
|
-
);
|
|
342
|
-
try {
|
|
343
|
-
const data = await gateway.callGatewayGet({
|
|
344
|
-
agent_id: agentId,
|
|
345
|
-
user_id: identity.user_id,
|
|
346
|
-
path,
|
|
347
|
-
scene: identity.scene,
|
|
348
|
-
group_id: identity.group_id,
|
|
349
|
-
release_name: releaseName || undefined,
|
|
350
|
-
from: params.from,
|
|
351
|
-
lines: params.lines
|
|
352
|
-
});
|
|
353
|
-
return {
|
|
354
|
-
content: [{ type: "text", text: data.text }],
|
|
355
|
-
details: { path: data.path, text: data.text }
|
|
356
|
-
};
|
|
357
|
-
} catch (err) {
|
|
358
|
-
console.error("[memory-search-plugin] get failed:", err.message);
|
|
359
|
-
if (err.message?.includes("403")) {
|
|
360
|
-
return {
|
|
361
|
-
content: [
|
|
362
|
-
{
|
|
363
|
-
type: "text",
|
|
364
|
-
text: `Access denied: ${path}`
|
|
365
|
-
}
|
|
366
|
-
]
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
if (originalGetTool) {
|
|
370
|
-
console.warn(
|
|
371
|
-
"[memory-search-plugin] falling back to local memory_get for:",
|
|
372
|
-
path
|
|
373
|
-
);
|
|
374
|
-
return await originalGetTool.execute(toolCallId, { path, from: params.from, lines: params.lines });
|
|
375
|
-
}
|
|
251
|
+
if (data.messages.length === 0) {
|
|
376
252
|
return {
|
|
377
253
|
content: [
|
|
378
|
-
{
|
|
379
|
-
|
|
380
|
-
text: `Failed to read ${path}: Gateway unavailable.`
|
|
381
|
-
}
|
|
382
|
-
],
|
|
383
|
-
details: { path, text: "", error: err.message }
|
|
254
|
+
{ type: "text", text: "No matching messages found." }
|
|
255
|
+
]
|
|
384
256
|
};
|
|
385
257
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
return
|
|
389
|
-
}
|
|
258
|
+
const text = data.messages.map((m) => {
|
|
259
|
+
const tag = m.message_type === "group" && m.group_id ? `group/${m.group_id}` : m.message_type;
|
|
260
|
+
return `[${tag}] ${m.formatted_text}`;
|
|
261
|
+
}).join("\n");
|
|
262
|
+
return { content: [{ type: "text", text }] };
|
|
263
|
+
} catch (err) {
|
|
264
|
+
console.error("[memory-search] get failed:", err.message);
|
|
390
265
|
return {
|
|
391
266
|
content: [
|
|
392
267
|
{
|
|
393
268
|
type: "text",
|
|
394
|
-
text:
|
|
269
|
+
text: "Message search temporarily unavailable."
|
|
395
270
|
}
|
|
396
271
|
]
|
|
397
272
|
};
|
|
@@ -401,17 +276,9 @@ var index_default = definePluginEntry({
|
|
|
401
276
|
},
|
|
402
277
|
{ names: ["memory_get"] }
|
|
403
278
|
);
|
|
404
|
-
api.registerCli(
|
|
405
|
-
({ program }) => {
|
|
406
|
-
try {
|
|
407
|
-
api.runtime?.tools?.registerMemoryCli(program);
|
|
408
|
-
} catch {
|
|
409
|
-
}
|
|
410
|
-
},
|
|
411
|
-
{ commands: ["memory"] }
|
|
412
|
-
);
|
|
413
279
|
}
|
|
414
280
|
});
|
|
281
|
+
|
|
415
282
|
export {
|
|
416
283
|
index_default as default
|
|
417
284
|
};
|