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/internal/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Re-exports shared types, values, and utilities needed by the Next.js app.
|
|
4
4
|
*/
|
|
5
5
|
export type { AuthorPermission, AutoTier, EffortPosition, ModelAlias, ModelProvider, Payload, PayloadEvent, ProviderConfig, PushPermission, ShellPermission, ToolPermission, WriteablePayload, XrepoConfig, } from "../external.ts";
|
|
6
|
-
export { AUTO_EFFICIENT, AUTO_INTELLIGENT, DEFAULT_EFFORT_POSITION, DEFAULT_PROXY_MODEL, defaultAutoTier, EFFORT_ALIASES, getAutoSelectHintModel, getModelEffortLevels, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, isAutoTier, isCardGatedModel, isEffortPosition, isOssAllowedModel, modelAliases, modelHasStoredAuth, OSS_MODEL_ALLOWLIST, OSS_RECOMMENDED_MODEL, offeredRungs, ossFundedModelNames, parseEffortPosition, parseModel, providers, pullfrogMcpName, resolveAutoTier, resolveCliModel, resolveDisplayAlias, resolveModelRung, resolveModelSlug, resolveOpenRouterModel, resolveRung, rungLabel, rungPosition, } from "../external.ts";
|
|
6
|
+
export { AUTO_EFFICIENT, AUTO_INTELLIGENT, DEFAULT_EFFORT_POSITION, DEFAULT_PROXY_MODEL, defaultAutoTier, EFFORT_ALIASES, getAutoSelectHintModel, getModelEffortLevels, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, isAutoTier, isCardGatedModel, isEffortPosition, isOssAllowedModel, modelAliases, modelHasStoredAuth, OSS_MODEL_ALLOWLIST, OSS_RECOMMENDED_MODEL, offeredRungs, ossFundedModelNames, parseEffortPosition, parseModel, providers, pullfrogMcpName, resolveAutoTier, resolveCliModel, resolveDisplayAlias, resolveModelRung, resolveModelSlug, resolveOpenRouterModel, resolveRung, rungLabel, rungPosition, SUBSIDY_RUNG, } from "../external.ts";
|
|
7
7
|
export type { Mode } from "../modes.ts";
|
|
8
8
|
export { modes } from "../modes.ts";
|
|
9
9
|
export { commercialPaywallBody } from "../utils/billingErrors.ts";
|
package/dist/internal.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createRequire as __createRequire } from 'module'; import { fileURLToPat
|
|
|
2
2
|
|
|
3
3
|
// effort.ts
|
|
4
4
|
var DEFAULT_EFFORT_POSITION = 0.5;
|
|
5
|
+
var SUBSIDY_RUNG = "high";
|
|
5
6
|
var EFFORT_ALIASES = {
|
|
6
7
|
low: 0,
|
|
7
8
|
medium: 0.25,
|
|
@@ -338,6 +339,69 @@ var providers = {
|
|
|
338
339
|
}
|
|
339
340
|
}
|
|
340
341
|
}),
|
|
342
|
+
// the same models as `moonshotai` above, billed against a Kimi membership
|
|
343
|
+
// instead of a Moonshot API balance — a separate endpoint, separate model
|
|
344
|
+
// ids and a separate key, which is why it is a provider rather than a second
|
|
345
|
+
// `envVars` entry. no provider injection is needed: models.dev carries
|
|
346
|
+
// `kimi-for-coding` (api `https://api.kimi.com/coding/v1`, npm
|
|
347
|
+
// `@ai-sdk/anthropic`) and opencode's env loop enables it from a bare
|
|
348
|
+
// `KIMI_API_KEY`, verified against our pinned opencode-ai@1.18.5 — all four
|
|
349
|
+
// ids list in `opencode models` and a run reaches Kimi's own auth check.
|
|
350
|
+
//
|
|
351
|
+
// NO `openRouterResolve` ON PURPOSE. OpenRouter cannot serve a Kimi
|
|
352
|
+
// membership, so a Router path here would silently bill the wallet for
|
|
353
|
+
// Moonshot pay-as-you-go under a slug picked for the opposite reason. The
|
|
354
|
+
// absence is load-bearing: `isCardGatedModel` reads it as "not Router-
|
|
355
|
+
// resolvable", `decideModelAccess` answers an explicit pick with the
|
|
356
|
+
// `router` copy ("add your own provider key"), and run-context clamps a
|
|
357
|
+
// keyless Router pick to the default subsidy model with `noRouterPath`.
|
|
358
|
+
"kimi-for-coding": provider({
|
|
359
|
+
// "Kimi Code" is the product name on kimi.com/code and in the console the
|
|
360
|
+
// key is minted from. The provider KEY has to stay `kimi-for-coding` — it
|
|
361
|
+
// is models.dev's id, so it is what `enabled_providers` and every
|
|
362
|
+
// `resolve` prefix must spell.
|
|
363
|
+
displayName: "Kimi Code",
|
|
364
|
+
envVars: ["KIMI_API_KEY"],
|
|
365
|
+
models: {
|
|
366
|
+
// the tier each model needs is in `description` because Kimi answers an
|
|
367
|
+
// out-of-tier request with 401 — indistinguishable from a bad key by
|
|
368
|
+
// status alone, and only `isKimiPlanTierError` tells them apart after the
|
|
369
|
+
// fact. saying it in the picker is the half that stops the run happening.
|
|
370
|
+
"kimi-k3": {
|
|
371
|
+
displayName: "Kimi K3",
|
|
372
|
+
description: "1M context, but only on Allegretto and above \xB7 Moderato caps it at 256K",
|
|
373
|
+
resolve: "kimi-for-coding/k3",
|
|
374
|
+
effort: ["low", "high", "max"],
|
|
375
|
+
subagentModel: "kimi-k2"
|
|
376
|
+
},
|
|
377
|
+
// `preferred` sits on the 256K variant rather than the 1M flagship, which
|
|
378
|
+
// inverts the usual "top tier wins" rule for a reason specific to Kimi:
|
|
379
|
+
// below Allegretto the two are the SAME 256K ceiling and `k3` charges
|
|
380
|
+
// roughly double the quota for it, so on the median tier the flagship is
|
|
381
|
+
// strictly dominated rather than merely pricier. This flag seeds the
|
|
382
|
+
// onboarding pick (`getRecommendedSlug`) and wins key-only auto-select
|
|
383
|
+
// (`autoSelectModel`), which are exactly the two moments nobody has
|
|
384
|
+
// chosen yet.
|
|
385
|
+
"kimi-k3-256k": {
|
|
386
|
+
displayName: "Kimi K3 256K",
|
|
387
|
+
description: "Same model at 256K for ~half the quota \xB7 Moderato or above",
|
|
388
|
+
resolve: "kimi-for-coding/k3-256k",
|
|
389
|
+
effort: ["low", "high", "max"],
|
|
390
|
+
preferred: true,
|
|
391
|
+
subagentModel: "kimi-k2"
|
|
392
|
+
},
|
|
393
|
+
"kimi-k2": {
|
|
394
|
+
displayName: "Kimi K2",
|
|
395
|
+
description: "Included in every Kimi membership tier",
|
|
396
|
+
resolve: "kimi-for-coding/kimi-for-coding"
|
|
397
|
+
},
|
|
398
|
+
"kimi-k2-highspeed": {
|
|
399
|
+
displayName: "Kimi K2 HighSpeed",
|
|
400
|
+
description: "~6x output speed for ~3x quota \xB7 needs Allegretto or above",
|
|
401
|
+
resolve: "kimi-for-coding/kimi-for-coding-highspeed"
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}),
|
|
341
405
|
opencode: provider({
|
|
342
406
|
displayName: "OpenCode Zen",
|
|
343
407
|
envVars: ["OPENCODE_API_KEY"],
|
|
@@ -354,6 +418,15 @@ var providers = {
|
|
|
354
418
|
// the model does cost nothing.
|
|
355
419
|
isFree: true
|
|
356
420
|
},
|
|
421
|
+
// Zen meters Fable like any other model, so this route reaches it without
|
|
422
|
+
// the Anthropic access grant `anthropic/claude-fable` still needs.
|
|
423
|
+
"claude-fable": {
|
|
424
|
+
displayName: "Claude Fable",
|
|
425
|
+
resolve: "opencode/claude-fable-5-1",
|
|
426
|
+
effort: ["low", "medium", "high", "xhigh", "max"],
|
|
427
|
+
openRouterResolve: "openrouter/~anthropic/claude-fable-latest",
|
|
428
|
+
subagentModel: "claude-sonnet"
|
|
429
|
+
},
|
|
357
430
|
"claude-opus": {
|
|
358
431
|
displayName: "Claude Opus",
|
|
359
432
|
resolve: "opencode/claude-opus-5",
|
|
@@ -467,6 +540,17 @@ var providers = {
|
|
|
467
540
|
effort: ["minimal", "low", "medium", "high"],
|
|
468
541
|
openRouterResolve: "openrouter/google/gemini-3.6-flash"
|
|
469
542
|
},
|
|
543
|
+
// Zen serves K3, but rule 7 can only move a mirror when its upstream moves,
|
|
544
|
+
// so the K3 generation could never reach this block by bumping `kimi-k2`.
|
|
545
|
+
"kimi-k3": {
|
|
546
|
+
displayName: "Kimi K3",
|
|
547
|
+
resolve: "opencode/kimi-k3",
|
|
548
|
+
// Zen publishes a single rung for K3 where OpenRouter publishes three.
|
|
549
|
+
effort: ["max"],
|
|
550
|
+
openRouterEffort: ["low", "high", "max"],
|
|
551
|
+
openRouterResolve: "openrouter/moonshotai/kimi-k3",
|
|
552
|
+
subagentModel: "kimi-k2"
|
|
553
|
+
},
|
|
470
554
|
"kimi-k2": {
|
|
471
555
|
displayName: "Kimi K2",
|
|
472
556
|
// k2.7-code is UNDEPLOYED on Zen — still listed in /zen/v1/models, but
|
|
@@ -478,25 +562,58 @@ var providers = {
|
|
|
478
562
|
resolve: "opencode/kimi-k2.6",
|
|
479
563
|
openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
|
|
480
564
|
},
|
|
565
|
+
// M3 is its own line beside M2, not a bump of it — same reason `kimi-k3`
|
|
566
|
+
// sits beside `kimi-k2` rather than replacing it.
|
|
567
|
+
"minimax-m3": {
|
|
568
|
+
displayName: "MiniMax M3",
|
|
569
|
+
resolve: "opencode/minimax-m3",
|
|
570
|
+
openRouterResolve: "openrouter/minimax/minimax-m3"
|
|
571
|
+
},
|
|
481
572
|
// slug pins the m2 line for DB stability; resolve tracks the current m2.7.
|
|
482
573
|
"minimax-m2.5": {
|
|
483
574
|
displayName: "MiniMax M2",
|
|
484
575
|
resolve: "opencode/minimax-m2.7",
|
|
485
576
|
openRouterResolve: "openrouter/minimax/minimax-m2.7"
|
|
486
577
|
},
|
|
578
|
+
// Z.ai and xAI reach Zen subscribers only here — before this, `opencode-go`
|
|
579
|
+
// was the catalog's only GLM route, and Grok had no Zen route at all.
|
|
580
|
+
glm: {
|
|
581
|
+
displayName: "GLM",
|
|
582
|
+
resolve: "opencode/glm-5.2",
|
|
583
|
+
effort: ["high", "max"],
|
|
584
|
+
openRouterEffort: ["high", "xhigh"],
|
|
585
|
+
openRouterResolve: "openrouter/z-ai/glm-5.2"
|
|
586
|
+
},
|
|
587
|
+
grok: {
|
|
588
|
+
displayName: "Grok",
|
|
589
|
+
resolve: "opencode/grok-4.6",
|
|
590
|
+
effort: ["low", "medium", "high", "xhigh"],
|
|
591
|
+
openRouterResolve: "openrouter/x-ai/grok-4.6"
|
|
592
|
+
},
|
|
487
593
|
"gpt-5-nano": {
|
|
488
594
|
displayName: "GPT Nano",
|
|
489
595
|
resolve: "opencode/gpt-5-nano",
|
|
490
596
|
effort: ["minimal", "low", "medium", "high"],
|
|
491
597
|
openRouterResolve: "openrouter/openai/gpt-5-nano"
|
|
492
598
|
},
|
|
599
|
+
// Zen's live free MiMo, and the second free row in a menu that big-pickle
|
|
600
|
+
// was alone in since `mimo-v2-pro-free` lost its model.
|
|
601
|
+
mimo: {
|
|
602
|
+
displayName: "MiMo",
|
|
603
|
+
resolve: "opencode/mimo-v2.5-free",
|
|
604
|
+
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
605
|
+
// see the big-pickle note above (#1077).
|
|
606
|
+
isFree: true
|
|
607
|
+
},
|
|
493
608
|
"mimo-v2-pro-free": {
|
|
494
609
|
displayName: "MiMo V2 Pro",
|
|
495
610
|
resolve: "opencode/mimo-v2-pro-free",
|
|
496
611
|
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
497
612
|
// see the big-pickle note above (#1077).
|
|
498
613
|
isFree: true,
|
|
499
|
-
|
|
614
|
+
// the model id Zen dropped; land a stored MiMo pick back on MiMo rather
|
|
615
|
+
// than on the unrelated model it had to settle for while none was live.
|
|
616
|
+
fallback: "opencode/mimo"
|
|
500
617
|
},
|
|
501
618
|
"minimax-m2.5-free": {
|
|
502
619
|
displayName: "MiniMax M2",
|
|
@@ -591,6 +708,16 @@ var providers = {
|
|
|
591
708
|
resolve: "opencode-go/qwen3.7-plus",
|
|
592
709
|
openRouterResolve: "openrouter/qwen/qwen3.7-plus"
|
|
593
710
|
},
|
|
711
|
+
// the cheap rung Alibaba added under Plus (0.15/0.47 against 0.5/3), and
|
|
712
|
+
// the only model either OpenCode plan has added since this block was written.
|
|
713
|
+
"qwen-flash": {
|
|
714
|
+
displayName: "Qwen Flash",
|
|
715
|
+
resolve: "opencode-go/qwen3.8-flash",
|
|
716
|
+
effort: ["low", "medium", "xhigh"],
|
|
717
|
+
// the Go route publishes rungs where OpenRouter publishes none.
|
|
718
|
+
openRouterEffort: [],
|
|
719
|
+
openRouterResolve: "openrouter/qwen/qwen3.8-flash"
|
|
720
|
+
},
|
|
594
721
|
// MiniMax — parity with opencode/* and openrouter/*; the m2 slug pins the
|
|
595
722
|
// line for DB stability while the resolve tracks the current m2.7.
|
|
596
723
|
"minimax-m3": {
|
|
@@ -890,6 +1017,80 @@ var providers = {
|
|
|
890
1017
|
openRouterResolve: "openrouter/minimax/minimax-m3"
|
|
891
1018
|
}
|
|
892
1019
|
}
|
|
1020
|
+
}),
|
|
1021
|
+
vercel: provider({
|
|
1022
|
+
// Vercel AI Gateway — one key serves every model it fronts. model IDs use
|
|
1023
|
+
// the models.dev `vercel` catalog's own naming (dotted versions, e.g.
|
|
1024
|
+
// `anthropic/claude-opus-5`, `zai/glm-5.3`), and effort ladders mirror that
|
|
1025
|
+
// catalog's entries, not the upstream vendor's. deliberately no
|
|
1026
|
+
// `openRouterResolve`: a gateway pick is BYOK-only — silently rerouting it
|
|
1027
|
+
// over the Router proxy would bill the wallet for traffic the user pointed
|
|
1028
|
+
// at their own gateway.
|
|
1029
|
+
displayName: "Vercel AI Gateway",
|
|
1030
|
+
envVars: ["AI_GATEWAY_API_KEY"],
|
|
1031
|
+
models: {
|
|
1032
|
+
"claude-opus": {
|
|
1033
|
+
displayName: "Claude Opus",
|
|
1034
|
+
resolve: "vercel/anthropic/claude-opus-5",
|
|
1035
|
+
effort: ["low", "medium", "high", "xhigh", "max"],
|
|
1036
|
+
preferred: true,
|
|
1037
|
+
subagentModel: "claude-sonnet"
|
|
1038
|
+
},
|
|
1039
|
+
"claude-sonnet": {
|
|
1040
|
+
displayName: "Claude Sonnet",
|
|
1041
|
+
resolve: "vercel/anthropic/claude-sonnet-5",
|
|
1042
|
+
effort: ["low", "medium", "high", "xhigh"]
|
|
1043
|
+
},
|
|
1044
|
+
"claude-haiku": {
|
|
1045
|
+
displayName: "Claude Haiku",
|
|
1046
|
+
resolve: "vercel/anthropic/claude-haiku-4.5"
|
|
1047
|
+
},
|
|
1048
|
+
"gpt-sol": {
|
|
1049
|
+
displayName: "GPT Sol",
|
|
1050
|
+
resolve: "vercel/openai/gpt-5.6-sol",
|
|
1051
|
+
effort: ["none", "low", "medium", "high", "xhigh", "max"],
|
|
1052
|
+
subagentModel: "gpt-terra"
|
|
1053
|
+
},
|
|
1054
|
+
"gpt-terra": {
|
|
1055
|
+
displayName: "GPT Terra",
|
|
1056
|
+
resolve: "vercel/openai/gpt-5.6-terra",
|
|
1057
|
+
effort: ["none", "low", "medium", "high", "xhigh", "max"]
|
|
1058
|
+
},
|
|
1059
|
+
"gpt-luna": {
|
|
1060
|
+
displayName: "GPT Luna",
|
|
1061
|
+
resolve: "vercel/openai/gpt-5.6-luna",
|
|
1062
|
+
effort: ["none", "low", "medium", "high", "xhigh", "max"]
|
|
1063
|
+
},
|
|
1064
|
+
"gemini-pro": {
|
|
1065
|
+
displayName: "Gemini Pro",
|
|
1066
|
+
resolve: "vercel/google/gemini-3.1-pro-preview",
|
|
1067
|
+
effort: ["low", "medium", "high"]
|
|
1068
|
+
},
|
|
1069
|
+
"gemini-flash": {
|
|
1070
|
+
displayName: "Gemini Flash",
|
|
1071
|
+
resolve: "vercel/google/gemini-3.6-flash",
|
|
1072
|
+
effort: ["minimal", "low", "medium", "high"]
|
|
1073
|
+
},
|
|
1074
|
+
"deepseek-pro": {
|
|
1075
|
+
displayName: "DeepSeek Pro",
|
|
1076
|
+
resolve: "vercel/deepseek/deepseek-v4-pro-0813",
|
|
1077
|
+
effort: ["high", "xhigh"]
|
|
1078
|
+
},
|
|
1079
|
+
"deepseek-flash": {
|
|
1080
|
+
displayName: "DeepSeek Flash",
|
|
1081
|
+
resolve: "vercel/deepseek/deepseek-v4-flash",
|
|
1082
|
+
effort: ["high", "xhigh"]
|
|
1083
|
+
},
|
|
1084
|
+
glm: {
|
|
1085
|
+
displayName: "GLM",
|
|
1086
|
+
resolve: "vercel/zai/glm-5.3",
|
|
1087
|
+
effort: ["low", "high", "max"]
|
|
1088
|
+
},
|
|
1089
|
+
"kimi-k3": {
|
|
1090
|
+
displayName: "Kimi K3",
|
|
1091
|
+
resolve: "vercel/moonshotai/kimi-k3"
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
893
1094
|
})
|
|
894
1095
|
};
|
|
895
1096
|
function parseModel(slug) {
|
|
@@ -1498,6 +1699,9 @@ function formatModelLabel(params) {
|
|
|
1498
1699
|
if (params.fallbackFrom) {
|
|
1499
1700
|
return `${base} (credentials for ${providerDisplayName(params.fallbackFrom)} were rejected by the provider)`;
|
|
1500
1701
|
}
|
|
1702
|
+
if (params.clamped?.reason === "trial") {
|
|
1703
|
+
return `${base} (free trial)`;
|
|
1704
|
+
}
|
|
1501
1705
|
if (params.clamped) {
|
|
1502
1706
|
const target = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
|
|
1503
1707
|
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)`;
|
|
@@ -1507,6 +1711,15 @@ function formatModelLabel(params) {
|
|
|
1507
1711
|
}
|
|
1508
1712
|
return base;
|
|
1509
1713
|
}
|
|
1714
|
+
function buildTrialDisclosure(owner) {
|
|
1715
|
+
const consoleUrl = owner ? `https://pullfrog.com/console/${owner}` : "https://pullfrog.com/console";
|
|
1716
|
+
return [
|
|
1717
|
+
"---",
|
|
1718
|
+
"",
|
|
1719
|
+
"> [!IMPORTANT]",
|
|
1720
|
+
`> **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})`
|
|
1721
|
+
].join("\n");
|
|
1722
|
+
}
|
|
1510
1723
|
function buildPullfrogFooter(params) {
|
|
1511
1724
|
const parts = [];
|
|
1512
1725
|
if (params.shaPinned) {
|
|
@@ -1539,10 +1752,13 @@ function buildPullfrogFooter(params) {
|
|
|
1539
1752
|
);
|
|
1540
1753
|
}
|
|
1541
1754
|
const allParts = [...parts, "[\u{1D54F}](https://x.com/pullfrogai)"];
|
|
1755
|
+
const disclosure = params.clamped?.reason === "trial" ? `${buildTrialDisclosure(params.owner)}
|
|
1756
|
+
|
|
1757
|
+
` : "";
|
|
1542
1758
|
return `
|
|
1543
1759
|
|
|
1544
1760
|
${PULLFROG_DIVIDER}
|
|
1545
|
-
<sup>${FROG_LOGO} \uFF5C ${allParts.join(" \uFF5C ")}</sup>`;
|
|
1761
|
+
${disclosure}<sup>${FROG_LOGO} \uFF5C ${allParts.join(" \uFF5C ")}</sup>`;
|
|
1546
1762
|
}
|
|
1547
1763
|
function stripExistingFooter(body) {
|
|
1548
1764
|
const dividerIndex = body.indexOf(PULLFROG_DIVIDER);
|
|
@@ -2093,6 +2309,7 @@ export {
|
|
|
2093
2309
|
OSS_RECOMMENDED_MODEL,
|
|
2094
2310
|
PULLFROG_DIVIDER,
|
|
2095
2311
|
RUN_STATUS_CHECK_NAME,
|
|
2312
|
+
SUBSIDY_RUNG,
|
|
2096
2313
|
TIMEOUT_DISABLED,
|
|
2097
2314
|
buildPullfrogFooter,
|
|
2098
2315
|
commercialPaywallBody,
|
package/dist/models.d.ts
CHANGED
|
@@ -120,6 +120,7 @@ export declare const providers: {
|
|
|
120
120
|
xai: ProviderConfig;
|
|
121
121
|
deepseek: ProviderConfig;
|
|
122
122
|
moonshotai: ProviderConfig;
|
|
123
|
+
"kimi-for-coding": ProviderConfig;
|
|
123
124
|
opencode: ProviderConfig;
|
|
124
125
|
"opencode-go": ProviderConfig;
|
|
125
126
|
bedrock: ProviderConfig;
|
|
@@ -127,6 +128,7 @@ export declare const providers: {
|
|
|
127
128
|
azure: ProviderConfig;
|
|
128
129
|
"openai-compatible": ProviderConfig;
|
|
129
130
|
openrouter: ProviderConfig;
|
|
131
|
+
vercel: ProviderConfig;
|
|
130
132
|
};
|
|
131
133
|
export type ModelProvider = keyof typeof providers;
|
|
132
134
|
export declare function parseModel(slug: string): {
|
package/dist/toolState.d.ts
CHANGED
|
@@ -144,7 +144,7 @@ export interface ToolState {
|
|
|
144
144
|
unselectedProxyDefault?: boolean | undefined;
|
|
145
145
|
modelClamped?: {
|
|
146
146
|
from: string;
|
|
147
|
-
reason: "card" | "noRouterPath" | "oss";
|
|
147
|
+
reason: "card" | "noRouterPath" | "oss" | "trial";
|
|
148
148
|
} | undefined;
|
|
149
149
|
shaPinned?: boolean | undefined;
|
|
150
150
|
oss?: boolean | undefined;
|
package/dist/utils/apiKeys.d.ts
CHANGED
|
@@ -49,6 +49,25 @@ export declare const ROUTER_UNFUNDED_MARKER = "your Pullfrog Router balance is e
|
|
|
49
49
|
* hand that agent the ability to suppress every other error body.
|
|
50
50
|
*/
|
|
51
51
|
export declare const CREDENTIAL_REJECTED_MARKER = "was rejected by its provider";
|
|
52
|
+
/**
|
|
53
|
+
* Three ways to arrive at "the runner has no key", each with a different CTA:
|
|
54
|
+
* we couldn't read the key you stored, your Router wallet ran dry and you have
|
|
55
|
+
* no key of your own, or you genuinely have no key. Every throw site picks by
|
|
56
|
+
* these flags.
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* Nothing in the environment can pay for this run — as distinct from a
|
|
60
|
+
* credential that IS configured but incompletely (the Bedrock/Vertex/Azure/
|
|
61
|
+
* OpenAI-compatible setup validators), an agent that could not start
|
|
62
|
+
* (`getModelsFailure`), or Pullfrog failing to hand its own secrets over.
|
|
63
|
+
*
|
|
64
|
+
* The trial fallback keys on this class, and that is the whole reason it
|
|
65
|
+
* exists: every other failure in `validateAgentApiKey` means the user HAS
|
|
66
|
+
* brought a key, so falling back would swap their model for a cheap one and
|
|
67
|
+
* swallow the message telling them what to fix.
|
|
68
|
+
*/
|
|
69
|
+
export declare class NoUsableCredentialError extends Error {
|
|
70
|
+
}
|
|
52
71
|
/**
|
|
53
72
|
* Validate that the resolved model can actually be served by the chosen
|
|
54
73
|
* agent. For routing slugs (Bedrock / Vertex) the auth shape is multi-var
|
|
@@ -135,6 +154,21 @@ export declare function isMalformedKeyError(text: string): boolean;
|
|
|
135
154
|
* user controls fixes it, so it gets its own copy instead of the re-auth CTA.
|
|
136
155
|
*/
|
|
137
156
|
export declare function isClaudeSubscriptionDisabledError(text: string): boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Kimi Code entitlement denial — the key is valid and the membership is live,
|
|
159
|
+
* but the tier doesn't include the model or the context window the run asked
|
|
160
|
+
* for (`k3` and `k3-256k` need Moderato, `kimi-for-coding-highspeed` and K3's
|
|
161
|
+
* 1M window need Allegretto). Kimi answers all of them with **401**, the same
|
|
162
|
+
* status as a revoked key, so nothing but the sentence tells them apart — and
|
|
163
|
+
* without that the run renders "rotate the key in your provider dashboard",
|
|
164
|
+
* which names three things that will not fix it.
|
|
165
|
+
*
|
|
166
|
+
* Both published shapes, parameterised over the clause that varies rather than
|
|
167
|
+
* the model id inside it, per `isOAuthCredentialExpiredError`. Listed in
|
|
168
|
+
* `isApiKeyAuthError` below so the branch is reachable whatever `type` Kimi
|
|
169
|
+
* puts in the payload. See wiki/kimi-code.md.
|
|
170
|
+
*/
|
|
171
|
+
export declare function isKimiPlanTierError(text: string): boolean;
|
|
138
172
|
export declare function isClaudeSessionLimitError(text: string): boolean;
|
|
139
173
|
/**
|
|
140
174
|
* The provider rejected a credential we checked before the agent started, and
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
* Actions job summary and the PR progress comment.
|
|
10
10
|
*
|
|
11
11
|
* Lives outside `main.ts` so adding a new error `code` branch is a one-file
|
|
12
|
-
* edit
|
|
13
|
-
* in `action/test/coverage.ts::ALWAYS_RUN_ALL`).
|
|
12
|
+
* edit rather than an orchestrator edit (see wiki/main.md).
|
|
14
13
|
*/
|
|
15
14
|
/**
|
|
16
15
|
* Billing-layer error surfaced from `/api/proxy-token` as a 402. User-actionable,
|
|
@@ -36,7 +36,7 @@ export interface BuildPullfrogFooterParams {
|
|
|
36
36
|
*/
|
|
37
37
|
clamped?: {
|
|
38
38
|
from: string;
|
|
39
|
-
reason: "card" | "noRouterPath" | "oss";
|
|
39
|
+
reason: "card" | "noRouterPath" | "oss" | "trial";
|
|
40
40
|
} | undefined;
|
|
41
41
|
/**
|
|
42
42
|
* true when the run used the default proxy model only because no model was
|
|
@@ -57,6 +57,9 @@ export interface BuildPullfrogFooterParams {
|
|
|
57
57
|
* with the phrase linking to the OSS application page.
|
|
58
58
|
*/
|
|
59
59
|
oss?: boolean | undefined;
|
|
60
|
+
/** repo owner, used to deep-link the trial disclosure at that account's own
|
|
61
|
+
* console rather than the generic landing page. */
|
|
62
|
+
owner?: string | undefined;
|
|
60
63
|
}
|
|
61
64
|
/**
|
|
62
65
|
* build a pullfrog footer with configurable parts
|
package/dist/utils/payload.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare const JsonPayload: import("arktype/internal/variants/object.ts").
|
|
|
4
4
|
"~pullfrog": true;
|
|
5
5
|
version: string;
|
|
6
6
|
prompt: string;
|
|
7
|
+
type?: string | undefined;
|
|
7
8
|
model?: string | undefined;
|
|
8
9
|
modelExplicit?: boolean | undefined;
|
|
9
10
|
effort?: string | number | undefined;
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
export declare const PROVIDER_BILLING_EXHAUSTED_LABEL = "provider billing exhausted";
|
|
3
3
|
/** Stable label for "OpenRouter can route this model nowhere you permit". */
|
|
4
4
|
export declare const PROVIDER_NO_ENDPOINTS_LABEL = "provider no routable endpoints";
|
|
5
|
+
/**
|
|
6
|
+
* A SUBSCRIPTION usage window that has run out, which is deliberately NOT
|
|
7
|
+
* `PROVIDER_BILLING_EXHAUSTED_LABEL`: that label routes to a body whose CTA is
|
|
8
|
+
* "Top up your provider balance", and a capped ChatGPT or Zen plan has no
|
|
9
|
+
* balance to top up — it resets on its own. This label carries the cause into
|
|
10
|
+
* the headline and lets the generic body stand.
|
|
11
|
+
*/
|
|
12
|
+
export declare const PROVIDER_USAGE_LIMIT_LABEL = "provider usage limit reached";
|
|
5
13
|
export declare function findAnthropicSpendCap(text: string): {
|
|
6
14
|
regainAt: string | null;
|
|
7
15
|
} | null;
|
package/dist/utils/proxy.d.ts
CHANGED
|
@@ -44,3 +44,27 @@ export declare function runProxyResolution(ctx: {
|
|
|
44
44
|
};
|
|
45
45
|
toolState: ToolState;
|
|
46
46
|
}): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Late fallback for a run inside the no-card trial whose own key search came up
|
|
49
|
+
* dry. Mints a Pullfrog-funded key on the efficient tier so a new account's
|
|
50
|
+
* first run produces a review rather than a credentials error.
|
|
51
|
+
*
|
|
52
|
+
* Deliberately runs AFTER `validateAgentApiKey` rather than beside the ordinary
|
|
53
|
+
* proxy resolution: the server grants permission but cannot see workflow `env:`
|
|
54
|
+
* keys, so only the runner knows whether anything else could have paid. Minting
|
|
55
|
+
* eagerly would silently downgrade every account whose key lives in GitHub
|
|
56
|
+
* Actions secrets.
|
|
57
|
+
*
|
|
58
|
+
* Returns false when the mint is unavailable (no OIDC, server declined), leaving
|
|
59
|
+
* the caller to raise the original missing-key error unchanged.
|
|
60
|
+
*/
|
|
61
|
+
export declare function resolveTrialFallback(ctx: {
|
|
62
|
+
payload: ResolvedPayload;
|
|
63
|
+
configuredModel: string | undefined;
|
|
64
|
+
oidcCredentials: OidcCredentials | null;
|
|
65
|
+
repo: {
|
|
66
|
+
owner: string;
|
|
67
|
+
name: string;
|
|
68
|
+
};
|
|
69
|
+
toolState: ToolState;
|
|
70
|
+
}): Promise<boolean>;
|
|
@@ -87,6 +87,10 @@ export interface RunContext {
|
|
|
87
87
|
* funding state. see wiki/billing.md.
|
|
88
88
|
*/
|
|
89
89
|
routerUnfunded?: boolean | undefined;
|
|
90
|
+
/** the account is inside its no-card trial and nothing else could fund this
|
|
91
|
+
* run — the runner may mint a subsidized efficient-tier key if, and only if,
|
|
92
|
+
* its own key search comes up dry. see the run-context route. */
|
|
93
|
+
trialFallback?: boolean | undefined;
|
|
90
94
|
}
|
|
91
95
|
/**
|
|
92
96
|
* fetch run context from Pullfrog API
|
|
@@ -97,4 +101,7 @@ export declare function fetchRunContext(params: {
|
|
|
97
101
|
token: string;
|
|
98
102
|
repoContext: RepoContext;
|
|
99
103
|
oidcToken?: string | undefined;
|
|
104
|
+
/** `payload.type` — lets the server apply this repo's per-trigger model
|
|
105
|
+
* override, which it cannot derive from owner/repo alone. */
|
|
106
|
+
runType?: string | undefined;
|
|
100
107
|
}): Promise<RunContext>;
|
|
@@ -20,10 +20,19 @@ export interface RunContextData {
|
|
|
20
20
|
/** the Router was declined because the wallet is empty. see
|
|
21
21
|
* `RunContext.routerUnfunded`. */
|
|
22
22
|
routerUnfunded?: boolean | undefined;
|
|
23
|
+
/** the account is inside its no-card trial and nothing else could fund this
|
|
24
|
+
* run, so the runner MAY mint a subsidized key on the efficient tier if its
|
|
25
|
+
* own key search comes up dry. a permission, not a routing decision — the
|
|
26
|
+
* server cannot see workflow `env:` keys. see `RunContext.trialFallback`. */
|
|
27
|
+
trialFallback?: boolean | undefined;
|
|
23
28
|
}
|
|
24
29
|
interface ResolveRunContextDataParams {
|
|
25
30
|
octokit: OctokitWithPlugins;
|
|
26
31
|
token: string;
|
|
32
|
+
/** the dispatch payload's run type, read before the payload is resolved
|
|
33
|
+
* because run-context is fetched first and needs it to pick this trigger's
|
|
34
|
+
* model override. */
|
|
35
|
+
runType?: string | undefined;
|
|
27
36
|
}
|
|
28
37
|
/**
|
|
29
38
|
* true when the action is pinned to a full commit SHA (vs the moving `@v0`
|