pullfrog 0.1.66 → 0.1.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -149
- package/dist/cli.mjs +461 -126
- package/dist/effort.d.ts +10 -0
- package/dist/external.d.ts +9 -1
- package/dist/index.js +345 -63
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal.js +219 -2
- package/dist/models.d.ts +2 -0
- package/dist/toolState.d.ts +1 -1
- package/dist/utils/apiKeys.d.ts +34 -0
- package/dist/utils/billingErrors.d.ts +1 -2
- package/dist/utils/buildPullfrogFooter.d.ts +4 -1
- package/dist/utils/payload.d.ts +1 -0
- package/dist/utils/providerErrors.d.ts +8 -0
- package/dist/utils/proxy.d.ts +24 -0
- package/dist/utils/runContext.d.ts +7 -0
- package/dist/utils/runContextData.d.ts +9 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -107718,6 +107718,7 @@ import { performance as performance5 } from "node:perf_hooks";
|
|
|
107718
107718
|
|
|
107719
107719
|
// effort.ts
|
|
107720
107720
|
var DEFAULT_EFFORT_POSITION = 0.5;
|
|
107721
|
+
var SUBSIDY_RUNG = "high";
|
|
107721
107722
|
var EFFORT_ALIASES = {
|
|
107722
107723
|
low: 0,
|
|
107723
107724
|
medium: 0.25,
|
|
@@ -108042,6 +108043,69 @@ var providers = {
|
|
|
108042
108043
|
}
|
|
108043
108044
|
}
|
|
108044
108045
|
}),
|
|
108046
|
+
// the same models as `moonshotai` above, billed against a Kimi membership
|
|
108047
|
+
// instead of a Moonshot API balance — a separate endpoint, separate model
|
|
108048
|
+
// ids and a separate key, which is why it is a provider rather than a second
|
|
108049
|
+
// `envVars` entry. no provider injection is needed: models.dev carries
|
|
108050
|
+
// `kimi-for-coding` (api `https://api.kimi.com/coding/v1`, npm
|
|
108051
|
+
// `@ai-sdk/anthropic`) and opencode's env loop enables it from a bare
|
|
108052
|
+
// `KIMI_API_KEY`, verified against our pinned opencode-ai@1.18.5 — all four
|
|
108053
|
+
// ids list in `opencode models` and a run reaches Kimi's own auth check.
|
|
108054
|
+
//
|
|
108055
|
+
// NO `openRouterResolve` ON PURPOSE. OpenRouter cannot serve a Kimi
|
|
108056
|
+
// membership, so a Router path here would silently bill the wallet for
|
|
108057
|
+
// Moonshot pay-as-you-go under a slug picked for the opposite reason. The
|
|
108058
|
+
// absence is load-bearing: `isCardGatedModel` reads it as "not Router-
|
|
108059
|
+
// resolvable", `decideModelAccess` answers an explicit pick with the
|
|
108060
|
+
// `router` copy ("add your own provider key"), and run-context clamps a
|
|
108061
|
+
// keyless Router pick to the default subsidy model with `noRouterPath`.
|
|
108062
|
+
"kimi-for-coding": provider({
|
|
108063
|
+
// "Kimi Code" is the product name on kimi.com/code and in the console the
|
|
108064
|
+
// key is minted from. The provider KEY has to stay `kimi-for-coding` — it
|
|
108065
|
+
// is models.dev's id, so it is what `enabled_providers` and every
|
|
108066
|
+
// `resolve` prefix must spell.
|
|
108067
|
+
displayName: "Kimi Code",
|
|
108068
|
+
envVars: ["KIMI_API_KEY"],
|
|
108069
|
+
models: {
|
|
108070
|
+
// the tier each model needs is in `description` because Kimi answers an
|
|
108071
|
+
// out-of-tier request with 401 — indistinguishable from a bad key by
|
|
108072
|
+
// status alone, and only `isKimiPlanTierError` tells them apart after the
|
|
108073
|
+
// fact. saying it in the picker is the half that stops the run happening.
|
|
108074
|
+
"kimi-k3": {
|
|
108075
|
+
displayName: "Kimi K3",
|
|
108076
|
+
description: "1M context, but only on Allegretto and above \xB7 Moderato caps it at 256K",
|
|
108077
|
+
resolve: "kimi-for-coding/k3",
|
|
108078
|
+
effort: ["low", "high", "max"],
|
|
108079
|
+
subagentModel: "kimi-k2"
|
|
108080
|
+
},
|
|
108081
|
+
// `preferred` sits on the 256K variant rather than the 1M flagship, which
|
|
108082
|
+
// inverts the usual "top tier wins" rule for a reason specific to Kimi:
|
|
108083
|
+
// below Allegretto the two are the SAME 256K ceiling and `k3` charges
|
|
108084
|
+
// roughly double the quota for it, so on the median tier the flagship is
|
|
108085
|
+
// strictly dominated rather than merely pricier. This flag seeds the
|
|
108086
|
+
// onboarding pick (`getRecommendedSlug`) and wins key-only auto-select
|
|
108087
|
+
// (`autoSelectModel`), which are exactly the two moments nobody has
|
|
108088
|
+
// chosen yet.
|
|
108089
|
+
"kimi-k3-256k": {
|
|
108090
|
+
displayName: "Kimi K3 256K",
|
|
108091
|
+
description: "Same model at 256K for ~half the quota \xB7 Moderato or above",
|
|
108092
|
+
resolve: "kimi-for-coding/k3-256k",
|
|
108093
|
+
effort: ["low", "high", "max"],
|
|
108094
|
+
preferred: true,
|
|
108095
|
+
subagentModel: "kimi-k2"
|
|
108096
|
+
},
|
|
108097
|
+
"kimi-k2": {
|
|
108098
|
+
displayName: "Kimi K2",
|
|
108099
|
+
description: "Included in every Kimi membership tier",
|
|
108100
|
+
resolve: "kimi-for-coding/kimi-for-coding"
|
|
108101
|
+
},
|
|
108102
|
+
"kimi-k2-highspeed": {
|
|
108103
|
+
displayName: "Kimi K2 HighSpeed",
|
|
108104
|
+
description: "~6x output speed for ~3x quota \xB7 needs Allegretto or above",
|
|
108105
|
+
resolve: "kimi-for-coding/kimi-for-coding-highspeed"
|
|
108106
|
+
}
|
|
108107
|
+
}
|
|
108108
|
+
}),
|
|
108045
108109
|
opencode: provider({
|
|
108046
108110
|
displayName: "OpenCode Zen",
|
|
108047
108111
|
envVars: ["OPENCODE_API_KEY"],
|
|
@@ -108058,6 +108122,15 @@ var providers = {
|
|
|
108058
108122
|
// the model does cost nothing.
|
|
108059
108123
|
isFree: true
|
|
108060
108124
|
},
|
|
108125
|
+
// Zen meters Fable like any other model, so this route reaches it without
|
|
108126
|
+
// the Anthropic access grant `anthropic/claude-fable` still needs.
|
|
108127
|
+
"claude-fable": {
|
|
108128
|
+
displayName: "Claude Fable",
|
|
108129
|
+
resolve: "opencode/claude-fable-5-1",
|
|
108130
|
+
effort: ["low", "medium", "high", "xhigh", "max"],
|
|
108131
|
+
openRouterResolve: "openrouter/~anthropic/claude-fable-latest",
|
|
108132
|
+
subagentModel: "claude-sonnet"
|
|
108133
|
+
},
|
|
108061
108134
|
"claude-opus": {
|
|
108062
108135
|
displayName: "Claude Opus",
|
|
108063
108136
|
resolve: "opencode/claude-opus-5",
|
|
@@ -108171,6 +108244,17 @@ var providers = {
|
|
|
108171
108244
|
effort: ["minimal", "low", "medium", "high"],
|
|
108172
108245
|
openRouterResolve: "openrouter/google/gemini-3.6-flash"
|
|
108173
108246
|
},
|
|
108247
|
+
// Zen serves K3, but rule 7 can only move a mirror when its upstream moves,
|
|
108248
|
+
// so the K3 generation could never reach this block by bumping `kimi-k2`.
|
|
108249
|
+
"kimi-k3": {
|
|
108250
|
+
displayName: "Kimi K3",
|
|
108251
|
+
resolve: "opencode/kimi-k3",
|
|
108252
|
+
// Zen publishes a single rung for K3 where OpenRouter publishes three.
|
|
108253
|
+
effort: ["max"],
|
|
108254
|
+
openRouterEffort: ["low", "high", "max"],
|
|
108255
|
+
openRouterResolve: "openrouter/moonshotai/kimi-k3",
|
|
108256
|
+
subagentModel: "kimi-k2"
|
|
108257
|
+
},
|
|
108174
108258
|
"kimi-k2": {
|
|
108175
108259
|
displayName: "Kimi K2",
|
|
108176
108260
|
// k2.7-code is UNDEPLOYED on Zen — still listed in /zen/v1/models, but
|
|
@@ -108182,25 +108266,58 @@ var providers = {
|
|
|
108182
108266
|
resolve: "opencode/kimi-k2.6",
|
|
108183
108267
|
openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
|
|
108184
108268
|
},
|
|
108269
|
+
// M3 is its own line beside M2, not a bump of it — same reason `kimi-k3`
|
|
108270
|
+
// sits beside `kimi-k2` rather than replacing it.
|
|
108271
|
+
"minimax-m3": {
|
|
108272
|
+
displayName: "MiniMax M3",
|
|
108273
|
+
resolve: "opencode/minimax-m3",
|
|
108274
|
+
openRouterResolve: "openrouter/minimax/minimax-m3"
|
|
108275
|
+
},
|
|
108185
108276
|
// slug pins the m2 line for DB stability; resolve tracks the current m2.7.
|
|
108186
108277
|
"minimax-m2.5": {
|
|
108187
108278
|
displayName: "MiniMax M2",
|
|
108188
108279
|
resolve: "opencode/minimax-m2.7",
|
|
108189
108280
|
openRouterResolve: "openrouter/minimax/minimax-m2.7"
|
|
108190
108281
|
},
|
|
108282
|
+
// Z.ai and xAI reach Zen subscribers only here — before this, `opencode-go`
|
|
108283
|
+
// was the catalog's only GLM route, and Grok had no Zen route at all.
|
|
108284
|
+
glm: {
|
|
108285
|
+
displayName: "GLM",
|
|
108286
|
+
resolve: "opencode/glm-5.2",
|
|
108287
|
+
effort: ["high", "max"],
|
|
108288
|
+
openRouterEffort: ["high", "xhigh"],
|
|
108289
|
+
openRouterResolve: "openrouter/z-ai/glm-5.2"
|
|
108290
|
+
},
|
|
108291
|
+
grok: {
|
|
108292
|
+
displayName: "Grok",
|
|
108293
|
+
resolve: "opencode/grok-4.6",
|
|
108294
|
+
effort: ["low", "medium", "high", "xhigh"],
|
|
108295
|
+
openRouterResolve: "openrouter/x-ai/grok-4.6"
|
|
108296
|
+
},
|
|
108191
108297
|
"gpt-5-nano": {
|
|
108192
108298
|
displayName: "GPT Nano",
|
|
108193
108299
|
resolve: "opencode/gpt-5-nano",
|
|
108194
108300
|
effort: ["minimal", "low", "medium", "high"],
|
|
108195
108301
|
openRouterResolve: "openrouter/openai/gpt-5-nano"
|
|
108196
108302
|
},
|
|
108303
|
+
// Zen's live free MiMo, and the second free row in a menu that big-pickle
|
|
108304
|
+
// was alone in since `mimo-v2-pro-free` lost its model.
|
|
108305
|
+
mimo: {
|
|
108306
|
+
displayName: "MiMo",
|
|
108307
|
+
resolve: "opencode/mimo-v2.5-free",
|
|
108308
|
+
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
108309
|
+
// see the big-pickle note above (#1077).
|
|
108310
|
+
isFree: true
|
|
108311
|
+
},
|
|
108197
108312
|
"mimo-v2-pro-free": {
|
|
108198
108313
|
displayName: "MiMo V2 Pro",
|
|
108199
108314
|
resolve: "opencode/mimo-v2-pro-free",
|
|
108200
108315
|
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
108201
108316
|
// see the big-pickle note above (#1077).
|
|
108202
108317
|
isFree: true,
|
|
108203
|
-
|
|
108318
|
+
// the model id Zen dropped; land a stored MiMo pick back on MiMo rather
|
|
108319
|
+
// than on the unrelated model it had to settle for while none was live.
|
|
108320
|
+
fallback: "opencode/mimo"
|
|
108204
108321
|
},
|
|
108205
108322
|
"minimax-m2.5-free": {
|
|
108206
108323
|
displayName: "MiniMax M2",
|
|
@@ -108295,6 +108412,16 @@ var providers = {
|
|
|
108295
108412
|
resolve: "opencode-go/qwen3.7-plus",
|
|
108296
108413
|
openRouterResolve: "openrouter/qwen/qwen3.7-plus"
|
|
108297
108414
|
},
|
|
108415
|
+
// the cheap rung Alibaba added under Plus (0.15/0.47 against 0.5/3), and
|
|
108416
|
+
// the only model either OpenCode plan has added since this block was written.
|
|
108417
|
+
"qwen-flash": {
|
|
108418
|
+
displayName: "Qwen Flash",
|
|
108419
|
+
resolve: "opencode-go/qwen3.8-flash",
|
|
108420
|
+
effort: ["low", "medium", "xhigh"],
|
|
108421
|
+
// the Go route publishes rungs where OpenRouter publishes none.
|
|
108422
|
+
openRouterEffort: [],
|
|
108423
|
+
openRouterResolve: "openrouter/qwen/qwen3.8-flash"
|
|
108424
|
+
},
|
|
108298
108425
|
// MiniMax — parity with opencode/* and openrouter/*; the m2 slug pins the
|
|
108299
108426
|
// line for DB stability while the resolve tracks the current m2.7.
|
|
108300
108427
|
"minimax-m3": {
|
|
@@ -108594,6 +108721,80 @@ var providers = {
|
|
|
108594
108721
|
openRouterResolve: "openrouter/minimax/minimax-m3"
|
|
108595
108722
|
}
|
|
108596
108723
|
}
|
|
108724
|
+
}),
|
|
108725
|
+
vercel: provider({
|
|
108726
|
+
// Vercel AI Gateway — one key serves every model it fronts. model IDs use
|
|
108727
|
+
// the models.dev `vercel` catalog's own naming (dotted versions, e.g.
|
|
108728
|
+
// `anthropic/claude-opus-5`, `zai/glm-5.3`), and effort ladders mirror that
|
|
108729
|
+
// catalog's entries, not the upstream vendor's. deliberately no
|
|
108730
|
+
// `openRouterResolve`: a gateway pick is BYOK-only — silently rerouting it
|
|
108731
|
+
// over the Router proxy would bill the wallet for traffic the user pointed
|
|
108732
|
+
// at their own gateway.
|
|
108733
|
+
displayName: "Vercel AI Gateway",
|
|
108734
|
+
envVars: ["AI_GATEWAY_API_KEY"],
|
|
108735
|
+
models: {
|
|
108736
|
+
"claude-opus": {
|
|
108737
|
+
displayName: "Claude Opus",
|
|
108738
|
+
resolve: "vercel/anthropic/claude-opus-5",
|
|
108739
|
+
effort: ["low", "medium", "high", "xhigh", "max"],
|
|
108740
|
+
preferred: true,
|
|
108741
|
+
subagentModel: "claude-sonnet"
|
|
108742
|
+
},
|
|
108743
|
+
"claude-sonnet": {
|
|
108744
|
+
displayName: "Claude Sonnet",
|
|
108745
|
+
resolve: "vercel/anthropic/claude-sonnet-5",
|
|
108746
|
+
effort: ["low", "medium", "high", "xhigh"]
|
|
108747
|
+
},
|
|
108748
|
+
"claude-haiku": {
|
|
108749
|
+
displayName: "Claude Haiku",
|
|
108750
|
+
resolve: "vercel/anthropic/claude-haiku-4.5"
|
|
108751
|
+
},
|
|
108752
|
+
"gpt-sol": {
|
|
108753
|
+
displayName: "GPT Sol",
|
|
108754
|
+
resolve: "vercel/openai/gpt-5.6-sol",
|
|
108755
|
+
effort: ["none", "low", "medium", "high", "xhigh", "max"],
|
|
108756
|
+
subagentModel: "gpt-terra"
|
|
108757
|
+
},
|
|
108758
|
+
"gpt-terra": {
|
|
108759
|
+
displayName: "GPT Terra",
|
|
108760
|
+
resolve: "vercel/openai/gpt-5.6-terra",
|
|
108761
|
+
effort: ["none", "low", "medium", "high", "xhigh", "max"]
|
|
108762
|
+
},
|
|
108763
|
+
"gpt-luna": {
|
|
108764
|
+
displayName: "GPT Luna",
|
|
108765
|
+
resolve: "vercel/openai/gpt-5.6-luna",
|
|
108766
|
+
effort: ["none", "low", "medium", "high", "xhigh", "max"]
|
|
108767
|
+
},
|
|
108768
|
+
"gemini-pro": {
|
|
108769
|
+
displayName: "Gemini Pro",
|
|
108770
|
+
resolve: "vercel/google/gemini-3.1-pro-preview",
|
|
108771
|
+
effort: ["low", "medium", "high"]
|
|
108772
|
+
},
|
|
108773
|
+
"gemini-flash": {
|
|
108774
|
+
displayName: "Gemini Flash",
|
|
108775
|
+
resolve: "vercel/google/gemini-3.6-flash",
|
|
108776
|
+
effort: ["minimal", "low", "medium", "high"]
|
|
108777
|
+
},
|
|
108778
|
+
"deepseek-pro": {
|
|
108779
|
+
displayName: "DeepSeek Pro",
|
|
108780
|
+
resolve: "vercel/deepseek/deepseek-v4-pro-0813",
|
|
108781
|
+
effort: ["high", "xhigh"]
|
|
108782
|
+
},
|
|
108783
|
+
"deepseek-flash": {
|
|
108784
|
+
displayName: "DeepSeek Flash",
|
|
108785
|
+
resolve: "vercel/deepseek/deepseek-v4-flash",
|
|
108786
|
+
effort: ["high", "xhigh"]
|
|
108787
|
+
},
|
|
108788
|
+
glm: {
|
|
108789
|
+
displayName: "GLM",
|
|
108790
|
+
resolve: "vercel/zai/glm-5.3",
|
|
108791
|
+
effort: ["low", "high", "max"]
|
|
108792
|
+
},
|
|
108793
|
+
"kimi-k3": {
|
|
108794
|
+
displayName: "Kimi K3",
|
|
108795
|
+
resolve: "vercel/moonshotai/kimi-k3"
|
|
108796
|
+
}
|
|
108797
|
+
}
|
|
108597
108798
|
})
|
|
108598
108799
|
};
|
|
108599
108800
|
function parseModel(slug2) {
|
|
@@ -109345,6 +109546,7 @@ async function installFromNpmTarball(params) {
|
|
|
109345
109546
|
// utils/providerErrors.ts
|
|
109346
109547
|
var PROVIDER_BILLING_EXHAUSTED_LABEL = "provider billing exhausted";
|
|
109347
109548
|
var PROVIDER_NO_ENDPOINTS_LABEL = "provider no routable endpoints";
|
|
109549
|
+
var PROVIDER_USAGE_LIMIT_LABEL = "provider usage limit reached";
|
|
109348
109550
|
var statusKey = `\\b(?:status[_ ]?code|http[_ ]?status|status)["']?\\s*[:=]\\s*["']?`;
|
|
109349
109551
|
var ANTHROPIC_SPEND_CAP_PATTERN = /reached your specified API usage limits\.?(?:\s*You will regain access on ([^"\n]+?)\.)?/i;
|
|
109350
109552
|
function findAnthropicSpendCap(text) {
|
|
@@ -109390,6 +109592,14 @@ var PROVIDER_ERROR_PATTERNS = [
|
|
|
109390
109592
|
// the wallet-shaped patterns above reach, and its 400 sits nowhere near a
|
|
109391
109593
|
// `status:` key either — so the whole message was dropped on the floor (#1208).
|
|
109392
109594
|
{ regex: ANTHROPIC_SPEND_CAP_PATTERN, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
109595
|
+
// OpenCode Zen / Codex-subscription cap: `AI_APICallError: The usage limit has
|
|
109596
|
+
// been reached`. Its noun is "usage limit" with no "rate", no status code and
|
|
109597
|
+
// no wallet wording, so every pattern here missed it and `lastProviderError`
|
|
109598
|
+
// stayed unset — which suppresses nothing, so the run was reported as "The
|
|
109599
|
+
// model produced no output at all … usually transient; re-running often
|
|
109600
|
+
// succeeds" while the same log held nine of these. Measured on a live account
|
|
109601
|
+
// whose ChatGPT subscription was capped.
|
|
109602
|
+
{ regex: /\bthe usage limit has been reached\b/i, label: PROVIDER_USAGE_LIMIT_LABEL },
|
|
109393
109603
|
// the OpenRouter shapes `isRouterKeylimitExhaustedError` matches. on a Router
|
|
109394
109604
|
// run those mean the PULLFROG wallet is empty and `renderRunError` returns a
|
|
109395
109605
|
// `BillingError` before ever reaching this list; on a BYOK run the very same
|
|
@@ -109520,7 +109730,7 @@ function ossEffortFloor(ctx) {
|
|
|
109520
109730
|
const alias = resolveRunAlias(ctx);
|
|
109521
109731
|
const published = alias?.openRouterEffort ?? alias?.effort;
|
|
109522
109732
|
if (!published) return 0;
|
|
109523
|
-
return rungPosition({ rung:
|
|
109733
|
+
return rungPosition({ rung: SUBSIDY_RUNG, published }) ?? 0;
|
|
109524
109734
|
}
|
|
109525
109735
|
function resolveRunEffort(ctx) {
|
|
109526
109736
|
const configured = ctx.payload.effort !== void 0;
|
|
@@ -109552,7 +109762,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
109552
109762
|
// package.json
|
|
109553
109763
|
var package_default = {
|
|
109554
109764
|
name: "pullfrog",
|
|
109555
|
-
version: "0.1.
|
|
109765
|
+
version: "0.1.68",
|
|
109556
109766
|
type: "module",
|
|
109557
109767
|
bin: {
|
|
109558
109768
|
pullfrog: "dist/cli.mjs",
|
|
@@ -192236,6 +192446,9 @@ function formatModelLabel(params) {
|
|
|
192236
192446
|
if (params.fallbackFrom) {
|
|
192237
192447
|
return `${base} (credentials for ${providerDisplayName(params.fallbackFrom)} were rejected by the provider)`;
|
|
192238
192448
|
}
|
|
192449
|
+
if (params.clamped?.reason === "trial") {
|
|
192450
|
+
return `${base} (free trial)`;
|
|
192451
|
+
}
|
|
192239
192452
|
if (params.clamped) {
|
|
192240
192453
|
const target = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
|
|
192241
192454
|
return params.clamped.reason === "card" ? `${base} (${target} needs a [card on file](https://docs.pullfrog.com/models))` : `${base} (${target} needs a [provider key](https://docs.pullfrog.com/models) \u2014 no Router support yet)`;
|
|
@@ -192245,6 +192458,15 @@ function formatModelLabel(params) {
|
|
|
192245
192458
|
}
|
|
192246
192459
|
return base;
|
|
192247
192460
|
}
|
|
192461
|
+
function buildTrialDisclosure(owner) {
|
|
192462
|
+
const consoleUrl = owner ? `https://pullfrog.com/console/${owner}` : "https://pullfrog.com/console";
|
|
192463
|
+
return [
|
|
192464
|
+
"---",
|
|
192465
|
+
"",
|
|
192466
|
+
"> [!IMPORTANT]",
|
|
192467
|
+
`> **This run used the free trial model.** \`DeepSeek Flash\` is fast and cheap \u2014 expect lighter work than a frontier model. [Connect a subscription or API key \u2192](${consoleUrl})`
|
|
192468
|
+
].join("\n");
|
|
192469
|
+
}
|
|
192248
192470
|
function buildPullfrogFooter(params) {
|
|
192249
192471
|
const parts = [];
|
|
192250
192472
|
if (params.shaPinned) {
|
|
@@ -192277,10 +192499,13 @@ function buildPullfrogFooter(params) {
|
|
|
192277
192499
|
);
|
|
192278
192500
|
}
|
|
192279
192501
|
const allParts = [...parts, "[\u{1D54F}](https://x.com/pullfrogai)"];
|
|
192502
|
+
const disclosure = params.clamped?.reason === "trial" ? `${buildTrialDisclosure(params.owner)}
|
|
192503
|
+
|
|
192504
|
+
` : "";
|
|
192280
192505
|
return `
|
|
192281
192506
|
|
|
192282
192507
|
${PULLFROG_DIVIDER}
|
|
192283
|
-
<sup>${FROG_LOGO} \uFF5C ${allParts.join(" \uFF5C ")}</sup>`;
|
|
192508
|
+
${disclosure}<sup>${FROG_LOGO} \uFF5C ${allParts.join(" \uFF5C ")}</sup>`;
|
|
192284
192509
|
}
|
|
192285
192510
|
function stripExistingFooter(body) {
|
|
192286
192511
|
const dividerIndex = body.indexOf(PULLFROG_DIVIDER);
|
|
@@ -192434,7 +192659,8 @@ function buildCommentFooter(ctx, customParts) {
|
|
|
192434
192659
|
clamped: ctx.toolState.modelClamped,
|
|
192435
192660
|
unselectedProxyDefault: ctx.toolState.unselectedProxyDefault,
|
|
192436
192661
|
shaPinned: ctx.toolState.shaPinned,
|
|
192437
|
-
oss: ctx.oss
|
|
192662
|
+
oss: ctx.oss,
|
|
192663
|
+
owner: ctx.repo.owner
|
|
192438
192664
|
});
|
|
192439
192665
|
}
|
|
192440
192666
|
function buildImplementPlanLink(ctx, issueNumber, commentId) {
|
|
@@ -193433,7 +193659,8 @@ async function createAndSubmitWithFooter(ctx, params, opts) {
|
|
|
193433
193659
|
clamped: ctx.toolState.modelClamped,
|
|
193434
193660
|
unselectedProxyDefault: ctx.toolState.unselectedProxyDefault,
|
|
193435
193661
|
shaPinned: ctx.toolState.shaPinned,
|
|
193436
|
-
oss: ctx.oss
|
|
193662
|
+
oss: ctx.oss,
|
|
193663
|
+
owner: ctx.repo.owner
|
|
193437
193664
|
});
|
|
193438
193665
|
return await ctx.octokit.rest.pulls.submitReview({
|
|
193439
193666
|
owner: params.owner,
|
|
@@ -196194,7 +196421,8 @@ function buildPrBodyWithFooter(ctx, body) {
|
|
|
196194
196421
|
clamped: ctx.toolState.modelClamped,
|
|
196195
196422
|
unselectedProxyDefault: ctx.toolState.unselectedProxyDefault,
|
|
196196
196423
|
shaPinned: ctx.toolState.shaPinned,
|
|
196197
|
-
oss: ctx.oss
|
|
196424
|
+
oss: ctx.oss,
|
|
196425
|
+
owner: ctx.repo.owner
|
|
196198
196426
|
});
|
|
196199
196427
|
const bodyWithoutFooter = stripExistingFooter(fixDoubleEscapedString(body));
|
|
196200
196428
|
return `${bodyWithoutFooter}${footer}`;
|
|
@@ -197501,10 +197729,12 @@ function isByokSetupError(text) {
|
|
|
197501
197729
|
var SECRETS_UNAVAILABLE_MARKER = "couldn't load your Pullfrog secrets";
|
|
197502
197730
|
var ROUTER_UNFUNDED_MARKER = "your Pullfrog Router balance is empty";
|
|
197503
197731
|
var CREDENTIAL_REJECTED_MARKER = "was rejected by its provider";
|
|
197504
|
-
|
|
197505
|
-
|
|
197506
|
-
|
|
197507
|
-
|
|
197732
|
+
var NoUsableCredentialError = class extends Error {
|
|
197733
|
+
};
|
|
197734
|
+
function throwKeyError(params) {
|
|
197735
|
+
if (params.secretsUnavailable) throw new Error(buildSecretsUnavailableError(params));
|
|
197736
|
+
if (params.routerUnfunded) throw new NoUsableCredentialError(buildRouterUnfundedError(params));
|
|
197737
|
+
throw new NoUsableCredentialError(buildMissingApiKeyError(params));
|
|
197508
197738
|
}
|
|
197509
197739
|
function buildRouterUnfundedError(params) {
|
|
197510
197740
|
const billingUrl = `${getApiUrl()}/console/${params.owner}#billing`;
|
|
@@ -197703,61 +197933,55 @@ function validateAgentApiKey(params) {
|
|
|
197703
197933
|
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
197704
197934
|
return;
|
|
197705
197935
|
}
|
|
197706
|
-
|
|
197707
|
-
|
|
197936
|
+
if (process.env[BEDROCK_MODEL_ID_ENV]?.trim() === params.model) {
|
|
197937
|
+
validateBedrockSetup({ owner: params.owner, name: params.name });
|
|
197938
|
+
return;
|
|
197939
|
+
}
|
|
197708
197940
|
}
|
|
197709
197941
|
if (params.agent.name === "opencode") {
|
|
197710
197942
|
if (params.authorized.has(params.model)) return;
|
|
197711
197943
|
const reason = getModelsFailure();
|
|
197712
197944
|
if (reason) throw new Error(reason);
|
|
197713
197945
|
if (getModelEnvVars(params.model).some(hasEnvVar2)) return;
|
|
197714
|
-
|
|
197715
|
-
buildKeyError({
|
|
197716
|
-
owner: params.owner,
|
|
197717
|
-
name: params.name,
|
|
197718
|
-
model: params.model,
|
|
197719
|
-
secretsUnavailable: params.secretsUnavailable,
|
|
197720
|
-
routerUnfunded: params.routerUnfunded
|
|
197721
|
-
})
|
|
197722
|
-
);
|
|
197723
|
-
}
|
|
197724
|
-
if (hasSingleProviderAuth(params.agent.name)) return;
|
|
197725
|
-
throw new Error(
|
|
197726
|
-
buildKeyError({
|
|
197946
|
+
throwKeyError({
|
|
197727
197947
|
owner: params.owner,
|
|
197728
197948
|
name: params.name,
|
|
197729
197949
|
model: params.model,
|
|
197730
197950
|
secretsUnavailable: params.secretsUnavailable,
|
|
197731
197951
|
routerUnfunded: params.routerUnfunded
|
|
197732
|
-
})
|
|
197733
|
-
|
|
197952
|
+
});
|
|
197953
|
+
}
|
|
197954
|
+
if (hasSingleProviderAuth(params.agent.name)) return;
|
|
197955
|
+
throwKeyError({
|
|
197956
|
+
owner: params.owner,
|
|
197957
|
+
name: params.name,
|
|
197958
|
+
model: params.model,
|
|
197959
|
+
secretsUnavailable: params.secretsUnavailable,
|
|
197960
|
+
routerUnfunded: params.routerUnfunded
|
|
197961
|
+
});
|
|
197734
197962
|
}
|
|
197735
197963
|
if (params.agent.name === "opencode") {
|
|
197736
197964
|
if ([...params.authorized].some(modelHasRuntimeAuth)) return;
|
|
197737
197965
|
const reason = getModelsFailure();
|
|
197738
197966
|
if (reason) throw new Error(reason);
|
|
197739
|
-
|
|
197740
|
-
buildKeyError({
|
|
197741
|
-
owner: params.owner,
|
|
197742
|
-
name: params.name,
|
|
197743
|
-
secretsUnavailable: params.secretsUnavailable,
|
|
197744
|
-
routerUnfunded: params.routerUnfunded
|
|
197745
|
-
})
|
|
197746
|
-
);
|
|
197747
|
-
}
|
|
197748
|
-
if (hasSingleProviderAuth(params.agent.name)) return;
|
|
197749
|
-
throw new Error(
|
|
197750
|
-
buildKeyError({
|
|
197967
|
+
throwKeyError({
|
|
197751
197968
|
owner: params.owner,
|
|
197752
197969
|
name: params.name,
|
|
197753
197970
|
secretsUnavailable: params.secretsUnavailable,
|
|
197754
197971
|
routerUnfunded: params.routerUnfunded
|
|
197755
|
-
})
|
|
197756
|
-
|
|
197972
|
+
});
|
|
197973
|
+
}
|
|
197974
|
+
if (hasSingleProviderAuth(params.agent.name)) return;
|
|
197975
|
+
throwKeyError({
|
|
197976
|
+
owner: params.owner,
|
|
197977
|
+
name: params.name,
|
|
197978
|
+
secretsUnavailable: params.secretsUnavailable,
|
|
197979
|
+
routerUnfunded: params.routerUnfunded
|
|
197980
|
+
});
|
|
197757
197981
|
}
|
|
197758
197982
|
function isApiKeyAuthError(text) {
|
|
197759
197983
|
if (!text) return false;
|
|
197760
|
-
return text.includes(MISSING_KEY_MARKER) || /Invalid API key/i.test(text) || /Incorrect API key provided/i.test(text) || /\bUser not found\b/i.test(text) || /\bInvalid authentication\b/i.test(text) || /authentication_error/i.test(text) || /Invalid bearer token/i.test(text) || /api_error_status\s*=\s*401/i.test(text) || /API Error:\s*401/i.test(text) || /Failed to authenticate\. API Error:/i.test(text) || /Your api key:.*is invalid/i.test(text) || isMalformedKeyError(text) || isClaudeSubscriptionDisabledError(text) || isClaudeSessionLimitError(text) || isOAuthCredentialExpiredError(text);
|
|
197984
|
+
return text.includes(MISSING_KEY_MARKER) || /Invalid API key/i.test(text) || /Incorrect API key provided/i.test(text) || /\bUser not found\b/i.test(text) || /\bInvalid authentication\b/i.test(text) || /authentication_error/i.test(text) || /Invalid bearer token/i.test(text) || /api_error_status\s*=\s*401/i.test(text) || /API Error:\s*401/i.test(text) || /Failed to authenticate\. API Error:/i.test(text) || /Your api key:.*is invalid/i.test(text) || isMalformedKeyError(text) || isClaudeSubscriptionDisabledError(text) || isKimiPlanTierError(text) || isClaudeSessionLimitError(text) || isOAuthCredentialExpiredError(text);
|
|
197761
197985
|
}
|
|
197762
197986
|
function isOAuthCredentialExpiredError(text) {
|
|
197763
197987
|
return (
|
|
@@ -197778,6 +198002,9 @@ function isMalformedKeyError(text) {
|
|
|
197778
198002
|
function isClaudeSubscriptionDisabledError(text) {
|
|
197779
198003
|
return /disabled Claude subscription access/i.test(text);
|
|
197780
198004
|
}
|
|
198005
|
+
function isKimiPlanTierError(text) {
|
|
198006
|
+
return /Your current (?:subscription does not have access to|plan supports only)\b/i.test(text);
|
|
198007
|
+
}
|
|
197781
198008
|
var CLAUDE_SESSION_LIMIT_PATTERN = /hit your (?:session|weekly|five-hour|Opus|Sonnet|Haiku)\s+limit(?:\s*·\s*resets\s+([^"\n]+))?/i;
|
|
197782
198009
|
function isClaudeSessionLimitError(text) {
|
|
197783
198010
|
return CLAUDE_SESSION_LIMIT_PATTERN.test(text);
|
|
@@ -197851,6 +198078,13 @@ function formatApiKeyErrorSummary(params) {
|
|
|
197851
198078
|
`[Add repo secret \u2192](${githubSecretsUrl}) \xB7 [Model settings \u2192](${settingsUrl}) \xB7 [Setup docs \u2192](https://docs.pullfrog.com/keys) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`
|
|
197852
198079
|
].join("\n");
|
|
197853
198080
|
}
|
|
198081
|
+
if (isKimiPlanTierError(params.raw)) {
|
|
198082
|
+
return [
|
|
198083
|
+
"**Your Kimi membership doesn't include the model this run asked for.** Kimi K3 needs a Moderato plan or above, and K3's 1M context and Kimi K2 HighSpeed need Allegretto or above. Upgrade the membership, or switch this repo to **Kimi K2**, which every tier includes.",
|
|
198084
|
+
"",
|
|
198085
|
+
`[Kimi plans \u2192](https://www.kimi.com/membership/pricing) \xB7 [Model settings \u2192](${settingsUrl}) \xB7 [Setup docs \u2192](https://docs.pullfrog.com/kimi-code) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`
|
|
198086
|
+
].join("\n");
|
|
198087
|
+
}
|
|
197854
198088
|
if (isOAuthCredentialExpiredError(params.raw)) {
|
|
197855
198089
|
return [
|
|
197856
198090
|
`**Your provider OAuth credential has expired or been revoked.** Re-authenticate the provider connection (e.g. \`pullfrog auth claude\` / \`pullfrog auth codex\` / \`pullfrog auth grok\`), then re-trigger the run.`,
|
|
@@ -197868,9 +198102,9 @@ function formatApiKeyErrorSummary(params) {
|
|
|
197868
198102
|
].join("\n");
|
|
197869
198103
|
}
|
|
197870
198104
|
return [
|
|
197871
|
-
`**Your LLM provider API key was rejected.** Rotate the key in your provider dashboard, then update the
|
|
198105
|
+
`**Your LLM provider API key was rejected.** Rotate the key in your provider dashboard, then update the copy Pullfrog uses \u2014 wherever you saved it.`,
|
|
197872
198106
|
"",
|
|
197873
|
-
`[
|
|
198107
|
+
`[Pullfrog secrets \u2192](${getApiUrl()}/console/${params.owner}) \xB7 [Repo secrets \u2192](${githubSecretsUrl}) \xB7 [Model settings \u2192](${settingsUrl}) \xB7 [Setup docs \u2192](https://docs.pullfrog.com/keys) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`
|
|
197874
198108
|
].join("\n");
|
|
197875
198109
|
}
|
|
197876
198110
|
|
|
@@ -199096,6 +199330,9 @@ var DebugInput = type.enumerated("disabled", "enabled");
|
|
|
199096
199330
|
var JsonPayload = type({
|
|
199097
199331
|
"~pullfrog": "true",
|
|
199098
199332
|
version: "string",
|
|
199333
|
+
// the server's run type, forwarded verbatim to run-context. optional so a
|
|
199334
|
+
// payload from an older server build still parses against a newer action.
|
|
199335
|
+
"type?": "string | undefined",
|
|
199099
199336
|
"model?": "string | undefined",
|
|
199100
199337
|
"modelExplicit?": "boolean | undefined",
|
|
199101
199338
|
"effort?": "number | string | undefined",
|
|
@@ -199581,7 +199818,8 @@ ${ctx.error}` : ctx.error;
|
|
|
199581
199818
|
clamped: ctx.toolState.modelClamped,
|
|
199582
199819
|
unselectedProxyDefault: ctx.toolState.unselectedProxyDefault,
|
|
199583
199820
|
shaPinned: ctx.toolState.shaPinned,
|
|
199584
|
-
oss: ctx.toolState.oss
|
|
199821
|
+
oss: ctx.toolState.oss,
|
|
199822
|
+
owner: repoContext.owner
|
|
199585
199823
|
});
|
|
199586
199824
|
const body = `${formattedError}${footer}`;
|
|
199587
199825
|
const comment = ctx.toolState.progressComment;
|
|
@@ -199664,7 +199902,7 @@ async function mintProxyKey(ctx) {
|
|
|
199664
199902
|
}
|
|
199665
199903
|
}
|
|
199666
199904
|
async function buildProxyTokenHeaders(ctx) {
|
|
199667
|
-
const fundingSource = ctx.
|
|
199905
|
+
const fundingSource = ctx.fundingSource;
|
|
199668
199906
|
if (ctx.oidcCredentials) {
|
|
199669
199907
|
const creds = ctx.oidcCredentials;
|
|
199670
199908
|
const oidcToken = await op(() => fetchIdTokenFromStash(creds), {
|
|
@@ -199696,7 +199934,7 @@ async function resolveProxyModel(ctx) {
|
|
|
199696
199934
|
const key = await mintProxyKey({
|
|
199697
199935
|
oidcCredentials: ctx.oidcCredentials,
|
|
199698
199936
|
repo: ctx.repo,
|
|
199699
|
-
|
|
199937
|
+
fundingSource: ctx.oss ? "oss" : "router"
|
|
199700
199938
|
});
|
|
199701
199939
|
if (!key) return;
|
|
199702
199940
|
process.env.OPENROUTER_API_KEY = key;
|
|
@@ -199768,6 +200006,26 @@ async function runProxyResolution(ctx) {
|
|
|
199768
200006
|
throw error62;
|
|
199769
200007
|
}
|
|
199770
200008
|
}
|
|
200009
|
+
async function resolveTrialFallback(ctx) {
|
|
200010
|
+
if (process.env.PULLFROG_MODEL?.trim()) return false;
|
|
200011
|
+
if (!ctx.oidcCredentials && !isLocalApiUrl()) return false;
|
|
200012
|
+
const key = await mintProxyKey({
|
|
200013
|
+
oidcCredentials: ctx.oidcCredentials,
|
|
200014
|
+
repo: ctx.repo,
|
|
200015
|
+
fundingSource: "trial"
|
|
200016
|
+
});
|
|
200017
|
+
if (!key) return false;
|
|
200018
|
+
process.env.OPENROUTER_API_KEY = key;
|
|
200019
|
+
core9.setSecret(key);
|
|
200020
|
+
ctx.payload.proxyModel = DEFAULT_PROXY_MODEL;
|
|
200021
|
+
ctx.toolState.model = DEFAULT_PROXY_MODEL;
|
|
200022
|
+
ctx.toolState.modelClamped = {
|
|
200023
|
+
from: ctx.configuredModel ?? DEFAULT_PROXY_MODEL,
|
|
200024
|
+
reason: "trial"
|
|
200025
|
+
};
|
|
200026
|
+
log.info(`\xBB proxy: trial \u2192 ${DEFAULT_PROXY_MODEL}`);
|
|
200027
|
+
return true;
|
|
200028
|
+
}
|
|
199771
200029
|
|
|
199772
200030
|
// utils/prSummary.ts
|
|
199773
200031
|
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
|
|
@@ -199945,8 +200203,9 @@ async function fetchRunContext(params) {
|
|
|
199945
200203
|
if (params.oidcToken) {
|
|
199946
200204
|
headers["X-GitHub-OIDC-Token"] = params.oidcToken;
|
|
199947
200205
|
}
|
|
200206
|
+
const query = params.runType ? `?type=${encodeURIComponent(params.runType)}` : "";
|
|
199948
200207
|
const response = await apiFetch({
|
|
199949
|
-
path: `/api/repo/${params.repoContext.owner}/${params.repoContext.name}/run-context`,
|
|
200208
|
+
path: `/api/repo/${params.repoContext.owner}/${params.repoContext.name}/run-context${query}`,
|
|
199950
200209
|
headers,
|
|
199951
200210
|
signal: controller.signal
|
|
199952
200211
|
});
|
|
@@ -199983,7 +200242,8 @@ async function fetchRunContext(params) {
|
|
|
199983
200242
|
proxyModel: data.proxyModel,
|
|
199984
200243
|
dbSecrets: data.dbSecrets,
|
|
199985
200244
|
secretsUnavailable: data.secretsUnavailable,
|
|
199986
|
-
routerUnfunded: data.routerUnfunded
|
|
200245
|
+
routerUnfunded: data.routerUnfunded,
|
|
200246
|
+
trialFallback: data.trialFallback
|
|
199987
200247
|
};
|
|
199988
200248
|
} catch {
|
|
199989
200249
|
clearTimeout(timeoutId);
|
|
@@ -200024,7 +200284,7 @@ async function resolveRunContextData(params) {
|
|
|
200024
200284
|
retries: [100, 500],
|
|
200025
200285
|
bail: (error62) => !isTransientOctokitError(error62)
|
|
200026
200286
|
})(),
|
|
200027
|
-
fetchRunContext({ token: params.token, repoContext, oidcToken })
|
|
200287
|
+
fetchRunContext({ token: params.token, repoContext, oidcToken, runType: params.runType })
|
|
200028
200288
|
]);
|
|
200029
200289
|
return {
|
|
200030
200290
|
repo: {
|
|
@@ -200042,7 +200302,8 @@ async function resolveRunContextData(params) {
|
|
|
200042
200302
|
// a failed mint on a runner that should have been able to mint is the same
|
|
200043
200303
|
// outcome as the server-side failure: the run never sees stored secrets.
|
|
200044
200304
|
secretsUnavailable: runContext.secretsUnavailable || !!process.env.ACTIONS_ID_TOKEN_REQUEST_URL && oidcToken === void 0,
|
|
200045
|
-
routerUnfunded: runContext.routerUnfunded
|
|
200305
|
+
routerUnfunded: runContext.routerUnfunded,
|
|
200306
|
+
trialFallback: runContext.trialFallback
|
|
200046
200307
|
};
|
|
200047
200308
|
}
|
|
200048
200309
|
|
|
@@ -201122,7 +201383,11 @@ async function main() {
|
|
|
201122
201383
|
resolveGit();
|
|
201123
201384
|
const jobToken = getJobToken();
|
|
201124
201385
|
const initialOctokit = createOctokit(jobToken);
|
|
201125
|
-
const runContext = await resolveRunContextData({
|
|
201386
|
+
const runContext = await resolveRunContextData({
|
|
201387
|
+
octokit: initialOctokit,
|
|
201388
|
+
token: jobToken,
|
|
201389
|
+
runType: typeof resolvedPromptInput === "string" ? void 0 : resolvedPromptInput.type
|
|
201390
|
+
});
|
|
201126
201391
|
timer.checkpoint("runContextData");
|
|
201127
201392
|
const payload = resolvePayload(resolvedPromptInput, runContext.repoSettings);
|
|
201128
201393
|
const toolState = initToolState({
|
|
@@ -201303,7 +201568,7 @@ async function main() {
|
|
|
201303
201568
|
}
|
|
201304
201569
|
const resolvedModel = credentials.kind === "fellBack" ? credentials.replacement : configuredModel;
|
|
201305
201570
|
vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
|
|
201306
|
-
|
|
201571
|
+
let agent2 = resolveAgent({
|
|
201307
201572
|
model: resolvedModel,
|
|
201308
201573
|
proxyModel: payload.proxyModel,
|
|
201309
201574
|
// the account opt-in and the canary arm are both admissions to codex, so
|
|
@@ -201315,15 +201580,32 @@ async function main() {
|
|
|
201315
201580
|
const effectiveModel = payload.proxyModel ?? resolvedModel ?? payload.model;
|
|
201316
201581
|
toolState.model = effectiveModel;
|
|
201317
201582
|
if (!payload.proxyModel) {
|
|
201318
|
-
|
|
201319
|
-
|
|
201320
|
-
|
|
201321
|
-
|
|
201322
|
-
|
|
201323
|
-
|
|
201324
|
-
|
|
201325
|
-
|
|
201326
|
-
|
|
201583
|
+
try {
|
|
201584
|
+
validateAgentApiKey({
|
|
201585
|
+
agent: agent2,
|
|
201586
|
+
model: effectiveModel,
|
|
201587
|
+
authorized: getAuthorizedModels(),
|
|
201588
|
+
owner: runContext.repo.owner,
|
|
201589
|
+
name: runContext.repo.name,
|
|
201590
|
+
secretsUnavailable: runContext.secretsUnavailable,
|
|
201591
|
+
routerUnfunded: runContext.routerUnfunded
|
|
201592
|
+
});
|
|
201593
|
+
} catch (missingKey) {
|
|
201594
|
+
const funded = runContext.trialFallback && missingKey instanceof NoUsableCredentialError ? await resolveTrialFallback({
|
|
201595
|
+
payload,
|
|
201596
|
+
configuredModel: effectiveModel,
|
|
201597
|
+
oidcCredentials,
|
|
201598
|
+
repo: runContext.repo,
|
|
201599
|
+
toolState
|
|
201600
|
+
}) : false;
|
|
201601
|
+
if (!funded) throw missingKey;
|
|
201602
|
+
agent2 = resolveAgent({
|
|
201603
|
+
model: resolvedModel,
|
|
201604
|
+
proxyModel: payload.proxyModel,
|
|
201605
|
+
codexAgent: runContext.repoSettings.codexAgent || payload.codexArm === true
|
|
201606
|
+
});
|
|
201607
|
+
toolState.agent = agent2.name;
|
|
201608
|
+
}
|
|
201327
201609
|
}
|
|
201328
201610
|
await setupGit({
|
|
201329
201611
|
gitToken: tokenRef.gitToken,
|