@aliyunrds/ctxdb 1.0.2 → 1.0.4

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.
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  captureParsedMessages
4
- } from "../chunk-IMYLU5C2.js";
5
- import "../chunk-TGVURF54.js";
4
+ } from "../chunk-SAQT6VL6.js";
5
+ import "../chunk-USMJLDBD.js";
6
6
  import {
7
7
  HttpClient,
8
8
  agentFromArgvWithFallback,
9
9
  debug,
10
10
  load,
11
11
  setDebug
12
- } from "../chunk-6FZL67GH.js";
12
+ } from "../chunk-JFTKYEVN.js";
13
13
  import {
14
14
  shouldSkipHooks
15
15
  } from "../chunk-UEKR2Z3S.js";
@@ -2,17 +2,17 @@
2
2
  import {
3
3
  HOOK_TIMEOUT_MS,
4
4
  composeSessionStart
5
- } from "../chunk-WTP4ZX22.js";
5
+ } from "../chunk-CWGF5D52.js";
6
6
  import {
7
7
  composeUserPromptSubmit
8
- } from "../chunk-2CSEFSLC.js";
8
+ } from "../chunk-BVCDRUU4.js";
9
9
  import {
10
10
  fetchKbCatalogBlock
11
- } from "../chunk-EUQ3OFCQ.js";
12
- import "../chunk-UH7AJF6F.js";
11
+ } from "../chunk-Q4JYST7K.js";
12
+ import "../chunk-3PFMHU3C.js";
13
13
  import {
14
14
  isCircuitOpen
15
- } from "../chunk-TGVURF54.js";
15
+ } from "../chunk-USMJLDBD.js";
16
16
  import {
17
17
  HttpClient,
18
18
  agentFromArgvWithFallback,
@@ -20,7 +20,7 @@ import {
20
20
  isComplete,
21
21
  load,
22
22
  setDebug
23
- } from "../chunk-6FZL67GH.js";
23
+ } from "../chunk-JFTKYEVN.js";
24
24
  import {
25
25
  shouldSkipHooks
26
26
  } from "../chunk-UEKR2Z3S.js";
@@ -3,12 +3,12 @@ import {
3
3
  HOOK_TIMEOUT_MS,
4
4
  composeSessionStart,
5
5
  formatSessionStartStdout
6
- } from "../chunk-WTP4ZX22.js";
7
- import "../chunk-EUQ3OFCQ.js";
8
- import "../chunk-UH7AJF6F.js";
6
+ } from "../chunk-CWGF5D52.js";
7
+ import "../chunk-Q4JYST7K.js";
8
+ import "../chunk-3PFMHU3C.js";
9
9
  import {
10
10
  isCircuitOpen
11
- } from "../chunk-TGVURF54.js";
11
+ } from "../chunk-USMJLDBD.js";
12
12
  import {
13
13
  HttpClient,
14
14
  agentFromArgvWithFallback,
@@ -16,7 +16,7 @@ import {
16
16
  isComplete,
17
17
  load,
18
18
  setDebug
19
- } from "../chunk-6FZL67GH.js";
19
+ } from "../chunk-JFTKYEVN.js";
20
20
  import {
21
21
  shouldSkipHooks
22
22
  } from "../chunk-UEKR2Z3S.js";
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  captureTurn
4
- } from "../chunk-IMYLU5C2.js";
5
- import "../chunk-TGVURF54.js";
4
+ } from "../chunk-SAQT6VL6.js";
5
+ import "../chunk-USMJLDBD.js";
6
6
  import {
7
7
  HttpClient,
8
8
  agentFromArgvWithFallback,
9
9
  debug,
10
10
  load,
11
11
  setDebug
12
- } from "../chunk-6FZL67GH.js";
12
+ } from "../chunk-JFTKYEVN.js";
13
13
  import {
14
14
  shouldSkipHooks
15
15
  } from "../chunk-UEKR2Z3S.js";
@@ -2,12 +2,12 @@
2
2
  import {
3
3
  composeUserPromptSubmit,
4
4
  formatUserPromptSubmitStdout
5
- } from "../chunk-2CSEFSLC.js";
6
- import "../chunk-EUQ3OFCQ.js";
7
- import "../chunk-UH7AJF6F.js";
5
+ } from "../chunk-BVCDRUU4.js";
6
+ import "../chunk-Q4JYST7K.js";
7
+ import "../chunk-3PFMHU3C.js";
8
8
  import {
9
9
  isCircuitOpen
10
- } from "../chunk-TGVURF54.js";
10
+ } from "../chunk-USMJLDBD.js";
11
11
  import {
12
12
  HttpClient,
13
13
  agentFromArgvWithFallback,
@@ -15,7 +15,7 @@ import {
15
15
  isComplete,
16
16
  load,
17
17
  setDebug
18
- } from "../chunk-6FZL67GH.js";
18
+ } from "../chunk-JFTKYEVN.js";
19
19
  import {
20
20
  shouldSkipHooks
21
21
  } from "../chunk-UEKR2Z3S.js";
