@aliyunrds/ctxdb 1.0.8-beta.3 → 1.0.8-beta.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.
- package/README.md +39 -6
- package/dist/{chunk-EI63DQX3.js → chunk-5DGRNP55.js} +1 -1
- package/dist/{chunk-R67JELM7.js → chunk-5ITT5GSP.js} +3 -2
- package/dist/{chunk-LZ2LOWZL.js → chunk-6MEWI73Y.js} +2 -2
- package/dist/{chunk-ZFS6OMWE.js → chunk-76AXXLVE.js} +2 -2
- package/dist/{chunk-AUBVVYQL.js → chunk-O6MKQ2I3.js} +1 -1
- package/dist/{chunk-ULAWTBBC.js → chunk-OEZM2ZYA.js} +1 -1
- package/dist/{chunk-VIG4SYLU.js → chunk-PI2SUS3M.js} +1 -1
- package/dist/{chunk-BUK4SZC2.js → chunk-SVO6H62S.js} +36 -17
- package/dist/{chunk-7OX6UVPB.js → chunk-WJTV7JNR.js} +3 -3
- package/dist/{chunk-3NJ37TEY.js → chunk-ZW7YXNJ6.js} +1 -1
- package/dist/cli/main.js +282 -72
- package/dist/hooks/hermes-post-llm-call.js +5 -5
- package/dist/hooks/hermes-pre-llm-call.js +8 -8
- package/dist/hooks/pre-tool-use.js +1 -1
- package/dist/hooks/session-start.js +7 -7
- package/dist/hooks/stop.js +5 -5
- package/dist/hooks/user-prompt-submit.js +7 -7
- package/dist/opencode/index.js +611 -36
- package/dist/workers/version-check.js +3 -3
- package/package.json +2 -2
package/dist/cli/main.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
uploadFile,
|
|
17
17
|
uploadText,
|
|
18
18
|
validateLocalFile
|
|
19
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-ZW7YXNJ6.js";
|
|
20
20
|
import {
|
|
21
21
|
AGENT_CHOICES,
|
|
22
22
|
CtxdbError,
|
|
@@ -31,29 +31,31 @@ import {
|
|
|
31
31
|
agentHomeDir,
|
|
32
32
|
agentHomeDirs,
|
|
33
33
|
agentPlatformSupport,
|
|
34
|
-
apiKeyCredential,
|
|
35
34
|
configuredAgents,
|
|
35
|
+
defaultConfigPath,
|
|
36
36
|
detectInstalledAgents,
|
|
37
37
|
hasConfiguredAgent,
|
|
38
38
|
inspectAgentHomes,
|
|
39
39
|
isAgentSlug,
|
|
40
40
|
isBuiltinAgent,
|
|
41
|
+
isDataApiReady,
|
|
41
42
|
load,
|
|
42
43
|
removeAgent,
|
|
43
44
|
resolveDataApiCredential,
|
|
44
45
|
save,
|
|
46
|
+
secureAtomicWrite,
|
|
45
47
|
updateConfiguredDebug,
|
|
46
48
|
writeInstalledPkgVersion
|
|
47
|
-
} from "../chunk-
|
|
49
|
+
} from "../chunk-SVO6H62S.js";
|
|
48
50
|
import {
|
|
49
51
|
beginUpdateNotification,
|
|
50
52
|
completeUpdateNotification,
|
|
51
53
|
runSelfUpdate
|
|
52
|
-
} from "../chunk-
|
|
54
|
+
} from "../chunk-OEZM2ZYA.js";
|
|
53
55
|
import {
|
|
54
56
|
DISTRIBUTION_MANIFEST
|
|
55
|
-
} from "../chunk-
|
|
56
|
-
import "../chunk-
|
|
57
|
+
} from "../chunk-5ITT5GSP.js";
|
|
58
|
+
import "../chunk-PI2SUS3M.js";
|
|
57
59
|
|
|
58
60
|
// src/cli/util.ts
|
|
59
61
|
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
@@ -472,11 +474,14 @@ async function runSetup(options) {
|
|
|
472
474
|
}
|
|
473
475
|
const cfg = load({ agent });
|
|
474
476
|
const persistedCredentialConfig = options.persistCredential === false ? load({ agent, env: {}, managedCredentials: false }) : null;
|
|
475
|
-
if (options.apiKey)
|
|
477
|
+
if (options.apiKey) {
|
|
478
|
+
cfg.apiKey = options.apiKey;
|
|
479
|
+
cfg.oauthCredential = void 0;
|
|
480
|
+
}
|
|
476
481
|
if (options.baseUrl) cfg.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
477
482
|
else if (!cfg.baseUrl) cfg.baseUrl = DEFAULT_BASE_URL;
|
|
478
483
|
cfg.userId = options.userId ?? cfg.userId ?? DEFAULT_USER_ID;
|
|
479
|
-
if (!cfg
|
|
484
|
+
if (!isDataApiReady(cfg)) {
|
|
480
485
|
steps.push({
|
|
481
486
|
step: "write-config",
|
|
482
487
|
ok: false,
|
|
@@ -496,7 +501,7 @@ async function runSetup(options) {
|
|
|
496
501
|
ok: true,
|
|
497
502
|
detail: `${agent}: ${cfg.baseUrl} (user_id=${cfg.userId})`
|
|
498
503
|
});
|
|
499
|
-
if (isBuiltinAgent(agent)) {
|
|
504
|
+
if (isBuiltinAgent(agent) && !cfg.oauthCredential) {
|
|
500
505
|
const hasDefault = configuredAgents().includes("default");
|
|
501
506
|
if (!hasDefault) {
|
|
502
507
|
save(persistedCfg, void 0, { agent: "default", omitApiKey });
|
|
@@ -720,7 +725,7 @@ async function runSetup(options) {
|
|
|
720
725
|
}
|
|
721
726
|
}
|
|
722
727
|
if (validate) {
|
|
723
|
-
if (!cfg
|
|
728
|
+
if (!isDataApiReady(cfg)) {
|
|
724
729
|
steps.push({
|
|
725
730
|
step: "validate-ping",
|
|
726
731
|
ok: false,
|
|
@@ -730,7 +735,7 @@ async function runSetup(options) {
|
|
|
730
735
|
try {
|
|
731
736
|
const client = new HttpClient({
|
|
732
737
|
baseUrl: cfg.baseUrl,
|
|
733
|
-
credential:
|
|
738
|
+
credential: resolveDataApiCredential(cfg)
|
|
734
739
|
});
|
|
735
740
|
await client.get("/v1/ping/");
|
|
736
741
|
steps.push({ step: "validate-ping", ok: true });
|
|
@@ -818,8 +823,8 @@ async function runSetupAll(options = {}, dependencies = {}) {
|
|
|
818
823
|
}
|
|
819
824
|
for (const agent of detection.selected) {
|
|
820
825
|
const existing = configSnapshot.get(agent);
|
|
821
|
-
const apiKey = options.apiKey ?? existing.apiKey;
|
|
822
|
-
if (!apiKey) {
|
|
826
|
+
const apiKey = options.apiKey ?? (existing.oauthCredential ? void 0 : existing.apiKey ?? void 0);
|
|
827
|
+
if (!apiKey && !isDataApiReady(existing)) {
|
|
823
828
|
agents[agent] = missingApiKeyResult(agent);
|
|
824
829
|
continue;
|
|
825
830
|
}
|
|
@@ -2214,6 +2219,205 @@ async function ping(args) {
|
|
|
2214
2219
|
return 0;
|
|
2215
2220
|
}
|
|
2216
2221
|
|
|
2222
|
+
// src/cli/device-auth-cli.ts
|
|
2223
|
+
import { dirname as dirname3, join as join2 } from "path";
|
|
2224
|
+
import { CoreDeviceClient, normalizeCoreOrigin as normalizeCoreOrigin2, OAuthSessionStore } from "@aliyunrds/ctxdb-shared";
|
|
2225
|
+
|
|
2226
|
+
// src/lib/oauth-login-config.ts
|
|
2227
|
+
import { closeSync, existsSync as existsSync2, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
2228
|
+
import { dirname as dirname2 } from "path";
|
|
2229
|
+
import { setTimeout as delay } from "timers/promises";
|
|
2230
|
+
import { normalizeCoreOrigin, oauthProfile } from "@aliyunrds/ctxdb-shared";
|
|
2231
|
+
function read(path) {
|
|
2232
|
+
if (!existsSync2(path)) return { version: 2, agents: {} };
|
|
2233
|
+
let raw;
|
|
2234
|
+
try {
|
|
2235
|
+
raw = JSON.parse(readFileSync2(path, "utf8"));
|
|
2236
|
+
} catch {
|
|
2237
|
+
throw new Error("Invalid ctxdb configuration; login did not overwrite it.");
|
|
2238
|
+
}
|
|
2239
|
+
if (!raw || raw.version !== 2 || !raw.agents || typeof raw.agents !== "object" || Array.isArray(raw.agents)) {
|
|
2240
|
+
throw new Error("Unsupported ctxdb configuration; login did not overwrite it.");
|
|
2241
|
+
}
|
|
2242
|
+
return raw;
|
|
2243
|
+
}
|
|
2244
|
+
function selectedOAuthProfile(path, agent) {
|
|
2245
|
+
const section = read(path).agents[agent];
|
|
2246
|
+
return oauthProfile(section?.oauth_credential_ref, path, agent, section?.base_url);
|
|
2247
|
+
}
|
|
2248
|
+
async function commitOAuthProfile(path, agent, reference, baseUrl) {
|
|
2249
|
+
oauthProfile(reference, path, agent, baseUrl);
|
|
2250
|
+
mkdirSync2(dirname2(path), { recursive: true, mode: 448 });
|
|
2251
|
+
const lock = path + ".oauth-config.lock", deadline = Date.now() + 1e4;
|
|
2252
|
+
let fd;
|
|
2253
|
+
while (true) {
|
|
2254
|
+
try {
|
|
2255
|
+
fd = openSync(lock, "wx", 384);
|
|
2256
|
+
break;
|
|
2257
|
+
} catch (error) {
|
|
2258
|
+
if (error.code !== "EEXIST") throw new Error("Cannot lock OAuth profile configuration.");
|
|
2259
|
+
if (Date.now() >= deadline) throw new Error("OAuth profile configuration is locked; recover a crashed login's config lock before retrying.");
|
|
2260
|
+
await delay(25);
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2263
|
+
try {
|
|
2264
|
+
const raw = read(path), section = raw.agents[agent] ?? {};
|
|
2265
|
+
if (typeof section !== "object" || Array.isArray(section)) throw new Error("Invalid agent profile; login did not overwrite it.");
|
|
2266
|
+
const previous = oauthProfile(section.oauth_credential_ref, path, agent, section.base_url);
|
|
2267
|
+
raw.agents[agent] = { ...section, oauth_credential_ref: reference, base_url: normalizeCoreOrigin(baseUrl) };
|
|
2268
|
+
delete raw.agents[agent].api_key;
|
|
2269
|
+
secureAtomicWrite(path, JSON.stringify(raw, null, 2) + "\n");
|
|
2270
|
+
return previous;
|
|
2271
|
+
} finally {
|
|
2272
|
+
closeSync(fd);
|
|
2273
|
+
unlinkSync2(lock);
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
function consoleAuthorizationBase(path, core) {
|
|
2277
|
+
if (!existsSync2(path)) return void 0;
|
|
2278
|
+
try {
|
|
2279
|
+
const raw = JSON.parse(readFileSync2(path, "utf8"));
|
|
2280
|
+
if (raw.version !== 1 || !Array.isArray(raw.environments) || raw.environments.length > 32) throw new Error();
|
|
2281
|
+
const matches = raw.environments.filter((entry) => normalizeCoreOrigin(entry.core_url) === core);
|
|
2282
|
+
if (matches.length > 1) throw new Error();
|
|
2283
|
+
if (!matches.length) return void 0;
|
|
2284
|
+
const url = new URL(matches[0].authorization_url);
|
|
2285
|
+
if (url.protocol !== "https:" || url.username || url.password || url.search || url.hash) throw new Error();
|
|
2286
|
+
return url.toString();
|
|
2287
|
+
} catch {
|
|
2288
|
+
throw new Error("Invalid local device-environments.json. No authorization request was created.");
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
// src/cli/device-auth-cli.ts
|
|
2293
|
+
var usage = "ctxdb login [--agent <name>] [--server <core-origin>] [--device-code] [--no-browser] [--json]\n";
|
|
2294
|
+
function createPublicAuthCommands(dependencies = {}) {
|
|
2295
|
+
const env = () => dependencies.env ?? process.env;
|
|
2296
|
+
const stdout = dependencies.stdout ?? ((s) => {
|
|
2297
|
+
process.stdout.write(s);
|
|
2298
|
+
});
|
|
2299
|
+
const stderr = dependencies.stderr ?? ((s) => {
|
|
2300
|
+
process.stderr.write(s);
|
|
2301
|
+
});
|
|
2302
|
+
const client = dependencies.client ?? ((url) => new CoreDeviceClient(url));
|
|
2303
|
+
const output = (value, json) => stdout(json ? JSON.stringify(value) + "\n" : String(value) + "\n");
|
|
2304
|
+
function options(args, login = false) {
|
|
2305
|
+
const allowed = ["agent", "json", "help", "h", ...login ? ["server", "device-code", "no-browser"] : []];
|
|
2306
|
+
if (args.positional.length || Object.keys(args.flags).some((k) => !allowed.includes(k))) throw new Error("Unsupported Device login option.");
|
|
2307
|
+
for (const flag of ["json", "help", "h", "device-code", "no-browser"]) {
|
|
2308
|
+
if (args.flags[flag] !== void 0 && args.flags[flag] !== true) throw new Error("Invalid boolean Device login option.");
|
|
2309
|
+
}
|
|
2310
|
+
const agent = args.flags.agent ?? agentFromEnv(env());
|
|
2311
|
+
if (!isAgentSlug(agent)) throw new Error("Invalid agent profile.");
|
|
2312
|
+
const path = defaultConfigPath(env());
|
|
2313
|
+
return { agent, path, json: args.flags.json === true };
|
|
2314
|
+
}
|
|
2315
|
+
async function revoke(profile) {
|
|
2316
|
+
return new OAuthSessionStore(profile.directory).logout(profile.reference, profile.profile, client(profile.baseUrl));
|
|
2317
|
+
}
|
|
2318
|
+
return {
|
|
2319
|
+
async login(args) {
|
|
2320
|
+
if (args.flags.help || args.flags.h) {
|
|
2321
|
+
stdout(usage);
|
|
2322
|
+
return 0;
|
|
2323
|
+
}
|
|
2324
|
+
const { agent, path, json } = options(args, true);
|
|
2325
|
+
if (["CTXDB_API_KEY", "CTXDB_ACCESS_TOKEN", "CTXDB_BASE_URL"].some((k) => env()[k])) {
|
|
2326
|
+
throw new Error("Unset CTXDB_API_KEY, CTXDB_ACCESS_TOKEN and CTXDB_BASE_URL before managed login; use --server to select Core.");
|
|
2327
|
+
}
|
|
2328
|
+
if (args.flags.server !== void 0 && typeof args.flags.server !== "string") throw new Error("--server requires a Core origin.");
|
|
2329
|
+
const previous = selectedOAuthProfile(path, agent);
|
|
2330
|
+
const baseUrl = normalizeCoreOrigin2(args.flags.server ?? previous?.baseUrl ?? DEFAULT_BASE_URL);
|
|
2331
|
+
const consoleBase = consoleAuthorizationBase(join2(dirname3(path), "device-environments.json"), baseUrl);
|
|
2332
|
+
const connection = client(baseUrl), controller = new AbortController();
|
|
2333
|
+
const interrupt = () => controller.abort();
|
|
2334
|
+
process.once("SIGINT", interrupt);
|
|
2335
|
+
try {
|
|
2336
|
+
const session = await connection.login({ signal: controller.signal, onPrompt: (prompt) => {
|
|
2337
|
+
const url = consoleBase ? new URL(consoleBase) : void 0;
|
|
2338
|
+
url?.searchParams.set("user_code", prompt.userCode);
|
|
2339
|
+
const safe = {
|
|
2340
|
+
event: "device_authorization",
|
|
2341
|
+
user_code: prompt.userCode,
|
|
2342
|
+
request_id: prompt.requestId,
|
|
2343
|
+
expires_in: prompt.expiresIn,
|
|
2344
|
+
...url ? { authorization_url: url.toString() } : {}
|
|
2345
|
+
};
|
|
2346
|
+
stderr(json ? JSON.stringify(safe) + "\n" : `User code: ${prompt.userCode}
|
|
2347
|
+
${url ? url.toString() : "Console URL is not configured. Complete authorization with the independent POP test client."}
|
|
2348
|
+
`);
|
|
2349
|
+
} });
|
|
2350
|
+
const store = new OAuthSessionStore(join2(dirname3(path), "oauth-credentials"));
|
|
2351
|
+
const reference = store.saveLogin(agent, session);
|
|
2352
|
+
let replaced;
|
|
2353
|
+
try {
|
|
2354
|
+
replaced = await commitOAuthProfile(path, agent, reference, baseUrl);
|
|
2355
|
+
} catch (error) {
|
|
2356
|
+
await store.logout(reference, agent, connection);
|
|
2357
|
+
throw error;
|
|
2358
|
+
}
|
|
2359
|
+
if (replaced) {
|
|
2360
|
+
try {
|
|
2361
|
+
if (!(await revoke(replaced)).remoteRevoked) stderr("New login saved; old session could not be revoked remotely.\n");
|
|
2362
|
+
} catch {
|
|
2363
|
+
stderr("New login saved; old credential cleanup needs attention.\n");
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
output(json ? {
|
|
2367
|
+
ok: true,
|
|
2368
|
+
agent,
|
|
2369
|
+
workspace_id: session.workspaceId,
|
|
2370
|
+
member_id: session.memberId,
|
|
2371
|
+
scope: session.scope,
|
|
2372
|
+
client_id: session.clientId,
|
|
2373
|
+
account_display: session.accountDisplay,
|
|
2374
|
+
authorization_method: "device-code"
|
|
2375
|
+
} : `Logged in for ${agent}: Workspace ${session.workspaceId}, Member ${session.memberId}, scope ${session.scope}. Run ctxdb setup --agent ${agent} separately.`, json);
|
|
2376
|
+
return 0;
|
|
2377
|
+
} finally {
|
|
2378
|
+
process.removeListener("SIGINT", interrupt);
|
|
2379
|
+
}
|
|
2380
|
+
},
|
|
2381
|
+
async status(args) {
|
|
2382
|
+
if (args.flags.help || args.flags.h) {
|
|
2383
|
+
stdout("ctxdb auth status [--agent <name>] [--json]\n");
|
|
2384
|
+
return 0;
|
|
2385
|
+
}
|
|
2386
|
+
const { agent, path, json } = options(args);
|
|
2387
|
+
const profile = selectedOAuthProfile(path, agent);
|
|
2388
|
+
const state = profile ? new OAuthSessionStore(profile.directory).status(profile.reference, agent) : { state: "missing" };
|
|
2389
|
+
const overridden = Boolean(env().CTXDB_ACCESS_TOKEN || env().CTXDB_API_KEY);
|
|
2390
|
+
const ok = state.state === "ready";
|
|
2391
|
+
output(json ? { ok, agent, ...state, environment_credential_override: overridden } : `${agent}: ${state.state}${overridden ? " (environment credential takes precedence for DATA requests)" : ""}`, json);
|
|
2392
|
+
return ok ? 0 : 1;
|
|
2393
|
+
},
|
|
2394
|
+
async logout(args) {
|
|
2395
|
+
if (args.flags.help || args.flags.h) {
|
|
2396
|
+
stdout("ctxdb logout [--agent <name>] [--json]\n");
|
|
2397
|
+
return 0;
|
|
2398
|
+
}
|
|
2399
|
+
const { agent, path, json } = options(args);
|
|
2400
|
+
const profile = selectedOAuthProfile(path, agent);
|
|
2401
|
+
if (!profile) {
|
|
2402
|
+
output(json ? { ok: true, agent, local_cleared: true, remote_revoked: false, status: "no_managed_session" } : `${agent}: no managed session.`, json);
|
|
2403
|
+
return 0;
|
|
2404
|
+
}
|
|
2405
|
+
const store = new OAuthSessionStore(profile.directory);
|
|
2406
|
+
if (store.status(profile.reference, agent).state === "logged_out") {
|
|
2407
|
+
output(json ? { ok: true, agent, local_cleared: true, remote_revoked: false, status: "already_logged_out" } : `${agent}: already logged out locally.`, json);
|
|
2408
|
+
return 0;
|
|
2409
|
+
}
|
|
2410
|
+
const result = await revoke(profile);
|
|
2411
|
+
output(json ? { ok: result.remoteRevoked, agent, local_cleared: true, remote_revoked: result.remoteRevoked } : `${agent}: local credential cleared; ${result.remoteRevoked ? "remote revoke completed" : "remote revoke failed or could not be confirmed"}.`, json);
|
|
2412
|
+
return result.remoteRevoked ? 0 : 1;
|
|
2413
|
+
}
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
var commands = createPublicAuthCommands();
|
|
2417
|
+
var deviceLogin = commands.login;
|
|
2418
|
+
var deviceAuthStatus = commands.status;
|
|
2419
|
+
var deviceLogout = commands.logout;
|
|
2420
|
+
|
|
2217
2421
|
// src/cli/setup-cli.ts
|
|
2218
2422
|
var HELP = `ctxdb setup \u2014 configure an agent
|
|
2219
2423
|
|
|
@@ -2792,12 +2996,12 @@ function parseFileUpdate(args) {
|
|
|
2792
2996
|
}
|
|
2793
2997
|
fail(UPDATE_FILE_USAGE, 2);
|
|
2794
2998
|
}
|
|
2795
|
-
function shouldWaitForIngest(args,
|
|
2999
|
+
function shouldWaitForIngest(args, usage2) {
|
|
2796
3000
|
const waitRequested = args.flags.wait !== void 0;
|
|
2797
3001
|
const noWaitRequested = args.flags["no-wait"] !== void 0;
|
|
2798
3002
|
if (waitRequested && noWaitRequested) {
|
|
2799
3003
|
fail(`cannot use --wait and --no-wait together
|
|
2800
|
-
${
|
|
3004
|
+
${usage2}`, 2);
|
|
2801
3005
|
}
|
|
2802
3006
|
return waitRequested;
|
|
2803
3007
|
}
|
|
@@ -3407,130 +3611,130 @@ function stringFlag(args, name) {
|
|
|
3407
3611
|
const value = args.flags[name];
|
|
3408
3612
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
3409
3613
|
}
|
|
3410
|
-
function requireIdFlag(args, name,
|
|
3614
|
+
function requireIdFlag(args, name, usage2) {
|
|
3411
3615
|
const value = stringFlag(args, name);
|
|
3412
3616
|
if (value === void 0) fail(`--${name} is required
|
|
3413
|
-
${
|
|
3617
|
+
${usage2}`, 2);
|
|
3414
3618
|
return value;
|
|
3415
3619
|
}
|
|
3416
|
-
function requireTemplateIdPositional(args,
|
|
3620
|
+
function requireTemplateIdPositional(args, usage2) {
|
|
3417
3621
|
const templateId = args.positional[0];
|
|
3418
|
-
if (!templateId || templateId.trim() === "") fail(
|
|
3622
|
+
if (!templateId || templateId.trim() === "") fail(usage2, 2);
|
|
3419
3623
|
return templateId;
|
|
3420
3624
|
}
|
|
3421
|
-
function intFlag(args, name,
|
|
3625
|
+
function intFlag(args, name, usage2) {
|
|
3422
3626
|
const raw = stringFlag(args, name);
|
|
3423
3627
|
if (raw === void 0) return void 0;
|
|
3424
3628
|
const n = Number(raw);
|
|
3425
3629
|
if (!Number.isInteger(n) || n < 1) {
|
|
3426
3630
|
fail(`invalid --${name}: ${raw} (expected a positive integer)
|
|
3427
|
-
${
|
|
3631
|
+
${usage2}`, 2);
|
|
3428
3632
|
}
|
|
3429
3633
|
return n;
|
|
3430
3634
|
}
|
|
3431
|
-
function parseIdsFlag(args,
|
|
3635
|
+
function parseIdsFlag(args, usage2) {
|
|
3432
3636
|
const raw = stringFlag(args, "ids");
|
|
3433
3637
|
if (raw === void 0) fail(`--ids is required (comma-separated)
|
|
3434
|
-
${
|
|
3638
|
+
${usage2}`, 2);
|
|
3435
3639
|
const ids = raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
3436
3640
|
if (ids.length === 0) fail(`--ids must contain at least one id
|
|
3437
|
-
${
|
|
3641
|
+
${usage2}`, 2);
|
|
3438
3642
|
if (ids.length > BATCH_MAX_ITEMS) {
|
|
3439
3643
|
fail(`--ids accepts at most ${BATCH_MAX_ITEMS} items per request (got ${ids.length})
|
|
3440
|
-
${
|
|
3644
|
+
${usage2}`, 2);
|
|
3441
3645
|
}
|
|
3442
3646
|
return ids;
|
|
3443
3647
|
}
|
|
3444
|
-
function parseResolutions(raw,
|
|
3648
|
+
function parseResolutions(raw, usage2) {
|
|
3445
3649
|
let parsed;
|
|
3446
3650
|
try {
|
|
3447
3651
|
parsed = JSON.parse(raw);
|
|
3448
3652
|
} catch {
|
|
3449
3653
|
fail(`--resolutions-json is not valid JSON
|
|
3450
|
-
${
|
|
3654
|
+
${usage2}`, 2);
|
|
3451
3655
|
}
|
|
3452
3656
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
3453
3657
|
fail(`--resolutions-json must be a non-empty array
|
|
3454
|
-
${
|
|
3658
|
+
${usage2}`, 2);
|
|
3455
3659
|
}
|
|
3456
3660
|
return parsed.map((entry, i) => {
|
|
3457
3661
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
3458
3662
|
fail(`--resolutions-json[${i}] must be an object
|
|
3459
|
-
${
|
|
3663
|
+
${usage2}`, 2);
|
|
3460
3664
|
}
|
|
3461
3665
|
const e = entry;
|
|
3462
3666
|
if (typeof e.index !== "number" || !Number.isInteger(e.index) || e.index < 0) {
|
|
3463
3667
|
fail(`--resolutions-json[${i}].index must be a non-negative integer
|
|
3464
|
-
${
|
|
3668
|
+
${usage2}`, 2);
|
|
3465
3669
|
}
|
|
3466
3670
|
if (typeof e.choice !== "string" || e.choice.trim() === "") {
|
|
3467
3671
|
fail(`--resolutions-json[${i}].choice must be a non-empty string
|
|
3468
|
-
${
|
|
3672
|
+
${usage2}`, 2);
|
|
3469
3673
|
}
|
|
3470
3674
|
const out = { index: e.index, choice: e.choice };
|
|
3471
3675
|
if (e.comment !== void 0 && e.comment !== null) {
|
|
3472
3676
|
if (typeof e.comment !== "string") {
|
|
3473
3677
|
fail(`--resolutions-json[${i}].comment must be a string
|
|
3474
|
-
${
|
|
3678
|
+
${usage2}`, 2);
|
|
3475
3679
|
}
|
|
3476
3680
|
out.comment = e.comment;
|
|
3477
3681
|
}
|
|
3478
3682
|
return out;
|
|
3479
3683
|
});
|
|
3480
3684
|
}
|
|
3481
|
-
function buildTemplateUpsertBody(args,
|
|
3685
|
+
function buildTemplateUpsertBody(args, usage2) {
|
|
3482
3686
|
const name = stringFlag(args, "name");
|
|
3483
3687
|
if (name === void 0) fail(`--name is required
|
|
3484
|
-
${
|
|
3688
|
+
${usage2}`, 2);
|
|
3485
3689
|
const sectionsRaw = args.flags["sections-json"];
|
|
3486
3690
|
if (typeof sectionsRaw !== "string" || sectionsRaw.trim() === "") {
|
|
3487
3691
|
fail(`--sections-json is required
|
|
3488
|
-
${
|
|
3692
|
+
${usage2}`, 2);
|
|
3489
3693
|
}
|
|
3490
|
-
const sections = parseSections(sectionsRaw,
|
|
3694
|
+
const sections = parseSections(sectionsRaw, usage2);
|
|
3491
3695
|
const body = { name, sections };
|
|
3492
3696
|
if (args.flags["is-default"] === true) body.is_default = true;
|
|
3493
3697
|
return body;
|
|
3494
3698
|
}
|
|
3495
|
-
function parseSections(raw,
|
|
3699
|
+
function parseSections(raw, usage2) {
|
|
3496
3700
|
let parsed;
|
|
3497
3701
|
try {
|
|
3498
3702
|
parsed = JSON.parse(raw);
|
|
3499
3703
|
} catch {
|
|
3500
3704
|
fail(`--sections-json is not valid JSON
|
|
3501
|
-
${
|
|
3705
|
+
${usage2}`, 2);
|
|
3502
3706
|
}
|
|
3503
3707
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
3504
3708
|
fail(`--sections-json must be a non-empty array
|
|
3505
|
-
${
|
|
3709
|
+
${usage2}`, 2);
|
|
3506
3710
|
}
|
|
3507
3711
|
if (parsed.length > TEMPLATE_SECTIONS_MAX) {
|
|
3508
3712
|
fail(`--sections-json accepts at most ${TEMPLATE_SECTIONS_MAX} sections (got ${parsed.length})
|
|
3509
|
-
${
|
|
3713
|
+
${usage2}`, 2);
|
|
3510
3714
|
}
|
|
3511
3715
|
return parsed.map((entry, i) => {
|
|
3512
3716
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
3513
3717
|
fail(`--sections-json[${i}] must be an object
|
|
3514
|
-
${
|
|
3718
|
+
${usage2}`, 2);
|
|
3515
3719
|
}
|
|
3516
3720
|
const e = entry;
|
|
3517
3721
|
if (typeof e.title !== "string" || e.title.trim() === "") {
|
|
3518
3722
|
fail(`--sections-json[${i}].title must be a non-empty string
|
|
3519
|
-
${
|
|
3723
|
+
${usage2}`, 2);
|
|
3520
3724
|
}
|
|
3521
3725
|
if (/[\r\n]/.test(e.title.trim())) {
|
|
3522
3726
|
fail(`--sections-json[${i}].title must not contain line breaks
|
|
3523
|
-
${
|
|
3727
|
+
${usage2}`, 2);
|
|
3524
3728
|
}
|
|
3525
3729
|
if (typeof e.guidance !== "string" || e.guidance.trim() === "") {
|
|
3526
3730
|
fail(`--sections-json[${i}].guidance must be a non-empty string
|
|
3527
|
-
${
|
|
3731
|
+
${usage2}`, 2);
|
|
3528
3732
|
}
|
|
3529
3733
|
const out = { title: e.title, guidance: e.guidance };
|
|
3530
3734
|
if (e.level !== void 0 && e.level !== null) {
|
|
3531
3735
|
if (typeof e.level !== "number" || !Number.isInteger(e.level) || e.level < 1 || e.level > 3) {
|
|
3532
3736
|
fail(`--sections-json[${i}].level must be an integer in 1-3
|
|
3533
|
-
${
|
|
3737
|
+
${usage2}`, 2);
|
|
3534
3738
|
}
|
|
3535
3739
|
out.level = e.level;
|
|
3536
3740
|
}
|
|
@@ -3605,7 +3809,7 @@ function compactTemplateList(data) {
|
|
|
3605
3809
|
}
|
|
3606
3810
|
|
|
3607
3811
|
// src/cli/review-cli.ts
|
|
3608
|
-
import { readFileSync as
|
|
3812
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
3609
3813
|
|
|
3610
3814
|
// src/lib/review.ts
|
|
3611
3815
|
function unwrapReviewData(response, operation) {
|
|
@@ -3907,43 +4111,43 @@ function stringValue(args, name) {
|
|
|
3907
4111
|
const value = args.flags[name];
|
|
3908
4112
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
3909
4113
|
}
|
|
3910
|
-
function requireId(args, flagName, positionalIndex,
|
|
4114
|
+
function requireId(args, flagName, positionalIndex, usage2) {
|
|
3911
4115
|
const positional = args.positional[positionalIndex]?.trim();
|
|
3912
4116
|
const value = positional !== void 0 && positional !== "" ? positional : stringValue(args, flagName);
|
|
3913
|
-
if (value === void 0) fail(
|
|
4117
|
+
if (value === void 0) fail(usage2, 2);
|
|
3914
4118
|
return value.trim();
|
|
3915
4119
|
}
|
|
3916
|
-
function requireEnumFlag(args, flagName, allowed,
|
|
4120
|
+
function requireEnumFlag(args, flagName, allowed, usage2) {
|
|
3917
4121
|
const value = stringValue(args, flagName);
|
|
3918
|
-
if (value === void 0) fail(
|
|
4122
|
+
if (value === void 0) fail(usage2, 2);
|
|
3919
4123
|
if (!allowed.includes(value)) {
|
|
3920
4124
|
fail(`${flagName} must be one of ${allowed.join("|")}
|
|
3921
|
-
${
|
|
4125
|
+
${usage2}`, 2);
|
|
3922
4126
|
}
|
|
3923
4127
|
return value;
|
|
3924
4128
|
}
|
|
3925
|
-
function positiveIntFlag(args, flagName,
|
|
4129
|
+
function positiveIntFlag(args, flagName, usage2) {
|
|
3926
4130
|
const value = args.flags[flagName];
|
|
3927
4131
|
if (value === void 0) return void 0;
|
|
3928
|
-
if (typeof value !== "string") fail(
|
|
4132
|
+
if (typeof value !== "string") fail(usage2, 2);
|
|
3929
4133
|
const parsed = Number(value);
|
|
3930
4134
|
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
3931
4135
|
fail(`${flagName} must be a positive integer
|
|
3932
|
-
${
|
|
4136
|
+
${usage2}`, 2);
|
|
3933
4137
|
}
|
|
3934
4138
|
return parsed;
|
|
3935
4139
|
}
|
|
3936
|
-
function readPayloadInput(args, inlineFlag, fileFlag,
|
|
4140
|
+
function readPayloadInput(args, inlineFlag, fileFlag, usage2) {
|
|
3937
4141
|
const inline = stringValue(args, inlineFlag);
|
|
3938
4142
|
const filePath = stringValue(args, fileFlag);
|
|
3939
4143
|
if (inline !== void 0 && filePath !== void 0) {
|
|
3940
4144
|
fail(`cannot use --${inlineFlag} and --${fileFlag} together
|
|
3941
|
-
${
|
|
4145
|
+
${usage2}`, 2);
|
|
3942
4146
|
}
|
|
3943
4147
|
if (inline !== void 0) return inline;
|
|
3944
4148
|
if (filePath !== void 0) {
|
|
3945
4149
|
try {
|
|
3946
|
-
return
|
|
4150
|
+
return readFileSync3(filePath, "utf-8");
|
|
3947
4151
|
} catch (error) {
|
|
3948
4152
|
fail(
|
|
3949
4153
|
`cannot read --${fileFlag} ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -3951,17 +4155,17 @@ ${usage}`, 2);
|
|
|
3951
4155
|
);
|
|
3952
4156
|
}
|
|
3953
4157
|
}
|
|
3954
|
-
fail(
|
|
4158
|
+
fail(usage2, 2);
|
|
3955
4159
|
}
|
|
3956
|
-
function parseIdsFlag2(args,
|
|
4160
|
+
function parseIdsFlag2(args, usage2) {
|
|
3957
4161
|
const raw = stringValue(args, "ids");
|
|
3958
|
-
if (raw === void 0) fail(
|
|
4162
|
+
if (raw === void 0) fail(usage2, 2);
|
|
3959
4163
|
const ids = parseIdList(raw);
|
|
3960
4164
|
if (ids.length === 0) fail(`--ids must contain at least one id
|
|
3961
|
-
${
|
|
4165
|
+
${usage2}`, 2);
|
|
3962
4166
|
if (ids.length > BATCH_MAX_ITEMS2) {
|
|
3963
4167
|
fail(`--ids accepts at most ${BATCH_MAX_ITEMS2} ids per request
|
|
3964
|
-
${
|
|
4168
|
+
${usage2}`, 2);
|
|
3965
4169
|
}
|
|
3966
4170
|
return ids;
|
|
3967
4171
|
}
|
|
@@ -4045,7 +4249,7 @@ ${REVIEW_ACTION_USAGE}`, 2);
|
|
|
4045
4249
|
if (editedContent !== void 0) body.edited_content = editedContent;
|
|
4046
4250
|
else if (editedContentFile !== void 0) {
|
|
4047
4251
|
try {
|
|
4048
|
-
body.edited_content =
|
|
4252
|
+
body.edited_content = readFileSync3(editedContentFile, "utf-8");
|
|
4049
4253
|
} catch (error) {
|
|
4050
4254
|
fail(
|
|
4051
4255
|
`cannot read --edited-content-file ${editedContentFile}: ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -4126,28 +4330,28 @@ async function reviewTemplateList(args) {
|
|
|
4126
4330
|
printResult(out, !!args.flags.json);
|
|
4127
4331
|
return 0;
|
|
4128
4332
|
}
|
|
4129
|
-
function buildTemplateUpsertBody2(args,
|
|
4333
|
+
function buildTemplateUpsertBody2(args, usage2, requireNameAndSections) {
|
|
4130
4334
|
const body = {};
|
|
4131
4335
|
const name = stringValue(args, "name");
|
|
4132
4336
|
if (name !== void 0) {
|
|
4133
4337
|
if (name.length > TEMPLATE_MAX_NAME_LENGTH) {
|
|
4134
4338
|
fail(`--name must be at most ${TEMPLATE_MAX_NAME_LENGTH} characters
|
|
4135
|
-
${
|
|
4339
|
+
${usage2}`, 2);
|
|
4136
4340
|
}
|
|
4137
4341
|
body.name = name;
|
|
4138
4342
|
}
|
|
4139
4343
|
const hasSectionsInput = Object.hasOwn(args.flags, "sections") || Object.hasOwn(args.flags, "sections-file");
|
|
4140
4344
|
if (hasSectionsInput) {
|
|
4141
|
-
const raw = readPayloadInput(args, "sections", "sections-file",
|
|
4345
|
+
const raw = readPayloadInput(args, "sections", "sections-file", usage2);
|
|
4142
4346
|
try {
|
|
4143
4347
|
body.sections = parseTemplateSections(raw);
|
|
4144
4348
|
} catch (error) {
|
|
4145
4349
|
fail(`${error instanceof Error ? error.message : String(error)}
|
|
4146
|
-
${
|
|
4350
|
+
${usage2}`, 2);
|
|
4147
4351
|
}
|
|
4148
4352
|
}
|
|
4149
4353
|
if (requireNameAndSections && (body.name === void 0 || body.sections === void 0)) {
|
|
4150
|
-
fail(
|
|
4354
|
+
fail(usage2, 2);
|
|
4151
4355
|
}
|
|
4152
4356
|
return body;
|
|
4153
4357
|
}
|
|
@@ -4310,7 +4514,12 @@ USAGE
|
|
|
4310
4514
|
ctxdb <command> [args] [--flags]
|
|
4311
4515
|
|
|
4312
4516
|
COMMANDS
|
|
4313
|
-
|
|
4517
|
+
${DISTRIBUTION_MANIFEST.capabilities.deviceFlow ? ` login [--agent <name>] [--scope read_only|read_write|default] [--server <core-origin>]
|
|
4518
|
+
[--device-code] [--no-browser] [--json]
|
|
4519
|
+
Device Flow login only; run setup separately.
|
|
4520
|
+
auth status [--agent <name>] [--json]
|
|
4521
|
+
logout [--agent <name>] [--json]
|
|
4522
|
+
` : ""} setup [--agent <${SUPPORTED_AGENT_CHOICES}> | --all]
|
|
4314
4523
|
[--api-key=K] [--base-url=URL] [--user-id=ID]
|
|
4315
4524
|
[--no-install-skill] [--no-validate] [--json]
|
|
4316
4525
|
Without --agent \u2192 writes agents.default (CLI-only, no hooks/skills)
|
|
@@ -4499,6 +4708,7 @@ CONFIG: ~/.ctxdb/ctxdb.json (agents.default / ${SUPPORTED_AGENTS.map((agent) =>
|
|
|
4499
4708
|
LOGS: ~/.ctxdb/logs/ctxdb.log, ~/.ctxdb/logs/recall-trace.jsonl
|
|
4500
4709
|
`;
|
|
4501
4710
|
var ROUTES = {
|
|
4711
|
+
...DISTRIBUTION_MANIFEST.capabilities.deviceFlow ? { login: deviceLogin, logout: deviceLogout, auth: { status: deviceAuthStatus } } : {},
|
|
4502
4712
|
setup,
|
|
4503
4713
|
status,
|
|
4504
4714
|
ping,
|
|
@@ -4603,14 +4813,14 @@ async function dispatch(argv, routes = ROUTES, help = HELP5) {
|
|
|
4603
4813
|
return dispatchGroup([first], route, rest);
|
|
4604
4814
|
}
|
|
4605
4815
|
async function dispatchGroup(path, group, argv) {
|
|
4606
|
-
const
|
|
4816
|
+
const usage2 = `usage: ctxdb ${path.join(" ")} <${Object.keys(group).join("|")}> ...
|
|
4607
4817
|
`;
|
|
4608
4818
|
if (argv.length === 0) {
|
|
4609
|
-
process.stderr.write(
|
|
4819
|
+
process.stderr.write(usage2);
|
|
4610
4820
|
return 2;
|
|
4611
4821
|
}
|
|
4612
4822
|
if (argv[0] === "-h" || argv[0] === "--help") {
|
|
4613
|
-
process.stdout.write(
|
|
4823
|
+
process.stdout.write(usage2);
|
|
4614
4824
|
return 0;
|
|
4615
4825
|
}
|
|
4616
4826
|
const [sub, ...subRest] = argv;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
captureParsedMessages
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-76AXXLVE.js";
|
|
5
|
+
import "../chunk-5DGRNP55.js";
|
|
6
6
|
import {
|
|
7
7
|
HttpClient,
|
|
8
8
|
agentFromArgvWithFallback,
|
|
@@ -10,12 +10,12 @@ import {
|
|
|
10
10
|
load,
|
|
11
11
|
resolveDataApiCredential,
|
|
12
12
|
setDebug
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-SVO6H62S.js";
|
|
14
14
|
import {
|
|
15
15
|
shouldSkipHooks
|
|
16
16
|
} from "../chunk-5ML4VSXN.js";
|
|
17
|
-
import "../chunk-
|
|
18
|
-
import "../chunk-
|
|
17
|
+
import "../chunk-5ITT5GSP.js";
|
|
18
|
+
import "../chunk-PI2SUS3M.js";
|
|
19
19
|
|
|
20
20
|
// src/hooks/hermes-post-llm-call.ts
|
|
21
21
|
import { pathToFileURL } from "url";
|