@clawos-dev/clawd 0.2.657 → 0.2.659
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/app-builder-plugin/mcp-server.cjs +15 -3
- package/dist/cli.cjs +738 -613
- package/dist/cloud-persona-conversations.html +72 -72
- package/dist/dispatch/mcp-server.cjs +54 -29
- package/dist/persona-defaults/persona-app-builder/mcp/clawd-app-builder/mcp-server.cjs +15 -3
- package/dist/persona-defaults/persona-dataclaw-builder/mcp/clawd-app-builder/mcp-server.cjs +15 -3
- package/dist/share-ui/assets/{guest-B_B67yze.js → guest-CeIO68-h.js} +136 -136
- package/dist/share-ui/guest.html +1 -1
- package/package.json +1 -1
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({
|
|
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\
|
|
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,
|
|
15883
|
-
if (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 &&
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
17024
|
+
const child = (0, import_node_child_process3.spawn)(cmd, args, {
|
|
16490
17025
|
cwd: ctx.cwd,
|
|
16491
|
-
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
|
|
49142
|
-
|
|
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
|
|
53277
|
-
var
|
|
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
|
|
53901
|
-
var
|
|
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,
|
|
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(
|
|
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
|
|
53975
|
-
var
|
|
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 =
|
|
54516
|
+
const file = import_node_path24.default.join(args.cwd, ".codex", "config.toml");
|
|
53983
54517
|
let text;
|
|
53984
54518
|
try {
|
|
53985
|
-
text =
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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 =
|
|
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,
|
|
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: [
|
|
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
|
|
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,
|
|
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
|
|
54624
|
-
var
|
|
54625
|
-
var
|
|
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:
|
|
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 =
|
|
55834
|
-
const file =
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
56309
|
-
var
|
|
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
|
|
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
|
-
|
|
56331
|
-
|
|
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
|
|
56337
|
-
var
|
|
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
|
|
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
|
-
|
|
56362
|
-
|
|
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
|
|
56368
|
-
var
|
|
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
|
|
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
|
|
56390
|
-
await
|
|
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
|
|
56396
|
-
var
|
|
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
|
|
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
|
|
56418
|
-
await
|
|
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
|
|
56424
|
-
var
|
|
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
|
|
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
|
-
|
|
56444
|
-
|
|
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
|
|
56450
|
-
var
|
|
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
|
|
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
|
-
|
|
56472
|
-
|
|
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
|
|
56478
|
-
var
|
|
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 =
|
|
56486
|
-
candidates.push(
|
|
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 (
|
|
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 =
|
|
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(
|
|
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:
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
57007
|
+
import_node_fs33.default.rmSync(file, { force: true });
|
|
56571
57008
|
return;
|
|
56572
57009
|
}
|
|
56573
|
-
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
57100
|
-
var
|
|
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 =
|
|
57107
|
-
if (
|
|
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 (!
|
|
57110
|
-
const resolved =
|
|
57111
|
-
if (!resolved.startsWith(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 =
|
|
57553
|
+
const root = import_node_fs34.default.realpathSync(dir);
|
|
57117
57554
|
try {
|
|
57118
|
-
|
|
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 (
|
|
57560
|
+
if (import_node_fs34.default.lstatSync(import_node_path39.default.join(root, ".clawd")).isSymbolicLink()) throw new Error("symlink");
|
|
57124
57561
|
try {
|
|
57125
|
-
|
|
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 (
|
|
57132
|
-
const test = PublisherTestSchema.parse(JSON.parse(
|
|
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
|
|
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
|
|
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
|
|
57545
|
-
var
|
|
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 =
|
|
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(
|
|
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 =
|
|
57734
|
-
var SCAN_FILE =
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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);
|
|
@@ -61614,7 +62051,6 @@ async function storeGithubAuth(args) {
|
|
|
61614
62051
|
init_zod();
|
|
61615
62052
|
var SLUG = "ottin4ttc/clawos";
|
|
61616
62053
|
var WORKFLOW = ".github/workflows/base-image-acr.yml";
|
|
61617
|
-
var DOCKERFILE = "cloud-host/Dockerfile.base";
|
|
61618
62054
|
var SHA = external_exports.string().regex(/^[a-f0-9]{40}$/);
|
|
61619
62055
|
var SourceSchema = external_exports.object({ cloudHost: SHA, workflow: SHA });
|
|
61620
62056
|
var BaseSchema = external_exports.object({
|
|
@@ -61627,10 +62063,10 @@ var BaseSchema = external_exports.object({
|
|
|
61627
62063
|
workflowCommit: SHA,
|
|
61628
62064
|
buildId: external_exports.string().min(1)
|
|
61629
62065
|
});
|
|
61630
|
-
async function
|
|
61631
|
-
const head = await api.getJsonStrict(`/repos/${SLUG}/commits
|
|
61632
|
-
if (
|
|
61633
|
-
const
|
|
62066
|
+
async function buildSource(api, commit) {
|
|
62067
|
+
const head = await api.getJsonStrict(`/repos/${SLUG}/commits/${commit}`);
|
|
62068
|
+
if (head?.sha !== commit || !SHA.safeParse(head?.commit?.tree?.sha).success) throw new Error("\u8BFB\u4E0D\u5230\u53EF\u4FE1\u7684\u5E95\u5EA7\u6784\u5EFA\u6E90\u7801\u7248\u672C");
|
|
62069
|
+
const tree = SHA.parse(head?.commit?.tree?.sha);
|
|
61634
62070
|
const [root, workflow] = await Promise.all([
|
|
61635
62071
|
api.getJsonStrict(`/repos/${SLUG}/git/trees/${tree}`),
|
|
61636
62072
|
api.getJsonStrict(`/repos/${SLUG}/contents/${WORKFLOW}?ref=${commit}`)
|
|
@@ -61638,33 +62074,13 @@ async function currentSource(api) {
|
|
|
61638
62074
|
if (root?.truncated || workflow?.type !== "file") throw new Error("\u8BFB\u4E0D\u5230\u5B8C\u6574\u5E95\u5EA7\u6E90\u7801\u7248\u672C");
|
|
61639
62075
|
const source = SourceSchema.safeParse({ cloudHost: root?.tree?.find((e) => e.path === "cloud-host" && e.type === "tree")?.sha, workflow: workflow.sha });
|
|
61640
62076
|
if (!source.success) throw new Error("\u5E95\u5EA7\u6E90\u7801\u7248\u672C\u8BB0\u5F55\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u5237\u65B0\u540E\u518D\u53D1\u5E03");
|
|
61641
|
-
return
|
|
61642
|
-
}
|
|
61643
|
-
function dockerfileInputs(text) {
|
|
61644
|
-
if (!/^\s*FROM\s+/im.test(text)) throw new Error("\u8BFB\u4E0D\u5230\u53EF\u4FE1\u7684\u5E95\u5EA7\u6784\u5EFA\u914D\u65B9");
|
|
61645
|
-
const logical = text.replace(/\\\r?\n/g, " ");
|
|
61646
|
-
if (/^\s*RUN\b.*--mount=/im.test(logical)) throw new Error("\u5E95\u5EA7\u6302\u8F7D\u8F93\u5165\u65E0\u6CD5\u5B8C\u6574\u6BD4\u8F83\uFF0C\u8BF7\u91CD\u65B0\u6784\u5EFA");
|
|
61647
|
-
const inputs = /* @__PURE__ */ new Set([DOCKERFILE, "cloud-host/.dockerignore", "cloud-host/Dockerfile.base.dockerignore"]);
|
|
61648
|
-
for (const line of logical.split("\n")) {
|
|
61649
|
-
const instruction = /^\s*(?:COPY|ADD)\s+(.+)$/i.exec(line)?.[1];
|
|
61650
|
-
if (!instruction || /^--from=\S+\s/.test(instruction)) continue;
|
|
61651
|
-
const tokens = instruction.startsWith("[") ? JSON.parse(instruction) : instruction.trim().split(/\s+/);
|
|
61652
|
-
if (!Array.isArray(tokens) || tokens.length < 2) throw new Error("\u5E95\u5EA7 COPY \u8F93\u5165\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u91CD\u65B0\u6784\u5EFA");
|
|
61653
|
-
for (const source of tokens.slice(0, -1)) {
|
|
61654
|
-
if (typeof source !== "string" || !/^[A-Za-z0-9_-][A-Za-z0-9_./-]*$/.test(source) || source.split("/").some((segment) => !segment || segment === "." || segment === "..")) {
|
|
61655
|
-
throw new Error("\u5E95\u5EA7 COPY \u8F93\u5165\u65E0\u6CD5\u5B8C\u6574\u6BD4\u8F83\uFF0C\u8BF7\u91CD\u65B0\u6784\u5EFA");
|
|
61656
|
-
}
|
|
61657
|
-
inputs.add("cloud-host/" + source.replace(/\/$/, ""));
|
|
61658
|
-
}
|
|
61659
|
-
}
|
|
61660
|
-
return inputs;
|
|
62077
|
+
return source.data;
|
|
61661
62078
|
}
|
|
61662
62079
|
async function readCurrentBase(api) {
|
|
61663
|
-
const
|
|
61664
|
-
const listed = await api.getJsonStrict(`/repos/${SLUG}/actions/workflows/base-image-acr.yml/runs?branch=release&per_page=1`);
|
|
62080
|
+
const listed = await api.getJsonStrict(`/repos/${SLUG}/actions/workflows/base-image-acr.yml/runs?branch=release&status=success&per_page=1`);
|
|
61665
62081
|
const run = listed?.workflow_runs?.[0];
|
|
61666
|
-
if (!run || !Number.isSafeInteger(run.id) || run.id <= 0 || !Number.isSafeInteger(run.run_attempt) || run.run_attempt <= 0 || run.head_branch !== "release" || run.path !== WORKFLOW || run.head_repository?.full_name !== SLUG || !["push", "workflow_dispatch"].includes(run.event)) throw new Error("\u6CA1\u6709\u53EF\u4FE1\u7684
|
|
61667
|
-
if (run.status !== "completed" || run.conclusion !== "success") throw new Error("\
|
|
62082
|
+
if (!run || !Number.isSafeInteger(run.id) || run.id <= 0 || !Number.isSafeInteger(run.run_attempt) || run.run_attempt <= 0 || run.head_branch !== "release" || run.path !== WORKFLOW || run.head_repository?.full_name !== SLUG || !["push", "workflow_dispatch"].includes(run.event)) throw new Error("\u6CA1\u6709\u53EF\u4FE1\u7684\u6210\u529F\u5E95\u5EA7\u6784\u5EFA\uFF0C\u8BF7\u8FD0\u884C\u5E95\u5EA7\u6D41\u6C34\u7EBF\u540E\u518D\u53D1\u5E03");
|
|
62083
|
+
if (run.status !== "completed" || run.conclusion !== "success") throw new Error("\u5E95\u5EA7\u6784\u5EFA\u5C1A\u672A\u6210\u529F\uFF0C\u8BF7\u67E5\u770B clawos \u5E95\u5EA7 Actions \u540E\u518D\u53D1\u5E03");
|
|
61668
62084
|
SHA.parse(run.head_sha);
|
|
61669
62085
|
let artifact;
|
|
61670
62086
|
for (let page = 1; page <= 30; page++) {
|
|
@@ -61680,23 +62096,9 @@ async function readCurrentBase(api) {
|
|
|
61680
62096
|
const parsed = BaseSchema.safeParse(await readReleaseArchive(await api.downloadArtifact(SLUG, artifact.id)));
|
|
61681
62097
|
if (!parsed.success) throw new Error("\u5E95\u5EA7\u5236\u54C1\u7248\u672C\u8BB0\u5F55\u65E0\u6548\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u5E95\u5EA7\u6784\u5EFA");
|
|
61682
62098
|
const release2 = parsed.data;
|
|
61683
|
-
|
|
61684
|
-
|
|
61685
|
-
|
|
61686
|
-
if (release2.commit === candidate.commit) return false;
|
|
61687
|
-
const comparison = await api.getJsonStrict(`/repos/${SLUG}/compare/${release2.commit}...${candidate.commit}`);
|
|
61688
|
-
if (comparison.status !== "ahead" || !Array.isArray(comparison.files) || comparison.files.length >= 300 || comparison.files.some((file) => typeof file.filename !== "string" || !file.filename)) {
|
|
61689
|
-
throw new Error("\u65E0\u6CD5\u5B8C\u6574\u6BD4\u8F83\u5E95\u5EA7\u8F93\u5165\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u5E95\u5EA7\u6D41\u6C34\u7EBF");
|
|
61690
|
-
}
|
|
61691
|
-
if (comparison.files.some((file) => file.filename === DOCKERFILE || file.previous_filename === DOCKERFILE)) return false;
|
|
61692
|
-
const recipe = await api.getJsonStrict(`/repos/${SLUG}/contents/${DOCKERFILE}?ref=${candidate.commit}`);
|
|
61693
|
-
if (recipe.type !== "file" || recipe.encoding !== "base64" || typeof recipe.content !== "string") throw new Error("\u8BFB\u4E0D\u5230\u5E95\u5EA7\u6784\u5EFA\u914D\u65B9");
|
|
61694
|
-
const inputs = dockerfileInputs(Buffer.from(recipe.content, "base64").toString("utf8"));
|
|
61695
|
-
return comparison.files.every((file) => ![file.filename, file.previous_filename].some((filename) => filename && [...inputs].some((input) => filename === input || filename.startsWith(input + "/"))));
|
|
61696
|
-
};
|
|
61697
|
-
if (release2.commit !== run.head_sha || release2.workflowCommit !== run.head_sha || !await matches(current)) throw new Error("\u5E95\u5EA7\u5C1A\u672A\u6784\u5EFA\u5F53\u524D release \u6E90\u7801\uFF0C\u8BF7\u7B49\u5F85\u6216\u91CD\u65B0\u8FD0\u884C\u5E95\u5EA7\u6D41\u6C34\u7EBF");
|
|
61698
|
-
const after = await currentSource(api);
|
|
61699
|
-
if ((after.source.cloudHost !== current.source.cloudHost || after.source.workflow !== current.source.workflow) && !await matches(after)) throw new Error("\u5E95\u5EA7\u6E90\u7801\u5728\u53D1\u5E03\u51C6\u5907\u671F\u95F4\u53D8\u5316\uFF0C\u8BF7\u7B49\u65B0\u6784\u5EFA\u6210\u529F\u540E\u518D\u53D1\u5E03");
|
|
62099
|
+
if (release2.commit !== run.head_sha || release2.workflowCommit !== run.head_sha) throw new Error("\u5E95\u5EA7\u5236\u54C1\u4E0E\u6784\u5EFA\u63D0\u4EA4\u4E0D\u5339\u914D\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u5E95\u5EA7\u6D41\u6C34\u7EBF");
|
|
62100
|
+
const source = await buildSource(api, run.head_sha);
|
|
62101
|
+
if (release2.source.cloudHost !== source.cloudHost || release2.source.workflow !== source.workflow) throw new Error("\u5E95\u5EA7\u5236\u54C1\u6E90\u7801\u7248\u672C\u4E0E\u6784\u5EFA\u63D0\u4EA4\u4E0D\u5339\u914D\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u5E95\u5EA7\u6D41\u6C34\u7EBF");
|
|
61700
62102
|
return release2;
|
|
61701
62103
|
}
|
|
61702
62104
|
|
|
@@ -62117,7 +62519,7 @@ var runCommand = (cmd, args, opts = {}) => new Promise((resolve9) => {
|
|
|
62117
62519
|
});
|
|
62118
62520
|
|
|
62119
62521
|
// src/deploy/repo.ts
|
|
62120
|
-
var DEPLOY_FILE_REL = DEPLOY_FILE.split(
|
|
62522
|
+
var DEPLOY_FILE_REL = DEPLOY_FILE.split(import_node_path42.default.sep).join("/");
|
|
62121
62523
|
var PERSONA_FILE_REL = ".clawd/persona.json";
|
|
62122
62524
|
var DIRTY_IGNORED = [DEPLOY_FILE_REL, PERSONA_FILE_REL];
|
|
62123
62525
|
var RepoError = class extends Error {
|
|
@@ -62150,7 +62552,7 @@ async function prepareIntegration(exec, dir, auth) {
|
|
|
62150
62552
|
for (const name of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"]) {
|
|
62151
62553
|
const rel = await mustGit(exec, dir, ["rev-parse", "--git-path", name], "\u68C0\u67E5 Git \u64CD\u4F5C");
|
|
62152
62554
|
try {
|
|
62153
|
-
await import_promises5.default.stat(
|
|
62555
|
+
await import_promises5.default.stat(import_node_path42.default.resolve(dir, rel));
|
|
62154
62556
|
throw new RepoError("Git \u5408\u5E76\u6216\u53D8\u57FA\u8FD8\u672A\u5B8C\u6210\uFF0C\u5148\u5904\u7406\u518D\u53D1\u5E03");
|
|
62155
62557
|
} catch (err) {
|
|
62156
62558
|
if (err.code !== "ENOENT") throw err;
|
|
@@ -62211,7 +62613,7 @@ async function samePath(a2, b3) {
|
|
|
62211
62613
|
try {
|
|
62212
62614
|
return await import_promises5.default.realpath(x2);
|
|
62213
62615
|
} catch {
|
|
62214
|
-
return
|
|
62616
|
+
return import_node_path42.default.resolve(x2);
|
|
62215
62617
|
}
|
|
62216
62618
|
};
|
|
62217
62619
|
return await real(a2) === await real(b3);
|
|
@@ -62237,7 +62639,7 @@ async function identityArgs(exec, dir) {
|
|
|
62237
62639
|
return ["-c", "user.name=clawd", "-c", "user.email=clawd@clawos.local"];
|
|
62238
62640
|
}
|
|
62239
62641
|
async function writeGitignore(dir) {
|
|
62240
|
-
const gi =
|
|
62642
|
+
const gi = import_node_path42.default.join(dir, ".gitignore");
|
|
62241
62643
|
let existing;
|
|
62242
62644
|
try {
|
|
62243
62645
|
existing = await import_promises5.default.readFile(gi, "utf8");
|
|
@@ -62248,18 +62650,18 @@ async function writeGitignore(dir) {
|
|
|
62248
62650
|
}
|
|
62249
62651
|
async function writeWorkflow(dir) {
|
|
62250
62652
|
for (const [rel, body] of [[WORKFLOW_PATH, WORKFLOW_TEMPLATE], [UNPUBLISH_WORKFLOW_PATH, UNPUBLISH_WORKFLOW_TEMPLATE]]) {
|
|
62251
|
-
const wf =
|
|
62252
|
-
await import_promises5.default.mkdir(
|
|
62653
|
+
const wf = import_node_path42.default.join(dir, rel);
|
|
62654
|
+
await import_promises5.default.mkdir(import_node_path42.default.dirname(wf), { recursive: true });
|
|
62253
62655
|
await import_promises5.default.writeFile(wf, body);
|
|
62254
62656
|
}
|
|
62255
62657
|
}
|
|
62256
62658
|
async function writeDockerfile(dir, personaId2, image) {
|
|
62257
62659
|
const baseImage = image.replace("registry-vpc.cn-hangzhou.aliyuncs.com/", "registry.cn-hangzhou.aliyuncs.com/");
|
|
62258
|
-
await import_promises5.default.mkdir(
|
|
62259
|
-
await import_promises5.default.writeFile(
|
|
62660
|
+
await import_promises5.default.mkdir(import_node_path42.default.join(dir, ".clawd"), { recursive: true });
|
|
62661
|
+
await import_promises5.default.writeFile(import_node_path42.default.join(dir, ".clawd", "base-image.txt"), `${baseImage}
|
|
62260
62662
|
`);
|
|
62261
|
-
await import_promises5.default.writeFile(
|
|
62262
|
-
await import_promises5.default.writeFile(
|
|
62663
|
+
await import_promises5.default.writeFile(import_node_path42.default.join(dir, DOCKERFILE_PATH), renderDockerfile(personaId2, baseImage));
|
|
62664
|
+
await import_promises5.default.writeFile(import_node_path42.default.join(dir, DOCKERIGNORE_PATH), DOCKERIGNORE_TEMPLATE);
|
|
62263
62665
|
}
|
|
62264
62666
|
var RepoAlreadyExistsError = class extends RepoError {
|
|
62265
62667
|
constructor(slug) {
|
|
@@ -62298,7 +62700,7 @@ async function ensureRepo(exec, api, args) {
|
|
|
62298
62700
|
const existing = await repoInfo(exec, dir);
|
|
62299
62701
|
if (existing) return { created: false, url: existing.url };
|
|
62300
62702
|
await writeGitignore(dir);
|
|
62301
|
-
await import_promises5.default.rm(
|
|
62703
|
+
await import_promises5.default.rm(import_node_path42.default.join(dir, WORKFLOW_PATH), { force: true });
|
|
62302
62704
|
let created;
|
|
62303
62705
|
try {
|
|
62304
62706
|
created = await createOrgRepo(exec, api, { dir, org, repoName: personaId2, message: "clawd: \u4E0A\u4E91", auth: args.auth });
|
|
@@ -62516,9 +62918,9 @@ init_protocol();
|
|
|
62516
62918
|
|
|
62517
62919
|
// src/deploy/artifact.ts
|
|
62518
62920
|
var import_node_crypto13 = require("crypto");
|
|
62519
|
-
var
|
|
62520
|
-
var
|
|
62521
|
-
var
|
|
62921
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
62922
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
62923
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
62522
62924
|
var import_node_stream3 = require("stream");
|
|
62523
62925
|
var import_promises6 = require("stream/promises");
|
|
62524
62926
|
var ARTIFACT_MAX_BYTES = 200 * 1024 * 1024;
|
|
@@ -62552,8 +62954,8 @@ function downloadArtifact(exec) {
|
|
|
62552
62954
|
if (!res.ok || !res.body) throw new Error(`\u4E0B\u8F7D\u5931\u8D25 HTTP ${res.status}\uFF1A${url}`);
|
|
62553
62955
|
const declared = Number(res.headers.get("content-length") ?? 0);
|
|
62554
62956
|
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
|
|
62556
|
-
const file =
|
|
62957
|
+
const dir = await import_node_fs36.default.promises.mkdtemp(import_node_path43.default.join(import_node_os13.default.tmpdir(), "clawd-artifact-"));
|
|
62958
|
+
const file = import_node_path43.default.join(dir, "pkg");
|
|
62557
62959
|
const hash = (0, import_node_crypto13.createHash)("sha256");
|
|
62558
62960
|
let size = 0;
|
|
62559
62961
|
const meter = new import_node_stream3.Transform({
|
|
@@ -62565,7 +62967,7 @@ function downloadArtifact(exec) {
|
|
|
62565
62967
|
}
|
|
62566
62968
|
});
|
|
62567
62969
|
try {
|
|
62568
|
-
await (0, import_promises6.pipeline)(import_node_stream3.Readable.fromWeb(res.body), meter,
|
|
62970
|
+
await (0, import_promises6.pipeline)(import_node_stream3.Readable.fromWeb(res.body), meter, import_node_fs36.default.createWriteStream(file));
|
|
62569
62971
|
let entries;
|
|
62570
62972
|
if (listEntries) {
|
|
62571
62973
|
const r2 = await exec("tar", ["-tzf", file], { timeoutMs: 3e4 });
|
|
@@ -62574,7 +62976,7 @@ function downloadArtifact(exec) {
|
|
|
62574
62976
|
}
|
|
62575
62977
|
return { sha256: hash.digest("hex"), size, ...entries ? { entries } : {} };
|
|
62576
62978
|
} finally {
|
|
62577
|
-
await
|
|
62979
|
+
await import_node_fs36.default.promises.rm(dir, { recursive: true, force: true });
|
|
62578
62980
|
}
|
|
62579
62981
|
};
|
|
62580
62982
|
}
|
|
@@ -63136,6 +63538,7 @@ function buildDeployHandlers(deps) {
|
|
|
63136
63538
|
...publisherFeishuAuth ? { publisherFeishuAuth } : {},
|
|
63137
63539
|
targets,
|
|
63138
63540
|
promotions: file.promotions,
|
|
63541
|
+
...file.engineChannels ? { engineChannels: file.engineChannels } : {},
|
|
63139
63542
|
...repo2 ? { repo: repo2 } : {},
|
|
63140
63543
|
scans,
|
|
63141
63544
|
releases: file.releases,
|
|
@@ -63257,10 +63660,12 @@ function buildDeployHandlers(deps) {
|
|
|
63257
63660
|
const args = parseArgs2(DeploySetEngineAuthArgsSchema, frame, "deploy:setEngineAuth");
|
|
63258
63661
|
const dir = mustPersona(args.personaId);
|
|
63259
63662
|
let auth = args.auth;
|
|
63663
|
+
let channelSource = null;
|
|
63260
63664
|
if (args.channelId) {
|
|
63261
63665
|
const channel = deps.channelStore?.get(args.channelId);
|
|
63262
63666
|
if (!channel) throw invalid(`\u672A\u627E\u5230 ID \u4E3A ${args.channelId} \u7684\u8BA2\u9605\u901A\u9053`);
|
|
63263
63667
|
auth = { baseUrl: channel.baseUrl, apiKey: channel.apiKey };
|
|
63668
|
+
channelSource = { channelId: channel.id, updatedAt: channel.updatedAt };
|
|
63264
63669
|
}
|
|
63265
63670
|
let writes;
|
|
63266
63671
|
if (auth) {
|
|
@@ -63276,6 +63681,8 @@ function buildDeployHandlers(deps) {
|
|
|
63276
63681
|
writes = [[ENGINE_AUTH_SECRETS.apiKey, apiKey], [ENGINE_AUTH_SECRETS.baseUrl, baseUrl]];
|
|
63277
63682
|
}
|
|
63278
63683
|
const { api } = await requireGithub();
|
|
63684
|
+
const before = await readHistory(dir);
|
|
63685
|
+
await writeScanFile(dir, { ...before, engineChannels: { ...before.engineChannels, [args.environment]: null } });
|
|
63279
63686
|
try {
|
|
63280
63687
|
if (args.environment === "production") {
|
|
63281
63688
|
for (const env of [ENGINE_AUTH_SECRETS.baseUrl, ENGINE_AUTH_SECRETS.apiKey]) {
|
|
@@ -63286,6 +63693,8 @@ function buildDeployHandlers(deps) {
|
|
|
63286
63693
|
await deleteSecret(deps.exec, api, { dir, env: args.environment === "integration" ? "CLAWD_INT_" + ENGINE_AUTH_SECRETS.baseUrl : ENGINE_AUTH_SECRETS.baseUrl, environment: args.environment });
|
|
63287
63694
|
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
63695
|
} 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 });
|
|
63696
|
+
const latest = await readHistory(dir);
|
|
63697
|
+
await writeScanFile(dir, { ...latest, engineChannels: { ...latest.engineChannels, [args.environment]: channelSource } });
|
|
63289
63698
|
} catch (err) {
|
|
63290
63699
|
throw toClawdError(err);
|
|
63291
63700
|
} finally {
|
|
@@ -63724,325 +64133,8 @@ function buildDeployHandlers(deps) {
|
|
|
63724
64133
|
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
63725
64134
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
63726
64135
|
var import_node_path44 = __toESM(require("path"), 1);
|
|
63727
|
-
|
|
63728
|
-
|
|
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
|
|
64136
|
+
init_subscription_channels_apply();
|
|
64137
|
+
init_codex_config_toml();
|
|
64046
64138
|
var CHANNELS_FILE_NAME = "subscription-channels.json";
|
|
64047
64139
|
function providerKey(provider, codexHome) {
|
|
64048
64140
|
if ([provider.env_key, provider.experimental_bearer_token, provider.auth].includes(UNREADABLE)) return null;
|
|
@@ -64227,6 +64319,9 @@ var SubscriptionChannelStore = class {
|
|
|
64227
64319
|
}
|
|
64228
64320
|
};
|
|
64229
64321
|
|
|
64322
|
+
// src/index.ts
|
|
64323
|
+
init_subscription_channels_apply();
|
|
64324
|
+
|
|
64230
64325
|
// src/deploy/local-probe.ts
|
|
64231
64326
|
function pickVersion(s2) {
|
|
64232
64327
|
return /(\d+)\.(\d+)(?:\.(\d+))?/.exec(s2)?.[0];
|
|
@@ -65698,7 +65793,8 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
65698
65793
|
await deps.getCapabilities(args.tool);
|
|
65699
65794
|
}
|
|
65700
65795
|
if (args.model !== void 0) {
|
|
65701
|
-
const
|
|
65796
|
+
const caps = await deps.getCapabilities?.(effectiveTool);
|
|
65797
|
+
const allowed = caps ? caps.models.map((m3) => m3.id).filter((id) => id !== "") : effectiveTool === "claude" ? CLAUDE_MODEL_IDS : [];
|
|
65702
65798
|
if (!allowed.includes(args.model)) {
|
|
65703
65799
|
throw new ClawdError(
|
|
65704
65800
|
ERROR_CODES.INVALID_PARAM,
|
|
@@ -66918,16 +67014,22 @@ var PiAdapter = class {
|
|
|
66918
67014
|
probeCache = null;
|
|
66919
67015
|
// 进程级 memo,**回落结果同样缓存**(pi 没装时别每次开弹窗都 spawn 一次必然失败的子进程;同 codex)
|
|
66920
67016
|
capsPromise;
|
|
67017
|
+
capsRevision = 0;
|
|
66921
67018
|
windows = /* @__PURE__ */ new Map();
|
|
66922
67019
|
async probe() {
|
|
66923
67020
|
if (this.probeCache) return this.probeCache;
|
|
66924
67021
|
this.probeCache = this.opts.probeOverride ? await this.opts.probeOverride() : await probePi();
|
|
66925
67022
|
return this.probeCache;
|
|
66926
67023
|
}
|
|
67024
|
+
invalidateCapabilities() {
|
|
67025
|
+
this.capsRevision++;
|
|
67026
|
+
this.capsPromise = void 0;
|
|
67027
|
+
}
|
|
66927
67028
|
async capabilities(opts) {
|
|
66928
67029
|
if (opts?.refresh) {
|
|
67030
|
+
const revision = this.capsRevision;
|
|
66929
67031
|
const fresh = await this.loadCapabilities({ strict: true, refresh: true });
|
|
66930
|
-
this.capsPromise = Promise.resolve(fresh);
|
|
67032
|
+
if (revision === this.capsRevision) this.capsPromise = Promise.resolve(fresh);
|
|
66931
67033
|
return fresh;
|
|
66932
67034
|
}
|
|
66933
67035
|
if (!this.capsPromise) this.capsPromise = this.loadCapabilities({ strict: false, refresh: false });
|
|
@@ -73528,6 +73630,8 @@ function buildEngineHandlers(deps, overrides = {}) {
|
|
|
73528
73630
|
// src/handlers/channels.ts
|
|
73529
73631
|
var import_node_fs66 = __toESM(require("fs"), 1);
|
|
73530
73632
|
var import_node_path75 = __toESM(require("path"), 1);
|
|
73633
|
+
init_subscription_channels_apply();
|
|
73634
|
+
init_codex_provider_models();
|
|
73531
73635
|
function buildChannelsHandlers(deps) {
|
|
73532
73636
|
let queue = Promise.resolve();
|
|
73533
73637
|
const serialized = (fn) => (frame, context) => {
|
|
@@ -73540,6 +73644,12 @@ function buildChannelsHandlers(deps) {
|
|
|
73540
73644
|
async function transact(mutate) {
|
|
73541
73645
|
const codexHome = resolveCodexHome2(deps.codexHome);
|
|
73542
73646
|
const agentDir = resolvePiAgentDir(deps.agentDir);
|
|
73647
|
+
const claudeDir = resolveClaudeConfigDir(deps.claudeConfigDir);
|
|
73648
|
+
let restoreClaude;
|
|
73649
|
+
let restoreClaudeBackup;
|
|
73650
|
+
const invalidateModels = () => {
|
|
73651
|
+
for (const tool of ["codex", "claude", "pi"]) deps.manager.invalidateCapabilities(tool);
|
|
73652
|
+
};
|
|
73543
73653
|
const restoreStore = deps.store.snapshot();
|
|
73544
73654
|
const restoreCodex = snapshotFile(import_node_path75.default.join(codexHome, "config.toml"));
|
|
73545
73655
|
const restorePi = import_node_fs66.default.existsSync(agentDir) ? snapshotFile(import_node_path75.default.join(agentDir, PI_SUBSCRIPTION_FILE)) : null;
|
|
@@ -73548,6 +73658,8 @@ function buildChannelsHandlers(deps) {
|
|
|
73548
73658
|
next = mutate();
|
|
73549
73659
|
if (next === void 0) return;
|
|
73550
73660
|
if (next) {
|
|
73661
|
+
const commitStore = deps.store.snapshot();
|
|
73662
|
+
restoreStore();
|
|
73551
73663
|
try {
|
|
73552
73664
|
await fetchProviderModels({ baseUrl: next.baseUrl, headers: {
|
|
73553
73665
|
Accept: "application/json",
|
|
@@ -73558,14 +73670,21 @@ function buildChannelsHandlers(deps) {
|
|
|
73558
73670
|
const authFailed = /HTTP (401|403)\b/.test(message);
|
|
73559
73671
|
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
73672
|
}
|
|
73673
|
+
commitStore();
|
|
73561
73674
|
}
|
|
73675
|
+
restoreClaude = snapshotFile(import_node_path75.default.join(claudeDir, "settings.json"));
|
|
73676
|
+
restoreClaudeBackup = snapshotFile(import_node_path75.default.join(claudeDir, CLAUDE_SUBSCRIPTION_BACKUP));
|
|
73562
73677
|
applyCodexSubscriptionChannel({ codexHome, channel: next });
|
|
73563
73678
|
applyPiSubscriptionChannel({ agentDir, channel: next });
|
|
73564
|
-
|
|
73679
|
+
applyClaudeSubscriptionChannel({ configDir: claudeDir, channel: next });
|
|
73680
|
+
invalidateModels();
|
|
73565
73681
|
} catch (err) {
|
|
73566
73682
|
restoreStore();
|
|
73567
73683
|
restoreCodex();
|
|
73568
73684
|
restorePi?.();
|
|
73685
|
+
restoreClaude?.();
|
|
73686
|
+
restoreClaudeBackup?.();
|
|
73687
|
+
invalidateModels();
|
|
73569
73688
|
if (next?.id === "default-pool" && err instanceof Error && /HTTP 401/.test(err.message)) {
|
|
73570
73689
|
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
73690
|
}
|
|
@@ -73598,8 +73717,10 @@ function buildChannelsHandlers(deps) {
|
|
|
73598
73717
|
return { response: { ok: true } };
|
|
73599
73718
|
});
|
|
73600
73719
|
const models = async (frame) => {
|
|
73601
|
-
parseArgs2(SubscriptionChannelModelsArgsSchema, frame, "subscriptionChannel:models");
|
|
73602
|
-
const active = deps.store.getActive();
|
|
73720
|
+
const args = parseArgs2(SubscriptionChannelModelsArgsSchema, frame, "subscriptionChannel:models");
|
|
73721
|
+
const active = args.channelId ? deps.store.get(args.channelId) : deps.store.getActive();
|
|
73722
|
+
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");
|
|
73723
|
+
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
73724
|
if (!active) return { response: { channelId: null, models: [] } };
|
|
73604
73725
|
const list = await fetchProviderModels(
|
|
73605
73726
|
{ baseUrl: active.baseUrl, headers: { Accept: "application/json", Authorization: `Bearer ${active.apiKey}` } },
|
|
@@ -74529,7 +74650,7 @@ function computeMethodAccess(args) {
|
|
|
74529
74650
|
}
|
|
74530
74651
|
|
|
74531
74652
|
// src/version.ts
|
|
74532
|
-
var version = "0.2.
|
|
74653
|
+
var version = "0.2.659".length > 0 ? "0.2.659" : "dev";
|
|
74533
74654
|
|
|
74534
74655
|
// src/cli-probe/probe.ts
|
|
74535
74656
|
var fs85 = __toESM(require("fs"), 1);
|
|
@@ -77142,7 +77263,10 @@ async function startDaemon(config) {
|
|
|
77142
77263
|
const personaStore = new PersonaStore(import_node_path88.default.join(config.dataDir, "personas"));
|
|
77143
77264
|
const subscriptionChannelStore = new SubscriptionChannelStore({ dataDir: config.dataDir });
|
|
77144
77265
|
const activeSubscriptionChannel = subscriptionChannelStore.getActive();
|
|
77145
|
-
if (activeSubscriptionChannel)
|
|
77266
|
+
if (activeSubscriptionChannel) {
|
|
77267
|
+
applyPiSubscriptionChannel({ channel: activeSubscriptionChannel });
|
|
77268
|
+
applyClaudeSubscriptionChannel({ channel: activeSubscriptionChannel });
|
|
77269
|
+
}
|
|
77146
77270
|
const usersRoot = import_node_path88.default.join(config.dataDir, "users");
|
|
77147
77271
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
77148
77272
|
if (defaultsRoot) {
|
|
@@ -77551,6 +77675,7 @@ async function startDaemon(config) {
|
|
|
77551
77675
|
manager.attachObserver(observer);
|
|
77552
77676
|
deliverPendingRef = (sid) => manager.deliverPending(sid);
|
|
77553
77677
|
const claudeAdapter = config.mode === "tui" ? new ClaudeTuiAdapter({
|
|
77678
|
+
getSubscriptionChannel: () => subscriptionChannelStore.getActive(),
|
|
77554
77679
|
logger,
|
|
77555
77680
|
historyReader: new ClaudeHistoryReader(),
|
|
77556
77681
|
onPtyRegister: (tsid, pty) => manager.registerPty(tsid, pty),
|
|
@@ -77563,7 +77688,7 @@ async function startDaemon(config) {
|
|
|
77563
77688
|
onReady: (tsid) => manager.dispatchReadyDetected(tsid),
|
|
77564
77689
|
onScreenIdle: (tsid) => manager.notifyScreenIdle(tsid),
|
|
77565
77690
|
screenIdleProbeLogger
|
|
77566
|
-
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
77691
|
+
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader(), getSubscriptionChannel: () => subscriptionChannelStore.getActive() });
|
|
77567
77692
|
const cloudGateway = new CloudGatewayClient({
|
|
77568
77693
|
getLoginPass: () => ownerIdentityStore.read()?.loginPass ?? null,
|
|
77569
77694
|
centralApi: config.clawosApi ?? DEFAULT_CLAWOS_API,
|