@aliyunrds/ctxdb 1.0.2 → 1.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/README.md +174 -5
- package/dist/chunk-3PFMHU3C.js +442 -0
- package/dist/chunk-BQA7YSXT.js +462 -0
- package/dist/{chunk-2CSEFSLC.js → chunk-BVCDRUU4.js} +1 -1
- package/dist/{chunk-WTP4ZX22.js → chunk-CWGF5D52.js} +2 -2
- package/dist/{chunk-6FZL67GH.js → chunk-JFTKYEVN.js} +333 -45
- package/dist/{chunk-EUQ3OFCQ.js → chunk-Q4JYST7K.js} +3 -3
- package/dist/{chunk-IMYLU5C2.js → chunk-SAQT6VL6.js} +2 -2
- package/dist/{chunk-TGVURF54.js → chunk-USMJLDBD.js} +1 -1
- package/dist/cli/main.js +347 -160
- package/dist/hooks/hermes-post-llm-call.js +3 -3
- package/dist/hooks/hermes-pre-llm-call.js +6 -6
- package/dist/hooks/session-start.js +5 -5
- package/dist/hooks/stop.js +3 -3
- package/dist/hooks/user-prompt-submit.js +5 -5
- package/dist/setup/skills/contextdb-knowledge/SKILL.md +13 -3
- package/dist/workers/version-check.js +65 -0
- package/package.json +1 -1
- package/dist/chunk-UH7AJF6F.js +0 -204
package/dist/cli/main.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
DEFAULT_FILE_INGEST_TIMEOUT_MS,
|
|
4
|
+
DEFAULT_FILE_UPLOAD_TIMEOUT_MS,
|
|
4
5
|
DEFAULT_INGEST_TIMEOUT_MS,
|
|
5
6
|
compactKbQueryResponse,
|
|
6
7
|
createKb,
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
pollIngest,
|
|
12
13
|
uploadFile,
|
|
13
14
|
uploadText
|
|
14
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-3PFMHU3C.js";
|
|
15
16
|
import {
|
|
16
17
|
DEFAULT_BASE_URL,
|
|
17
18
|
DEFAULT_USER_ID,
|
|
@@ -21,7 +22,10 @@ import {
|
|
|
21
22
|
agentFromEnv,
|
|
22
23
|
agentHomeDir,
|
|
23
24
|
agentHomeDirs,
|
|
25
|
+
agentPlatformSupport,
|
|
24
26
|
configuredAgents,
|
|
27
|
+
detectInstalledAgents,
|
|
28
|
+
inspectAgentHomes,
|
|
25
29
|
isAgentSlug,
|
|
26
30
|
isBuiltinAgent,
|
|
27
31
|
isComplete,
|
|
@@ -29,7 +33,12 @@ import {
|
|
|
29
33
|
removeAgent,
|
|
30
34
|
save,
|
|
31
35
|
writeInstalledPkgVersion
|
|
32
|
-
} from "../chunk-
|
|
36
|
+
} from "../chunk-JFTKYEVN.js";
|
|
37
|
+
import {
|
|
38
|
+
beginUpdateNotification,
|
|
39
|
+
completeUpdateNotification,
|
|
40
|
+
runSelfUpdate
|
|
41
|
+
} from "../chunk-BQA7YSXT.js";
|
|
33
42
|
|
|
34
43
|
// src/cli/util.ts
|
|
35
44
|
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
@@ -55,6 +64,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
55
64
|
"all",
|
|
56
65
|
// memory delete
|
|
57
66
|
// kb
|
|
67
|
+
"wait",
|
|
68
|
+
// kb upload-text / upload-file
|
|
58
69
|
"no-wait",
|
|
59
70
|
// kb upload-text / upload-file
|
|
60
71
|
"verbose",
|
|
@@ -125,7 +136,12 @@ function isSetupResult(v) {
|
|
|
125
136
|
}
|
|
126
137
|
function isUpgradeResult(v) {
|
|
127
138
|
if (typeof v !== "object" || v === null) return false;
|
|
128
|
-
return "agents" in v && typeof v.agents === "object" && !("steps" in v);
|
|
139
|
+
return "agents" in v && typeof v.agents === "object" && !("steps" in v) && !("mode" in v);
|
|
140
|
+
}
|
|
141
|
+
function isMultiAgentResult(v) {
|
|
142
|
+
if (typeof v !== "object" || v === null) return false;
|
|
143
|
+
const value = v;
|
|
144
|
+
return value.mode === "all" && (value.operation === "setup" || value.operation === "status") && typeof value.agents === "object" && value.agents !== null && Array.isArray(value.skipped) && typeof value.summary === "object" && value.summary !== null;
|
|
129
145
|
}
|
|
130
146
|
function isStatusResult(v) {
|
|
131
147
|
if (typeof v !== "object" || v === null) return false;
|
|
@@ -158,6 +174,45 @@ function formatUpgradeResult(r) {
|
|
|
158
174
|
}
|
|
159
175
|
return lines.join("\n");
|
|
160
176
|
}
|
|
177
|
+
function formatMultiAgentResult(r) {
|
|
178
|
+
const lines = [];
|
|
179
|
+
const { selected, succeeded, failed, skipped } = r.summary;
|
|
180
|
+
lines.push(
|
|
181
|
+
`${r.ok ? CHECK : CROSS} ${BOLD}ctxdb ${r.operation} --all${RESET} ${r.ok ? "completed" : "failed"} ${DIM}(${selected} selected, ${succeeded} succeeded, ${failed} failed, ${skipped} skipped)${RESET}
|
|
182
|
+
`
|
|
183
|
+
);
|
|
184
|
+
for (const [name, result] of Object.entries(r.agents)) {
|
|
185
|
+
const agentOk = r.operation === "setup" ? Boolean(result.ok) : Boolean(result.ok && result.connected);
|
|
186
|
+
lines.push(` ${agentOk ? CHECK : CROSS} ${BOLD}${name}${RESET}`);
|
|
187
|
+
if (r.operation === "setup") {
|
|
188
|
+
for (const step of result.steps ?? []) {
|
|
189
|
+
const detail = step.detail ? ` ${DIM}${step.detail}${RESET}` : "";
|
|
190
|
+
lines.push(` ${step.ok ? CHECK : CROSS} ${step.step}${detail}`);
|
|
191
|
+
}
|
|
192
|
+
for (const hint of result.hints ?? []) {
|
|
193
|
+
lines.push(` ${DIM}hint${RESET} ${hint}`);
|
|
194
|
+
}
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
lines.push(` ${DIM}config${RESET} ${result.ok ? "complete" : "incomplete"}`);
|
|
198
|
+
lines.push(` ${DIM}connected${RESET} ${result.connected ? "yes" : "no"}`);
|
|
199
|
+
if (result.hooks_node !== void 0) {
|
|
200
|
+
lines.push(` ${DIM}hooks${RESET} ${result.hooks_node}`);
|
|
201
|
+
}
|
|
202
|
+
if (result.ping_error) {
|
|
203
|
+
lines.push(` ${DIM}ping_error${RESET} ${result.ping_error}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (r.skipped.length > 0) {
|
|
207
|
+
lines.push("");
|
|
208
|
+
lines.push(` ${DIM}skipped${RESET}`);
|
|
209
|
+
for (const item of r.skipped) {
|
|
210
|
+
const detail = item.detail ? ` \u2014 ${item.detail}` : "";
|
|
211
|
+
lines.push(` ${item.agent}: ${item.reason}${detail}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return lines.join("\n");
|
|
215
|
+
}
|
|
161
216
|
function formatStatusResult(r) {
|
|
162
217
|
const lines = [];
|
|
163
218
|
const ok = r.connected ? CHECK : CROSS;
|
|
@@ -190,6 +245,8 @@ function formatStatusResult(r) {
|
|
|
190
245
|
function printResult(value, json, command) {
|
|
191
246
|
if (json) {
|
|
192
247
|
process.stdout.write(JSON.stringify(value, null, 2) + "\n");
|
|
248
|
+
} else if (isMultiAgentResult(value)) {
|
|
249
|
+
process.stdout.write(formatMultiAgentResult(value) + "\n");
|
|
193
250
|
} else if (isUpgradeResult(value)) {
|
|
194
251
|
process.stdout.write(formatUpgradeResult(value) + "\n");
|
|
195
252
|
} else if (isSetupResult(value)) {
|
|
@@ -227,6 +284,9 @@ function fail(message, code = 1) {
|
|
|
227
284
|
process.exit(code);
|
|
228
285
|
}
|
|
229
286
|
|
|
287
|
+
// src/cli/main.ts
|
|
288
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
289
|
+
|
|
230
290
|
// src/setup/installer.ts
|
|
231
291
|
import {
|
|
232
292
|
readFileSync,
|
|
@@ -248,6 +308,10 @@ import { execFileSync } from "child_process";
|
|
|
248
308
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
249
309
|
var UNINSTALL_NPM_HINT = "To also remove the npm binaries: `npm uninstall -g @aliyunrds/ctxdb @aliyunrds/ctxdb-shared`";
|
|
250
310
|
var UNINSTALL_ORDER_HINT = "When you eventually want to uninstall: run `ctxdb uninstall --purge-all` FIRST, then `npm uninstall -g @aliyunrds/ctxdb @aliyunrds/ctxdb-shared`. (npm 7+ removed uninstall lifecycle hooks, so the order matters \u2014 otherwise agent settings.json hooks + ~/.ctxdb/ residue stay behind.)";
|
|
311
|
+
var HERMES_RESTART_HINT = "Restart any running Hermes CLI or gateway process to load the registered hooks; Hermes registers shell hooks only at process startup.";
|
|
312
|
+
var HERMES_ALLOWLIST_ACTION_HINT = "Next action [hermes-hook-allowlist]: run `hermes --accept-hooks chat`; after Hermes starts, exit the chat and rerun `ctxdb setup --agent hermes`, then restart any running Hermes CLI or gateway process.";
|
|
313
|
+
var HERMES_WEBUI_GATEWAY_HINT = "Using hermes-webui? Its default legacy backend does not load Hermes shell hooks. Set `HERMES_WEBUI_CHAT_BACKEND=gateway` to route chat through Hermes Gateway; if the gateway requires authentication, also set `HERMES_WEBUI_GATEWAY_API_KEY`, then restart hermes-webui. Reference: https://github.com/nesquena/hermes-webui/blob/master/docs/advanced-chat-setup.md#gateway-backed-browser-chat";
|
|
314
|
+
var NO_AGENTS_DETECTED_HINT = "No setup-compatible Agent detected. Install or start a supported Agent once, then rerun `ctxdb setup --all`; use `ctxdb setup --agent <name>` to target one explicitly.";
|
|
251
315
|
function skillInstallRoot(agent) {
|
|
252
316
|
switch (agent) {
|
|
253
317
|
case "qoder":
|
|
@@ -579,8 +643,13 @@ async function runSetup(options) {
|
|
|
579
643
|
}
|
|
580
644
|
}
|
|
581
645
|
}
|
|
582
|
-
const
|
|
646
|
+
const failedSteps = steps.filter((s) => !s.ok);
|
|
647
|
+
const ok = failedSteps.length === 0;
|
|
648
|
+
const actionRequired = agent === "hermes" && failedSteps.length === 1 && failedSteps[0]?.step === "check-hermes-hook-allowlist" ? "hermes-hook-allowlist" : void 0;
|
|
583
649
|
const hints = ok ? [UNINSTALL_ORDER_HINT] : [];
|
|
650
|
+
if (actionRequired) {
|
|
651
|
+
hints.unshift(HERMES_ALLOWLIST_ACTION_HINT, HERMES_WEBUI_GATEWAY_HINT);
|
|
652
|
+
}
|
|
584
653
|
if (ok && agent === "opencode") {
|
|
585
654
|
hints.unshift(
|
|
586
655
|
`OpenCode plugin shim: ${opencodeShimPath()}`,
|
|
@@ -589,10 +658,98 @@ async function runSetup(options) {
|
|
|
589
658
|
}
|
|
590
659
|
if (ok && agent === "hermes") {
|
|
591
660
|
hints.unshift(
|
|
592
|
-
`Hermes shell hooks: ${hermesConfigPath()} \u2192 pre_llm_call + post_llm_call
|
|
661
|
+
`Hermes shell hooks: ${hermesConfigPath()} \u2192 pre_llm_call + post_llm_call`,
|
|
662
|
+
HERMES_RESTART_HINT,
|
|
663
|
+
HERMES_WEBUI_GATEWAY_HINT
|
|
593
664
|
);
|
|
594
665
|
}
|
|
595
|
-
return {
|
|
666
|
+
return {
|
|
667
|
+
ok,
|
|
668
|
+
steps,
|
|
669
|
+
actionRequired,
|
|
670
|
+
hints: hints.length > 0 ? hints : void 0
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
function skippedFromDetection(detection) {
|
|
674
|
+
return detection.observations.filter((item) => !item.selected).map((item) => ({
|
|
675
|
+
agent: item.agent,
|
|
676
|
+
reason: item.reason,
|
|
677
|
+
evidence: item.evidence,
|
|
678
|
+
...item.detail ? { detail: item.detail } : {}
|
|
679
|
+
}));
|
|
680
|
+
}
|
|
681
|
+
function withoutSharedUninstallHint(result) {
|
|
682
|
+
const hints = result.hints?.filter((hint) => hint !== UNINSTALL_ORDER_HINT);
|
|
683
|
+
return {
|
|
684
|
+
...result,
|
|
685
|
+
...hints && hints.length > 0 ? { hints } : { hints: void 0 }
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
function missingApiKeyResult(agent) {
|
|
689
|
+
return {
|
|
690
|
+
ok: false,
|
|
691
|
+
steps: [{
|
|
692
|
+
step: "write-config",
|
|
693
|
+
ok: false,
|
|
694
|
+
detail: `${agent}: --api-key is required (won't write config without a valid API key)`
|
|
695
|
+
}]
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
async function runSetupAll(options = {}, dependencies = {}) {
|
|
699
|
+
const detect = dependencies.detect ?? detectInstalledAgents;
|
|
700
|
+
const loadConfig = dependencies.loadConfig ?? ((agent) => load({ agent }));
|
|
701
|
+
const setup2 = dependencies.setup ?? runSetup;
|
|
702
|
+
const detection = detect(options.detection);
|
|
703
|
+
const agents = {};
|
|
704
|
+
if (detection.selected.length === 0) {
|
|
705
|
+
return {
|
|
706
|
+
ok: false,
|
|
707
|
+
operation: "setup",
|
|
708
|
+
mode: "all",
|
|
709
|
+
agents,
|
|
710
|
+
skipped: skippedFromDetection(detection),
|
|
711
|
+
summary: { selected: 0, succeeded: 0, failed: 0, skipped: detection.observations.length },
|
|
712
|
+
hints: [NO_AGENTS_DETECTED_HINT]
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
const configSnapshot = /* @__PURE__ */ new Map();
|
|
716
|
+
for (const agent of detection.selected) {
|
|
717
|
+
configSnapshot.set(agent, loadConfig(agent));
|
|
718
|
+
}
|
|
719
|
+
for (const agent of detection.selected) {
|
|
720
|
+
const existing = configSnapshot.get(agent);
|
|
721
|
+
const apiKey = options.apiKey ?? existing.apiKey;
|
|
722
|
+
if (!apiKey) {
|
|
723
|
+
agents[agent] = missingApiKeyResult(agent);
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
agents[agent] = withoutSharedUninstallHint(await setup2({
|
|
727
|
+
agent,
|
|
728
|
+
apiKey,
|
|
729
|
+
baseUrl: options.baseUrl ?? existing.baseUrl,
|
|
730
|
+
userId: options.userId ?? existing.userId,
|
|
731
|
+
installSkill: options.installSkill,
|
|
732
|
+
validate: options.validate
|
|
733
|
+
}));
|
|
734
|
+
}
|
|
735
|
+
const results = Object.values(agents);
|
|
736
|
+
const succeeded = results.filter((result) => result.ok).length;
|
|
737
|
+
const failed = results.length - succeeded;
|
|
738
|
+
const skipped = skippedFromDetection(detection);
|
|
739
|
+
return {
|
|
740
|
+
ok: failed === 0,
|
|
741
|
+
operation: "setup",
|
|
742
|
+
mode: "all",
|
|
743
|
+
agents,
|
|
744
|
+
skipped,
|
|
745
|
+
summary: {
|
|
746
|
+
selected: results.length,
|
|
747
|
+
succeeded,
|
|
748
|
+
failed,
|
|
749
|
+
skipped: skipped.length
|
|
750
|
+
},
|
|
751
|
+
hints: [UNINSTALL_ORDER_HINT]
|
|
752
|
+
};
|
|
596
753
|
}
|
|
597
754
|
function runRemove(agent, options = {}) {
|
|
598
755
|
const steps = [];
|
|
@@ -794,11 +951,12 @@ function runRemove(agent, options = {}) {
|
|
|
794
951
|
return { ok: steps.every((s) => s.ok), steps };
|
|
795
952
|
}
|
|
796
953
|
function checkAgentHome(agent) {
|
|
797
|
-
|
|
954
|
+
const platform = agentPlatformSupport(agent);
|
|
955
|
+
if (!platform.supported) {
|
|
798
956
|
return {
|
|
799
957
|
step: "check-agent-home",
|
|
800
958
|
ok: false,
|
|
801
|
-
detail:
|
|
959
|
+
detail: platform.detail
|
|
802
960
|
};
|
|
803
961
|
}
|
|
804
962
|
if (agent === "opencode" || agent === "hermes") {
|
|
@@ -814,7 +972,7 @@ function checkAgentHome(agent) {
|
|
|
814
972
|
};
|
|
815
973
|
}
|
|
816
974
|
}
|
|
817
|
-
const dirs =
|
|
975
|
+
const dirs = inspectAgentHomes(agent).existing;
|
|
818
976
|
if (dirs.length === 0) {
|
|
819
977
|
const primary = agentHomeDir(agent);
|
|
820
978
|
return {
|
|
@@ -845,23 +1003,27 @@ function runTeardown(options = {}) {
|
|
|
845
1003
|
}
|
|
846
1004
|
if (purgeConfig) {
|
|
847
1005
|
const cfgPath = join(homedir(), ".ctxdb", "ctxdb.json");
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
steps.push({ step: "purge-config", ok: true, detail: cfgPath });
|
|
852
|
-
} catch (err) {
|
|
853
|
-
steps.push({
|
|
854
|
-
step: "purge-config",
|
|
855
|
-
ok: false,
|
|
856
|
-
detail: `${cfgPath}: ${err?.message ?? String(err)}`
|
|
857
|
-
});
|
|
858
|
-
}
|
|
859
|
-
} else {
|
|
1006
|
+
const ownedConfigFiles = [cfgPath, `${cfgPath}.bak`];
|
|
1007
|
+
const existing = ownedConfigFiles.filter((path) => existsSync(path));
|
|
1008
|
+
if (existing.length === 0) {
|
|
860
1009
|
steps.push({
|
|
861
1010
|
step: "purge-config",
|
|
862
1011
|
ok: true,
|
|
863
1012
|
detail: `nothing to remove (${cfgPath})`
|
|
864
1013
|
});
|
|
1014
|
+
} else {
|
|
1015
|
+
for (const path of existing) {
|
|
1016
|
+
try {
|
|
1017
|
+
unlinkSync(path);
|
|
1018
|
+
steps.push({ step: "purge-config", ok: true, detail: path });
|
|
1019
|
+
} catch (err) {
|
|
1020
|
+
steps.push({
|
|
1021
|
+
step: "purge-config",
|
|
1022
|
+
ok: false,
|
|
1023
|
+
detail: `${path}: ${err?.message ?? String(err)}`
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
865
1027
|
}
|
|
866
1028
|
}
|
|
867
1029
|
if (purgeLogs) {
|
|
@@ -1357,7 +1519,7 @@ function hermesAllowlistPath() {
|
|
|
1357
1519
|
}
|
|
1358
1520
|
function hermesHookApprovalHint(events = HERMES_HOOK_EVENTS) {
|
|
1359
1521
|
const hookNames = events.map((event) => `\`${event}\``).join(" and ");
|
|
1360
|
-
return `Approve the Hermes ctxdb hooks ${hookNames}: run \`hermes --accept-hooks chat\` once. This command opens an interactive chat; after Hermes starts, exit the chat,
|
|
1522
|
+
return `Approve the Hermes ctxdb hooks ${hookNames}: run \`hermes --accept-hooks chat\` once. This command opens an interactive chat; after Hermes starts, exit the chat, rerun \`ctxdb setup --agent hermes\`, then restart any running Hermes CLI or gateway process.`;
|
|
1361
1523
|
}
|
|
1362
1524
|
function backupHermesConfig() {
|
|
1363
1525
|
backupSettingsFile(hermesConfigPath());
|
|
@@ -1806,8 +1968,17 @@ async function runUpgrade(options = {}) {
|
|
|
1806
1968
|
}
|
|
1807
1969
|
|
|
1808
1970
|
// src/cli/top.ts
|
|
1809
|
-
|
|
1810
|
-
|
|
1971
|
+
var STATUS_HELP = `ctxdb status \u2014 inspect configuration and connectivity
|
|
1972
|
+
|
|
1973
|
+
USAGE
|
|
1974
|
+
ctxdb status [--agent <qoder|qoderwork|codex|claude|opencode|hermes|default> | --all] [--json]
|
|
1975
|
+
|
|
1976
|
+
FLAGS
|
|
1977
|
+
--agent <name> Inspect exactly one Agent profile
|
|
1978
|
+
--all Inspect every setup-compatible detected built-in Agent
|
|
1979
|
+
--json Machine-readable output
|
|
1980
|
+
`;
|
|
1981
|
+
async function inspectStatus(agent) {
|
|
1811
1982
|
const cfg = load({ agent });
|
|
1812
1983
|
const complete = isComplete(cfg);
|
|
1813
1984
|
let connected = false;
|
|
@@ -1822,8 +1993,8 @@ async function status(args) {
|
|
|
1822
1993
|
}
|
|
1823
1994
|
}
|
|
1824
1995
|
const hookHealth = isBuiltinAgent(agent) ? checkHookNodePaths(agent) : { installed: false, nodePaths: [], nodeOk: true, detail: "no hooks (default agent)" };
|
|
1825
|
-
|
|
1826
|
-
{
|
|
1996
|
+
return {
|
|
1997
|
+
result: {
|
|
1827
1998
|
ok: complete,
|
|
1828
1999
|
agent,
|
|
1829
2000
|
base_url: cfg.baseUrl,
|
|
@@ -1840,9 +2011,69 @@ async function status(args) {
|
|
|
1840
2011
|
hooks_node_ok: hookHealth.nodeOk,
|
|
1841
2012
|
version: PACKAGE_VERSION
|
|
1842
2013
|
},
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
2014
|
+
success: complete && connected
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
2017
|
+
function statusSkips(detection) {
|
|
2018
|
+
return {
|
|
2019
|
+
selected: detection.selected,
|
|
2020
|
+
skipped: detection.observations.filter((item) => !item.selected).map((item) => ({
|
|
2021
|
+
agent: item.agent,
|
|
2022
|
+
reason: item.reason,
|
|
2023
|
+
evidence: item.evidence,
|
|
2024
|
+
...item.detail ? { detail: item.detail } : {}
|
|
2025
|
+
}))
|
|
2026
|
+
};
|
|
2027
|
+
}
|
|
2028
|
+
async function statusAll(dependencies = {}) {
|
|
2029
|
+
const detection = statusSkips((dependencies.detect ?? detectInstalledAgents)());
|
|
2030
|
+
const inspect = dependencies.inspect ?? inspectStatus;
|
|
2031
|
+
const agents = {};
|
|
2032
|
+
let succeeded = 0;
|
|
2033
|
+
for (const agent of detection.selected) {
|
|
2034
|
+
const inspection = await inspect(agent);
|
|
2035
|
+
agents[agent] = inspection.result;
|
|
2036
|
+
if (inspection.success) succeeded += 1;
|
|
2037
|
+
}
|
|
2038
|
+
const failed = detection.selected.length - succeeded;
|
|
2039
|
+
return {
|
|
2040
|
+
ok: detection.selected.length > 0 && failed === 0,
|
|
2041
|
+
operation: "status",
|
|
2042
|
+
mode: "all",
|
|
2043
|
+
agents,
|
|
2044
|
+
skipped: detection.skipped,
|
|
2045
|
+
summary: {
|
|
2046
|
+
selected: detection.selected.length,
|
|
2047
|
+
succeeded,
|
|
2048
|
+
failed,
|
|
2049
|
+
skipped: detection.skipped.length
|
|
2050
|
+
},
|
|
2051
|
+
...detection.selected.length === 0 ? { hints: ["No setup-compatible Agent detected. Install or start one, then rerun `ctxdb status --all`."] } : {}
|
|
2052
|
+
};
|
|
2053
|
+
}
|
|
2054
|
+
async function status(args) {
|
|
2055
|
+
if (args.flags.help || args.flags.h) {
|
|
2056
|
+
process.stdout.write(STATUS_HELP);
|
|
2057
|
+
return 0;
|
|
2058
|
+
}
|
|
2059
|
+
if (args.flags.all === true) {
|
|
2060
|
+
if (args.flags.agent !== void 0) {
|
|
2061
|
+
process.stderr.write("cannot use --all and --agent together\n");
|
|
2062
|
+
return 2;
|
|
2063
|
+
}
|
|
2064
|
+
const result = await statusAll();
|
|
2065
|
+
printResult(result, !!args.flags.json);
|
|
2066
|
+
if (!args.flags.json && result.hints) {
|
|
2067
|
+
for (const hint of result.hints) process.stderr.write(`
|
|
2068
|
+
${hint}
|
|
2069
|
+
`);
|
|
2070
|
+
}
|
|
2071
|
+
return result.ok ? 0 : 1;
|
|
2072
|
+
}
|
|
2073
|
+
const agent = agentFromFlags(args.flags);
|
|
2074
|
+
const inspection = await inspectStatus(agent);
|
|
2075
|
+
printResult(inspection.result, !!args.flags.json);
|
|
2076
|
+
return inspection.success ? 0 : 1;
|
|
1846
2077
|
}
|
|
1847
2078
|
async function ping(args) {
|
|
1848
2079
|
const agent = agentFromFlags(args.flags);
|
|
@@ -1862,7 +2093,7 @@ async function ping(args) {
|
|
|
1862
2093
|
var HELP = `ctxdb setup \u2014 configure an agent
|
|
1863
2094
|
|
|
1864
2095
|
USAGE
|
|
1865
|
-
ctxdb setup [--agent <qoder|qoderwork|codex|claude|opencode|hermes>]
|
|
2096
|
+
ctxdb setup [--agent <qoder|qoderwork|codex|claude|opencode|hermes> | --all]
|
|
1866
2097
|
[--api-key=K] [--base-url=URL] [--user-id=ID]
|
|
1867
2098
|
[--no-install-skill] [--no-validate] [--json]
|
|
1868
2099
|
|
|
@@ -1871,13 +2102,20 @@ BEHAVIOR
|
|
|
1871
2102
|
no hooks or skills installed).
|
|
1872
2103
|
With --agent Writes agent config + installs hooks + skills for the
|
|
1873
2104
|
specified agent harness.
|
|
2105
|
+
Rerun for a new Agent, to repair integration files, or
|
|
2106
|
+
with --api-key <new-key> to replace that Agent's key.
|
|
2107
|
+
With --all Detects setup-compatible Agents on this host and runs the
|
|
2108
|
+
same setup lifecycle sequentially for each one. Successful
|
|
2109
|
+
Agents are preserved when another Agent fails.
|
|
1874
2110
|
Hermes Also verifies ~/.hermes/shell-hooks-allowlist.json.
|
|
1875
2111
|
Approve pre_llm_call + post_llm_call with
|
|
1876
2112
|
\`hermes --accept-hooks chat\`. It opens interactive chat;
|
|
1877
|
-
exit after Hermes starts,
|
|
2113
|
+
exit after Hermes starts, rerun ctxdb setup, then restart
|
|
2114
|
+
any running Hermes CLI/gateway process to load the hooks.
|
|
1878
2115
|
|
|
1879
2116
|
FLAGS
|
|
1880
2117
|
--agent <name> Target agent (qoder|qoderwork|codex|claude|opencode|hermes)
|
|
2118
|
+
--all Target every setup-compatible detected Agent
|
|
1881
2119
|
--api-key <key> API key (required on first setup)
|
|
1882
2120
|
--base-url <url> Server URL (default: https://context-database.aliyuncs.com)
|
|
1883
2121
|
--user-id <id> User bucket (default: "default")
|
|
@@ -1885,6 +2123,10 @@ FLAGS
|
|
|
1885
2123
|
--no-validate Skip connectivity ping after setup
|
|
1886
2124
|
--json Machine-readable JSON output
|
|
1887
2125
|
`;
|
|
2126
|
+
var CODEX_HOOKS_TRUST_REMINDER = [
|
|
2127
|
+
"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",
|
|
2128
|
+
"\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 \u548C SessionStart \u91CC\u7684 aliyunrds/ctxdb \u94A9\u5B50\u3002"
|
|
2129
|
+
].join("\n");
|
|
1888
2130
|
function parseAgent(args) {
|
|
1889
2131
|
const raw = args.flags.agent;
|
|
1890
2132
|
if (raw === void 0) return "default";
|
|
@@ -1900,8 +2142,36 @@ async function setup(args) {
|
|
|
1900
2142
|
process.stdout.write(HELP);
|
|
1901
2143
|
return 0;
|
|
1902
2144
|
}
|
|
1903
|
-
const agent = parseAgent(args);
|
|
1904
2145
|
const json = !!args.flags.json;
|
|
2146
|
+
const all = args.flags.all === true;
|
|
2147
|
+
if (all && args.flags.agent !== void 0) {
|
|
2148
|
+
process.stderr.write("cannot use --all and --agent together\n");
|
|
2149
|
+
return 2;
|
|
2150
|
+
}
|
|
2151
|
+
if (all) {
|
|
2152
|
+
const result2 = await runSetupAll({
|
|
2153
|
+
apiKey: typeof args.flags["api-key"] === "string" ? args.flags["api-key"] : void 0,
|
|
2154
|
+
baseUrl: typeof args.flags["base-url"] === "string" ? args.flags["base-url"] : void 0,
|
|
2155
|
+
userId: typeof args.flags["user-id"] === "string" ? args.flags["user-id"] : void 0,
|
|
2156
|
+
installSkill: !args.flags["no-install-skill"],
|
|
2157
|
+
validate: !args.flags["no-validate"]
|
|
2158
|
+
});
|
|
2159
|
+
printResult(result2, json);
|
|
2160
|
+
if (!json && result2.hints) {
|
|
2161
|
+
for (const hint of result2.hints) process.stderr.write(`
|
|
2162
|
+
${hint}
|
|
2163
|
+
`);
|
|
2164
|
+
}
|
|
2165
|
+
if (!json && result2.agents.codex?.ok) {
|
|
2166
|
+
process.stderr.write(
|
|
2167
|
+
`
|
|
2168
|
+
${dim(CODEX_HOOKS_TRUST_REMINDER)}
|
|
2169
|
+
`
|
|
2170
|
+
);
|
|
2171
|
+
}
|
|
2172
|
+
return result2.ok ? 0 : 1;
|
|
2173
|
+
}
|
|
2174
|
+
const agent = parseAgent(args);
|
|
1905
2175
|
if (agent === "default" && !json && !configuredAgents().includes("default")) {
|
|
1906
2176
|
process.stderr.write(
|
|
1907
2177
|
`hint: creating CLI-only "default" agent (no hooks/skills). Use --agent <claude|qoder|qoderwork|codex|opencode|hermes> for full setup.
|
|
@@ -1925,7 +2195,7 @@ ${h}
|
|
|
1925
2195
|
if (!json && agent === "codex" && result.ok) {
|
|
1926
2196
|
process.stderr.write(
|
|
1927
2197
|
`
|
|
1928
|
-
${dim(
|
|
2198
|
+
${dim(CODEX_HOOKS_TRUST_REMINDER)}
|
|
1929
2199
|
`
|
|
1930
2200
|
);
|
|
1931
2201
|
}
|
|
@@ -1996,118 +2266,6 @@ ${h}
|
|
|
1996
2266
|
return result.ok ? 0 : 1;
|
|
1997
2267
|
}
|
|
1998
2268
|
|
|
1999
|
-
// src/lib/self-update.ts
|
|
2000
|
-
import { spawnSync } from "child_process";
|
|
2001
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2002
|
-
import { dirname as dirname2 } from "path";
|
|
2003
|
-
import semver from "semver";
|
|
2004
|
-
var PACKAGE_NAME = "@aliyunrds/ctxdb";
|
|
2005
|
-
var NPM_VIEW_TIMEOUT_MS = 1e4;
|
|
2006
|
-
function npmCommand(platform = process.platform) {
|
|
2007
|
-
return platform === "win32" ? "npm.cmd" : "npm";
|
|
2008
|
-
}
|
|
2009
|
-
function ctxdbCommand(platform = process.platform) {
|
|
2010
|
-
return platform === "win32" ? "ctxdb.cmd" : "ctxdb";
|
|
2011
|
-
}
|
|
2012
|
-
function detectInstallMethod() {
|
|
2013
|
-
const dir = dirname2(fileURLToPath2(import.meta.url));
|
|
2014
|
-
return dir.includes("/node_modules/") || dir.includes("\\node_modules\\") ? "npm" : "unknown";
|
|
2015
|
-
}
|
|
2016
|
-
function checkLatestVersion(currentVersion) {
|
|
2017
|
-
const result = spawnSync(npmCommand(), ["view", PACKAGE_NAME, "version"], {
|
|
2018
|
-
encoding: "utf-8",
|
|
2019
|
-
timeout: NPM_VIEW_TIMEOUT_MS,
|
|
2020
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
2021
|
-
shell: process.platform === "win32"
|
|
2022
|
-
});
|
|
2023
|
-
if (result.status !== 0 || !result.stdout?.trim()) {
|
|
2024
|
-
return {
|
|
2025
|
-
latest: null,
|
|
2026
|
-
current: currentVersion,
|
|
2027
|
-
isNewer: false,
|
|
2028
|
-
error: spawnFailureMessage(result, "npm view")
|
|
2029
|
-
};
|
|
2030
|
-
}
|
|
2031
|
-
const latest = result.stdout.trim();
|
|
2032
|
-
return {
|
|
2033
|
-
latest,
|
|
2034
|
-
current: currentVersion,
|
|
2035
|
-
isNewer: isNewerVersion(latest, currentVersion)
|
|
2036
|
-
};
|
|
2037
|
-
}
|
|
2038
|
-
function spawnFailureMessage(result, commandLabel) {
|
|
2039
|
-
const stderr = result.stderr?.toString().trim();
|
|
2040
|
-
if (stderr) return stderr;
|
|
2041
|
-
if (result.error) return `${commandLabel} failed: ${result.error.message}`;
|
|
2042
|
-
if (result.signal) return `${commandLabel} terminated by signal ${result.signal}`;
|
|
2043
|
-
return `${commandLabel} exited with code ${result.status}`;
|
|
2044
|
-
}
|
|
2045
|
-
function isNewerVersion(candidate, current) {
|
|
2046
|
-
const candidateVersion = semver.valid(candidate);
|
|
2047
|
-
const currentVersion = semver.valid(current);
|
|
2048
|
-
return Boolean(
|
|
2049
|
-
candidateVersion && currentVersion && semver.gt(candidateVersion, currentVersion)
|
|
2050
|
-
);
|
|
2051
|
-
}
|
|
2052
|
-
function runSelfUpdate(currentVersion, passthroughArgs = [], options = {}) {
|
|
2053
|
-
const method = options.installMethod ?? detectInstallMethod();
|
|
2054
|
-
if (method !== "npm") {
|
|
2055
|
-
return {
|
|
2056
|
-
ok: false,
|
|
2057
|
-
updated: false,
|
|
2058
|
-
fromVersion: currentVersion,
|
|
2059
|
-
error: "ctxdb was not installed via npm. Update manually with your package manager."
|
|
2060
|
-
};
|
|
2061
|
-
}
|
|
2062
|
-
const check = checkLatestVersion(currentVersion);
|
|
2063
|
-
if (check.error) {
|
|
2064
|
-
return {
|
|
2065
|
-
ok: false,
|
|
2066
|
-
updated: false,
|
|
2067
|
-
fromVersion: currentVersion,
|
|
2068
|
-
error: `npm view failed: ${check.error}`
|
|
2069
|
-
};
|
|
2070
|
-
}
|
|
2071
|
-
if (!check.isNewer) {
|
|
2072
|
-
process.stderr.write(
|
|
2073
|
-
`ctxdb: package already up to date (current v${currentVersion}, latest v${check.latest})
|
|
2074
|
-
`
|
|
2075
|
-
);
|
|
2076
|
-
return { ok: true, updated: false, fromVersion: currentVersion };
|
|
2077
|
-
}
|
|
2078
|
-
process.stderr.write(`ctxdb: updating ${PACKAGE_NAME} v${currentVersion} \u2192 v${check.latest}...
|
|
2079
|
-
`);
|
|
2080
|
-
const install = spawnSync(npmCommand(), ["install", "-g", `${PACKAGE_NAME}@${check.latest}`], {
|
|
2081
|
-
stdio: "inherit",
|
|
2082
|
-
encoding: "utf-8",
|
|
2083
|
-
shell: process.platform === "win32"
|
|
2084
|
-
});
|
|
2085
|
-
if (install.status !== 0) {
|
|
2086
|
-
return {
|
|
2087
|
-
ok: false,
|
|
2088
|
-
updated: false,
|
|
2089
|
-
fromVersion: currentVersion,
|
|
2090
|
-
error: spawnFailureMessage(install, "npm install -g")
|
|
2091
|
-
};
|
|
2092
|
-
}
|
|
2093
|
-
process.stderr.write(`ctxdb: package updated to v${check.latest}, running setup...
|
|
2094
|
-
`);
|
|
2095
|
-
const setupArgs = ["update", "--no-self-update", ...passthroughArgs];
|
|
2096
|
-
const refresh = spawnSync(ctxdbCommand(), setupArgs, {
|
|
2097
|
-
stdio: "inherit",
|
|
2098
|
-
encoding: "utf-8",
|
|
2099
|
-
shell: process.platform === "win32"
|
|
2100
|
-
});
|
|
2101
|
-
return {
|
|
2102
|
-
ok: refresh.status === 0,
|
|
2103
|
-
updated: true,
|
|
2104
|
-
fromVersion: currentVersion,
|
|
2105
|
-
toVersion: check.latest,
|
|
2106
|
-
error: refresh.status !== 0 ? spawnFailureMessage(refresh, "ctxdb setup") : void 0,
|
|
2107
|
-
failureHandled: refresh.status !== null && refresh.status !== 0
|
|
2108
|
-
};
|
|
2109
|
-
}
|
|
2110
|
-
|
|
2111
2269
|
// src/cli/upgrade.ts
|
|
2112
2270
|
var HELP3 = `ctxdb upgrade \u2014 refresh skills + hooks
|
|
2113
2271
|
|
|
@@ -2396,18 +2554,28 @@ function parseMetadataFlags(raw) {
|
|
|
2396
2554
|
}
|
|
2397
2555
|
|
|
2398
2556
|
// src/cli/kb-cli.ts
|
|
2557
|
+
var UPLOAD_TEXT_USAGE = "usage: ctxdb kb upload-text <kb-name> <doc-name> --text=<body> [--file-path=<server-logical-path>] [--wait|--no-wait]";
|
|
2558
|
+
var UPLOAD_FILE_USAGE = "usage: ctxdb kb upload-file <kb-name> <local-path> [--doc-name=...] [--file-path=<server-logical-path>] [--wait|--no-wait]";
|
|
2559
|
+
function shouldWaitForIngest(args, usage) {
|
|
2560
|
+
const waitRequested = args.flags.wait !== void 0;
|
|
2561
|
+
const noWaitRequested = args.flags["no-wait"] !== void 0;
|
|
2562
|
+
if (waitRequested && noWaitRequested) {
|
|
2563
|
+
fail(`cannot use --wait and --no-wait together
|
|
2564
|
+
${usage}`, 2);
|
|
2565
|
+
}
|
|
2566
|
+
return waitRequested;
|
|
2567
|
+
}
|
|
2399
2568
|
async function kbUploadText(args) {
|
|
2569
|
+
const shouldWait = shouldWaitForIngest(args, UPLOAD_TEXT_USAGE);
|
|
2400
2570
|
const [kbName, docName] = args.positional;
|
|
2401
2571
|
const text = args.flags["text"];
|
|
2402
2572
|
if (!kbName || !docName || typeof text !== "string") {
|
|
2403
|
-
fail(
|
|
2404
|
-
"usage: ctxdb kb upload-text <kb-name> <doc-name> --text=<body> [--file-path=<server-logical-path>] [--no-wait]"
|
|
2405
|
-
);
|
|
2573
|
+
fail(UPLOAD_TEXT_USAGE);
|
|
2406
2574
|
}
|
|
2407
2575
|
const ctx = buildContext(args);
|
|
2408
2576
|
const filePath = typeof args.flags["file-path"] === "string" ? args.flags["file-path"] : void 0;
|
|
2409
2577
|
const doc = await uploadText(ctx.client, kbName, docName, text, "text/plain", filePath);
|
|
2410
|
-
if (
|
|
2578
|
+
if (!shouldWait) {
|
|
2411
2579
|
printResult({ document: doc }, !!args.flags.json);
|
|
2412
2580
|
return 0;
|
|
2413
2581
|
}
|
|
@@ -2418,19 +2586,18 @@ async function kbUploadText(args) {
|
|
|
2418
2586
|
return 0;
|
|
2419
2587
|
}
|
|
2420
2588
|
async function kbUploadFile(args) {
|
|
2589
|
+
const shouldWait = shouldWaitForIngest(args, UPLOAD_FILE_USAGE);
|
|
2421
2590
|
const [kbName, localPath] = args.positional;
|
|
2422
2591
|
if (!kbName || !localPath) {
|
|
2423
|
-
fail(
|
|
2424
|
-
"usage: ctxdb kb upload-file <kb-name> <local-path> [--doc-name=...] [--file-path=<server-logical-path>] [--no-wait]"
|
|
2425
|
-
);
|
|
2592
|
+
fail(UPLOAD_FILE_USAGE);
|
|
2426
2593
|
}
|
|
2427
2594
|
const ctx = buildContext(args);
|
|
2428
2595
|
const doc = await uploadFile(ctx.client, kbName, localPath, {
|
|
2429
2596
|
docName: typeof args.flags["doc-name"] === "string" ? args.flags["doc-name"] : void 0,
|
|
2430
2597
|
filePath: typeof args.flags["file-path"] === "string" ? args.flags["file-path"] : void 0,
|
|
2431
|
-
timeoutMs:
|
|
2598
|
+
timeoutMs: DEFAULT_FILE_UPLOAD_TIMEOUT_MS
|
|
2432
2599
|
});
|
|
2433
|
-
if (
|
|
2600
|
+
if (!shouldWait) {
|
|
2434
2601
|
printResult({ document: doc }, !!args.flags.json);
|
|
2435
2602
|
return 0;
|
|
2436
2603
|
}
|
|
@@ -2510,7 +2677,7 @@ USAGE
|
|
|
2510
2677
|
ctxdb <command> [args] [--flags]
|
|
2511
2678
|
|
|
2512
2679
|
COMMANDS
|
|
2513
|
-
setup [--agent <qoder|qoderwork|codex|claude|opencode|hermes>]
|
|
2680
|
+
setup [--agent <qoder|qoderwork|codex|claude|opencode|hermes> | --all]
|
|
2514
2681
|
[--api-key=K] [--base-url=URL] [--user-id=ID]
|
|
2515
2682
|
[--no-install-skill] [--no-validate] [--json]
|
|
2516
2683
|
Without --agent \u2192 writes agents.default (CLI-only, no hooks/skills)
|
|
@@ -2521,8 +2688,12 @@ COMMANDS
|
|
|
2521
2688
|
OpenCode \u2192 writes agents.opencode config + ~/.config/opencode/plugins/ctxdb.ts shim + skill
|
|
2522
2689
|
Hermes \u2192 writes agents.hermes config + ~/.hermes/config.yaml pre/post_llm_call hooks + skill
|
|
2523
2690
|
Approve pre_llm_call + post_llm_call with \`hermes --accept-hooks chat\`
|
|
2524
|
-
(
|
|
2525
|
-
|
|
2691
|
+
(exit chat, rerun setup, then restart any running Hermes CLI/gateway)
|
|
2692
|
+
--all \u2192 detects and configures every setup-compatible built-in Agent
|
|
2693
|
+
status [--agent <name> | --all] [--json]
|
|
2694
|
+
Inspect configuration, connectivity, and integration health.
|
|
2695
|
+
--all inspects the same detected Agent set as setup --all.
|
|
2696
|
+
Rerun setup to add/repair an Agent or replace its API key.
|
|
2526
2697
|
ping [--agent <name>] [--json]
|
|
2527
2698
|
uninstall [--agent <name>] [--purge-config] [--purge-logs] [--purge-all] [--json]
|
|
2528
2699
|
teardown (alias for uninstall)
|
|
@@ -2551,9 +2722,12 @@ COMMANDS
|
|
|
2551
2722
|
|
|
2552
2723
|
kb create <kb-name> [--description=<desc>] [--agent=<name>]
|
|
2553
2724
|
kb upload-text <kb-name> <doc-name> --text=<body> [--agent=<name>]
|
|
2554
|
-
[--file-path=<server-logical-path>] [--no-wait]
|
|
2725
|
+
[--file-path=<server-logical-path>] [--wait|--no-wait]
|
|
2555
2726
|
kb upload-file <kb-name> <local-path> [--agent=<name>] [--doc-name=...]
|
|
2556
|
-
[--file-path=<server-logical-path>] [--no-wait]
|
|
2727
|
+
[--file-path=<server-logical-path>] [--wait|--no-wait]
|
|
2728
|
+
Uploads return immediately by default.
|
|
2729
|
+
--wait polls for terminal ingest status.
|
|
2730
|
+
--no-wait is a compatibility alias for the default.
|
|
2557
2731
|
kb list [--agent=<name>]
|
|
2558
2732
|
kb documents-list <kb-name> [--agent=<name>]
|
|
2559
2733
|
kb document-get <kb-name> <doc-id> [--agent=<name>]
|
|
@@ -2580,6 +2754,10 @@ ENV VARS (override selected ~/.ctxdb/ctxdb.json agent config):
|
|
|
2580
2754
|
CTXDB_AGENT CTXDB_API_KEY CTXDB_BASE_URL CTXDB_USER_ID
|
|
2581
2755
|
CTXDB_AGENT_ID CTXDB_APP_ID
|
|
2582
2756
|
|
|
2757
|
+
UPDATE CHECK ENV VARS:
|
|
2758
|
+
CTXDB_DISABLE_UPDATE_CHECK=1
|
|
2759
|
+
Disable background version checks and hints.
|
|
2760
|
+
|
|
2583
2761
|
HOOK ENV VARS:
|
|
2584
2762
|
CTXDB_SKIP_HOOKS=TRUE Hook/plugin entrypoints exit immediately.
|
|
2585
2763
|
Direct ctxdb CLI commands are unchanged.
|
|
@@ -2616,7 +2794,7 @@ var ROUTES = {
|
|
|
2616
2794
|
search: kbSearch
|
|
2617
2795
|
}
|
|
2618
2796
|
};
|
|
2619
|
-
async function
|
|
2797
|
+
async function dispatch(argv) {
|
|
2620
2798
|
if (argv.length === 0 || argv[0] === "-h" || argv[0] === "--help") {
|
|
2621
2799
|
process.stdout.write(HELP5);
|
|
2622
2800
|
return 0;
|
|
@@ -2660,6 +2838,15 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
2660
2838
|
}
|
|
2661
2839
|
return Promise.resolve(handler(parseArgs(subRest)));
|
|
2662
2840
|
}
|
|
2841
|
+
async function main(argv = process.argv.slice(2)) {
|
|
2842
|
+
const notification = beginUpdateNotification(argv, {
|
|
2843
|
+
currentVersion: PACKAGE_VERSION,
|
|
2844
|
+
workerPath: fileURLToPath2(new URL("../workers/version-check.js", import.meta.url))
|
|
2845
|
+
});
|
|
2846
|
+
const code = await dispatch(argv);
|
|
2847
|
+
completeUpdateNotification(notification, code);
|
|
2848
|
+
return code;
|
|
2849
|
+
}
|
|
2663
2850
|
main().then(
|
|
2664
2851
|
(code) => {
|
|
2665
2852
|
if (typeof code === "number") process.exitCode = code;
|