@aliyunrds/ctxdb 1.0.1-beta.7 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ fetchKbCatalogBlock,
4
+ recallTurn
5
+ } from "./chunk-EUQ3OFCQ.js";
6
+
7
+ // src/lib/user-prompt-submit-compose.ts
8
+ async function composeUserPromptSubmit(cfg, agent, client, prompt) {
9
+ const [recall, kbBlock] = await Promise.all([
10
+ recallTurn(prompt, cfg, client, agent),
11
+ cfg.kbCatalogInjection === "user_prompt_submit" ? fetchKbCatalogBlock(client, agent).catch(() => "") : Promise.resolve("")
12
+ ]);
13
+ let ctx = recall.additionalContext || "";
14
+ if (kbBlock) ctx = ctx ? `${ctx}
15
+
16
+ ${kbBlock}` : kbBlock;
17
+ return { ctx, recall, kbBlock };
18
+ }
19
+ function formatUserPromptSubmitStdout(agent, ctx) {
20
+ if (agent === "codex") return ctx + "\n";
21
+ const out = {
22
+ hookSpecificOutput: {
23
+ hookEventName: "UserPromptSubmit",
24
+ additionalContext: ctx
25
+ }
26
+ };
27
+ return JSON.stringify(out) + "\n";
28
+ }
29
+
30
+ export {
31
+ composeUserPromptSubmit,
32
+ formatUserPromptSubmitStdout
33
+ };
@@ -4,22 +4,8 @@ import {
4
4
  recallTurn
5
5
  } from "./chunk-EUQ3OFCQ.js";
6
6
  import {
7
- isCircuitOpen
8
- } from "./chunk-TGVURF54.js";
9
- import {
10
- HttpClient,
11
- agentFromArgvWithFallback,
12
- debug,
13
- isComplete,
14
- load,
15
- setDebug
7
+ debug
16
8
  } from "./chunk-6FZL67GH.js";
17
- import {
18
- shouldSkipHooks
19
- } from "./chunk-UEKR2Z3S.js";
20
-
21
- // src/hooks/session-start.ts
22
- import { pathToFileURL } from "url";
23
9
 
24
10
  // src/lib/warmup-recall.ts
25
11
  import { execSync } from "child_process";
@@ -72,7 +58,7 @@ async function warmupRecall(cwd, cfg, client) {
72
58
  return recallTurn(query, cfg, client);
73
59
  }
74
60
 
75
- // src/hooks/session-start.ts
61
+ // src/lib/session-start-compose.ts
76
62
  var HOOK_TIMEOUT_MS = 5e3;
77
63
  function timeout(ms) {
78
64
  return new Promise((resolve) => setTimeout(() => resolve(null), ms));
@@ -109,74 +95,6 @@ function formatSessionStartStdout(agent, ctx) {
109
95
  };
110
96
  return JSON.stringify(out) + "\n";
111
97
  }
112
- async function readStdinJson() {
113
- let raw = "";
114
- for await (const chunk of process.stdin) raw += chunk;
115
- if (!raw.trim()) return {};
116
- try {
117
- const obj = JSON.parse(raw);
118
- return obj && typeof obj === "object" && !Array.isArray(obj) ? obj : {};
119
- } catch {
120
- return {};
121
- }
122
- }
123
- async function main() {
124
- try {
125
- if (shouldSkipHooks()) return 0;
126
- const event = await readStdinJson();
127
- const { agent, fellBack } = agentFromArgvWithFallback();
128
- if (fellBack) {
129
- process.stderr.write(
130
- `ctxdb warmup: agent unspecified, defaulting to ${agent}
131
- `
132
- );
133
- }
134
- const cwd = typeof event.cwd === "string" ? event.cwd : "";
135
- if (!cwd) return 0;
136
- const cfg = load({ agent });
137
- setDebug(cfg.debug);
138
- debug("warmup", "start", { cwd, userId: cfg.userId });
139
- const kbInjectHere = cfg.kbCatalogInjection === "session_start";
140
- if (!isComplete(cfg) || !cfg.warmupRecall && !kbInjectHere) {
141
- debug("warmup", "skip (config incomplete or both warmup+kb off)");
142
- return 0;
143
- }
144
- if (isCircuitOpen(agent, cfg.baseUrl)) {
145
- debug("warmup", "skip (circuit open)");
146
- return 0;
147
- }
148
- const client = new HttpClient({
149
- baseUrl: cfg.baseUrl,
150
- apiKey: cfg.apiKey,
151
- timeoutMs: HOOK_TIMEOUT_MS
152
- });
153
- const composed = await composeSessionStart(cfg, agent, client, cwd);
154
- if (composed.warmupTimedOut) {
155
- process.stderr.write("ctxdb warmup: timeout\n");
156
- }
157
- if (!composed.ctx) return 0;
158
- const { memoryCount, kbChunkCount, kbCatalogLines, ctx } = composed;
159
- debug(
160
- "warmup",
161
- `ok, memories=${memoryCount} kb=${kbChunkCount} kb_catalog=${kbCatalogLines}`
162
- );
163
- process.stderr.write(
164
- `ctxdb warmup: ok (${memoryCount} memories, ${kbChunkCount} kb chunks, kb_catalog=${kbCatalogLines} lines)
165
- `
166
- );
167
- process.stdout.write(formatSessionStartStdout(agent, ctx));
168
- return 0;
169
- } catch (err) {
170
- process.stderr.write(`ctxdb warmup: unexpected error: ${err?.message ?? err}
171
- `);
172
- return 0;
173
- }
174
- }
175
- if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
176
- main().then((code) => {
177
- process.exitCode = code;
178
- });
179
- }
180
98
 
