@aliyunrds/ctxdb 0.0.1 → 0.0.3
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/{chunk-464RHJDQ.js → chunk-7NOXAU2X.js} +1 -1
- package/dist/{chunk-L4YJ7LDI.js → chunk-QSSNPN3M.js} +94 -21
- package/dist/cli/main.js +388 -126
- package/dist/hooks/session-start.js +6 -8
- package/dist/hooks/stop.js +5 -7
- package/dist/hooks/user-prompt-submit.js +5 -7
- package/dist/setup/skills/cli-only/SKILL.md +18 -3
- package/dist/setup/skills/hooks-driven/SKILL.md +91 -50
- package/package.json +1 -1
- package/dist/chunk-GDJVHVIT.js +0 -35
|
@@ -1,6 +1,54 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// src/lib/logger.ts
|
|
4
|
+
import { appendFileSync, mkdirSync } from "fs";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
import { dirname, join } from "path";
|
|
7
|
+
function logPath() {
|
|
8
|
+
return join(homedir(), ".ctxdb", "logs", "ctxdb.log");
|
|
9
|
+
}
|
|
10
|
+
var _enabled = null;
|
|
11
|
+
function setDebug(enabled) {
|
|
12
|
+
_enabled = enabled;
|
|
13
|
+
}
|
|
14
|
+
function isDebug() {
|
|
15
|
+
return _enabled === true;
|
|
16
|
+
}
|
|
17
|
+
function debug(tag, msg, data) {
|
|
18
|
+
if (_enabled !== true) return;
|
|
19
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
20
|
+
let line = `${ts} [${tag}] ${msg}`;
|
|
21
|
+
if (data !== void 0) {
|
|
22
|
+
const s = typeof data === "string" ? data : JSON.stringify(data, null, 2);
|
|
23
|
+
line += `
|
|
24
|
+
${s}`;
|
|
25
|
+
}
|
|
26
|
+
line += "\n";
|
|
27
|
+
const p = logPath();
|
|
28
|
+
try {
|
|
29
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
30
|
+
appendFileSync(p, line, "utf-8");
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
3
35
|
// src/lib/http-client.ts
|
|
36
|
+
import { readFileSync } from "fs";
|
|
37
|
+
import { fileURLToPath } from "url";
|
|
38
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
39
|
+
function findPackageVersion() {
|
|
40
|
+
let dir = dirname2(fileURLToPath(import.meta.url));
|
|
41
|
+
for (let i = 0; i < 5; i++) {
|
|
42
|
+
try {
|
|
43
|
+
const pkg = JSON.parse(readFileSync(join2(dir, "package.json"), "utf-8"));
|
|
44
|
+
if (pkg.name === "@aliyunrds/ctxdb") return pkg.version;
|
|
45
|
+
} catch {
|
|
46
|
+
}
|
|
47
|
+
dir = dirname2(dir);
|
|
48
|
+
}
|
|
49
|
+
return "0.0.0";
|
|
50
|
+
}
|
|
51
|
+
var PKG_VERSION = findPackageVersion();
|
|
4
52
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
5
53
|
var CtxdbError = class extends Error {
|
|
6
54
|
constructor(message) {
|
|
@@ -53,7 +101,7 @@ var HttpClient = class {
|
|
|
53
101
|
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
54
102
|
this.apiKey = opts.apiKey;
|
|
55
103
|
this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
56
|
-
this.userAgent = opts.userAgent ??
|
|
104
|
+
this.userAgent = opts.userAgent ?? `ctxdb-cli/${PKG_VERSION}`;
|
|
57
105
|
this.extraHeaders = { ...opts.extraHeaders ?? {} };
|
|
58
106
|
const f = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
59
107
|
this.fetchImpl = f;
|
|
@@ -77,8 +125,15 @@ var HttpClient = class {
|
|
|
77
125
|
const s = qs.toString();
|
|
78
126
|
if (s) url = `${url}?${s}`;
|
|
79
127
|
}
|
|
128
|
+
const effectiveTimeout = init.timeoutMs ?? this.timeoutMs;
|
|
129
|
+
const dbg = isDebug();
|
|
130
|
+
let t0 = 0;
|
|
131
|
+
if (dbg) {
|
|
132
|
+
t0 = Date.now();
|
|
133
|
+
debug("http", `\u2192 ${method} ${url} (timeout=${effectiveTimeout}ms)`);
|
|
134
|
+
}
|
|
80
135
|
const controller = new AbortController();
|
|
81
|
-
const timer = setTimeout(() => controller.abort(),
|
|
136
|
+
const timer = setTimeout(() => controller.abort(), effectiveTimeout);
|
|
82
137
|
try {
|
|
83
138
|
let resp;
|
|
84
139
|
try {
|
|
@@ -90,27 +145,36 @@ var HttpClient = class {
|
|
|
90
145
|
});
|
|
91
146
|
} catch (err) {
|
|
92
147
|
if (err?.name === "AbortError") {
|
|
93
|
-
|
|
148
|
+
if (dbg) debug("http", `\u2717 ${method} ${path} timeout after ${Date.now() - t0}ms`);
|
|
149
|
+
throw new CtxdbError(`request timeout after ${effectiveTimeout}ms: ${url}`);
|
|
94
150
|
}
|
|
151
|
+
if (dbg) debug("http", `\u2717 ${method} ${path} network error after ${Date.now() - t0}ms: ${err?.message ?? err}`);
|
|
95
152
|
throw new CtxdbError(`network error contacting ${url}: ${err?.message ?? err}`);
|
|
96
153
|
}
|
|
97
|
-
if (resp.status === 204)
|
|
154
|
+
if (resp.status === 204) {
|
|
155
|
+
if (dbg) debug("http", `\u2190 ${method} ${path} 204 (${Date.now() - t0}ms)`);
|
|
156
|
+
return {};
|
|
157
|
+
}
|
|
98
158
|
let text;
|
|
99
159
|
try {
|
|
100
160
|
text = await resp.text();
|
|
101
161
|
} catch (err) {
|
|
102
162
|
if (err?.name === "AbortError") {
|
|
103
|
-
|
|
163
|
+
if (dbg) debug("http", `\u2717 ${method} ${path} body-read timeout after ${Date.now() - t0}ms`);
|
|
164
|
+
throw new CtxdbError(`request timeout after ${effectiveTimeout}ms (body read): ${url}`);
|
|
104
165
|
}
|
|
166
|
+
if (dbg) debug("http", `\u2717 ${method} ${path} body-read error after ${Date.now() - t0}ms: ${err?.message ?? err}`);
|
|
105
167
|
throw new CtxdbError(`network error reading body from ${url}: ${err?.message ?? err}`);
|
|
106
168
|
}
|
|
107
169
|
if (!resp.ok) {
|
|
108
170
|
const detail = extractErrorDetail(text, `HTTP ${resp.status}`);
|
|
171
|
+
if (dbg) debug("http", `\u2190 ${method} ${path} ${resp.status} (${Date.now() - t0}ms) ${detail}`);
|
|
109
172
|
if (resp.status === 401) throw new AuthError();
|
|
110
173
|
if (resp.status === 404) throw new NotFoundError(path);
|
|
111
174
|
if (resp.status === 400) throw new APIError(path, detail);
|
|
112
175
|
throw new CtxdbHttpError(resp.status, detail);
|
|
113
176
|
}
|
|
177
|
+
if (dbg) debug("http", `\u2190 ${method} ${path} ${resp.status} (${Date.now() - t0}ms) body=${text.length}B`);
|
|
114
178
|
if (!text) return {};
|
|
115
179
|
return maybeJson(text);
|
|
116
180
|
} finally {
|
|
@@ -145,7 +209,7 @@ var HttpClient = class {
|
|
|
145
209
|
* header — when fetch sees a FormData body it sets the multipart
|
|
146
210
|
* boundary itself.
|
|
147
211
|
*/
|
|
148
|
-
postMultipart(path, fields = {}, files = {}) {
|
|
212
|
+
postMultipart(path, fields = {}, files = {}, options = {}) {
|
|
149
213
|
const fd = new FormData();
|
|
150
214
|
for (const [name, value] of Object.entries(fields)) {
|
|
151
215
|
fd.append(name, value);
|
|
@@ -154,7 +218,7 @@ var HttpClient = class {
|
|
|
154
218
|
const blob = part.content instanceof Blob ? part.content : new Blob([part.content], { type: part.mimeType });
|
|
155
219
|
fd.append(name, blob, part.filename);
|
|
156
220
|
}
|
|
157
|
-
return this.doRequest("POST", path, { body: fd });
|
|
221
|
+
return this.doRequest("POST", path, { body: fd, timeoutMs: options.timeoutMs });
|
|
158
222
|
}
|
|
159
223
|
};
|
|
160
224
|
function maybeJson(text) {
|
|
@@ -184,8 +248,8 @@ function extractErrorDetail(text, fallback) {
|
|
|
184
248
|
}
|
|
185
249
|
|
|
186
250
|
// src/lib/agents.ts
|
|
187
|
-
import { homedir } from "os";
|
|
188
|
-
import { join } from "path";
|
|
251
|
+
import { homedir as homedir2 } from "os";
|
|
252
|
+
import { join as join3 } from "path";
|
|
189
253
|
var SUPPORTED_AGENTS = ["qoder", "codex", "claude"];
|
|
190
254
|
function isAgent(v) {
|
|
191
255
|
return typeof v === "string" && SUPPORTED_AGENTS.includes(v);
|
|
@@ -193,11 +257,11 @@ function isAgent(v) {
|
|
|
193
257
|
function agentHomeDir(agent) {
|
|
194
258
|
switch (agent) {
|
|
195
259
|
case "qoder":
|
|
196
|
-
return
|
|
260
|
+
return join3(homedir2(), ".qoder");
|
|
197
261
|
case "codex":
|
|
198
|
-
return
|
|
262
|
+
return join3(homedir2(), ".codex");
|
|
199
263
|
case "claude":
|
|
200
|
-
return
|
|
264
|
+
return join3(homedir2(), ".claude");
|
|
201
265
|
}
|
|
202
266
|
}
|
|
203
267
|
function agentFromEnv(env = process.env) {
|
|
@@ -218,13 +282,13 @@ function agentFromArgvWithFallback(argv = process.argv.slice(2), env = process.e
|
|
|
218
282
|
}
|
|
219
283
|
|
|
220
284
|
// src/lib/config.ts
|
|
221
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from "fs";
|
|
222
|
-
import { homedir as
|
|
223
|
-
import { dirname, join as
|
|
285
|
+
import { readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync2, existsSync, unlinkSync } from "fs";
|
|
286
|
+
import { homedir as homedir3 } from "os";
|
|
287
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
224
288
|
function defaultConfigPath() {
|
|
225
|
-
return
|
|
289
|
+
return join4(homedir3(), ".ctxdb", "ctxdb.json");
|
|
226
290
|
}
|
|
227
|
-
var DEFAULT_CONFIG_PATH =
|
|
291
|
+
var DEFAULT_CONFIG_PATH = join4(homedir3(), ".ctxdb", "ctxdb.json");
|
|
228
292
|
var DEFAULT_BASE_URL = "https://context-database.aliyuncs.com";
|
|
229
293
|
var DEFAULT_USER_ID = "default";
|
|
230
294
|
var DEFAULT_TOP_K = 5;
|
|
@@ -255,7 +319,7 @@ function coerceBool(v, fallback) {
|
|
|
255
319
|
function readRaw(path) {
|
|
256
320
|
if (!existsSync(path)) return {};
|
|
257
321
|
try {
|
|
258
|
-
const parsed = JSON.parse(
|
|
322
|
+
const parsed = JSON.parse(readFileSync2(path, "utf-8"));
|
|
259
323
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
260
324
|
return parsed;
|
|
261
325
|
}
|
|
@@ -284,7 +348,7 @@ function configFromDisk(raw) {
|
|
|
284
348
|
userId: typeof raw.user_id === "string" && raw.user_id ? raw.user_id : DEFAULT_USER_ID,
|
|
285
349
|
autoCapture: coerceBool(raw.auto_capture, true),
|
|
286
350
|
autoRecall: coerceBool(raw.auto_recall, true),
|
|
287
|
-
warmupRecall: coerceBool(raw.warmup_recall,
|
|
351
|
+
warmupRecall: coerceBool(raw.warmup_recall, false),
|
|
288
352
|
recallKnowledge: coerceBool(raw.recall_knowledge, false),
|
|
289
353
|
topK: coerceInt(raw.top_k, DEFAULT_TOP_K),
|
|
290
354
|
threshold: coerceFloat(raw.threshold, DEFAULT_THRESHOLD),
|
|
@@ -373,11 +437,19 @@ function save(cfg, path, options = {}) {
|
|
|
373
437
|
[agent]: configToDisk(cfg)
|
|
374
438
|
}
|
|
375
439
|
};
|
|
376
|
-
|
|
440
|
+
mkdirSync2(dirname3(target), { recursive: true });
|
|
377
441
|
writeFileSync(target, JSON.stringify(onDisk, null, 2) + "\n", "utf-8");
|
|
378
442
|
}
|
|
443
|
+
function configuredAgents(path) {
|
|
444
|
+
const target = path ?? defaultConfigPath();
|
|
445
|
+
const raw = readRaw(target);
|
|
446
|
+
if (!isV2Schema(raw) || !raw.agents || typeof raw.agents !== "object") return [];
|
|
447
|
+
return Object.keys(raw.agents).filter(isAgent);
|
|
448
|
+
}
|
|
379
449
|
|
|
380
450
|
export {
|
|
451
|
+
setDebug,
|
|
452
|
+
debug,
|
|
381
453
|
CtxdbError,
|
|
382
454
|
NotFoundError,
|
|
383
455
|
HttpClient,
|
|
@@ -391,5 +463,6 @@ export {
|
|
|
391
463
|
isComplete,
|
|
392
464
|
load,
|
|
393
465
|
removeAgent,
|
|
394
|
-
save
|
|
466
|
+
save,
|
|
467
|
+
configuredAgents
|
|
395
468
|
};
|