pullfrog 0.1.85 → 0.1.87

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/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 select2 = require_select();
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 select2.matches(this, selector);
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 select2(selector, this)[0];
84681
+ return select(selector, this)[0];
84682
84682
  } },
84683
84683
  querySelectorAll: { value: function(selector) {
84684
- var nodes = select2(selector, this);
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 select2 = require_select();
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 = select2(selector, context);
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 select2 = require_select();
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 select2(selector, this)[0];
88917
+ return select(selector, this)[0];
88918
88918
  } },
88919
88919
  querySelectorAll: { value: function(selector) {
88920
- var nodes = select2(selector, this);
88920
+ var nodes = select(selector, this);
88921
88921
  return nodes.item ? nodes : new NodeList(nodes);
88922
88922
  } }
88923
88923
  });
@@ -103467,9 +103467,9 @@ var providers = {
103467
103467
  },
103468
103468
  "claude-sonnet": {
103469
103469
  displayName: "Claude Sonnet",
103470
- resolve: "anthropic/claude-sonnet-5",
103470
+ resolve: "anthropic/claude-sonnet-5-5",
103471
103471
  effort: ["low", "medium", "high", "xhigh", "max"],
103472
- openRouterResolve: "openrouter/anthropic/claude-sonnet-5"
103472
+ openRouterResolve: "openrouter/anthropic/claude-sonnet-5.5"
103473
103473
  },
103474
103474
  "claude-haiku": {
103475
103475
  displayName: "Claude Haiku",
@@ -103886,9 +103886,9 @@ var providers = {
103886
103886
  },
103887
103887
  "claude-sonnet": {
103888
103888
  displayName: "Claude Sonnet",
103889
- resolve: "opencode/claude-sonnet-5",
103889
+ resolve: "opencode/claude-sonnet-5-5",
103890
103890
  effort: ["low", "medium", "high", "xhigh", "max"],
103891
- openRouterResolve: "openrouter/anthropic/claude-sonnet-5"
103891
+ openRouterResolve: "openrouter/anthropic/claude-sonnet-5.5"
103892
103892
  },
103893
103893
  "claude-haiku": {
103894
103894
  displayName: "Claude Haiku",
@@ -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: ["none", "low", "medium", "high", "xhigh", "max"]
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.85",
105726
+ version: "0.1.87",
105727
105727
  cliContractVersion: "1",
105728
105728
  type: "module",
105729
105729
  bin: {
@@ -105751,7 +105751,7 @@ var package_default = {
105751
105751
  },
105752
105752
  devDependencies: {
105753
105753
  "@actions/core": "^1.11.1",
105754
- "@anthropic-ai/claude-code": "2.1.280",
105754
+ "@anthropic-ai/claude-code": "2.1.284",
105755
105755
  "@ark/fs": "0.56.0",
105756
105756
  "@ark/util": "0.56.0",
105757
105757
  "@clack/prompts": "^1.2.0",
@@ -107292,7 +107292,7 @@ function buildAgentsJson() {
107292
107292
  [REVIEWER_AGENT_NAME]: {
107293
107293
  description: "Read-only review subagent for lens-based code review (correctness, security, billing-subsystem, etc.). Reads only \u2014 no writes, no state-changing shell or MCP calls, no nested subagent dispatch.",
107294
107294
  prompt: REVIEWER_SYSTEM_PROMPT,
107295
- model: "claude-sonnet-5"
107295
+ model: "claude-sonnet-5-5"
107296
107296
  }
107297
107297
  };
107298
107298
  return JSON.stringify(agents2);
@@ -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: configuredModel,
197999
- authorized: /* @__PURE__ */ new Set([
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
- if (payload.proxyModel) configuredModel = void 0;
198033
- const credentials = payload.proxyModel || poolSelected ? { kind: "ok" } : await checkConfiguredCredentials({
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 usable2 = resolveTimeoutMs(payload.timeout);
198365
- if (payload.timeout && usable2 === null) {
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 = usable2 ?? 36e5;
198369
- const actualTimeout = usable2 !== null ? payload.timeout : "1h";
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(() => {