@aliyunrds/ctxdb 0.0.5 → 0.0.7
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 +3 -3
- package/dist/{chunk-HAUTENYD.js → chunk-6S5RJYBC.js} +20 -77
- package/dist/{chunk-7NOXAU2X.js → chunk-LIC44DR6.js} +9 -2
- package/dist/chunk-Q2EEP4CE.js +69 -0
- package/dist/{chunk-QSSNPN3M.js → chunk-S45GOYUU.js} +46 -12
- package/dist/cli/main.js +417 -164
- package/dist/hooks/session-start.js +10 -3
- package/dist/hooks/stop.js +100 -21
- package/dist/hooks/user-prompt-submit.js +14 -5
- package/dist/setup/skills/contextdb-knowledge/SKILL.md +161 -0
- package/dist/setup/skills/contextdb-memory/SKILL.md +142 -0
- package/package.json +2 -2
- package/dist/setup/skills/cli-only/SKILL.md +0 -116
- package/dist/setup/skills/hooks-driven/SKILL.md +0 -144
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
recallTurn
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-LIC44DR6.js";
|
|
5
|
+
import {
|
|
6
|
+
isCircuitOpen
|
|
7
|
+
} from "../chunk-Q2EEP4CE.js";
|
|
5
8
|
import {
|
|
6
9
|
HttpClient,
|
|
7
10
|
agentFromArgvWithFallback,
|
|
@@ -9,7 +12,7 @@ import {
|
|
|
9
12
|
isComplete,
|
|
10
13
|
load,
|
|
11
14
|
setDebug
|
|
12
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-S45GOYUU.js";
|
|
13
16
|
|
|
14
17
|
// src/lib/warmup-recall.ts
|
|
15
18
|
import { execSync } from "child_process";
|
|
@@ -63,7 +66,7 @@ async function warmupRecall(cwd, cfg, client) {
|
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
// src/hooks/session-start.ts
|
|
66
|
-
var HOOK_TIMEOUT_MS =
|
|
69
|
+
var HOOK_TIMEOUT_MS = 5e3;
|
|
67
70
|
async function readStdinJson() {
|
|
68
71
|
let raw = "";
|
|
69
72
|
for await (const chunk of process.stdin) raw += chunk;
|
|
@@ -97,6 +100,10 @@ async function main() {
|
|
|
97
100
|
debug("warmup", "skip (config incomplete or warmupRecall=false)");
|
|
98
101
|
return 0;
|
|
99
102
|
}
|
|
103
|
+
if (isCircuitOpen(agent, cfg.baseUrl)) {
|
|
104
|
+
debug("warmup", "skip (circuit open)");
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
100
107
|
const client = new HttpClient({
|
|
101
108
|
baseUrl: cfg.baseUrl,
|
|
102
109
|
apiKey: cfg.apiKey,
|
package/dist/hooks/stop.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
isCircuitOpen,
|
|
4
|
+
isConnectionError,
|
|
5
|
+
resetCircuit,
|
|
6
|
+
tripCircuit
|
|
7
|
+
} from "../chunk-Q2EEP4CE.js";
|
|
2
8
|
import {
|
|
3
9
|
CtxdbError,
|
|
4
10
|
HttpClient,
|
|
@@ -6,7 +12,7 @@ import {
|
|
|
6
12
|
debug,
|
|
7
13
|
load,
|
|
8
14
|
setDebug
|
|
9
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-S45GOYUU.js";
|
|
10
16
|
|
|
11
17
|
// src/lib/capture-orchestrator.ts
|
|
12
18
|
import {
|
|
@@ -15,6 +21,26 @@ import {
|
|
|
15
21
|
selectTurnMessages
|
|
16
22
|
} from "@aliyunrds/ctxdb-shared";
|
|
17
23
|
|
|
24
|
+
// src/lib/git-context.ts
|
|
25
|
+
import { execSync } from "child_process";
|
|
26
|
+
function getGitContext() {
|
|
27
|
+
try {
|
|
28
|
+
const raw = execSync("git rev-parse --show-toplevel --abbrev-ref HEAD", {
|
|
29
|
+
encoding: "utf-8",
|
|
30
|
+
timeout: 3e3,
|
|
31
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
32
|
+
}).trim();
|
|
33
|
+
const lines = raw.split("\n");
|
|
34
|
+
if (lines.length < 2) return null;
|
|
35
|
+
const project = lines[0].split("/").pop();
|
|
36
|
+
if (!project) return null;
|
|
37
|
+
const branch = lines[1];
|
|
38
|
+
return { project, branch };
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
18
44
|
// src/lib/transcript.ts
|
|
19
45
|
import { existsSync, readFileSync } from "fs";
|
|
20
46
|
var ANTHROPIC_MESSAGE_TYPES = /* @__PURE__ */ new Set(["user", "assistant"]);
|
|
@@ -157,21 +183,10 @@ function toParsedMessages(rows) {
|
|
|
157
183
|
}
|
|
158
184
|
continue;
|
|
159
185
|
}
|
|
160
|
-
if (ptype === "reasoning")
|
|
161
|
-
const summary = p.summary;
|
|
162
|
-
if (!Array.isArray(summary)) continue;
|
|
163
|
-
for (const block of summary) {
|
|
164
|
-
if (!block || typeof block !== "object") continue;
|
|
165
|
-
const btype = block.type;
|
|
166
|
-
if (btype === "summary_text") {
|
|
167
|
-
const v = block.text;
|
|
168
|
-
if (typeof v === "string") push("assistant", v);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
186
|
+
if (ptype === "reasoning") continue;
|
|
173
187
|
continue;
|
|
174
188
|
}
|
|
189
|
+
if (row.isMeta === true) continue;
|
|
175
190
|
const msg = row.message;
|
|
176
191
|
if (!msg || typeof msg !== "object") continue;
|
|
177
192
|
const role = msg.role;
|
|
@@ -189,9 +204,6 @@ function toParsedMessages(rows) {
|
|
|
189
204
|
if (btype === "text") {
|
|
190
205
|
const v = block.text;
|
|
191
206
|
if (typeof v === "string") text = v;
|
|
192
|
-
} else if (btype === "thinking") {
|
|
193
|
-
const v = block.thinking;
|
|
194
|
-
if (typeof v === "string") text = v;
|
|
195
207
|
}
|
|
196
208
|
if (text) push(role, text);
|
|
197
209
|
}
|
|
@@ -199,15 +211,66 @@ function toParsedMessages(rows) {
|
|
|
199
211
|
}
|
|
200
212
|
return parsed;
|
|
201
213
|
}
|
|
214
|
+
var COMMAND_MESSAGE_RE = /<command-message>([\s\S]*?)<\/command-message>/;
|
|
215
|
+
var COMMAND_ARGS_RE = /<command-args>([\s\S]*?)<\/command-args>/;
|
|
216
|
+
function extractSkillSignals(rows) {
|
|
217
|
+
const signals = [];
|
|
218
|
+
const seen = /* @__PURE__ */ new Set();
|
|
219
|
+
const add = (s) => {
|
|
220
|
+
const key = `${s.trigger}:${s.skill}`;
|
|
221
|
+
if (seen.has(key)) return;
|
|
222
|
+
seen.add(key);
|
|
223
|
+
signals.push(s);
|
|
224
|
+
};
|
|
225
|
+
for (const row of rows) {
|
|
226
|
+
if (!row || typeof row !== "object") continue;
|
|
227
|
+
if (row.type === "user") {
|
|
228
|
+
const msg = row.message;
|
|
229
|
+
if (!msg || typeof msg !== "object") continue;
|
|
230
|
+
const content = msg.content;
|
|
231
|
+
if (typeof content === "string") {
|
|
232
|
+
const m = COMMAND_MESSAGE_RE.exec(content);
|
|
233
|
+
if (m) {
|
|
234
|
+
const argsMatch = COMMAND_ARGS_RE.exec(content);
|
|
235
|
+
add({
|
|
236
|
+
skill: m[1].trim(),
|
|
237
|
+
args: argsMatch?.[1]?.trim() || void 0,
|
|
238
|
+
trigger: "command"
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (row.type === "assistant") {
|
|
244
|
+
const msg = row.message;
|
|
245
|
+
if (!msg || typeof msg !== "object") continue;
|
|
246
|
+
const content = msg.content;
|
|
247
|
+
if (!Array.isArray(content)) continue;
|
|
248
|
+
for (const block of content) {
|
|
249
|
+
if (block && typeof block === "object" && block.type === "tool_use" && block.name === "Skill") {
|
|
250
|
+
const input = block.input;
|
|
251
|
+
if (input && typeof input === "object") {
|
|
252
|
+
const skill = typeof input.skill === "string" ? input.skill : "";
|
|
253
|
+
const args = typeof input.args === "string" ? input.args : void 0;
|
|
254
|
+
if (skill) add({ skill, args, trigger: "agent" });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return signals;
|
|
261
|
+
}
|
|
202
262
|
|
|
203
263
|
// src/lib/capture-orchestrator.ts
|
|
204
|
-
async function captureTurn(transcriptPath, cfg, client) {
|
|
264
|
+
async function captureTurn(transcriptPath, cfg, client, agent = "default") {
|
|
205
265
|
if (!cfg.apiKey || !cfg.baseUrl) {
|
|
206
266
|
return { captured: false, reason: "config_incomplete", messageCount: 0 };
|
|
207
267
|
}
|
|
208
268
|
if (!cfg.autoCapture) {
|
|
209
269
|
return { captured: false, reason: "auto_capture_disabled", messageCount: 0 };
|
|
210
270
|
}
|
|
271
|
+
if (isCircuitOpen(agent, cfg.baseUrl)) {
|
|
272
|
+
return { captured: false, reason: `circuit_open: ${cfg.baseUrl}`, messageCount: 0 };
|
|
273
|
+
}
|
|
211
274
|
const rows = readTranscript(transcriptPath);
|
|
212
275
|
if (rows.length === 0) {
|
|
213
276
|
return { captured: false, reason: "empty_transcript", messageCount: 0 };
|
|
@@ -240,16 +303,32 @@ async function captureTurn(transcriptPath, cfg, client) {
|
|
|
240
303
|
if (filtered.length === 0) {
|
|
241
304
|
return { captured: false, reason: "all_filtered", messageCount: 0 };
|
|
242
305
|
}
|
|
306
|
+
const git = getGitContext();
|
|
307
|
+
const skills = extractSkillSignals(rows);
|
|
308
|
+
const bgParts = [];
|
|
309
|
+
if (git) {
|
|
310
|
+
bgParts.push(`This conversation took place in project "${git.project}", branch "${git.branch}".`);
|
|
311
|
+
}
|
|
312
|
+
if (skills.length > 0) {
|
|
313
|
+
const descs = skills.map((s) => {
|
|
314
|
+
const label = s.trigger === "command" ? "user-invoked" : "agent-invoked";
|
|
315
|
+
return s.args ? `${s.skill} (${label}, args: "${s.args}")` : `${s.skill} (${label})`;
|
|
316
|
+
});
|
|
317
|
+
bgParts.push(`Skills used: ${descs.join(", ")}.`);
|
|
318
|
+
}
|
|
319
|
+
const messages = bgParts.length > 0 ? [{ role: "background", content: bgParts.join("\n") }, ...filtered] : filtered;
|
|
243
320
|
const payload = {
|
|
244
|
-
messages
|
|
321
|
+
messages,
|
|
245
322
|
user_id: cfg.userId,
|
|
246
323
|
async_mode: true
|
|
247
324
|
};
|
|
248
325
|
let resp;
|
|
249
326
|
try {
|
|
250
327
|
resp = await client.postJson("/v3/memories/add/", payload);
|
|
328
|
+
resetCircuit(agent);
|
|
251
329
|
} catch (err) {
|
|
252
330
|
const msg = err instanceof CtxdbError ? err.message : String(err);
|
|
331
|
+
if (isConnectionError(err)) tripCircuit(agent, cfg.baseUrl, msg);
|
|
253
332
|
return {
|
|
254
333
|
captured: false,
|
|
255
334
|
reason: `http_error: ${msg}`,
|
|
@@ -295,8 +374,8 @@ async function main() {
|
|
|
295
374
|
debug("capture", "skip (config incomplete)");
|
|
296
375
|
return 0;
|
|
297
376
|
}
|
|
298
|
-
const client = new HttpClient({ baseUrl: cfg.baseUrl, apiKey: cfg.apiKey });
|
|
299
|
-
const result = await captureTurn(transcriptPath, cfg, client);
|
|
377
|
+
const client = new HttpClient({ baseUrl: cfg.baseUrl, apiKey: cfg.apiKey, timeoutMs: 5e3 });
|
|
378
|
+
const result = await captureTurn(transcriptPath, cfg, client, agent);
|
|
300
379
|
if (result.captured) {
|
|
301
380
|
debug("capture", `ok (${result.messageCount} msgs)`, result);
|
|
302
381
|
process.stderr.write(
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
listKnowledgeBases
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-6S5RJYBC.js";
|
|
5
5
|
import {
|
|
6
6
|
recallTurn
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-LIC44DR6.js";
|
|
8
|
+
import {
|
|
9
|
+
isCircuitOpen
|
|
10
|
+
} from "../chunk-Q2EEP4CE.js";
|
|
8
11
|
import {
|
|
9
12
|
HttpClient,
|
|
10
13
|
agentFromArgvWithFallback,
|
|
@@ -12,7 +15,7 @@ import {
|
|
|
12
15
|
isComplete,
|
|
13
16
|
load,
|
|
14
17
|
setDebug
|
|
15
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-S45GOYUU.js";
|
|
16
19
|
|
|
17
20
|
// src/lib/kb-catalog.ts
|
|
18
21
|
async function fetchKbCatalogBlock(client, agent) {
|
|
@@ -59,9 +62,15 @@ async function main() {
|
|
|
59
62
|
debug("recall", "skip (config incomplete or autoRecall=false)");
|
|
60
63
|
return 0;
|
|
61
64
|
}
|
|
62
|
-
|
|
65
|
+
if (isCircuitOpen(agent, cfg.baseUrl)) {
|
|
66
|
+
debug("recall", "skip (circuit open)");
|
|
67
|
+
process.stderr.write(`ctxdb recall: skip (circuit_open: ${cfg.baseUrl})
|
|
68
|
+
`);
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
const client = new HttpClient({ baseUrl: cfg.baseUrl, apiKey: cfg.apiKey, timeoutMs: 5e3 });
|
|
63
72
|
const [result, kbBlock] = await Promise.all([
|
|
64
|
-
recallTurn(prompt, cfg, client),
|
|
73
|
+
recallTurn(prompt, cfg, client, agent),
|
|
65
74
|
fetchKbCatalogBlock(client, agent).catch(() => "")
|
|
66
75
|
]);
|
|
67
76
|
if (!result.ok && !result.additionalContext && !kbBlock) {
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: contextdb-knowledge
|
|
3
|
+
description: RDS contextdb 知识库操作全量参考。覆盖 kb create / search / upload-text / upload-file / list / documents-list / document-get 的完整参数和 JSON 输出结构。当用户提到"查知识库"、"查 KB"、"上传到 KB"、"灌进知识库"、"列出知识库"、"看文档"、"建知识库"等场景时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# contextdb Knowledge Base 操作参考
|
|
7
|
+
|
|
8
|
+
## 配置
|
|
9
|
+
|
|
10
|
+
- 配置文件:`~/.ctxdb/ctxdb.json`
|
|
11
|
+
- 配置命令:`ctxdb setup --api-key=<key> --base-url=<url> [--user-id=<id>]`
|
|
12
|
+
- 带 `--agent <name>` 时写入指定 agent 的配置段并安装 hooks + skill
|
|
13
|
+
- 不带 `--agent` 时写入 `agents.default` 配置段(仅 CLI 使用)
|
|
14
|
+
- 连接检查:`ctxdb ping`,状态查看:`ctxdb status`
|
|
15
|
+
|
|
16
|
+
## kb search
|
|
17
|
+
|
|
18
|
+
搜索知识库。
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
ctxdb kb search "<query>" [--kb=<name1,name2>] [--top-k=N] [--threshold=F] [--verbose] [--raw] [--agent=<name>]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| 参数 | 说明 | 默认值 |
|
|
25
|
+
|------|------|--------|
|
|
26
|
+
| `<query>` | 搜索文本(必填) | |
|
|
27
|
+
| `--kb` | 指定搜索的知识库名称,逗号分隔 | 搜索所有 KB |
|
|
28
|
+
| `--top-k` | 返回 chunk 数上限 | 6 |
|
|
29
|
+
| `--threshold` | 相关度阈值 | 0.4 |
|
|
30
|
+
| `--verbose` | 每个 chunk 增加 `doc_name` / `kb_id` / `doc_id` / `tags` 字段 | false |
|
|
31
|
+
| `--raw` | 服务端原始响应(13+ 字段,含 tokenizer 细节) | false |
|
|
32
|
+
| `--agent` | 指定操作哪个 agent 的配置 | agents.default |
|
|
33
|
+
|
|
34
|
+
**输出 JSON 结构**(默认):
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"chunks": [
|
|
39
|
+
{
|
|
40
|
+
"content": "chunk 文本内容",
|
|
41
|
+
"score": 0.82
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`--verbose` 模式增加字段:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"chunks": [
|
|
52
|
+
{
|
|
53
|
+
"content": "chunk 文本内容",
|
|
54
|
+
"score": 0.82,
|
|
55
|
+
"doc_name": "zircodb-overview",
|
|
56
|
+
"kb_id": "kb-uuid",
|
|
57
|
+
"doc_id": "doc-uuid",
|
|
58
|
+
"tags": ["architecture"]
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## kb create
|
|
65
|
+
|
|
66
|
+
创建知识库。
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
ctxdb kb create <kb-name> [--description=<desc>] [--agent=<name>]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
| 参数 | 说明 |
|
|
73
|
+
|------|------|
|
|
74
|
+
| `<kb-name>` | 知识库名称(必填) |
|
|
75
|
+
| `--description` | 知识库描述 |
|
|
76
|
+
|
|
77
|
+
上传前须先创建 KB。`upload-text` / `upload-file` 不会自动创建 KB,KB 不存在时会报错。
|
|
78
|
+
|
|
79
|
+
## kb upload-file
|
|
80
|
+
|
|
81
|
+
上传本地文件到知识库。
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
ctxdb kb upload-file <kb-name> <local-path> [--doc-name=<name>] [--file-path=<server-logical-path>] [--no-wait] [--agent=<name>]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
| 参数 | 说明 |
|
|
88
|
+
|------|------|
|
|
89
|
+
| `<kb-name>` | 目标知识库名称(须已存在) |
|
|
90
|
+
| `<local-path>` | 本机文件路径 |
|
|
91
|
+
| `--doc-name` | 服务端文档名(默认取文件名) |
|
|
92
|
+
| `--file-path` | 服务端逻辑路径(归档/分类用) |
|
|
93
|
+
| `--no-wait` | 不等待 chunking 完成,立即返回 |
|
|
94
|
+
|
|
95
|
+
支持格式:PDF、DOCX、MD、TXT。
|
|
96
|
+
|
|
97
|
+
## kb upload-text
|
|
98
|
+
|
|
99
|
+
上传文本内容到知识库。
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
ctxdb kb upload-text <kb-name> <doc-name> --text="<body>" [--file-path=<server-logical-path>] [--no-wait] [--agent=<name>]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
| 参数 | 说明 |
|
|
106
|
+
|------|------|
|
|
107
|
+
| `<kb-name>` | 目标知识库名称(须已存在) |
|
|
108
|
+
| `<doc-name>` | 文档名称 |
|
|
109
|
+
| `--text` | 文本内容(必填) |
|
|
110
|
+
| `--file-path` | 服务端逻辑路径 |
|
|
111
|
+
| `--no-wait` | 不等待 chunking 完成 |
|
|
112
|
+
|
|
113
|
+
## kb list
|
|
114
|
+
|
|
115
|
+
列出所有知识库。
|
|
116
|
+
|
|
117
|
+
```sh
|
|
118
|
+
ctxdb kb list [--agent=<name>]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
返回 `knowledge_bases` 数组,每项含知识库名称、ID、文档数等。
|
|
122
|
+
|
|
123
|
+
## kb documents-list
|
|
124
|
+
|
|
125
|
+
列出知识库中的文档。
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
ctxdb kb documents-list <kb-name> [--agent=<name>]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## kb document-get
|
|
132
|
+
|
|
133
|
+
查看文档详情。
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
ctxdb kb document-get <kb-name> <doc-id> [--agent=<name>]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## 写操作注意事项
|
|
140
|
+
|
|
141
|
+
`kb create`、`kb upload-text`、`kb upload-file` 是副作用操作(创建 KB / 写入文档)。执行前须明确目标 KB 名称:
|
|
142
|
+
|
|
143
|
+
- 用户指定了 KB 名称 → 直接使用
|
|
144
|
+
- 用户未指定 → 先用 `kb list` 查看现有知识库,向用户确认目标 KB 后再操作
|
|
145
|
+
- KB 不存在时 upload 命令会自动创建,需确认用户意图是新建还是写入已有 KB
|
|
146
|
+
|
|
147
|
+
## --agent 参数
|
|
148
|
+
|
|
149
|
+
所有 kb 命令支持 `--agent <name>` 指定操作目标。知识库归属于 workspace,不同 agent 若共享同一 workspace 则访问相同的知识库。
|
|
150
|
+
|
|
151
|
+
不带 `--agent` 时的解析顺序:`CTXDB_AGENT` 环境变量 → `agents.default` 配置段。
|
|
152
|
+
|
|
153
|
+
## Hooks 感知
|
|
154
|
+
|
|
155
|
+
**KB 目录注入**:如果对话中出现 `<available-knowledge-bases>` 块,表示 hooks 已启用,该块列出可用知识库名称,可直接用于 `--kb=<name>` 参数。
|
|
156
|
+
|
|
157
|
+
**B-3c 守卫**:包含 `kb upload-text` 或 `kb upload-file` 操作的对话轮次,其内容不会被 autoCapture 写入记忆(防止文档原文混入记忆)。
|
|
158
|
+
|
|
159
|
+
如果对话中没有 `<available-knowledge-bases>`,表示当前为纯 CLI 模式,用 `kb list` 查看可用知识库。
|
|
160
|
+
|
|
161
|
+
所有命令输出 JSON 到 stdout,错误输出到 stderr 并返回非零退出码。
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: contextdb-memory
|
|
3
|
+
description: RDS contextdb 记忆操作全量参考。覆盖 memory add / search / list / get / update / delete 的完整参数、JSON 输出结构和 hooks 感知机制。当用户提到"记住"、"记一下"、"查记忆"、"删记忆"、"改记忆"、"之前说过"等场景时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# contextdb Memory 操作参考
|
|
7
|
+
|
|
8
|
+
## 配置
|
|
9
|
+
|
|
10
|
+
- 配置文件:`~/.ctxdb/ctxdb.json`
|
|
11
|
+
- 配置命令:`ctxdb setup --api-key=<key> --base-url=<url> [--user-id=<id>]`
|
|
12
|
+
- 带 `--agent <name>` 时写入指定 agent 的配置段并安装 hooks + skill
|
|
13
|
+
- 不带 `--agent` 时写入 `agents.default` 配置段(仅 CLI 使用)
|
|
14
|
+
- 连接检查:`ctxdb ping`,状态查看:`ctxdb status`
|
|
15
|
+
|
|
16
|
+
## memory add
|
|
17
|
+
|
|
18
|
+
将文本写入长期记忆。
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
ctxdb memory add "<text>" [--no-infer] [--user-id=<id>] [--metadata=K1=V1,K2=V2] [--agent=<name>]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| 参数 | 说明 |
|
|
25
|
+
|------|------|
|
|
26
|
+
| `<text>` | 要记忆的文本内容(必填) |
|
|
27
|
+
| `--no-infer` | 跳过 LLM fact-extraction,原文直存 |
|
|
28
|
+
| `--user-id` | 覆盖配置中的 user_id |
|
|
29
|
+
| `--metadata` | 附加键值对元数据,逗号分隔 |
|
|
30
|
+
| `--agent` | 指定操作哪个 agent 的记忆桶(默认使用 agents.default 配置) |
|
|
31
|
+
|
|
32
|
+
服务端默认走同步模式(`async_mode: false`),等待 LLM fact-extraction 完成后返回结果。`--no-infer` 跳过提炼,适用于需要原文保留的场景(如项目代号、精确数值)。
|
|
33
|
+
|
|
34
|
+
**输出 JSON 结构**(同步模式):
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"results": [
|
|
39
|
+
{
|
|
40
|
+
"id": "mem-uuid",
|
|
41
|
+
"memory": "提炼后的事实文本",
|
|
42
|
+
"event": "ADD"
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`event` 可能的值:`ADD`(新增)、`UPDATE`(更新已有记忆)、`NONE`(无新事实提取)。`results` 为空数组表示服务端未从输入中提取出新事实。
|
|
49
|
+
|
|
50
|
+
## memory search
|
|
51
|
+
|
|
52
|
+
搜索长期记忆。
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
ctxdb memory search "<query>" [--top-k=N] [--threshold=F] [--knowledge] [--verbose] [--raw] [--agent=<name>]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
| 参数 | 说明 | 默认值 |
|
|
59
|
+
|------|------|--------|
|
|
60
|
+
| `<query>` | 搜索文本(必填) | |
|
|
61
|
+
| `--top-k` | 返回条数上限 | 5 |
|
|
62
|
+
| `--threshold` | 相关度阈值 | 0.4 |
|
|
63
|
+
| `--knowledge` | 同时搜索知识库 chunks | false |
|
|
64
|
+
| `--verbose` | 增加 doc_name/kb_id 等字段(knowledge 模式) | false |
|
|
65
|
+
| `--raw` | 服务端原始响应 | false |
|
|
66
|
+
| `--agent` | 指定操作哪个 agent 的记忆桶 | agents.default |
|
|
67
|
+
|
|
68
|
+
**输出 JSON 结构**:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"results": [
|
|
73
|
+
{
|
|
74
|
+
"id": "mem-uuid",
|
|
75
|
+
"memory": "事实文本",
|
|
76
|
+
"score": 0.85
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`results` 为空数组表示未找到匹配记忆。
|
|
83
|
+
|
|
84
|
+
带 `--knowledge` 时额外返回 `knowledge` 数组(每项含 `content` / `score`,`--verbose` 增加 `doc_name` / `kb_id` / `doc_id` / `tags`)。
|
|
85
|
+
|
|
86
|
+
## memory list
|
|
87
|
+
|
|
88
|
+
列出记忆。
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
ctxdb memory list [--page-size=N] [--category=<cat>] [--agent=<name>]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
| 参数 | 说明 | 默认值 |
|
|
95
|
+
|------|------|--------|
|
|
96
|
+
| `--page-size` | 每页条数 | 100 |
|
|
97
|
+
| `--category` | 按分类过滤 | |
|
|
98
|
+
|
|
99
|
+
## memory get
|
|
100
|
+
|
|
101
|
+
查看单条记忆。
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
ctxdb memory get <memory-id> [--agent=<name>]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## memory update
|
|
108
|
+
|
|
109
|
+
修改记忆内容。
|
|
110
|
+
|
|
111
|
+
```sh
|
|
112
|
+
ctxdb memory update <memory-id> --text="<new-text>" [--agent=<name>]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## memory delete
|
|
116
|
+
|
|
117
|
+
删除记忆。
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
ctxdb memory delete <memory-id> [--agent=<name>]
|
|
121
|
+
ctxdb memory delete --all [--agent=<name>]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`--all` 删除当前 user_id 下的所有记忆。
|
|
125
|
+
|
|
126
|
+
## --agent 参数
|
|
127
|
+
|
|
128
|
+
所有 memory 命令支持 `--agent <name>` 指定操作目标。不同 agent 的记忆存储在各自的配置桶中(由 `~/.ctxdb/ctxdb.json` 的 `agents.<name>.user_id` 决定)。
|
|
129
|
+
|
|
130
|
+
不带 `--agent` 时的解析顺序:`CTXDB_AGENT` 环境变量 → `agents.default` 配置段。
|
|
131
|
+
|
|
132
|
+
## Hooks 感知
|
|
133
|
+
|
|
134
|
+
**autoCapture**:如果对话中出现 `<recalled-memories>` 块,表示 Stop hook 在每轮对话结束后自动提取事实写入记忆。`memory add` 在此基础上用于用户主动强调的内容(加强记忆)。
|
|
135
|
+
|
|
136
|
+
**autoRecall**:`<recalled-memories>` 块内容是 UserPromptSubmit hook 自动搜索当前 prompt 相关记忆的结果。
|
|
137
|
+
|
|
138
|
+
**B-3c 守卫**:包含 `kb upload-text` 或 `kb upload-file` 操作的对话轮次,其内容不会被 autoCapture 写入记忆(防止文档原文混入记忆)。
|
|
139
|
+
|
|
140
|
+
如果对话中没有 `<recalled-memories>`,表示当前为纯 CLI 模式,所有操作需主动调用。
|
|
141
|
+
|
|
142
|
+
所有命令输出 JSON 到 stdout,错误输出到 stderr 并返回非零退出码。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aliyunrds/ctxdb",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Unified access layer for RDS ContextDatabase: `ctxdb` CLI (memory + KB ops), one-shot `setup --agent <qoder|codex|claude>` installer, per-agent config, hooks, and SKILL.md.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"node": ">=22"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@aliyunrds/ctxdb-shared": "~0.0.
|
|
31
|
+
"@aliyunrds/ctxdb-shared": "~0.0.3"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^22.15.0",
|