@aliyunrds/ctxdb 1.0.11-beta.1 → 1.0.12-beta.0
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 +26 -11
- package/dist/{chunk-CA7XEF4X.js → chunk-4GYXLFNU.js} +32 -6
- package/dist/{chunk-XWJAZAMN.js → chunk-7CZIQG6Z.js} +1 -1
- package/dist/{chunk-5HPYYOPH.js → chunk-BRCQTX2M.js} +1 -1
- package/dist/{chunk-VMBCSFGF.js → chunk-C66FQHNI.js} +3 -3
- package/dist/{chunk-SG4LQTOF.js → chunk-CGA7EITY.js} +2 -2
- package/dist/{chunk-SZ3AZDMU.js → chunk-EX6SM7I3.js} +1 -1
- package/dist/{chunk-TZFDXKLJ.js → chunk-HUX2XS5P.js} +19 -10
- package/dist/cli/main.js +44 -22
- package/dist/hooks/hermes-post-llm-call.js +16 -30
- package/dist/hooks/hermes-pre-llm-call.js +8 -8
- package/dist/hooks/session-end.js +1 -1
- package/dist/hooks/session-start.js +5 -5
- package/dist/hooks/stop.js +9 -4
- package/dist/hooks/user-prompt-submit.js +5 -5
- package/dist/opencode/index.js +421 -69
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -44,9 +44,9 @@ session remains available for `ctxdb setup --agent <name>` to retry. Hermes appr
|
|
|
44
44
|
remain explicit, and successful setup includes the usual host restart/trust reminders.
|
|
45
45
|
Ordinary setup preserves
|
|
46
46
|
existing authentication and binds the default login only for an Agent without an authentication
|
|
47
|
-
choice.
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
choice. Setup, setup --all, update and reauthorization retain each credential's saved DATA endpoint.
|
|
48
|
+
A fresh installation defaults to China. To switch sites, authorize a new login with `--site`,
|
|
49
|
+
or supply that site's API key with `setup --api-key ... --site ...`; setup never redirects an existing token.
|
|
50
50
|
An explicit invalid `--base-url` (including a missing or empty value) fails before configuration
|
|
51
51
|
changes and suggests the current production URL; it never acts like an omitted option.
|
|
52
52
|
|
|
@@ -85,13 +85,20 @@ Upgrade the CLI and the actual hooks/plugin artifacts together before enabling s
|
|
|
85
85
|
New CLI reading old v2 configuration is supported; old CLI reading shared-login configuration is not.
|
|
86
86
|
See [共享登录、完整命令与兼容契约](../../docs/cli-shared-login.md) for migration and concurrency details.
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
`
|
|
90
|
-
`
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
Official site presets live in `access_layer/shared/src/sites.ts` and are shared with debug policy.
|
|
89
|
+
Use `ctxdb login --agent codex --site intl` for international Singapore, or `--site cn` for China.
|
|
90
|
+
`setup --api-key <key> --site intl` and `openclaw ctxdb init --api-key <key> --site intl`
|
|
91
|
+
select the same service. A matching `setup --site` preserves the credential's exact official alias.
|
|
92
|
+
|
|
93
|
+
| Site | Core endpoint | Console authorization page |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `cn` | `https://api.cn-hangzhou.agentcontext.aliyuncs.com` | `https://rdsnext.console.aliyun.com/contextDbCliAuthorization/cn-hangzhou` |
|
|
96
|
+
| `intl` | `https://context-database.ap-southeast-1.aliyuncs.com` | `https://rds.console.alibabacloud.com/contextDbCliAuthorization/ap-southeast-1` |
|
|
97
|
+
|
|
98
|
+
The China alias `https://context-database.aliyuncs.com` retains its China console mapping.
|
|
99
|
+
Specifying the Singapore `--base-url` also selects the international authorization page automatically.
|
|
100
|
+
CLI appends the current `user_code`. A site preset cannot be combined with `--base-url`, `--server`
|
|
101
|
+
or `--login-url`; explicit `--site` uses its built-in authorization page.
|
|
95
102
|
Use `--base-url` to select the Core service and `--login-url` to supply the HTTPS console page
|
|
96
103
|
for this invocation. The latter does not change the service origin or persist a console mapping.
|
|
97
104
|
The legacy `--server` alias for `--base-url` remains accepted; do not pass both.
|
|
@@ -411,7 +418,8 @@ hooks, plugins, or skills. It requires that profile to already exist.
|
|
|
411
418
|
|
|
412
419
|
The official-production URL allowlist contains
|
|
413
420
|
`https://api.cn-hangzhou.agentcontext.aliyuncs.com` and the legacy
|
|
414
|
-
`https://context-database.aliyuncs.com
|
|
421
|
+
`https://context-database.aliyuncs.com`, plus Singapore
|
|
422
|
+
`https://context-database.ap-southeast-1.aliyuncs.com` (a trailing slash is equivalent).
|
|
415
423
|
Policy is evaluated after profile/default inheritance and `CTXDB_BASE_URL`.
|
|
416
424
|
Any other complete URL—including pre-production domains, numeric IPs,
|
|
417
425
|
localhost, HTTP, alternate ports or paths—and any invalid URL forces effective
|
|
@@ -1021,3 +1029,10 @@ Codex 0.153.4 has completed the automatic lifecycle against a local test center/
|
|
|
1021
1029
|
上传时可用 `ctxdb kb upload-text` 或 `ctxdb kb upload-file` 的 `--review-enabled` / `--no-review-enabled` 覆盖本次文档评审开关;不传时沿用服务端默认,不修改知识库策略。两标志互斥,分片上传保留同一选择。上传回执不代表评审或入库完成,应查询实际状态。
|
|
1022
1030
|
|
|
1023
1031
|
`memory get <fact-id> --verbose` 通过原生 Fact 详情接口读取状态、关联实体 ID、来源及参考/记录时间;默认 `memory get` 的 mem0 输出保持兼容。召回统计可从同一身份的 `memory list` 中按 ID 对应读取。
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
### 删除记忆与自动采集
|
|
1035
|
+
|
|
1036
|
+
Agent 本轮实际调用 `ctxdb memory delete` / `memory batch-delete` 或已注册的 ContextDB 删除工具后,该轮自动采集返回 `memory_cleanup_skip`。即使删除失败,也不会把清理请求和结果汇报再次自动写入记忆;同轮其他业务信息也会跳过。查询、搜索、列出记忆正常采集,下一轮正常判断。
|
|
1037
|
+
|
|
1038
|
+
该规则不改变删除接口,不新增配置项。自动采集只发送当前轮正文,不重复加入前序摘要。命令示例和帮助命令不触发;隐藏在自定义脚本、动态命令或直接 HTTP/SDK 请求内的删除不在首版检测保证范围。宿主完成条件与验收范围见 [hooks 支持矩阵](../../docs/hooks-support-matrix.md)。
|
|
@@ -7,22 +7,27 @@ import {
|
|
|
7
7
|
isConnectionError,
|
|
8
8
|
resetCircuit,
|
|
9
9
|
tripCircuit
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-7CZIQG6Z.js";
|
|
11
11
|
import {
|
|
12
12
|
CtxdbError,
|
|
13
13
|
debug,
|
|
14
14
|
extractSkillSignals,
|
|
15
15
|
isDataApiReady,
|
|
16
16
|
isDebug,
|
|
17
|
-
|
|
17
|
+
normalizeTranscriptRows,
|
|
18
|
+
readTranscriptSnapshot,
|
|
18
19
|
selectTurnRows,
|
|
19
20
|
toKbDetectionMessages,
|
|
20
21
|
toParsedMessages
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-HUX2XS5P.js";
|
|
22
23
|
|
|
23
24
|
// src/lib/capture-orchestrator.ts
|
|
24
25
|
import {
|
|
25
26
|
filterMessagesForExtraction,
|
|
27
|
+
detectMemoryCleanup,
|
|
28
|
+
captureToolCalls,
|
|
29
|
+
selectCaptureTurn,
|
|
30
|
+
captureCompletionReason,
|
|
26
31
|
isKnowledgeBaseUploadTurn,
|
|
27
32
|
selectTurnMessages
|
|
28
33
|
} from "@aliyunrds/ctxdb-shared";
|
|
@@ -48,10 +53,23 @@ function getGitContext() {
|
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
// src/lib/capture-orchestrator.ts
|
|
51
|
-
async function captureTurn(transcriptPath, cfg, client, agent = "default", sessionId) {
|
|
56
|
+
async function captureTurn(transcriptPath, cfg, client, agent = "default", sessionId, completion = {}) {
|
|
52
57
|
const preflight = capturePreflight(cfg, agent);
|
|
53
58
|
if (preflight) return preflight;
|
|
54
|
-
const
|
|
59
|
+
const snapshot = readTranscriptSnapshot(transcriptPath);
|
|
60
|
+
if (snapshot.incomplete) return { captured: false, reason: "transcript_incomplete", messageCount: 0 };
|
|
61
|
+
const rawTurn = selectCaptureTurn(snapshot.rawRows);
|
|
62
|
+
const toolCalls = captureToolCalls(rawTurn);
|
|
63
|
+
const cleanup = detectMemoryCleanup(toolCalls);
|
|
64
|
+
if (cleanup.detected) {
|
|
65
|
+
debug("capture", "memory cleanup skipped", { agent, sessionId, turnId: completion.turnId, operation: cleanup.operation, source: cleanup.source });
|
|
66
|
+
return { captured: false, reason: "memory_cleanup_skip", messageCount: 0 };
|
|
67
|
+
}
|
|
68
|
+
const rows = normalizeTranscriptRows(rawTurn);
|
|
69
|
+
if (!rawTurn.length && snapshot.rows.length) {
|
|
70
|
+
const reason = toParsedMessages(snapshot.rows).length ? "empty_turn_slice" : `transcript_schema_mismatch: rows=${snapshot.rows.length} parsed=0`;
|
|
71
|
+
return { captured: false, reason, messageCount: 0 };
|
|
72
|
+
}
|
|
55
73
|
if (rows.length === 0) {
|
|
56
74
|
return { captured: false, reason: "empty_transcript", messageCount: 0 };
|
|
57
75
|
}
|
|
@@ -69,12 +87,19 @@ async function captureTurn(transcriptPath, cfg, client, agent = "default", sessi
|
|
|
69
87
|
if (dbg) debug("capture", "current turn rows", summarizeTranscriptRows(turnRows));
|
|
70
88
|
return captureParsedMessages(parsed, cfg, client, agent, sessionId, {
|
|
71
89
|
kbDetectionMessages: toKbDetectionMessages(turnRows),
|
|
72
|
-
skills: extractSkillSignals(rows)
|
|
90
|
+
skills: extractSkillSignals(rows),
|
|
91
|
+
toolCalls,
|
|
92
|
+
completionReason: captureCompletionReason(rawTurn, completion)
|
|
73
93
|
});
|
|
74
94
|
}
|
|
75
95
|
async function captureParsedMessages(parsed, cfg, client, agent = "default", sessionId, options = {}) {
|
|
76
96
|
const preflight = capturePreflight(cfg, agent);
|
|
77
97
|
if (preflight) return preflight;
|
|
98
|
+
const cleanup = detectMemoryCleanup(options.toolCalls ?? captureToolCalls(options.kbDetectionMessages ?? []));
|
|
99
|
+
if (cleanup.detected) {
|
|
100
|
+
debug("capture", "memory cleanup skipped", { agent, sessionId, operation: cleanup.operation, source: cleanup.source });
|
|
101
|
+
return { captured: false, reason: "memory_cleanup_skip", messageCount: 0 };
|
|
102
|
+
}
|
|
78
103
|
if (parsed.length === 0) {
|
|
79
104
|
return { captured: false, reason: "empty_messages", messageCount: 0 };
|
|
80
105
|
}
|
|
@@ -101,6 +126,7 @@ async function captureParsedMessages(parsed, cfg, client, agent = "default", ses
|
|
|
101
126
|
messageCount: 0
|
|
102
127
|
};
|
|
103
128
|
}
|
|
129
|
+
if (options.completionReason) return { captured: false, reason: options.completionReason, messageCount: 0 };
|
|
104
130
|
const rawMessages = turn.map((m) => ({ role: m.role, content: m.content }));
|
|
105
131
|
const filtered = filterMessagesForExtraction(rawMessages);
|
|
106
132
|
if (dbg) debug("capture", "filtered messages", summarizeTextMessages(filtered));
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
listKnowledgeBases
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EX6SM7I3.js";
|
|
5
5
|
import {
|
|
6
6
|
isConnectionError,
|
|
7
7
|
resetCircuit,
|
|
8
8
|
tripCircuit
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7CZIQG6Z.js";
|
|
10
10
|
import {
|
|
11
11
|
CtxdbError,
|
|
12
12
|
isDataApiReady,
|
|
13
13
|
resolveDataApiCredential
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-HUX2XS5P.js";
|
|
15
15
|
|
|
16
16
|
// src/lib/kb-catalog.ts
|
|
17
17
|
function sanitizeKeyEntities(raw) {
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
fetchKbCatalogBlock,
|
|
4
4
|
recallTurn
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-C66FQHNI.js";
|
|
6
6
|
import {
|
|
7
7
|
debug
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HUX2XS5P.js";
|
|
9
9
|
|
|
10
10
|
// src/lib/warmup-recall.ts
|
|
11
11
|
import { execSync } from "node:child_process";
|
|
@@ -1891,24 +1891,31 @@ import { randomUUID as randomUUID4 } from "node:crypto";
|
|
|
1891
1891
|
import { existsSync as existsSync5, readFileSync as readFileSync6 } from "node:fs";
|
|
1892
1892
|
var ANTHROPIC_MESSAGE_TYPES = /* @__PURE__ */ new Set(["user", "assistant"]);
|
|
1893
1893
|
var CODEX_RESPONSE_ITEM = "response_item";
|
|
1894
|
-
function
|
|
1895
|
-
|
|
1894
|
+
function readTranscriptSnapshot(path) {
|
|
1895
|
+
const rawRows = [];
|
|
1896
|
+
let incomplete = false;
|
|
1897
|
+
if (!existsSync5(path)) return { rows: [], rawRows, incomplete };
|
|
1896
1898
|
let text;
|
|
1897
1899
|
try {
|
|
1898
1900
|
text = readFileSync6(path, "utf-8");
|
|
1899
1901
|
} catch {
|
|
1900
|
-
return [];
|
|
1902
|
+
return { rows: [], rawRows, incomplete };
|
|
1901
1903
|
}
|
|
1902
|
-
const out = [];
|
|
1903
1904
|
for (const line of text.split("\n")) {
|
|
1904
|
-
|
|
1905
|
-
if (!s) continue;
|
|
1906
|
-
let obj;
|
|
1905
|
+
if (!line.trim()) continue;
|
|
1907
1906
|
try {
|
|
1908
|
-
|
|
1907
|
+
const value = JSON.parse(line);
|
|
1908
|
+
if (value && typeof value === "object" && !Array.isArray(value)) rawRows.push(value);
|
|
1909
|
+
else incomplete = true;
|
|
1909
1910
|
} catch {
|
|
1910
|
-
|
|
1911
|
+
incomplete = true;
|
|
1911
1912
|
}
|
|
1913
|
+
}
|
|
1914
|
+
return { rows: normalizeTranscriptRows(rawRows), rawRows, incomplete };
|
|
1915
|
+
}
|
|
1916
|
+
function normalizeTranscriptRows(rawRows) {
|
|
1917
|
+
const out = [];
|
|
1918
|
+
for (const obj of rawRows) {
|
|
1912
1919
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) continue;
|
|
1913
1920
|
const o = obj;
|
|
1914
1921
|
const rawType = typeof o.type === "string" ? o.type : "";
|
|
@@ -2136,6 +2143,7 @@ function toParsedMessages(rows) {
|
|
|
2136
2143
|
const role = msg.role;
|
|
2137
2144
|
if (role !== "user" && role !== "assistant") continue;
|
|
2138
2145
|
const content = msg.content;
|
|
2146
|
+
if (role === "user" && Array.isArray(content) && content.some((b) => b?.type === "tool_result")) continue;
|
|
2139
2147
|
if (typeof content === "string") {
|
|
2140
2148
|
push(role, content);
|
|
2141
2149
|
continue;
|
|
@@ -3249,7 +3257,8 @@ export {
|
|
|
3249
3257
|
getBinding,
|
|
3250
3258
|
bindSession,
|
|
3251
3259
|
verifiedClient,
|
|
3252
|
-
|
|
3260
|
+
readTranscriptSnapshot,
|
|
3261
|
+
normalizeTranscriptRows,
|
|
3253
3262
|
toKbDetectionMessages,
|
|
3254
3263
|
selectTurnRows,
|
|
3255
3264
|
toParsedMessages,
|
package/dist/cli/main.js
CHANGED
|
@@ -4,6 +4,9 @@ import {
|
|
|
4
4
|
completeUpdateNotification,
|
|
5
5
|
runSelfUpdate
|
|
6
6
|
} from "../chunk-G3MDJEX5.js";
|
|
7
|
+
import {
|
|
8
|
+
resolveMemoryUploadAgentId
|
|
9
|
+
} from "../chunk-SR3M7AL5.js";
|
|
7
10
|
import {
|
|
8
11
|
DEFAULT_FILE_INGEST_TIMEOUT_MS,
|
|
9
12
|
DEFAULT_FILE_UPLOAD_TIMEOUT_MS,
|
|
@@ -36,10 +39,7 @@ import {
|
|
|
36
39
|
uploadFile,
|
|
37
40
|
uploadText,
|
|
38
41
|
validateLocalFile
|
|
39
|
-
} from "../chunk-
|
|
40
|
-
import {
|
|
41
|
-
resolveMemoryUploadAgentId
|
|
42
|
-
} from "../chunk-SR3M7AL5.js";
|
|
42
|
+
} from "../chunk-EX6SM7I3.js";
|
|
43
43
|
import {
|
|
44
44
|
AGENT_CHOICES,
|
|
45
45
|
CtxdbError,
|
|
@@ -100,7 +100,7 @@ import {
|
|
|
100
100
|
withStateLock,
|
|
101
101
|
writeInstalledPkgVersion,
|
|
102
102
|
writeState
|
|
103
|
-
} from "../chunk-
|
|
103
|
+
} from "../chunk-HUX2XS5P.js";
|
|
104
104
|
import {
|
|
105
105
|
DISTRIBUTION_MANIFEST
|
|
106
106
|
} from "../chunk-5ITT5GSP.js";
|
|
@@ -987,7 +987,8 @@ async function runSetupAll(options = {}, dependencies = {}) {
|
|
|
987
987
|
agent,
|
|
988
988
|
apiKey,
|
|
989
989
|
login: options.login,
|
|
990
|
-
|
|
990
|
+
site: options.site,
|
|
991
|
+
// Public setup resolves site assertions and preserves each credential's endpoint.
|
|
991
992
|
baseUrl: options.baseUrl ?? (publicAuth ? void 0 : existing?.baseUrl),
|
|
992
993
|
userId: options.userId ?? existing?.userId,
|
|
993
994
|
persistCredential: options.persistCredential,
|
|
@@ -2275,7 +2276,7 @@ async function runUpgrade(options = {}) {
|
|
|
2275
2276
|
}
|
|
2276
2277
|
|
|
2277
2278
|
// src/cli/setup-cli.ts
|
|
2278
|
-
import { validateDataBaseUrl as validateDataBaseUrl2 } from "@aliyunrds/ctxdb-shared";
|
|
2279
|
+
import { validateDataBaseUrl as validateDataBaseUrl2, parsePublicSite, siteBaseUrl } from "@aliyunrds/ctxdb-shared";
|
|
2279
2280
|
var HELP = `ctxdb setup \u2014 configure an agent
|
|
2280
2281
|
|
|
2281
2282
|
USAGE
|
|
@@ -2348,7 +2349,7 @@ async function setup(args) {
|
|
|
2348
2349
|
).replace(
|
|
2349
2350
|
" --base-url <url> Server URL (default: https://api.cn-hangzhou.agentcontext.aliyuncs.com)\n",
|
|
2350
2351
|
""
|
|
2351
|
-
) : HELP.replace("[--api-key=K]", "[--api-key=K | --login=default|ID]").replace(" --api-key <key> API key (required on first setup)", " --api-key <key> Replace this Agent's authentication with an API key\n --login <default|ID> Bind an existing login; ordinary setup preserves existing authentication").replace("BEHAVIOR\n", "BEHAVIOR\n First-time auth binds default's login when available. Explicit unbind or invalid auth is preserved.\n")
|
|
2352
|
+
) : HELP.replace("[--base-url=URL]", "[--site=cn|intl | --base-url=URL]").replace(" --base-url <url> Server URL (default: https://api.cn-hangzhou.agentcontext.aliyuncs.com)", " --site <cn|intl> Official site; intl selects Singapore\n --base-url <url> Custom service URL; omitted URL preserves existing credentials").replace("[--api-key=K]", "[--api-key=K | --login=default|ID]").replace(" --api-key <key> API key (required on first setup)", " --api-key <key> Replace this Agent's authentication with an API key\n --login <default|ID> Bind an existing login; ordinary setup preserves existing authentication").replace("BEHAVIOR\n", "BEHAVIOR\n First-time auth binds default's login when available. Explicit unbind or invalid auth is preserved.\n")
|
|
2352
2353
|
);
|
|
2353
2354
|
return 0;
|
|
2354
2355
|
}
|
|
@@ -2376,6 +2377,15 @@ async function setup(args) {
|
|
|
2376
2377
|
);
|
|
2377
2378
|
return 2;
|
|
2378
2379
|
}
|
|
2380
|
+
let site;
|
|
2381
|
+
try {
|
|
2382
|
+
site = parsePublicSite(args.flags.site);
|
|
2383
|
+
siteBaseUrl(site, args.flags["base-url"]);
|
|
2384
|
+
if (site && DISTRIBUTION_MANIFEST.capabilities.managedCredentials) throw new Error("--site is supported only in the public distribution.");
|
|
2385
|
+
} catch (error) {
|
|
2386
|
+
process.stderr.write(error.message + "\n");
|
|
2387
|
+
return 2;
|
|
2388
|
+
}
|
|
2379
2389
|
const baseUrl = args.flags["base-url"];
|
|
2380
2390
|
if (baseUrl !== void 0) {
|
|
2381
2391
|
try {
|
|
@@ -2394,6 +2404,7 @@ async function setup(args) {
|
|
|
2394
2404
|
const result2 = await runSetupAll({
|
|
2395
2405
|
apiKey: explicitApiKey,
|
|
2396
2406
|
login,
|
|
2407
|
+
site,
|
|
2397
2408
|
baseUrl,
|
|
2398
2409
|
userId: typeof args.flags["user-id"] === "string" ? args.flags["user-id"] : void 0,
|
|
2399
2410
|
persistCredential,
|
|
@@ -2428,6 +2439,7 @@ ${highlightInlineCode(hint)}
|
|
|
2428
2439
|
agent,
|
|
2429
2440
|
apiKey: explicitApiKey,
|
|
2430
2441
|
login,
|
|
2442
|
+
site,
|
|
2431
2443
|
baseUrl,
|
|
2432
2444
|
userId: typeof args.flags["user-id"] === "string" ? args.flags["user-id"] : void 0,
|
|
2433
2445
|
persistCredential,
|
|
@@ -6031,9 +6043,9 @@ function publicSetupSpec(managedCredentials) {
|
|
|
6031
6043
|
option("--login", "Bind an existing login ID; default selects the default Agent's current login.", {
|
|
6032
6044
|
valueName: "default|ID"
|
|
6033
6045
|
}),
|
|
6034
|
-
option("--
|
|
6035
|
-
|
|
6036
|
-
|
|
6046
|
+
option("--site", "Official site: cn (China) or intl (Singapore).", { valueName: "cn|intl", choices: ["cn", "intl"] }),
|
|
6047
|
+
option("--base-url", "Custom DATA URL; omitted URL preserves the saved endpoint.", {
|
|
6048
|
+
valueName: "url"
|
|
6037
6049
|
})
|
|
6038
6050
|
];
|
|
6039
6051
|
return leaf(
|
|
@@ -6042,7 +6054,7 @@ function publicSetupSpec(managedCredentials) {
|
|
|
6042
6054
|
setup,
|
|
6043
6055
|
details({
|
|
6044
6056
|
usage: [
|
|
6045
|
-
`ctxdb setup [--agent <${SUPPORTED_AGENT_CHOICES}> | --all]${managedCredentials ? "" : " [--api-key=<key> | --login=<default|ID>] [--base-url=<url>]"} [--user-id=<id>] [--no-install-skill] [--no-validate] [--json]`
|
|
6057
|
+
`ctxdb setup [--agent <${SUPPORTED_AGENT_CHOICES}> | --all]${managedCredentials ? "" : " [--api-key=<key> | --login=<default|ID>] [--site=<cn|intl> | --base-url=<url>]"} [--user-id=<id>] [--no-install-skill] [--no-validate] [--json]`
|
|
6046
6058
|
],
|
|
6047
6059
|
options: [
|
|
6048
6060
|
option("--agent", "Configure exactly one built-in Agent; omit for the CLI-only default profile.", {
|
|
@@ -6069,6 +6081,7 @@ function publicSetupSpec(managedCredentials) {
|
|
|
6069
6081
|
"--agent and --all are mutually exclusive.",
|
|
6070
6082
|
...!managedCredentials ? [
|
|
6071
6083
|
"--api-key and --login are mutually exclusive.",
|
|
6084
|
+
"--site and --base-url are mutually exclusive. Switching sites requires login or a new API key.",
|
|
6072
6085
|
"Unset CTXDB_ACCESS_TOKEN and CTXDB_API_KEY before explicitly switching persisted authentication."
|
|
6073
6086
|
] : []
|
|
6074
6087
|
],
|
|
@@ -7374,13 +7387,15 @@ import {
|
|
|
7374
7387
|
rejectAuthEnvironment,
|
|
7375
7388
|
releaseLogin,
|
|
7376
7389
|
collectUnusedLogins,
|
|
7377
|
-
validateDataBaseUrl as validateDataBaseUrl3
|
|
7390
|
+
validateDataBaseUrl as validateDataBaseUrl3,
|
|
7391
|
+
parsePublicSite as parsePublicSite2,
|
|
7392
|
+
siteBaseUrl as siteBaseUrl2,
|
|
7393
|
+
PUBLIC_SITES as PUBLIC_SITES2
|
|
7378
7394
|
} from "@aliyunrds/ctxdb-shared";
|
|
7379
7395
|
|
|
7380
7396
|
// src/lib/oauth-login-config.ts
|
|
7381
7397
|
import { existsSync as existsSync7, readFileSync as readFileSync3 } from "node:fs";
|
|
7382
|
-
import {
|
|
7383
|
-
var PRODUCTION_AUTHORIZATION_URL = "https://rdsnext.console.aliyun.com/contextDbCliAuthorization/cn-hangzhou";
|
|
7398
|
+
import { PUBLIC_SITES, publicSiteForUrl, normalizeCoreOrigin } from "@aliyunrds/ctxdb-shared";
|
|
7384
7399
|
function authorizationPage(value2) {
|
|
7385
7400
|
if (typeof value2 !== "string" || !value2.trim()) throw new Error();
|
|
7386
7401
|
const url = new URL(value2);
|
|
@@ -7395,7 +7410,8 @@ function consoleAuthorizationBase(path, core, loginUrl) {
|
|
|
7395
7410
|
throw new Error("--login-url requires an HTTPS page URL without credentials, query parameters or fragment. No authorization request was created.");
|
|
7396
7411
|
}
|
|
7397
7412
|
}
|
|
7398
|
-
const
|
|
7413
|
+
const site = publicSiteForUrl(core);
|
|
7414
|
+
const fallback = site ? PUBLIC_SITES[site].authorizationUrl : void 0;
|
|
7399
7415
|
if (!existsSync7(path)) return fallback;
|
|
7400
7416
|
try {
|
|
7401
7417
|
const raw = JSON.parse(readFileSync3(path, "utf8"));
|
|
@@ -7439,7 +7455,7 @@ function openBrowser(url) {
|
|
|
7439
7455
|
}
|
|
7440
7456
|
|
|
7441
7457
|
// src/cli/device-auth-cli.ts
|
|
7442
|
-
var usage = "ctxdb login [--agent <name> | --login <default|ID>] [--base-url <core-origin> | --server <core-origin>] [--login-url <console-page>] [--yes] [--device-code] [--no-browser] [--json]\n";
|
|
7458
|
+
var usage = "ctxdb login [--agent <name> | --login <default|ID>] [--site <cn|intl> | --base-url <core-origin> | --server <core-origin>] [--login-url <console-page>] [--yes] [--device-code] [--no-browser] [--json]\n";
|
|
7443
7459
|
function createPublicAuthCommands(dependencies = {}) {
|
|
7444
7460
|
const env = () => dependencies.env ?? process.env;
|
|
7445
7461
|
const stdout = dependencies.stdout ?? ((s) => {
|
|
@@ -7452,7 +7468,7 @@ function createPublicAuthCommands(dependencies = {}) {
|
|
|
7452
7468
|
const launchBrowser = dependencies.openBrowser ?? openBrowser;
|
|
7453
7469
|
const output = (value2, json) => stdout(json ? JSON.stringify(value2) + "\n" : String(value2) + "\n");
|
|
7454
7470
|
function options(args, command) {
|
|
7455
|
-
const allowed = ["agent", "json", "help", "h", ...command === "login" ? ["base-url", "login-url", "server", "device-code", "no-browser", "login", "yes"] : command === "logout" ? ["login", "yes"] : command === "status" ? ["all"] : []];
|
|
7471
|
+
const allowed = ["agent", "json", "help", "h", ...command === "login" ? ["site", "base-url", "login-url", "server", "device-code", "no-browser", "login", "yes"] : command === "logout" ? ["login", "yes"] : command === "status" ? ["all"] : []];
|
|
7456
7472
|
if (args.positional.length || Object.keys(args.flags).some((k) => !allowed.includes(k))) throw new Error("Unsupported authentication option.");
|
|
7457
7473
|
for (const flag of ["json", "help", "h", "device-code", "no-browser", "yes", "all"]) {
|
|
7458
7474
|
if (args.flags[flag] !== void 0 && args.flags[flag] !== true) throw new Error("Invalid boolean authentication option.");
|
|
@@ -7493,10 +7509,13 @@ function createPublicAuthCommands(dependencies = {}) {
|
|
|
7493
7509
|
if (args.flags["base-url"] !== void 0 && args.flags.server !== void 0) throw new Error("Use --base-url or its legacy alias --server, not both.");
|
|
7494
7510
|
const explicitBase = args.flags["base-url"] ?? args.flags.server;
|
|
7495
7511
|
if (explicitBase !== void 0) validateDataBaseUrl3(explicitBase, true);
|
|
7512
|
+
const site = parsePublicSite2(args.flags.site);
|
|
7513
|
+
const presetBase = siteBaseUrl2(site, explicitBase);
|
|
7514
|
+
if (site && args.flags["login-url"] !== void 0) throw new Error("--site and --login-url are mutually exclusive.");
|
|
7496
7515
|
const pending = beginLogin(path, agent, name);
|
|
7497
7516
|
await confirmImpact(name ? pending.users[0] ?? agent : agent, pending.users, args, "Reauthorizing this login");
|
|
7498
|
-
const baseUrl = normalizeCoreOrigin2(explicitBase ?? DEFAULT_BASE_URL);
|
|
7499
|
-
const consoleBase = consoleAuthorizationBase(join6(dirname2(path), "device-environments.json"), baseUrl, args.flags["login-url"]);
|
|
7517
|
+
const baseUrl = normalizeCoreOrigin2(presetBase ?? explicitBase ?? pending.previous?.baseUrl ?? load({ path, agent, env: {} }).baseUrl ?? DEFAULT_BASE_URL);
|
|
7518
|
+
const consoleBase = site ? PUBLIC_SITES2[site].authorizationUrl : consoleAuthorizationBase(join6(dirname2(path), "device-environments.json"), baseUrl, args.flags["login-url"]);
|
|
7500
7519
|
const connection = client(baseUrl), controller = new AbortController();
|
|
7501
7520
|
let browserOpening = Promise.resolve();
|
|
7502
7521
|
const interrupt = () => controller.abort();
|
|
@@ -7720,10 +7739,11 @@ var ENVIRONMENT_CONSTRAINT = "Unset CTXDB_ACCESS_TOKEN and CTXDB_API_KEY before
|
|
|
7720
7739
|
function publicCommands() {
|
|
7721
7740
|
return [
|
|
7722
7741
|
leaf("login", "Authorize a public Device Flow login and configure the selected Agent.", deviceLogin, details({
|
|
7723
|
-
usage: ["ctxdb login [--agent=<name> | --login=<default|ID>] [--base-url=<core-origin> | --server=<core-origin>] [--login-url=<console-page>] [--device-code] [--no-browser] [--yes] [--json]"],
|
|
7742
|
+
usage: ["ctxdb login [--agent=<name> | --login=<default|ID>] [--site=<cn|intl> | --base-url=<core-origin> | --server=<core-origin>] [--login-url=<console-page>] [--device-code] [--no-browser] [--yes] [--json]"],
|
|
7724
7743
|
options: [
|
|
7725
7744
|
AGENT_OPTION2,
|
|
7726
7745
|
LOGIN_OPTION,
|
|
7746
|
+
option("--site", "Official site: cn (China) or intl (Singapore).", { valueName: "cn|intl", choices: ["cn", "intl"] }),
|
|
7727
7747
|
option("--base-url", "Core service origin for Device Flow and DATA requests.", { valueName: "core-origin" }),
|
|
7728
7748
|
option("--server", "Legacy alias for --base-url; do not combine them.", { valueName: "core-origin" }),
|
|
7729
7749
|
option("--login-url", "HTTPS console authorization page; CLI appends the current user_code.", { valueName: "console-page" }),
|
|
@@ -7732,8 +7752,9 @@ function publicCommands() {
|
|
|
7732
7752
|
YES_OPTION,
|
|
7733
7753
|
JSON_OPTION2
|
|
7734
7754
|
],
|
|
7735
|
-
constraints: ["--agent and --login are mutually exclusive.", "--base-url and --server are mutually exclusive.", ENVIRONMENT_CONSTRAINT],
|
|
7755
|
+
constraints: ["--agent and --login are mutually exclusive.", "--base-url and --server are mutually exclusive.", "--site cannot be combined with --base-url, --server or --login-url.", ENVIRONMENT_CONSTRAINT],
|
|
7736
7756
|
notes: [
|
|
7757
|
+
"With no site or URL override, reauthorization keeps the saved endpoint; a fresh installation defaults to cn.",
|
|
7737
7758
|
"Default login creates or updates the default shared login; login for another Agent creates an independent login.",
|
|
7738
7759
|
"--login reauthorizes the selected existing login while retaining its stable local ID.",
|
|
7739
7760
|
"Device scope is fixed to default. A non-default Agent login also installs hooks/skills and validates connectivity; no separate setup command is needed.",
|
|
@@ -7747,6 +7768,7 @@ function publicCommands() {
|
|
|
7747
7768
|
examples: [
|
|
7748
7769
|
{ command: "ctxdb login" },
|
|
7749
7770
|
{ command: "ctxdb login --agent=codex --json" },
|
|
7771
|
+
{ command: "ctxdb login --agent=codex --site=intl" },
|
|
7750
7772
|
{ command: "ctxdb login --login=default --yes --json" },
|
|
7751
7773
|
{ command: "ctxdb login --base-url=https://core.example.com --login-url=https://console.example.com/contextDbCliAuthorization/cn-hangzhou" }
|
|
7752
7774
|
]
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
captureParsedMessages
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-4GYXLFNU.js";
|
|
5
5
|
import "../chunk-SR3M7AL5.js";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-7CZIQG6Z.js";
|
|
7
7
|
import {
|
|
8
8
|
HttpClient,
|
|
9
9
|
agentFromArgvWithFallback,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
sessionBinding,
|
|
14
14
|
setDebug,
|
|
15
15
|
skillStopRows
|
|
16
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-HUX2XS5P.js";
|
|
17
17
|
import "../chunk-5ITT5GSP.js";
|
|
18
18
|
import {
|
|
19
19
|
shouldSkipHooks
|
|
@@ -22,6 +22,7 @@ import "../chunk-PI2SUS3M.js";
|
|
|
22
22
|
|
|
23
23
|
// src/hooks/hermes-post-llm-call.ts
|
|
24
24
|
import { pathToFileURL } from "node:url";
|
|
25
|
+
import { selectCaptureTurn, captureText, captureToolCalls, captureCompletionReason } from "@aliyunrds/ctxdb-shared";
|
|
25
26
|
function asRecord(value) {
|
|
26
27
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
27
28
|
}
|
|
@@ -31,38 +32,15 @@ function firstString(...values) {
|
|
|
31
32
|
}
|
|
32
33
|
return "";
|
|
33
34
|
}
|
|
34
|
-
function textContent(content) {
|
|
35
|
-
if (typeof content === "string") return content.trim();
|
|
36
|
-
if (!Array.isArray(content)) return "";
|
|
37
|
-
const chunks = [];
|
|
38
|
-
for (const rawBlock of content) {
|
|
39
|
-
if (typeof rawBlock === "string") {
|
|
40
|
-
if (rawBlock.trim()) chunks.push(rawBlock.trim());
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
const block = asRecord(rawBlock);
|
|
44
|
-
const text = firstString(block.text, block.content);
|
|
45
|
-
if (text.trim()) chunks.push(text.trim());
|
|
46
|
-
}
|
|
47
|
-
return chunks.join("\n").trim();
|
|
48
|
-
}
|
|
49
35
|
function currentTurnHistory(history) {
|
|
50
|
-
|
|
51
|
-
let start = -1;
|
|
52
|
-
for (let i = records.length - 1; i >= 0; i--) {
|
|
53
|
-
if (records[i].role === "user") {
|
|
54
|
-
start = i;
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return start >= 0 ? records.slice(start) : records;
|
|
36
|
+
return selectCaptureTurn(history).map(asRecord);
|
|
59
37
|
}
|
|
60
38
|
function parsedHistoryMessages(history) {
|
|
61
39
|
const messages = [];
|
|
62
40
|
for (const item of history) {
|
|
63
41
|
const role = item.role;
|
|
64
42
|
if (role !== "user" && role !== "assistant") continue;
|
|
65
|
-
const content =
|
|
43
|
+
const content = captureText(item).trim();
|
|
66
44
|
if (!content) continue;
|
|
67
45
|
messages.push({
|
|
68
46
|
role,
|
|
@@ -147,7 +125,15 @@ function extractHermesPostLlmCall(event) {
|
|
|
147
125
|
return {
|
|
148
126
|
sessionId,
|
|
149
127
|
messages: userMessage && assistantResponse ? explicitMessages : historyMessages.length > 0 ? historyMessages : explicitMessages,
|
|
150
|
-
kbDetectionMessages: toHermesKbDetectionMessages(turnHistory)
|
|
128
|
+
kbDetectionMessages: toHermesKbDetectionMessages(turnHistory),
|
|
129
|
+
toolCalls: captureToolCalls(turnHistory),
|
|
130
|
+
completionReason: userMessage && historyMessages.find((m) => m.role === "user")?.content !== userMessage ? "turn_unverified" : captureCompletionReason(turnHistory, {
|
|
131
|
+
// post_llm_call may fire for tool-producing intermediate calls. Require
|
|
132
|
+
// the host's final answer to match the final history message as well.
|
|
133
|
+
lastAssistantMessage: assistantResponse || void 0,
|
|
134
|
+
turnId: firstString(extra.turn_id, event.turn_id) || void 0,
|
|
135
|
+
sessionId
|
|
136
|
+
})
|
|
151
137
|
};
|
|
152
138
|
}
|
|
153
139
|
async function readStdinJson() {
|
|
@@ -213,7 +199,7 @@ async function main() {
|
|
|
213
199
|
client,
|
|
214
200
|
agent,
|
|
215
201
|
input.sessionId,
|
|
216
|
-
{ kbDetectionMessages: input.kbDetectionMessages }
|
|
202
|
+
{ kbDetectionMessages: input.kbDetectionMessages, toolCalls: input.toolCalls, completionReason: input.completionReason }
|
|
217
203
|
);
|
|
218
204
|
if (result.captured) {
|
|
219
205
|
debug("hermes.post_llm_call", `ok (${result.messageCount} msgs)`, result);
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
composeUserPromptSubmit
|
|
4
|
-
} from "../chunk-5HPYYOPH.js";
|
|
5
2
|
import {
|
|
6
3
|
HOOK_TIMEOUT_MS,
|
|
7
4
|
composeSessionStart
|
|
8
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-CGA7EITY.js";
|
|
6
|
+
import {
|
|
7
|
+
composeUserPromptSubmit
|
|
8
|
+
} from "../chunk-BRCQTX2M.js";
|
|
9
9
|
import {
|
|
10
10
|
fetchKbCatalogBlock
|
|
11
|
-
} from "../chunk-
|
|
12
|
-
import "../chunk-
|
|
11
|
+
} from "../chunk-C66FQHNI.js";
|
|
12
|
+
import "../chunk-EX6SM7I3.js";
|
|
13
13
|
import {
|
|
14
14
|
isCircuitOpen
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-7CZIQG6Z.js";
|
|
16
16
|
import {
|
|
17
17
|
HttpClient,
|
|
18
18
|
agentFromArgvWithFallback,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
skillDeferredFeedback,
|
|
26
26
|
skillPromptContext,
|
|
27
27
|
skillSessionStart
|
|
28
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-HUX2XS5P.js";
|
|
29
29
|
import "../chunk-5ITT5GSP.js";
|
|
30
30
|
import {
|
|
31
31
|
shouldSkipHooks
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
HOOK_TIMEOUT_MS,
|
|
4
4
|
composeSessionStart,
|
|
5
5
|
formatSessionStartStdout
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-CGA7EITY.js";
|
|
7
|
+
import "../chunk-C66FQHNI.js";
|
|
8
|
+
import "../chunk-EX6SM7I3.js";
|
|
9
9
|
import {
|
|
10
10
|
isCircuitOpen
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-7CZIQG6Z.js";
|
|
12
12
|
import {
|
|
13
13
|
HttpClient,
|
|
14
14
|
agentFromArgvWithFallback,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
resolveDataApiCredential,
|
|
18
18
|
setDebug,
|
|
19
19
|
skillSessionStart
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-HUX2XS5P.js";
|
|
21
21
|
import "../chunk-5ITT5GSP.js";
|
|
22
22
|
import {
|
|
23
23
|
shouldSkipHooks
|