pullfrog 0.1.85 → 0.1.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +95 -363
- package/dist/index.js +91 -399
- package/dist/internal.js +3 -3
- package/package.json +1 -1
- package/dist/utils/credentialPool.d.ts +0 -10
package/dist/cli.mjs
CHANGED
|
@@ -84177,7 +84177,7 @@ var require_Element = __commonJS({
|
|
|
84177
84177
|
var FilteredElementList = require_FilteredElementList();
|
|
84178
84178
|
var DOMException2 = require_DOMException();
|
|
84179
84179
|
var DOMTokenList = require_DOMTokenList();
|
|
84180
|
-
var
|
|
84180
|
+
var select2 = require_select();
|
|
84181
84181
|
var ContainerNode = require_ContainerNode();
|
|
84182
84182
|
var ChildNode = require_ChildNode();
|
|
84183
84183
|
var NonDocumentTypeChildNode = require_NonDocumentTypeChildNode();
|
|
@@ -84938,7 +84938,7 @@ var require_Element = __commonJS({
|
|
|
84938
84938
|
this.className = v;
|
|
84939
84939
|
} },
|
|
84940
84940
|
matches: { value: function(selector) {
|
|
84941
|
-
return
|
|
84941
|
+
return select2.matches(this, selector);
|
|
84942
84942
|
} },
|
|
84943
84943
|
closest: { value: function(selector) {
|
|
84944
84944
|
var el = this;
|
|
@@ -84951,10 +84951,10 @@ var require_Element = __commonJS({
|
|
|
84951
84951
|
return null;
|
|
84952
84952
|
} },
|
|
84953
84953
|
querySelector: { value: function(selector) {
|
|
84954
|
-
return
|
|
84954
|
+
return select2(selector, this)[0];
|
|
84955
84955
|
} },
|
|
84956
84956
|
querySelectorAll: { value: function(selector) {
|
|
84957
|
-
var nodes =
|
|
84957
|
+
var nodes = select2(selector, this);
|
|
84958
84958
|
return nodes.item ? nodes : new NodeList(nodes);
|
|
84959
84959
|
} }
|
|
84960
84960
|
});
|
|
@@ -85482,7 +85482,7 @@ var require_DocumentFragment = __commonJS({
|
|
|
85482
85482
|
var NodeList = require_NodeList();
|
|
85483
85483
|
var ContainerNode = require_ContainerNode();
|
|
85484
85484
|
var Element = require_Element();
|
|
85485
|
-
var
|
|
85485
|
+
var select2 = require_select();
|
|
85486
85486
|
var utils = require_utils8();
|
|
85487
85487
|
function DocumentFragment(doc) {
|
|
85488
85488
|
ContainerNode.call(this);
|
|
@@ -85511,7 +85511,7 @@ var require_DocumentFragment = __commonJS({
|
|
|
85511
85511
|
context.isHTML = true;
|
|
85512
85512
|
context.getElementsByTagName = Element.prototype.getElementsByTagName;
|
|
85513
85513
|
context.nextElement = Object.getOwnPropertyDescriptor(Element.prototype, "firstElementChild").get;
|
|
85514
|
-
var nodes =
|
|
85514
|
+
var nodes = select2(selector, context);
|
|
85515
85515
|
return nodes.item ? nodes : new NodeList(nodes);
|
|
85516
85516
|
} },
|
|
85517
85517
|
// Utility methods
|
|
@@ -88626,7 +88626,7 @@ var require_Document = __commonJS({
|
|
|
88626
88626
|
var NodeIterator = require_NodeIterator();
|
|
88627
88627
|
var NodeFilter = require_NodeFilter();
|
|
88628
88628
|
var URL2 = require_URL();
|
|
88629
|
-
var
|
|
88629
|
+
var select2 = require_select();
|
|
88630
88630
|
var events = require_events3();
|
|
88631
88631
|
var xml = require_xmlnames();
|
|
88632
88632
|
var html = require_htmlelts();
|
|
@@ -89187,10 +89187,10 @@ var require_Document = __commonJS({
|
|
|
89187
89187
|
return this._templateDocCache;
|
|
89188
89188
|
} },
|
|
89189
89189
|
querySelector: { value: function(selector) {
|
|
89190
|
-
return
|
|
89190
|
+
return select2(selector, this)[0];
|
|
89191
89191
|
} },
|
|
89192
89192
|
querySelectorAll: { value: function(selector) {
|
|
89193
|
-
var nodes =
|
|
89193
|
+
var nodes = select2(selector, this);
|
|
89194
89194
|
return nodes.item ? nodes : new NodeList(nodes);
|
|
89195
89195
|
} }
|
|
89196
89196
|
});
|
|
@@ -107103,7 +107103,7 @@ var import_picocolors = __toESM(require_picocolors(), 1);
|
|
|
107103
107103
|
// package.json
|
|
107104
107104
|
var package_default = {
|
|
107105
107105
|
name: "pullfrog",
|
|
107106
|
-
version: "0.1.
|
|
107106
|
+
version: "0.1.86",
|
|
107107
107107
|
cliContractVersion: "1",
|
|
107108
107108
|
type: "module",
|
|
107109
107109
|
bin: {
|
|
@@ -110310,8 +110310,8 @@ var providers = {
|
|
|
110310
110310
|
},
|
|
110311
110311
|
"claude-sonnet": {
|
|
110312
110312
|
displayName: "Claude Sonnet",
|
|
110313
|
-
resolve: "vercel/anthropic/claude-sonnet-5",
|
|
110314
|
-
effort: ["
|
|
110313
|
+
resolve: "vercel/anthropic/claude-sonnet-5.5",
|
|
110314
|
+
effort: ["low", "medium", "high", "xhigh", "max"]
|
|
110315
110315
|
},
|
|
110316
110316
|
"claude-haiku": {
|
|
110317
110317
|
displayName: "Claude Haiku",
|
|
@@ -113518,17 +113518,6 @@ import { join as join6 } from "node:path";
|
|
|
113518
113518
|
var CODEX_AUTH_ENV = "CODEX_AUTH_JSON";
|
|
113519
113519
|
var XAI_AUTH_ENV = "GROK_AUTH_JSON";
|
|
113520
113520
|
var installedSubscriptionPaths = /* @__PURE__ */ new Map();
|
|
113521
|
-
function clearInstalledSubscription(name) {
|
|
113522
|
-
const path4 = installedSubscriptionPaths.get(name);
|
|
113523
|
-
if (!path4 || !existsSync5(path4)) return;
|
|
113524
|
-
const value2 = JSON.parse(readFileSync3(path4, "utf8"));
|
|
113525
|
-
if (!value2 || typeof value2 !== "object") return;
|
|
113526
|
-
if (name === "CODEX_AUTH_JSON" && "openai" in value2) delete value2.openai;
|
|
113527
|
-
if (name === "GROK_AUTH_JSON" && "xai" in value2) delete value2.xai;
|
|
113528
|
-
writeFileSync5(path4, `${JSON.stringify(value2)}
|
|
113529
|
-
`, { mode: 384 });
|
|
113530
|
-
installedSubscriptionPaths.delete(name);
|
|
113531
|
-
}
|
|
113532
113521
|
var PULLFROG_DATA_DIR = "/var/lib/pullfrog";
|
|
113533
113522
|
function isRejectedChain(body) {
|
|
113534
113523
|
if (!body.refresh_rejected_at) return false;
|
|
@@ -113859,8 +113848,8 @@ async function writeBackEntry(apiToken, entry) {
|
|
|
113859
113848
|
}
|
|
113860
113849
|
try {
|
|
113861
113850
|
const poolState = core2.getState("credential_receipts");
|
|
113862
|
-
const
|
|
113863
|
-
const receipt =
|
|
113851
|
+
const receipts = external_exports.record(external_exports.string(), external_exports.string()).parse(JSON.parse(poolState || "{}"));
|
|
113852
|
+
const receipt = receipts[entry.secretName];
|
|
113864
113853
|
if (poolState && !receipt) return;
|
|
113865
113854
|
const response = await apiFetch({
|
|
113866
113855
|
path: receipt ? "/api/runtime/credentials" : "/api/runtime/secret",
|
|
@@ -198136,304 +198125,6 @@ async function checkConfiguredCredentials(params) {
|
|
|
198136
198125
|
return replacement ? { kind: "fellBack", ...outcome, replacement } : { kind: "dead", ...outcome };
|
|
198137
198126
|
}
|
|
198138
198127
|
|
|
198139
|
-
// utils/normalizeEnv.ts
|
|
198140
|
-
function hasControlCharacter(value2) {
|
|
198141
|
-
return [...value2].some((ch) => {
|
|
198142
|
-
const code = ch.charCodeAt(0);
|
|
198143
|
-
return code < 32 || code === 127;
|
|
198144
|
-
});
|
|
198145
|
-
}
|
|
198146
|
-
function sanitizeSecret(key, value2) {
|
|
198147
|
-
const trimmed = value2.trim();
|
|
198148
|
-
if (trimmed.length === 0) {
|
|
198149
|
-
log2.warning(
|
|
198150
|
-
`\xBB ${key} is whitespace-only \u2014 leaving env var unchanged. check your secret value.`
|
|
198151
|
-
);
|
|
198152
|
-
return null;
|
|
198153
|
-
}
|
|
198154
|
-
if (key.endsWith("_API_KEY") && hasControlCharacter(trimmed)) {
|
|
198155
|
-
log2.warning(
|
|
198156
|
-
`\xBB ${key} contains a line break or control character and cannot be sent as an HTTP header \u2014 leaving env var unchanged. re-save the secret as a single line.`
|
|
198157
|
-
);
|
|
198158
|
-
return null;
|
|
198159
|
-
}
|
|
198160
|
-
if (trimmed !== value2) {
|
|
198161
|
-
log2.warning(
|
|
198162
|
-
`\xBB stripped whitespace from ${key} (whitespace in secret values breaks GitHub Actions log masking)`
|
|
198163
|
-
);
|
|
198164
|
-
}
|
|
198165
|
-
maskSecret(trimmed);
|
|
198166
|
-
return trimmed;
|
|
198167
|
-
}
|
|
198168
|
-
function normalizeEnv() {
|
|
198169
|
-
const upperKeys = /* @__PURE__ */ new Map();
|
|
198170
|
-
for (const key of Object.keys(process.env)) {
|
|
198171
|
-
const upper2 = key.toUpperCase();
|
|
198172
|
-
const existing = upperKeys.get(upper2) || [];
|
|
198173
|
-
existing.push(key);
|
|
198174
|
-
upperKeys.set(upper2, existing);
|
|
198175
|
-
}
|
|
198176
|
-
for (const [upperKey, keys] of upperKeys) {
|
|
198177
|
-
if (keys.length === 1) {
|
|
198178
|
-
const key = keys[0];
|
|
198179
|
-
if (key !== upperKey) {
|
|
198180
|
-
process.env[upperKey] = process.env[key];
|
|
198181
|
-
delete process.env[key];
|
|
198182
|
-
}
|
|
198183
|
-
continue;
|
|
198184
|
-
}
|
|
198185
|
-
const values = keys.map((k2) => process.env[k2]);
|
|
198186
|
-
const uniqueValues = new Set(values);
|
|
198187
|
-
if (uniqueValues.size > 1) {
|
|
198188
|
-
log2.warning(
|
|
198189
|
-
`env var conflict: ${keys.join(", ")} have different values. using uppercase ${upperKey}.`
|
|
198190
|
-
);
|
|
198191
|
-
}
|
|
198192
|
-
const preferredKey = keys.find((k2) => k2 === upperKey) || keys[0];
|
|
198193
|
-
const preferredValue = process.env[preferredKey];
|
|
198194
|
-
for (const key of keys) {
|
|
198195
|
-
delete process.env[key];
|
|
198196
|
-
}
|
|
198197
|
-
process.env[upperKey] = preferredValue;
|
|
198198
|
-
}
|
|
198199
|
-
for (const key of Object.keys(process.env)) {
|
|
198200
|
-
if (!isSensitiveEnvName(key)) continue;
|
|
198201
|
-
const value2 = process.env[key];
|
|
198202
|
-
if (typeof value2 !== "string" || value2.length === 0) continue;
|
|
198203
|
-
const sanitized = sanitizeSecret(key, value2);
|
|
198204
|
-
if (sanitized !== null) process.env[key] = sanitized;
|
|
198205
|
-
}
|
|
198206
|
-
}
|
|
198207
|
-
|
|
198208
|
-
// utils/subscriptionProbe.ts
|
|
198209
|
-
var identitySchema = external_exports.object({
|
|
198210
|
-
email: external_exports.string().email().optional(),
|
|
198211
|
-
sub: external_exports.string().optional(),
|
|
198212
|
-
user_id: external_exports.string().optional(),
|
|
198213
|
-
account_id: external_exports.string().optional(),
|
|
198214
|
-
email_verified: external_exports.boolean().optional()
|
|
198215
|
-
});
|
|
198216
|
-
var codexUsageSchema = external_exports.object({
|
|
198217
|
-
rate_limit: external_exports.object({ allowed: external_exports.boolean(), limit_reached: external_exports.boolean() }).optional()
|
|
198218
|
-
});
|
|
198219
|
-
async function readSubscriptionEndpoint(input) {
|
|
198220
|
-
const headers = new Headers({ authorization: `Bearer ${input.token}` });
|
|
198221
|
-
if (input.accountId) headers.set("ChatGPT-Account-Id", input.accountId);
|
|
198222
|
-
if (input.grokBilling) headers.set("x-xai-token-auth", "xai-grok-cli");
|
|
198223
|
-
return fetch(input.url, {
|
|
198224
|
-
headers,
|
|
198225
|
-
redirect: "error",
|
|
198226
|
-
signal: AbortSignal.timeout(1e4)
|
|
198227
|
-
}).catch(() => null);
|
|
198228
|
-
}
|
|
198229
|
-
async function probeSubscription(input) {
|
|
198230
|
-
if (input.name === "CLAUDE_CODE_OAUTH_TOKEN") {
|
|
198231
|
-
const result = await preflightClaudeSubscription({ token: input.value, model: input.model });
|
|
198232
|
-
return result.usable ? "usable" : "rejected";
|
|
198233
|
-
}
|
|
198234
|
-
const codex2 = input.name === "CODEX_AUTH_JSON" ? parseCodexAuthBody(input.value) : null;
|
|
198235
|
-
const grok = input.name === "GROK_AUTH_JSON" ? parseXaiAuthBody(input.value) : null;
|
|
198236
|
-
const auth2 = codex2 ?? grok;
|
|
198237
|
-
if (!auth2 || auth2.refresh_rejected_at) return "rejected";
|
|
198238
|
-
if (grok && input.model)
|
|
198239
|
-
return probeInference({
|
|
198240
|
-
name: "XAI_API_KEY",
|
|
198241
|
-
value: grok.tokens.access_token,
|
|
198242
|
-
model: input.model
|
|
198243
|
-
});
|
|
198244
|
-
const response = await readSubscriptionEndpoint({
|
|
198245
|
-
url: codex2 ? "https://chatgpt.com/backend-api/wham/usage" : "https://cli-chat-proxy.grok.com/v1/billing?format=credits",
|
|
198246
|
-
token: auth2.tokens.access_token,
|
|
198247
|
-
accountId: codex2?.tokens.account_id,
|
|
198248
|
-
grokBilling: !!grok
|
|
198249
|
-
});
|
|
198250
|
-
if (response?.status === 401) return "rejected";
|
|
198251
|
-
if (!response?.ok) return "unknown";
|
|
198252
|
-
const body = await response.json().catch(() => null);
|
|
198253
|
-
if (codex2) {
|
|
198254
|
-
const parsed2 = codexUsageSchema.safeParse(body);
|
|
198255
|
-
const limit = parsed2.success ? parsed2.data.rate_limit : void 0;
|
|
198256
|
-
if (!limit) return "unknown";
|
|
198257
|
-
return limit.allowed && !limit.limit_reached ? "usable" : "rejected";
|
|
198258
|
-
}
|
|
198259
|
-
return "unknown";
|
|
198260
|
-
}
|
|
198261
|
-
async function probeInference(input) {
|
|
198262
|
-
const anthropic = input.name === "ANTHROPIC_API_KEY";
|
|
198263
|
-
const openai = input.name === "OPENAI_API_KEY";
|
|
198264
|
-
if (!anthropic && !openai && input.name !== "XAI_API_KEY") {
|
|
198265
|
-
const result = await verifyCredential({ envVar: input.name, value: input.value });
|
|
198266
|
-
return result === "dead" ? "rejected" : result === "alive" ? "usable" : "unknown";
|
|
198267
|
-
}
|
|
198268
|
-
const headers = new Headers({ "content-type": "application/json" });
|
|
198269
|
-
if (anthropic) {
|
|
198270
|
-
headers.set("x-api-key", input.value);
|
|
198271
|
-
headers.set("anthropic-version", "2023-06-01");
|
|
198272
|
-
} else headers.set("authorization", `Bearer ${input.value}`);
|
|
198273
|
-
const response = await fetch(
|
|
198274
|
-
anthropic ? "https://api.anthropic.com/v1/messages" : openai ? "https://api.openai.com/v1/responses" : "https://api.x.ai/v1/chat/completions",
|
|
198275
|
-
{
|
|
198276
|
-
method: "POST",
|
|
198277
|
-
headers,
|
|
198278
|
-
body: JSON.stringify(
|
|
198279
|
-
openai ? { model: input.model, input: "Reply OK.", max_output_tokens: 16, store: false } : {
|
|
198280
|
-
model: input.model,
|
|
198281
|
-
messages: [{ role: "user", content: "Reply OK." }],
|
|
198282
|
-
max_tokens: 1
|
|
198283
|
-
}
|
|
198284
|
-
),
|
|
198285
|
-
redirect: "error",
|
|
198286
|
-
signal: AbortSignal.timeout(1e4)
|
|
198287
|
-
}
|
|
198288
|
-
).catch(() => null);
|
|
198289
|
-
if (response?.status === 400 && input.name === "XAI_API_KEY") {
|
|
198290
|
-
const error49 = external_exports.object({ error: external_exports.string() }).safeParse(await response.json().catch(() => null));
|
|
198291
|
-
return error49.success && error49.data.error.startsWith("Incorrect API key provided.") ? "rejected" : "unknown";
|
|
198292
|
-
}
|
|
198293
|
-
await response?.body?.cancel();
|
|
198294
|
-
if (!response) return "unknown";
|
|
198295
|
-
if (response.ok) return "usable";
|
|
198296
|
-
return [401, 402, 403, 429].includes(response.status) ? "rejected" : "unknown";
|
|
198297
|
-
}
|
|
198298
|
-
|
|
198299
|
-
// utils/credentialPool.ts
|
|
198300
|
-
var receipts = {};
|
|
198301
|
-
var workflowCredentials = {};
|
|
198302
|
-
function saveReceipts() {
|
|
198303
|
-
for (const receipt of Object.values(receipts)) maskSecret(receipt);
|
|
198304
|
-
saveSecretState("credential_receipts", JSON.stringify(receipts));
|
|
198305
|
-
}
|
|
198306
|
-
var select2 = op(
|
|
198307
|
-
async (input) => {
|
|
198308
|
-
const response = await apiFetch({
|
|
198309
|
-
path: "/api/runtime/credentials",
|
|
198310
|
-
method: "POST",
|
|
198311
|
-
headers: {
|
|
198312
|
-
authorization: `Bearer ${input.access.token}`,
|
|
198313
|
-
"content-type": "application/json"
|
|
198314
|
-
},
|
|
198315
|
-
body: JSON.stringify({ id: input.candidate.id }),
|
|
198316
|
-
signal: AbortSignal.timeout(35e3)
|
|
198317
|
-
});
|
|
198318
|
-
if (response.status === 404) return null;
|
|
198319
|
-
if (!response.ok)
|
|
198320
|
-
throw new Error("could not load a configured credential; no fallback was charged", {
|
|
198321
|
-
cause: response.status
|
|
198322
|
-
});
|
|
198323
|
-
return selectedCredentialSchema.parse(await response.json());
|
|
198324
|
-
},
|
|
198325
|
-
{
|
|
198326
|
-
retries: [250, 1e3],
|
|
198327
|
-
bail: (error49) => error49 instanceof Error && typeof error49.cause === "number" && error49.cause >= 400 && error49.cause < 500
|
|
198328
|
-
}
|
|
198329
|
-
);
|
|
198330
|
-
function subscriptionForModel(model) {
|
|
198331
|
-
if (!model.includes("/")) return null;
|
|
198332
|
-
const provider2 = getModelProvider(model);
|
|
198333
|
-
return provider2 === "anthropic" ? "CLAUDE_CODE_OAUTH_TOKEN" : provider2 === "openai" ? "CODEX_AUTH_JSON" : provider2 === "xai" ? "GROK_AUTH_JSON" : null;
|
|
198334
|
-
}
|
|
198335
|
-
async function initializeCredentialPool(ctx, model) {
|
|
198336
|
-
const access = ctx.credentialAccess;
|
|
198337
|
-
if (!access) return;
|
|
198338
|
-
maskSecret(access.token);
|
|
198339
|
-
const names = /* @__PURE__ */ new Set([
|
|
198340
|
-
...access.candidates.map((candidate) => candidate.name),
|
|
198341
|
-
...subscriptionNameSchema.options,
|
|
198342
|
-
"ANTHROPIC_API_KEY",
|
|
198343
|
-
"OPENAI_API_KEY",
|
|
198344
|
-
"XAI_API_KEY"
|
|
198345
|
-
]);
|
|
198346
|
-
for (const name of names) {
|
|
198347
|
-
const value2 = process.env[name];
|
|
198348
|
-
if (value2) workflowCredentials[name] = value2;
|
|
198349
|
-
}
|
|
198350
|
-
for (const name of subscriptionNameSchema.options) {
|
|
198351
|
-
if (model && subscriptionForModel(model) !== name) continue;
|
|
198352
|
-
if (workflowCredentials[name]) continue;
|
|
198353
|
-
const candidate = access.candidates.find((item) => item.name === name);
|
|
198354
|
-
if (!candidate) continue;
|
|
198355
|
-
const selected = await select2({ access, candidate }).catch(() => {
|
|
198356
|
-
log2.warning(`\xBB could not load ${name} for model discovery; selection will retry if needed`);
|
|
198357
|
-
return null;
|
|
198358
|
-
});
|
|
198359
|
-
if (!selected) continue;
|
|
198360
|
-
const value2 = sanitizeSecret(name, selected.value);
|
|
198361
|
-
if (!value2) continue;
|
|
198362
|
-
process.env[name] = value2;
|
|
198363
|
-
receipts[name] = selected.receipt;
|
|
198364
|
-
}
|
|
198365
|
-
saveReceipts();
|
|
198366
|
-
}
|
|
198367
|
-
function resolvePoolModel(input) {
|
|
198368
|
-
const agent2 = resolveAgent({
|
|
198369
|
-
model: void 0,
|
|
198370
|
-
proxyModel: void 0,
|
|
198371
|
-
codexAgent: input.codexAgent
|
|
198372
|
-
});
|
|
198373
|
-
if (agent2.name === "opencode") return autoSelectModel();
|
|
198374
|
-
const provider2 = agent2.name === "claude" ? "anthropic" : "openai";
|
|
198375
|
-
return modelAliases.find(
|
|
198376
|
-
(alias) => alias.provider === provider2 && alias.preferred && !alias.hidden && !alias.fallback && !alias.routing
|
|
198377
|
-
)?.resolve;
|
|
198378
|
-
}
|
|
198379
|
-
async function selectConfiguredCredential(input) {
|
|
198380
|
-
const access = input.ctx.credentialAccess;
|
|
198381
|
-
const model = input.model;
|
|
198382
|
-
if (!access || !model?.includes("/") || getProviderGatewayUrl(model)) return false;
|
|
198383
|
-
const subscription = subscriptionForModel(model);
|
|
198384
|
-
const names = getModelEnvVars(model).filter((name) => name !== subscription);
|
|
198385
|
-
if (subscription) names.unshift(subscription);
|
|
198386
|
-
const candidates = access.candidates.filter((candidate) => names.includes(candidate.name));
|
|
198387
|
-
const workflow = names.filter((name) => workflowCredentials[name]);
|
|
198388
|
-
if (!candidates.length && !workflow.length) return false;
|
|
198389
|
-
for (const name of workflow) {
|
|
198390
|
-
const value2 = workflowCredentials[name];
|
|
198391
|
-
if (await usable({ name, value: value2, model })) {
|
|
198392
|
-
activate({ names, name, value: value2, receipt: void 0 });
|
|
198393
|
-
return true;
|
|
198394
|
-
}
|
|
198395
|
-
}
|
|
198396
|
-
for (const candidate of candidates) {
|
|
198397
|
-
const selected = await select2({ access, candidate });
|
|
198398
|
-
if (!selected) continue;
|
|
198399
|
-
if (await usable({ ...selected, model })) {
|
|
198400
|
-
activate({ names, ...selected });
|
|
198401
|
-
log2.info(`\xBB selected ${candidate.name} from ${candidate.source} scope`);
|
|
198402
|
-
return true;
|
|
198403
|
-
}
|
|
198404
|
-
log2.info(
|
|
198405
|
-
`\xBB ${candidate.name} from ${candidate.source} scope unavailable; trying the next credential`
|
|
198406
|
-
);
|
|
198407
|
-
}
|
|
198408
|
-
throw new Error(
|
|
198409
|
-
`all configured credentials for ${model} were rejected or exhausted; no other model or provider was selected`
|
|
198410
|
-
);
|
|
198411
|
-
}
|
|
198412
|
-
async function usable(input) {
|
|
198413
|
-
const subscription = subscriptionNameSchema.safeParse(input.name);
|
|
198414
|
-
if (subscription.success)
|
|
198415
|
-
return await probeSubscription({
|
|
198416
|
-
name: subscription.data,
|
|
198417
|
-
value: input.value,
|
|
198418
|
-
model: stripProviderPrefix(input.model)
|
|
198419
|
-
}) !== "rejected";
|
|
198420
|
-
return await probeInference({ ...input, model: stripProviderPrefix(input.model) }) !== "rejected";
|
|
198421
|
-
}
|
|
198422
|
-
function activate(input) {
|
|
198423
|
-
for (const name of input.names) {
|
|
198424
|
-
delete process.env[name];
|
|
198425
|
-
delete receipts[name];
|
|
198426
|
-
if (name === "CODEX_AUTH_JSON" || name === "GROK_AUTH_JSON") clearInstalledSubscription(name);
|
|
198427
|
-
}
|
|
198428
|
-
const value2 = sanitizeSecret(input.name, input.value);
|
|
198429
|
-
if (!value2) throw new Error("configured credential was empty");
|
|
198430
|
-
process.env[input.name] = value2;
|
|
198431
|
-
if (input.receipt) receipts[input.name] = input.receipt;
|
|
198432
|
-
installCodexAuth();
|
|
198433
|
-
installXaiAuth();
|
|
198434
|
-
saveReceipts();
|
|
198435
|
-
}
|
|
198436
|
-
|
|
198437
198128
|
// utils/gitAuthServer.ts
|
|
198438
198129
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
198439
198130
|
import { writeFileSync as writeFileSync15 } from "node:fs";
|
|
@@ -199137,6 +198828,75 @@ function buildModelAccessError(input) {
|
|
|
199137
198828
|
return [headline, "", why, "", cta].join("\n");
|
|
199138
198829
|
}
|
|
199139
198830
|
|
|
198831
|
+
// utils/normalizeEnv.ts
|
|
198832
|
+
function hasControlCharacter(value2) {
|
|
198833
|
+
return [...value2].some((ch) => {
|
|
198834
|
+
const code = ch.charCodeAt(0);
|
|
198835
|
+
return code < 32 || code === 127;
|
|
198836
|
+
});
|
|
198837
|
+
}
|
|
198838
|
+
function sanitizeSecret(key, value2) {
|
|
198839
|
+
const trimmed = value2.trim();
|
|
198840
|
+
if (trimmed.length === 0) {
|
|
198841
|
+
log2.warning(
|
|
198842
|
+
`\xBB ${key} is whitespace-only \u2014 leaving env var unchanged. check your secret value.`
|
|
198843
|
+
);
|
|
198844
|
+
return null;
|
|
198845
|
+
}
|
|
198846
|
+
if (key.endsWith("_API_KEY") && hasControlCharacter(trimmed)) {
|
|
198847
|
+
log2.warning(
|
|
198848
|
+
`\xBB ${key} contains a line break or control character and cannot be sent as an HTTP header \u2014 leaving env var unchanged. re-save the secret as a single line.`
|
|
198849
|
+
);
|
|
198850
|
+
return null;
|
|
198851
|
+
}
|
|
198852
|
+
if (trimmed !== value2) {
|
|
198853
|
+
log2.warning(
|
|
198854
|
+
`\xBB stripped whitespace from ${key} (whitespace in secret values breaks GitHub Actions log masking)`
|
|
198855
|
+
);
|
|
198856
|
+
}
|
|
198857
|
+
maskSecret(trimmed);
|
|
198858
|
+
return trimmed;
|
|
198859
|
+
}
|
|
198860
|
+
function normalizeEnv() {
|
|
198861
|
+
const upperKeys = /* @__PURE__ */ new Map();
|
|
198862
|
+
for (const key of Object.keys(process.env)) {
|
|
198863
|
+
const upper2 = key.toUpperCase();
|
|
198864
|
+
const existing = upperKeys.get(upper2) || [];
|
|
198865
|
+
existing.push(key);
|
|
198866
|
+
upperKeys.set(upper2, existing);
|
|
198867
|
+
}
|
|
198868
|
+
for (const [upperKey, keys] of upperKeys) {
|
|
198869
|
+
if (keys.length === 1) {
|
|
198870
|
+
const key = keys[0];
|
|
198871
|
+
if (key !== upperKey) {
|
|
198872
|
+
process.env[upperKey] = process.env[key];
|
|
198873
|
+
delete process.env[key];
|
|
198874
|
+
}
|
|
198875
|
+
continue;
|
|
198876
|
+
}
|
|
198877
|
+
const values = keys.map((k2) => process.env[k2]);
|
|
198878
|
+
const uniqueValues = new Set(values);
|
|
198879
|
+
if (uniqueValues.size > 1) {
|
|
198880
|
+
log2.warning(
|
|
198881
|
+
`env var conflict: ${keys.join(", ")} have different values. using uppercase ${upperKey}.`
|
|
198882
|
+
);
|
|
198883
|
+
}
|
|
198884
|
+
const preferredKey = keys.find((k2) => k2 === upperKey) || keys[0];
|
|
198885
|
+
const preferredValue = process.env[preferredKey];
|
|
198886
|
+
for (const key of keys) {
|
|
198887
|
+
delete process.env[key];
|
|
198888
|
+
}
|
|
198889
|
+
process.env[upperKey] = preferredValue;
|
|
198890
|
+
}
|
|
198891
|
+
for (const key of Object.keys(process.env)) {
|
|
198892
|
+
if (!isSensitiveEnvName(key)) continue;
|
|
198893
|
+
const value2 = process.env[key];
|
|
198894
|
+
if (typeof value2 !== "string" || value2.length === 0) continue;
|
|
198895
|
+
const sanitized = sanitizeSecret(key, value2);
|
|
198896
|
+
if (sanitized !== null) process.env[key] = sanitized;
|
|
198897
|
+
}
|
|
198898
|
+
}
|
|
198899
|
+
|
|
199140
198900
|
// utils/overrides.ts
|
|
199141
198901
|
var DENIED_OVERRIDE_NAMES = /* @__PURE__ */ new Set([
|
|
199142
198902
|
"GITHUB_TOKEN",
|
|
@@ -200091,8 +199851,7 @@ async function fetchRunContext(params) {
|
|
|
200091
199851
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
200092
199852
|
try {
|
|
200093
199853
|
const headers = {
|
|
200094
|
-
Authorization: `Bearer ${params.token}
|
|
200095
|
-
"X-Pullfrog-Credential-Pools": "1"
|
|
199854
|
+
Authorization: `Bearer ${params.token}`
|
|
200096
199855
|
};
|
|
200097
199856
|
if (params.oidcToken) {
|
|
200098
199857
|
headers["X-GitHub-OIDC-Token"] = params.oidcToken;
|
|
@@ -201362,7 +201121,6 @@ async function main() {
|
|
|
201362
201121
|
const preIntrospectionDirty = repoDir ? await dirtyTrackedPaths({ cwd: repoDir }) : null;
|
|
201363
201122
|
const opencodeCliPath = await agents.opencode.install();
|
|
201364
201123
|
captureBaselineModels(opencodeCliPath);
|
|
201365
|
-
await initializeCredentialPool(runContext, resolveModel({ slug: payload.model }));
|
|
201366
201124
|
if (runContext.dbSecrets) {
|
|
201367
201125
|
for (const [key, value2] of Object.entries(runContext.dbSecrets)) {
|
|
201368
201126
|
if (!process.env[key]) {
|
|
@@ -201446,27 +201204,14 @@ async function main() {
|
|
|
201446
201204
|
}
|
|
201447
201205
|
const gitAuthServer = __using(_stack2, await startGitAuthServer(tmpdir4), true);
|
|
201448
201206
|
setGitAuthServer(gitAuthServer);
|
|
201449
|
-
let configuredModel = resolveModel({ slug: payload.model });
|
|
201450
|
-
if (!configuredModel && !payload.proxyModel && runContext.credentialAccess?.candidates.length) {
|
|
201451
|
-
configuredModel = resolvePoolModel({
|
|
201452
|
-
codexAgent: runContext.repoSettings.codexAgent || payload.codexArm === true
|
|
201453
|
-
});
|
|
201454
|
-
}
|
|
201455
|
-
let poolSelected = !payload.proxyModel && await selectConfiguredCredential({
|
|
201456
|
-
ctx: runContext,
|
|
201457
|
-
model: configuredModel
|
|
201458
|
-
});
|
|
201459
201207
|
const access = decideModelAccess({
|
|
201460
201208
|
modelExplicit: payload.modelExplicit ?? false,
|
|
201461
201209
|
model: payload.model,
|
|
201462
201210
|
oss: runContext.oss,
|
|
201463
201211
|
proxyActive: !!payload.proxyModel,
|
|
201464
201212
|
subsidyTarget: runContext.proxyModel,
|
|
201465
|
-
resolvedModel:
|
|
201466
|
-
authorized:
|
|
201467
|
-
...getAuthorizedModels(),
|
|
201468
|
-
...poolSelected && configuredModel ? [configuredModel] : []
|
|
201469
|
-
])
|
|
201213
|
+
resolvedModel: resolveModel({ slug: payload.model }),
|
|
201214
|
+
authorized: getAuthorizedModels()
|
|
201470
201215
|
});
|
|
201471
201216
|
if (access.kind === "error") {
|
|
201472
201217
|
throw new Error(
|
|
@@ -201479,25 +201224,12 @@ async function main() {
|
|
|
201479
201224
|
);
|
|
201480
201225
|
}
|
|
201481
201226
|
if (access.kind === "proxy") payload.proxyModel = access.target;
|
|
201482
|
-
if (access.kind === "byok")
|
|
201483
|
-
payload.proxyModel = void 0;
|
|
201484
|
-
if (!poolSelected)
|
|
201485
|
-
poolSelected = await selectConfiguredCredential({
|
|
201486
|
-
ctx: runContext,
|
|
201487
|
-
model: configuredModel
|
|
201488
|
-
});
|
|
201489
|
-
}
|
|
201490
|
-
if (poolSelected) {
|
|
201491
|
-
const before = repoDir ? await dirtyTrackedPaths({ cwd: repoDir }) : null;
|
|
201492
|
-
captureAuthorizedModels(opencodeCliPath);
|
|
201493
|
-
if (before && repoDir)
|
|
201494
|
-
await restoreDirtiedSince({ before, actor: "model introspection", cwd: repoDir });
|
|
201495
|
-
}
|
|
201227
|
+
if (access.kind === "byok") payload.proxyModel = void 0;
|
|
201496
201228
|
if (runContext.oss && payload.proxyModel) {
|
|
201497
201229
|
payload.effort = ossEffortFloor({ payload });
|
|
201498
201230
|
}
|
|
201499
|
-
|
|
201500
|
-
const credentials = payload.proxyModel
|
|
201231
|
+
const configuredModel = payload.proxyModel ? void 0 : resolveModel({ slug: payload.model });
|
|
201232
|
+
const credentials = payload.proxyModel ? { kind: "ok" } : await checkConfiguredCredentials({
|
|
201501
201233
|
model: configuredModel,
|
|
201502
201234
|
authorized: getAuthorizedModels()
|
|
201503
201235
|
});
|
|
@@ -201828,12 +201560,12 @@ ${instructions.user}` : null,
|
|
|
201828
201560
|
if (payload.timeout === TIMEOUT_DISABLED) {
|
|
201829
201561
|
result = await Promise.race([agentPromise, activityTimeout.promise]);
|
|
201830
201562
|
} else {
|
|
201831
|
-
const
|
|
201832
|
-
if (payload.timeout &&
|
|
201563
|
+
const usable = resolveTimeoutMs(payload.timeout);
|
|
201564
|
+
if (payload.timeout && usable === null) {
|
|
201833
201565
|
log2.warning(`invalid timeout "${payload.timeout}" (use --notimeout to disable), using 1h`);
|
|
201834
201566
|
}
|
|
201835
|
-
const timeoutMs =
|
|
201836
|
-
const actualTimeout =
|
|
201567
|
+
const timeoutMs = usable ?? 36e5;
|
|
201568
|
+
const actualTimeout = usable !== null ? payload.timeout : "1h";
|
|
201837
201569
|
let timeoutId;
|
|
201838
201570
|
const timeoutPromise = new Promise((_4, reject) => {
|
|
201839
201571
|
timeoutId = setTimeout(() => {
|
|
@@ -202461,7 +202193,7 @@ function resolveTarget2(repo) {
|
|
|
202461
202193
|
return { owner: match3[1], repo: match3[2] };
|
|
202462
202194
|
}
|
|
202463
202195
|
function cliVersion() {
|
|
202464
|
-
const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.
|
|
202196
|
+
const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.86");
|
|
202465
202197
|
if (!parts) return "0.0.0";
|
|
202466
202198
|
return `${Number(parts[1])}.${Number(parts[2])}.${Number(parts[3])}`;
|
|
202467
202199
|
}
|
|
@@ -202628,7 +202360,7 @@ async function runCli8(input) {
|
|
|
202628
202360
|
}
|
|
202629
202361
|
|
|
202630
202362
|
// cli.ts
|
|
202631
|
-
var VERSION10 = "0.1.
|
|
202363
|
+
var VERSION10 = "0.1.86";
|
|
202632
202364
|
var bin = basename2(process.argv[1] || "");
|
|
202633
202365
|
var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
|
|
202634
202366
|
var rawArgs = process.argv.slice(2);
|
package/dist/index.js
CHANGED
|
@@ -83904,7 +83904,7 @@ var require_Element = __commonJS({
|
|
|
83904
83904
|
var FilteredElementList = require_FilteredElementList();
|
|
83905
83905
|
var DOMException2 = require_DOMException();
|
|
83906
83906
|
var DOMTokenList = require_DOMTokenList();
|
|
83907
|
-
var
|
|
83907
|
+
var select = require_select();
|
|
83908
83908
|
var ContainerNode = require_ContainerNode();
|
|
83909
83909
|
var ChildNode = require_ChildNode();
|
|
83910
83910
|
var NonDocumentTypeChildNode = require_NonDocumentTypeChildNode();
|
|
@@ -84665,7 +84665,7 @@ var require_Element = __commonJS({
|
|
|
84665
84665
|
this.className = v;
|
|
84666
84666
|
} },
|
|
84667
84667
|
matches: { value: function(selector) {
|
|
84668
|
-
return
|
|
84668
|
+
return select.matches(this, selector);
|
|
84669
84669
|
} },
|
|
84670
84670
|
closest: { value: function(selector) {
|
|
84671
84671
|
var el = this;
|
|
@@ -84678,10 +84678,10 @@ var require_Element = __commonJS({
|
|
|
84678
84678
|
return null;
|
|
84679
84679
|
} },
|
|
84680
84680
|
querySelector: { value: function(selector) {
|
|
84681
|
-
return
|
|
84681
|
+
return select(selector, this)[0];
|
|
84682
84682
|
} },
|
|
84683
84683
|
querySelectorAll: { value: function(selector) {
|
|
84684
|
-
var nodes =
|
|
84684
|
+
var nodes = select(selector, this);
|
|
84685
84685
|
return nodes.item ? nodes : new NodeList(nodes);
|
|
84686
84686
|
} }
|
|
84687
84687
|
});
|
|
@@ -85209,7 +85209,7 @@ var require_DocumentFragment = __commonJS({
|
|
|
85209
85209
|
var NodeList = require_NodeList();
|
|
85210
85210
|
var ContainerNode = require_ContainerNode();
|
|
85211
85211
|
var Element = require_Element();
|
|
85212
|
-
var
|
|
85212
|
+
var select = require_select();
|
|
85213
85213
|
var utils = require_utils8();
|
|
85214
85214
|
function DocumentFragment(doc) {
|
|
85215
85215
|
ContainerNode.call(this);
|
|
@@ -85238,7 +85238,7 @@ var require_DocumentFragment = __commonJS({
|
|
|
85238
85238
|
context.isHTML = true;
|
|
85239
85239
|
context.getElementsByTagName = Element.prototype.getElementsByTagName;
|
|
85240
85240
|
context.nextElement = Object.getOwnPropertyDescriptor(Element.prototype, "firstElementChild").get;
|
|
85241
|
-
var nodes =
|
|
85241
|
+
var nodes = select(selector, context);
|
|
85242
85242
|
return nodes.item ? nodes : new NodeList(nodes);
|
|
85243
85243
|
} },
|
|
85244
85244
|
// Utility methods
|
|
@@ -88353,7 +88353,7 @@ var require_Document = __commonJS({
|
|
|
88353
88353
|
var NodeIterator = require_NodeIterator();
|
|
88354
88354
|
var NodeFilter = require_NodeFilter();
|
|
88355
88355
|
var URL2 = require_URL();
|
|
88356
|
-
var
|
|
88356
|
+
var select = require_select();
|
|
88357
88357
|
var events = require_events3();
|
|
88358
88358
|
var xml = require_xmlnames();
|
|
88359
88359
|
var html = require_htmlelts();
|
|
@@ -88914,10 +88914,10 @@ var require_Document = __commonJS({
|
|
|
88914
88914
|
return this._templateDocCache;
|
|
88915
88915
|
} },
|
|
88916
88916
|
querySelector: { value: function(selector) {
|
|
88917
|
-
return
|
|
88917
|
+
return select(selector, this)[0];
|
|
88918
88918
|
} },
|
|
88919
88919
|
querySelectorAll: { value: function(selector) {
|
|
88920
|
-
var nodes =
|
|
88920
|
+
var nodes = select(selector, this);
|
|
88921
88921
|
return nodes.item ? nodes : new NodeList(nodes);
|
|
88922
88922
|
} }
|
|
88923
88923
|
});
|
|
@@ -104596,8 +104596,8 @@ var providers = {
|
|
|
104596
104596
|
},
|
|
104597
104597
|
"claude-sonnet": {
|
|
104598
104598
|
displayName: "Claude Sonnet",
|
|
104599
|
-
resolve: "vercel/anthropic/claude-sonnet-5",
|
|
104600
|
-
effort: ["
|
|
104599
|
+
resolve: "vercel/anthropic/claude-sonnet-5.5",
|
|
104600
|
+
effort: ["low", "medium", "high", "xhigh", "max"]
|
|
104601
104601
|
},
|
|
104602
104602
|
"claude-haiku": {
|
|
104603
104603
|
displayName: "Claude Haiku",
|
|
@@ -105723,7 +105723,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
105723
105723
|
// package.json
|
|
105724
105724
|
var package_default = {
|
|
105725
105725
|
name: "pullfrog",
|
|
105726
|
-
version: "0.1.
|
|
105726
|
+
version: "0.1.86",
|
|
105727
105727
|
cliContractVersion: "1",
|
|
105728
105728
|
type: "module",
|
|
105729
105729
|
bin: {
|
|
@@ -107995,17 +107995,6 @@ function parseXaiAuthBody(raw2) {
|
|
|
107995
107995
|
var CODEX_AUTH_ENV = "CODEX_AUTH_JSON";
|
|
107996
107996
|
var XAI_AUTH_ENV = "GROK_AUTH_JSON";
|
|
107997
107997
|
var installedSubscriptionPaths = /* @__PURE__ */ new Map();
|
|
107998
|
-
function clearInstalledSubscription(name) {
|
|
107999
|
-
const path4 = installedSubscriptionPaths.get(name);
|
|
108000
|
-
if (!path4 || !existsSync4(path4)) return;
|
|
108001
|
-
const value2 = JSON.parse(readFileSync2(path4, "utf8"));
|
|
108002
|
-
if (!value2 || typeof value2 !== "object") return;
|
|
108003
|
-
if (name === "CODEX_AUTH_JSON" && "openai" in value2) delete value2.openai;
|
|
108004
|
-
if (name === "GROK_AUTH_JSON" && "xai" in value2) delete value2.xai;
|
|
108005
|
-
writeFileSync4(path4, `${JSON.stringify(value2)}
|
|
108006
|
-
`, { mode: 384 });
|
|
108007
|
-
installedSubscriptionPaths.delete(name);
|
|
108008
|
-
}
|
|
108009
107998
|
var PULLFROG_DATA_DIR = "/var/lib/pullfrog";
|
|
108010
107999
|
function isRejectedChain(body) {
|
|
108011
108000
|
if (!body.refresh_rejected_at) return false;
|
|
@@ -194629,344 +194618,6 @@ async function checkConfiguredCredentials(params) {
|
|
|
194629
194618
|
return replacement ? { kind: "fellBack", ...outcome, replacement } : { kind: "dead", ...outcome };
|
|
194630
194619
|
}
|
|
194631
194620
|
|
|
194632
|
-
// utils/normalizeEnv.ts
|
|
194633
|
-
function hasControlCharacter(value2) {
|
|
194634
|
-
return [...value2].some((ch) => {
|
|
194635
|
-
const code = ch.charCodeAt(0);
|
|
194636
|
-
return code < 32 || code === 127;
|
|
194637
|
-
});
|
|
194638
|
-
}
|
|
194639
|
-
function sanitizeSecret(key, value2) {
|
|
194640
|
-
const trimmed = value2.trim();
|
|
194641
|
-
if (trimmed.length === 0) {
|
|
194642
|
-
log.warning(
|
|
194643
|
-
`\xBB ${key} is whitespace-only \u2014 leaving env var unchanged. check your secret value.`
|
|
194644
|
-
);
|
|
194645
|
-
return null;
|
|
194646
|
-
}
|
|
194647
|
-
if (key.endsWith("_API_KEY") && hasControlCharacter(trimmed)) {
|
|
194648
|
-
log.warning(
|
|
194649
|
-
`\xBB ${key} contains a line break or control character and cannot be sent as an HTTP header \u2014 leaving env var unchanged. re-save the secret as a single line.`
|
|
194650
|
-
);
|
|
194651
|
-
return null;
|
|
194652
|
-
}
|
|
194653
|
-
if (trimmed !== value2) {
|
|
194654
|
-
log.warning(
|
|
194655
|
-
`\xBB stripped whitespace from ${key} (whitespace in secret values breaks GitHub Actions log masking)`
|
|
194656
|
-
);
|
|
194657
|
-
}
|
|
194658
|
-
maskSecret(trimmed);
|
|
194659
|
-
return trimmed;
|
|
194660
|
-
}
|
|
194661
|
-
function normalizeEnv() {
|
|
194662
|
-
const upperKeys = /* @__PURE__ */ new Map();
|
|
194663
|
-
for (const key of Object.keys(process.env)) {
|
|
194664
|
-
const upper2 = key.toUpperCase();
|
|
194665
|
-
const existing = upperKeys.get(upper2) || [];
|
|
194666
|
-
existing.push(key);
|
|
194667
|
-
upperKeys.set(upper2, existing);
|
|
194668
|
-
}
|
|
194669
|
-
for (const [upperKey, keys] of upperKeys) {
|
|
194670
|
-
if (keys.length === 1) {
|
|
194671
|
-
const key = keys[0];
|
|
194672
|
-
if (key !== upperKey) {
|
|
194673
|
-
process.env[upperKey] = process.env[key];
|
|
194674
|
-
delete process.env[key];
|
|
194675
|
-
}
|
|
194676
|
-
continue;
|
|
194677
|
-
}
|
|
194678
|
-
const values = keys.map((k2) => process.env[k2]);
|
|
194679
|
-
const uniqueValues = new Set(values);
|
|
194680
|
-
if (uniqueValues.size > 1) {
|
|
194681
|
-
log.warning(
|
|
194682
|
-
`env var conflict: ${keys.join(", ")} have different values. using uppercase ${upperKey}.`
|
|
194683
|
-
);
|
|
194684
|
-
}
|
|
194685
|
-
const preferredKey = keys.find((k2) => k2 === upperKey) || keys[0];
|
|
194686
|
-
const preferredValue = process.env[preferredKey];
|
|
194687
|
-
for (const key of keys) {
|
|
194688
|
-
delete process.env[key];
|
|
194689
|
-
}
|
|
194690
|
-
process.env[upperKey] = preferredValue;
|
|
194691
|
-
}
|
|
194692
|
-
for (const key of Object.keys(process.env)) {
|
|
194693
|
-
if (!isSensitiveEnvName(key)) continue;
|
|
194694
|
-
const value2 = process.env[key];
|
|
194695
|
-
if (typeof value2 !== "string" || value2.length === 0) continue;
|
|
194696
|
-
const sanitized = sanitizeSecret(key, value2);
|
|
194697
|
-
if (sanitized !== null) process.env[key] = sanitized;
|
|
194698
|
-
}
|
|
194699
|
-
}
|
|
194700
|
-
|
|
194701
|
-
// utils/subscriptionCredentials.ts
|
|
194702
|
-
var subscriptionNameSchema = external_exports.enum([
|
|
194703
|
-
"CLAUDE_CODE_OAUTH_TOKEN",
|
|
194704
|
-
"CODEX_AUTH_JSON",
|
|
194705
|
-
"GROK_AUTH_JSON"
|
|
194706
|
-
]);
|
|
194707
|
-
var subscriptionSchema = external_exports.object({
|
|
194708
|
-
id: external_exports.string(),
|
|
194709
|
-
credentialId: external_exports.string(),
|
|
194710
|
-
name: subscriptionNameSchema,
|
|
194711
|
-
label: external_exports.string(),
|
|
194712
|
-
owner: external_exports.string(),
|
|
194713
|
-
inherited: external_exports.boolean(),
|
|
194714
|
-
shared: external_exports.boolean(),
|
|
194715
|
-
registeredAt: external_exports.string()
|
|
194716
|
-
});
|
|
194717
|
-
var subscriptionListSchema = external_exports.object({
|
|
194718
|
-
subscriptions: external_exports.array(subscriptionSchema),
|
|
194719
|
-
writable: external_exports.boolean()
|
|
194720
|
-
});
|
|
194721
|
-
var subscriptionInputSchema = external_exports.object({
|
|
194722
|
-
name: subscriptionNameSchema,
|
|
194723
|
-
value: external_exports.string().trim().min(1).refine((value2) => Buffer.byteLength(value2, "utf8") <= 49152),
|
|
194724
|
-
replaceId: external_exports.string().optional()
|
|
194725
|
-
});
|
|
194726
|
-
var credentialCandidateSchema = external_exports.object({
|
|
194727
|
-
id: external_exports.string(),
|
|
194728
|
-
name: external_exports.string(),
|
|
194729
|
-
source: external_exports.enum(["repo", "account", "personal"])
|
|
194730
|
-
});
|
|
194731
|
-
var credentialAccessSchema = external_exports.object({
|
|
194732
|
-
token: external_exports.string(),
|
|
194733
|
-
candidates: external_exports.array(credentialCandidateSchema)
|
|
194734
|
-
});
|
|
194735
|
-
var selectedCredentialSchema = external_exports.object({
|
|
194736
|
-
name: external_exports.string(),
|
|
194737
|
-
value: external_exports.string(),
|
|
194738
|
-
receipt: external_exports.string()
|
|
194739
|
-
});
|
|
194740
|
-
|
|
194741
|
-
// utils/subscriptionProbe.ts
|
|
194742
|
-
var identitySchema = external_exports.object({
|
|
194743
|
-
email: external_exports.string().email().optional(),
|
|
194744
|
-
sub: external_exports.string().optional(),
|
|
194745
|
-
user_id: external_exports.string().optional(),
|
|
194746
|
-
account_id: external_exports.string().optional(),
|
|
194747
|
-
email_verified: external_exports.boolean().optional()
|
|
194748
|
-
});
|
|
194749
|
-
var codexUsageSchema = external_exports.object({
|
|
194750
|
-
rate_limit: external_exports.object({ allowed: external_exports.boolean(), limit_reached: external_exports.boolean() }).optional()
|
|
194751
|
-
});
|
|
194752
|
-
async function readSubscriptionEndpoint(input) {
|
|
194753
|
-
const headers = new Headers({ authorization: `Bearer ${input.token}` });
|
|
194754
|
-
if (input.accountId) headers.set("ChatGPT-Account-Id", input.accountId);
|
|
194755
|
-
if (input.grokBilling) headers.set("x-xai-token-auth", "xai-grok-cli");
|
|
194756
|
-
return fetch(input.url, {
|
|
194757
|
-
headers,
|
|
194758
|
-
redirect: "error",
|
|
194759
|
-
signal: AbortSignal.timeout(1e4)
|
|
194760
|
-
}).catch(() => null);
|
|
194761
|
-
}
|
|
194762
|
-
async function probeSubscription(input) {
|
|
194763
|
-
if (input.name === "CLAUDE_CODE_OAUTH_TOKEN") {
|
|
194764
|
-
const result = await preflightClaudeSubscription({ token: input.value, model: input.model });
|
|
194765
|
-
return result.usable ? "usable" : "rejected";
|
|
194766
|
-
}
|
|
194767
|
-
const codex2 = input.name === "CODEX_AUTH_JSON" ? parseCodexAuthBody(input.value) : null;
|
|
194768
|
-
const grok = input.name === "GROK_AUTH_JSON" ? parseXaiAuthBody(input.value) : null;
|
|
194769
|
-
const auth2 = codex2 ?? grok;
|
|
194770
|
-
if (!auth2 || auth2.refresh_rejected_at) return "rejected";
|
|
194771
|
-
if (grok && input.model)
|
|
194772
|
-
return probeInference({
|
|
194773
|
-
name: "XAI_API_KEY",
|
|
194774
|
-
value: grok.tokens.access_token,
|
|
194775
|
-
model: input.model
|
|
194776
|
-
});
|
|
194777
|
-
const response = await readSubscriptionEndpoint({
|
|
194778
|
-
url: codex2 ? "https://chatgpt.com/backend-api/wham/usage" : "https://cli-chat-proxy.grok.com/v1/billing?format=credits",
|
|
194779
|
-
token: auth2.tokens.access_token,
|
|
194780
|
-
accountId: codex2?.tokens.account_id,
|
|
194781
|
-
grokBilling: !!grok
|
|
194782
|
-
});
|
|
194783
|
-
if (response?.status === 401) return "rejected";
|
|
194784
|
-
if (!response?.ok) return "unknown";
|
|
194785
|
-
const body = await response.json().catch(() => null);
|
|
194786
|
-
if (codex2) {
|
|
194787
|
-
const parsed2 = codexUsageSchema.safeParse(body);
|
|
194788
|
-
const limit = parsed2.success ? parsed2.data.rate_limit : void 0;
|
|
194789
|
-
if (!limit) return "unknown";
|
|
194790
|
-
return limit.allowed && !limit.limit_reached ? "usable" : "rejected";
|
|
194791
|
-
}
|
|
194792
|
-
return "unknown";
|
|
194793
|
-
}
|
|
194794
|
-
async function probeInference(input) {
|
|
194795
|
-
const anthropic = input.name === "ANTHROPIC_API_KEY";
|
|
194796
|
-
const openai = input.name === "OPENAI_API_KEY";
|
|
194797
|
-
if (!anthropic && !openai && input.name !== "XAI_API_KEY") {
|
|
194798
|
-
const result = await verifyCredential({ envVar: input.name, value: input.value });
|
|
194799
|
-
return result === "dead" ? "rejected" : result === "alive" ? "usable" : "unknown";
|
|
194800
|
-
}
|
|
194801
|
-
const headers = new Headers({ "content-type": "application/json" });
|
|
194802
|
-
if (anthropic) {
|
|
194803
|
-
headers.set("x-api-key", input.value);
|
|
194804
|
-
headers.set("anthropic-version", "2023-06-01");
|
|
194805
|
-
} else headers.set("authorization", `Bearer ${input.value}`);
|
|
194806
|
-
const response = await fetch(
|
|
194807
|
-
anthropic ? "https://api.anthropic.com/v1/messages" : openai ? "https://api.openai.com/v1/responses" : "https://api.x.ai/v1/chat/completions",
|
|
194808
|
-
{
|
|
194809
|
-
method: "POST",
|
|
194810
|
-
headers,
|
|
194811
|
-
body: JSON.stringify(
|
|
194812
|
-
openai ? { model: input.model, input: "Reply OK.", max_output_tokens: 16, store: false } : {
|
|
194813
|
-
model: input.model,
|
|
194814
|
-
messages: [{ role: "user", content: "Reply OK." }],
|
|
194815
|
-
max_tokens: 1
|
|
194816
|
-
}
|
|
194817
|
-
),
|
|
194818
|
-
redirect: "error",
|
|
194819
|
-
signal: AbortSignal.timeout(1e4)
|
|
194820
|
-
}
|
|
194821
|
-
).catch(() => null);
|
|
194822
|
-
if (response?.status === 400 && input.name === "XAI_API_KEY") {
|
|
194823
|
-
const error49 = external_exports.object({ error: external_exports.string() }).safeParse(await response.json().catch(() => null));
|
|
194824
|
-
return error49.success && error49.data.error.startsWith("Incorrect API key provided.") ? "rejected" : "unknown";
|
|
194825
|
-
}
|
|
194826
|
-
await response?.body?.cancel();
|
|
194827
|
-
if (!response) return "unknown";
|
|
194828
|
-
if (response.ok) return "usable";
|
|
194829
|
-
return [401, 402, 403, 429].includes(response.status) ? "rejected" : "unknown";
|
|
194830
|
-
}
|
|
194831
|
-
|
|
194832
|
-
// utils/credentialPool.ts
|
|
194833
|
-
var receipts = {};
|
|
194834
|
-
var workflowCredentials = {};
|
|
194835
|
-
function saveReceipts() {
|
|
194836
|
-
for (const receipt of Object.values(receipts)) maskSecret(receipt);
|
|
194837
|
-
saveSecretState("credential_receipts", JSON.stringify(receipts));
|
|
194838
|
-
}
|
|
194839
|
-
var select = op(
|
|
194840
|
-
async (input) => {
|
|
194841
|
-
const response = await apiFetch({
|
|
194842
|
-
path: "/api/runtime/credentials",
|
|
194843
|
-
method: "POST",
|
|
194844
|
-
headers: {
|
|
194845
|
-
authorization: `Bearer ${input.access.token}`,
|
|
194846
|
-
"content-type": "application/json"
|
|
194847
|
-
},
|
|
194848
|
-
body: JSON.stringify({ id: input.candidate.id }),
|
|
194849
|
-
signal: AbortSignal.timeout(35e3)
|
|
194850
|
-
});
|
|
194851
|
-
if (response.status === 404) return null;
|
|
194852
|
-
if (!response.ok)
|
|
194853
|
-
throw new Error("could not load a configured credential; no fallback was charged", {
|
|
194854
|
-
cause: response.status
|
|
194855
|
-
});
|
|
194856
|
-
return selectedCredentialSchema.parse(await response.json());
|
|
194857
|
-
},
|
|
194858
|
-
{
|
|
194859
|
-
retries: [250, 1e3],
|
|
194860
|
-
bail: (error49) => error49 instanceof Error && typeof error49.cause === "number" && error49.cause >= 400 && error49.cause < 500
|
|
194861
|
-
}
|
|
194862
|
-
);
|
|
194863
|
-
function subscriptionForModel(model) {
|
|
194864
|
-
if (!model.includes("/")) return null;
|
|
194865
|
-
const provider2 = getModelProvider(model);
|
|
194866
|
-
return provider2 === "anthropic" ? "CLAUDE_CODE_OAUTH_TOKEN" : provider2 === "openai" ? "CODEX_AUTH_JSON" : provider2 === "xai" ? "GROK_AUTH_JSON" : null;
|
|
194867
|
-
}
|
|
194868
|
-
async function initializeCredentialPool(ctx, model) {
|
|
194869
|
-
const access = ctx.credentialAccess;
|
|
194870
|
-
if (!access) return;
|
|
194871
|
-
maskSecret(access.token);
|
|
194872
|
-
const names = /* @__PURE__ */ new Set([
|
|
194873
|
-
...access.candidates.map((candidate) => candidate.name),
|
|
194874
|
-
...subscriptionNameSchema.options,
|
|
194875
|
-
"ANTHROPIC_API_KEY",
|
|
194876
|
-
"OPENAI_API_KEY",
|
|
194877
|
-
"XAI_API_KEY"
|
|
194878
|
-
]);
|
|
194879
|
-
for (const name of names) {
|
|
194880
|
-
const value2 = process.env[name];
|
|
194881
|
-
if (value2) workflowCredentials[name] = value2;
|
|
194882
|
-
}
|
|
194883
|
-
for (const name of subscriptionNameSchema.options) {
|
|
194884
|
-
if (model && subscriptionForModel(model) !== name) continue;
|
|
194885
|
-
if (workflowCredentials[name]) continue;
|
|
194886
|
-
const candidate = access.candidates.find((item) => item.name === name);
|
|
194887
|
-
if (!candidate) continue;
|
|
194888
|
-
const selected = await select({ access, candidate }).catch(() => {
|
|
194889
|
-
log.warning(`\xBB could not load ${name} for model discovery; selection will retry if needed`);
|
|
194890
|
-
return null;
|
|
194891
|
-
});
|
|
194892
|
-
if (!selected) continue;
|
|
194893
|
-
const value2 = sanitizeSecret(name, selected.value);
|
|
194894
|
-
if (!value2) continue;
|
|
194895
|
-
process.env[name] = value2;
|
|
194896
|
-
receipts[name] = selected.receipt;
|
|
194897
|
-
}
|
|
194898
|
-
saveReceipts();
|
|
194899
|
-
}
|
|
194900
|
-
function resolvePoolModel(input) {
|
|
194901
|
-
const agent2 = resolveAgent({
|
|
194902
|
-
model: void 0,
|
|
194903
|
-
proxyModel: void 0,
|
|
194904
|
-
codexAgent: input.codexAgent
|
|
194905
|
-
});
|
|
194906
|
-
if (agent2.name === "opencode") return autoSelectModel();
|
|
194907
|
-
const provider2 = agent2.name === "claude" ? "anthropic" : "openai";
|
|
194908
|
-
return modelAliases.find(
|
|
194909
|
-
(alias) => alias.provider === provider2 && alias.preferred && !alias.hidden && !alias.fallback && !alias.routing
|
|
194910
|
-
)?.resolve;
|
|
194911
|
-
}
|
|
194912
|
-
async function selectConfiguredCredential(input) {
|
|
194913
|
-
const access = input.ctx.credentialAccess;
|
|
194914
|
-
const model = input.model;
|
|
194915
|
-
if (!access || !model?.includes("/") || getProviderGatewayUrl(model)) return false;
|
|
194916
|
-
const subscription = subscriptionForModel(model);
|
|
194917
|
-
const names = getModelEnvVars(model).filter((name) => name !== subscription);
|
|
194918
|
-
if (subscription) names.unshift(subscription);
|
|
194919
|
-
const candidates = access.candidates.filter((candidate) => names.includes(candidate.name));
|
|
194920
|
-
const workflow = names.filter((name) => workflowCredentials[name]);
|
|
194921
|
-
if (!candidates.length && !workflow.length) return false;
|
|
194922
|
-
for (const name of workflow) {
|
|
194923
|
-
const value2 = workflowCredentials[name];
|
|
194924
|
-
if (await usable({ name, value: value2, model })) {
|
|
194925
|
-
activate({ names, name, value: value2, receipt: void 0 });
|
|
194926
|
-
return true;
|
|
194927
|
-
}
|
|
194928
|
-
}
|
|
194929
|
-
for (const candidate of candidates) {
|
|
194930
|
-
const selected = await select({ access, candidate });
|
|
194931
|
-
if (!selected) continue;
|
|
194932
|
-
if (await usable({ ...selected, model })) {
|
|
194933
|
-
activate({ names, ...selected });
|
|
194934
|
-
log.info(`\xBB selected ${candidate.name} from ${candidate.source} scope`);
|
|
194935
|
-
return true;
|
|
194936
|
-
}
|
|
194937
|
-
log.info(
|
|
194938
|
-
`\xBB ${candidate.name} from ${candidate.source} scope unavailable; trying the next credential`
|
|
194939
|
-
);
|
|
194940
|
-
}
|
|
194941
|
-
throw new Error(
|
|
194942
|
-
`all configured credentials for ${model} were rejected or exhausted; no other model or provider was selected`
|
|
194943
|
-
);
|
|
194944
|
-
}
|
|
194945
|
-
async function usable(input) {
|
|
194946
|
-
const subscription = subscriptionNameSchema.safeParse(input.name);
|
|
194947
|
-
if (subscription.success)
|
|
194948
|
-
return await probeSubscription({
|
|
194949
|
-
name: subscription.data,
|
|
194950
|
-
value: input.value,
|
|
194951
|
-
model: stripProviderPrefix(input.model)
|
|
194952
|
-
}) !== "rejected";
|
|
194953
|
-
return await probeInference({ ...input, model: stripProviderPrefix(input.model) }) !== "rejected";
|
|
194954
|
-
}
|
|
194955
|
-
function activate(input) {
|
|
194956
|
-
for (const name of input.names) {
|
|
194957
|
-
delete process.env[name];
|
|
194958
|
-
delete receipts[name];
|
|
194959
|
-
if (name === "CODEX_AUTH_JSON" || name === "GROK_AUTH_JSON") clearInstalledSubscription(name);
|
|
194960
|
-
}
|
|
194961
|
-
const value2 = sanitizeSecret(input.name, input.value);
|
|
194962
|
-
if (!value2) throw new Error("configured credential was empty");
|
|
194963
|
-
process.env[input.name] = value2;
|
|
194964
|
-
if (input.receipt) receipts[input.name] = input.receipt;
|
|
194965
|
-
installCodexAuth();
|
|
194966
|
-
installXaiAuth();
|
|
194967
|
-
saveReceipts();
|
|
194968
|
-
}
|
|
194969
|
-
|
|
194970
194621
|
// utils/gitAuthServer.ts
|
|
194971
194622
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
194972
194623
|
import { writeFileSync as writeFileSync14 } from "node:fs";
|
|
@@ -195670,6 +195321,75 @@ function buildModelAccessError(input) {
|
|
|
195670
195321
|
return [headline, "", why, "", cta].join("\n");
|
|
195671
195322
|
}
|
|
195672
195323
|
|
|
195324
|
+
// utils/normalizeEnv.ts
|
|
195325
|
+
function hasControlCharacter(value2) {
|
|
195326
|
+
return [...value2].some((ch) => {
|
|
195327
|
+
const code = ch.charCodeAt(0);
|
|
195328
|
+
return code < 32 || code === 127;
|
|
195329
|
+
});
|
|
195330
|
+
}
|
|
195331
|
+
function sanitizeSecret(key, value2) {
|
|
195332
|
+
const trimmed = value2.trim();
|
|
195333
|
+
if (trimmed.length === 0) {
|
|
195334
|
+
log.warning(
|
|
195335
|
+
`\xBB ${key} is whitespace-only \u2014 leaving env var unchanged. check your secret value.`
|
|
195336
|
+
);
|
|
195337
|
+
return null;
|
|
195338
|
+
}
|
|
195339
|
+
if (key.endsWith("_API_KEY") && hasControlCharacter(trimmed)) {
|
|
195340
|
+
log.warning(
|
|
195341
|
+
`\xBB ${key} contains a line break or control character and cannot be sent as an HTTP header \u2014 leaving env var unchanged. re-save the secret as a single line.`
|
|
195342
|
+
);
|
|
195343
|
+
return null;
|
|
195344
|
+
}
|
|
195345
|
+
if (trimmed !== value2) {
|
|
195346
|
+
log.warning(
|
|
195347
|
+
`\xBB stripped whitespace from ${key} (whitespace in secret values breaks GitHub Actions log masking)`
|
|
195348
|
+
);
|
|
195349
|
+
}
|
|
195350
|
+
maskSecret(trimmed);
|
|
195351
|
+
return trimmed;
|
|
195352
|
+
}
|
|
195353
|
+
function normalizeEnv() {
|
|
195354
|
+
const upperKeys = /* @__PURE__ */ new Map();
|
|
195355
|
+
for (const key of Object.keys(process.env)) {
|
|
195356
|
+
const upper2 = key.toUpperCase();
|
|
195357
|
+
const existing = upperKeys.get(upper2) || [];
|
|
195358
|
+
existing.push(key);
|
|
195359
|
+
upperKeys.set(upper2, existing);
|
|
195360
|
+
}
|
|
195361
|
+
for (const [upperKey, keys] of upperKeys) {
|
|
195362
|
+
if (keys.length === 1) {
|
|
195363
|
+
const key = keys[0];
|
|
195364
|
+
if (key !== upperKey) {
|
|
195365
|
+
process.env[upperKey] = process.env[key];
|
|
195366
|
+
delete process.env[key];
|
|
195367
|
+
}
|
|
195368
|
+
continue;
|
|
195369
|
+
}
|
|
195370
|
+
const values = keys.map((k2) => process.env[k2]);
|
|
195371
|
+
const uniqueValues = new Set(values);
|
|
195372
|
+
if (uniqueValues.size > 1) {
|
|
195373
|
+
log.warning(
|
|
195374
|
+
`env var conflict: ${keys.join(", ")} have different values. using uppercase ${upperKey}.`
|
|
195375
|
+
);
|
|
195376
|
+
}
|
|
195377
|
+
const preferredKey = keys.find((k2) => k2 === upperKey) || keys[0];
|
|
195378
|
+
const preferredValue = process.env[preferredKey];
|
|
195379
|
+
for (const key of keys) {
|
|
195380
|
+
delete process.env[key];
|
|
195381
|
+
}
|
|
195382
|
+
process.env[upperKey] = preferredValue;
|
|
195383
|
+
}
|
|
195384
|
+
for (const key of Object.keys(process.env)) {
|
|
195385
|
+
if (!isSensitiveEnvName(key)) continue;
|
|
195386
|
+
const value2 = process.env[key];
|
|
195387
|
+
if (typeof value2 !== "string" || value2.length === 0) continue;
|
|
195388
|
+
const sanitized = sanitizeSecret(key, value2);
|
|
195389
|
+
if (sanitized !== null) process.env[key] = sanitized;
|
|
195390
|
+
}
|
|
195391
|
+
}
|
|
195392
|
+
|
|
195673
195393
|
// utils/overrides.ts
|
|
195674
195394
|
var DENIED_OVERRIDE_NAMES = /* @__PURE__ */ new Set([
|
|
195675
195395
|
"GITHUB_TOKEN",
|
|
@@ -196624,8 +196344,7 @@ async function fetchRunContext(params) {
|
|
|
196624
196344
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
196625
196345
|
try {
|
|
196626
196346
|
const headers = {
|
|
196627
|
-
Authorization: `Bearer ${params.token}
|
|
196628
|
-
"X-Pullfrog-Credential-Pools": "1"
|
|
196347
|
+
Authorization: `Bearer ${params.token}`
|
|
196629
196348
|
};
|
|
196630
196349
|
if (params.oidcToken) {
|
|
196631
196350
|
headers["X-GitHub-OIDC-Token"] = params.oidcToken;
|
|
@@ -197895,7 +197614,6 @@ async function main() {
|
|
|
197895
197614
|
const preIntrospectionDirty = repoDir ? await dirtyTrackedPaths({ cwd: repoDir }) : null;
|
|
197896
197615
|
const opencodeCliPath = await agents.opencode.install();
|
|
197897
197616
|
captureBaselineModels(opencodeCliPath);
|
|
197898
|
-
await initializeCredentialPool(runContext, resolveModel({ slug: payload.model }));
|
|
197899
197617
|
if (runContext.dbSecrets) {
|
|
197900
197618
|
for (const [key, value2] of Object.entries(runContext.dbSecrets)) {
|
|
197901
197619
|
if (!process.env[key]) {
|
|
@@ -197979,27 +197697,14 @@ async function main() {
|
|
|
197979
197697
|
}
|
|
197980
197698
|
const gitAuthServer = __using(_stack2, await startGitAuthServer(tmpdir3), true);
|
|
197981
197699
|
setGitAuthServer(gitAuthServer);
|
|
197982
|
-
let configuredModel = resolveModel({ slug: payload.model });
|
|
197983
|
-
if (!configuredModel && !payload.proxyModel && runContext.credentialAccess?.candidates.length) {
|
|
197984
|
-
configuredModel = resolvePoolModel({
|
|
197985
|
-
codexAgent: runContext.repoSettings.codexAgent || payload.codexArm === true
|
|
197986
|
-
});
|
|
197987
|
-
}
|
|
197988
|
-
let poolSelected = !payload.proxyModel && await selectConfiguredCredential({
|
|
197989
|
-
ctx: runContext,
|
|
197990
|
-
model: configuredModel
|
|
197991
|
-
});
|
|
197992
197700
|
const access = decideModelAccess({
|
|
197993
197701
|
modelExplicit: payload.modelExplicit ?? false,
|
|
197994
197702
|
model: payload.model,
|
|
197995
197703
|
oss: runContext.oss,
|
|
197996
197704
|
proxyActive: !!payload.proxyModel,
|
|
197997
197705
|
subsidyTarget: runContext.proxyModel,
|
|
197998
|
-
resolvedModel:
|
|
197999
|
-
authorized:
|
|
198000
|
-
...getAuthorizedModels(),
|
|
198001
|
-
...poolSelected && configuredModel ? [configuredModel] : []
|
|
198002
|
-
])
|
|
197706
|
+
resolvedModel: resolveModel({ slug: payload.model }),
|
|
197707
|
+
authorized: getAuthorizedModels()
|
|
198003
197708
|
});
|
|
198004
197709
|
if (access.kind === "error") {
|
|
198005
197710
|
throw new Error(
|
|
@@ -198012,25 +197717,12 @@ async function main() {
|
|
|
198012
197717
|
);
|
|
198013
197718
|
}
|
|
198014
197719
|
if (access.kind === "proxy") payload.proxyModel = access.target;
|
|
198015
|
-
if (access.kind === "byok")
|
|
198016
|
-
payload.proxyModel = void 0;
|
|
198017
|
-
if (!poolSelected)
|
|
198018
|
-
poolSelected = await selectConfiguredCredential({
|
|
198019
|
-
ctx: runContext,
|
|
198020
|
-
model: configuredModel
|
|
198021
|
-
});
|
|
198022
|
-
}
|
|
198023
|
-
if (poolSelected) {
|
|
198024
|
-
const before = repoDir ? await dirtyTrackedPaths({ cwd: repoDir }) : null;
|
|
198025
|
-
captureAuthorizedModels(opencodeCliPath);
|
|
198026
|
-
if (before && repoDir)
|
|
198027
|
-
await restoreDirtiedSince({ before, actor: "model introspection", cwd: repoDir });
|
|
198028
|
-
}
|
|
197720
|
+
if (access.kind === "byok") payload.proxyModel = void 0;
|
|
198029
197721
|
if (runContext.oss && payload.proxyModel) {
|
|
198030
197722
|
payload.effort = ossEffortFloor({ payload });
|
|
198031
197723
|
}
|
|
198032
|
-
|
|
198033
|
-
const credentials = payload.proxyModel
|
|
197724
|
+
const configuredModel = payload.proxyModel ? void 0 : resolveModel({ slug: payload.model });
|
|
197725
|
+
const credentials = payload.proxyModel ? { kind: "ok" } : await checkConfiguredCredentials({
|
|
198034
197726
|
model: configuredModel,
|
|
198035
197727
|
authorized: getAuthorizedModels()
|
|
198036
197728
|
});
|
|
@@ -198361,12 +198053,12 @@ ${instructions.user}` : null,
|
|
|
198361
198053
|
if (payload.timeout === TIMEOUT_DISABLED) {
|
|
198362
198054
|
result = await Promise.race([agentPromise, activityTimeout.promise]);
|
|
198363
198055
|
} else {
|
|
198364
|
-
const
|
|
198365
|
-
if (payload.timeout &&
|
|
198056
|
+
const usable = resolveTimeoutMs(payload.timeout);
|
|
198057
|
+
if (payload.timeout && usable === null) {
|
|
198366
198058
|
log.warning(`invalid timeout "${payload.timeout}" (use --notimeout to disable), using 1h`);
|
|
198367
198059
|
}
|
|
198368
|
-
const timeoutMs =
|
|
198369
|
-
const actualTimeout =
|
|
198060
|
+
const timeoutMs = usable ?? 36e5;
|
|
198061
|
+
const actualTimeout = usable !== null ? payload.timeout : "1h";
|
|
198370
198062
|
let timeoutId;
|
|
198371
198063
|
const timeoutPromise = new Promise((_4, reject) => {
|
|
198372
198064
|
timeoutId = setTimeout(() => {
|
package/dist/internal.js
CHANGED
|
@@ -8,7 +8,7 @@ var __export = (target, all) => {
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "pullfrog",
|
|
11
|
-
version: "0.1.
|
|
11
|
+
version: "0.1.86",
|
|
12
12
|
cliContractVersion: "1",
|
|
13
13
|
type: "module",
|
|
14
14
|
bin: {
|
|
@@ -15487,8 +15487,8 @@ var providers = {
|
|
|
15487
15487
|
},
|
|
15488
15488
|
"claude-sonnet": {
|
|
15489
15489
|
displayName: "Claude Sonnet",
|
|
15490
|
-
resolve: "vercel/anthropic/claude-sonnet-5",
|
|
15491
|
-
effort: ["
|
|
15490
|
+
resolve: "vercel/anthropic/claude-sonnet-5.5",
|
|
15491
|
+
effort: ["low", "medium", "high", "xhigh", "max"]
|
|
15492
15492
|
},
|
|
15493
15493
|
"claude-haiku": {
|
|
15494
15494
|
displayName: "Claude Haiku",
|
package/package.json
CHANGED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { RunContextData } from "./runContextData.ts";
|
|
2
|
-
/** load one subscription per provider for model discovery; keep the pool unflattened. */
|
|
3
|
-
export declare function initializeCredentialPool(ctx: RunContextData, model?: string): Promise<void>;
|
|
4
|
-
export declare function resolvePoolModel(input: {
|
|
5
|
-
codexAgent: boolean;
|
|
6
|
-
}): string | undefined;
|
|
7
|
-
export declare function selectConfiguredCredential(input: {
|
|
8
|
-
ctx: RunContextData;
|
|
9
|
-
model: string | undefined;
|
|
10
|
-
}): Promise<boolean>;
|