@clawos-dev/clawd 0.2.656 → 0.2.658

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -5830,7 +5830,11 @@ var init_subscription_channel = __esm({
5830
5830
  SubscriptionChannelActivateArgsSchema = external_exports.object({
5831
5831
  id: external_exports.string().min(1).nullable()
5832
5832
  }).strict();
5833
- SubscriptionChannelModelsArgsSchema = external_exports.object({}).strict();
5833
+ SubscriptionChannelModelsArgsSchema = external_exports.object({
5834
+ channelId: external_exports.string().min(1).optional(),
5835
+ /** Reject discovery when the saved cloud credential source has since been edited. */
5836
+ updatedAt: external_exports.number().optional()
5837
+ }).strict().refine((args) => args.updatedAt === void 0 || args.channelId !== void 0, { message: "updatedAt requires channelId" });
5834
5838
  SubscriptionChannelModelsResultSchema = external_exports.object({
5835
5839
  /** 没有激活通道 = null(models 为空) */
5836
5840
  channelId: external_exports.string().nullable(),
@@ -6313,7 +6317,7 @@ function cloudEngineSettings(p3) {
6313
6317
  function repoSlug(url) {
6314
6318
  return url.trim().replace(/^git@[^:]+:/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/\.git$/, "");
6315
6319
  }
6316
- var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DEPLOY_PROMOTION_PHASES, DeployPromotionSchema, DeployScanFileSchema, DeployRepoSchema, DeploySecretPresenceSchema, ENGINE_AUTH_SECRETS, ENGINE_AUTH_PARTIAL_BLOCKER, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_VERIFY_STAGE, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, CLOUD_ENGINES, DeployUnpublishRunSchema, DeployStateSchema, DeployUnpublishResultSchema, DeployPatchResultSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployGetArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployConfirmTestArgsSchema, DeployPromoteArgsSchema, DeployOpenTestArgsSchema, DeployEnvironmentArgsSchema, DeployConfirmTestResultSchema, DeployPromoteResultSchema, DeployOpenTestResultSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeploySetEngineAuthArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
6320
+ var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DEPLOY_PROMOTION_PHASES, DeployPromotionSchema, DeployEngineChannelSchema, DeployEngineChannelsSchema, DeployScanFileSchema, DeployRepoSchema, DeploySecretPresenceSchema, ENGINE_AUTH_SECRETS, ENGINE_AUTH_PARTIAL_BLOCKER, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_VERIFY_STAGE, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, CLOUD_ENGINES, DeployUnpublishRunSchema, DeployStateSchema, DeployUnpublishResultSchema, DeployPatchResultSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployGetArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployConfirmTestArgsSchema, DeployPromoteArgsSchema, DeployOpenTestArgsSchema, DeployEnvironmentArgsSchema, DeployConfirmTestResultSchema, DeployPromoteResultSchema, DeployOpenTestResultSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeploySetEngineAuthArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
6317
6321
  var init_deploy_schemas = __esm({
6318
6322
  "../protocol/src/deploy-schemas.ts"() {
6319
6323
  "use strict";
@@ -6381,8 +6385,14 @@ var init_deploy_schemas = __esm({
6381
6385
  runAttempt: external_exports.number().int().positive().optional(),
6382
6386
  error: external_exports.string().optional()
6383
6387
  }).strict();
6388
+ DeployEngineChannelSchema = external_exports.object({ channelId: external_exports.string().min(1), updatedAt: external_exports.number() }).strict();
6389
+ DeployEngineChannelsSchema = external_exports.object({
6390
+ integration: DeployEngineChannelSchema.nullable().optional(),
6391
+ production: DeployEngineChannelSchema.nullable().optional()
6392
+ }).strict();
6384
6393
  DeployScanFileSchema = external_exports.object({
6385
6394
  version: external_exports.literal(4),
6395
+ engineChannels: DeployEngineChannelsSchema.optional(),
6386
6396
  scans: external_exports.array(DeployScanSchema),
6387
6397
  releases: external_exports.array(DeployReleasedSchema),
6388
6398
  promotions: external_exports.array(DeployPromotionSchema).default([])
@@ -6439,6 +6449,7 @@ var init_deploy_schemas = __esm({
6439
6449
  }).strict();
6440
6450
  DeployStateSchema = external_exports.object({
6441
6451
  personaId: external_exports.string().min(1),
6452
+ engineChannels: DeployEngineChannelsSchema.optional(),
6442
6453
  /** 本机 GitHub 身份(机器级,githubAuth:* 的同一份;上云页顶上那张卡用)。老 daemon 不给(可选只为兼容),UI 缺席时按未知处理 */
6443
6454
  github: GithubAuthStatusSchema.optional(),
6444
6455
  /** Current publisher's Feishu tool grant, including authorization links before first release. */
@@ -9332,8 +9343,9 @@ var init_methods = __esm({
9332
9343
  args: SubscriptionChannelActivateArgsSchema
9333
9344
  },
9334
9345
  "subscriptionChannel:models": {
9335
- summary: "\u5217\u51FA\u5F53\u524D\u6FC0\u6D3B\u8BA2\u9605\u901A\u9053\uFF08\u53F7\u6C60\uFF09GET {baseUrl}/models \u7684\u6A21\u578B id\u3002\u4E0A\u4E91\u9875 Claude \u5F15\u64CE\u7684\u6A21\u578B\u5019\u9009\u3002\u6CA1\u6709\u6FC0\u6D3B\u901A\u9053\u56DE\u7A7A\u8868\uFF1B\u53F7\u6C60\u8BF7\u6C42\u5931\u8D25 reject\u3002owner-only",
9336
- args: SubscriptionChannelModelsArgsSchema
9346
+ summary: "\u5217\u51FA\u6307\u5B9A\u8BA2\u9605\u901A\u9053\u7684\u6A21\u578B ID\uFF0C\u4E0D\u6FC0\u6D3B\u672C\u673A\u901A\u9053\uFF1B\u7701\u7565 channelId \u65F6\u67E5\u672C\u673A\u6FC0\u6D3B\u901A\u9053\u3002updatedAt \u6821\u9A8C\u4E91\u7AEF\u4FDD\u5B58\u540E\u901A\u9053\u662F\u5426\u53D8\u66F4\u3002\u6CA1\u6709\u672C\u673A\u6FC0\u6D3B\u901A\u9053\u56DE\u7A7A\u8868\uFF1B\u6307\u5B9A\u901A\u9053\u4E0D\u5B58\u5728\u3001\u5DF2\u53D8\u66F4\u6216\u8BF7\u6C42\u5931\u8D25 reject\u3002owner-only",
9347
+ args: SubscriptionChannelModelsArgsSchema,
9348
+ argsConstraints: { dependentRequired: { updatedAt: ["channelId"] } }
9337
9349
  },
9338
9350
  "engine:connectPool": {
9339
9351
  summary: "\u63A5\u5165\u53F7\u6C60\uFF1A\u62FF\u81EA\u52A9\u53F0\u53D1\u7684\u4E2A\u4EBA key\uFF0C\u62C9\u53F7\u6C60 setup.sh \u8DD1\u4E00\u904D\uFF08\u5199 ~/.codex/config.toml \u6307\u5411 CLIProxyAPI \u4EE3\u7406\uFF09\uFF0C\u518D\u5237 codex \u6A21\u578B\u8868\u9A8C\u8BC1\u3002\u6210\u529F\u56DE { ok:true }\uFF1B\u62FF\u4E0D\u5230\u811A\u672C / \u811A\u672C\u62A5\u9519 / \u8D85\u65F6 / 401 \u4E00\u5F8B reject \u5E26\u4EBA\u8BDD\u3002\u53EA\u7BA1 codex\uFF1B\u672C\u673A\u6CA1\u88C5 codex \u62A5 INVALID_PARAM\u3002owner-only",
@@ -15876,17 +15888,504 @@ var init_permission_stdio = __esm({
15876
15888
  }
15877
15889
  });
15878
15890
 
15891
+ // src/tools/codex-provider-models.ts
15892
+ function asRecord2(v3) {
15893
+ return v3 && typeof v3 === "object" && !Array.isArray(v3) ? v3 : null;
15894
+ }
15895
+ function readAuthKey(codexHome) {
15896
+ try {
15897
+ const raw = JSON.parse(import_node_fs21.default.readFileSync(import_node_path21.default.join(codexHome, "auth.json"), "utf8"));
15898
+ const key = asRecord2(raw)?.OPENAI_API_KEY;
15899
+ return typeof key === "string" && key ? key : void 0;
15900
+ } catch {
15901
+ return void 0;
15902
+ }
15903
+ }
15904
+ async function runAuthCommand(name, auth, deps) {
15905
+ const command = typeof auth.command === "string" && auth.command ? auth.command : void 0;
15906
+ if (!command) return void 0;
15907
+ const args = Array.isArray(auth.args) ? auth.args.filter((a2) => typeof a2 === "string") : [];
15908
+ const timeout = typeof auth.timeout_ms === "number" && auth.timeout_ms > 0 ? Math.min(auth.timeout_ms, AUTH_COMMAND_TIMEOUT_MS) : AUTH_COMMAND_TIMEOUT_MS;
15909
+ const cwd = typeof auth.cwd === "string" && auth.cwd ? auth.cwd : void 0;
15910
+ try {
15911
+ const { stdout } = await deps.execFileImpl(command, args, { ...cwd ? { cwd } : {}, timeout });
15912
+ const token = String(stdout).trim();
15913
+ if (token) return token;
15914
+ deps.logger?.warn?.(`provider "${name}": auth command \`${command}\` produced an empty token, sending unauthenticated`);
15915
+ } catch (err) {
15916
+ const e = err;
15917
+ const why = e.killed ? `killed by ${e.signal ?? "signal"} (timeout ${timeout}ms)` : e.code !== void 0 ? `exit/code ${e.code}` : "failed";
15918
+ deps.logger?.warn?.(`provider "${name}": auth command \`${command}\` ${why}, sending unauthenticated`);
15919
+ }
15920
+ return void 0;
15921
+ }
15922
+ async function resolveProviderEndpoint(rawConfig, deps = {}) {
15923
+ const config = asRecord2(asRecord2(rawConfig)?.config);
15924
+ if (!config) return null;
15925
+ const name = config.model_provider;
15926
+ if (typeof name !== "string" || !name) return null;
15927
+ const entry = asRecord2(asRecord2(config.model_providers)?.[name]);
15928
+ if (!entry) return null;
15929
+ const baseUrl = entry.base_url;
15930
+ if (typeof baseUrl !== "string" || !baseUrl) return null;
15931
+ const env = deps.env ?? process.env;
15932
+ const codexHome = deps.codexHome ?? env.CODEX_HOME ?? import_node_path21.default.join(import_node_os10.default.homedir(), ".codex");
15933
+ const envKey = typeof entry.env_key === "string" && entry.env_key ? entry.env_key : null;
15934
+ const inlineToken = typeof entry.experimental_bearer_token === "string" && entry.experimental_bearer_token ? entry.experimental_bearer_token : void 0;
15935
+ const auth = asRecord2(entry.auth);
15936
+ let token;
15937
+ if (envKey) token = env[envKey];
15938
+ else if (inlineToken) token = inlineToken;
15939
+ else if (auth && typeof auth.command === "string" && auth.command) {
15940
+ token = await runAuthCommand(name, auth, { execFileImpl: deps.execFileImpl ?? defaultExecFile, ...deps.logger ? { logger: deps.logger } : {} });
15941
+ } else token = readAuthKey(codexHome);
15942
+ if (!token && !(auth && typeof auth.command === "string" && auth.command)) {
15943
+ deps.logger?.warn?.(
15944
+ envKey ? `provider "${name}": env_key ${envKey} is not set in the daemon process, sending unauthenticated` : `provider "${name}": no OPENAI_API_KEY in ${codexHome}/auth.json, sending unauthenticated`
15945
+ );
15946
+ }
15947
+ return {
15948
+ baseUrl,
15949
+ headers: {
15950
+ Accept: "application/json",
15951
+ ...token ? { Authorization: `Bearer ${token}` } : {}
15952
+ }
15953
+ };
15954
+ }
15955
+ async function fetchProviderModels(endpoint, deps = {}) {
15956
+ const fetchImpl = deps.fetchImpl ?? fetch;
15957
+ const controller = new AbortController();
15958
+ const timer = setTimeout(() => controller.abort(), deps.timeoutMs ?? PROVIDER_FETCH_TIMEOUT_MS);
15959
+ const url = `${endpoint.baseUrl.replace(/\/$/, "")}/models`;
15960
+ try {
15961
+ const res = await fetchImpl(url, { headers: endpoint.headers, signal: controller.signal });
15962
+ if (!res.ok) throw new Error(`provider model list failed: HTTP ${res.status} from ${url}`);
15963
+ const data = asRecord2(await res.json())?.data;
15964
+ if (!Array.isArray(data)) throw new Error(`provider model list: \`data\` is not an array (${url})`);
15965
+ const out = [];
15966
+ for (const item of data) {
15967
+ const e = asRecord2(item);
15968
+ if (!e || typeof e.id !== "string" || !e.id) continue;
15969
+ out.push({ id: e.id, ...typeof e.owned_by === "string" ? { ownedBy: e.owned_by } : {} });
15970
+ }
15971
+ return out;
15972
+ } catch (err) {
15973
+ if (deps.throwOnFailure) throw err;
15974
+ deps.logger?.warn?.(`provider model list failed: ${err.message}`);
15975
+ return [];
15976
+ } finally {
15977
+ clearTimeout(timer);
15978
+ }
15979
+ }
15980
+ var import_node_child_process2, import_node_fs21, import_node_os10, import_node_path21, import_node_util, PROVIDER_FETCH_TIMEOUT_MS, defaultExecFile, AUTH_COMMAND_TIMEOUT_MS;
15981
+ var init_codex_provider_models = __esm({
15982
+ "src/tools/codex-provider-models.ts"() {
15983
+ "use strict";
15984
+ import_node_child_process2 = require("child_process");
15985
+ import_node_fs21 = __toESM(require("fs"), 1);
15986
+ import_node_os10 = __toESM(require("os"), 1);
15987
+ import_node_path21 = __toESM(require("path"), 1);
15988
+ import_node_util = require("util");
15989
+ PROVIDER_FETCH_TIMEOUT_MS = 3e3;
15990
+ defaultExecFile = (0, import_node_util.promisify)(import_node_child_process2.execFile);
15991
+ AUTH_COMMAND_TIMEOUT_MS = 5e3;
15992
+ }
15993
+ });
15994
+
15995
+ // src/tools/codex-config-toml.ts
15996
+ function parseKey(src, start) {
15997
+ const parts = [];
15998
+ let i2 = start;
15999
+ for (; ; ) {
16000
+ while (src[i2] === " " || src[i2] === " ") i2++;
16001
+ let part;
16002
+ if (src[i2] === '"') {
16003
+ let j2 = i2 + 1;
16004
+ while (j2 < src.length && src[j2] !== '"') j2 += src[j2] === "\\" ? 2 : 1;
16005
+ if (j2 >= src.length) return null;
16006
+ try {
16007
+ part = JSON.parse(src.slice(i2, j2 + 1));
16008
+ } catch {
16009
+ part = src.slice(i2 + 1, j2);
16010
+ }
16011
+ i2 = j2 + 1;
16012
+ } else if (src[i2] === "'") {
16013
+ const j2 = src.indexOf("'", i2 + 1);
16014
+ if (j2 < 0) return null;
16015
+ part = src.slice(i2 + 1, j2);
16016
+ i2 = j2 + 1;
16017
+ } else {
16018
+ const bare = /^[A-Za-z0-9_-]+/.exec(src.slice(i2));
16019
+ if (!bare) return null;
16020
+ part = bare[0];
16021
+ i2 += part.length;
16022
+ }
16023
+ parts.push(part);
16024
+ while (src[i2] === " " || src[i2] === " ") i2++;
16025
+ if (src[i2] !== ".") return { parts, end: i2 };
16026
+ i2++;
16027
+ }
16028
+ }
16029
+ function tableHeader(line) {
16030
+ const open = /^\s*(\[\[?)/.exec(line);
16031
+ if (!open) return null;
16032
+ const key = parseKey(line, open[0].length);
16033
+ if (!key) return null;
16034
+ const close = open[1] === "[[" ? "]]" : "]";
16035
+ if (!line.startsWith(close, key.end)) return null;
16036
+ return /^\s*(?:#.*)?$/.test(line.slice(key.end + close.length)) ? key.parts : null;
16037
+ }
16038
+ function keyLine(line) {
16039
+ const lead = /^\s*/.exec(line)[0].length;
16040
+ if (line[lead] === "[" || line[lead] === "#") return null;
16041
+ const key = parseKey(line, lead);
16042
+ return key && line[key.end] === "=" ? { parts: key.parts, valueStart: key.end + 1 } : null;
16043
+ }
16044
+ function scanValue(s2, start, st2) {
16045
+ let i2 = start;
16046
+ while (i2 < s2.length) {
16047
+ if (st2.ml) {
16048
+ if (st2.ml === '"""' && s2[i2] === "\\") {
16049
+ i2 += 2;
16050
+ continue;
16051
+ }
16052
+ if (s2.startsWith(st2.ml, i2)) {
16053
+ let j2 = i2 + 3;
16054
+ while (j2 < s2.length && j2 < i2 + 5 && s2[j2] === st2.ml[0]) j2++;
16055
+ st2.ml = null;
16056
+ i2 = j2;
16057
+ continue;
16058
+ }
16059
+ i2++;
16060
+ continue;
16061
+ }
16062
+ const c2 = s2[i2];
16063
+ if (c2 === "#") return;
16064
+ if (s2.startsWith('"""', i2) || s2.startsWith("'''", i2)) {
16065
+ st2.ml = s2.slice(i2, i2 + 3);
16066
+ i2 += 3;
16067
+ continue;
16068
+ }
16069
+ if (c2 === '"') {
16070
+ i2++;
16071
+ while (i2 < s2.length && s2[i2] !== '"') i2 += s2[i2] === "\\" ? 2 : 1;
16072
+ i2++;
16073
+ continue;
16074
+ }
16075
+ if (c2 === "'") {
16076
+ const j2 = s2.indexOf("'", i2 + 1);
16077
+ i2 = j2 < 0 ? s2.length : j2 + 1;
16078
+ continue;
16079
+ }
16080
+ if (c2 === "[" || c2 === "{") st2.depth++;
16081
+ else if ((c2 === "]" || c2 === "}") && st2.depth > 0) st2.depth--;
16082
+ i2++;
16083
+ }
16084
+ }
16085
+ function scanToml(text) {
16086
+ const out = [];
16087
+ const st2 = { ml: null, depth: 0 };
16088
+ let table = [];
16089
+ for (const line of text.split("\n")) {
16090
+ if (st2.ml || st2.depth > 0) {
16091
+ scanValue(line, 0, st2);
16092
+ out.push({ text: line, kind: "continuation", table });
16093
+ continue;
16094
+ }
16095
+ const header = tableHeader(line);
16096
+ if (header) {
16097
+ table = header;
16098
+ out.push({ text: line, kind: "header", table, key: header });
16099
+ continue;
16100
+ }
16101
+ const key = keyLine(line);
16102
+ if (key) {
16103
+ scanValue(line, key.valueStart, st2);
16104
+ out.push({ text: line, kind: "key", table, key: key.parts, value: line.slice(key.valueStart) });
16105
+ continue;
16106
+ }
16107
+ out.push({ text: line, kind: "other", table });
16108
+ }
16109
+ return out;
16110
+ }
16111
+ function parseTomlValue(raw) {
16112
+ const parsed = parseValueAt(raw, 0);
16113
+ if (!parsed) return void 0;
16114
+ return /^\s*(?:#[^\n]*)?\s*$/.test(raw.slice(parsed.end)) ? parsed.value : void 0;
16115
+ }
16116
+ function skipSeparators(s2, start) {
16117
+ let i2 = start;
16118
+ for (; ; ) {
16119
+ while (i2 < s2.length && " \r\n,".includes(s2[i2])) i2++;
16120
+ if (s2[i2] !== "#") return i2;
16121
+ const newline = s2.indexOf("\n", i2);
16122
+ i2 = newline < 0 ? s2.length : newline;
16123
+ }
16124
+ }
16125
+ function parseValueAt(s2, start) {
16126
+ let i2 = start;
16127
+ while (s2[i2] === " " || s2[i2] === " ") i2++;
16128
+ const c2 = s2[i2];
16129
+ if (c2 === '"') {
16130
+ if (s2.startsWith('"""', i2)) return null;
16131
+ let j2 = i2 + 1;
16132
+ while (j2 < s2.length && s2[j2] !== '"') j2 += s2[j2] === "\\" ? 2 : 1;
16133
+ if (j2 >= s2.length) return null;
16134
+ try {
16135
+ return { value: JSON.parse(s2.slice(i2, j2 + 1)), end: j2 + 1 };
16136
+ } catch {
16137
+ return null;
16138
+ }
16139
+ }
16140
+ if (c2 === "'") {
16141
+ if (s2.startsWith("'''", i2)) return null;
16142
+ const j2 = s2.indexOf("'", i2 + 1);
16143
+ return j2 < 0 ? null : { value: s2.slice(i2 + 1, j2), end: j2 + 1 };
16144
+ }
16145
+ if (c2 === "[") {
16146
+ const items = [];
16147
+ i2++;
16148
+ for (; ; ) {
16149
+ i2 = skipSeparators(s2, i2);
16150
+ if (s2[i2] === "]") return { value: items, end: i2 + 1 };
16151
+ const item = parseValueAt(s2, i2);
16152
+ if (!item) return null;
16153
+ items.push(item.value);
16154
+ i2 = item.end;
16155
+ }
16156
+ }
16157
+ if (c2 === "{") {
16158
+ const table = {};
16159
+ i2++;
16160
+ for (; ; ) {
16161
+ i2 = skipSeparators(s2, i2);
16162
+ if (s2[i2] === "}") return { value: table, end: i2 + 1 };
16163
+ const key = parseKey(s2, i2);
16164
+ if (!key || s2[key.end] !== "=") return null;
16165
+ const item = parseValueAt(s2, key.end + 1);
16166
+ if (!item) return null;
16167
+ setPath(table, key.parts, item.value);
16168
+ i2 = item.end;
16169
+ }
16170
+ }
16171
+ const bare = /^[^\s,\]}#]+/.exec(s2.slice(i2));
16172
+ return bare ? { value: bare[0], end: i2 + bare[0].length } : null;
16173
+ }
16174
+ function setPath(target, path110, value) {
16175
+ let node = target;
16176
+ for (const part of path110.slice(0, -1)) {
16177
+ const next = node[part];
16178
+ if (!next || typeof next !== "object" || Array.isArray(next)) node[part] = {};
16179
+ node = node[part];
16180
+ }
16181
+ const last = path110[path110.length - 1];
16182
+ const existing = node[last];
16183
+ if (existing && typeof existing === "object" && !Array.isArray(existing) && value && typeof value === "object" && !Array.isArray(value)) {
16184
+ Object.assign(existing, value);
16185
+ } else node[last] = value;
16186
+ }
16187
+ function readTomlTable(text, path110) {
16188
+ const result = {};
16189
+ let found = false;
16190
+ const within = (full) => full.length >= path110.length && path110.every((part, i2) => full[i2] === part);
16191
+ const lines = scanToml(text);
16192
+ for (let index = 0; index < lines.length; index++) {
16193
+ const line = lines[index];
16194
+ if (line.kind === "header" && within(line.key)) {
16195
+ found = true;
16196
+ if (line.key.length > path110.length) setPath(result, line.key.slice(path110.length), {});
16197
+ continue;
16198
+ }
16199
+ if (line.kind !== "key") continue;
16200
+ const full = [...line.table, ...line.key];
16201
+ if (!within(full)) continue;
16202
+ let raw = line.value;
16203
+ while (lines[index + 1]?.kind === "continuation") raw += `
16204
+ ${lines[++index].text}`;
16205
+ const parsed = parseTomlValue(raw);
16206
+ const value = parsed === void 0 ? UNREADABLE : parsed;
16207
+ found = true;
16208
+ if (full.length === path110.length) {
16209
+ if (value && typeof value === "object" && !Array.isArray(value)) Object.assign(result, value);
16210
+ } else setPath(result, full.slice(path110.length), value);
16211
+ }
16212
+ return found ? result : null;
16213
+ }
16214
+ var UNREADABLE;
16215
+ var init_codex_config_toml = __esm({
16216
+ "src/tools/codex-config-toml.ts"() {
16217
+ "use strict";
16218
+ UNREADABLE = /* @__PURE__ */ Symbol("unreadable TOML value");
16219
+ }
16220
+ });
16221
+
16222
+ // src/tools/subscription-channels-apply.ts
16223
+ function stripCodexProvider(text) {
16224
+ const out = [];
16225
+ let dropping = false;
16226
+ let droppingValue = false;
16227
+ for (const line of scanToml(text)) {
16228
+ if (line.kind === "header") {
16229
+ dropping = isOwnProvider(line.key);
16230
+ droppingValue = false;
16231
+ if (!dropping) out.push(line.text);
16232
+ continue;
16233
+ }
16234
+ if (line.kind === "continuation") {
16235
+ if (!dropping && !droppingValue) out.push(line.text);
16236
+ continue;
16237
+ }
16238
+ if (dropping) continue;
16239
+ if (line.kind === "key") {
16240
+ const full = [...line.table, ...line.key];
16241
+ droppingValue = full.length === 1 && full[0] === "model_provider" || isOwnProvider(full);
16242
+ if (!droppingValue) out.push(line.text);
16243
+ continue;
16244
+ }
16245
+ out.push(line.text);
16246
+ }
16247
+ return out.join("\n").trim();
16248
+ }
16249
+ function writeFileAtomic(file, data) {
16250
+ const target = import_node_fs22.default.existsSync(file) && import_node_fs22.default.lstatSync(file).isSymbolicLink() ? import_node_fs22.default.realpathSync(file) : file;
16251
+ const tmp = `${target}.tmp.${process.pid}.${Date.now()}`;
16252
+ import_node_fs22.default.writeFileSync(tmp, data, { mode: 384 });
16253
+ import_node_fs22.default.renameSync(tmp, target);
16254
+ }
16255
+ function snapshotFile(file) {
16256
+ const original = import_node_fs22.default.existsSync(file) ? import_node_fs22.default.readFileSync(file) : null;
16257
+ return () => {
16258
+ const current = import_node_fs22.default.existsSync(file) ? import_node_fs22.default.readFileSync(file) : null;
16259
+ if (original === null) {
16260
+ if (current !== null) import_node_fs22.default.rmSync(file, { force: true });
16261
+ return;
16262
+ }
16263
+ if (current !== null && current.equals(original)) return;
16264
+ writeFileAtomic(file, original);
16265
+ };
16266
+ }
16267
+ function applyCodexSubscriptionChannel(opts) {
16268
+ const codexHome = resolveCodexHome2(opts.codexHome);
16269
+ import_node_fs22.default.mkdirSync(codexHome, { recursive: true });
16270
+ const configFile = import_node_path22.default.join(codexHome, "config.toml");
16271
+ const original = import_node_fs22.default.existsSync(configFile) ? import_node_fs22.default.readFileSync(configFile, "utf8") : "";
16272
+ const rest = stripCodexProvider(original);
16273
+ let content;
16274
+ if (opts.channel) {
16275
+ const ch = opts.channel;
16276
+ content = [
16277
+ `model_provider = "${PROVIDER_ID}"`,
16278
+ ...rest ? ["", rest] : [],
16279
+ "",
16280
+ `[model_providers.${PROVIDER_ID}]`,
16281
+ `name = "${PROVIDER_ID}"`,
16282
+ `base_url = ${JSON.stringify(ch.baseUrl)}`,
16283
+ 'wire_api = "responses"',
16284
+ `auth = { command = "echo", args = [${JSON.stringify(ch.apiKey)}] }`,
16285
+ ""
16286
+ ].join("\n");
16287
+ } else {
16288
+ content = [
16289
+ 'model_provider = "openai"',
16290
+ ...rest ? ["", rest] : [],
16291
+ ""
16292
+ ].join("\n");
16293
+ }
16294
+ writeFileAtomic(configFile, content);
16295
+ }
16296
+ function applyPiSubscriptionChannel(opts) {
16297
+ const agentDir = resolvePiAgentDir(opts.agentDir);
16298
+ if (!import_node_fs22.default.existsSync(agentDir)) return false;
16299
+ const configFile = import_node_path22.default.join(agentDir, PI_SUBSCRIPTION_FILE);
16300
+ if (opts.channel) {
16301
+ const data = { baseUrl: opts.channel.baseUrl, apiKey: opts.channel.apiKey };
16302
+ writeFileAtomic(configFile, JSON.stringify(data, null, 2) + "\n");
16303
+ return true;
16304
+ }
16305
+ return false;
16306
+ }
16307
+ function claudeSubscriptionEnv(channel) {
16308
+ return {
16309
+ ANTHROPIC_BASE_URL: channel.baseUrl.replace(/\/+$/, "").replace(/\/v1$/, ""),
16310
+ ANTHROPIC_AUTH_TOKEN: channel.apiKey,
16311
+ ANTHROPIC_API_KEY: "",
16312
+ CLAUDE_CODE_USE_BEDROCK: "0",
16313
+ CLAUDE_CODE_USE_VERTEX: "0",
16314
+ CLAUDE_CODE_USE_FOUNDRY: "0"
16315
+ };
16316
+ }
16317
+ function readSettings(file) {
16318
+ if (!import_node_fs22.default.existsSync(file)) return {};
16319
+ const value = JSON.parse(import_node_fs22.default.readFileSync(file, "utf8"));
16320
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Claude settings must be a JSON object");
16321
+ return value;
16322
+ }
16323
+ function applyClaudeSubscriptionChannel(opts) {
16324
+ const dir = resolveClaudeConfigDir(opts.configDir);
16325
+ const file = import_node_path22.default.join(dir, "settings.json");
16326
+ const backupFile = import_node_path22.default.join(dir, CLAUDE_SUBSCRIPTION_BACKUP);
16327
+ if (!opts.channel && !import_node_fs22.default.existsSync(backupFile)) return;
16328
+ const settings = readSettings(file);
16329
+ if (settings.env !== void 0 && (!settings.env || typeof settings.env !== "object" || Array.isArray(settings.env))) {
16330
+ throw new Error("Claude settings.env must be a JSON object");
16331
+ }
16332
+ const env = { ...settings.env };
16333
+ if (opts.channel) {
16334
+ const connection = claudeSubscriptionEnv(opts.channel);
16335
+ import_node_fs22.default.mkdirSync(dir, { recursive: true });
16336
+ if (!import_node_fs22.default.existsSync(backupFile)) {
16337
+ writeFileAtomic(backupFile, JSON.stringify({
16338
+ hadSettings: import_node_fs22.default.existsSync(file),
16339
+ hadEnv: settings.env !== void 0,
16340
+ env: Object.fromEntries(Object.keys(connection).filter((key) => key in env).map((key) => [key, env[key]]))
16341
+ }) + "\n");
16342
+ }
16343
+ settings.env = { ...env, ...connection };
16344
+ writeFileAtomic(file, JSON.stringify(settings, null, 2) + "\n");
16345
+ return;
16346
+ }
16347
+ const backup = readSettings(backupFile);
16348
+ if (typeof backup.hadSettings !== "boolean" || typeof backup.hadEnv !== "boolean" || !backup.env || typeof backup.env !== "object" || Array.isArray(backup.env)) {
16349
+ throw new Error("Claude subscription backup is invalid; native configuration was not changed");
16350
+ }
16351
+ for (const key of CLAUDE_CONNECTION_KEYS) delete env[key];
16352
+ Object.assign(env, backup.env);
16353
+ if (Object.keys(env).length || backup.hadEnv) settings.env = env;
16354
+ else delete settings.env;
16355
+ if (!backup.hadSettings && !Object.keys(settings).length) import_node_fs22.default.rmSync(file, { force: true });
16356
+ else writeFileAtomic(file, JSON.stringify(settings, null, 2) + "\n");
16357
+ import_node_fs22.default.unlinkSync(backupFile);
16358
+ }
16359
+ var import_node_fs22, import_node_os11, import_node_path22, PROVIDER_ID, isOwnProvider, resolveCodexHome2, resolvePiAgentDir, PI_SUBSCRIPTION_FILE, resolveClaudeConfigDir, CLAUDE_SUBSCRIPTION_BACKUP, CLAUDE_CONNECTION_KEYS;
16360
+ var init_subscription_channels_apply = __esm({
16361
+ "src/tools/subscription-channels-apply.ts"() {
16362
+ "use strict";
16363
+ import_node_fs22 = __toESM(require("fs"), 1);
16364
+ import_node_os11 = __toESM(require("os"), 1);
16365
+ import_node_path22 = __toESM(require("path"), 1);
16366
+ init_codex_config_toml();
16367
+ PROVIDER_ID = "cliproxyapi";
16368
+ isOwnProvider = (path110) => path110[0] === "model_providers" && path110[1] === PROVIDER_ID;
16369
+ resolveCodexHome2 = (codexHome) => codexHome || process.env.CODEX_HOME || import_node_path22.default.join(import_node_os11.default.homedir(), ".codex");
16370
+ resolvePiAgentDir = (agentDir) => agentDir || process.env.PI_CODING_AGENT_DIR || import_node_path22.default.join(import_node_os11.default.homedir(), ".pi", "agent");
16371
+ PI_SUBSCRIPTION_FILE = "cliproxyapi.json";
16372
+ resolveClaudeConfigDir = (configDir) => configDir || process.env.CLAUDE_CONFIG_DIR || import_node_path22.default.join(import_node_os11.default.homedir(), ".claude");
16373
+ CLAUDE_SUBSCRIPTION_BACKUP = "clawd-subscription-backup.json";
16374
+ CLAUDE_CONNECTION_KEYS = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_API_KEY", "CLAUDE_CODE_USE_BEDROCK", "CLAUDE_CODE_USE_VERTEX", "CLAUDE_CODE_USE_FOUNDRY"];
16375
+ }
16376
+ });
16377
+
15879
16378
  // src/tools/claude.ts
15880
16379
  function probeViaWhich() {
15881
16380
  try {
15882
- const out = (0, import_node_child_process3.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
15883
- if (out && import_node_fs21.default.existsSync(out)) return out;
16381
+ const out = (0, import_node_child_process4.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
16382
+ if (out && import_node_fs23.default.existsSync(out)) return out;
15884
16383
  } catch {
15885
16384
  }
15886
16385
  return null;
15887
16386
  }
15888
16387
  async function probeClaude(env = process.env) {
15889
- if (env.CLAUDE_BIN && import_node_fs21.default.existsSync(env.CLAUDE_BIN)) {
16388
+ if (env.CLAUDE_BIN && import_node_fs23.default.existsSync(env.CLAUDE_BIN)) {
15890
16389
  return { available: true, path: env.CLAUDE_BIN };
15891
16390
  }
15892
16391
  const w3 = probeViaWhich();
@@ -16366,14 +16865,16 @@ function resolveClaudeContextWindow(modelId) {
16366
16865
  if (/\[1m\]/i.test(modelId)) return 1e6;
16367
16866
  return void 0;
16368
16867
  }
16369
- var import_node_child_process2, import_node_child_process3, import_node_fs21, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODEL_IDS, CLAUDE_MODELS, _assertModelIdsAligned, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
16868
+ var import_node_child_process3, import_node_child_process4, import_node_fs23, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODEL_IDS, CLAUDE_MODELS, _assertModelIdsAligned, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
16370
16869
  var init_claude = __esm({
16371
16870
  "src/tools/claude.ts"() {
16372
16871
  "use strict";
16373
- import_node_child_process2 = require("child_process");
16374
16872
  import_node_child_process3 = require("child_process");
16375
- import_node_fs21 = __toESM(require("fs"), 1);
16873
+ import_node_child_process4 = require("child_process");
16874
+ import_node_fs23 = __toESM(require("fs"), 1);
16376
16875
  init_protocol();
16876
+ init_codex_provider_models();
16877
+ init_subscription_channels_apply();
16377
16878
  init_claude_history();
16378
16879
  init_tool_result_extra();
16379
16880
  ATTACHMENT_SILENT_SUBTYPES2 = /* @__PURE__ */ new Set([
@@ -16454,7 +16955,11 @@ var init_claude = __esm({
16454
16955
  logger;
16455
16956
  historyReader;
16456
16957
  probeOverride;
16958
+ getSubscriptionChannel;
16959
+ fetchImpl;
16457
16960
  constructor(opts = {}) {
16961
+ this.getSubscriptionChannel = opts.getSubscriptionChannel;
16962
+ this.fetchImpl = opts.fetchImpl;
16458
16963
  this.logger = opts.logger;
16459
16964
  this.historyReader = opts.historyReader;
16460
16965
  this.probeOverride = opts.probeOverride;
@@ -16477,8 +16982,38 @@ var init_claude = __esm({
16477
16982
  appendTurnDurationRow(args) {
16478
16983
  appendTurnDurationRowToJsonl(args);
16479
16984
  }
16480
- async capabilities() {
16481
- return CLAUDE_CAPABILITIES;
16985
+ async capabilities(opts) {
16986
+ const channel = this.getSubscriptionChannel?.();
16987
+ if (!channel) return CLAUDE_CAPABILITIES;
16988
+ const provider = await fetchProviderModels(
16989
+ { baseUrl: channel.baseUrl, headers: { Accept: "application/json", Authorization: "Bearer " + channel.apiKey } },
16990
+ { fetchImpl: this.fetchImpl, logger: this.logger, throwOnFailure: opts?.refresh }
16991
+ );
16992
+ const known = /* @__PURE__ */ new Set();
16993
+ const merged = [];
16994
+ for (const model of provider) {
16995
+ if (known.has(model.id)) continue;
16996
+ known.add(model.id);
16997
+ const native = CLAUDE_MODELS.find((entry) => entry.id === model.id);
16998
+ merged.push(native ?? { id: model.id, label: model.id, contextWindowSize: resolveClaudeContextWindow(model.id) ?? 2e5 });
16999
+ }
17000
+ merged.sort((a2, b3) => a2.id.localeCompare(b3.id));
17001
+ return {
17002
+ ...CLAUDE_CAPABILITIES,
17003
+ models: merged,
17004
+ configSchema: CLAUDE_CAPABILITIES.configSchema.map((field) => field.name === "model" ? { ...field, default: merged[0]?.id ?? "", options: merged.map((m3) => ({ value: m3.id, label: m3.label, description: m3.description })) } : field)
17005
+ };
17006
+ }
17007
+ /** Global settings serve terminal CLI; inject the same connection for guest sessions that exclude user settings. */
17008
+ spawnEnv(ctx) {
17009
+ const channel = this.getSubscriptionChannel?.();
17010
+ if (!channel) return buildSpawnEnv(ctx.env);
17011
+ const env = { ...ctx.env, ...claudeSubscriptionEnv(channel) };
17012
+ if (ctx.model && !CLAUDE_MODEL_IDS.includes(ctx.model)) {
17013
+ for (const alias of CLAUDE_MODEL_IDS) env["ANTHROPIC_DEFAULT_" + alias.toUpperCase() + "_MODEL"] = ctx.model;
17014
+ env.CLAUDE_CODE_SUBAGENT_MODEL = ctx.model;
17015
+ }
17016
+ return buildSpawnEnv(env);
16482
17017
  }
16483
17018
  resolveContextWindow(modelId) {
16484
17019
  return resolveClaudeContextWindow(modelId);
@@ -16486,9 +17021,9 @@ var init_claude = __esm({
16486
17021
  spawn(ctx) {
16487
17022
  const args = buildSpawnArgs(ctx);
16488
17023
  const cmd = process.env.CLAUDE_BIN ?? "claude";
16489
- const child = (0, import_node_child_process2.spawn)(cmd, args, {
17024
+ const child = (0, import_node_child_process3.spawn)(cmd, args, {
16490
17025
  cwd: ctx.cwd,
16491
- env: buildSpawnEnv(ctx.env),
17026
+ env: this.spawnEnv(ctx),
16492
17027
  stdio: ["pipe", "pipe", "pipe"]
16493
17028
  });
16494
17029
  this.logger?.info("claude spawn", { cmd, args, cwd: ctx.cwd });
@@ -49138,9 +49673,8 @@ var SessionManager = class {
49138
49673
  const adapter = this.deps.getAdapter(tool);
49139
49674
  const revision = this.capabilitiesRevision.get(tool);
49140
49675
  const caps = await adapter.capabilities(opts);
49141
- if (revision === this.capabilitiesRevision.get(tool)) {
49142
- this.capabilitiesCache.set(tool, { caps, loadedAt: Date.now() });
49143
- }
49676
+ if (revision !== this.capabilitiesRevision.get(tool)) return this.getCapabilities(tool, opts);
49677
+ this.capabilitiesCache.set(tool, { caps, loadedAt: Date.now() });
49144
49678
  return caps;
49145
49679
  }
49146
49680
  invalidateCapabilities(tool) {
@@ -53273,8 +53807,8 @@ function createVisitorStore(opts) {
53273
53807
  init_claude();
53274
53808
 
53275
53809
  // src/tools/codex-session.ts
53276
- var import_node_child_process5 = require("child_process");
53277
- var import_node_path24 = __toESM(require("path"), 1);
53810
+ var import_node_child_process6 = require("child_process");
53811
+ var import_node_path26 = __toESM(require("path"), 1);
53278
53812
 
53279
53813
  // src/tools/codex-app-server-events.ts
53280
53814
  function translateNotification(method, params) {
@@ -53897,17 +54431,17 @@ function stringValue2(value) {
53897
54431
  }
53898
54432
 
53899
54433
  // src/tools/mcp-server-defs.ts
53900
- var import_node_fs22 = __toESM(require("fs"), 1);
53901
- var import_node_path21 = __toESM(require("path"), 1);
54434
+ var import_node_fs24 = __toESM(require("fs"), 1);
54435
+ var import_node_path23 = __toESM(require("path"), 1);
53902
54436
  var HTTP_TYPES = /* @__PURE__ */ new Set(["http", "sse", "streamable_http", "streamable-http"]);
53903
54437
  function loadMcpServerDefs(args) {
53904
54438
  const out = [];
53905
54439
  const seen = /* @__PURE__ */ new Set();
53906
- const sources = [...args.mcpConfigPaths, import_node_path21.default.join(args.cwd, ".mcp.json")];
54440
+ const sources = [...args.mcpConfigPaths, import_node_path23.default.join(args.cwd, ".mcp.json")];
53907
54441
  for (const file of sources) {
53908
54442
  let parsed;
53909
54443
  try {
53910
- parsed = JSON.parse(import_node_fs22.default.readFileSync(file, "utf8"));
54444
+ parsed = JSON.parse(import_node_fs24.default.readFileSync(file, "utf8"));
53911
54445
  } catch (e) {
53912
54446
  const code = e.code;
53913
54447
  if (code !== "ENOENT") {
@@ -53971,18 +54505,18 @@ function loadMcpServerDefs(args) {
53971
54505
  }
53972
54506
 
53973
54507
  // src/tools/codex-agents-config.ts
53974
- var import_node_fs23 = __toESM(require("fs"), 1);
53975
- var import_node_path22 = __toESM(require("path"), 1);
54508
+ var import_node_fs25 = __toESM(require("fs"), 1);
54509
+ var import_node_path24 = __toESM(require("path"), 1);
53976
54510
  var AGENTS_SECTION = /^\[agents\][^\n]*\n([\s\S]*?)(?=^\[|$(?![\s\S]))/m;
53977
54511
  function readKey(section, key) {
53978
54512
  const m3 = new RegExp(`^[ \\t]*${key}[ \\t]*=[ \\t]*(["'])(.*?)\\1`, "m").exec(section);
53979
54513
  return m3?.[2].trim() || void 0;
53980
54514
  }
53981
54515
  function loadCodexAgentsConfig(args) {
53982
- const file = import_node_path22.default.join(args.cwd, ".codex", "config.toml");
54516
+ const file = import_node_path24.default.join(args.cwd, ".codex", "config.toml");
53983
54517
  let text;
53984
54518
  try {
53985
- text = import_node_fs23.default.readFileSync(file, "utf8");
54519
+ text = import_node_fs25.default.readFileSync(file, "utf8");
53986
54520
  } catch (e) {
53987
54521
  const code = e.code;
53988
54522
  if (code !== "ENOENT") {
@@ -54000,13 +54534,13 @@ function loadCodexAgentsConfig(args) {
54000
54534
  }
54001
54535
 
54002
54536
  // src/tools/codex-features.ts
54003
- var import_node_child_process4 = require("child_process");
54537
+ var import_node_child_process5 = require("child_process");
54004
54538
  var cachedNetworkProxy;
54005
54539
  function hasNetworkProxyFeature(deps = {}) {
54006
54540
  if (cachedNetworkProxy !== void 0) return cachedNetworkProxy;
54007
54541
  try {
54008
54542
  const cmd = codexCommand();
54009
- const out = deps.execOverride ? deps.execOverride() : (0, import_node_child_process4.execFileSync)(cmd, ["features", "list"], {
54543
+ const out = deps.execOverride ? deps.execOverride() : (0, import_node_child_process5.execFileSync)(cmd, ["features", "list"], {
54010
54544
  env: codexEnvironment(cmd),
54011
54545
  encoding: "utf8",
54012
54546
  timeout: 3e3
@@ -54023,7 +54557,7 @@ function warmCodexFeatureCache() {
54023
54557
  if (cachedNetworkProxy !== void 0 || warming) return;
54024
54558
  warming = true;
54025
54559
  const cmd = codexCommand();
54026
- (0, import_node_child_process4.execFile)(
54560
+ (0, import_node_child_process5.execFile)(
54027
54561
  cmd,
54028
54562
  ["features", "list"],
54029
54563
  { encoding: "utf8", timeout: 3e3, env: codexEnvironment(cmd) },
@@ -54041,7 +54575,7 @@ function warmCodexFeatureCache() {
54041
54575
  }
54042
54576
 
54043
54577
  // src/attachment/mime.ts
54044
- var import_node_path23 = __toESM(require("path"), 1);
54578
+ var import_node_path25 = __toESM(require("path"), 1);
54045
54579
  var TEXT_PLAIN = "text/plain; charset=utf-8";
54046
54580
  var EXT_TO_NATIVE_MIME = {
54047
54581
  ".png": "image/png",
@@ -54140,7 +54674,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
54140
54674
  ".mk"
54141
54675
  ]);
54142
54676
  function lookupMime(filePathOrName) {
54143
- const ext = import_node_path23.default.extname(filePathOrName).toLowerCase();
54677
+ const ext = import_node_path25.default.extname(filePathOrName).toLowerCase();
54144
54678
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
54145
54679
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
54146
54680
  return "application/octet-stream";
@@ -54177,7 +54711,7 @@ function createCodexSession(ctx, sink, deps = {}) {
54177
54711
  ...resolvedCodexHome ? { CODEX_HOME: resolvedCodexHome } : {},
54178
54712
  ...ctx.env
54179
54713
  });
54180
- const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0, import_node_child_process5.spawn)(cmd, args, { cwd: ctx.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
54714
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0, import_node_child_process6.spawn)(cmd, args, { cwd: ctx.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
54181
54715
  const alive = () => proc.exitCode === null && proc.signalCode === null;
54182
54716
  const driver = driveCodexThread({
54183
54717
  ctx,
@@ -54187,7 +54721,7 @@ function createCodexSession(ctx, sink, deps = {}) {
54187
54721
  threadParams: threadStartParams(ctx),
54188
54722
  // persona 惯例装在 <cwd>/.claude/skills/,经 extraRoots 注入 discovery
54189
54723
  // (skills:list RPC 侧 codex-skills.ts 同款注入,两处保持一致)。
54190
- skillsExtraRoots: [import_node_path24.default.join(ctx.cwd, ".claude", "skills")],
54724
+ skillsExtraRoots: [import_node_path26.default.join(ctx.cwd, ".claude", "skills")],
54191
54725
  // 附件图片:验签认出本机 absPath → localImage,codex 自己读文件(TUI 拖图 / SDK local_image 同一条路)。
54192
54726
  // 0.145 起 http(s) URL 在 turn/start 入口被拒,不能再按 url 传(codex-app-server-params.ts 头注释)。
54193
54727
  // 与云上 cloudImageInput 同一道 mime 门:非图片(签过的 .md 之类)留文本,别让 codex 读到一半才炸。
@@ -54216,12 +54750,12 @@ function createCodexSession(ctx, sink, deps = {}) {
54216
54750
  }
54217
54751
 
54218
54752
  // src/tools/codex-app-server-query.ts
54219
- var import_node_child_process6 = require("child_process");
54753
+ var import_node_child_process7 = require("child_process");
54220
54754
  var DEFAULT_CODEX_QUERY_TIMEOUT_MS = 8e3;
54221
54755
  async function withCodexAppServerClient(cwd, operation, run, deps = {}) {
54222
54756
  const cmd = codexCommand();
54223
54757
  const args = ["app-server", "--listen", "stdio://"];
54224
- const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process6.spawn)(cmd, args, { cwd, env: codexEnvironment(cmd), stdio: ["pipe", "pipe", "pipe"] });
54758
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process7.spawn)(cmd, args, { cwd, env: codexEnvironment(cmd), stdio: ["pipe", "pipe", "pipe"] });
54225
54759
  const client = new CodexAppServerClient(stdioLineStream(proc), {});
54226
54760
  const timeoutMs = deps.timeoutMs ?? DEFAULT_CODEX_QUERY_TIMEOUT_MS;
54227
54761
  let timer;
@@ -54336,105 +54870,8 @@ function mergeProviderModels(native, provider) {
54336
54870
  return sorted.map((m3) => ({ ...m3, group: modelFamily(m3.id) }));
54337
54871
  }
54338
54872
 
54339
- // src/tools/codex-provider-models.ts
54340
- var import_node_child_process7 = require("child_process");
54341
- var import_node_fs24 = __toESM(require("fs"), 1);
54342
- var import_node_os10 = __toESM(require("os"), 1);
54343
- var import_node_path25 = __toESM(require("path"), 1);
54344
- var import_node_util = require("util");
54345
- var PROVIDER_FETCH_TIMEOUT_MS = 3e3;
54346
- function asRecord2(v3) {
54347
- return v3 && typeof v3 === "object" && !Array.isArray(v3) ? v3 : null;
54348
- }
54349
- function readAuthKey(codexHome) {
54350
- try {
54351
- const raw = JSON.parse(import_node_fs24.default.readFileSync(import_node_path25.default.join(codexHome, "auth.json"), "utf8"));
54352
- const key = asRecord2(raw)?.OPENAI_API_KEY;
54353
- return typeof key === "string" && key ? key : void 0;
54354
- } catch {
54355
- return void 0;
54356
- }
54357
- }
54358
- var defaultExecFile = (0, import_node_util.promisify)(import_node_child_process7.execFile);
54359
- var AUTH_COMMAND_TIMEOUT_MS = 5e3;
54360
- async function runAuthCommand(name, auth, deps) {
54361
- const command = typeof auth.command === "string" && auth.command ? auth.command : void 0;
54362
- if (!command) return void 0;
54363
- const args = Array.isArray(auth.args) ? auth.args.filter((a2) => typeof a2 === "string") : [];
54364
- const timeout = typeof auth.timeout_ms === "number" && auth.timeout_ms > 0 ? Math.min(auth.timeout_ms, AUTH_COMMAND_TIMEOUT_MS) : AUTH_COMMAND_TIMEOUT_MS;
54365
- const cwd = typeof auth.cwd === "string" && auth.cwd ? auth.cwd : void 0;
54366
- try {
54367
- const { stdout } = await deps.execFileImpl(command, args, { ...cwd ? { cwd } : {}, timeout });
54368
- const token = String(stdout).trim();
54369
- if (token) return token;
54370
- deps.logger?.warn?.(`provider "${name}": auth command \`${command}\` produced an empty token, sending unauthenticated`);
54371
- } catch (err) {
54372
- const e = err;
54373
- const why = e.killed ? `killed by ${e.signal ?? "signal"} (timeout ${timeout}ms)` : e.code !== void 0 ? `exit/code ${e.code}` : "failed";
54374
- deps.logger?.warn?.(`provider "${name}": auth command \`${command}\` ${why}, sending unauthenticated`);
54375
- }
54376
- return void 0;
54377
- }
54378
- async function resolveProviderEndpoint(rawConfig, deps = {}) {
54379
- const config = asRecord2(asRecord2(rawConfig)?.config);
54380
- if (!config) return null;
54381
- const name = config.model_provider;
54382
- if (typeof name !== "string" || !name) return null;
54383
- const entry = asRecord2(asRecord2(config.model_providers)?.[name]);
54384
- if (!entry) return null;
54385
- const baseUrl = entry.base_url;
54386
- if (typeof baseUrl !== "string" || !baseUrl) return null;
54387
- const env = deps.env ?? process.env;
54388
- const codexHome = deps.codexHome ?? env.CODEX_HOME ?? import_node_path25.default.join(import_node_os10.default.homedir(), ".codex");
54389
- const envKey = typeof entry.env_key === "string" && entry.env_key ? entry.env_key : null;
54390
- const inlineToken = typeof entry.experimental_bearer_token === "string" && entry.experimental_bearer_token ? entry.experimental_bearer_token : void 0;
54391
- const auth = asRecord2(entry.auth);
54392
- let token;
54393
- if (envKey) token = env[envKey];
54394
- else if (inlineToken) token = inlineToken;
54395
- else if (auth && typeof auth.command === "string" && auth.command) {
54396
- token = await runAuthCommand(name, auth, { execFileImpl: deps.execFileImpl ?? defaultExecFile, ...deps.logger ? { logger: deps.logger } : {} });
54397
- } else token = readAuthKey(codexHome);
54398
- if (!token && !(auth && typeof auth.command === "string" && auth.command)) {
54399
- deps.logger?.warn?.(
54400
- envKey ? `provider "${name}": env_key ${envKey} is not set in the daemon process, sending unauthenticated` : `provider "${name}": no OPENAI_API_KEY in ${codexHome}/auth.json, sending unauthenticated`
54401
- );
54402
- }
54403
- return {
54404
- baseUrl,
54405
- headers: {
54406
- Accept: "application/json",
54407
- ...token ? { Authorization: `Bearer ${token}` } : {}
54408
- }
54409
- };
54410
- }
54411
- async function fetchProviderModels(endpoint, deps = {}) {
54412
- const fetchImpl = deps.fetchImpl ?? fetch;
54413
- const controller = new AbortController();
54414
- const timer = setTimeout(() => controller.abort(), deps.timeoutMs ?? PROVIDER_FETCH_TIMEOUT_MS);
54415
- const url = `${endpoint.baseUrl.replace(/\/$/, "")}/models`;
54416
- try {
54417
- const res = await fetchImpl(url, { headers: endpoint.headers, signal: controller.signal });
54418
- if (!res.ok) throw new Error(`provider model list failed: HTTP ${res.status} from ${url}`);
54419
- const data = asRecord2(await res.json())?.data;
54420
- if (!Array.isArray(data)) throw new Error(`provider model list: \`data\` is not an array (${url})`);
54421
- const out = [];
54422
- for (const item of data) {
54423
- const e = asRecord2(item);
54424
- if (!e || typeof e.id !== "string" || !e.id) continue;
54425
- out.push({ id: e.id, ...typeof e.owned_by === "string" ? { ownedBy: e.owned_by } : {} });
54426
- }
54427
- return out;
54428
- } catch (err) {
54429
- if (deps.throwOnFailure) throw err;
54430
- deps.logger?.warn?.(`provider model list failed: ${err.message}`);
54431
- return [];
54432
- } finally {
54433
- clearTimeout(timer);
54434
- }
54435
- }
54436
-
54437
54873
  // src/tools/codex.ts
54874
+ init_codex_provider_models();
54438
54875
  init_claude();
54439
54876
  var CODEX_EFFORTS = [
54440
54877
  { value: "low", label: "Low", description: "Fast responses with lighter reasoning" },
@@ -54620,9 +55057,9 @@ var CodexAdapter = class {
54620
55057
 
54621
55058
  // src/tools/claude-tui.ts
54622
55059
  var import_node_crypto9 = require("crypto");
54623
- var import_node_fs25 = __toESM(require("fs"), 1);
54624
- var import_node_os11 = __toESM(require("os"), 1);
54625
- var import_node_path26 = __toESM(require("path"), 1);
55060
+ var import_node_fs26 = __toESM(require("fs"), 1);
55061
+ var import_node_os12 = __toESM(require("os"), 1);
55062
+ var import_node_path27 = __toESM(require("path"), 1);
54626
55063
  var import_headless = __toESM(require_xterm_headless(), 1);
54627
55064
 
54628
55065
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -55645,7 +56082,7 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
55645
56082
  command: cmd,
55646
56083
  args,
55647
56084
  cwd: ctx.cwd,
55648
- env: buildSpawnEnv(ctx.env)
56085
+ env: this.spawnEnv(ctx)
55649
56086
  });
55650
56087
  if (ctx.toolSessionId && this.tuiOpts.onPtyRegister) {
55651
56088
  this.tuiOpts.onPtyRegister(ctx.toolSessionId, pty);
@@ -55830,10 +56267,10 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
55830
56267
  }
55831
56268
  function jsonlExistsForCtx(ctx) {
55832
56269
  if (!ctx.toolSessionId) return false;
55833
- const home = import_node_os11.default.homedir();
55834
- const file = import_node_path26.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
56270
+ const home = import_node_os12.default.homedir();
56271
+ const file = import_node_path27.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
55835
56272
  try {
55836
- return import_node_fs25.default.statSync(file).isFile();
56273
+ return import_node_fs26.default.statSync(file).isFile();
55837
56274
  } catch {
55838
56275
  return false;
55839
56276
  }
@@ -55916,7 +56353,7 @@ var PersonaDispatchManager = class {
55916
56353
 
55917
56354
  // src/dispatch/store.ts
55918
56355
  var import_promises = __toESM(require("fs/promises"), 1);
55919
- var import_node_path27 = __toESM(require("path"), 1);
56356
+ var import_node_path28 = __toESM(require("path"), 1);
55920
56357
 
55921
56358
  // src/shift/constants.ts
55922
56359
  var MAX_RUNS_PER_SHIFT = 30;
@@ -55954,7 +56391,7 @@ function createDispatchStore(deps) {
55954
56391
  flushTimer = null;
55955
56392
  }
55956
56393
  const content = { version: 1, records };
55957
- await import_promises.default.mkdir(import_node_path27.default.dirname(deps.filePath), { recursive: true });
56394
+ await import_promises.default.mkdir(import_node_path28.default.dirname(deps.filePath), { recursive: true });
55958
56395
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
55959
56396
  await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
55960
56397
  await import_promises.default.rename(tmp, deps.filePath);
@@ -56023,7 +56460,7 @@ function createDispatchStore(deps) {
56023
56460
 
56024
56461
  // src/channel/json-store.ts
56025
56462
  var import_promises2 = __toESM(require("fs/promises"), 1);
56026
- var import_node_path28 = __toESM(require("path"), 1);
56463
+ var import_node_path29 = __toESM(require("path"), 1);
56027
56464
  function createJsonStore(deps) {
56028
56465
  let items = [];
56029
56466
  let flushTimer = null;
@@ -56034,7 +56471,7 @@ function createJsonStore(deps) {
56034
56471
  flushTimer = null;
56035
56472
  }
56036
56473
  const content = { version: version2, [deps.key]: items };
56037
- await import_promises2.default.mkdir(import_node_path28.default.dirname(deps.filePath), { recursive: true });
56474
+ await import_promises2.default.mkdir(import_node_path29.default.dirname(deps.filePath), { recursive: true });
56038
56475
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
56039
56476
  await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
56040
56477
  await import_promises2.default.rename(tmp, deps.filePath);
@@ -56305,10 +56742,10 @@ function createTopicStore(deps) {
56305
56742
  }
56306
56743
 
56307
56744
  // src/dispatch/mcp-config.ts
56308
- var import_node_fs26 = __toESM(require("fs"), 1);
56309
- var import_node_path29 = __toESM(require("path"), 1);
56745
+ var import_node_fs27 = __toESM(require("fs"), 1);
56746
+ var import_node_path30 = __toESM(require("path"), 1);
56310
56747
  function dispatchMcpConfigPath(dataDir) {
56311
- return import_node_path29.default.join(dataDir, "dispatch.mcp.json");
56748
+ return import_node_path30.default.join(dataDir, "dispatch.mcp.json");
56312
56749
  }
56313
56750
  function writeDispatchMcpConfig(args) {
56314
56751
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -56327,16 +56764,16 @@ function writeDispatchMcpConfig(args) {
56327
56764
  }
56328
56765
  }
56329
56766
  };
56330
- import_node_fs26.default.mkdirSync(args.dataDir, { recursive: true });
56331
- import_node_fs26.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
56767
+ import_node_fs27.default.mkdirSync(args.dataDir, { recursive: true });
56768
+ import_node_fs27.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
56332
56769
  return cfgPath;
56333
56770
  }
56334
56771
 
56335
56772
  // src/ticket/mcp-config.ts
56336
- var import_node_fs27 = __toESM(require("fs"), 1);
56337
- var import_node_path30 = __toESM(require("path"), 1);
56773
+ var import_node_fs28 = __toESM(require("fs"), 1);
56774
+ var import_node_path31 = __toESM(require("path"), 1);
56338
56775
  function ticketMcpConfigPath(dataDir) {
56339
- return import_node_path30.default.join(dataDir, "ticket.mcp.json");
56776
+ return import_node_path31.default.join(dataDir, "ticket.mcp.json");
56340
56777
  }
56341
56778
  function writeTicketMcpConfig(args) {
56342
56779
  const cfgPath = ticketMcpConfigPath(args.dataDir);
@@ -56358,16 +56795,16 @@ function writeTicketMcpConfig(args) {
56358
56795
  }
56359
56796
  }
56360
56797
  };
56361
- import_node_fs27.default.mkdirSync(args.dataDir, { recursive: true });
56362
- import_node_fs27.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
56798
+ import_node_fs28.default.mkdirSync(args.dataDir, { recursive: true });
56799
+ import_node_fs28.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
56363
56800
  return cfgPath;
56364
56801
  }
56365
56802
 
56366
56803
  // src/shift/mcp-config.ts
56367
- var import_node_fs28 = __toESM(require("fs"), 1);
56368
- var import_node_path31 = __toESM(require("path"), 1);
56804
+ var import_node_fs29 = __toESM(require("fs"), 1);
56805
+ var import_node_path32 = __toESM(require("path"), 1);
56369
56806
  function shiftMcpConfigPath(dataDir) {
56370
- return import_node_path31.default.join(dataDir, "shift.mcp.json");
56807
+ return import_node_path32.default.join(dataDir, "shift.mcp.json");
56371
56808
  }
56372
56809
  async function writeShiftMcpConfig(args) {
56373
56810
  const cfgPath = shiftMcpConfigPath(args.dataDir);
@@ -56386,16 +56823,16 @@ async function writeShiftMcpConfig(args) {
56386
56823
  }
56387
56824
  }
56388
56825
  };
56389
- await import_node_fs28.default.promises.mkdir(args.dataDir, { recursive: true });
56390
- await import_node_fs28.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
56826
+ await import_node_fs29.default.promises.mkdir(args.dataDir, { recursive: true });
56827
+ await import_node_fs29.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
56391
56828
  return cfgPath;
56392
56829
  }
56393
56830
 
56394
56831
  // src/inbox/mcp-config.ts
56395
- var import_node_fs29 = __toESM(require("fs"), 1);
56396
- var import_node_path32 = __toESM(require("path"), 1);
56832
+ var import_node_fs30 = __toESM(require("fs"), 1);
56833
+ var import_node_path33 = __toESM(require("path"), 1);
56397
56834
  function inboxMcpConfigPath(dataDir) {
56398
- return import_node_path32.default.join(dataDir, "inbox.mcp.json");
56835
+ return import_node_path33.default.join(dataDir, "inbox.mcp.json");
56399
56836
  }
56400
56837
  async function writeInboxMcpConfig(args) {
56401
56838
  const cfgPath = inboxMcpConfigPath(args.dataDir);
@@ -56414,16 +56851,16 @@ async function writeInboxMcpConfig(args) {
56414
56851
  }
56415
56852
  }
56416
56853
  };
56417
- await import_node_fs29.default.promises.mkdir(args.dataDir, { recursive: true });
56418
- await import_node_fs29.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
56854
+ await import_node_fs30.default.promises.mkdir(args.dataDir, { recursive: true });
56855
+ await import_node_fs30.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
56419
56856
  return cfgPath;
56420
56857
  }
56421
56858
 
56422
56859
  // src/peer-ops/mcp-config.ts
56423
- var import_node_fs30 = __toESM(require("fs"), 1);
56424
- var import_node_path33 = __toESM(require("path"), 1);
56860
+ var import_node_fs31 = __toESM(require("fs"), 1);
56861
+ var import_node_path34 = __toESM(require("path"), 1);
56425
56862
  function peerOpsMcpConfigPath(dataDir) {
56426
- return import_node_path33.default.join(dataDir, "peer-ops.mcp.json");
56863
+ return import_node_path34.default.join(dataDir, "peer-ops.mcp.json");
56427
56864
  }
56428
56865
  function writePeerOpsMcpConfig(args) {
56429
56866
  const cfgPath = peerOpsMcpConfigPath(args.dataDir);
@@ -56440,16 +56877,16 @@ function writePeerOpsMcpConfig(args) {
56440
56877
  }
56441
56878
  }
56442
56879
  };
56443
- import_node_fs30.default.mkdirSync(args.dataDir, { recursive: true });
56444
- import_node_fs30.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
56880
+ import_node_fs31.default.mkdirSync(args.dataDir, { recursive: true });
56881
+ import_node_fs31.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
56445
56882
  return cfgPath;
56446
56883
  }
56447
56884
 
56448
56885
  // src/rpc-tool/mcp-config.ts
56449
- var import_node_fs31 = __toESM(require("fs"), 1);
56450
- var import_node_path34 = __toESM(require("path"), 1);
56886
+ var import_node_fs32 = __toESM(require("fs"), 1);
56887
+ var import_node_path35 = __toESM(require("path"), 1);
56451
56888
  function rpcToolMcpConfigPath(dataDir) {
56452
- return import_node_path34.default.join(dataDir, "rpc-tool.mcp.json");
56889
+ return import_node_path35.default.join(dataDir, "rpc-tool.mcp.json");
56453
56890
  }
56454
56891
  function writeRpcToolMcpConfig(args) {
56455
56892
  const cfgPath = rpcToolMcpConfigPath(args.dataDir);
@@ -56468,29 +56905,29 @@ function writeRpcToolMcpConfig(args) {
56468
56905
  }
56469
56906
  }
56470
56907
  };
56471
- import_node_fs31.default.mkdirSync(args.dataDir, { recursive: true });
56472
- import_node_fs31.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
56908
+ import_node_fs32.default.mkdirSync(args.dataDir, { recursive: true });
56909
+ import_node_fs32.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
56473
56910
  return cfgPath;
56474
56911
  }
56475
56912
 
56476
56913
  // src/deploy/secret-table.ts
56477
- var import_node_fs32 = __toESM(require("fs"), 1);
56478
- var import_node_path35 = __toESM(require("path"), 1);
56914
+ var import_node_fs33 = __toESM(require("fs"), 1);
56915
+ var import_node_path36 = __toESM(require("path"), 1);
56479
56916
  var import_node_url5 = require("url");
56480
56917
  var import_meta5 = {};
56481
56918
  var LOCAL_SECRETS_DIRNAME = "secrets";
56482
56919
  function findSecretsBundleRoot(logger) {
56483
56920
  const candidates = [];
56484
56921
  try {
56485
- const here = import_node_path35.default.dirname((0, import_node_url5.fileURLToPath)(import_meta5.url));
56486
- candidates.push(import_node_path35.default.resolve(here, "..", "secrets"));
56922
+ const here = import_node_path36.default.dirname((0, import_node_url5.fileURLToPath)(import_meta5.url));
56923
+ candidates.push(import_node_path36.default.resolve(here, "..", "secrets"));
56487
56924
  } catch {
56488
56925
  }
56489
56926
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "secrets");
56490
56927
  if (fromArgv) candidates.push(fromArgv);
56491
56928
  for (const c2 of candidates) {
56492
56929
  try {
56493
- if (import_node_fs32.default.statSync(c2).isDirectory()) return c2;
56930
+ if (import_node_fs33.default.statSync(c2).isDirectory()) return c2;
56494
56931
  } catch {
56495
56932
  }
56496
56933
  }
@@ -56516,7 +56953,7 @@ function readDir(dir, logger) {
56516
56953
  const out = {};
56517
56954
  let files;
56518
56955
  try {
56519
- files = import_node_fs32.default.readdirSync(dir).filter((f2) => f2.endsWith(".env")).sort();
56956
+ files = import_node_fs33.default.readdirSync(dir).filter((f2) => f2.endsWith(".env")).sort();
56520
56957
  } catch (e) {
56521
56958
  const code = e.code;
56522
56959
  if (code !== "ENOENT") logger?.warn("secrets.dir-unreadable", { dir, code: code ?? "unknown" });
@@ -56524,19 +56961,19 @@ function readDir(dir, logger) {
56524
56961
  }
56525
56962
  for (const f2 of files) {
56526
56963
  try {
56527
- Object.assign(out, parseEnvFile(import_node_fs32.default.readFileSync(import_node_path35.default.join(dir, f2), "utf8")));
56964
+ Object.assign(out, parseEnvFile(import_node_fs33.default.readFileSync(import_node_path36.default.join(dir, f2), "utf8")));
56528
56965
  } catch (e) {
56529
- logger?.warn("secrets.file-unreadable", { file: import_node_path35.default.join(dir, f2), error: e.message });
56966
+ logger?.warn("secrets.file-unreadable", { file: import_node_path36.default.join(dir, f2), error: e.message });
56530
56967
  }
56531
56968
  }
56532
56969
  return out;
56533
56970
  }
56534
56971
  function upsertEnvFileVar(file, key, value) {
56535
56972
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new Error(`invalid env name: ${key}`);
56536
- import_node_fs32.default.mkdirSync(import_node_path35.default.dirname(file), { recursive: true, mode: 448 });
56973
+ import_node_fs33.default.mkdirSync(import_node_path36.default.dirname(file), { recursive: true, mode: 448 });
56537
56974
  let lines = [];
56538
56975
  try {
56539
- lines = import_node_fs32.default.readFileSync(file, "utf8").split("\n");
56976
+ lines = import_node_fs33.default.readFileSync(file, "utf8").split("\n");
56540
56977
  if (lines[lines.length - 1] === "") lines.pop();
56541
56978
  } catch {
56542
56979
  }
@@ -56544,12 +56981,12 @@ function upsertEnvFileVar(file, key, value) {
56544
56981
  let replaced = false;
56545
56982
  const out = lines.map((l2) => re2.test(l2) ? (replaced = true, `${key}=${value}`) : l2);
56546
56983
  if (!replaced) out.push(`${key}=${value}`);
56547
- import_node_fs32.default.writeFileSync(file, `${out.join("\n")}
56984
+ import_node_fs33.default.writeFileSync(file, `${out.join("\n")}
56548
56985
  `, { encoding: "utf8", mode: 384 });
56549
56986
  }
56550
56987
  function readEnvFileVar(file, key) {
56551
56988
  try {
56552
- return parseEnvFile(import_node_fs32.default.readFileSync(file, "utf8"))[key];
56989
+ return parseEnvFile(import_node_fs33.default.readFileSync(file, "utf8"))[key];
56553
56990
  } catch {
56554
56991
  return void 0;
56555
56992
  }
@@ -56558,7 +56995,7 @@ function removeEnvFileVar(file, key) {
56558
56995
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new Error(`invalid env name: ${key}`);
56559
56996
  let lines;
56560
56997
  try {
56561
- lines = import_node_fs32.default.readFileSync(file, "utf8").split("\n");
56998
+ lines = import_node_fs33.default.readFileSync(file, "utf8").split("\n");
56562
56999
  } catch {
56563
57000
  return;
56564
57001
  }
@@ -56567,10 +57004,10 @@ function removeEnvFileVar(file, key) {
56567
57004
  const out = lines.filter((l2) => !re2.test(l2));
56568
57005
  if (out.length === lines.length) return;
56569
57006
  if (out.every((l2) => l2.trim() === "" || l2.trim().startsWith("#"))) {
56570
- import_node_fs32.default.rmSync(file, { force: true });
57007
+ import_node_fs33.default.rmSync(file, { force: true });
56571
57008
  return;
56572
57009
  }
56573
- import_node_fs32.default.writeFileSync(file, `${out.join("\n")}
57010
+ import_node_fs33.default.writeFileSync(file, `${out.join("\n")}
56574
57011
  `, { encoding: "utf8", mode: 384 });
56575
57012
  }
56576
57013
  function readSecretTable(args) {
@@ -56581,12 +57018,12 @@ function readSecretTable(args) {
56581
57018
  }
56582
57019
 
56583
57020
  // src/dispatch/source-transcript.ts
56584
- var import_node_path36 = __toESM(require("path"), 1);
57021
+ var import_node_path37 = __toESM(require("path"), 1);
56585
57022
  init_claude_history();
56586
57023
  var NO_SOURCE_TRANSCRIPT = "(no transcript yet \u2014 operate from the task description alone)";
56587
57024
  function resolveSourceJsonlPath(sourceFile, home) {
56588
57025
  if (!sourceFile?.toolSessionId) return NO_SOURCE_TRANSCRIPT;
56589
- return import_node_path36.default.join(
57026
+ return import_node_path37.default.join(
56590
57027
  home,
56591
57028
  ".claude",
56592
57029
  "projects",
@@ -56597,7 +57034,7 @@ function resolveSourceJsonlPath(sourceFile, home) {
56597
57034
 
56598
57035
  // src/shift/store.ts
56599
57036
  var import_promises3 = __toESM(require("fs/promises"), 1);
56600
- var import_node_path37 = __toESM(require("path"), 1);
57037
+ var import_node_path38 = __toESM(require("path"), 1);
56601
57038
  var import_node_crypto10 = require("crypto");
56602
57039
 
56603
57040
  // src/shift/schedule.ts
@@ -56672,7 +57109,7 @@ function createShiftStore(deps) {
56672
57109
  flushTimer = null;
56673
57110
  }
56674
57111
  const content = { version: 1, shifts };
56675
- await import_promises3.default.mkdir(import_node_path37.default.dirname(deps.filePath), { recursive: true });
57112
+ await import_promises3.default.mkdir(import_node_path38.default.dirname(deps.filePath), { recursive: true });
56676
57113
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
56677
57114
  await import_promises3.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
56678
57115
  await import_promises3.default.rename(tmp, deps.filePath);
@@ -57096,40 +57533,40 @@ var import_node_crypto14 = require("crypto");
57096
57533
  var import_node_perf_hooks = require("perf_hooks");
57097
57534
 
57098
57535
  // src/deploy/persona-test.ts
57099
- var import_node_fs33 = __toESM(require("fs"), 1);
57100
- var import_node_path38 = __toESM(require("path"), 1);
57536
+ var import_node_fs34 = __toESM(require("fs"), 1);
57537
+ var import_node_path39 = __toESM(require("path"), 1);
57101
57538
  init_protocol();
57102
57539
  var TEST_SCAN_NOTE_PREFIX = PUBLISHER_TEST_NOTE_PREFIX;
57103
57540
  function regularFile(root, relative5) {
57104
57541
  let current = root;
57105
57542
  for (const segment of relative5.split("/")) {
57106
- current = import_node_path38.default.join(current, segment);
57107
- if (import_node_fs33.default.lstatSync(current).isSymbolicLink()) throw new Error("symlink");
57543
+ current = import_node_path39.default.join(current, segment);
57544
+ if (import_node_fs34.default.lstatSync(current).isSymbolicLink()) throw new Error("symlink");
57108
57545
  }
57109
- if (!import_node_fs33.default.statSync(current).isFile()) throw new Error("not a file");
57110
- const resolved = import_node_fs33.default.realpathSync(current);
57111
- if (!resolved.startsWith(root + import_node_path38.default.sep)) throw new Error("outside root");
57546
+ if (!import_node_fs34.default.statSync(current).isFile()) throw new Error("not a file");
57547
+ const resolved = import_node_fs34.default.realpathSync(current);
57548
+ if (!resolved.startsWith(root + import_node_path39.default.sep)) throw new Error("outside root");
57112
57549
  return resolved;
57113
57550
  }
57114
57551
  function discoverPublisherTest(dir) {
57115
57552
  try {
57116
- const root = import_node_fs33.default.realpathSync(dir);
57553
+ const root = import_node_fs34.default.realpathSync(dir);
57117
57554
  try {
57118
- import_node_fs33.default.lstatSync(import_node_path38.default.join(root, ".clawd"));
57555
+ import_node_fs34.default.lstatSync(import_node_path39.default.join(root, ".clawd"));
57119
57556
  } catch (error) {
57120
57557
  if (error.code === "ENOENT") return { problems: [] };
57121
57558
  throw error;
57122
57559
  }
57123
- if (import_node_fs33.default.lstatSync(import_node_path38.default.join(root, ".clawd")).isSymbolicLink()) throw new Error("symlink");
57560
+ if (import_node_fs34.default.lstatSync(import_node_path39.default.join(root, ".clawd")).isSymbolicLink()) throw new Error("symlink");
57124
57561
  try {
57125
- import_node_fs33.default.lstatSync(import_node_path38.default.join(root, ".clawd/test.json"));
57562
+ import_node_fs34.default.lstatSync(import_node_path39.default.join(root, ".clawd/test.json"));
57126
57563
  } catch (error) {
57127
57564
  if (error.code === "ENOENT") return { problems: [] };
57128
57565
  throw error;
57129
57566
  }
57130
57567
  const file = regularFile(root, ".clawd/test.json");
57131
- if (import_node_fs33.default.statSync(file).size > 64 * 1024) throw new Error("oversized");
57132
- const test = PublisherTestSchema.parse(JSON.parse(import_node_fs33.default.readFileSync(file, "utf8")));
57568
+ if (import_node_fs34.default.statSync(file).size > 64 * 1024) throw new Error("oversized");
57569
+ const test = PublisherTestSchema.parse(JSON.parse(import_node_fs34.default.readFileSync(file, "utf8")));
57133
57570
  regularFile(root, test.entry);
57134
57571
  return { test, problems: [] };
57135
57572
  } catch {
@@ -57530,19 +57967,19 @@ function openHttpTurn(opts) {
57530
57967
 
57531
57968
  // src/deploy/repo.ts
57532
57969
  var import_promises5 = __toESM(require("fs/promises"), 1);
57533
- var import_node_path41 = __toESM(require("path"), 1);
57970
+ var import_node_path42 = __toESM(require("path"), 1);
57534
57971
  init_protocol();
57535
57972
 
57536
57973
  // src/deploy/deploy-file.ts
57537
57974
  var import_promises4 = __toESM(require("fs/promises"), 1);
57538
- var import_node_path40 = __toESM(require("path"), 1);
57975
+ var import_node_path41 = __toESM(require("path"), 1);
57539
57976
  var import_node_crypto11 = require("crypto");
57540
57977
  init_zod();
57541
57978
  init_protocol();
57542
57979
 
57543
57980
  // src/deploy/connectors.ts
57544
- var import_node_fs34 = __toESM(require("fs"), 1);
57545
- var import_node_path39 = __toESM(require("path"), 1);
57981
+ var import_node_fs35 = __toESM(require("fs"), 1);
57982
+ var import_node_path40 = __toESM(require("path"), 1);
57546
57983
  init_zod();
57547
57984
  init_protocol();
57548
57985
 
@@ -57630,11 +58067,11 @@ var PACKAGE_RUNNERS = /* @__PURE__ */ new Set(["npx", "uvx", "pnpx", "bunx"]);
57630
58067
  var SCRIPT_RUNNERS = /* @__PURE__ */ new Set(["node", "bun", "deno", "python", "python3"]);
57631
58068
  var HOST_ARG_PLACEHOLDER = "CLAWD_PERSONA_DIR";
57632
58069
  function scanMcpConnectors(personaDir) {
57633
- const file = import_node_path39.default.join(personaDir, ".mcp.json");
58070
+ const file = import_node_path40.default.join(personaDir, ".mcp.json");
57634
58071
  const out = { readable: true, connectors: [], evidence: [], warnings: [] };
57635
58072
  let parsed;
57636
58073
  try {
57637
- parsed = JSON.parse(import_node_fs34.default.readFileSync(file, "utf8"));
58074
+ parsed = JSON.parse(import_node_fs35.default.readFileSync(file, "utf8"));
57638
58075
  } catch (e) {
57639
58076
  if (e.code === "ENOENT") return out;
57640
58077
  out.readable = false;
@@ -57730,8 +58167,8 @@ function mergeScannedConnectors(existing, scanned) {
57730
58167
  }
57731
58168
 
57732
58169
  // src/deploy/deploy-file.ts
57733
- var DEPLOY_FILE = import_node_path40.default.join(".clawd", "deploy.json");
57734
- var SCAN_FILE = import_node_path40.default.join(".clawd", "deploy-scan.json");
58170
+ var DEPLOY_FILE = import_node_path41.default.join(".clawd", "deploy.json");
58171
+ var SCAN_FILE = import_node_path41.default.join(".clawd", "deploy-scan.json");
57735
58172
  async function readJson(file) {
57736
58173
  let raw;
57737
58174
  try {
@@ -57747,14 +58184,14 @@ async function readJson(file) {
57747
58184
  }
57748
58185
  }
57749
58186
  async function writeJson(file, value) {
57750
- await import_promises4.default.mkdir(import_node_path40.default.dirname(file), { recursive: true });
58187
+ await import_promises4.default.mkdir(import_node_path41.default.dirname(file), { recursive: true });
57751
58188
  const tmp = `${file}.tmp-${process.pid}`;
57752
58189
  await import_promises4.default.writeFile(tmp, `${JSON.stringify(value, null, 2)}
57753
58190
  `);
57754
58191
  await import_promises4.default.rename(tmp, file);
57755
58192
  }
57756
58193
  async function readDeployFile(dir) {
57757
- const raw = await readJson(import_node_path40.default.join(dir, DEPLOY_FILE));
58194
+ const raw = await readJson(import_node_path41.default.join(dir, DEPLOY_FILE));
57758
58195
  if (raw === void 0) return void 0;
57759
58196
  const parsed = DeployFileSchema.safeParse(raw);
57760
58197
  if (!parsed.success) {
@@ -57764,18 +58201,18 @@ async function readDeployFile(dir) {
57764
58201
  return parsed.data;
57765
58202
  }
57766
58203
  async function writeDeployFile(dir, file) {
57767
- await writeJson(import_node_path40.default.join(dir, DEPLOY_FILE), DeployFileSchema.parse(file));
58204
+ await writeJson(import_node_path41.default.join(dir, DEPLOY_FILE), DeployFileSchema.parse(file));
57768
58205
  }
57769
58206
  async function readDeployFileRaw(dir) {
57770
58207
  try {
57771
- return await import_promises4.default.readFile(import_node_path40.default.join(dir, DEPLOY_FILE), "utf8");
58208
+ return await import_promises4.default.readFile(import_node_path41.default.join(dir, DEPLOY_FILE), "utf8");
57772
58209
  } catch (err) {
57773
58210
  if (err.code === "ENOENT") return void 0;
57774
58211
  throw err;
57775
58212
  }
57776
58213
  }
57777
58214
  async function restoreDeployFileRaw(dir, raw) {
57778
- const file = import_node_path40.default.join(dir, DEPLOY_FILE);
58215
+ const file = import_node_path41.default.join(dir, DEPLOY_FILE);
57779
58216
  if (raw === void 0) await import_promises4.default.rm(file, { force: true });
57780
58217
  else await import_promises4.default.writeFile(file, raw);
57781
58218
  }
@@ -57826,7 +58263,7 @@ function normalizeLegacyScan(raw) {
57826
58263
  return fix(raw);
57827
58264
  }
57828
58265
  async function readScanFile(dir) {
57829
- const raw = normalizeLegacyScan(await readJson(import_node_path40.default.join(dir, SCAN_FILE)));
58266
+ const raw = normalizeLegacyScan(await readJson(import_node_path41.default.join(dir, SCAN_FILE)));
57830
58267
  if (raw === void 0) return void 0;
57831
58268
  const badShape = (issues) => {
57832
58269
  const first = issues[0];
@@ -57852,7 +58289,7 @@ async function readScanFile(dir) {
57852
58289
  return parsed.data;
57853
58290
  }
57854
58291
  async function writeScanFile(dir, file) {
57855
- await writeJson(import_node_path40.default.join(dir, SCAN_FILE), DeployScanFileSchema.parse(file));
58292
+ await writeJson(import_node_path41.default.join(dir, SCAN_FILE), DeployScanFileSchema.parse(file));
57856
58293
  }
57857
58294
  function replaceScan(file, entry) {
57858
58295
  const idx = file.scans.findIndex((s2) => s2.id === entry.id);
@@ -62117,7 +62554,7 @@ var runCommand = (cmd, args, opts = {}) => new Promise((resolve9) => {
62117
62554
  });
62118
62555
 
62119
62556
  // src/deploy/repo.ts
62120
- var DEPLOY_FILE_REL = DEPLOY_FILE.split(import_node_path41.default.sep).join("/");
62557
+ var DEPLOY_FILE_REL = DEPLOY_FILE.split(import_node_path42.default.sep).join("/");
62121
62558
  var PERSONA_FILE_REL = ".clawd/persona.json";
62122
62559
  var DIRTY_IGNORED = [DEPLOY_FILE_REL, PERSONA_FILE_REL];
62123
62560
  var RepoError = class extends Error {
@@ -62150,7 +62587,7 @@ async function prepareIntegration(exec, dir, auth) {
62150
62587
  for (const name of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"]) {
62151
62588
  const rel = await mustGit(exec, dir, ["rev-parse", "--git-path", name], "\u68C0\u67E5 Git \u64CD\u4F5C");
62152
62589
  try {
62153
- await import_promises5.default.stat(import_node_path41.default.resolve(dir, rel));
62590
+ await import_promises5.default.stat(import_node_path42.default.resolve(dir, rel));
62154
62591
  throw new RepoError("Git \u5408\u5E76\u6216\u53D8\u57FA\u8FD8\u672A\u5B8C\u6210\uFF0C\u5148\u5904\u7406\u518D\u53D1\u5E03");
62155
62592
  } catch (err) {
62156
62593
  if (err.code !== "ENOENT") throw err;
@@ -62211,7 +62648,7 @@ async function samePath(a2, b3) {
62211
62648
  try {
62212
62649
  return await import_promises5.default.realpath(x2);
62213
62650
  } catch {
62214
- return import_node_path41.default.resolve(x2);
62651
+ return import_node_path42.default.resolve(x2);
62215
62652
  }
62216
62653
  };
62217
62654
  return await real(a2) === await real(b3);
@@ -62237,7 +62674,7 @@ async function identityArgs(exec, dir) {
62237
62674
  return ["-c", "user.name=clawd", "-c", "user.email=clawd@clawos.local"];
62238
62675
  }
62239
62676
  async function writeGitignore(dir) {
62240
- const gi = import_node_path41.default.join(dir, ".gitignore");
62677
+ const gi = import_node_path42.default.join(dir, ".gitignore");
62241
62678
  let existing;
62242
62679
  try {
62243
62680
  existing = await import_promises5.default.readFile(gi, "utf8");
@@ -62248,18 +62685,18 @@ async function writeGitignore(dir) {
62248
62685
  }
62249
62686
  async function writeWorkflow(dir) {
62250
62687
  for (const [rel, body] of [[WORKFLOW_PATH, WORKFLOW_TEMPLATE], [UNPUBLISH_WORKFLOW_PATH, UNPUBLISH_WORKFLOW_TEMPLATE]]) {
62251
- const wf = import_node_path41.default.join(dir, rel);
62252
- await import_promises5.default.mkdir(import_node_path41.default.dirname(wf), { recursive: true });
62688
+ const wf = import_node_path42.default.join(dir, rel);
62689
+ await import_promises5.default.mkdir(import_node_path42.default.dirname(wf), { recursive: true });
62253
62690
  await import_promises5.default.writeFile(wf, body);
62254
62691
  }
62255
62692
  }
62256
62693
  async function writeDockerfile(dir, personaId2, image) {
62257
62694
  const baseImage = image.replace("registry-vpc.cn-hangzhou.aliyuncs.com/", "registry.cn-hangzhou.aliyuncs.com/");
62258
- await import_promises5.default.mkdir(import_node_path41.default.join(dir, ".clawd"), { recursive: true });
62259
- await import_promises5.default.writeFile(import_node_path41.default.join(dir, ".clawd", "base-image.txt"), `${baseImage}
62695
+ await import_promises5.default.mkdir(import_node_path42.default.join(dir, ".clawd"), { recursive: true });
62696
+ await import_promises5.default.writeFile(import_node_path42.default.join(dir, ".clawd", "base-image.txt"), `${baseImage}
62260
62697
  `);
62261
- await import_promises5.default.writeFile(import_node_path41.default.join(dir, DOCKERFILE_PATH), renderDockerfile(personaId2, baseImage));
62262
- await import_promises5.default.writeFile(import_node_path41.default.join(dir, DOCKERIGNORE_PATH), DOCKERIGNORE_TEMPLATE);
62698
+ await import_promises5.default.writeFile(import_node_path42.default.join(dir, DOCKERFILE_PATH), renderDockerfile(personaId2, baseImage));
62699
+ await import_promises5.default.writeFile(import_node_path42.default.join(dir, DOCKERIGNORE_PATH), DOCKERIGNORE_TEMPLATE);
62263
62700
  }
62264
62701
  var RepoAlreadyExistsError = class extends RepoError {
62265
62702
  constructor(slug) {
@@ -62298,7 +62735,7 @@ async function ensureRepo(exec, api, args) {
62298
62735
  const existing = await repoInfo(exec, dir);
62299
62736
  if (existing) return { created: false, url: existing.url };
62300
62737
  await writeGitignore(dir);
62301
- await import_promises5.default.rm(import_node_path41.default.join(dir, WORKFLOW_PATH), { force: true });
62738
+ await import_promises5.default.rm(import_node_path42.default.join(dir, WORKFLOW_PATH), { force: true });
62302
62739
  let created;
62303
62740
  try {
62304
62741
  created = await createOrgRepo(exec, api, { dir, org, repoName: personaId2, message: "clawd: \u4E0A\u4E91", auth: args.auth });
@@ -62516,9 +62953,9 @@ init_protocol();
62516
62953
 
62517
62954
  // src/deploy/artifact.ts
62518
62955
  var import_node_crypto13 = require("crypto");
62519
- var import_node_fs35 = __toESM(require("fs"), 1);
62520
- var import_node_os12 = __toESM(require("os"), 1);
62521
- var import_node_path42 = __toESM(require("path"), 1);
62956
+ var import_node_fs36 = __toESM(require("fs"), 1);
62957
+ var import_node_os13 = __toESM(require("os"), 1);
62958
+ var import_node_path43 = __toESM(require("path"), 1);
62522
62959
  var import_node_stream3 = require("stream");
62523
62960
  var import_promises6 = require("stream/promises");
62524
62961
  var ARTIFACT_MAX_BYTES = 200 * 1024 * 1024;
@@ -62552,8 +62989,8 @@ function downloadArtifact(exec) {
62552
62989
  if (!res.ok || !res.body) throw new Error(`\u4E0B\u8F7D\u5931\u8D25 HTTP ${res.status}\uFF1A${url}`);
62553
62990
  const declared = Number(res.headers.get("content-length") ?? 0);
62554
62991
  if (declared > ARTIFACT_MAX_BYTES) throw new Error(`\u8D44\u4EA7 ${declared} \u5B57\u8282\uFF0C\u8D85\u8FC7\u4E0A\u9650 ${ARTIFACT_MAX_BYTES}\uFF1A${url}`);
62555
- const dir = await import_node_fs35.default.promises.mkdtemp(import_node_path42.default.join(import_node_os12.default.tmpdir(), "clawd-artifact-"));
62556
- const file = import_node_path42.default.join(dir, "pkg");
62992
+ const dir = await import_node_fs36.default.promises.mkdtemp(import_node_path43.default.join(import_node_os13.default.tmpdir(), "clawd-artifact-"));
62993
+ const file = import_node_path43.default.join(dir, "pkg");
62557
62994
  const hash = (0, import_node_crypto13.createHash)("sha256");
62558
62995
  let size = 0;
62559
62996
  const meter = new import_node_stream3.Transform({
@@ -62565,7 +63002,7 @@ function downloadArtifact(exec) {
62565
63002
  }
62566
63003
  });
62567
63004
  try {
62568
- await (0, import_promises6.pipeline)(import_node_stream3.Readable.fromWeb(res.body), meter, import_node_fs35.default.createWriteStream(file));
63005
+ await (0, import_promises6.pipeline)(import_node_stream3.Readable.fromWeb(res.body), meter, import_node_fs36.default.createWriteStream(file));
62569
63006
  let entries;
62570
63007
  if (listEntries) {
62571
63008
  const r2 = await exec("tar", ["-tzf", file], { timeoutMs: 3e4 });
@@ -62574,7 +63011,7 @@ function downloadArtifact(exec) {
62574
63011
  }
62575
63012
  return { sha256: hash.digest("hex"), size, ...entries ? { entries } : {} };
62576
63013
  } finally {
62577
- await import_node_fs35.default.promises.rm(dir, { recursive: true, force: true });
63014
+ await import_node_fs36.default.promises.rm(dir, { recursive: true, force: true });
62578
63015
  }
62579
63016
  };
62580
63017
  }
@@ -63136,6 +63573,7 @@ function buildDeployHandlers(deps) {
63136
63573
  ...publisherFeishuAuth ? { publisherFeishuAuth } : {},
63137
63574
  targets,
63138
63575
  promotions: file.promotions,
63576
+ ...file.engineChannels ? { engineChannels: file.engineChannels } : {},
63139
63577
  ...repo2 ? { repo: repo2 } : {},
63140
63578
  scans,
63141
63579
  releases: file.releases,
@@ -63257,10 +63695,12 @@ function buildDeployHandlers(deps) {
63257
63695
  const args = parseArgs2(DeploySetEngineAuthArgsSchema, frame, "deploy:setEngineAuth");
63258
63696
  const dir = mustPersona(args.personaId);
63259
63697
  let auth = args.auth;
63698
+ let channelSource = null;
63260
63699
  if (args.channelId) {
63261
63700
  const channel = deps.channelStore?.get(args.channelId);
63262
63701
  if (!channel) throw invalid(`\u672A\u627E\u5230 ID \u4E3A ${args.channelId} \u7684\u8BA2\u9605\u901A\u9053`);
63263
63702
  auth = { baseUrl: channel.baseUrl, apiKey: channel.apiKey };
63703
+ channelSource = { channelId: channel.id, updatedAt: channel.updatedAt };
63264
63704
  }
63265
63705
  let writes;
63266
63706
  if (auth) {
@@ -63276,6 +63716,8 @@ function buildDeployHandlers(deps) {
63276
63716
  writes = [[ENGINE_AUTH_SECRETS.apiKey, apiKey], [ENGINE_AUTH_SECRETS.baseUrl, baseUrl]];
63277
63717
  }
63278
63718
  const { api } = await requireGithub();
63719
+ const before = await readHistory(dir);
63720
+ await writeScanFile(dir, { ...before, engineChannels: { ...before.engineChannels, [args.environment]: null } });
63279
63721
  try {
63280
63722
  if (args.environment === "production") {
63281
63723
  for (const env of [ENGINE_AUTH_SECRETS.baseUrl, ENGINE_AUTH_SECRETS.apiKey]) {
@@ -63286,6 +63728,8 @@ function buildDeployHandlers(deps) {
63286
63728
  await deleteSecret(deps.exec, api, { dir, env: args.environment === "integration" ? "CLAWD_INT_" + ENGINE_AUTH_SECRETS.baseUrl : ENGINE_AUTH_SECRETS.baseUrl, environment: args.environment });
63287
63729
  for (const [env, value] of writes) await setSecret(deps.exec, api, { dir, env: args.environment === "integration" ? "CLAWD_INT_" + env : env, value, environment: args.environment });
63288
63730
  } else for (const env of [ENGINE_AUTH_SECRETS.apiKey, ENGINE_AUTH_SECRETS.baseUrl]) await deleteSecret(deps.exec, api, { dir, env: args.environment === "integration" ? "CLAWD_INT_" + env : env, environment: args.environment });
63731
+ const latest = await readHistory(dir);
63732
+ await writeScanFile(dir, { ...latest, engineChannels: { ...latest.engineChannels, [args.environment]: channelSource } });
63289
63733
  } catch (err) {
63290
63734
  throw toClawdError(err);
63291
63735
  } finally {
@@ -63724,325 +64168,8 @@ function buildDeployHandlers(deps) {
63724
64168
  var import_node_fs37 = __toESM(require("fs"), 1);
63725
64169
  var import_node_os14 = __toESM(require("os"), 1);
63726
64170
  var import_node_path44 = __toESM(require("path"), 1);
63727
-
63728
- // src/tools/subscription-channels-apply.ts
63729
- var import_node_fs36 = __toESM(require("fs"), 1);
63730
- var import_node_os13 = __toESM(require("os"), 1);
63731
- var import_node_path43 = __toESM(require("path"), 1);
63732
-
63733
- // src/tools/codex-config-toml.ts
63734
- function parseKey(src, start) {
63735
- const parts = [];
63736
- let i2 = start;
63737
- for (; ; ) {
63738
- while (src[i2] === " " || src[i2] === " ") i2++;
63739
- let part;
63740
- if (src[i2] === '"') {
63741
- let j2 = i2 + 1;
63742
- while (j2 < src.length && src[j2] !== '"') j2 += src[j2] === "\\" ? 2 : 1;
63743
- if (j2 >= src.length) return null;
63744
- try {
63745
- part = JSON.parse(src.slice(i2, j2 + 1));
63746
- } catch {
63747
- part = src.slice(i2 + 1, j2);
63748
- }
63749
- i2 = j2 + 1;
63750
- } else if (src[i2] === "'") {
63751
- const j2 = src.indexOf("'", i2 + 1);
63752
- if (j2 < 0) return null;
63753
- part = src.slice(i2 + 1, j2);
63754
- i2 = j2 + 1;
63755
- } else {
63756
- const bare = /^[A-Za-z0-9_-]+/.exec(src.slice(i2));
63757
- if (!bare) return null;
63758
- part = bare[0];
63759
- i2 += part.length;
63760
- }
63761
- parts.push(part);
63762
- while (src[i2] === " " || src[i2] === " ") i2++;
63763
- if (src[i2] !== ".") return { parts, end: i2 };
63764
- i2++;
63765
- }
63766
- }
63767
- function tableHeader(line) {
63768
- const open = /^\s*(\[\[?)/.exec(line);
63769
- if (!open) return null;
63770
- const key = parseKey(line, open[0].length);
63771
- if (!key) return null;
63772
- const close = open[1] === "[[" ? "]]" : "]";
63773
- if (!line.startsWith(close, key.end)) return null;
63774
- return /^\s*(?:#.*)?$/.test(line.slice(key.end + close.length)) ? key.parts : null;
63775
- }
63776
- function keyLine(line) {
63777
- const lead = /^\s*/.exec(line)[0].length;
63778
- if (line[lead] === "[" || line[lead] === "#") return null;
63779
- const key = parseKey(line, lead);
63780
- return key && line[key.end] === "=" ? { parts: key.parts, valueStart: key.end + 1 } : null;
63781
- }
63782
- function scanValue(s2, start, st2) {
63783
- let i2 = start;
63784
- while (i2 < s2.length) {
63785
- if (st2.ml) {
63786
- if (st2.ml === '"""' && s2[i2] === "\\") {
63787
- i2 += 2;
63788
- continue;
63789
- }
63790
- if (s2.startsWith(st2.ml, i2)) {
63791
- let j2 = i2 + 3;
63792
- while (j2 < s2.length && j2 < i2 + 5 && s2[j2] === st2.ml[0]) j2++;
63793
- st2.ml = null;
63794
- i2 = j2;
63795
- continue;
63796
- }
63797
- i2++;
63798
- continue;
63799
- }
63800
- const c2 = s2[i2];
63801
- if (c2 === "#") return;
63802
- if (s2.startsWith('"""', i2) || s2.startsWith("'''", i2)) {
63803
- st2.ml = s2.slice(i2, i2 + 3);
63804
- i2 += 3;
63805
- continue;
63806
- }
63807
- if (c2 === '"') {
63808
- i2++;
63809
- while (i2 < s2.length && s2[i2] !== '"') i2 += s2[i2] === "\\" ? 2 : 1;
63810
- i2++;
63811
- continue;
63812
- }
63813
- if (c2 === "'") {
63814
- const j2 = s2.indexOf("'", i2 + 1);
63815
- i2 = j2 < 0 ? s2.length : j2 + 1;
63816
- continue;
63817
- }
63818
- if (c2 === "[" || c2 === "{") st2.depth++;
63819
- else if ((c2 === "]" || c2 === "}") && st2.depth > 0) st2.depth--;
63820
- i2++;
63821
- }
63822
- }
63823
- function scanToml(text) {
63824
- const out = [];
63825
- const st2 = { ml: null, depth: 0 };
63826
- let table = [];
63827
- for (const line of text.split("\n")) {
63828
- if (st2.ml || st2.depth > 0) {
63829
- scanValue(line, 0, st2);
63830
- out.push({ text: line, kind: "continuation", table });
63831
- continue;
63832
- }
63833
- const header = tableHeader(line);
63834
- if (header) {
63835
- table = header;
63836
- out.push({ text: line, kind: "header", table, key: header });
63837
- continue;
63838
- }
63839
- const key = keyLine(line);
63840
- if (key) {
63841
- scanValue(line, key.valueStart, st2);
63842
- out.push({ text: line, kind: "key", table, key: key.parts, value: line.slice(key.valueStart) });
63843
- continue;
63844
- }
63845
- out.push({ text: line, kind: "other", table });
63846
- }
63847
- return out;
63848
- }
63849
- var UNREADABLE = /* @__PURE__ */ Symbol("unreadable TOML value");
63850
- function parseTomlValue(raw) {
63851
- const parsed = parseValueAt(raw, 0);
63852
- if (!parsed) return void 0;
63853
- return /^\s*(?:#[^\n]*)?\s*$/.test(raw.slice(parsed.end)) ? parsed.value : void 0;
63854
- }
63855
- function skipSeparators(s2, start) {
63856
- let i2 = start;
63857
- for (; ; ) {
63858
- while (i2 < s2.length && " \r\n,".includes(s2[i2])) i2++;
63859
- if (s2[i2] !== "#") return i2;
63860
- const newline = s2.indexOf("\n", i2);
63861
- i2 = newline < 0 ? s2.length : newline;
63862
- }
63863
- }
63864
- function parseValueAt(s2, start) {
63865
- let i2 = start;
63866
- while (s2[i2] === " " || s2[i2] === " ") i2++;
63867
- const c2 = s2[i2];
63868
- if (c2 === '"') {
63869
- if (s2.startsWith('"""', i2)) return null;
63870
- let j2 = i2 + 1;
63871
- while (j2 < s2.length && s2[j2] !== '"') j2 += s2[j2] === "\\" ? 2 : 1;
63872
- if (j2 >= s2.length) return null;
63873
- try {
63874
- return { value: JSON.parse(s2.slice(i2, j2 + 1)), end: j2 + 1 };
63875
- } catch {
63876
- return null;
63877
- }
63878
- }
63879
- if (c2 === "'") {
63880
- if (s2.startsWith("'''", i2)) return null;
63881
- const j2 = s2.indexOf("'", i2 + 1);
63882
- return j2 < 0 ? null : { value: s2.slice(i2 + 1, j2), end: j2 + 1 };
63883
- }
63884
- if (c2 === "[") {
63885
- const items = [];
63886
- i2++;
63887
- for (; ; ) {
63888
- i2 = skipSeparators(s2, i2);
63889
- if (s2[i2] === "]") return { value: items, end: i2 + 1 };
63890
- const item = parseValueAt(s2, i2);
63891
- if (!item) return null;
63892
- items.push(item.value);
63893
- i2 = item.end;
63894
- }
63895
- }
63896
- if (c2 === "{") {
63897
- const table = {};
63898
- i2++;
63899
- for (; ; ) {
63900
- i2 = skipSeparators(s2, i2);
63901
- if (s2[i2] === "}") return { value: table, end: i2 + 1 };
63902
- const key = parseKey(s2, i2);
63903
- if (!key || s2[key.end] !== "=") return null;
63904
- const item = parseValueAt(s2, key.end + 1);
63905
- if (!item) return null;
63906
- setPath(table, key.parts, item.value);
63907
- i2 = item.end;
63908
- }
63909
- }
63910
- const bare = /^[^\s,\]}#]+/.exec(s2.slice(i2));
63911
- return bare ? { value: bare[0], end: i2 + bare[0].length } : null;
63912
- }
63913
- function setPath(target, path110, value) {
63914
- let node = target;
63915
- for (const part of path110.slice(0, -1)) {
63916
- const next = node[part];
63917
- if (!next || typeof next !== "object" || Array.isArray(next)) node[part] = {};
63918
- node = node[part];
63919
- }
63920
- const last = path110[path110.length - 1];
63921
- const existing = node[last];
63922
- if (existing && typeof existing === "object" && !Array.isArray(existing) && value && typeof value === "object" && !Array.isArray(value)) {
63923
- Object.assign(existing, value);
63924
- } else node[last] = value;
63925
- }
63926
- function readTomlTable(text, path110) {
63927
- const result = {};
63928
- let found = false;
63929
- const within = (full) => full.length >= path110.length && path110.every((part, i2) => full[i2] === part);
63930
- const lines = scanToml(text);
63931
- for (let index = 0; index < lines.length; index++) {
63932
- const line = lines[index];
63933
- if (line.kind === "header" && within(line.key)) {
63934
- found = true;
63935
- if (line.key.length > path110.length) setPath(result, line.key.slice(path110.length), {});
63936
- continue;
63937
- }
63938
- if (line.kind !== "key") continue;
63939
- const full = [...line.table, ...line.key];
63940
- if (!within(full)) continue;
63941
- let raw = line.value;
63942
- while (lines[index + 1]?.kind === "continuation") raw += `
63943
- ${lines[++index].text}`;
63944
- const parsed = parseTomlValue(raw);
63945
- const value = parsed === void 0 ? UNREADABLE : parsed;
63946
- found = true;
63947
- if (full.length === path110.length) {
63948
- if (value && typeof value === "object" && !Array.isArray(value)) Object.assign(result, value);
63949
- } else setPath(result, full.slice(path110.length), value);
63950
- }
63951
- return found ? result : null;
63952
- }
63953
-
63954
- // src/tools/subscription-channels-apply.ts
63955
- var PROVIDER_ID = "cliproxyapi";
63956
- var isOwnProvider = (path110) => path110[0] === "model_providers" && path110[1] === PROVIDER_ID;
63957
- function stripCodexProvider(text) {
63958
- const out = [];
63959
- let dropping = false;
63960
- let droppingValue = false;
63961
- for (const line of scanToml(text)) {
63962
- if (line.kind === "header") {
63963
- dropping = isOwnProvider(line.key);
63964
- droppingValue = false;
63965
- if (!dropping) out.push(line.text);
63966
- continue;
63967
- }
63968
- if (line.kind === "continuation") {
63969
- if (!dropping && !droppingValue) out.push(line.text);
63970
- continue;
63971
- }
63972
- if (dropping) continue;
63973
- if (line.kind === "key") {
63974
- const full = [...line.table, ...line.key];
63975
- droppingValue = full.length === 1 && full[0] === "model_provider" || isOwnProvider(full);
63976
- if (!droppingValue) out.push(line.text);
63977
- continue;
63978
- }
63979
- out.push(line.text);
63980
- }
63981
- return out.join("\n").trim();
63982
- }
63983
- function writeFileAtomic(file, data) {
63984
- const target = import_node_fs36.default.existsSync(file) && import_node_fs36.default.lstatSync(file).isSymbolicLink() ? import_node_fs36.default.realpathSync(file) : file;
63985
- const tmp = `${target}.tmp.${process.pid}.${Date.now()}`;
63986
- import_node_fs36.default.writeFileSync(tmp, data, { mode: 384 });
63987
- import_node_fs36.default.renameSync(tmp, target);
63988
- }
63989
- function snapshotFile(file) {
63990
- const original = import_node_fs36.default.existsSync(file) ? import_node_fs36.default.readFileSync(file) : null;
63991
- return () => {
63992
- const current = import_node_fs36.default.existsSync(file) ? import_node_fs36.default.readFileSync(file) : null;
63993
- if (original === null) {
63994
- if (current !== null) import_node_fs36.default.rmSync(file, { force: true });
63995
- return;
63996
- }
63997
- if (current !== null && current.equals(original)) return;
63998
- writeFileAtomic(file, original);
63999
- };
64000
- }
64001
- var resolveCodexHome2 = (codexHome) => codexHome || process.env.CODEX_HOME || import_node_path43.default.join(import_node_os13.default.homedir(), ".codex");
64002
- var resolvePiAgentDir = (agentDir) => agentDir || process.env.PI_CODING_AGENT_DIR || import_node_path43.default.join(import_node_os13.default.homedir(), ".pi", "agent");
64003
- var PI_SUBSCRIPTION_FILE = "cliproxyapi.json";
64004
- function applyCodexSubscriptionChannel(opts) {
64005
- const codexHome = resolveCodexHome2(opts.codexHome);
64006
- import_node_fs36.default.mkdirSync(codexHome, { recursive: true });
64007
- const configFile = import_node_path43.default.join(codexHome, "config.toml");
64008
- const original = import_node_fs36.default.existsSync(configFile) ? import_node_fs36.default.readFileSync(configFile, "utf8") : "";
64009
- const rest = stripCodexProvider(original);
64010
- let content;
64011
- if (opts.channel) {
64012
- const ch = opts.channel;
64013
- content = [
64014
- `model_provider = "${PROVIDER_ID}"`,
64015
- ...rest ? ["", rest] : [],
64016
- "",
64017
- `[model_providers.${PROVIDER_ID}]`,
64018
- `name = "${PROVIDER_ID}"`,
64019
- `base_url = ${JSON.stringify(ch.baseUrl)}`,
64020
- 'wire_api = "responses"',
64021
- `auth = { command = "echo", args = [${JSON.stringify(ch.apiKey)}] }`,
64022
- ""
64023
- ].join("\n");
64024
- } else {
64025
- content = [
64026
- 'model_provider = "openai"',
64027
- ...rest ? ["", rest] : [],
64028
- ""
64029
- ].join("\n");
64030
- }
64031
- writeFileAtomic(configFile, content);
64032
- }
64033
- function applyPiSubscriptionChannel(opts) {
64034
- const agentDir = resolvePiAgentDir(opts.agentDir);
64035
- if (!import_node_fs36.default.existsSync(agentDir)) return false;
64036
- const configFile = import_node_path43.default.join(agentDir, PI_SUBSCRIPTION_FILE);
64037
- if (opts.channel) {
64038
- const data = { baseUrl: opts.channel.baseUrl, apiKey: opts.channel.apiKey };
64039
- writeFileAtomic(configFile, JSON.stringify(data, null, 2) + "\n");
64040
- return true;
64041
- }
64042
- return false;
64043
- }
64044
-
64045
- // src/tools/subscription-channels-store.ts
64171
+ init_subscription_channels_apply();
64172
+ init_codex_config_toml();
64046
64173
  var CHANNELS_FILE_NAME = "subscription-channels.json";
64047
64174
  function providerKey(provider, codexHome) {
64048
64175
  if ([provider.env_key, provider.experimental_bearer_token, provider.auth].includes(UNREADABLE)) return null;
@@ -64227,6 +64354,9 @@ var SubscriptionChannelStore = class {
64227
64354
  }
64228
64355
  };
64229
64356
 
64357
+ // src/index.ts
64358
+ init_subscription_channels_apply();
64359
+
64230
64360
  // src/deploy/local-probe.ts
64231
64361
  function pickVersion(s2) {
64232
64362
  return /(\d+)\.(\d+)(?:\.(\d+))?/.exec(s2)?.[0];
@@ -65698,7 +65828,8 @@ function buildPersonaDispatchHandlers(deps) {
65698
65828
  await deps.getCapabilities(args.tool);
65699
65829
  }
65700
65830
  if (args.model !== void 0) {
65701
- const allowed = effectiveTool === "claude" ? CLAUDE_MODEL_IDS : ((await deps.getCapabilities?.(effectiveTool))?.models ?? []).map((m3) => m3.id).filter((id) => id !== "");
65831
+ const caps = await deps.getCapabilities?.(effectiveTool);
65832
+ const allowed = caps ? caps.models.map((m3) => m3.id).filter((id) => id !== "") : effectiveTool === "claude" ? CLAUDE_MODEL_IDS : [];
65702
65833
  if (!allowed.includes(args.model)) {
65703
65834
  throw new ClawdError(
65704
65835
  ERROR_CODES.INVALID_PARAM,
@@ -66918,16 +67049,22 @@ var PiAdapter = class {
66918
67049
  probeCache = null;
66919
67050
  // 进程级 memo,**回落结果同样缓存**(pi 没装时别每次开弹窗都 spawn 一次必然失败的子进程;同 codex)
66920
67051
  capsPromise;
67052
+ capsRevision = 0;
66921
67053
  windows = /* @__PURE__ */ new Map();
66922
67054
  async probe() {
66923
67055
  if (this.probeCache) return this.probeCache;
66924
67056
  this.probeCache = this.opts.probeOverride ? await this.opts.probeOverride() : await probePi();
66925
67057
  return this.probeCache;
66926
67058
  }
67059
+ invalidateCapabilities() {
67060
+ this.capsRevision++;
67061
+ this.capsPromise = void 0;
67062
+ }
66927
67063
  async capabilities(opts) {
66928
67064
  if (opts?.refresh) {
67065
+ const revision = this.capsRevision;
66929
67066
  const fresh = await this.loadCapabilities({ strict: true, refresh: true });
66930
- this.capsPromise = Promise.resolve(fresh);
67067
+ if (revision === this.capsRevision) this.capsPromise = Promise.resolve(fresh);
66931
67068
  return fresh;
66932
67069
  }
66933
67070
  if (!this.capsPromise) this.capsPromise = this.loadCapabilities({ strict: false, refresh: false });
@@ -73528,6 +73665,8 @@ function buildEngineHandlers(deps, overrides = {}) {
73528
73665
  // src/handlers/channels.ts
73529
73666
  var import_node_fs66 = __toESM(require("fs"), 1);
73530
73667
  var import_node_path75 = __toESM(require("path"), 1);
73668
+ init_subscription_channels_apply();
73669
+ init_codex_provider_models();
73531
73670
  function buildChannelsHandlers(deps) {
73532
73671
  let queue = Promise.resolve();
73533
73672
  const serialized = (fn) => (frame, context) => {
@@ -73540,6 +73679,12 @@ function buildChannelsHandlers(deps) {
73540
73679
  async function transact(mutate) {
73541
73680
  const codexHome = resolveCodexHome2(deps.codexHome);
73542
73681
  const agentDir = resolvePiAgentDir(deps.agentDir);
73682
+ const claudeDir = resolveClaudeConfigDir(deps.claudeConfigDir);
73683
+ let restoreClaude;
73684
+ let restoreClaudeBackup;
73685
+ const invalidateModels = () => {
73686
+ for (const tool of ["codex", "claude", "pi"]) deps.manager.invalidateCapabilities(tool);
73687
+ };
73543
73688
  const restoreStore = deps.store.snapshot();
73544
73689
  const restoreCodex = snapshotFile(import_node_path75.default.join(codexHome, "config.toml"));
73545
73690
  const restorePi = import_node_fs66.default.existsSync(agentDir) ? snapshotFile(import_node_path75.default.join(agentDir, PI_SUBSCRIPTION_FILE)) : null;
@@ -73548,6 +73693,8 @@ function buildChannelsHandlers(deps) {
73548
73693
  next = mutate();
73549
73694
  if (next === void 0) return;
73550
73695
  if (next) {
73696
+ const commitStore = deps.store.snapshot();
73697
+ restoreStore();
73551
73698
  try {
73552
73699
  await fetchProviderModels({ baseUrl: next.baseUrl, headers: {
73553
73700
  Accept: "application/json",
@@ -73558,14 +73705,21 @@ function buildChannelsHandlers(deps) {
73558
73705
  const authFailed = /HTTP (401|403)\b/.test(message);
73559
73706
  throw new Error(`${authFailed ? "\u8BA2\u9605 API \u9274\u6743\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 API Key" : "\u8BA2\u9605 API \u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5730\u5740\u4E0E\u7F51\u7EDC"}\uFF1A${message}`);
73560
73707
  }
73708
+ commitStore();
73561
73709
  }
73710
+ restoreClaude = snapshotFile(import_node_path75.default.join(claudeDir, "settings.json"));
73711
+ restoreClaudeBackup = snapshotFile(import_node_path75.default.join(claudeDir, CLAUDE_SUBSCRIPTION_BACKUP));
73562
73712
  applyCodexSubscriptionChannel({ codexHome, channel: next });
73563
73713
  applyPiSubscriptionChannel({ agentDir, channel: next });
73564
- deps.manager.invalidateCapabilities("codex");
73714
+ applyClaudeSubscriptionChannel({ configDir: claudeDir, channel: next });
73715
+ invalidateModels();
73565
73716
  } catch (err) {
73566
73717
  restoreStore();
73567
73718
  restoreCodex();
73568
73719
  restorePi?.();
73720
+ restoreClaude?.();
73721
+ restoreClaudeBackup?.();
73722
+ invalidateModels();
73569
73723
  if (next?.id === "default-pool" && err instanceof Error && /HTTP 401/.test(err.message)) {
73570
73724
  throw new Error("\u9ED8\u8BA4\u53F7\u6C60\u8BA4\u8BC1\u5931\u8D25\uFF08HTTP 401\uFF09\uFF1A\u8BF7\u7F16\u8F91\u300C\u9ED8\u8BA4\u56E2\u961F\u53F7\u6C60\u300D\u5E76\u91CD\u65B0\u586B\u5199\u53F7\u6C60 API Key\uFF0C\u518D\u8BBE\u4E3A\u5F53\u524D\u3002");
73571
73725
  }
@@ -73598,8 +73752,10 @@ function buildChannelsHandlers(deps) {
73598
73752
  return { response: { ok: true } };
73599
73753
  });
73600
73754
  const models = async (frame) => {
73601
- parseArgs2(SubscriptionChannelModelsArgsSchema, frame, "subscriptionChannel:models");
73602
- const active = deps.store.getActive();
73755
+ const args = parseArgs2(SubscriptionChannelModelsArgsSchema, frame, "subscriptionChannel:models");
73756
+ const active = args.channelId ? deps.store.get(args.channelId) : deps.store.getActive();
73757
+ if (args.channelId && !active) throw new Error("\u672A\u627E\u5230\u4E91\u7AEF\u9009\u7528\u7684\u8BA2\u9605\u901A\u9053\uFF0C\u8BF7\u5728\u53D1\u5E03\u9875\u91CD\u65B0\u9009\u62E9");
73758
+ if (active && args.updatedAt !== void 0 && args.updatedAt !== active.updatedAt) throw new Error("\u8BA2\u9605\u901A\u9053\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u5728\u53D1\u5E03\u9875\u91CD\u65B0\u4FDD\u5B58\u4E91\u7AEF\u8BA2\u9605");
73603
73759
  if (!active) return { response: { channelId: null, models: [] } };
73604
73760
  const list = await fetchProviderModels(
73605
73761
  { baseUrl: active.baseUrl, headers: { Accept: "application/json", Authorization: `Bearer ${active.apiKey}` } },
@@ -74529,7 +74685,7 @@ function computeMethodAccess(args) {
74529
74685
  }
74530
74686
 
74531
74687
  // src/version.ts
74532
- var version = "0.2.656".length > 0 ? "0.2.656" : "dev";
74688
+ var version = "0.2.658".length > 0 ? "0.2.658" : "dev";
74533
74689
 
74534
74690
  // src/cli-probe/probe.ts
74535
74691
  var fs85 = __toESM(require("fs"), 1);
@@ -77142,7 +77298,10 @@ async function startDaemon(config) {
77142
77298
  const personaStore = new PersonaStore(import_node_path88.default.join(config.dataDir, "personas"));
77143
77299
  const subscriptionChannelStore = new SubscriptionChannelStore({ dataDir: config.dataDir });
77144
77300
  const activeSubscriptionChannel = subscriptionChannelStore.getActive();
77145
- if (activeSubscriptionChannel) applyPiSubscriptionChannel({ channel: activeSubscriptionChannel });
77301
+ if (activeSubscriptionChannel) {
77302
+ applyPiSubscriptionChannel({ channel: activeSubscriptionChannel });
77303
+ applyClaudeSubscriptionChannel({ channel: activeSubscriptionChannel });
77304
+ }
77146
77305
  const usersRoot = import_node_path88.default.join(config.dataDir, "users");
77147
77306
  const defaultsRoot = findDefaultsRoot(logger);
77148
77307
  if (defaultsRoot) {
@@ -77551,6 +77710,7 @@ async function startDaemon(config) {
77551
77710
  manager.attachObserver(observer);
77552
77711
  deliverPendingRef = (sid) => manager.deliverPending(sid);
77553
77712
  const claudeAdapter = config.mode === "tui" ? new ClaudeTuiAdapter({
77713
+ getSubscriptionChannel: () => subscriptionChannelStore.getActive(),
77554
77714
  logger,
77555
77715
  historyReader: new ClaudeHistoryReader(),
77556
77716
  onPtyRegister: (tsid, pty) => manager.registerPty(tsid, pty),
@@ -77563,7 +77723,7 @@ async function startDaemon(config) {
77563
77723
  onReady: (tsid) => manager.dispatchReadyDetected(tsid),
77564
77724
  onScreenIdle: (tsid) => manager.notifyScreenIdle(tsid),
77565
77725
  screenIdleProbeLogger
77566
- }) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
77726
+ }) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader(), getSubscriptionChannel: () => subscriptionChannelStore.getActive() });
77567
77727
  const cloudGateway = new CloudGatewayClient({
77568
77728
  getLoginPass: () => ownerIdentityStore.read()?.loginPass ?? null,
77569
77729
  centralApi: config.clawosApi ?? DEFAULT_CLAWOS_API,