181
99
  export {
182
100
  HOOK_TIMEOUT_MS,
package/dist/cli/main.js CHANGED
@@ -2000,6 +2000,7 @@ ${h}
2000
2000
  import { spawnSync } from "child_process";
2001
2001
  import { fileURLToPath as fileURLToPath2 } from "url";
2002
2002
  import { dirname as dirname2 } from "path";
2003
+ import semver from "semver";
2003
2004
  var PACKAGE_NAME = "@aliyunrds/ctxdb";
2004
2005
  var NPM_VIEW_TIMEOUT_MS = 1e4;
2005
2006
  function npmCommand(platform = process.platform) {
@@ -2042,12 +2043,11 @@ function spawnFailureMessage(result, commandLabel) {
2042
2043
  return `${commandLabel} exited with code ${result.status}`;
2043
2044
  }
2044
2045
  function isNewerVersion(candidate, current) {
2045
- const parse = (v) => v.replace(/^v/, "").split(".").map(Number);
2046
- const [cMaj = 0, cMin = 0, cPat = 0] = parse(candidate);
2047
- const [uMaj = 0, uMin = 0, uPat = 0] = parse(current);
2048
- if (cMaj !== uMaj) return cMaj > uMaj;
2049
- if (cMin !== uMin) return cMin > uMin;
2050
- return cPat > uPat;
2046
+ const candidateVersion = semver.valid(candidate);
2047
+ const currentVersion = semver.valid(current);
2048
+ return Boolean(
2049
+ candidateVersion && currentVersion && semver.gt(candidateVersion, currentVersion)
2050
+ );
2051
2051
  }
2052
2052
  function runSelfUpdate(currentVersion, passthroughArgs = [], options = {}) {
2053
2053
  const method = options.installMethod ?? detectInstallMethod();
@@ -2069,8 +2069,10 @@ function runSelfUpdate(currentVersion, passthroughArgs = [], options = {}) {
2069
2069
  };
2070
2070
  }
2071
2071
  if (!check.isNewer) {
2072
- process.stderr.write(`ctxdb: package already up to date (v${currentVersion})
2073
- `);
2072
+ process.stderr.write(
2073
+ `ctxdb: package already up to date (current v${currentVersion}, latest v${check.latest})
2074
+ `
2075
+ );
2074
2076
  return { ok: true, updated: false, fromVersion: currentVersion };
2075
2077
  }
2076
2078
  process.stderr.write(`ctxdb: updating ${PACKAGE_NAME} v${currentVersion} \u2192 v${check.latest}...
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  HOOK_TIMEOUT_MS,
4
4
  composeSessionStart
5
- } from "../chunk-RZONPKY4.js";
5
+ } from "../chunk-WTP4ZX22.js";
6
6
  import {
7
7
  composeUserPromptSubmit
8
- } from "../chunk-FD3AMXVU.js";
8
+ } from "../chunk-2CSEFSLC.js";
9
9
  import {
10
10
  fetchKbCatalogBlock
11
11
  } from "../chunk-EUQ3OFCQ.js";
@@ -3,12 +3,94 @@ import {
3
3
  HOOK_TIMEOUT_MS,
4
4
  composeSessionStart,
5
5
  formatSessionStartStdout
6
- } from "../chunk-RZONPKY4.js";
6
+ } from "../chunk-WTP4ZX22.js";
7
7
  import "../chunk-EUQ3OFCQ.js";
8
8
  import "../chunk-UH7AJF6F.js";
9
- import "../chunk-TGVURF54.js";
10
- import "../chunk-6FZL67GH.js";
11
- import "../chunk-UEKR2Z3S.js";
9
+ import {
10
+ isCircuitOpen
11
+ } from "../chunk-TGVURF54.js";
12
+ import {
13
+ HttpClient,
14
+ agentFromArgvWithFallback,
15
+ debug,
16
+ isComplete,
17
+ load,
18
+ setDebug
19
+ } from "../chunk-6FZL67GH.js";
20
+ import {
21
+ shouldSkipHooks
22
+ } from "../chunk-UEKR2Z3S.js";
23
+
24
+ // src/hooks/session-start.ts
25
+ import { pathToFileURL } from "url";
26
+ async function readStdinJson() {
27
+ let raw = "";
28
+ for await (const chunk of process.stdin) raw += chunk;
29
+ if (!raw.trim()) return {};
30
+ try {
31
+ const obj = JSON.parse(raw);
32
+ return obj && typeof obj === "object" && !Array.isArray(obj) ? obj : {};
33
+ } catch {
34
+ return {};
35
+ }
36
+ }
37
+ async function main() {
38
+ try {
39
+ if (shouldSkipHooks()) return 0;
40
+ const event = await readStdinJson();
41
+ const { agent, fellBack } = agentFromArgvWithFallback();
42
+ if (fellBack) {
43
+ process.stderr.write(
44
+ `ctxdb warmup: agent unspecified, defaulting to ${agent}
45
+ `
46
+ );
47
+ }
48
+ const cwd = typeof event.cwd === "string" ? event.cwd : "";
49
+ if (!cwd) return 0;
50
+ const cfg = load({ agent });
51
+ setDebug(cfg.debug);
52
+ debug("warmup", "start", { cwd, userId: cfg.userId });
53
+ const kbInjectHere = cfg.kbCatalogInjection === "session_start";
54
+ if (!isComplete(cfg) || !cfg.warmupRecall && !kbInjectHere) {
55
+ debug("warmup", "skip (config incomplete or both warmup+kb off)");
56
+ return 0;
57
+ }
58
+ if (isCircuitOpen(agent, cfg.baseUrl)) {
59
+ debug("warmup", "skip (circuit open)");
60
+ return 0;
61
+ }
62
+ const client = new HttpClient({
63
+ baseUrl: cfg.baseUrl,
64
+ apiKey: cfg.apiKey,
65
+ timeoutMs: HOOK_TIMEOUT_MS
66
+ });
67
+ const composed = await composeSessionStart(cfg, agent, client, cwd);
68
+ if (composed.warmupTimedOut) {
69
+ process.stderr.write("ctxdb warmup: timeout\n");
70
+ }
71
+ if (!composed.ctx) return 0;
72
+ const { memoryCount, kbChunkCount, kbCatalogLines, ctx } = composed;
73
+ debug(
74
+ "warmup",
75
+ `ok, memories=${memoryCount} kb=${kbChunkCount} kb_catalog=${kbCatalogLines}`
76
+ );
77
+ process.stderr.write(
78
+ `ctxdb warmup: ok (${memoryCount} memories, ${kbChunkCount} kb chunks, kb_catalog=${kbCatalogLines} lines)
79
+ `
80
+ );
81
+ process.stdout.write(formatSessionStartStdout(agent, ctx));
82
+ return 0;
83
+ } catch (err) {
84
+ process.stderr.write(`ctxdb warmup: unexpected error: ${err?.message ?? err}
85
+ `);
86
+ return 0;
87
+ }
88
+ }
89
+ if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
90
+ main().then((code) => {
91
+ process.exitCode = code;
92
+ });
93
+ }
12
94
  export {
13
95
  HOOK_TIMEOUT_MS,
14
96
  composeSessionStart,
@@ -2,12 +2,89 @@
2
2
  import {
3
3
  composeUserPromptSubmit,
4
4
  formatUserPromptSubmitStdout
5
- } from "../chunk-FD3AMXVU.js";
5
+ } from "../chunk-2CSEFSLC.js";
6
6
  import "../chunk-EUQ3OFCQ.js";
7
7
  import "../chunk-UH7AJF6F.js";
8
- import "../chunk-TGVURF54.js";
9
- import "../chunk-6FZL67GH.js";
10
- import "../chunk-UEKR2Z3S.js";
8
+ import {
9
+ isCircuitOpen
10
+ } from "../chunk-TGVURF54.js";
11
+ import {
12
+ HttpClient,
13
+ agentFromArgvWithFallback,
14
+ debug,
15
+ isComplete,
16
+ load,
17
+ setDebug
18
+ } from "../chunk-6FZL67GH.js";
19
+ import {
20
+ shouldSkipHooks
21
+ } from "../chunk-UEKR2Z3S.js";
22
+
23
+ // src/hooks/user-prompt-submit.ts
24
+ import { pathToFileURL } from "url";
25
+ async function readStdinJson() {
26
+ let raw = "";
27
+ for await (const chunk of process.stdin) raw += chunk;
28
+ if (!raw.trim()) return {};
29
+ try {
30
+ const obj = JSON.parse(raw);
31
+ return obj && typeof obj === "object" && !Array.isArray(obj) ? obj : {};
32
+ } catch {
33
+ return {};
34
+ }
35
+ }
36
+ async function main() {
37
+ try {
38
+ if (shouldSkipHooks()) return 0;
39
+ const event = await readStdinJson();
40
+ const { agent, fellBack } = agentFromArgvWithFallback();
41
+ if (fellBack) {
42
+ process.stderr.write(
43
+ `ctxdb recall: agent unspecified, defaulting to ${agent}
44
+ `
45
+ );
46
+ }
47
+ const prompt = typeof event.prompt === "string" ? event.prompt : "";
48
+ if (!prompt.trim()) return 0;
49
+ const cfg = load({ agent });
50
+ setDebug(cfg.debug);
51
+ debug("recall", "start", { prompt: prompt.slice(0, 200), userId: cfg.userId });
52
+ if (!isComplete(cfg) || !cfg.autoRecall) {
53
+ debug("recall", "skip (config incomplete or autoRecall=false)");
54
+ return 0;
55
+ }
56
+ if (isCircuitOpen(agent, cfg.baseUrl)) {
57
+ debug("recall", "skip (circuit open)");
58
+ process.stderr.write(`ctxdb recall: skip (circuit_open: ${cfg.baseUrl})
59
+ `);
60
+ return 0;
61
+ }
62
+ const client = new HttpClient({ baseUrl: cfg.baseUrl, apiKey: cfg.apiKey, timeoutMs: 5e3 });
63
+ const { ctx, recall, kbBlock } = await composeUserPromptSubmit(cfg, agent, client, prompt);
64
+ if (!recall.ok && !recall.additionalContext && !kbBlock) {
65
+ const reason = recall.reason ?? "no_context";
66
+ debug("recall", `no result: ${reason}`, recall);
67
+ if (recall.reason && recall.reason.startsWith("http_error:")) {
68
+ process.stderr.write(`ctxdb recall: ${recall.reason}
69
+ `);
70
+ }
71
+ return 0;
72
+ }
73
+ if (!ctx) return 0;
74
+ debug("recall", `ok, additionalContext length=${ctx.length}`);
75
+ process.stdout.write(formatUserPromptSubmitStdout(agent, ctx));
76
+ return 0;
77
+ } catch (err) {
78
+ process.stderr.write(`ctxdb recall: unexpected error: ${err?.message ?? err}
79
+ `);
80
+ return 0;
81
+ }
82
+ }
83
+ if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
84
+ main().then((code) => {
85
+ process.exitCode = code;
86
+ });
87
+ }
11
88
  export {
12
89
  composeUserPromptSubmit,
13
90
  formatUserPromptSubmitStdout
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliyunrds/ctxdb",
3
- "version": "1.0.1-beta.7",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "description": "Unified access layer for RDS ContextDatabase: `ctxdb` CLI (memory + KB ops), one-shot `setup --agent <qoder|qoderwork|codex|claude|opencode|hermes>` installer, per-agent config, hooks/plugins, and SKILL.md.",
6
6
  "license": "Apache-2.0",
@@ -30,11 +30,13 @@
30
30
  "node": ">=20"
31
31
  },
32
32
  "dependencies": {
33
+ "semver": "^7.8.5",
33
34
  "yaml": "^2.9.0",
34
- "@aliyunrds/ctxdb-shared": "~0.0.4"
35
+ "@aliyunrds/ctxdb-shared": "~0.0.5"
35
36
  },
36
37
  "devDependencies": {
37
38
  "@types/node": "^22.15.0",
39
+ "@types/semver": "^7.7.1",
38
40
  "@vitest/coverage-v8": "^4.0.18",
39
41
  "tsup": "^8.5.0",
40
42
  "typescript": "^5.8.3",
@@ -1,111 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- fetchKbCatalogBlock,
4
- recallTurn
5
- } from "./chunk-EUQ3OFCQ.js";
6
- import {
7
- isCircuitOpen
8
- } from "./chunk-TGVURF54.js";
9
- import {
10
- HttpClient,
11
- agentFromArgvWithFallback,
12
- debug,
13
- isComplete,
14
- load,
15
- setDebug
16
- } from "./chunk-6FZL67GH.js";
17
- import {
18
- shouldSkipHooks
19
- } from "./chunk-UEKR2Z3S.js";
20
-
21
- // src/hooks/user-prompt-submit.ts
22
- import { pathToFileURL } from "url";
23
- async function composeUserPromptSubmit(cfg, agent, client, prompt) {
24
- const [recall, kbBlock] = await Promise.all([
25
- recallTurn(prompt, cfg, client, agent),
26
- cfg.kbCatalogInjection === "user_prompt_submit" ? fetchKbCatalogBlock(client, agent).catch(() => "") : Promise.resolve("")
27
- ]);
28
- let ctx = recall.additionalContext || "";
29
- if (kbBlock) ctx = ctx ? `${ctx}
30
-
31
- ${kbBlock}` : kbBlock;
32
- return { ctx, recall, kbBlock };
33
- }
34
- function formatUserPromptSubmitStdout(agent, ctx) {
35
- if (agent === "codex") return ctx + "\n";
36
- const out = {
37
- hookSpecificOutput: {
38
- hookEventName: "UserPromptSubmit",
39
- additionalContext: ctx
40
- }
41
- };
42
- return JSON.stringify(out) + "\n";
43
- }
44
- async function readStdinJson() {
45
- let raw = "";
46
- for await (const chunk of process.stdin) raw += chunk;
47
- if (!raw.trim()) return {};
48
- try {
49
- const obj = JSON.parse(raw);
50
- return obj && typeof obj === "object" && !Array.isArray(obj) ? obj : {};
51
- } catch {
52
- return {};
53
- }
54
- }
55
- async function main() {
56
- try {
57
- if (shouldSkipHooks()) return 0;
58
- const event = await readStdinJson();
59
- const { agent, fellBack } = agentFromArgvWithFallback();
60
- if (fellBack) {
61
- process.stderr.write(
62
- `ctxdb recall: agent unspecified, defaulting to ${agent}
63
- `
64
- );
65
- }
66
- const prompt = typeof event.prompt === "string" ? event.prompt : "";
67
- if (!prompt.trim()) return 0;
68
- const cfg = load({ agent });
69
- setDebug(cfg.debug);
70
- debug("recall", "start", { prompt: prompt.slice(0, 200), userId: cfg.userId });
71
- if (!isComplete(cfg) || !cfg.autoRecall) {
72
- debug("recall", "skip (config incomplete or autoRecall=false)");
73
- return 0;
74
- }
75
- if (isCircuitOpen(agent, cfg.baseUrl)) {
76
- debug("recall", "skip (circuit open)");
77
- process.stderr.write(`ctxdb recall: skip (circuit_open: ${cfg.baseUrl})
78
- `);
79
- return 0;
80
- }
81
- const client = new HttpClient({ baseUrl: cfg.baseUrl, apiKey: cfg.apiKey, timeoutMs: 5e3 });
82
- const { ctx, recall, kbBlock } = await composeUserPromptSubmit(cfg, agent, client, prompt);
83
- if (!recall.ok && !recall.additionalContext && !kbBlock) {
84
- const reason = recall.reason ?? "no_context";
85
- debug("recall", `no result: ${reason}`, recall);
86
- if (recall.reason && recall.reason.startsWith("http_error:")) {
87
- process.stderr.write(`ctxdb recall: ${recall.reason}
88
- `);
89
- }
90
- return 0;
91
- }
92
- if (!ctx) return 0;
93
- debug("recall", `ok, additionalContext length=${ctx.length}`);
94
- process.stdout.write(formatUserPromptSubmitStdout(agent, ctx));
95
- return 0;
96
- } catch (err) {
97
- process.stderr.write(`ctxdb recall: unexpected error: ${err?.message ?? err}
98
- `);
99
- return 0;
100
- }
101
- }
102
- if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
103
- main().then((code) => {
104
- process.exitCode = code;
105
- });
106
- }
107
-
108
- export {
109
- composeUserPromptSubmit,
110
- formatUserPromptSubmitStdout
111
- };