@modelstudio/modelstudio-memory-for-openclaw 1.0.0 → 1.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 +8 -14
- package/index.ts +49 -20
- package/openclaw.plugin.json +5 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,8 +57,8 @@ openclaw modelstudio-memory stats
|
|
|
57
57
|
enabled: true,
|
|
58
58
|
config: {
|
|
59
59
|
// 必需配置
|
|
60
|
-
"apiKey": "
|
|
61
|
-
"userId": "
|
|
60
|
+
"apiKey": "your-dashscope-api-key",
|
|
61
|
+
"userId": "openclaw_memory",
|
|
62
62
|
|
|
63
63
|
// 可选配置(以下为默认值)
|
|
64
64
|
"baseUrl": "https://dashscope.aliyuncs.com/api/v2/apps/memory",
|
|
@@ -80,8 +80,8 @@ openclaw modelstudio-memory stats
|
|
|
80
80
|
|
|
81
81
|
| 配置项 | 类型 | 必需 | 默认值 | 说明 |
|
|
82
82
|
|--------|------|------|--------|------|
|
|
83
|
-
| `apiKey` | `string` | ✅ | - | DashScope API Key
|
|
84
|
-
| `userId` | `string` |
|
|
83
|
+
| `apiKey` | `string` | ✅ | - | DashScope API Key(在 openclaw.json 中配置) |
|
|
84
|
+
| `userId` | `string` | ❌ | `openclaw_memory` | 用户 ID,用于隔离不同用户的记忆 |
|
|
85
85
|
| `baseUrl` | `string` | ❌ | `https://dashscope.aliyuncs.com/api/v2/apps/memory` | API endpoint(私有部署时填写完整 URL) |
|
|
86
86
|
| `autoCapture` | `boolean` | ❌ | `true` | 是否自动捕获对话 |
|
|
87
87
|
| `autoRecall` | `boolean` | ❌ | `true` | 是否自动召回记忆 |
|
|
@@ -91,17 +91,11 @@ openclaw modelstudio-memory stats
|
|
|
91
91
|
| `recallMinPromptLength` | `number` | ❌ | `10` | 触发自动召回的最小 prompt 长度 |
|
|
92
92
|
| `recallCacheTtlMs` | `number` | ❌ | `300000` | 召回缓存时间(毫秒),0 禁用缓存 |
|
|
93
93
|
|
|
94
|
-
##
|
|
94
|
+
## 获取 API Key
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
# 设置 DashScope API Key
|
|
98
|
-
export DASHSCOPE_API_KEY="your-api-key"
|
|
99
|
-
|
|
100
|
-
# 重启 Gateway
|
|
101
|
-
openclaw gateway restart
|
|
102
|
-
```
|
|
96
|
+
在 [阿里云百炼控制台](https://help.aliyun.com/zh/model-studio/get-api-key) 获取 DashScope API Key,并在 `openclaw.json` 的 `config.apiKey` 中配置。
|
|
103
97
|
|
|
104
|
-
|
|
98
|
+
**提示**:若安装后未配置 apiKey,插件仍会加载。当用户使用记忆功能(如询问「我之前说过什么」)时,Agent 会提示用户配置 apiKey。
|
|
105
99
|
|
|
106
100
|
## 使用方法
|
|
107
101
|
|
|
@@ -230,7 +224,7 @@ tail -f ~/.openclaw/logs/gateway.log | grep modelstudio-memory
|
|
|
230
224
|
|
|
231
225
|
| 错误 | 原因 | 解决方案 |
|
|
232
226
|
|------|------|----------|
|
|
233
|
-
| `apiKey is required` | 未配置 API Key |
|
|
227
|
+
| `apiKey is required` | 未配置 API Key | 在 openclaw.json 的 config 中配置 apiKey |
|
|
234
228
|
| `InvalidApiKey` | API Key 无效 | 检查 API Key 是否正确 |
|
|
235
229
|
| `TooManyRequests` | 请求频率过高 | 降低调用频率 |
|
|
236
230
|
|
package/index.ts
CHANGED
|
@@ -80,14 +80,6 @@ const ALLOWED_KEYS = [
|
|
|
80
80
|
"recallCacheTtlMs",
|
|
81
81
|
];
|
|
82
82
|
|
|
83
|
-
function resolveEnvVars(value: string): string {
|
|
84
|
-
if (!value) return value;
|
|
85
|
-
return value.replace(/\$\{([^}]+)\}/g, (_, key) => {
|
|
86
|
-
const envValue = process.env[key];
|
|
87
|
-
return envValue || "";
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
83
|
function assertAllowedKeys(
|
|
92
84
|
value: Record<string, unknown>,
|
|
93
85
|
allowed: string[],
|
|
@@ -106,17 +98,9 @@ const modelstudioMemoryConfigSchema = {
|
|
|
106
98
|
const cfg = value as Record<string, unknown>;
|
|
107
99
|
assertAllowedKeys(cfg, ALLOWED_KEYS, "modelstudio-memory-for-openclaw config");
|
|
108
100
|
|
|
109
|
-
// apiKey
|
|
110
|
-
const apiKey = typeof cfg.apiKey === "string" ?
|
|
111
|
-
|
|
112
|
-
throw new Error("apiKey is required for modelstudio-memory-for-openclaw");
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// userId is required
|
|
116
|
-
const userId = typeof cfg.userId === "string" ? cfg.userId : "";
|
|
117
|
-
if (!userId) {
|
|
118
|
-
throw new Error("userId is required for modelstudio-memory-for-openclaw");
|
|
119
|
-
}
|
|
101
|
+
// apiKey: allow empty at parse time; tools return config prompt when missing
|
|
102
|
+
const apiKey = typeof cfg.apiKey === "string" ? cfg.apiKey : "";
|
|
103
|
+
const userId = typeof cfg.userId === "string" && cfg.userId ? cfg.userId : "openclaw_memory";
|
|
120
104
|
|
|
121
105
|
return {
|
|
122
106
|
apiKey,
|
|
@@ -373,6 +357,9 @@ function stripInjectedContext(text: string): string {
|
|
|
373
357
|
return text.replace(/<relevant-memories>[\s\S]*?<\/relevant-memories>\s*/g, "").trim();
|
|
374
358
|
}
|
|
375
359
|
|
|
360
|
+
const CONFIG_REQUIRED_MESSAGE =
|
|
361
|
+
"Memory plugin is not configured. Please add apiKey and userId to ~/.openclaw/openclaw.json under plugins.entries.modelstudio-memory-for-openclaw.config. Get API Key: https://help.aliyun.com/zh/model-studio/get-api-key";
|
|
362
|
+
|
|
376
363
|
// ============================================================================
|
|
377
364
|
// Plugin Definition
|
|
378
365
|
// ============================================================================
|
|
@@ -393,6 +380,11 @@ const modelstudioMemoryPlugin = {
|
|
|
393
380
|
api.logger
|
|
394
381
|
);
|
|
395
382
|
|
|
383
|
+
if (!cfg.apiKey) {
|
|
384
|
+
api.logger.warn(
|
|
385
|
+
"modelstudio-memory: apiKey not configured. Memory features disabled until config is added to openclaw.json."
|
|
386
|
+
);
|
|
387
|
+
}
|
|
396
388
|
api.logger.info(
|
|
397
389
|
`modelstudio-memory: registered (user: ${cfg.userId}, autoCapture: ${cfg.autoCapture}, autoRecall: ${cfg.autoRecall})`
|
|
398
390
|
);
|
|
@@ -413,6 +405,12 @@ const modelstudioMemoryPlugin = {
|
|
|
413
405
|
),
|
|
414
406
|
}),
|
|
415
407
|
async execute(_id, params) {
|
|
408
|
+
if (!cfg.apiKey) {
|
|
409
|
+
return {
|
|
410
|
+
content: [{ type: "text", text: CONFIG_REQUIRED_MESSAGE }],
|
|
411
|
+
isError: true,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
416
414
|
try {
|
|
417
415
|
const limit = Math.min(
|
|
418
416
|
Math.max(1, params.limit ?? cfg.topK),
|
|
@@ -484,6 +482,12 @@ const modelstudioMemoryPlugin = {
|
|
|
484
482
|
content: Type.String({ description: "Content to store" }),
|
|
485
483
|
}),
|
|
486
484
|
async execute(_id, params) {
|
|
485
|
+
if (!cfg.apiKey) {
|
|
486
|
+
return {
|
|
487
|
+
content: [{ type: "text", text: CONFIG_REQUIRED_MESSAGE }],
|
|
488
|
+
isError: true,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
487
491
|
try {
|
|
488
492
|
const result = await client.addCustomContent(params.content);
|
|
489
493
|
|
|
@@ -529,6 +533,12 @@ const modelstudioMemoryPlugin = {
|
|
|
529
533
|
),
|
|
530
534
|
}),
|
|
531
535
|
async execute(_id, params) {
|
|
536
|
+
if (!cfg.apiKey) {
|
|
537
|
+
return {
|
|
538
|
+
content: [{ type: "text", text: CONFIG_REQUIRED_MESSAGE }],
|
|
539
|
+
isError: true,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
532
542
|
try {
|
|
533
543
|
const page = Math.max(1, params.page ?? 1);
|
|
534
544
|
const pageSize = Math.min(100, Math.max(1, params.pageSize ?? 10));
|
|
@@ -589,6 +599,12 @@ const modelstudioMemoryPlugin = {
|
|
|
589
599
|
index: Type.Optional(Type.Number({ description: "Delete Nth memory (1-based)" })),
|
|
590
600
|
}),
|
|
591
601
|
async execute(_id, params) {
|
|
602
|
+
if (!cfg.apiKey) {
|
|
603
|
+
return {
|
|
604
|
+
content: [{ type: "text", text: CONFIG_REQUIRED_MESSAGE }],
|
|
605
|
+
isError: true,
|
|
606
|
+
};
|
|
607
|
+
}
|
|
592
608
|
try {
|
|
593
609
|
let targetId = params.memoryId;
|
|
594
610
|
|
|
@@ -706,6 +722,7 @@ const modelstudioMemoryPlugin = {
|
|
|
706
722
|
// ========== autoRecall ==========
|
|
707
723
|
if (cfg.autoRecall) {
|
|
708
724
|
api.on("before_agent_start", async (event) => {
|
|
725
|
+
if (!cfg.apiKey) return;
|
|
709
726
|
const prompt = extractTextContent(event.prompt);
|
|
710
727
|
if (!prompt || prompt.length < cfg.recallMinPromptLength) {
|
|
711
728
|
return;
|
|
@@ -739,7 +756,7 @@ const modelstudioMemoryPlugin = {
|
|
|
739
756
|
// ========== autoCapture ==========
|
|
740
757
|
if (cfg.autoCapture) {
|
|
741
758
|
api.on("agent_end", async (event) => {
|
|
742
|
-
if (!event.success || !event.messages) {
|
|
759
|
+
if (!cfg.apiKey || !event.success || !event.messages) {
|
|
743
760
|
return;
|
|
744
761
|
}
|
|
745
762
|
|
|
@@ -814,6 +831,10 @@ const modelstudioMemoryPlugin = {
|
|
|
814
831
|
.argument("<query>", "Search query")
|
|
815
832
|
.option("--limit <n>", "Max results", String(cfg.topK))
|
|
816
833
|
.action(async (query: string, opts: { limit: string }) => {
|
|
834
|
+
if (!cfg.apiKey) {
|
|
835
|
+
console.error(CONFIG_REQUIRED_MESSAGE);
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
817
838
|
try {
|
|
818
839
|
const limit = Math.min(100, Math.max(1, parseInt(opts.limit, 10) || cfg.topK));
|
|
819
840
|
const cleanQuery = extractTextContent(query) || query.trim();
|
|
@@ -848,6 +869,10 @@ const modelstudioMemoryPlugin = {
|
|
|
848
869
|
.command("stats")
|
|
849
870
|
.description("Show memory statistics")
|
|
850
871
|
.action(async () => {
|
|
872
|
+
if (!cfg.apiKey) {
|
|
873
|
+
console.error(CONFIG_REQUIRED_MESSAGE);
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
851
876
|
try {
|
|
852
877
|
const result = await client.listMemory(1, 1);
|
|
853
878
|
console.log(`User: ${cfg.userId}`);
|
|
@@ -867,6 +892,10 @@ const modelstudioMemoryPlugin = {
|
|
|
867
892
|
.option("--page <n>", "Page number", "1")
|
|
868
893
|
.option("--size <n>", "Page size", "10")
|
|
869
894
|
.action(async (opts: { page: string; size: string }) => {
|
|
895
|
+
if (!cfg.apiKey) {
|
|
896
|
+
console.error(CONFIG_REQUIRED_MESSAGE);
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
870
899
|
try {
|
|
871
900
|
const page = Math.max(1, parseInt(opts.page, 10) || 1);
|
|
872
901
|
const size = Math.min(100, Math.max(1, parseInt(opts.size, 10) || 10));
|
package/openclaw.plugin.json
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
"name": "modelstudio-memory-for-openclaw",
|
|
4
4
|
"description": "阿里云百炼长期记忆服务,提供自动记忆捕获和召回能力",
|
|
5
5
|
"kind": "memory",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.2",
|
|
7
7
|
"configSchema": {
|
|
8
8
|
"type": "object",
|
|
9
9
|
"additionalProperties": false,
|
|
10
10
|
"properties": {
|
|
11
11
|
"apiKey": {
|
|
12
12
|
"type": "string",
|
|
13
|
-
"description": "DashScope API Key
|
|
13
|
+
"description": "DashScope API Key"
|
|
14
14
|
},
|
|
15
15
|
"userId": {
|
|
16
16
|
"type": "string",
|
|
17
|
-
"description": "用户 ID
|
|
17
|
+
"description": "用户 ID,用于隔离不同用户的记忆(默认 'openclaw_memory')"
|
|
18
18
|
},
|
|
19
19
|
"baseUrl": {
|
|
20
20
|
"type": "string",
|
|
@@ -62,11 +62,11 @@
|
|
|
62
62
|
"apiKey": {
|
|
63
63
|
"label": "API Key",
|
|
64
64
|
"sensitive": true,
|
|
65
|
-
"placeholder": "
|
|
65
|
+
"placeholder": "sk-..."
|
|
66
66
|
},
|
|
67
67
|
"userId": {
|
|
68
68
|
"label": "用户 ID",
|
|
69
|
-
"placeholder": "
|
|
69
|
+
"placeholder": "openclaw_memory"
|
|
70
70
|
},
|
|
71
71
|
"baseUrl": {
|
|
72
72
|
"label": "API Endpoint",
|