pullfrog 0.1.81 → 0.1.82
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/agents/opencodePlugin.d.ts +5 -0
- package/dist/cli.mjs +72 -17
- package/dist/index.js +70 -15
- package/dist/internal.js +33 -14
- package/dist/utils/runErrorRenderer.d.ts +5 -0
- package/package.json +1 -1
|
@@ -81,5 +81,10 @@ export declare const PULLFROG_OPENCODE_PLUGIN_SOURCE: string;
|
|
|
81
81
|
* session via `tool.execute.before`, complementing the runtime backstops from
|
|
82
82
|
* PR #796 (action/mcp/checkout.ts, action/mcp/git.ts). Deny-list source of
|
|
83
83
|
* truth: `action/agents/subagentToolGates.ts`.
|
|
84
|
+
*
|
|
85
|
+
* Also hard-blocks the native `bash` tool for EVERY session. bash stays in the
|
|
86
|
+
* tool list because Zen's free tier rejects a request without it (2026-09-17);
|
|
87
|
+
* `permission.bash: "ask"` is the fail-closed backstop should this plugin ever
|
|
88
|
+
* not load. see wiki/security.md.
|
|
84
89
|
*/
|
|
85
90
|
export declare function buildOpencodeSubagentGateSource(deniedTools: readonly string[]): string;
|
package/dist/cli.mjs
CHANGED
|
@@ -123005,7 +123005,7 @@ var import_picocolors = __toESM(require_picocolors(), 1);
|
|
|
123005
123005
|
// package.json
|
|
123006
123006
|
var package_default = {
|
|
123007
123007
|
name: "pullfrog",
|
|
123008
|
-
version: "0.1.
|
|
123008
|
+
version: "0.1.82",
|
|
123009
123009
|
cliContractVersion: "1",
|
|
123010
123010
|
type: "module",
|
|
123011
123011
|
bin: {
|
|
@@ -125285,12 +125285,20 @@ var providers = {
|
|
|
125285
125285
|
// the same models as `moonshotai` above, billed against a Kimi membership
|
|
125286
125286
|
// instead of a Moonshot API balance — a separate endpoint, separate model
|
|
125287
125287
|
// ids and a separate key, which is why it is a provider rather than a second
|
|
125288
|
-
// `envVars` entry. no provider injection is needed: models.dev carries
|
|
125289
|
-
//
|
|
125290
|
-
// `@ai-sdk/
|
|
125288
|
+
// `envVars` entry. no provider injection is needed: models.dev carries the
|
|
125289
|
+
// provider (api `https://api.kimi.com/coding/v1`, npm
|
|
125290
|
+
// `@ai-sdk/openai-compatible`) and opencode's env loop enables it from a bare
|
|
125291
125291
|
// `KIMI_API_KEY`, verified against our pinned opencode-ai@1.18.5 — all four
|
|
125292
125292
|
// ids list in `opencode models` and a run reaches Kimi's own auth check.
|
|
125293
125293
|
//
|
|
125294
|
+
// models.dev renamed that provider on 2026-09-18: `kimi-for-coding` became
|
|
125295
|
+
// `kimi-code-plan-cn` (api.kimi.com — where the console mints the key) and
|
|
125296
|
+
// `kimi-code-plan-global` (api.kimi.ai). opencode resolves providers from
|
|
125297
|
+
// its models.dev cache, so a `resolve` still spelling the old key names a
|
|
125298
|
+
// provider it does not know. the `resolve` targets track models.dev's key;
|
|
125299
|
+
// the provider KEY below is Pullfrog's slug and stays put. see
|
|
125300
|
+
// wiki/kimi-code.md.
|
|
125301
|
+
//
|
|
125294
125302
|
// NO `openRouterResolve` ON PURPOSE. OpenRouter cannot serve a Kimi
|
|
125295
125303
|
// membership, so a Router path here would silently bill the wallet for
|
|
125296
125304
|
// Moonshot pay-as-you-go under a slug picked for the opposite reason. The
|
|
@@ -125300,9 +125308,11 @@ var providers = {
|
|
|
125300
125308
|
// keyless Router pick to the default subsidy model with `noRouterPath`.
|
|
125301
125309
|
"kimi-for-coding": provider({
|
|
125302
125310
|
// "Kimi Code" is the product name on kimi.com/code and in the console the
|
|
125303
|
-
// key is minted from.
|
|
125304
|
-
//
|
|
125305
|
-
// `
|
|
125311
|
+
// key is minted from. the provider KEY stays `kimi-for-coding`: it is the
|
|
125312
|
+
// slug prefix every stored pick, `--model` flag and BYOK card spells, and
|
|
125313
|
+
// it is not what reaches opencode — `enabled_providers` is derived from
|
|
125314
|
+
// the `resolve` prefix (`action/agents/opencode.ts`), which is why the
|
|
125315
|
+
// two may differ here and nowhere else in this file.
|
|
125306
125316
|
displayName: "Kimi Code",
|
|
125307
125317
|
envVars: ["KIMI_API_KEY"],
|
|
125308
125318
|
models: {
|
|
@@ -125313,7 +125323,7 @@ var providers = {
|
|
|
125313
125323
|
"kimi-k3": {
|
|
125314
125324
|
displayName: "Kimi K3",
|
|
125315
125325
|
description: "1M context, but only on Allegretto and above \xB7 Moderato caps it at 256K",
|
|
125316
|
-
resolve: "kimi-
|
|
125326
|
+
resolve: "kimi-code-plan-cn/k3",
|
|
125317
125327
|
effort: ["low", "high", "max"],
|
|
125318
125328
|
subagentModel: "kimi-k2"
|
|
125319
125329
|
},
|
|
@@ -125328,7 +125338,7 @@ var providers = {
|
|
|
125328
125338
|
"kimi-k3-256k": {
|
|
125329
125339
|
displayName: "Kimi K3 256K",
|
|
125330
125340
|
description: "Same model at 256K for ~half the quota \xB7 Moderato or above",
|
|
125331
|
-
resolve: "kimi-
|
|
125341
|
+
resolve: "kimi-code-plan-cn/k3-256k",
|
|
125332
125342
|
effort: ["low", "high", "max"],
|
|
125333
125343
|
preferred: true,
|
|
125334
125344
|
subagentModel: "kimi-k2"
|
|
@@ -125336,7 +125346,7 @@ var providers = {
|
|
|
125336
125346
|
"kimi-k2": {
|
|
125337
125347
|
displayName: "Kimi K2",
|
|
125338
125348
|
description: "Included in every Kimi membership tier",
|
|
125339
|
-
resolve: "kimi-
|
|
125349
|
+
resolve: "kimi-code-plan-cn/kimi-for-coding",
|
|
125340
125350
|
// models.dev published this ladder on 2026-09-14; the catalog gate
|
|
125341
125351
|
// mirrors it, so main was red until the alias carried it too.
|
|
125342
125352
|
effort: ["low", "high", "max"]
|
|
@@ -125344,7 +125354,7 @@ var providers = {
|
|
|
125344
125354
|
"kimi-k2-highspeed": {
|
|
125345
125355
|
displayName: "Kimi K2 HighSpeed",
|
|
125346
125356
|
description: "~6x output speed for ~3x quota \xB7 needs Allegretto or above",
|
|
125347
|
-
resolve: "kimi-
|
|
125357
|
+
resolve: "kimi-code-plan-cn/kimi-for-coding-highspeed"
|
|
125348
125358
|
}
|
|
125349
125359
|
}
|
|
125350
125360
|
}),
|
|
@@ -125587,8 +125597,12 @@ var providers = {
|
|
|
125587
125597
|
"muse-spark": {
|
|
125588
125598
|
displayName: "Muse Spark",
|
|
125589
125599
|
resolve: "opencode/muse-spark-1.3",
|
|
125590
|
-
|
|
125591
|
-
|
|
125600
|
+
// models.dev dropped `max` from Zen's ladder on 2026-09-19 while the
|
|
125601
|
+
// OpenRouter and direct `meta/` routes kept it; the catalog gate
|
|
125602
|
+
// mirrors what is published per route.
|
|
125603
|
+
effort: ["minimal", "low", "medium", "high", "xhigh"],
|
|
125604
|
+
openRouterResolve: "openrouter/meta/muse-spark-1.3",
|
|
125605
|
+
openRouterEffort: ["minimal", "low", "medium", "high", "xhigh", "max"]
|
|
125592
125606
|
},
|
|
125593
125607
|
// Zen's FREE contributor tier: the same model at $0 because Meta trains
|
|
125594
125608
|
// on the prompts and completions. Zen served it to our key on 2026-09-12
|
|
@@ -125612,7 +125626,12 @@ var providers = {
|
|
|
125612
125626
|
resolve: "opencode/union-alpha",
|
|
125613
125627
|
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
125614
125628
|
// see the big-pickle note above (#1077).
|
|
125615
|
-
isFree: true
|
|
125629
|
+
isFree: true,
|
|
125630
|
+
// Zen dropped the id from `/v1/models` on 2026-09-18, two days after it
|
|
125631
|
+
// listed it, and answers a 500 for it. a stealth preview has no same-
|
|
125632
|
+
// family successor, so stored picks land on the other free stealth
|
|
125633
|
+
// model, as `minimax-m2.5-free` does.
|
|
125634
|
+
fallback: "opencode/big-pickle"
|
|
125616
125635
|
},
|
|
125617
125636
|
// Zen's live free MiMo, and the second free row in a menu that big-pickle
|
|
125618
125637
|
// was alone in since `mimo-v2-pro-free` lost its model.
|
|
@@ -135878,6 +135897,11 @@ export default async function pullfrogSubagentGatePlugin() {
|
|
|
135878
135897
|
// pick a different action.
|
|
135879
135898
|
const sessionID = typeof input?.sessionID === "string" ? input.sessionID : "";
|
|
135880
135899
|
const tool = typeof input?.tool === "string" ? input.tool : "";
|
|
135900
|
+
// above the sessionID check: the bash block must never depend on a
|
|
135901
|
+
// session id being present.
|
|
135902
|
+
if (tool === "bash") {
|
|
135903
|
+
throw new Error("the native bash tool is disabled in Pullfrog runs.");
|
|
135904
|
+
}
|
|
135881
135905
|
if (!sessionID || !tool) return;
|
|
135882
135906
|
if (orchestratorSessionID === undefined) orchestratorSessionID = sessionID;
|
|
135883
135907
|
if (sessionID === orchestratorSessionID) return;
|
|
@@ -136090,7 +136114,11 @@ var installCli = () => installOpencodeCli({ binPath: "bin/opencode.exe" });
|
|
|
136090
136114
|
function buildSecurityConfig(ctx, model) {
|
|
136091
136115
|
const config4 = {
|
|
136092
136116
|
permission: {
|
|
136093
|
-
|
|
136117
|
+
// listed but never run: Zen's free tier 403s a tool list missing `bash`,
|
|
136118
|
+
// `glob`, `grep` or `read` (2026-09-17), so the gate plugin throws on
|
|
136119
|
+
// every bash call and "ask" (no responder in serve mode) fails closed.
|
|
136120
|
+
// never switch one of those four to "deny". see wiki/security.md.
|
|
136121
|
+
bash: "ask",
|
|
136094
136122
|
edit: "allow",
|
|
136095
136123
|
read: "allow",
|
|
136096
136124
|
webfetch: "allow",
|
|
@@ -218076,6 +218104,23 @@ function isContextOverflowError(message) {
|
|
|
218076
218104
|
function isNoProviderAvailableError(message) {
|
|
218077
218105
|
return /\bNo provider available\b/i.test(message);
|
|
218078
218106
|
}
|
|
218107
|
+
function isZenFreeTierGateError(message) {
|
|
218108
|
+
return /free tier can only be used from within OpenCode/i.test(message);
|
|
218109
|
+
}
|
|
218110
|
+
function formatZenFreeTierGateSummary(input2) {
|
|
218111
|
+
const settingsUrl = `${getApiUrl()}/console/${input2.owner}/${input2.name}`;
|
|
218112
|
+
return [
|
|
218113
|
+
"**Zen's free tier refused a request this run made.** OpenCode Zen currently rejects free-model requests whose tool list is missing one of the built-in tools it expects ([upstream issue](https://github.com/anomalyco/opencode/issues/49587)). Pullfrog sends all of them, but opencode's mid-run context-compaction request carries no tools at all, and a repo-level `opencode.json` that denies `bash`, `glob`, `grep` or `read` strips that tool from every request.",
|
|
218114
|
+
"",
|
|
218115
|
+
'Pick a paid model for this repo, drop any `"deny"` on `bash`, `glob`, `grep` or `read` from the repo\'s `opencode.json` if it sets one, or split the PR so the run stays under the compaction threshold and re-trigger.',
|
|
218116
|
+
"",
|
|
218117
|
+
`[Model settings \u2192](${settingsUrl}) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`,
|
|
218118
|
+
"",
|
|
218119
|
+
`\`\`\`
|
|
218120
|
+
${input2.raw}
|
|
218121
|
+
\`\`\``
|
|
218122
|
+
].join("\n");
|
|
218123
|
+
}
|
|
218079
218124
|
function formatNoProviderAvailableSummary(input2) {
|
|
218080
218125
|
const settingsUrl = `${getApiUrl()}/console/${input2.owner}/${input2.name}`;
|
|
218081
218126
|
return [
|
|
@@ -218319,6 +218364,16 @@ ${body}`, comment: body };
|
|
|
218319
218364
|
});
|
|
218320
218365
|
return { summary: `### \u274C Pullfrog failed
|
|
218321
218366
|
|
|
218367
|
+
${body}`, comment: body };
|
|
218368
|
+
}
|
|
218369
|
+
if (isZenFreeTierGateError(input2.errorMessage)) {
|
|
218370
|
+
const body = formatZenFreeTierGateSummary({
|
|
218371
|
+
owner: input2.repo.owner,
|
|
218372
|
+
name: input2.repo.name,
|
|
218373
|
+
raw: input2.errorMessage
|
|
218374
|
+
});
|
|
218375
|
+
return { summary: `### \u274C Pullfrog failed
|
|
218376
|
+
|
|
218322
218377
|
${body}`, comment: body };
|
|
218323
218378
|
}
|
|
218324
218379
|
if (isContextOverflowError(input2.errorMessage)) {
|
|
@@ -220172,7 +220227,7 @@ function resolveTarget2(repo) {
|
|
|
220172
220227
|
return { owner: match3[1], repo: match3[2] };
|
|
220173
220228
|
}
|
|
220174
220229
|
function cliVersion() {
|
|
220175
|
-
const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.
|
|
220230
|
+
const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.82");
|
|
220176
220231
|
if (!parts) return "0.0.0";
|
|
220177
220232
|
return `${Number(parts[1])}.${Number(parts[2])}.${Number(parts[3])}`;
|
|
220178
220233
|
}
|
|
@@ -220339,7 +220394,7 @@ async function runCli8(input2) {
|
|
|
220339
220394
|
}
|
|
220340
220395
|
|
|
220341
220396
|
// cli.ts
|
|
220342
|
-
var VERSION10 = "0.1.
|
|
220397
|
+
var VERSION10 = "0.1.82";
|
|
220343
220398
|
var bin = basename2(process.argv[1] || "");
|
|
220344
220399
|
var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
|
|
220345
220400
|
var rawArgs = process.argv.slice(2);
|
package/dist/index.js
CHANGED
|
@@ -108061,12 +108061,20 @@ var providers = {
|
|
|
108061
108061
|
// the same models as `moonshotai` above, billed against a Kimi membership
|
|
108062
108062
|
// instead of a Moonshot API balance — a separate endpoint, separate model
|
|
108063
108063
|
// ids and a separate key, which is why it is a provider rather than a second
|
|
108064
|
-
// `envVars` entry. no provider injection is needed: models.dev carries
|
|
108065
|
-
//
|
|
108066
|
-
// `@ai-sdk/
|
|
108064
|
+
// `envVars` entry. no provider injection is needed: models.dev carries the
|
|
108065
|
+
// provider (api `https://api.kimi.com/coding/v1`, npm
|
|
108066
|
+
// `@ai-sdk/openai-compatible`) and opencode's env loop enables it from a bare
|
|
108067
108067
|
// `KIMI_API_KEY`, verified against our pinned opencode-ai@1.18.5 — all four
|
|
108068
108068
|
// ids list in `opencode models` and a run reaches Kimi's own auth check.
|
|
108069
108069
|
//
|
|
108070
|
+
// models.dev renamed that provider on 2026-09-18: `kimi-for-coding` became
|
|
108071
|
+
// `kimi-code-plan-cn` (api.kimi.com — where the console mints the key) and
|
|
108072
|
+
// `kimi-code-plan-global` (api.kimi.ai). opencode resolves providers from
|
|
108073
|
+
// its models.dev cache, so a `resolve` still spelling the old key names a
|
|
108074
|
+
// provider it does not know. the `resolve` targets track models.dev's key;
|
|
108075
|
+
// the provider KEY below is Pullfrog's slug and stays put. see
|
|
108076
|
+
// wiki/kimi-code.md.
|
|
108077
|
+
//
|
|
108070
108078
|
// NO `openRouterResolve` ON PURPOSE. OpenRouter cannot serve a Kimi
|
|
108071
108079
|
// membership, so a Router path here would silently bill the wallet for
|
|
108072
108080
|
// Moonshot pay-as-you-go under a slug picked for the opposite reason. The
|
|
@@ -108076,9 +108084,11 @@ var providers = {
|
|
|
108076
108084
|
// keyless Router pick to the default subsidy model with `noRouterPath`.
|
|
108077
108085
|
"kimi-for-coding": provider({
|
|
108078
108086
|
// "Kimi Code" is the product name on kimi.com/code and in the console the
|
|
108079
|
-
// key is minted from.
|
|
108080
|
-
//
|
|
108081
|
-
// `
|
|
108087
|
+
// key is minted from. the provider KEY stays `kimi-for-coding`: it is the
|
|
108088
|
+
// slug prefix every stored pick, `--model` flag and BYOK card spells, and
|
|
108089
|
+
// it is not what reaches opencode — `enabled_providers` is derived from
|
|
108090
|
+
// the `resolve` prefix (`action/agents/opencode.ts`), which is why the
|
|
108091
|
+
// two may differ here and nowhere else in this file.
|
|
108082
108092
|
displayName: "Kimi Code",
|
|
108083
108093
|
envVars: ["KIMI_API_KEY"],
|
|
108084
108094
|
models: {
|
|
@@ -108089,7 +108099,7 @@ var providers = {
|
|
|
108089
108099
|
"kimi-k3": {
|
|
108090
108100
|
displayName: "Kimi K3",
|
|
108091
108101
|
description: "1M context, but only on Allegretto and above \xB7 Moderato caps it at 256K",
|
|
108092
|
-
resolve: "kimi-
|
|
108102
|
+
resolve: "kimi-code-plan-cn/k3",
|
|
108093
108103
|
effort: ["low", "high", "max"],
|
|
108094
108104
|
subagentModel: "kimi-k2"
|
|
108095
108105
|
},
|
|
@@ -108104,7 +108114,7 @@ var providers = {
|
|
|
108104
108114
|
"kimi-k3-256k": {
|
|
108105
108115
|
displayName: "Kimi K3 256K",
|
|
108106
108116
|
description: "Same model at 256K for ~half the quota \xB7 Moderato or above",
|
|
108107
|
-
resolve: "kimi-
|
|
108117
|
+
resolve: "kimi-code-plan-cn/k3-256k",
|
|
108108
108118
|
effort: ["low", "high", "max"],
|
|
108109
108119
|
preferred: true,
|
|
108110
108120
|
subagentModel: "kimi-k2"
|
|
@@ -108112,7 +108122,7 @@ var providers = {
|
|
|
108112
108122
|
"kimi-k2": {
|
|
108113
108123
|
displayName: "Kimi K2",
|
|
108114
108124
|
description: "Included in every Kimi membership tier",
|
|
108115
|
-
resolve: "kimi-
|
|
108125
|
+
resolve: "kimi-code-plan-cn/kimi-for-coding",
|
|
108116
108126
|
// models.dev published this ladder on 2026-09-14; the catalog gate
|
|
108117
108127
|
// mirrors it, so main was red until the alias carried it too.
|
|
108118
108128
|
effort: ["low", "high", "max"]
|
|
@@ -108120,7 +108130,7 @@ var providers = {
|
|
|
108120
108130
|
"kimi-k2-highspeed": {
|
|
108121
108131
|
displayName: "Kimi K2 HighSpeed",
|
|
108122
108132
|
description: "~6x output speed for ~3x quota \xB7 needs Allegretto or above",
|
|
108123
|
-
resolve: "kimi-
|
|
108133
|
+
resolve: "kimi-code-plan-cn/kimi-for-coding-highspeed"
|
|
108124
108134
|
}
|
|
108125
108135
|
}
|
|
108126
108136
|
}),
|
|
@@ -108363,8 +108373,12 @@ var providers = {
|
|
|
108363
108373
|
"muse-spark": {
|
|
108364
108374
|
displayName: "Muse Spark",
|
|
108365
108375
|
resolve: "opencode/muse-spark-1.3",
|
|
108366
|
-
|
|
108367
|
-
|
|
108376
|
+
// models.dev dropped `max` from Zen's ladder on 2026-09-19 while the
|
|
108377
|
+
// OpenRouter and direct `meta/` routes kept it; the catalog gate
|
|
108378
|
+
// mirrors what is published per route.
|
|
108379
|
+
effort: ["minimal", "low", "medium", "high", "xhigh"],
|
|
108380
|
+
openRouterResolve: "openrouter/meta/muse-spark-1.3",
|
|
108381
|
+
openRouterEffort: ["minimal", "low", "medium", "high", "xhigh", "max"]
|
|
108368
108382
|
},
|
|
108369
108383
|
// Zen's FREE contributor tier: the same model at $0 because Meta trains
|
|
108370
108384
|
// on the prompts and completions. Zen served it to our key on 2026-09-12
|
|
@@ -108388,7 +108402,12 @@ var providers = {
|
|
|
108388
108402
|
resolve: "opencode/union-alpha",
|
|
108389
108403
|
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
108390
108404
|
// see the big-pickle note above (#1077).
|
|
108391
|
-
isFree: true
|
|
108405
|
+
isFree: true,
|
|
108406
|
+
// Zen dropped the id from `/v1/models` on 2026-09-18, two days after it
|
|
108407
|
+
// listed it, and answers a 500 for it. a stealth preview has no same-
|
|
108408
|
+
// family successor, so stored picks land on the other free stealth
|
|
108409
|
+
// model, as `minimax-m2.5-free` does.
|
|
108410
|
+
fallback: "opencode/big-pickle"
|
|
108392
108411
|
},
|
|
108393
108412
|
// Zen's live free MiMo, and the second free row in a menu that big-pickle
|
|
108394
108413
|
// was alone in since `mimo-v2-pro-free` lost its model.
|
|
@@ -109986,7 +110005,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
109986
110005
|
// package.json
|
|
109987
110006
|
var package_default = {
|
|
109988
110007
|
name: "pullfrog",
|
|
109989
|
-
version: "0.1.
|
|
110008
|
+
version: "0.1.82",
|
|
109990
110009
|
cliContractVersion: "1",
|
|
109991
110010
|
type: "module",
|
|
109992
110011
|
bin: {
|
|
@@ -118695,6 +118714,11 @@ export default async function pullfrogSubagentGatePlugin() {
|
|
|
118695
118714
|
// pick a different action.
|
|
118696
118715
|
const sessionID = typeof input?.sessionID === "string" ? input.sessionID : "";
|
|
118697
118716
|
const tool = typeof input?.tool === "string" ? input.tool : "";
|
|
118717
|
+
// above the sessionID check: the bash block must never depend on a
|
|
118718
|
+
// session id being present.
|
|
118719
|
+
if (tool === "bash") {
|
|
118720
|
+
throw new Error("the native bash tool is disabled in Pullfrog runs.");
|
|
118721
|
+
}
|
|
118698
118722
|
if (!sessionID || !tool) return;
|
|
118699
118723
|
if (orchestratorSessionID === undefined) orchestratorSessionID = sessionID;
|
|
118700
118724
|
if (sessionID === orchestratorSessionID) return;
|
|
@@ -118907,7 +118931,11 @@ var installCli = () => installOpencodeCli({ binPath: "bin/opencode.exe" });
|
|
|
118907
118931
|
function buildSecurityConfig(ctx, model) {
|
|
118908
118932
|
const config3 = {
|
|
118909
118933
|
permission: {
|
|
118910
|
-
|
|
118934
|
+
// listed but never run: Zen's free tier 403s a tool list missing `bash`,
|
|
118935
|
+
// `glob`, `grep` or `read` (2026-09-17), so the gate plugin throws on
|
|
118936
|
+
// every bash call and "ask" (no responder in serve mode) fails closed.
|
|
118937
|
+
// never switch one of those four to "deny". see wiki/security.md.
|
|
118938
|
+
bash: "ask",
|
|
118911
118939
|
edit: "allow",
|
|
118912
118940
|
read: "allow",
|
|
118913
118941
|
webfetch: "allow",
|
|
@@ -200893,6 +200921,23 @@ function isContextOverflowError(message) {
|
|
|
200893
200921
|
function isNoProviderAvailableError(message) {
|
|
200894
200922
|
return /\bNo provider available\b/i.test(message);
|
|
200895
200923
|
}
|
|
200924
|
+
function isZenFreeTierGateError(message) {
|
|
200925
|
+
return /free tier can only be used from within OpenCode/i.test(message);
|
|
200926
|
+
}
|
|
200927
|
+
function formatZenFreeTierGateSummary(input2) {
|
|
200928
|
+
const settingsUrl = `${getApiUrl()}/console/${input2.owner}/${input2.name}`;
|
|
200929
|
+
return [
|
|
200930
|
+
"**Zen's free tier refused a request this run made.** OpenCode Zen currently rejects free-model requests whose tool list is missing one of the built-in tools it expects ([upstream issue](https://github.com/anomalyco/opencode/issues/49587)). Pullfrog sends all of them, but opencode's mid-run context-compaction request carries no tools at all, and a repo-level `opencode.json` that denies `bash`, `glob`, `grep` or `read` strips that tool from every request.",
|
|
200931
|
+
"",
|
|
200932
|
+
'Pick a paid model for this repo, drop any `"deny"` on `bash`, `glob`, `grep` or `read` from the repo\'s `opencode.json` if it sets one, or split the PR so the run stays under the compaction threshold and re-trigger.',
|
|
200933
|
+
"",
|
|
200934
|
+
`[Model settings \u2192](${settingsUrl}) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`,
|
|
200935
|
+
"",
|
|
200936
|
+
`\`\`\`
|
|
200937
|
+
${input2.raw}
|
|
200938
|
+
\`\`\``
|
|
200939
|
+
].join("\n");
|
|
200940
|
+
}
|
|
200896
200941
|
function formatNoProviderAvailableSummary(input2) {
|
|
200897
200942
|
const settingsUrl = `${getApiUrl()}/console/${input2.owner}/${input2.name}`;
|
|
200898
200943
|
return [
|
|
@@ -201136,6 +201181,16 @@ ${body}`, comment: body };
|
|
|
201136
201181
|
});
|
|
201137
201182
|
return { summary: `### \u274C Pullfrog failed
|
|
201138
201183
|
|
|
201184
|
+
${body}`, comment: body };
|
|
201185
|
+
}
|
|
201186
|
+
if (isZenFreeTierGateError(input2.errorMessage)) {
|
|
201187
|
+
const body = formatZenFreeTierGateSummary({
|
|
201188
|
+
owner: input2.repo.owner,
|
|
201189
|
+
name: input2.repo.name,
|
|
201190
|
+
raw: input2.errorMessage
|
|
201191
|
+
});
|
|
201192
|
+
return { summary: `### \u274C Pullfrog failed
|
|
201193
|
+
|
|
201139
201194
|
${body}`, comment: body };
|
|
201140
201195
|
}
|
|
201141
201196
|
if (isContextOverflowError(input2.errorMessage)) {
|
package/dist/internal.js
CHANGED
|
@@ -8,7 +8,7 @@ var __export = (target, all) => {
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "pullfrog",
|
|
11
|
-
version: "0.1.
|
|
11
|
+
version: "0.1.82",
|
|
12
12
|
cliContractVersion: "1",
|
|
13
13
|
type: "module",
|
|
14
14
|
bin: {
|
|
@@ -14629,12 +14629,20 @@ var providers = {
|
|
|
14629
14629
|
// the same models as `moonshotai` above, billed against a Kimi membership
|
|
14630
14630
|
// instead of a Moonshot API balance — a separate endpoint, separate model
|
|
14631
14631
|
// ids and a separate key, which is why it is a provider rather than a second
|
|
14632
|
-
// `envVars` entry. no provider injection is needed: models.dev carries
|
|
14633
|
-
//
|
|
14634
|
-
// `@ai-sdk/
|
|
14632
|
+
// `envVars` entry. no provider injection is needed: models.dev carries the
|
|
14633
|
+
// provider (api `https://api.kimi.com/coding/v1`, npm
|
|
14634
|
+
// `@ai-sdk/openai-compatible`) and opencode's env loop enables it from a bare
|
|
14635
14635
|
// `KIMI_API_KEY`, verified against our pinned opencode-ai@1.18.5 — all four
|
|
14636
14636
|
// ids list in `opencode models` and a run reaches Kimi's own auth check.
|
|
14637
14637
|
//
|
|
14638
|
+
// models.dev renamed that provider on 2026-09-18: `kimi-for-coding` became
|
|
14639
|
+
// `kimi-code-plan-cn` (api.kimi.com — where the console mints the key) and
|
|
14640
|
+
// `kimi-code-plan-global` (api.kimi.ai). opencode resolves providers from
|
|
14641
|
+
// its models.dev cache, so a `resolve` still spelling the old key names a
|
|
14642
|
+
// provider it does not know. the `resolve` targets track models.dev's key;
|
|
14643
|
+
// the provider KEY below is Pullfrog's slug and stays put. see
|
|
14644
|
+
// wiki/kimi-code.md.
|
|
14645
|
+
//
|
|
14638
14646
|
// NO `openRouterResolve` ON PURPOSE. OpenRouter cannot serve a Kimi
|
|
14639
14647
|
// membership, so a Router path here would silently bill the wallet for
|
|
14640
14648
|
// Moonshot pay-as-you-go under a slug picked for the opposite reason. The
|
|
@@ -14644,9 +14652,11 @@ var providers = {
|
|
|
14644
14652
|
// keyless Router pick to the default subsidy model with `noRouterPath`.
|
|
14645
14653
|
"kimi-for-coding": provider({
|
|
14646
14654
|
// "Kimi Code" is the product name on kimi.com/code and in the console the
|
|
14647
|
-
// key is minted from.
|
|
14648
|
-
//
|
|
14649
|
-
// `
|
|
14655
|
+
// key is minted from. the provider KEY stays `kimi-for-coding`: it is the
|
|
14656
|
+
// slug prefix every stored pick, `--model` flag and BYOK card spells, and
|
|
14657
|
+
// it is not what reaches opencode — `enabled_providers` is derived from
|
|
14658
|
+
// the `resolve` prefix (`action/agents/opencode.ts`), which is why the
|
|
14659
|
+
// two may differ here and nowhere else in this file.
|
|
14650
14660
|
displayName: "Kimi Code",
|
|
14651
14661
|
envVars: ["KIMI_API_KEY"],
|
|
14652
14662
|
models: {
|
|
@@ -14657,7 +14667,7 @@ var providers = {
|
|
|
14657
14667
|
"kimi-k3": {
|
|
14658
14668
|
displayName: "Kimi K3",
|
|
14659
14669
|
description: "1M context, but only on Allegretto and above \xB7 Moderato caps it at 256K",
|
|
14660
|
-
resolve: "kimi-
|
|
14670
|
+
resolve: "kimi-code-plan-cn/k3",
|
|
14661
14671
|
effort: ["low", "high", "max"],
|
|
14662
14672
|
subagentModel: "kimi-k2"
|
|
14663
14673
|
},
|
|
@@ -14672,7 +14682,7 @@ var providers = {
|
|
|
14672
14682
|
"kimi-k3-256k": {
|
|
14673
14683
|
displayName: "Kimi K3 256K",
|
|
14674
14684
|
description: "Same model at 256K for ~half the quota \xB7 Moderato or above",
|
|
14675
|
-
resolve: "kimi-
|
|
14685
|
+
resolve: "kimi-code-plan-cn/k3-256k",
|
|
14676
14686
|
effort: ["low", "high", "max"],
|
|
14677
14687
|
preferred: true,
|
|
14678
14688
|
subagentModel: "kimi-k2"
|
|
@@ -14680,7 +14690,7 @@ var providers = {
|
|
|
14680
14690
|
"kimi-k2": {
|
|
14681
14691
|
displayName: "Kimi K2",
|
|
14682
14692
|
description: "Included in every Kimi membership tier",
|
|
14683
|
-
resolve: "kimi-
|
|
14693
|
+
resolve: "kimi-code-plan-cn/kimi-for-coding",
|
|
14684
14694
|
// models.dev published this ladder on 2026-09-14; the catalog gate
|
|
14685
14695
|
// mirrors it, so main was red until the alias carried it too.
|
|
14686
14696
|
effort: ["low", "high", "max"]
|
|
@@ -14688,7 +14698,7 @@ var providers = {
|
|
|
14688
14698
|
"kimi-k2-highspeed": {
|
|
14689
14699
|
displayName: "Kimi K2 HighSpeed",
|
|
14690
14700
|
description: "~6x output speed for ~3x quota \xB7 needs Allegretto or above",
|
|
14691
|
-
resolve: "kimi-
|
|
14701
|
+
resolve: "kimi-code-plan-cn/kimi-for-coding-highspeed"
|
|
14692
14702
|
}
|
|
14693
14703
|
}
|
|
14694
14704
|
}),
|
|
@@ -14931,8 +14941,12 @@ var providers = {
|
|
|
14931
14941
|
"muse-spark": {
|
|
14932
14942
|
displayName: "Muse Spark",
|
|
14933
14943
|
resolve: "opencode/muse-spark-1.3",
|
|
14934
|
-
|
|
14935
|
-
|
|
14944
|
+
// models.dev dropped `max` from Zen's ladder on 2026-09-19 while the
|
|
14945
|
+
// OpenRouter and direct `meta/` routes kept it; the catalog gate
|
|
14946
|
+
// mirrors what is published per route.
|
|
14947
|
+
effort: ["minimal", "low", "medium", "high", "xhigh"],
|
|
14948
|
+
openRouterResolve: "openrouter/meta/muse-spark-1.3",
|
|
14949
|
+
openRouterEffort: ["minimal", "low", "medium", "high", "xhigh", "max"]
|
|
14936
14950
|
},
|
|
14937
14951
|
// Zen's FREE contributor tier: the same model at $0 because Meta trains
|
|
14938
14952
|
// on the prompts and completions. Zen served it to our key on 2026-09-12
|
|
@@ -14956,7 +14970,12 @@ var providers = {
|
|
|
14956
14970
|
resolve: "opencode/union-alpha",
|
|
14957
14971
|
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
14958
14972
|
// see the big-pickle note above (#1077).
|
|
14959
|
-
isFree: true
|
|
14973
|
+
isFree: true,
|
|
14974
|
+
// Zen dropped the id from `/v1/models` on 2026-09-18, two days after it
|
|
14975
|
+
// listed it, and answers a 500 for it. a stealth preview has no same-
|
|
14976
|
+
// family successor, so stored picks land on the other free stealth
|
|
14977
|
+
// model, as `minimax-m2.5-free` does.
|
|
14978
|
+
fallback: "opencode/big-pickle"
|
|
14960
14979
|
},
|
|
14961
14980
|
// Zen's live free MiMo, and the second free row in a menu that big-pickle
|
|
14962
14981
|
// was alone in since `mimo-v2-pro-free` lost its model.
|
|
@@ -31,6 +31,11 @@
|
|
|
31
31
|
* provider declines to route it on this account's plan (OpenCode Zen's
|
|
32
32
|
* own refusal string). Same "pick another model" CTA, different reason.
|
|
33
33
|
*
|
|
34
|
+
* 4a'. Zen free-tier gate (#1377) — Zen 403s a free-tier request whose tool
|
|
35
|
+
* list is missing a built-in it expects. The harness keeps `bash` listed,
|
|
36
|
+
* but opencode's auto-compaction request carries no tools, so a long
|
|
37
|
+
* free-Zen run can still die mid-flight on the raw upstream string.
|
|
38
|
+
*
|
|
34
39
|
* 4b. Context-window overflow (#1116) — terminal `Prompt is too long` /
|
|
35
40
|
* `maximum context length is N tokens`. Actionable, so it renders on
|
|
36
41
|
* both surfaces rather than collapsing to the one-line comment.
|