@aliyunrds/ctxdb 1.0.4 → 1.0.6

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/dist/cli/main.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  pollIngest,
13
13
  uploadFile,
14
14
  uploadText
15
- } from "../chunk-3PFMHU3C.js";
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-JFTKYEVN.js";
38
+ } from "../chunk-ARZX2RLR.js";
37
39
  import {
38
40
  beginUpdateNotification,
39
41
  completeUpdateNotification,
40
42
  runSelfUpdate
41
- } from "../chunk-BQA7YSXT.js";
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 = [];
@@ -202,6 +206,9 @@ function formatMultiAgentResult(r) {
202
206
  }
203
207
  lines.push(` ${DIM}config${RESET} ${result.ok ? "complete" : "incomplete"}`);
204
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
+ );
205
212
  if (result.hooks_node !== void 0) {
206
213
  lines.push(` ${DIM}hooks${RESET} ${result.hooks_node}`);
207
214
  }
@@ -233,6 +240,10 @@ function formatStatusResult(r) {
233
240
  ["top_k", r.top_k],
234
241
  ["threshold", r.threshold],
235
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],
236
247
  ["connected", r.connected],
237
248
  ["version", r.version]
238
249
  ];
@@ -324,6 +335,8 @@ function skillInstallRoot(agent) {
324
335
  return join(homedir(), ".qoder", "skills");
325
336
  case "qoderwork":
326
337
  return join(homedir(), ".qoderwork", "skills");
338
+ case "qwenwork":
339
+ return join(homedir(), ".qwenwork", "skills");
327
340
  case "codex":
328
341
  return join(homedir(), ".codex", "skills");
329
342
  case "claude":
@@ -346,6 +359,8 @@ function hookConfigPath(agent) {
346
359
  return join(homedir(), ".qoder", "settings.json");
347
360
  case "qoderwork":
348
361
  return join(homedir(), ".qoderwork", "settings.json");
362
+ case "qwenwork":
363
+ return join(homedir(), ".qwenwork", "settings.json");
349
364
  case "codex":
350
365
  return join(homedir(), ".codex", "hooks.json");
351
366
  case "claude":
@@ -381,6 +396,7 @@ function checkCurrentNodeVersion() {
381
396
  }
382
397
  async function runSetup(options) {
383
398
  const steps = [];
399
+ let existingAgentHomes = [];
384
400
  if (!isAgentSlug(options.agent)) {
385
401
  steps.push({
386
402
  step: "validate-agent",
@@ -401,6 +417,7 @@ async function runSetup(options) {
401
417
  const homeCheck = checkAgentHome(agent);
402
418
  steps.push(homeCheck);
403
419
  if (!homeCheck.ok) return { ok: false, steps };
420
+ existingAgentHomes = inspectAgentHomes(agent).existing;
404
421
  }
405
422
  const cfg = load({ agent });
406
423
  if (options.apiKey) cfg.apiKey = options.apiKey;
@@ -429,7 +446,7 @@ async function runSetup(options) {
429
446
  detail: `default: copied from ${agent}`
430
447
  });
431
448
  }
432
- if (installSkill && isBuiltinAgent(agent)) {
449
+ if (installSkill && isBuiltinAgent(agent) && existingAgentHomes.includes(agentHomeDir(agent))) {
433
450
  const installRoot = skillInstallRoot(agent);
434
451
  for (const legacy of LEGACY_SKILL_DIRS) {
435
452
  const legacyDir = join(installRoot, legacy);
@@ -451,6 +468,8 @@ async function runSetup(options) {
451
468
  if (!skillResult.ok) return { ok: false, steps };
452
469
  }
453
470
  if (isBuiltinAgent(agent) && agentSupportsHooks(agent)) {
471
+ const primaryHome = agentHomeDir(agent);
472
+ const primaryHomeExists = existingAgentHomes.includes(primaryHome);
454
473
  const hookPaths = locateHookPaths();
455
474
  steps.push({
456
475
  step: "locate-hooks",
@@ -466,26 +485,28 @@ async function runSetup(options) {
466
485
  detail: nodeCheck.ok ? `${nodePath} (${nodeCheck.version})` : `node not executable: ${nodeCheck.error}`
467
486
  });
468
487
  if (!nodeCheck.ok) return { ok: false, steps };
469
- try {
470
- backupSettingsJson(agent);
471
- steps.push({ step: "backup-settings", ok: true });
472
- const removed = stripCtxdbHooks(agent);
473
- if (removed > 0) {
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) {
474
503
  steps.push({
475
- step: "clean-legacy-hooks",
476
- ok: true,
477
- detail: `removed ${removed} existing entries`
504
+ step: "settings-update",
505
+ ok: false,
506
+ detail: err?.message ?? String(err)
478
507
  });
508
+ return { ok: false, steps };
479
509
  }
480
- appendHooks(agent, hookPaths);
481
- steps.push({ step: "append-hooks", ok: true });
482
- } catch (err) {
483
- steps.push({
484
- step: "settings-update",
485
- ok: false,
486
- detail: err?.message ?? String(err)
487
- });
488
- return { ok: false, steps };
489
510
  }
490
511
  try {
491
512
  chmodSync(hookPaths.userPromptSubmit, 493);
@@ -505,8 +526,7 @@ async function runSetup(options) {
505
526
  if (agent === "codex") {
506
527
  steps.push(enableCodexHooksFeature());
507
528
  }
508
- const primaryHome = agentHomeDir(agent);
509
- const variantHomes = agentHomeDirs(agent).filter((d) => d !== primaryHome && existsSync(d));
529
+ const variantHomes = existingAgentHomes.filter((d) => d !== primaryHome);
510
530
  for (const vHome of variantHomes) {
511
531
  const tag = vHome.split("/").pop() ?? vHome;
512
532
  if (installSkill) {
@@ -1099,42 +1119,49 @@ function checkHookNodePaths(agent) {
1099
1119
  nodeOk: true,
1100
1120
  detail: "no hooks installed"
1101
1121
  };
1102
- const path = hookConfigPath(agent);
1103
- if (!path || !existsSync(path)) return empty;
1104
- let data;
1105
- try {
1106
- data = JSON.parse(readFileSync(path, "utf-8"));
1107
- } catch {
1108
- return empty;
1109
- }
1110
- 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;
1111
1127
  const nodePaths = /* @__PURE__ */ new Set();
1112
- for (const event of HOOK_EVENTS) {
1113
- const entries = data.hooks[event];
1114
- if (!Array.isArray(entries)) continue;
1115
- for (const entry of entries) {
1116
- if (!entryIsCtxdb(entry)) continue;
1117
- for (const h of entry.hooks ?? []) {
1118
- if (h?.type !== "command" || typeof h.command !== "string") continue;
1119
- if (Array.isArray(h.args) && h.args.length > 0) {
1120
- nodePaths.add(h.command);
1121
- } else {
1122
- const cmd = h.command;
1123
- let nodePath;
1124
- if (cmd.startsWith('"')) {
1125
- const closeQuote = cmd.indexOf('"', 1);
1126
- if (closeQuote > 1) nodePath = cmd.slice(1, closeQuote);
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);
1127
1146
  } else {
1128
- const parts = cmd.split(" ");
1129
- if (parts.length >= 2 && !parts[0].endsWith(".js") && !parts[0].endsWith(".ts") && (parts[0].includes("/") || parts[0].includes("\\"))) {
1130
- nodePath = parts[0];
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
+ }
1131
1157
  }
1158
+ if (nodePath) nodePaths.add(nodePath);
1132
1159
  }
1133
- if (nodePath) nodePaths.add(nodePath);
1134
1160
  }
1135
1161
  }
1136
1162
  }
1137
1163
  }
1164
+ if (!foundHooksObject) return empty;
1138
1165
  if (nodePaths.size === 0) {
1139
1166
  return { installed: true, nodePaths: [], nodeOk: true, detail: "hooks use shebang (no explicit node path)" };
1140
1167
  }
@@ -1366,6 +1393,8 @@ var SKILL_INSTALL_TARGETS = {
1366
1393
  qodercn: join(homedir(), ".qoder-cn", "skills"),
1367
1394
  qoderwork: join(homedir(), ".qoderwork", "skills"),
1368
1395
  qoderworkcn: join(homedir(), ".qoderworkcn", "skills"),
1396
+ qwenwork: join(homedir(), ".qwenwork", "skills"),
1397
+ qwenworkcn: join(homedir(), ".qwenworkcn", "skills"),
1369
1398
  codex: join(homedir(), ".codex", "skills"),
1370
1399
  claude: join(homedir(), ".claude", "skills"),
1371
1400
  opencode: join(homedir(), ".config", "opencode", "skills"),
@@ -1977,7 +2006,7 @@ async function runUpgrade(options = {}) {
1977
2006
  var STATUS_HELP = `ctxdb status \u2014 inspect configuration and connectivity
1978
2007
 
1979
2008
  USAGE
1980
- 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]
1981
2010
 
1982
2011
  FLAGS
1983
2012
  --agent <name> Inspect exactly one Agent profile
@@ -2011,6 +2040,10 @@ async function inspectStatus(agent) {
2011
2040
  top_k: cfg.topK,
2012
2041
  threshold: cfg.threshold,
2013
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,
2014
2047
  connected,
2015
2048
  ping_error: pingError,
2016
2049
  hooks_node: hookHealth.detail,
@@ -2099,7 +2132,7 @@ async function ping(args) {
2099
2132
  var HELP = `ctxdb setup \u2014 configure an agent
2100
2133
 
2101
2134
  USAGE
2102
- ctxdb setup [--agent <qoder|qoderwork|codex|claude|opencode|hermes> | --all]
2135
+ ctxdb setup [--agent <qoder|qoderwork|qwenwork|codex|claude|opencode|hermes> | --all]
2103
2136
  [--api-key=K] [--base-url=URL] [--user-id=ID]
2104
2137
  [--no-install-skill] [--no-validate] [--json]
2105
2138
 
@@ -2120,7 +2153,7 @@ BEHAVIOR
2120
2153
  any running Hermes CLI/gateway process to load the hooks.
2121
2154
 
2122
2155
  FLAGS
2123
- --agent <name> Target agent (qoder|qoderwork|codex|claude|opencode|hermes)
2156
+ --agent <name> Target agent (qoder|qoderwork|qwenwork|codex|claude|opencode|hermes)
2124
2157
  --all Target every setup-compatible detected Agent
2125
2158
  --api-key <key> API key (required on first setup)
2126
2159
  --base-url <url> Server URL (default: https://context-database.aliyuncs.com)
@@ -2133,6 +2166,24 @@ var CODEX_HOOKS_TRUST_REMINDER = [
2133
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",
2134
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"
2135
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
+ }
2136
2187
  function parseAgent(args) {
2137
2188
  const raw = args.flags.agent;
2138
2189
  if (raw === void 0) return "default";
@@ -2170,19 +2221,19 @@ ${highlightInlineCode(hint)}
2170
2221
  `);
2171
2222
  }
2172
2223
  }
2173
- if (!json && result2.agents.codex?.ok) {
2174
- process.stderr.write(
2175
- `
2176
- ${dim(CODEX_HOOKS_TRUST_REMINDER)}
2177
- `
2178
- );
2224
+ if (!json) {
2225
+ for (const agent2 of ["qoder", "qoderwork", "qwenwork", "codex"]) {
2226
+ if (result2.agents[agent2]?.ok) {
2227
+ printPostSetupReminder(agent2);
2228
+ }
2229
+ }
2179
2230
  }
2180
2231
  return result2.ok ? 0 : 1;
2181
2232
  }
2182
2233
  const agent = parseAgent(args);
2183
2234
  if (agent === "default" && !json && !configuredAgents().includes("default")) {
2184
2235
  process.stderr.write(
2185
- `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.
2186
2237
  `
2187
2238
  );
2188
2239
  }
@@ -2202,12 +2253,8 @@ ${highlightInlineCode(h)}
2202
2253
  `);
2203
2254
  }
2204
2255
  }
2205
- if (!json && agent === "codex" && result.ok) {
2206
- process.stderr.write(
2207
- `
2208
- ${dim(CODEX_HOOKS_TRUST_REMINDER)}
2209
- `
2210
- );
2256
+ if (!json && result.ok) {
2257
+ printPostSetupReminder(agent);
2211
2258
  }
2212
2259
  return result.ok ? 0 : 1;
2213
2260
  }
@@ -2216,11 +2263,11 @@ ${dim(CODEX_HOOKS_TRUST_REMINDER)}
2216
2263
  var HELP2 = `ctxdb uninstall \u2014 remove hooks + skills
2217
2264
 
2218
2265
  USAGE
2219
- 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]
2220
2267
 
2221
2268
  DEFAULT BEHAVIOR (no --agent, no purge flags)
2222
2269
  Strips ctxdb hook entries and skill directories for ALL agents (qoder,
2223
- 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/
2224
2271
  so you can re-run \`ctxdb setup\` later without losing configuration.
2225
2272
 
2226
2273
  WITH --agent <name>
@@ -2228,7 +2275,7 @@ WITH --agent <name>
2228
2275
  Other agents remain untouched.
2229
2276
 
2230
2277
  FLAGS
2231
- --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)
2232
2279
  --purge-config Also delete ~/.ctxdb/ctxdb.json
2233
2280
  --purge-logs Also delete ~/.ctxdb/logs/
2234
2281
  --purge-all Delete everything under ~/.ctxdb/
@@ -2280,7 +2327,7 @@ ${h}
2280
2327
  var HELP3 = `ctxdb upgrade \u2014 refresh skills + hooks
2281
2328
 
2282
2329
  USAGE
2283
- 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]
2284
2331
 
2285
2332
  BEHAVIOR
2286
2333
  Pulls the latest @aliyunrds/ctxdb package from npm, then re-runs setup
@@ -2290,7 +2337,7 @@ BEHAVIOR
2290
2337
  With --agent: sets up only the specified agent.
2291
2338
 
2292
2339
  FLAGS
2293
- --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)
2294
2341
  --self-update Pull latest package from npm (enabled by default)
2295
2342
  --no-self-update Skip the npm package update and only re-run setup
2296
2343
  --json Machine-readable JSON output
@@ -2418,7 +2465,8 @@ function skillInstall(args) {
2418
2465
  }
2419
2466
  const TARGET_TEMPLATE_AGENT = {
2420
2467
  qodercn: "qoder",
2421
- qoderworkcn: "qoderwork"
2468
+ qoderworkcn: "qoderwork",
2469
+ qwenworkcn: "qwenwork"
2422
2470
  };
2423
2471
  const templateAgent = TARGET_TEMPLATE_AGENT[target] ?? (target && isBuiltinAgent(target) ? target : "default");
2424
2472
  const result = installSkillsTo(targetRoot, templateAgent);
@@ -2680,6 +2728,163 @@ async function kbSearch(args) {
2680
2728
  return 0;
2681
2729
  }
2682
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
+
2683
2888
  // src/cli/main.ts
2684
2889
  var HELP5 = `ctxdb v${PACKAGE_VERSION} \u2014 RDS ContextDatabase CLI (multi-agent)
2685
2890
 
@@ -2687,7 +2892,7 @@ USAGE
2687
2892
  ctxdb <command> [args] [--flags]
2688
2893
 
2689
2894
  COMMANDS
2690
- setup [--agent <qoder|qoderwork|codex|claude|opencode|hermes> | --all]
2895
+ setup [--agent <qoder|qoderwork|qwenwork|codex|claude|opencode|hermes> | --all]
2691
2896
  [--api-key=K] [--base-url=URL] [--user-id=ID]
2692
2897
  [--no-install-skill] [--no-validate] [--json]
2693
2898
  Without --agent \u2192 writes agents.default (CLI-only, no hooks/skills)
@@ -2716,6 +2921,10 @@ COMMANDS
2716
2921
  upgrade|update [--agent <name>] [--no-self-update] [--json]
2717
2922
  Pull latest package from npm, then re-run
2718
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.
2719
2928
 
2720
2929
  memory add <text> [--agent=<name>] [--user-id=...] [--metadata=K1=V1,K2=V2] [--no-infer]
2721
2930
  memory search <query> [--agent=<name>] [--top-k=10] [--threshold=0.4] [--knowledge]
@@ -2750,7 +2959,7 @@ COMMANDS
2750
2959
  doc_id?/tags? for citation.
2751
2960
  --raw: server response verbatim (curl parity).
2752
2961
 
2753
- skill install --target <qoder|qoderwork|codex|claude|opencode|openclaw|hermes> [--json]
2962
+ skill install --target <qoder|qoderwork|qwenwork|codex|claude|opencode|openclaw|hermes> [--json]
2754
2963
  skill install --path <dir> [--json]
2755
2964
  Install skill files (contextdb-memory,
2756
2965
  contextdb-knowledge) to an agent's skill directory.
@@ -2773,7 +2982,7 @@ HOOK ENV VARS:
2773
2982
  Direct ctxdb CLI commands are unchanged.
2774
2983
 
2775
2984
  CONFIG: ~/.ctxdb/ctxdb.json (agents.default / agents.qoder / agents.qoderwork / agents.codex / agents.claude / agents.opencode / agents.hermes)
2776
- LOGS: ~/.ctxdb/logs/ctxdb.log
2985
+ LOGS: ~/.ctxdb/logs/ctxdb.log, ~/.ctxdb/logs/recall-trace.jsonl
2777
2986
  `;
2778
2987
  var ROUTES = {
2779
2988
  setup,
@@ -2783,6 +2992,11 @@ var ROUTES = {
2783
2992
  teardown: uninstall,
2784
2993
  upgrade,
2785
2994
  update: upgrade,
2995
+ debug: {
2996
+ enable: debugEnable,
2997
+ disable: debugDisable,
2998
+ recall: debugRecall
2999
+ },
2786
3000
  skill: {
2787
3001
  install: skillInstall
2788
3002
  },
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  captureParsedMessages
4
- } from "../chunk-SAQT6VL6.js";
5
- import "../chunk-USMJLDBD.js";
4
+ } from "../chunk-6BB65W5W.js";
5
+ import "../chunk-B7JCQL4O.js";
6
6
  import {
7
7
  HttpClient,
8
8
  agentFromArgvWithFallback,
9
9
  debug,
10
10
  load,
11
11
  setDebug
12
- } from "../chunk-JFTKYEVN.js";
12
+ } from "../chunk-ARZX2RLR.js";
13
13
  import {
14
14
  shouldSkipHooks
15
15
  } from "../chunk-UEKR2Z3S.js";