@@ -79,7 +79,9 @@ ctxdb kb documents-list <kb-name> --agent={{agent}}
79
79
  ctxdb kb upload-text <kb-name> <doc-name> --text="<body>" --agent={{agent}}
80
80
  ```
81
81
 
82
- 副作用操作。**用户没明示 KB 名前先 recipe 2 列出来确认**(见 §5 注意事项 3)。KB 不存在会直接报错,不自动创建。
82
+ 副作用操作。命令默认在服务端接受文档后立即返回;此时
83
+ `ingest_status=processing` 只表示已受理,不表示入库成功。调用方必须等到文本可检索时加
84
+ `--wait`。**用户没明示 KB 名前先 recipe 2 列出来确认**(见 §5 注意事项 3)。KB 不存在会直接报错,不自动创建。
83
85
 
84
86
  **何时不适用**:内容是本地文件 → recipe 5。
85
87
 
@@ -91,7 +93,11 @@ ctxdb kb upload-text <kb-name> <doc-name> --text="<body>" --agent={{agent}}
91
93
  ctxdb kb upload-file <kb-name> <local-path> --agent={{agent}}
92
94
  ```
93
95
 
94
- 支持格式:PDF / DOCX / MD / TXT。默认等待 chunking 完成;想立即返回加 `--no-wait`(见 §6)。
96
+ 文件格式和大小限制由服务端决定,CLI 不维护本地允许列表;未知扩展名也会提交给服务端
97
+ 判断。CLI 先尝试普通流式上传,服务端明确要求时会自动切换为分片上传。默认在服务端接受
98
+ 文档后立即返回;调用方必须等到 chunking 结束时加 `--wait`。`--no-wait` 仍可使用,
99
+ 行为与默认值相同(见 §6)。分片 init、part、complete 当前均为单次请求,超时或断网后
100
+ 不会自动重试,以免服务端已成功但响应丢失时产生重复副作用。
95
101
 
96
102
  **何时不适用**:要上传的内容是字符串而非本地文件 → recipe 4。
97
103
 
@@ -173,7 +179,11 @@ ctxdb kb upload-file <kb-name> <local-path> --agent={{agent}}
173
179
  |------|------|
174
180
  | `--doc-name` | (`upload-file`)服务端文档名,默认取本地文件名 |
175
181
  | `--file-path` | 服务端逻辑路径(归档/分类用) |
176
- | `--no-wait` | 不等 chunking 完成立即返回 |
182
+ | `--wait` | 等到 ingest 成功、失败或达到原有超时;用于迁移旧的默认等待行为 |
183
+ | `--no-wait` | 兼容参数;与新的“受理后立即返回”默认行为相同 |
184
+
185
+ `--wait` 与 `--no-wait` 互斥。无等待模式返回的
186
+ `ingest_status=processing` 不能当作终态成功。
177
187
 
178
188
  ### `kb create` 全部 flag
