@aliyunrds/ctxdb 1.0.3 → 1.0.6-beta.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/README.md +66 -14
- package/dist/{chunk-SAQT6VL6.js → chunk-6BB65W5W.js} +2 -2
- package/dist/{chunk-BVCDRUU4.js → chunk-7EIJB5LA.js} +7 -3
- package/dist/{chunk-JFTKYEVN.js → chunk-ARZX2RLR.js} +55 -7
- package/dist/{chunk-USMJLDBD.js → chunk-B7JCQL4O.js} +1 -1
- package/dist/{chunk-CWGF5D52.js → chunk-BHRWAU3E.js} +13 -6
- package/dist/{chunk-3PFMHU3C.js → chunk-L4GVGVOP.js} +4 -3
- package/dist/{chunk-Q4JYST7K.js → chunk-VHNHVMCA.js} +137 -20
- package/dist/{chunk-BQA7YSXT.js → chunk-Z6OHSEF2.js} +20 -16
- package/dist/cli/main.js +313 -89
- package/dist/hooks/hermes-post-llm-call.js +3 -3
- package/dist/hooks/hermes-pre-llm-call.js +31 -9
- package/dist/hooks/session-start.js +14 -6
- package/dist/hooks/stop.js +3 -3
- package/dist/hooks/user-prompt-submit.js +13 -6
- package/dist/opencode/index.js +657 -208
- package/dist/setup/skills/contextdb-knowledge/SKILL.md +7 -5
- package/dist/setup/skills/contextdb-memory/SKILL.md +1 -1
- package/dist/workers/version-check.js +1 -1
- package/package.json +2 -2
package/dist/cli/main.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
pollIngest,
|
|
13
13
|
uploadFile,
|
|
14
14
|
uploadText
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-L4GVGVOP.js";
|
|
16
16
|
import {
|
|
17
17
|
DEFAULT_BASE_URL,
|
|
18
18
|
DEFAULT_USER_ID,
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
agentPlatformSupport,
|
|
26
26
|
configuredAgents,
|
|
27
27
|
detectInstalledAgents,
|
|
28
|
+
hasConfiguredAgent,
|
|
28
29
|
inspectAgentHomes,
|
|
29
30
|
isAgentSlug,
|
|
30
31
|
isBuiltinAgent,
|
|
@@ -32,13 +33,14 @@ import {
|
|
|
32
33
|
load,
|
|
33
34
|
removeAgent,
|
|
34
35
|
save,
|
|
36
|
+
updateConfiguredDebug,
|
|
35
37
|
writeInstalledPkgVersion
|
|
36
|
-
} from "../chunk-
|
|
38
|
+
} from "../chunk-ARZX2RLR.js";
|
|
37
39
|
import {
|
|
38
40
|
beginUpdateNotification,
|
|
39
41
|
completeUpdateNotification,
|
|
40
42
|
runSelfUpdate
|
|
41
|
-
} from "../chunk-
|
|
43
|
+
} from "../chunk-Z6OHSEF2.js";
|
|
42
44
|
|
|
43
45
|
// src/cli/util.ts
|
|
44
46
|
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
@@ -70,8 +72,10 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
70
72
|
// kb upload-text / upload-file
|
|
71
73
|
"verbose",
|
|
72
74
|
// memory search / kb search (three-tier projection)
|
|
73
|
-
"raw"
|
|
75
|
+
"raw",
|
|
74
76
|
// kb search / memory search --knowledge (W3 compaction bypass)
|
|
77
|
+
"full"
|
|
78
|
+
// debug recall full-content human output
|
|
75
79
|
]);
|
|
76
80
|
function parseArgs(argv, booleanFlags = BOOLEAN_FLAGS) {
|
|
77
81
|
const positional = [];
|
|
@@ -127,8 +131,14 @@ var BOLD = "\x1B[1m";
|
|
|
127
131
|
var RESET = "\x1B[0m";
|
|
128
132
|
var CHECK = `${GREEN}\u2714${RESET}`;
|
|
129
133
|
var CROSS = `${RED}\u2718${RESET}`;
|
|
134
|
+
function highlightInlineCode(text, surroundingStyle = "") {
|
|
135
|
+
return text.replace(
|
|
136
|
+
/`([^`\n]+)`/g,
|
|
137
|
+
(_match, content) => `${RESET}${BOLD}${content}${RESET}${surroundingStyle}`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
130
140
|
function dim(text) {
|
|
131
|
-
return `${DIM}${text}${RESET}`;
|
|
141
|
+
return `${DIM}${highlightInlineCode(text, DIM)}${RESET}`;
|
|
132
142
|
}
|
|
133
143
|
function isSetupResult(v) {
|
|
134
144
|
if (typeof v !== "object" || v === null) return false;
|
|
@@ -153,7 +163,7 @@ function formatSetupResult(r, command = "setup") {
|
|
|
153
163
|
`);
|
|
154
164
|
for (const s of r.steps) {
|
|
155
165
|
const icon = s.ok ? CHECK : CROSS;
|
|
156
|
-
const detail = s.detail ? ` ${
|
|
166
|
+
const detail = s.detail ? ` ${dim(s.detail)}` : "";
|
|
157
167
|
lines.push(` ${icon} ${s.step}${detail}`);
|
|
158
168
|
}
|
|
159
169
|
return lines.join("\n");
|
|
@@ -168,7 +178,7 @@ function formatUpgradeResult(r) {
|
|
|
168
178
|
lines.push(` ${icon} ${BOLD}${name}${RESET}`);
|
|
169
179
|
for (const s of result.steps) {
|
|
170
180
|
const sIcon = s.ok ? CHECK : CROSS;
|
|
171
|
-
const detail = s.detail ? ` ${
|
|
181
|
+
const detail = s.detail ? ` ${dim(s.detail)}` : "";
|
|
172
182
|
lines.push(` ${sIcon} ${s.step}${detail}`);
|
|
173
183
|
}
|
|
174
184
|
}
|
|
@@ -186,16 +196,19 @@ function formatMultiAgentResult(r) {
|
|
|
186
196
|
lines.push(` ${agentOk ? CHECK : CROSS} ${BOLD}${name}${RESET}`);
|
|
187
197
|
if (r.operation === "setup") {
|
|
188
198
|
for (const step of result.steps ?? []) {
|
|
189
|
-
const detail = step.detail ? ` ${
|
|
199
|
+
const detail = step.detail ? ` ${dim(step.detail)}` : "";
|
|
190
200
|
lines.push(` ${step.ok ? CHECK : CROSS} ${step.step}${detail}`);
|
|
191
201
|
}
|
|
192
202
|
for (const hint of result.hints ?? []) {
|
|
193
|
-
lines.push(` ${DIM}hint${RESET} ${hint}`);
|
|
203
|
+
lines.push(` ${DIM}hint${RESET} ${highlightInlineCode(hint)}`);
|
|
194
204
|
}
|
|
195
205
|
continue;
|
|
196
206
|
}
|
|
197
207
|
lines.push(` ${DIM}config${RESET} ${result.ok ? "complete" : "incomplete"}`);
|
|
198
208
|
lines.push(` ${DIM}connected${RESET} ${result.connected ? "yes" : "no"}`);
|
|
209
|
+
lines.push(
|
|
210
|
+
` ${DIM}debug${RESET} ${result.debug ? "enabled" : "disabled"} (configured=${result.debug_configured ? "enabled" : "disabled"}, forced=${result.debug_forced ? "yes" : "no"}, reason=${result.debug_reason ?? "-"})`
|
|
211
|
+
);
|
|
199
212
|
if (result.hooks_node !== void 0) {
|
|
200
213
|
lines.push(` ${DIM}hooks${RESET} ${result.hooks_node}`);
|
|
201
214
|
}
|
|
@@ -227,6 +240,10 @@ function formatStatusResult(r) {
|
|
|
227
240
|
["top_k", r.top_k],
|
|
228
241
|
["threshold", r.threshold],
|
|
229
242
|
["knowledge_top_k", r.knowledge_top_k],
|
|
243
|
+
["debug", r.debug],
|
|
244
|
+
["debug_configured", r.debug_configured],
|
|
245
|
+
["debug_forced", r.debug_forced],
|
|
246
|
+
["debug_reason", r.debug_reason],
|
|
230
247
|
["connected", r.connected],
|
|
231
248
|
["version", r.version]
|
|
232
249
|
];
|
|
@@ -318,6 +335,8 @@ function skillInstallRoot(agent) {
|
|
|
318
335
|
return join(homedir(), ".qoder", "skills");
|
|
319
336
|
case "qoderwork":
|
|
320
337
|
return join(homedir(), ".qoderwork", "skills");
|
|
338
|
+
case "qwenwork":
|
|
339
|
+
return join(homedir(), ".qwenwork", "skills");
|
|
321
340
|
case "codex":
|
|
322
341
|
return join(homedir(), ".codex", "skills");
|
|
323
342
|
case "claude":
|
|
@@ -340,6 +359,8 @@ function hookConfigPath(agent) {
|
|
|
340
359
|
return join(homedir(), ".qoder", "settings.json");
|
|
341
360
|
case "qoderwork":
|
|
342
361
|
return join(homedir(), ".qoderwork", "settings.json");
|
|
362
|
+
case "qwenwork":
|
|
363
|
+
return join(homedir(), ".qwenwork", "settings.json");
|
|
343
364
|
case "codex":
|
|
344
365
|
return join(homedir(), ".codex", "hooks.json");
|
|
345
366
|
case "claude":
|
|
@@ -375,6 +396,7 @@ function checkCurrentNodeVersion() {
|
|
|
375
396
|
}
|
|
376
397
|
async function runSetup(options) {
|
|
377
398
|
const steps = [];
|
|
399
|
+
let existingAgentHomes = [];
|
|
378
400
|
if (!isAgentSlug(options.agent)) {
|
|
379
401
|
steps.push({
|
|
380
402
|
step: "validate-agent",
|
|
@@ -395,6 +417,7 @@ async function runSetup(options) {
|
|
|
395
417
|
const homeCheck = checkAgentHome(agent);
|
|
396
418
|
steps.push(homeCheck);
|
|
397
419
|
if (!homeCheck.ok) return { ok: false, steps };
|
|
420
|
+
existingAgentHomes = inspectAgentHomes(agent).existing;
|
|
398
421
|
}
|
|
399
422
|
const cfg = load({ agent });
|
|
400
423
|
if (options.apiKey) cfg.apiKey = options.apiKey;
|
|
@@ -423,7 +446,7 @@ async function runSetup(options) {
|
|
|
423
446
|
detail: `default: copied from ${agent}`
|
|
424
447
|
});
|
|
425
448
|
}
|
|
426
|
-
if (installSkill && isBuiltinAgent(agent)) {
|
|
449
|
+
if (installSkill && isBuiltinAgent(agent) && existingAgentHomes.includes(agentHomeDir(agent))) {
|
|
427
450
|
const installRoot = skillInstallRoot(agent);
|
|
428
451
|
for (const legacy of LEGACY_SKILL_DIRS) {
|
|
429
452
|
const legacyDir = join(installRoot, legacy);
|
|
@@ -445,6 +468,8 @@ async function runSetup(options) {
|
|
|
445
468
|
if (!skillResult.ok) return { ok: false, steps };
|
|
446
469
|
}
|
|
447
470
|
if (isBuiltinAgent(agent) && agentSupportsHooks(agent)) {
|
|
471
|
+
const primaryHome = agentHomeDir(agent);
|
|
472
|
+
const primaryHomeExists = existingAgentHomes.includes(primaryHome);
|
|
448
473
|
const hookPaths = locateHookPaths();
|
|
449
474
|
steps.push({
|
|
450
475
|
step: "locate-hooks",
|
|
@@ -460,26 +485,28 @@ async function runSetup(options) {
|
|
|
460
485
|
detail: nodeCheck.ok ? `${nodePath} (${nodeCheck.version})` : `node not executable: ${nodeCheck.error}`
|
|
461
486
|
});
|
|
462
487
|
if (!nodeCheck.ok) return { ok: false, steps };
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
488
|
+
if (primaryHomeExists) {
|
|
489
|
+
try {
|
|
490
|
+
backupSettingsJson(agent);
|
|
491
|
+
steps.push({ step: "backup-settings", ok: true });
|
|
492
|
+
const removed = stripCtxdbHooks(agent);
|
|
493
|
+
if (removed > 0) {
|
|
494
|
+
steps.push({
|
|
495
|
+
step: "clean-legacy-hooks",
|
|
496
|
+
ok: true,
|
|
497
|
+
detail: `removed ${removed} existing entries`
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
appendHooks(agent, hookPaths);
|
|
501
|
+
steps.push({ step: "append-hooks", ok: true });
|
|
502
|
+
} catch (err) {
|
|
468
503
|
steps.push({
|
|
469
|
-
step: "
|
|
470
|
-
ok:
|
|
471
|
-
detail:
|
|
504
|
+
step: "settings-update",
|
|
505
|
+
ok: false,
|
|
506
|
+
detail: err?.message ?? String(err)
|
|
472
507
|
});
|
|
508
|
+
return { ok: false, steps };
|
|
473
509
|
}
|
|
474
|
-
appendHooks(agent, hookPaths);
|
|
475
|
-
steps.push({ step: "append-hooks", ok: true });
|
|
476
|
-
} catch (err) {
|
|
477
|
-
steps.push({
|
|
478
|
-
step: "settings-update",
|
|
479
|
-
ok: false,
|
|
480
|
-
detail: err?.message ?? String(err)
|
|
481
|
-
});
|
|
482
|
-
return { ok: false, steps };
|
|
483
510
|
}
|
|
484
511
|
try {
|
|
485
512
|
chmodSync(hookPaths.userPromptSubmit, 493);
|
|
@@ -499,8 +526,7 @@ async function runSetup(options) {
|
|
|
499
526
|
if (agent === "codex") {
|
|
500
527
|
steps.push(enableCodexHooksFeature());
|
|
501
528
|
}
|
|
502
|
-
const
|
|
503
|
-
const variantHomes = agentHomeDirs(agent).filter((d) => d !== primaryHome && existsSync(d));
|
|
529
|
+
const variantHomes = existingAgentHomes.filter((d) => d !== primaryHome);
|
|
504
530
|
for (const vHome of variantHomes) {
|
|
505
531
|
const tag = vHome.split("/").pop() ?? vHome;
|
|
506
532
|
if (installSkill) {
|
|
@@ -1093,42 +1119,49 @@ function checkHookNodePaths(agent) {
|
|
|
1093
1119
|
nodeOk: true,
|
|
1094
1120
|
detail: "no hooks installed"
|
|
1095
1121
|
};
|
|
1096
|
-
const
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
} catch {
|
|
1102
|
-
return empty;
|
|
1103
|
-
}
|
|
1104
|
-
if (!data?.hooks || typeof data.hooks !== "object") return empty;
|
|
1122
|
+
const primaryHome = agentHomeDir(agent);
|
|
1123
|
+
const primaryPath = hookConfigPath(agent);
|
|
1124
|
+
const configPaths = agentHomeDirs(agent).filter((home) => existsSync(home)).map((home) => home === primaryHome ? primaryPath : join(home, "settings.json")).filter((path) => path !== null && existsSync(path));
|
|
1125
|
+
if (configPaths.length === 0) return empty;
|
|
1126
|
+
let foundHooksObject = false;
|
|
1105
1127
|
const nodePaths = /* @__PURE__ */ new Set();
|
|
1106
|
-
for (const
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1128
|
+
for (const configPath of configPaths) {
|
|
1129
|
+
let data;
|
|
1130
|
+
try {
|
|
1131
|
+
data = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
1132
|
+
} catch {
|
|
1133
|
+
continue;
|
|
1134
|
+
}
|
|
1135
|
+
if (!data?.hooks || typeof data.hooks !== "object") continue;
|
|
1136
|
+
foundHooksObject = true;
|
|
1137
|
+
for (const event of HOOK_EVENTS) {
|
|
1138
|
+
const entries = data.hooks[event];
|
|
1139
|
+
if (!Array.isArray(entries)) continue;
|
|
1140
|
+
for (const entry of entries) {
|
|
1141
|
+
if (!entryIsCtxdb(entry)) continue;
|
|
1142
|
+
for (const h of entry.hooks ?? []) {
|
|
1143
|
+
if (h?.type !== "command" || typeof h.command !== "string") continue;
|
|
1144
|
+
if (Array.isArray(h.args) && h.args.length > 0) {
|
|
1145
|
+
nodePaths.add(h.command);
|
|
1121
1146
|
} else {
|
|
1122
|
-
const
|
|
1123
|
-
|
|
1124
|
-
|
|
1147
|
+
const cmd = h.command;
|
|
1148
|
+
let nodePath;
|
|
1149
|
+
if (cmd.startsWith('"')) {
|
|
1150
|
+
const closeQuote = cmd.indexOf('"', 1);
|
|
1151
|
+
if (closeQuote > 1) nodePath = cmd.slice(1, closeQuote);
|
|
1152
|
+
} else {
|
|
1153
|
+
const parts = cmd.split(" ");
|
|
1154
|
+
if (parts.length >= 2 && !parts[0].endsWith(".js") && !parts[0].endsWith(".ts") && (parts[0].includes("/") || parts[0].includes("\\"))) {
|
|
1155
|
+
nodePath = parts[0];
|
|
1156
|
+
}
|
|
1125
1157
|
}
|
|
1158
|
+
if (nodePath) nodePaths.add(nodePath);
|
|
1126
1159
|
}
|
|
1127
|
-
if (nodePath) nodePaths.add(nodePath);
|
|
1128
1160
|
}
|
|
1129
1161
|
}
|
|
1130
1162
|
}
|
|
1131
1163
|
}
|
|
1164
|
+
if (!foundHooksObject) return empty;
|
|
1132
1165
|
if (nodePaths.size === 0) {
|
|
1133
1166
|
return { installed: true, nodePaths: [], nodeOk: true, detail: "hooks use shebang (no explicit node path)" };
|
|
1134
1167
|
}
|
|
@@ -1360,6 +1393,8 @@ var SKILL_INSTALL_TARGETS = {
|
|
|
1360
1393
|
qodercn: join(homedir(), ".qoder-cn", "skills"),
|
|
1361
1394
|
qoderwork: join(homedir(), ".qoderwork", "skills"),
|
|
1362
1395
|
qoderworkcn: join(homedir(), ".qoderworkcn", "skills"),
|
|
1396
|
+
qwenwork: join(homedir(), ".qwenwork", "skills"),
|
|
1397
|
+
qwenworkcn: join(homedir(), ".qwenworkcn", "skills"),
|
|
1363
1398
|
codex: join(homedir(), ".codex", "skills"),
|
|
1364
1399
|
claude: join(homedir(), ".claude", "skills"),
|
|
1365
1400
|
opencode: join(homedir(), ".config", "opencode", "skills"),
|
|
@@ -1518,7 +1553,7 @@ function hermesAllowlistPath() {
|
|
|
1518
1553
|
return join(dirname(hermesConfigPath()), HERMES_ALLOWLIST_FILENAME);
|
|
1519
1554
|
}
|
|
1520
1555
|
function hermesHookApprovalHint(events = HERMES_HOOK_EVENTS) {
|
|
1521
|
-
const hookNames = events.
|
|
1556
|
+
const hookNames = events.join(" and ");
|
|
1522
1557
|
return `Approve the Hermes ctxdb hooks ${hookNames}: run \`hermes --accept-hooks chat\` once. This command opens an interactive chat; after Hermes starts, exit the chat, rerun \`ctxdb setup --agent hermes\`, then restart any running Hermes CLI or gateway process.`;
|
|
1523
1558
|
}
|
|
1524
1559
|
function backupHermesConfig() {
|
|
@@ -1971,7 +2006,7 @@ async function runUpgrade(options = {}) {
|
|
|
1971
2006
|
var STATUS_HELP = `ctxdb status \u2014 inspect configuration and connectivity
|
|
1972
2007
|
|
|
1973
2008
|
USAGE
|
|
1974
|
-
ctxdb status [--agent <qoder|qoderwork|codex|claude|opencode|hermes|default> | --all] [--json]
|
|
2009
|
+
ctxdb status [--agent <qoder|qoderwork|qwenwork|codex|claude|opencode|hermes|default> | --all] [--json]
|
|
1975
2010
|
|
|
1976
2011
|
FLAGS
|
|
1977
2012
|
--agent <name> Inspect exactly one Agent profile
|
|
@@ -2005,6 +2040,10 @@ async function inspectStatus(agent) {
|
|
|
2005
2040
|
top_k: cfg.topK,
|
|
2006
2041
|
threshold: cfg.threshold,
|
|
2007
2042
|
knowledge_top_k: cfg.knowledgeTopK,
|
|
2043
|
+
debug: cfg.debug,
|
|
2044
|
+
debug_configured: cfg.debugConfigured,
|
|
2045
|
+
debug_forced: cfg.debugForced,
|
|
2046
|
+
debug_reason: cfg.debugReason,
|
|
2008
2047
|
connected,
|
|
2009
2048
|
ping_error: pingError,
|
|
2010
2049
|
hooks_node: hookHealth.detail,
|
|
@@ -2093,7 +2132,7 @@ async function ping(args) {
|
|
|
2093
2132
|
var HELP = `ctxdb setup \u2014 configure an agent
|
|
2094
2133
|
|
|
2095
2134
|
USAGE
|
|
2096
|
-
ctxdb setup [--agent <qoder|qoderwork|codex|claude|opencode|hermes> | --all]
|
|
2135
|
+
ctxdb setup [--agent <qoder|qoderwork|qwenwork|codex|claude|opencode|hermes> | --all]
|
|
2097
2136
|
[--api-key=K] [--base-url=URL] [--user-id=ID]
|
|
2098
2137
|
[--no-install-skill] [--no-validate] [--json]
|
|
2099
2138
|
|
|
@@ -2114,7 +2153,7 @@ BEHAVIOR
|
|
|
2114
2153
|
any running Hermes CLI/gateway process to load the hooks.
|
|
2115
2154
|
|
|
2116
2155
|
FLAGS
|
|
2117
|
-
--agent <name> Target agent (qoder|qoderwork|codex|claude|opencode|hermes)
|
|
2156
|
+
--agent <name> Target agent (qoder|qoderwork|qwenwork|codex|claude|opencode|hermes)
|
|
2118
2157
|
--all Target every setup-compatible detected Agent
|
|
2119
2158
|
--api-key <key> API key (required on first setup)
|
|
2120
2159
|
--base-url <url> Server URL (default: https://context-database.aliyuncs.com)
|
|
@@ -2124,9 +2163,27 @@ FLAGS
|
|
|
2124
2163
|
--json Machine-readable JSON output
|
|
2125
2164
|
`;
|
|
2126
2165
|
var CODEX_HOOKS_TRUST_REMINDER = [
|
|
2127
|
-
"codex hooks \u914D\u7F6E\u540E\uFF0C\u9700\u8981\u91CD\u542F Codex \u5BF9\u8BDD\uFF0C\u5728\u5F39\u51FA\u7684 hooks \u786E\u8BA4\u754C\u9762\u9009\u62E9
|
|
2128
|
-
"\u5982\u679C\u4F7F\u7528\u7684\u662F Codex App \u684C\u9762\u7248\uFF0C\u64CD\u4F5C\u8DEF\u5F84\u662F\uFF1A\u5DE6\u4E0B\u89D2\u70B9\u51FB\u7528\u6237\u540D \u2192 \u70B9\u51FB\u8BBE\u7F6E \u2192 \u70B9\u51FB\u4FA7\u8FB9\u680F\u7684 Hooks\uFF08\u94A9\u5B50\uFF09
|
|
2166
|
+
"codex hooks \u914D\u7F6E\u540E\uFF0C\u9700\u8981\u91CD\u542F Codex \u5BF9\u8BDD\uFF0C\u5728\u5F39\u51FA\u7684 hooks \u786E\u8BA4\u754C\u9762\u9009\u62E9`\u63A5\u6536\u6240\u6709 hooks(\u94A9\u5B50)`\u9009\u9879\u3002",
|
|
2167
|
+
"\u5982\u679C\u4F7F\u7528\u7684\u662F Codex App \u684C\u9762\u7248\uFF0C\u64CD\u4F5C\u8DEF\u5F84\u662F\uFF1A\u5DE6\u4E0B\u89D2\u70B9\u51FB\u7528\u6237\u540D \u2192 \u70B9\u51FB\u8BBE\u7F6E \u2192 \u70B9\u51FB\u4FA7\u8FB9\u680F\u7684 `Hooks\uFF08\u94A9\u5B50\uFF09`\u2192 \u70B9\u51FB`\u7528\u6237\u914D\u7F6E`\uFF0C\u4FE1\u4EFB `UserPromptSubmit`\u3001`SessionStart` \u548C `Stop` \u91CC\u7684 `aliyunrds/ctxdb` \u94A9\u5B50\u3002"
|
|
2129
2168
|
].join("\n");
|
|
2169
|
+
var FULL_APP_RESTART_REMINDERS = {
|
|
2170
|
+
qoder: "Next action: \u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u65B0\u542F\u52A8 Qoder\uFF08\u4E0D\u662F\u53EA\u5173\u95ED\u5F53\u524D\u5BF9\u8BDD\uFF09\uFF0C\u4F7F\u65B0\u7684 hooks \u548C skill \u751F\u6548\u3002",
|
|
2171
|
+
qoderwork: "Next action: \u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u65B0\u542F\u52A8 QoderWork\uFF08\u4E0D\u662F\u53EA\u5173\u95ED\u5F53\u524D\u5BF9\u8BDD\uFF09\uFF0C\u4F7F\u65B0\u7684 hooks \u548C skill \u751F\u6548\u3002",
|
|
2172
|
+
qwenwork: "Next action: \u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u65B0\u542F\u52A8 QwenWork\uFF08\u4E0D\u662F\u53EA\u5173\u95ED\u5F53\u524D\u5BF9\u8BDD\uFF09\uFF0C\u4F7F\u65B0\u7684 hooks \u548C skill \u751F\u6548\u3002"
|
|
2173
|
+
};
|
|
2174
|
+
function printPostSetupReminder(agent) {
|
|
2175
|
+
const restartReminder = FULL_APP_RESTART_REMINDERS[agent];
|
|
2176
|
+
if (restartReminder) {
|
|
2177
|
+
process.stderr.write(`
|
|
2178
|
+
${dim(restartReminder)}
|
|
2179
|
+
`);
|
|
2180
|
+
}
|
|
2181
|
+
if (agent === "codex") {
|
|
2182
|
+
process.stderr.write(`
|
|
2183
|
+
${dim(CODEX_HOOKS_TRUST_REMINDER)}
|
|
2184
|
+
`);
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2130
2187
|
function parseAgent(args) {
|
|
2131
2188
|
const raw = args.flags.agent;
|
|
2132
2189
|
if (raw === void 0) return "default";
|
|
@@ -2158,23 +2215,25 @@ async function setup(args) {
|
|
|
2158
2215
|
});
|
|
2159
2216
|
printResult(result2, json);
|
|
2160
2217
|
if (!json && result2.hints) {
|
|
2161
|
-
for (const hint of result2.hints)
|
|
2162
|
-
|
|
2218
|
+
for (const hint of result2.hints) {
|
|
2219
|
+
process.stderr.write(`
|
|
2220
|
+
${highlightInlineCode(hint)}
|
|
2163
2221
|
`);
|
|
2222
|
+
}
|
|
2164
2223
|
}
|
|
2165
|
-
if (!json
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2224
|
+
if (!json) {
|
|
2225
|
+
for (const agent2 of ["qoder", "qoderwork", "qwenwork", "codex"]) {
|
|
2226
|
+
if (result2.agents[agent2]?.ok) {
|
|
2227
|
+
printPostSetupReminder(agent2);
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2171
2230
|
}
|
|
2172
2231
|
return result2.ok ? 0 : 1;
|
|
2173
2232
|
}
|
|
2174
2233
|
const agent = parseAgent(args);
|
|
2175
2234
|
if (agent === "default" && !json && !configuredAgents().includes("default")) {
|
|
2176
2235
|
process.stderr.write(
|
|
2177
|
-
`hint: creating CLI-only "default" agent (no hooks/skills). Use --agent <claude|qoder|qoderwork|codex|opencode|hermes> for full setup.
|
|
2236
|
+
`hint: creating CLI-only "default" agent (no hooks/skills). Use --agent <claude|qoder|qoderwork|qwenwork|codex|opencode|hermes> for full setup.
|
|
2178
2237
|
`
|
|
2179
2238
|
);
|
|
2180
2239
|
}
|
|
@@ -2188,16 +2247,14 @@ ${dim(CODEX_HOOKS_TRUST_REMINDER)}
|
|
|
2188
2247
|
});
|
|
2189
2248
|
printResult(result, json);
|
|
2190
2249
|
if (!json && result.hints) {
|
|
2191
|
-
for (const h of result.hints)
|
|
2192
|
-
|
|
2250
|
+
for (const h of result.hints) {
|
|
2251
|
+
process.stderr.write(`
|
|
2252
|
+
${highlightInlineCode(h)}
|
|
2193
2253
|
`);
|
|
2254
|
+
}
|
|
2194
2255
|
}
|
|
2195
|
-
if (!json &&
|
|
2196
|
-
|
|
2197
|
-
`
|
|
2198
|
-
${dim(CODEX_HOOKS_TRUST_REMINDER)}
|
|
2199
|
-
`
|
|
2200
|
-
);
|
|
2256
|
+
if (!json && result.ok) {
|
|
2257
|
+
printPostSetupReminder(agent);
|
|
2201
2258
|
}
|
|
2202
2259
|
return result.ok ? 0 : 1;
|
|
2203
2260
|
}
|
|
@@ -2206,11 +2263,11 @@ ${dim(CODEX_HOOKS_TRUST_REMINDER)}
|
|
|
2206
2263
|
var HELP2 = `ctxdb uninstall \u2014 remove hooks + skills
|
|
2207
2264
|
|
|
2208
2265
|
USAGE
|
|
2209
|
-
ctxdb uninstall [--agent <qoder|qoderwork|codex|claude|opencode|hermes>] [--purge-config] [--purge-logs] [--purge-all] [--json]
|
|
2266
|
+
ctxdb uninstall [--agent <qoder|qoderwork|qwenwork|codex|claude|opencode|hermes>] [--purge-config] [--purge-logs] [--purge-all] [--json]
|
|
2210
2267
|
|
|
2211
2268
|
DEFAULT BEHAVIOR (no --agent, no purge flags)
|
|
2212
2269
|
Strips ctxdb hook entries and skill directories for ALL agents (qoder,
|
|
2213
|
-
qoderwork, codex, claude, opencode, hermes). Keeps ~/.ctxdb/ctxdb.json (credentials) and ~/.ctxdb/logs/
|
|
2270
|
+
qoderwork, qwenwork, codex, claude, opencode, hermes). Keeps ~/.ctxdb/ctxdb.json (credentials) and ~/.ctxdb/logs/
|
|
2214
2271
|
so you can re-run \`ctxdb setup\` later without losing configuration.
|
|
2215
2272
|
|
|
2216
2273
|
WITH --agent <name>
|
|
@@ -2218,7 +2275,7 @@ WITH --agent <name>
|
|
|
2218
2275
|
Other agents remain untouched.
|
|
2219
2276
|
|
|
2220
2277
|
FLAGS
|
|
2221
|
-
--agent <name> Target a single agent (qoder|qoderwork|codex|claude|opencode|hermes)
|
|
2278
|
+
--agent <name> Target a single agent (qoder|qoderwork|qwenwork|codex|claude|opencode|hermes)
|
|
2222
2279
|
--purge-config Also delete ~/.ctxdb/ctxdb.json
|
|
2223
2280
|
--purge-logs Also delete ~/.ctxdb/logs/
|
|
2224
2281
|
--purge-all Delete everything under ~/.ctxdb/
|
|
@@ -2270,7 +2327,7 @@ ${h}
|
|
|
2270
2327
|
var HELP3 = `ctxdb upgrade \u2014 refresh skills + hooks
|
|
2271
2328
|
|
|
2272
2329
|
USAGE
|
|
2273
|
-
ctxdb upgrade [--agent <qoder|qoderwork|codex|claude|opencode|hermes>] [--no-self-update] [--json]
|
|
2330
|
+
ctxdb upgrade [--agent <qoder|qoderwork|qwenwork|codex|claude|opencode|hermes>] [--no-self-update] [--json]
|
|
2274
2331
|
|
|
2275
2332
|
BEHAVIOR
|
|
2276
2333
|
Pulls the latest @aliyunrds/ctxdb package from npm, then re-runs setup
|
|
@@ -2280,7 +2337,7 @@ BEHAVIOR
|
|
|
2280
2337
|
With --agent: sets up only the specified agent.
|
|
2281
2338
|
|
|
2282
2339
|
FLAGS
|
|
2283
|
-
--agent <name> Target a single agent (qoder|qoderwork|codex|claude|opencode|hermes)
|
|
2340
|
+
--agent <name> Target a single agent (qoder|qoderwork|qwenwork|codex|claude|opencode|hermes)
|
|
2284
2341
|
--self-update Pull latest package from npm (enabled by default)
|
|
2285
2342
|
--no-self-update Skip the npm package update and only re-run setup
|
|
2286
2343
|
--json Machine-readable JSON output
|
|
@@ -2408,7 +2465,8 @@ function skillInstall(args) {
|
|
|
2408
2465
|
}
|
|
2409
2466
|
const TARGET_TEMPLATE_AGENT = {
|
|
2410
2467
|
qodercn: "qoder",
|
|
2411
|
-
qoderworkcn: "qoderwork"
|
|
2468
|
+
qoderworkcn: "qoderwork",
|
|
2469
|
+
qwenworkcn: "qwenwork"
|
|
2412
2470
|
};
|
|
2413
2471
|
const templateAgent = TARGET_TEMPLATE_AGENT[target] ?? (target && isBuiltinAgent(target) ? target : "default");
|
|
2414
2472
|
const result = installSkillsTo(targetRoot, templateAgent);
|
|
@@ -2670,6 +2728,163 @@ async function kbSearch(args) {
|
|
|
2670
2728
|
return 0;
|
|
2671
2729
|
}
|
|
2672
2730
|
|
|
2731
|
+
// src/cli/debug-cli.ts
|
|
2732
|
+
import {
|
|
2733
|
+
readRecallTraces
|
|
2734
|
+
} from "@aliyunrds/ctxdb-shared";
|
|
2735
|
+
var CONTROL_HELP = `ctxdb debug enable|disable \u2014 control local recall tracing
|
|
2736
|
+
|
|
2737
|
+
USAGE
|
|
2738
|
+
ctxdb debug enable [--agent=<name>] [--json]
|
|
2739
|
+
ctxdb debug disable [--agent=<name>] [--json]
|
|
2740
|
+
|
|
2741
|
+
Debug is forced on when the final CTXDB base URL is not the official
|
|
2742
|
+
production URL. A forced profile cannot be disabled until its endpoint changes.
|
|
2743
|
+
`;
|
|
2744
|
+
var RECALL_HELP = `ctxdb debug recall \u2014 replay local recall traces
|
|
2745
|
+
|
|
2746
|
+
USAGE
|
|
2747
|
+
ctxdb debug recall (--session=<id> | --event=<id>) [--full] [--json]
|
|
2748
|
+
|
|
2749
|
+
Reads ~/.ctxdb/logs/recall-trace.jsonl and its rotated generations.
|
|
2750
|
+
An unmatched recall.start means the hook was interrupted or terminated before
|
|
2751
|
+
recall.finish; it is not a completed timeout outcome.
|
|
2752
|
+
`;
|
|
2753
|
+
function resultFor(agent, changed) {
|
|
2754
|
+
const cfg = load({ agent });
|
|
2755
|
+
return {
|
|
2756
|
+
ok: true,
|
|
2757
|
+
agent,
|
|
2758
|
+
debug: cfg.debug,
|
|
2759
|
+
debug_configured: cfg.debugConfigured,
|
|
2760
|
+
debug_forced: cfg.debugForced,
|
|
2761
|
+
debug_reason: cfg.debugReason,
|
|
2762
|
+
changed
|
|
2763
|
+
};
|
|
2764
|
+
}
|
|
2765
|
+
function printControlResult(result, json) {
|
|
2766
|
+
if (json) {
|
|
2767
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
2768
|
+
`);
|
|
2769
|
+
return;
|
|
2770
|
+
}
|
|
2771
|
+
const configured = result.debug_configured ? "enabled" : "disabled";
|
|
2772
|
+
const effective = result.debug ? "enabled" : "disabled";
|
|
2773
|
+
const forced = result.debug_forced ? "yes" : "no";
|
|
2774
|
+
process.stdout.write(
|
|
2775
|
+
`ctxdb debug (${result.agent}): ${effective}
|
|
2776
|
+
configured: ${configured}
|
|
2777
|
+
forced: ${forced}
|
|
2778
|
+
reason: ${result.debug_reason ?? "-"}
|
|
2779
|
+
`
|
|
2780
|
+
);
|
|
2781
|
+
}
|
|
2782
|
+
async function controlDebug(args, configured) {
|
|
2783
|
+
if (args.flags.help || args.flags.h) {
|
|
2784
|
+
process.stdout.write(CONTROL_HELP);
|
|
2785
|
+
return 0;
|
|
2786
|
+
}
|
|
2787
|
+
const agent = agentFromFlags(args.flags);
|
|
2788
|
+
const current = load({ agent });
|
|
2789
|
+
if (!hasConfiguredAgent(agent)) {
|
|
2790
|
+
const hint = agent === "default" ? "run `ctxdb setup --api-key=<key>` or select a configured --agent" : `run \`ctxdb setup --agent ${agent}\` first`;
|
|
2791
|
+
process.stderr.write(`no configured profile for agent ${agent}; ${hint}
|
|
2792
|
+
`);
|
|
2793
|
+
return 1;
|
|
2794
|
+
}
|
|
2795
|
+
if (!configured && current.debugForced) {
|
|
2796
|
+
const result2 = {
|
|
2797
|
+
ok: false,
|
|
2798
|
+
agent,
|
|
2799
|
+
debug: current.debug,
|
|
2800
|
+
debug_configured: current.debugConfigured,
|
|
2801
|
+
debug_forced: current.debugForced,
|
|
2802
|
+
debug_reason: current.debugReason,
|
|
2803
|
+
changed: false
|
|
2804
|
+
};
|
|
2805
|
+
if (args.flags.json) {
|
|
2806
|
+
process.stdout.write(`${JSON.stringify(result2, null, 2)}
|
|
2807
|
+
`);
|
|
2808
|
+
} else {
|
|
2809
|
+
process.stderr.write(
|
|
2810
|
+
`cannot disable debug for ${agent}: debug is forced by non-production base_url (reason: ${current.debugReason})
|
|
2811
|
+
`
|
|
2812
|
+
);
|
|
2813
|
+
printControlResult(result2, false);
|
|
2814
|
+
}
|
|
2815
|
+
return 1;
|
|
2816
|
+
}
|
|
2817
|
+
const changed = current.debugConfigured !== configured;
|
|
2818
|
+
if (!updateConfiguredDebug(agent, configured)) {
|
|
2819
|
+
process.stderr.write(`failed to update debug for agent ${agent}
|
|
2820
|
+
`);
|
|
2821
|
+
return 1;
|
|
2822
|
+
}
|
|
2823
|
+
const result = resultFor(agent, changed);
|
|
2824
|
+
printControlResult(result, Boolean(args.flags.json));
|
|
2825
|
+
return 0;
|
|
2826
|
+
}
|
|
2827
|
+
function debugEnable(args) {
|
|
2828
|
+
return controlDebug(args, true);
|
|
2829
|
+
}
|
|
2830
|
+
function debugDisable(args) {
|
|
2831
|
+
return controlDebug(args, false);
|
|
2832
|
+
}
|
|
2833
|
+
function compactRecord(record) {
|
|
2834
|
+
const base = `${record.timestamp} ${record.agent}/${record.kind} ${record.type} event=${record.recall_event_id} session=${record.session_id ?? "-"}`;
|
|
2835
|
+
if (record.type === "recall.start") {
|
|
2836
|
+
return `${base} query_chars=${record.query.length}`;
|
|
2837
|
+
}
|
|
2838
|
+
return `${base} outcome=${record.outcome} duration_ms=${record.duration_ms} returned=${record.returned_memories.length} selected=${record.selection.selected.length} knowledge=${record.returned_knowledge.length}`;
|
|
2839
|
+
}
|
|
2840
|
+
async function debugRecall(args) {
|
|
2841
|
+
if (args.flags.help || args.flags.h) {
|
|
2842
|
+
process.stdout.write(RECALL_HELP);
|
|
2843
|
+
return 0;
|
|
2844
|
+
}
|
|
2845
|
+
const session = typeof args.flags.session === "string" && args.flags.session ? args.flags.session : null;
|
|
2846
|
+
const event = typeof args.flags.event === "string" && args.flags.event ? args.flags.event : null;
|
|
2847
|
+
if (session && event || !session && !event) {
|
|
2848
|
+
process.stderr.write(
|
|
2849
|
+
"exactly one of --session=<id> or --event=<id> is required\n"
|
|
2850
|
+
);
|
|
2851
|
+
return 2;
|
|
2852
|
+
}
|
|
2853
|
+
const result = readRecallTraces({
|
|
2854
|
+
...session ? { sessionId: session } : { recallEventId: event }
|
|
2855
|
+
});
|
|
2856
|
+
const output = {
|
|
2857
|
+
ok: true,
|
|
2858
|
+
selector: session ? { session } : { event },
|
|
2859
|
+
count: result.records.length,
|
|
2860
|
+
malformed_lines: result.malformedLines,
|
|
2861
|
+
records: result.records
|
|
2862
|
+
};
|
|
2863
|
+
if (args.flags.json) {
|
|
2864
|
+
process.stdout.write(`${JSON.stringify(output, null, 2)}
|
|
2865
|
+
`);
|
|
2866
|
+
return 0;
|
|
2867
|
+
}
|
|
2868
|
+
if (result.records.length === 0) {
|
|
2869
|
+
process.stdout.write("No matching recall traces.\n");
|
|
2870
|
+
return 0;
|
|
2871
|
+
}
|
|
2872
|
+
if (args.flags.full) {
|
|
2873
|
+
process.stdout.write(`${JSON.stringify(result.records, null, 2)}
|
|
2874
|
+
`);
|
|
2875
|
+
} else {
|
|
2876
|
+
process.stdout.write(`${result.records.map(compactRecord).join("\n")}
|
|
2877
|
+
`);
|
|
2878
|
+
}
|
|
2879
|
+
if (result.malformedLines > 0) {
|
|
2880
|
+
process.stderr.write(
|
|
2881
|
+
`skipped ${result.malformedLines} malformed recall trace line(s)
|
|
2882
|
+
`
|
|
2883
|
+
);
|
|
2884
|
+
}
|
|
2885
|
+
return 0;
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2673
2888
|
// src/cli/main.ts
|
|
2674
2889
|
var HELP5 = `ctxdb v${PACKAGE_VERSION} \u2014 RDS ContextDatabase CLI (multi-agent)
|
|
2675
2890
|
|
|
@@ -2677,7 +2892,7 @@ USAGE
|
|
|
2677
2892
|
ctxdb <command> [args] [--flags]
|
|
2678
2893
|
|
|
2679
2894
|
COMMANDS
|
|
2680
|
-
setup [--agent <qoder|qoderwork|codex|claude|opencode|hermes> | --all]
|
|
2895
|
+
setup [--agent <qoder|qoderwork|qwenwork|codex|claude|opencode|hermes> | --all]
|
|
2681
2896
|
[--api-key=K] [--base-url=URL] [--user-id=ID]
|
|
2682
2897
|
[--no-install-skill] [--no-validate] [--json]
|
|
2683
2898
|
Without --agent \u2192 writes agents.default (CLI-only, no hooks/skills)
|
|
@@ -2706,6 +2921,10 @@ COMMANDS
|
|
|
2706
2921
|
upgrade|update [--agent <name>] [--no-self-update] [--json]
|
|
2707
2922
|
Pull latest package from npm, then re-run
|
|
2708
2923
|
setup. Self-update is enabled by default.
|
|
2924
|
+
debug enable|disable [--agent <name>] [--json]
|
|
2925
|
+
Control configured debug for an existing profile.
|
|
2926
|
+
debug recall (--session=<id> | --event=<id>) [--full] [--json]
|
|
2927
|
+
Replay local full-fidelity recall traces.
|
|
2709
2928
|
|
|
2710
2929
|
memory add <text> [--agent=<name>] [--user-id=...] [--metadata=K1=V1,K2=V2] [--no-infer]
|
|
2711
2930
|
memory search <query> [--agent=<name>] [--top-k=10] [--threshold=0.4] [--knowledge]
|
|
@@ -2740,7 +2959,7 @@ COMMANDS
|
|
|
2740
2959
|
doc_id?/tags? for citation.
|
|
2741
2960
|
--raw: server response verbatim (curl parity).
|
|
2742
2961
|
|
|
2743
|
-
skill install --target <qoder|qoderwork|codex|claude|opencode|openclaw|hermes> [--json]
|
|
2962
|
+
skill install --target <qoder|qoderwork|qwenwork|codex|claude|opencode|openclaw|hermes> [--json]
|
|
2744
2963
|
skill install --path <dir> [--json]
|
|
2745
2964
|
Install skill files (contextdb-memory,
|
|
2746
2965
|
contextdb-knowledge) to an agent's skill directory.
|
|
@@ -2763,7 +2982,7 @@ HOOK ENV VARS:
|
|
|
2763
2982
|
Direct ctxdb CLI commands are unchanged.
|
|
2764
2983
|
|
|
2765
2984
|
CONFIG: ~/.ctxdb/ctxdb.json (agents.default / agents.qoder / agents.qoderwork / agents.codex / agents.claude / agents.opencode / agents.hermes)
|
|
2766
|
-
LOGS: ~/.ctxdb/logs/ctxdb.log
|
|
2985
|
+
LOGS: ~/.ctxdb/logs/ctxdb.log, ~/.ctxdb/logs/recall-trace.jsonl
|
|
2767
2986
|
`;
|
|
2768
2987
|
var ROUTES = {
|
|
2769
2988
|
setup,
|
|
@@ -2773,6 +2992,11 @@ var ROUTES = {
|
|
|
2773
2992
|
teardown: uninstall,
|
|
2774
2993
|
upgrade,
|
|
2775
2994
|
update: upgrade,
|
|
2995
|
+
debug: {
|
|
2996
|
+
enable: debugEnable,
|
|
2997
|
+
disable: debugDisable,
|
|
2998
|
+
recall: debugRecall
|
|
2999
|
+
},
|
|
2776
3000
|
skill: {
|
|
2777
3001
|
install: skillInstall
|
|
2778
3002
|
},
|