@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/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 +291 -77
- 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/README.md
CHANGED
|
@@ -6,12 +6,13 @@ Unified access layer for RDS ContextDatabase. One `ctxdb` CLI (memory + KB ops),
|
|
|
6
6
|
|---|---|---|---|
|
|
7
7
|
| **qoder** | ✅ UserPromptSubmit + Stop + SessionStart | `~/.qoder/skills/ctxdb/` | hooks-driven (auto capture/recall) |
|
|
8
8
|
| **qoderwork** | ✅ UserPromptSubmit + Stop + SessionStart | `~/.qoderwork/skills/ctxdb/` | hooks-driven (auto capture/recall) |
|
|
9
|
+
| **qwenwork** | ✅ UserPromptSubmit + Stop + SessionStart | `~/.qwenwork/skills/ctxdb/` | hooks-driven (auto capture/recall) |
|
|
9
10
|
| **codex** | ✅ UserPromptSubmit + Stop + SessionStart | `~/.codex/skills/ctxdb/` | hooks-driven (auto capture/recall) |
|
|
10
11
|
| **claude** | ✅ UserPromptSubmit + Stop + SessionStart | `~/.claude/skills/ctxdb/` | hooks-driven (auto capture/recall) |
|
|
11
12
|
| **opencode** | Plugin shim (`~/.config/opencode/plugins/ctxdb.ts`) | `~/.config/opencode/skills/` | in-process plugin (auto capture/recall + KB catalog injection) |
|
|
12
13
|
| **hermes** | ✅ `pre_llm_call` + `post_llm_call` | `~/.hermes/skills/` | shell hooks (auto capture/recall + first-turn warmup) |
|
|
13
14
|
|
|
14
|
-
Config and logs live under `~/.ctxdb/`. `~/.ctxdb/ctxdb.json` is one file, but runtime config is isolated per agent under `agents.qoder`, `agents.qoderwork`, `agents.codex`, `agents.claude`, `agents.opencode`, and `agents.hermes`. (Pre-2026-05-23 installs used `~/.ctxdb.json` at the home root; running `ctxdb setup --agent <name>` migrates the file into the selected agent section.)
|
|
15
|
+
Config and logs live under `~/.ctxdb/`. `~/.ctxdb/ctxdb.json` is one file, but runtime config is isolated per agent under `agents.qoder`, `agents.qoderwork`, `agents.qwenwork`, `agents.codex`, `agents.claude`, `agents.opencode`, and `agents.hermes`. (Pre-2026-05-23 installs used `~/.ctxdb.json` at the home root; running `ctxdb setup --agent <name>` migrates the file into the selected agent section.)
|
|
15
16
|
|
|
16
17
|
## Install
|
|
17
18
|
|
|
@@ -103,6 +104,8 @@ npm install -g @aliyunrds/ctxdb
|
|
|
103
104
|
ctxdb setup --agent qoder --api-key ctxdb-...
|
|
104
105
|
# QoderWork (hooks + skill)
|
|
105
106
|
ctxdb setup --agent qoderwork --api-key ctxdb-...
|
|
107
|
+
# QwenWork (hooks + skill)
|
|
108
|
+
ctxdb setup --agent qwenwork --api-key ctxdb-...
|
|
106
109
|
# Codex (hooks + skill)
|
|
107
110
|
ctxdb setup --agent codex --api-key ctxdb-...
|
|
108
111
|
# Claude Code (hooks + skill)
|
|
@@ -161,9 +164,9 @@ ctxdb setup --agent codex --api-key 'ctxdb-new-...'
|
|
|
161
164
|
ctxdb status --agent codex --json
|
|
162
165
|
```
|
|
163
166
|
|
|
164
|
-
Setup first checks that the target agent home exists (`~/.qoder`, `~/.qoderwork`, `~/.codex`, or `~/.claude
|
|
167
|
+
Setup first checks that the target agent home exists (`~/.qoder`, `~/.qoderwork`, `~/.qwenwork`, `~/.codex`, or `~/.claude`; the declared CN variant home also satisfies this check). Setup writes hooks and skills only into homes that already exist, so a CN-only install does not create the international product home, and vice versa. If no home exists, install or start that agent once before running `ctxdb setup --agent <name>`. OpenCode and Hermes are config-dir style: setup creates `~/.config/opencode` / `~/.hermes` when they are missing.
|
|
165
168
|
|
|
166
|
-
For **qoder**, **qoderwork**, **codex**, and **claude**, restart the harness (CLI: just exit + restart; app: Cmd+R or quit/relaunch) so it picks up the new hooks/skill. For **codex**, setup also writes `[features].hooks = true` into `~/.codex/config.toml` (creating the file if missing) — Codex won't fire any hook entries without it. On first use Codex may prompt you to trust the new hook commands. For **opencode**, restart OpenCode so it loads `~/.config/opencode/plugins/ctxdb.ts`. For **hermes**, setup also checks `~/.hermes/shell-hooks-allowlist.json`; it reports setup as incomplete until both ctxdb hook commands are approved.
|
|
169
|
+
For **qoder**, **qoderwork**, **qwenwork**, **codex**, and **claude**, restart the harness (CLI: just exit + restart; app: Cmd+R or quit/relaunch) so it picks up the new hooks/skill. For **codex**, setup also writes `[features].hooks = true` into `~/.codex/config.toml` (creating the file if missing) — Codex won't fire any hook entries without it. On first use Codex may prompt you to trust the new hook commands. For **opencode**, restart OpenCode so it loads `~/.config/opencode/plugins/ctxdb.ts`. For **hermes**, setup also checks `~/.hermes/shell-hooks-allowlist.json`; it reports setup as incomplete until both ctxdb hook commands are approved.
|
|
167
170
|
|
|
168
171
|
Hermes owns this security allowlist, so ctxdb only checks it and never writes approvals. Approve the ctxdb `pre_llm_call` and `post_llm_call` hooks with:
|
|
169
172
|
|
|
@@ -189,15 +192,15 @@ ctxdb update --agent codex
|
|
|
189
192
|
ctxdb update --no-self-update
|
|
190
193
|
```
|
|
191
194
|
|
|
192
|
-
For npm-installed copies, eligible
|
|
195
|
+
For npm-installed copies, eligible direct `ctxdb` commands use a detached version check regardless of whether stderr is a TTY or an Agent-routing flag is present. Checks run on a best-effort daily interval after either a recorded success or failure, so Agent shell tools can receive update information without following a specific invocation shape. The command never waits for npm: a newly discovered release can be shown only on a later invocation. A successful command may append this informational hint to stderr:
|
|
193
196
|
|
|
194
197
|
```text
|
|
195
|
-
ctxdb: update available v1.0.2 → v1.1.0;
|
|
198
|
+
ctxdb: update available v1.0.2 → v1.1.0; update with `ctxdb update` (informational only; do not run automatically).
|
|
196
199
|
```
|
|
197
200
|
|
|
198
|
-
|
|
201
|
+
Hints use a best-effort global three-day quiet period, so a higher target version does not bypass a recent reminder. Explicit `--json`, CI, `ctxdb update` / `ctxdb upgrade`, and non-npm layouts remain silent. Non-JSON automation may receive the advisory stderr line; use `--json` when a single machine-readable document is required, or set `CTXDB_DISABLE_UPDATE_CHECK=1` to opt out completely. Concurrent commands may rarely duplicate an advisory hint; the notifier does not add locking to the requested command path.
|
|
199
202
|
|
|
200
|
-
The notifier only reads/writes `~/.ctxdb/cache/version-check.json`; it never installs a package or changes agent setup. Updating remains an explicit `ctxdb update` action.
|
|
203
|
+
The notifier only reads/writes `~/.ctxdb/cache/version-check.json`; it never installs a package or changes agent setup. Updating remains an explicit `ctxdb update` action for the Agent or user to choose after seeing the hint.
|
|
201
204
|
|
|
202
205
|
The existing `--self-update` flag remains accepted for compatibility, but is no longer required. If the npm version check, global install, or setup pass fails, ctxdb prints the manual recovery commands:
|
|
203
206
|
|
|
@@ -208,7 +211,7 @@ ctxdb setup
|
|
|
208
211
|
|
|
209
212
|
## What it does
|
|
210
213
|
|
|
211
|
-
For **qoder**, **qoderwork**, **codex**, and **claude**, hooks fire automatically:
|
|
214
|
+
For **qoder**, **qoderwork**, **qwenwork**, **codex**, and **claude**, hooks fire automatically:
|
|
212
215
|
|
|
213
216
|
| Trigger | Hook | What runs |
|
|
214
217
|
|---|---|---|
|
|
@@ -230,13 +233,60 @@ For **hermes**, `ctxdb setup --agent hermes` writes two shell hooks under `~/.he
|
|
|
230
233
|
|
|
231
234
|
`ctxdb` ships grouped non-interactive commands:
|
|
232
235
|
|
|
233
|
-
- **Top-level**: `setup` / `status` / `ping` / `uninstall` / `update` (`upgrade` alias)
|
|
236
|
+
- **Top-level**: `setup` / `status` / `ping` / `debug` / `uninstall` / `update` (`upgrade` alias)
|
|
234
237
|
- **Memory**: `memory add|search|list|get|update|delete`
|
|
235
238
|
- **KB**: `kb upload-text|upload-file|list|documents-list|document-get|search`
|
|
236
239
|
|
|
237
240
|
See `ctxdb --help`.
|
|
238
241
|
|
|
239
|
-
|
|
242
|
+
### Debug control and recall replay
|
|
243
|
+
|
|
244
|
+
Debug is configured per existing Agent profile without editing JSON manually:
|
|
245
|
+
|
|
246
|
+
```sh
|
|
247
|
+
ctxdb debug enable --agent=codex
|
|
248
|
+
ctxdb debug disable --agent=codex
|
|
249
|
+
ctxdb debug recall --session=<host-session-id>
|
|
250
|
+
ctxdb debug recall --event=<recall-event-id> --full
|
|
251
|
+
ctxdb debug recall --event=<recall-event-id> --json
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Agent resolution follows the rest of the CLI: explicit `--agent`, then
|
|
255
|
+
`CTXDB_AGENT`, then `agents.default`. Enable/disable is local-only: it updates
|
|
256
|
+
only `agents.<name>.debug`, makes no network request, and does not reinstall
|
|
257
|
+
hooks, plugins, or skills. It requires that profile to already exist.
|
|
258
|
+
|
|
259
|
+
The only official-production URL currently allowlisted is exactly
|
|
260
|
+
`https://context-database.aliyuncs.com` (a trailing slash is equivalent).
|
|
261
|
+
Policy is evaluated after profile/default inheritance and `CTXDB_BASE_URL`.
|
|
262
|
+
Any other complete URL—including pre-production domains, numeric IPs,
|
|
263
|
+
localhost, HTTP, alternate ports or paths—and any invalid URL forces effective
|
|
264
|
+
debug on. `ctxdb debug disable` then fails without modifying the profile. The
|
|
265
|
+
stored preference is kept separately, so returning to the allowlisted URL
|
|
266
|
+
restores it. `ctxdb status` reports `debug` (effective), `debug_configured`,
|
|
267
|
+
`debug_forced`, and `debug_reason` (`non_production_base_url` when forced).
|
|
268
|
+
|
|
269
|
+
Effective debug writes full-fidelity recall records for qoder, qoderwork,
|
|
270
|
+
qwenwork, codex, claude, opencode, and hermes to
|
|
271
|
+
`~/.ctxdb/logs/recall-trace.jsonl`. The trace contains the complete query,
|
|
272
|
+
complete returned memory/KB candidates, local selected/excluded outcome, and
|
|
273
|
+
the exact context injected into the model. **This can contain sensitive project
|
|
274
|
+
or customer text.** The file is local-only, created with mode `0600`, rotated
|
|
275
|
+
at 10 MiB, and retains at most five rotated generations. API keys,
|
|
276
|
+
Authorization headers, full config objects, and unrelated HTTP bodies are not
|
|
277
|
+
recorded. Trace I/O is fail-open and cannot block a hook.
|
|
278
|
+
|
|
279
|
+
Each attempt has a `recall_event_id`; all attempts in one host conversation
|
|
280
|
+
carry its local `session_id`. This is distinct from the service `run_id`:
|
|
281
|
+
capture continues sending the host session as `run_id`, while automatic recall
|
|
282
|
+
never sends `run_id` because doing so would narrow long-term retrieval to one
|
|
283
|
+
session. A `recall.start` without a matching `recall.finish` means the hook was
|
|
284
|
+
interrupted or terminated before it could record a completed outcome; it must
|
|
285
|
+
not be interpreted as a completed `timeout`. Disabling debug stops future
|
|
286
|
+
writes but leaves existing trace files available for replay; `ctxdb uninstall
|
|
287
|
+
--purge-logs` removes them.
|
|
288
|
+
|
|
289
|
+
`setup` without `--agent` writes `agents.default` in `~/.ctxdb/ctxdb.json` (CLI-only, no hooks or skills); with `--agent <qoder|qoderwork|qwenwork|codex|claude|opencode|hermes>` it writes agent config and installs hooks/plugins + skills for that harness. Rerunning it repairs integration artifacts and may replace the selected Agent's API key. Memory and KB commands also accept `--agent <name>` so agents use their own config section; when omitted, `CTXDB_AGENT` env wins, otherwise `agents.default` is used. `uninstall` without `--agent` loops every supported agent; with `--agent <name>` it targets just that one. `teardown` is an alias for `uninstall`.
|
|
240
290
|
|
|
241
291
|
`memory add … --no-infer` stores the text verbatim (skips server-side LLM
|
|
242
292
|
fact-extraction). Use it when the user explicitly asks for a verbatim
|
|
@@ -338,6 +388,7 @@ Lives at `~/.ctxdb/ctxdb.json` (co-located with logs at `~/.ctxdb/logs/`). Schem
|
|
|
338
388
|
"debug": false
|
|
339
389
|
},
|
|
340
390
|
"qoderwork": { "...": "same schema, independent values" },
|
|
391
|
+
"qwenwork": { "...": "same schema, independent values" },
|
|
341
392
|
"codex": { "...": "same schema, independent values" },
|
|
342
393
|
"claude": { "...": "same schema, independent values" },
|
|
343
394
|
"opencode": { "...": "same schema, independent values" },
|
|
@@ -346,7 +397,7 @@ Lives at `~/.ctxdb/ctxdb.json` (co-located with logs at `~/.ctxdb/logs/`). Schem
|
|
|
346
397
|
}
|
|
347
398
|
```
|
|
348
399
|
|
|
349
|
-
Agent selection is driven by `--agent <qoder|qoderwork|codex|claude|opencode|hermes|default>` on every CLI invocation, falling back to `CTXDB_AGENT` env, then to `default`. There is no `default_agent` field — older installs that have one written get it dropped on the next save.
|
|
400
|
+
Agent selection is driven by `--agent <qoder|qoderwork|qwenwork|codex|claude|opencode|hermes|default>` on every CLI invocation, falling back to `CTXDB_AGENT` env, then to `default`. There is no `default_agent` field — older installs that have one written get it dropped on the next save.
|
|
350
401
|
|
|
351
402
|
Field reference:
|
|
352
403
|
|
|
@@ -361,13 +412,13 @@ Field reference:
|
|
|
361
412
|
| `recall_knowledge` | bool | `false` | When `auto_recall` is on, also pull KB chunks alongside memory. Default is **off** — the recommended KB-recall path is the agent calling `kb search --agent <name>` explicitly when the user asks |
|
|
362
413
|
| `top_k` / `threshold` | int / float | `5` / `0.4` | Memory recall pagination + similarity floor. `5` keeps the codex TUI `hook context: ...` line short enough to scan and bounds token spend on the modal recall path; raise it per-agent if you want more candidates |
|
|
363
414
|
| `knowledge_top_k` | int | `6` | KB chunks pulled per recall (only effective when `recall_knowledge: true`) |
|
|
364
|
-
| `debug` | bool | `false` |
|
|
415
|
+
| `debug` | bool | `false` | Configured preference for verbose hook logging and full recall tracing. Effective debug is forced on for every final `base_url` outside the exact official-production allowlist; see “Debug control and recall replay”. General logs go to `~/.ctxdb/logs/ctxdb.log`, structured full-content recall records to `~/.ctxdb/logs/recall-trace.jsonl` |
|
|
365
416
|
|
|
366
417
|
Env-var overrides apply to the selected agent config (env wins): `CTXDB_AGENT` / `CTXDB_API_KEY` / `CTXDB_BASE_URL` / `CTXDB_USER_ID` / `CTXDB_AGENT_ID` / `CTXDB_APP_ID`. The last two default to unset — the request body omits `agent_id`/`app_id` entirely; set them only when you want per-agent / per-app scope isolation on the server.
|
|
367
418
|
|
|
368
419
|
Hook/plugin escape hatch: set `CTXDB_SKIP_HOOKS=TRUE` on the agent process to make all ctxdb hook entrypoints exit immediately before reading config or calling the API. Direct `ctxdb memory` / `ctxdb kb` / `ctxdb setup` CLI commands are unchanged.
|
|
369
420
|
|
|
370
|
-
`run_id` is **not** env-driven: capture reads the host's session id from the lifecycle payload (Qoder / Codex / Claude Code and Hermes pass `session_id`; opencode reads `ev.properties.sessionID`) and sends it as `run_id` on capture only, so the server can associate turns within one session for richer extraction context. Recall never sends `run_id`. If the payload has no session id, `run_id`
|
|
421
|
+
`run_id` is **not** env-driven: capture reads the host's session id from the lifecycle payload (Qoder / Codex / Claude Code and Hermes pass `session_id`; opencode reads `ev.properties.sessionID`) and sends it as `run_id` on capture only, so the server can associate turns within one session for richer extraction context. Recall stores that host value locally as trace `session_id` but never sends `run_id`. If the payload has no session id, trace replay remains possible by `recall_event_id`; capture omits `run_id` and proceeds normally (the server falls back to baseMessages).
|
|
371
422
|
|
|
372
423
|
## Architecture
|
|
373
424
|
|
|
@@ -410,6 +461,7 @@ After step 1, `ctxdb uninstall` prints the exact `npm uninstall` command to run
|
|
|
410
461
|
# first-time install path cleanly.
|
|
411
462
|
ctxdb uninstall --agent qoder
|
|
412
463
|
ctxdb uninstall --agent qoderwork
|
|
464
|
+
ctxdb uninstall --agent qwenwork
|
|
413
465
|
ctxdb uninstall --agent codex
|
|
414
466
|
ctxdb uninstall --agent claude
|
|
415
467
|
ctxdb uninstall --agent opencode
|
|
@@ -423,7 +475,7 @@ ctxdb uninstall --purge-logs # also deletes ~/.ctxdb/logs/
|
|
|
423
475
|
|
|
424
476
|
### What uninstall does (and doesn't) touch
|
|
425
477
|
|
|
426
|
-
- **Hook entries in `~/.qoder/settings.json`, `~/.qoderwork/settings.json`, `~/.codex/hooks.json`, `~/.claude/settings.json`, and `~/.hermes/config.yaml`**: stripped precisely by marker (`_ctxdb = @aliyunrds/ctxdb`, plus legacy keys `_ctxdbQoder` / `_ctxdbPackage` and the legacy `@aliyunrds/ctxdb-qoder` value for installs predating the unified marker). Any hooks you added yourself stay. A timestamped `*.bak-ctxdb-<TS>` is written before each modification (rotation keeps the 5 most recent).
|
|
478
|
+
- **Hook entries in `~/.qoder/settings.json`, `~/.qoderwork/settings.json`, `~/.qwenwork/settings.json`, `~/.codex/hooks.json`, `~/.claude/settings.json`, and `~/.hermes/config.yaml`**: stripped precisely by marker (`_ctxdb = @aliyunrds/ctxdb`, plus legacy keys `_ctxdbQoder` / `_ctxdbPackage` and the legacy `@aliyunrds/ctxdb-qoder` value for installs predating the unified marker). Any hooks you added yourself stay. A timestamped `*.bak-ctxdb-<TS>` is written before each modification (rotation keeps the 5 most recent).
|
|
427
479
|
- **Skill directories**: `~/.<agent>/skills/ctxdb/` for each set-up agent, plus legacy dirs (`ctxdb-qoder`, `rds-ctxdb-qoder`, `qoder-ctxdb`) under `~/.qoder/skills/` from older package names.
|
|
428
480
|
- **`~/.ctxdb/` state**: only with `--purge-config` / `--purge-logs` / `--purge-all`. Defensive: `--purge-all` removes the `~/.ctxdb/` root only if it's empty after the named files are deleted (won't blanket-rm an unknown directory).
|
|
429
481
|
- **`~/.codex/config.toml` `[features].hooks`**: **NOT** reverted. Setup adds `hooks = true` so Codex will fire ctxdb's hook entries; uninstall leaves the flag alone because (a) the user may have wanted it on for non-ctxdb hooks, and (b) it's harmless when `~/.codex/hooks.json` is empty. If you want it off, edit the file by hand.
|
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
isConnectionError,
|
|
5
5
|
resetCircuit,
|
|
6
6
|
tripCircuit
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-B7JCQL4O.js";
|
|
8
8
|
import {
|
|
9
9
|
CtxdbError,
|
|
10
10
|
debug,
|
|
11
11
|
isDebug
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ARZX2RLR.js";
|
|
13
13
|
|
|
14
14
|
// src/lib/capture-orchestrator.ts
|
|
15
15
|
import {
|
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
fetchKbCatalogBlock,
|
|
4
4
|
recallTurn
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VHNHVMCA.js";
|
|
6
6
|
|
|
7
7
|
// src/lib/user-prompt-submit-compose.ts
|
|
8
|
-
async function composeUserPromptSubmit(cfg, agent, client, prompt) {
|
|
8
|
+
async function composeUserPromptSubmit(cfg, agent, client, prompt, sessionId = null) {
|
|
9
9
|
const [recall, kbBlock] = await Promise.all([
|
|
10
|
-
recallTurn(prompt, cfg, client,
|
|
10
|
+
recallTurn(prompt, cfg, client, {
|
|
11
|
+
agent,
|
|
12
|
+
sessionId,
|
|
13
|
+
kind: "prompt"
|
|
14
|
+
}),
|
|
11
15
|
cfg.kbCatalogInjection === "user_prompt_submit" ? fetchKbCatalogBlock(client, agent).catch(() => "") : Promise.resolve("")
|
|
12
16
|
]);
|
|
13
17
|
let ctx = recall.additionalContext || "";
|
|
@@ -326,7 +326,7 @@ function parseErrorResponse(text, fallback) {
|
|
|
326
326
|
import { homedir as homedir2 } from "os";
|
|
327
327
|
import { delimiter, join as join3, sep } from "path";
|
|
328
328
|
import { accessSync, constants, existsSync, statSync } from "fs";
|
|
329
|
-
var SUPPORTED_AGENTS = ["qoder", "qoderwork", "codex", "claude", "opencode", "hermes"];
|
|
329
|
+
var SUPPORTED_AGENTS = ["qoder", "qoderwork", "qwenwork", "codex", "claude", "opencode", "hermes"];
|
|
330
330
|
function isBuiltinAgent(v) {
|
|
331
331
|
return typeof v === "string" && SUPPORTED_AGENTS.includes(v);
|
|
332
332
|
}
|
|
@@ -340,6 +340,8 @@ function agentHomeDir(agent, home = homedir2()) {
|
|
|
340
340
|
return join3(home, ".qoder");
|
|
341
341
|
case "qoderwork":
|
|
342
342
|
return join3(home, ".qoderwork");
|
|
343
|
+
case "qwenwork":
|
|
344
|
+
return join3(home, ".qwenwork");
|
|
343
345
|
case "codex":
|
|
344
346
|
return join3(home, ".codex");
|
|
345
347
|
case "claude":
|
|
@@ -352,7 +354,8 @@ function agentHomeDir(agent, home = homedir2()) {
|
|
|
352
354
|
}
|
|
353
355
|
var AGENT_VARIANT_HOMES = {
|
|
354
356
|
qoder: [".qoder-cn"],
|
|
355
|
-
qoderwork: [".qoderworkcn"]
|
|
357
|
+
qoderwork: [".qoderworkcn"],
|
|
358
|
+
qwenwork: [".qwenworkcn"]
|
|
356
359
|
};
|
|
357
360
|
function agentHomeDirs(agent, home = homedir2()) {
|
|
358
361
|
const primary = agentHomeDir(agent, home);
|
|
@@ -602,6 +605,9 @@ import { createHmac, randomBytes as randomBytes2 } from "crypto";
|
|
|
602
605
|
var PROCESS_FINGERPRINT_KEY = randomBytes2(32);
|
|
603
606
|
|
|
604
607
|
// src/lib/config.ts
|
|
608
|
+
import {
|
|
609
|
+
resolveDebugPolicy
|
|
610
|
+
} from "@aliyunrds/ctxdb-shared";
|
|
605
611
|
function defaultConfigPath() {
|
|
606
612
|
return join4(homedir3(), ".ctxdb", "ctxdb.json");
|
|
607
613
|
}
|
|
@@ -669,7 +675,8 @@ function isV2Schema(raw) {
|
|
|
669
675
|
return raw.version === 2 && raw.agents !== null && typeof raw.agents === "object" && !Array.isArray(raw.agents);
|
|
670
676
|
}
|
|
671
677
|
function configFromDisk(raw) {
|
|
672
|
-
|
|
678
|
+
const debugConfigured = coerceBool(raw.debug, false);
|
|
679
|
+
return applyDebugPolicy({
|
|
673
680
|
apiKey: typeof raw.api_key === "string" && raw.api_key ? raw.api_key : null,
|
|
674
681
|
baseUrl: typeof raw.base_url === "string" && raw.base_url ? String(raw.base_url).replace(/\/+$/, "") : DEFAULT_BASE_URL,
|
|
675
682
|
userId: typeof raw.user_id === "string" && raw.user_id ? raw.user_id : DEFAULT_USER_ID,
|
|
@@ -682,9 +689,20 @@ function configFromDisk(raw) {
|
|
|
682
689
|
topK: coerceInt(raw.top_k, DEFAULT_TOP_K),
|
|
683
690
|
threshold: coerceFloat(raw.threshold, DEFAULT_THRESHOLD),
|
|
684
691
|
knowledgeTopK: coerceInt(raw.knowledge_top_k, DEFAULT_KNOWLEDGE_TOP_K),
|
|
685
|
-
debug:
|
|
692
|
+
debug: debugConfigured,
|
|
693
|
+
debugConfigured,
|
|
694
|
+
debugForced: false,
|
|
695
|
+
debugReason: null,
|
|
686
696
|
kbCatalogInjection: coerceKbCatalogInjection(raw.kb_catalog_injection)
|
|
687
|
-
};
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
function applyDebugPolicy(cfg) {
|
|
700
|
+
const policy = resolveDebugPolicy(cfg.debugConfigured, cfg.baseUrl);
|
|
701
|
+
cfg.debug = policy.debug;
|
|
702
|
+
cfg.debugConfigured = policy.debugConfigured;
|
|
703
|
+
cfg.debugForced = policy.debugForced;
|
|
704
|
+
cfg.debugReason = policy.debugReason;
|
|
705
|
+
return cfg;
|
|
688
706
|
}
|
|
689
707
|
function applyEnv(cfg, env) {
|
|
690
708
|
if (env.CTXDB_API_KEY) cfg.apiKey = env.CTXDB_API_KEY;
|
|
@@ -692,7 +710,7 @@ function applyEnv(cfg, env) {
|
|
|
692
710
|
if (env.CTXDB_USER_ID) cfg.userId = env.CTXDB_USER_ID;
|
|
693
711
|
if (env.CTXDB_AGENT_ID) cfg.agentId = env.CTXDB_AGENT_ID;
|
|
694
712
|
if (env.CTXDB_APP_ID) cfg.appId = env.CTXDB_APP_ID;
|
|
695
|
-
return cfg;
|
|
713
|
+
return applyDebugPolicy(cfg);
|
|
696
714
|
}
|
|
697
715
|
function load(options = {}) {
|
|
698
716
|
const path = options.path ?? defaultConfigPath();
|
|
@@ -736,7 +754,7 @@ function configToDisk(cfg) {
|
|
|
736
754
|
top_k: cfg.topK,
|
|
737
755
|
threshold: cfg.threshold,
|
|
738
756
|
knowledge_top_k: cfg.knowledgeTopK,
|
|
739
|
-
debug: cfg.
|
|
757
|
+
debug: cfg.debugConfigured,
|
|
740
758
|
kb_catalog_injection: cfg.kbCatalogInjection
|
|
741
759
|
};
|
|
742
760
|
}
|
|
@@ -794,6 +812,34 @@ function configuredAgents(path) {
|
|
|
794
812
|
if (!isV2Schema(raw) || !raw.agents || typeof raw.agents !== "object") return [];
|
|
795
813
|
return Object.keys(raw.agents).filter(isAgent);
|
|
796
814
|
}
|
|
815
|
+
function hasConfiguredAgent(agent, path) {
|
|
816
|
+
const raw = readRaw(path ?? defaultConfigPath());
|
|
817
|
+
if (!isV2Schema(raw) || !raw.agents || typeof raw.agents !== "object" || Array.isArray(raw.agents)) {
|
|
818
|
+
return false;
|
|
819
|
+
}
|
|
820
|
+
const profile = raw.agents[agent];
|
|
821
|
+
return Boolean(
|
|
822
|
+
profile && typeof profile === "object" && !Array.isArray(profile)
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
function updateConfiguredDebug(agent, configured, path) {
|
|
826
|
+
const target = path ?? defaultConfigPath();
|
|
827
|
+
const raw = readRaw(target);
|
|
828
|
+
if (!isV2Schema(raw) || !raw.agents || typeof raw.agents !== "object" || Array.isArray(raw.agents)) {
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
831
|
+
const agents = { ...raw.agents };
|
|
832
|
+
const profile = agents[agent];
|
|
833
|
+
if (!profile || typeof profile !== "object" || Array.isArray(profile)) {
|
|
834
|
+
return false;
|
|
835
|
+
}
|
|
836
|
+
agents[agent] = { ...profile, debug: configured };
|
|
837
|
+
secureAtomicWrite(
|
|
838
|
+
target,
|
|
839
|
+
JSON.stringify({ ...raw, agents }, null, 2) + "\n"
|
|
840
|
+
);
|
|
841
|
+
return true;
|
|
842
|
+
}
|
|
797
843
|
function writeInstalledPkgVersion(version, path) {
|
|
798
844
|
const target = path ?? defaultConfigPath();
|
|
799
845
|
const raw = readRaw(target);
|
|
@@ -826,5 +872,7 @@ export {
|
|
|
826
872
|
removeAgent,
|
|
827
873
|
save,
|
|
828
874
|
configuredAgents,
|
|
875
|
+
hasConfiguredAgent,
|
|
876
|
+
updateConfiguredDebug,
|
|
829
877
|
writeInstalledPkgVersion
|
|
830
878
|
};
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
fetchKbCatalogBlock,
|
|
4
4
|
recallTurn
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VHNHVMCA.js";
|
|
6
6
|
import {
|
|
7
7
|
debug
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ARZX2RLR.js";
|
|
9
9
|
|
|
10
10
|
// src/lib/warmup-recall.ts
|
|
11
11
|
import { execSync } from "child_process";
|
|
@@ -49,13 +49,17 @@ function buildWarmupQuery(cwd, git) {
|
|
|
49
49
|
}
|
|
50
50
|
return parts.join(", ");
|
|
51
51
|
}
|
|
52
|
-
async function warmupRecall(cwd, cfg, client) {
|
|
52
|
+
async function warmupRecall(cwd, cfg, client, agent = "default", sessionId = null) {
|
|
53
53
|
if (!cfg.warmupRecall) {
|
|
54
54
|
return { ok: false, reason: "warmup_recall_disabled", additionalContext: "", memoryCount: 0, knowledgeChunkCount: 0 };
|
|
55
55
|
}
|
|
56
56
|
const git = collectGitSignals(cwd);
|
|
57
57
|
const query = buildWarmupQuery(cwd, git);
|
|
58
|
-
return recallTurn(query, cfg, client
|
|
58
|
+
return recallTurn(query, cfg, client, {
|
|
59
|
+
agent,
|
|
60
|
+
sessionId,
|
|
61
|
+
kind: "warmup"
|
|
62
|
+
});
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
// src/lib/session-start-compose.ts
|
|
@@ -63,9 +67,12 @@ var HOOK_TIMEOUT_MS = 5e3;
|
|
|
63
67
|
function timeout(ms) {
|
|
64
68
|
return new Promise((resolve) => setTimeout(() => resolve(null), ms));
|
|
65
69
|
}
|
|
66
|
-
async function composeSessionStart(cfg, agent, client, cwd, timeoutMs = HOOK_TIMEOUT_MS) {
|
|
70
|
+
async function composeSessionStart(cfg, agent, client, cwd, timeoutMs = HOOK_TIMEOUT_MS, sessionId = null) {
|
|
67
71
|
const kbInjectHere = cfg.kbCatalogInjection === "session_start";
|
|
68
|
-
const warmupPromise = cfg.warmupRecall ? Promise.race([
|
|
72
|
+
const warmupPromise = cfg.warmupRecall ? Promise.race([
|
|
73
|
+
warmupRecall(cwd, cfg, client, agent, sessionId),
|
|
74
|
+
timeout(timeoutMs).then(() => null)
|
|
75
|
+
]) : Promise.resolve(null);
|
|
69
76
|
const kbPromise = kbInjectHere ? Promise.race([fetchKbCatalogBlock(client, agent).catch(() => ""), timeout(timeoutMs).then(() => "")]) : Promise.resolve("");
|
|
70
77
|
const [result, kbBlock] = await Promise.all([warmupPromise, kbPromise]);
|
|
71
78
|
const warmupTimedOut = cfg.warmupRecall && result === null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CtxdbError
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ARZX2RLR.js";
|
|
5
5
|
|
|
6
6
|
// src/lib/kb.ts
|
|
7
7
|
import {
|
|
@@ -243,12 +243,13 @@ async function uploadFileInChunks(client, options) {
|
|
|
243
243
|
"document_id",
|
|
244
244
|
"chunk complete"
|
|
245
245
|
);
|
|
246
|
-
|
|
246
|
+
const reusedSucceededDocument = completedDocumentId !== documentId && completed.status === "succeeded";
|
|
247
|
+
if (completedDocumentId !== documentId && !reusedSucceededDocument) {
|
|
247
248
|
throw new CtxdbError(
|
|
248
249
|
`chunk complete returned mismatched document_id ${completedDocumentId}`
|
|
249
250
|
);
|
|
250
251
|
}
|
|
251
|
-
return getDocument(client, options.kbName,
|
|
252
|
+
return getDocument(client, options.kbName, completedDocumentId);
|
|
252
253
|
} catch (error) {
|
|
253
254
|
if (!completeStarted) {
|
|
254
255
|
try {
|