179
189
 
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ checkLatestVersion,
4
+ recordVersionCheckFailure,
5
+ recordVersionCheckSuccess,
6
+ releaseVersionCheckLock
7
+ } from "../chunk-BQA7YSXT.js";
8
+
9
+ // src/workers/version-check.ts
10
+ import { fileURLToPath } from "url";
11
+ import { dirname, resolve } from "path";
12
+ function runVersionCheckWorker(options) {
13
+ const now = options.now ?? Date.now;
14
+ try {
15
+ const result = (options.check ?? checkLatestVersion)(options.currentVersion);
16
+ if (result.error || result.latest === null) {
17
+ recordVersionCheckFailure(options.paths, options.currentVersion, now());
18
+ } else {
19
+ recordVersionCheckSuccess(
20
+ options.paths,
21
+ options.currentVersion,
22
+ result.latest,
23
+ now()
24
+ );
25
+ }
26
+ } catch {
27
+ recordVersionCheckFailure(options.paths, options.currentVersion, now());
28
+ } finally {
29
+ releaseVersionCheckLock(options.paths, options.lockToken);
30
+ }
31
+ }
32
+ function parseWorkerArgs(argv) {
33
+ const values = /* @__PURE__ */ new Map();
34
+ for (const argument of argv) {
35
+ if (!argument.startsWith("--")) continue;
36
+ const separator = argument.indexOf("=");
37
+ if (separator < 3) continue;
38
+ values.set(argument.slice(2, separator), argument.slice(separator + 1));
39
+ }
40
+ const currentVersion = values.get("current-version");
41
+ const statePath = values.get("state-path");
42
+ const lockPath = values.get("lock-path");
43
+ const lockToken = values.get("lock-token");
44
+ if (!currentVersion || !statePath || !lockPath || !lockToken) return null;
45
+ return {
46
+ currentVersion,
47
+ lockToken,
48
+ paths: { cacheDir: dirname(statePath), statePath, lockPath }
49
+ };
50
+ }
51
+ function isProcessEntryPoint() {
52
+ if (!process.argv[1]) return false;
53
+ try {
54
+ return resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url));
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+ if (isProcessEntryPoint()) {
60
+ const options = parseWorkerArgs(process.argv.slice(2));
61
+ if (options) runVersionCheckWorker(options);
62
+ }
63
+ export {
64
+ runVersionCheckWorker
65
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliyunrds/ctxdb",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
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",
@@ -1,204 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/lib/kb.ts
4
- import { readFileSync, existsSync, statSync } from "fs";
5
- import { basename, extname } from "path";
6
- import { homedir } from "os";
7
- import { resolve } from "path";
8
- import {
9
- buildNormalizedGraphContext,
10
- extractKnowledgeBaseIds,
11
- extractKnowledgeChunkContent,
12
- extractKnowledgeChunkSourceLabel,
13
- extractKnowledgeChunkTags,
14
- partitionKnowledgeChunks
15
- } from "@aliyunrds/ctxdb-shared";
16
- var KB_COLLECTION = "/v1/knowledge/knowledge_bases";
17
- var DOCUMENTS = "/v1/knowledge/documents";
18
- var FILES = "/v1/knowledge/files";
19
- var DOCUMENT_DETAIL = "/v1/knowledge/documents/detail";
20
- var DEFAULT_POLL_INTERVAL_MS = 1500;
21
- var DEFAULT_INGEST_TIMEOUT_MS = 3e4;
22
- var DEFAULT_FILE_INGEST_TIMEOUT_MS = 6e4;
23
- var MIME_BY_EXT = {
24
- ".pdf": "application/pdf",
25
- ".txt": "text/plain",
26
- ".md": "text/markdown",
27
- ".markdown": "text/markdown",
28
- ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
29
- ".doc": "application/msword",
30
- ".html": "text/html",
31
- ".htm": "text/html",
32
- ".json": "application/json",
33
- ".csv": "text/csv",
34
- ".xml": "application/xml",
35
- ".rtf": "application/rtf"
36
- };
37
- async function listKnowledgeBases(client) {
38
- const resp = await client.get(KB_COLLECTION);
39
- if (Array.isArray(resp)) return resp;
40
- if (resp && typeof resp === "object") {
41
- const o = resp;
42
- return o.knowledge_bases ?? o.results ?? [];
43
- }
44
- return [];
45
- }
46
- async function createKb(client, kbName, description = "") {
47
- return client.postJson(KB_COLLECTION, { name: kbName, description: description || "" });
48
- }
49
- async function uploadText(client, kbName, docName, text, mimeType = "text/plain", filePath) {
50
- const body = {
51
- knowledge_base_name: kbName,
52
- name: docName,
53
- text,
54
- mime_type: mimeType
55
- };
56
- if (filePath !== void 0 && filePath !== "") body.file_path = filePath;
57
- return client.postJson(DOCUMENTS, body);
58
- }
59
- async function uploadFile(client, kbName, localPath, options = {}) {
60
- const MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
61
- const expanded = expandHome(localPath);
62
- if (!existsSync(expanded)) throw new Error(`file not found: ${expanded}`);
63
- const stat = statSync(expanded);
64
- if (!stat.isFile()) throw new Error(`not a file: ${expanded}`);
65
- if (stat.size > MAX_UPLOAD_BYTES) {
66
- throw new Error(
67
- `file too large (${(stat.size / 1024 / 1024).toFixed(1)} MB), maximum is 100 MB`
68
- );
69
- }
70
- const filename = basename(expanded);
71
- const docName = options.docName ?? filename;
72
- const content = readFileSync(expanded);
73
- const mime = guessMime(expanded);
74
- const fields = {
75
- knowledge_base_name: kbName,
76
- name: docName
77
- };
78
- if (options.filePath !== void 0 && options.filePath !== "") {
79
- fields.file_path = options.filePath;
80
- }
81
- return client.postMultipart(
82
- FILES,
83
- fields,
84
- { file: { filename, content, mimeType: mime } },
85
- { timeoutMs: options.timeoutMs }
86
- );
87
- }
88
- function guessMime(path) {
89
- const ext = extname(path).toLowerCase();
90
- if (ext in MIME_BY_EXT) return MIME_BY_EXT[ext];
91
- return "application/octet-stream";
92
- }
93
- async function getDocument(client, kbName, docId) {
94
- return client.get(DOCUMENT_DETAIL, {
95
- knowledge_base_name: kbName,
96
- document_id: docId
97
- });
98
- }
99
- async function listDocuments(client, kbName) {
100
- const resp = await client.get(DOCUMENTS, { knowledge_base_name: kbName });
101
- if (Array.isArray(resp)) return resp;
102
- if (resp && typeof resp === "object") {
103
- const o = resp;
104
- return o.documents ?? o.results ?? [];
105
- }
106
- return [];
107
- }
108
- async function pollIngest(client, kbName, docId, options = {}) {
109
- const timeoutMs = options.timeoutMs ?? DEFAULT_INGEST_TIMEOUT_MS;
110
- const intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
111
- const sleep = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
112
- const now = options.now ?? (() => performance.now());
113
- const deadline = now() + timeoutMs;
114
- let doc = await getDocument(client, kbName, docId);
115
- let timedOut = false;
116
- while (ingestInFlight(doc)) {
117
- if (now() >= deadline) {
118
- timedOut = true;
119
- break;
120
- }
121
- await sleep(intervalMs);
122
- try {
123
- doc = await getDocument(client, kbName, docId);
124
- } catch {
125
- break;
126
- }
127
- }
128
- if (doc && typeof doc === "object") {
129
- return { ...doc, _pollingTimedOut: timedOut };
130
- }
131
- return { _pollingTimedOut: timedOut };
132
- }
133
- function ingestInFlight(doc) {
134
- if (!doc || typeof doc !== "object") return false;
135
- const status = doc.ingest_status;
136
- return status === "processing" || status === "pending" || status === "in_progress";
137
- }
138
- function expandHome(p) {
139
- if (p.startsWith("~/") || p === "~") {
140
- return resolve(homedir(), p.slice(2));
141
- }
142
- return resolve(p);
143
- }
144
- function compactChunk(raw) {
145
- const c = raw ?? {};
146
- const content = extractKnowledgeChunkContent(raw);
147
- const doc_name = extractKnowledgeChunkSourceLabel(raw);
148
- const kb_id = extractKnowledgeBaseIds(raw)[0] ?? "";
149
- const docIdRaw = c.doc_id;
150
- const scoreRaw = c.similarity ?? c.rerank_score;
151
- const tags = extractKnowledgeChunkTags(raw);
152
- const out = {
153
- content,
154
- doc_name,
155
- kb_id,
156
- score: typeof scoreRaw === "number" ? scoreRaw : 0
157
- };
158
- if (typeof docIdRaw === "string" && docIdRaw.length > 0) {
159
- out.doc_id = docIdRaw;
160
- }
161
- if (tags.length > 0) {
162
- out.tags = tags;
163
- }
164
- return out;
165
- }
166
- function projectKbQueryResponse(raw, projectChunk, options = {}) {
167
- if (!raw || typeof raw !== "object") return { chunks: [] };
168
- const r = raw;
169
- const chunksIn = Array.isArray(r.chunks) ? r.chunks : [];
170
- const { graphChunks, documentChunks } = partitionKnowledgeChunks(chunksIn);
171
- const graphContext = buildNormalizedGraphContext(graphChunks, {
172
- verbose: options.verboseGraph
173
- });
174
- const out = {
175
- chunks: documentChunks.map(projectChunk)
176
- };
177
- if (typeof r.total === "number") out.total = r.total;
178
- if (graphContext) out.graph_context = graphContext;
179
- return out;
180
- }
181
- function compactKbQueryResponse(raw) {
182
- return projectKbQueryResponse(raw, compactChunk, { verboseGraph: true });
183
- }
184
- function minimalChunk(raw) {
185
- const c = compactChunk(raw);
186
- return { content: c.content, score: c.score };
187
- }
188
- function minimalKbQueryResponse(raw) {
189
- return projectKbQueryResponse(raw, minimalChunk);
190
- }
191
-
192
- export {
193
- DEFAULT_INGEST_TIMEOUT_MS,
194
- DEFAULT_FILE_INGEST_TIMEOUT_MS,
195
- listKnowledgeBases,
196
- createKb,
197
- uploadText,
198
- uploadFile,
199
- getDocument,
200
- listDocuments,
201
- pollIngest,
202
- compactKbQueryResponse,
203
- minimalKbQueryResponse
204
- };