pullfrog 0.1.33 → 0.1.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -99859,37 +99859,40 @@ var providers = {
99859
99859
  managedCredentials: ["CODEX_AUTH_JSON"],
99860
99860
  models: {
99861
99861
  gpt: {
99862
- displayName: "GPT",
99863
- resolve: "openai/gpt-5.5",
99864
- openRouterResolve: "openrouter/openai/gpt-5.5",
99862
+ displayName: "GPT Sol",
99863
+ resolve: "openai/gpt-5.6-sol",
99864
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
99865
99865
  preferred: true,
99866
- subagentModel: "gpt-5.4"
99866
+ subagentModel: "gpt-terra"
99867
99867
  },
99868
+ // Sol served at reasoning.mode=pro — same $/token as Sol, just more tokens
99869
+ // burned; not a pricier premium tier. models.dev has no -pro id, so direct-key
99870
+ // (BYOK) resolves to plain Sol; only the Router/OpenRouter path gets sol-pro.
99868
99871
  "gpt-pro": {
99869
- displayName: "GPT Pro",
99870
- resolve: "openai/gpt-5.5-pro",
99871
- openRouterResolve: "openrouter/openai/gpt-5.5-pro",
99872
+ displayName: "GPT Sol Pro",
99873
+ description: "Maximum reasoning effort",
99874
+ resolve: "openai/gpt-5.6-sol",
99875
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
99872
99876
  subagentModel: "gpt"
99873
99877
  },
99874
- // hidden subagent target `gpt` lenses run against this. surfacing
99875
- // it in the picker would just confuse users (it's the prior-flagship,
99876
- // and they already have `gpt` and `gpt-mini` to choose from).
99877
- "gpt-5.4": {
99878
- displayName: "GPT 5.4",
99879
- resolve: "openai/gpt-5.4",
99880
- openRouterResolve: "openrouter/openai/gpt-5.4",
99881
- hidden: true
99878
+ // gpt-5.6's balanced mid-tier (Sol/Terra/Luna are durable capability tiers,
99879
+ // not version bumps). selectable on its own and doubles as `gpt`'s cheaper
99880
+ // lens-fanout subagent replaces the old hidden gpt-5.4 subagent target.
99881
+ "gpt-terra": {
99882
+ displayName: "GPT Terra",
99883
+ resolve: "openai/gpt-5.6-terra",
99884
+ openRouterResolve: "openrouter/openai/gpt-5.6-terra"
99882
99885
  },
99883
99886
  "gpt-mini": {
99884
- displayName: "GPT Mini",
99885
- resolve: "openai/gpt-5.4-mini",
99886
- openRouterResolve: "openrouter/openai/gpt-5.4-mini"
99887
+ displayName: "GPT Luna",
99888
+ resolve: "openai/gpt-5.6-luna",
99889
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna"
99887
99890
  },
99888
99891
  // legacy aliases — openai unified the codex line into the main GPT family
99889
99892
  // and is shutting down every "-codex" snapshot on 2026-07-23. transparently
99890
99893
  // upgrade existing users via the fallback chain. UI display sites resolve
99891
99894
  // to the terminal alias's label (so dropdown trigger + PR footers show
99892
- // "GPT" / "GPT Mini", not the historical name).
99895
+ // "GPT Sol" / "GPT Luna", not the historical name).
99893
99896
  "gpt-codex": {
99894
99897
  displayName: "GPT Codex",
99895
99898
  resolve: "openai/gpt-5.3-codex",
@@ -99902,6 +99905,13 @@ var providers = {
99902
99905
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
99903
99906
  fallback: "openai/gpt-mini"
99904
99907
  },
99908
+ // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
99909
+ "gpt-5.4": {
99910
+ displayName: "GPT 5.4",
99911
+ resolve: "openai/gpt-5.4",
99912
+ openRouterResolve: "openrouter/openai/gpt-5.4",
99913
+ fallback: "openai/gpt"
99914
+ },
99905
99915
  o3: {
99906
99916
  displayName: "O3",
99907
99917
  resolve: "openai/o3",
@@ -100031,28 +100041,29 @@ var providers = {
100031
100041
  openRouterResolve: "openrouter/anthropic/claude-haiku-4.5"
100032
100042
  },
100033
100043
  gpt: {
100034
- displayName: "GPT",
100035
- resolve: "opencode/gpt-5.5",
100036
- openRouterResolve: "openrouter/openai/gpt-5.5",
100037
- subagentModel: "gpt-5.4"
100044
+ displayName: "GPT Sol",
100045
+ resolve: "opencode/gpt-5.6-sol",
100046
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100047
+ subagentModel: "gpt-terra"
100038
100048
  },
100049
+ // see openai/gpt-pro — Zen has no -pro id, so direct resolves to plain Sol.
100039
100050
  "gpt-pro": {
100040
- displayName: "GPT Pro",
100041
- resolve: "opencode/gpt-5.5-pro",
100042
- openRouterResolve: "openrouter/openai/gpt-5.5-pro",
100051
+ displayName: "GPT Sol Pro",
100052
+ description: "Maximum reasoning effort",
100053
+ resolve: "opencode/gpt-5.6-sol",
100054
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100043
100055
  subagentModel: "gpt"
100044
100056
  },
100045
- // hidden subagent target — see openai provider above for context.
100046
- "gpt-5.4": {
100047
- displayName: "GPT 5.4",
100048
- resolve: "opencode/gpt-5.4",
100049
- openRouterResolve: "openrouter/openai/gpt-5.4",
100050
- hidden: true
100057
+ // gpt-5.6 balanced mid-tierselectable + `gpt`'s subagent. see openai above.
100058
+ "gpt-terra": {
100059
+ displayName: "GPT Terra",
100060
+ resolve: "opencode/gpt-5.6-terra",
100061
+ openRouterResolve: "openrouter/openai/gpt-5.6-terra"
100051
100062
  },
100052
100063
  "gpt-mini": {
100053
- displayName: "GPT Mini",
100054
- resolve: "opencode/gpt-5.4-mini",
100055
- openRouterResolve: "openrouter/openai/gpt-5.4-mini"
100064
+ displayName: "GPT Luna",
100065
+ resolve: "opencode/gpt-5.6-luna",
100066
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna"
100056
100067
  },
100057
100068
  // legacy aliases — see openai provider above for context.
100058
100069
  "gpt-codex": {
@@ -100067,6 +100078,13 @@ var providers = {
100067
100078
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
100068
100079
  fallback: "opencode/gpt-mini"
100069
100080
  },
100081
+ // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
100082
+ "gpt-5.4": {
100083
+ displayName: "GPT 5.4",
100084
+ resolve: "opencode/gpt-5.4",
100085
+ openRouterResolve: "openrouter/openai/gpt-5.4",
100086
+ fallback: "opencode/gpt"
100087
+ },
100070
100088
  "gemini-pro": {
100071
100089
  displayName: "Gemini Pro",
100072
100090
  resolve: "opencode/gemini-3.1-pro",
@@ -100183,29 +100201,34 @@ var providers = {
100183
100201
  resolve: "openrouter/~anthropic/claude-haiku-latest",
100184
100202
  openRouterResolve: "openrouter/~anthropic/claude-haiku-latest"
100185
100203
  },
100204
+ // pinned to the explicit gpt-5.6 tiers (not the ~openai/gpt-latest rolling
100205
+ // alias): after the Sol/Terra/Luna rename, ~gpt-mini-latest no longer maps
100206
+ // to Luna, so rolling aliases would silently diverge `gpt`/`gpt-mini` from
100207
+ // the chosen tiers across funding paths.
100186
100208
  gpt: {
100187
- displayName: "GPT",
100188
- resolve: "openrouter/~openai/gpt-latest",
100189
- openRouterResolve: "openrouter/~openai/gpt-latest",
100190
- subagentModel: "gpt-5.4"
100209
+ displayName: "GPT Sol",
100210
+ resolve: "openrouter/openai/gpt-5.6-sol",
100211
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100212
+ subagentModel: "gpt-terra"
100191
100213
  },
100214
+ // see openai/gpt-pro. openrouter serves sol-pro directly on both routes.
100192
100215
  "gpt-pro": {
100193
- displayName: "GPT Pro",
100194
- resolve: "openrouter/openai/gpt-5.5-pro",
100195
- openRouterResolve: "openrouter/openai/gpt-5.5-pro",
100216
+ displayName: "GPT Sol Pro",
100217
+ description: "Maximum reasoning effort",
100218
+ resolve: "openrouter/openai/gpt-5.6-sol-pro",
100219
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100196
100220
  subagentModel: "gpt"
100197
100221
  },
100198
- // hidden subagent target — see openai provider above for context.
100199
- "gpt-5.4": {
100200
- displayName: "GPT 5.4",
100201
- resolve: "openrouter/openai/gpt-5.4",
100202
- openRouterResolve: "openrouter/openai/gpt-5.4",
100203
- hidden: true
100222
+ // gpt-5.6 balanced mid-tierselectable + `gpt`'s subagent. see openai above.
100223
+ "gpt-terra": {
100224
+ displayName: "GPT Terra",
100225
+ resolve: "openrouter/openai/gpt-5.6-terra",
100226
+ openRouterResolve: "openrouter/openai/gpt-5.6-terra"
100204
100227
  },
100205
100228
  "gpt-mini": {
100206
- displayName: "GPT Mini",
100207
- resolve: "openrouter/~openai/gpt-mini-latest",
100208
- openRouterResolve: "openrouter/~openai/gpt-mini-latest"
100229
+ displayName: "GPT Luna",
100230
+ resolve: "openrouter/openai/gpt-5.6-luna",
100231
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna"
100209
100232
  },
100210
100233
  // legacy aliases — see openai provider for context.
100211
100234
  "gpt-codex": {
@@ -100220,6 +100243,13 @@ var providers = {
100220
100243
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
100221
100244
  fallback: "openrouter/gpt-mini"
100222
100245
  },
100246
+ // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
100247
+ "gpt-5.4": {
100248
+ displayName: "GPT 5.4",
100249
+ resolve: "openrouter/openai/gpt-5.4",
100250
+ openRouterResolve: "openrouter/openai/gpt-5.4",
100251
+ fallback: "openrouter/gpt"
100252
+ },
100223
100253
  "o4-mini": {
100224
100254
  displayName: "O4 Mini",
100225
100255
  resolve: "openrouter/openai/o4-mini",
@@ -100299,6 +100329,7 @@ var modelAliases = Object.entries(providers).flatMap(
100299
100329
  slug: `${providerKey}/${modelId}`,
100300
100330
  provider: providerKey,
100301
100331
  displayName: def.displayName,
100332
+ description: def.description,
100302
100333
  resolve: def.resolve,
100303
100334
  openRouterResolve: def.openRouterResolve,
100304
100335
  preferred: def.preferred ?? false,
@@ -101041,7 +101072,7 @@ var import_semver = __toESM(require_semver2(), 1);
101041
101072
  // package.json
101042
101073
  var package_default = {
101043
101074
  name: "pullfrog",
101044
- version: "0.1.33",
101075
+ version: "0.1.35",
101045
101076
  type: "module",
101046
101077
  bin: {
101047
101078
  pullfrog: "dist/cli.mjs",
@@ -163558,6 +163589,11 @@ async function mintProxyKey(ctx) {
163558
163589
  body?.error ?? "billing service temporarily unavailable \u2014 retry shortly"
163559
163590
  );
163560
163591
  }
163592
+ if (response.status === 404) {
163593
+ throw new TransientError(
163594
+ "Pullfrog couldn't match this repository to its account \u2014 it may have just been renamed or transferred. The link refreshes automatically on the next run; if it keeps failing, reinstall the GitHub App on the repo's current owner."
163595
+ );
163596
+ }
163561
163597
  if (!response.ok) {
163562
163598
  log.warning(`proxy key mint failed (${response.status})`);
163563
163599
  return null;
@@ -164122,28 +164158,7 @@ ${genericBody}`,
164122
164158
  // utils/runLifecycle.ts
164123
164159
  var core10 = __toESM(require_core(), 1);
164124
164160
 
164125
- // utils/checksGate.ts
164126
- var OK_CONCLUSIONS = /* @__PURE__ */ new Set(["success", "neutral", "skipped"]);
164127
- var PULLFROG_CHECKS = /* @__PURE__ */ new Set(["pullfrog", "pullfrog-approval"]);
164128
- function checkRunsGate(params) {
164129
- for (const run of params.checkRuns) {
164130
- if (PULLFROG_CHECKS.has(run.name.toLowerCase())) continue;
164131
- if (run.status !== "completed")
164132
- return { ok: false, reason: `check "${run.name}" ${run.status}` };
164133
- if (!OK_CONCLUSIONS.has(run.conclusion ?? "")) {
164134
- return { ok: false, reason: `check "${run.name}" concluded ${run.conclusion}` };
164135
- }
164136
- }
164137
- return { ok: true, reason: "all checks passed" };
164138
- }
164139
- function hasVerifiedCheck(params) {
164140
- return params.checkRuns.some(
164141
- (r) => !PULLFROG_CHECKS.has(r.name.toLowerCase()) && r.status === "completed"
164142
- );
164143
- }
164144
-
164145
164161
  // utils/autoMerge.ts
164146
- var NON_MERGEABLE_STATES = /* @__PURE__ */ new Set(["dirty", "behind", "blocked"]);
164147
164162
  function hasBlockingHumanReview(reviews) {
164148
164163
  const latestByReviewer = /* @__PURE__ */ new Map();
164149
164164
  for (const review of reviews) {
@@ -164160,6 +164175,20 @@ function hasBlockingHumanReview(reviews) {
164160
164175
  }
164161
164176
  return false;
164162
164177
  }
164178
+ var ENABLE_AUTO_MERGE = (
164179
+ /* GraphQL */
164180
+ `
164181
+ mutation ($pullRequestId: ID!, $headSha: GitObjectID!) {
164182
+ enablePullRequestAutoMerge(input: {
164183
+ pullRequestId: $pullRequestId
164184
+ mergeMethod: SQUASH
164185
+ expectedHeadOid: $headSha
164186
+ }) { clientMutationId }
164187
+ }`
164188
+ );
164189
+ var isAlreadyMergeable = (error49) => error49 instanceof Error && /clean status/i.test(error49.message);
164190
+ var isHeadChanged = (error49) => error49 instanceof Error && /head has changed|expected head/i.test(error49.message);
164191
+ var isAutoMergeDisallowed = (error49) => error49 instanceof Error && /not allowed/i.test(error49.message);
164163
164192
  async function autoMergeAfterApprove(ctx) {
164164
164193
  if (!ctx.autoMergeEnabled) return;
164165
164194
  if (!ctx.prApproveEnabled) return;
@@ -164170,6 +164199,12 @@ async function autoMergeAfterApprove(ctx) {
164170
164199
  const skip = (reason) => log.info(
164171
164200
  `autoMerge: pr=#${pullNumber} approvalSha=${approval.sha?.slice(0, 7)} \u2192 skipped: ${reason}`
164172
164201
  );
164202
+ const comment = (body) => ctx.octokit.rest.issues.createComment({
164203
+ owner: ctx.repo.owner,
164204
+ repo: ctx.repo.name,
164205
+ issue_number: pullNumber,
164206
+ body: addFooter(ctx, body)
164207
+ }).catch((err) => log.debug(`autoMerge comment failed: ${err}`));
164173
164208
  const pr = await ctx.octokit.rest.pulls.get({
164174
164209
  owner: ctx.repo.owner,
164175
164210
  repo: ctx.repo.name,
@@ -164177,6 +164212,7 @@ async function autoMergeAfterApprove(ctx) {
164177
164212
  });
164178
164213
  if (pr.data.state !== "open") return skip("pr not open");
164179
164214
  if (pr.data.draft) return skip("pr is draft");
164215
+ if (pr.data.auto_merge) return skip("auto-merge already enabled");
164180
164216
  const headSha = pr.data.head.sha;
164181
164217
  if (approval.sha !== headSha) return skip(`approval sha != head ${headSha.slice(0, 7)}`);
164182
164218
  const outstanding = await countOutstandingPullfrogThreads(ctx, pullNumber);
@@ -164188,40 +164224,49 @@ async function autoMergeAfterApprove(ctx) {
164188
164224
  per_page: 100
164189
164225
  });
164190
164226
  if (hasBlockingHumanReview(reviews)) return skip("human changes requested");
164191
- if (pr.data.mergeable !== true) return skip(`not mergeable (mergeable=${pr.data.mergeable})`);
164192
- if (pr.data.mergeable_state && NON_MERGEABLE_STATES.has(pr.data.mergeable_state)) {
164193
- return skip(`mergeable_state=${pr.data.mergeable_state}`);
164227
+ try {
164228
+ await op(
164229
+ () => ctx.octokit.graphql(ENABLE_AUTO_MERGE, {
164230
+ pullRequestId: pr.data.node_id,
164231
+ headSha
164232
+ }),
164233
+ {
164234
+ name: "enablePullRequestAutoMerge",
164235
+ retries: [500, 2e3],
164236
+ bail: (error49) => !isTransientOctokitError(error49)
164237
+ }
164238
+ )();
164239
+ log.info(`autoMerge: pr=#${pullNumber} @ ${headSha.slice(0, 7)} \u2192 native auto-merge enabled`);
164240
+ await comment(
164241
+ "> \u2705 Approved \u2014 auto-merge enabled; GitHub will merge once required checks pass."
164242
+ );
164243
+ return;
164244
+ } catch (error49) {
164245
+ if (isHeadChanged(error49)) return skip("head moved during enable");
164246
+ if (isAutoMergeDisallowed(error49)) {
164247
+ await comment(
164248
+ "> \u26A0\uFE0F Approved, but auto-merge is off for this repo. Enable `Allow auto-merge` in Settings > General > Pull Requests."
164249
+ );
164250
+ return;
164251
+ }
164252
+ if (!isAlreadyMergeable(error49)) throw error49;
164194
164253
  }
164195
- const checkRuns = await ctx.octokit.paginate(ctx.octokit.rest.checks.listForRef, {
164196
- owner: ctx.repo.owner,
164197
- repo: ctx.repo.name,
164198
- ref: headSha,
164199
- per_page: 100
164200
- });
164201
- const gate = checkRunsGate({ checkRuns });
164202
- if (!gate.ok) return skip(`ci: ${gate.reason}`);
164203
- if (!hasVerifiedCheck({ checkRuns })) return skip("no completed external check-run to verify");
164254
+ const base = await ctx.octokit.rest.repos.getBranch({ owner: ctx.repo.owner, repo: ctx.repo.name, branch: pr.data.base.ref }).catch(() => null);
164255
+ if (!base?.data.protected) return skip("base branch not protected \u2014 refusing CI-ungated merge");
164204
164256
  const merge4 = await ctx.octokit.rest.pulls.merge({
164205
164257
  owner: ctx.repo.owner,
164206
164258
  repo: ctx.repo.name,
164207
164259
  pull_number: pullNumber,
164208
164260
  sha: headSha,
164209
164261
  merge_method: "squash",
164210
- commit_title: `${pr.data.title} (#${pullNumber})`,
164211
- commit_message: "merged autonomously by Pullfrog after a clean approval."
164262
+ commit_title: `${pr.data.title} (#${pullNumber})`
164212
164263
  });
164213
164264
  log.info(
164214
- `autoMerge: pr=#${pullNumber} approvalSha=${headSha.slice(0, 7)} outstanding=0 \u2192 merged ${merge4.data.sha?.slice(0, 7)}`
164265
+ `autoMerge: pr=#${pullNumber} @ ${headSha.slice(0, 7)} \u2192 merged directly ${merge4.data.sha?.slice(0, 7)}`
164266
+ );
164267
+ await comment(
164268
+ "> \u2705 Merged autonomously after Pullfrog approved this PR and resolved all of its own review threads."
164215
164269
  );
164216
- await ctx.octokit.rest.issues.createComment({
164217
- owner: ctx.repo.owner,
164218
- repo: ctx.repo.name,
164219
- issue_number: pullNumber,
164220
- body: addFooter(
164221
- ctx,
164222
- "> \u2705 Merged autonomously after Pullfrog approved this PR and resolved all of its own review threads."
164223
- )
164224
- }).catch((err) => log.debug(`autoMerge comment failed: ${err}`));
164225
164270
  }
164226
164271
 
164227
164272
  // utils/reviewCleanup.ts
@@ -8,7 +8,6 @@ export type { Mode } from "../modes.ts";
8
8
  export { modes } from "../modes.ts";
9
9
  export type { BuildPullfrogFooterParams, WorkflowRunFooterInfo, } from "../utils/buildPullfrogFooter.ts";
10
10
  export { buildPullfrogFooter, PULLFROG_DIVIDER, stripExistingFooter, } from "../utils/buildPullfrogFooter.ts";
11
- export { checkRunsGate, hasVerifiedCheck } from "../utils/checksGate.ts";
12
11
  export type { CodexAuthBody } from "../utils/codexOAuth.ts";
13
12
  export { decodeJwtExpMs, OAuthInvalidGrantError, parseCodexAuthBody, refreshCodexAuthBody, stringifyCodexAuthBody, } from "../utils/codexOAuth.ts";
14
13
  export type { ResourceUsage, UsageSummary } from "../utils/github.ts";
package/dist/internal.js CHANGED
@@ -50,37 +50,40 @@ var providers = {
50
50
  managedCredentials: ["CODEX_AUTH_JSON"],
51
51
  models: {
52
52
  gpt: {
53
- displayName: "GPT",
54
- resolve: "openai/gpt-5.5",
55
- openRouterResolve: "openrouter/openai/gpt-5.5",
53
+ displayName: "GPT Sol",
54
+ resolve: "openai/gpt-5.6-sol",
55
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
56
56
  preferred: true,
57
- subagentModel: "gpt-5.4"
57
+ subagentModel: "gpt-terra"
58
58
  },
59
+ // Sol served at reasoning.mode=pro — same $/token as Sol, just more tokens
60
+ // burned; not a pricier premium tier. models.dev has no -pro id, so direct-key
61
+ // (BYOK) resolves to plain Sol; only the Router/OpenRouter path gets sol-pro.
59
62
  "gpt-pro": {
60
- displayName: "GPT Pro",
61
- resolve: "openai/gpt-5.5-pro",
62
- openRouterResolve: "openrouter/openai/gpt-5.5-pro",
63
+ displayName: "GPT Sol Pro",
64
+ description: "Maximum reasoning effort",
65
+ resolve: "openai/gpt-5.6-sol",
66
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
63
67
  subagentModel: "gpt"
64
68
  },
65
- // hidden subagent target `gpt` lenses run against this. surfacing
66
- // it in the picker would just confuse users (it's the prior-flagship,
67
- // and they already have `gpt` and `gpt-mini` to choose from).
68
- "gpt-5.4": {
69
- displayName: "GPT 5.4",
70
- resolve: "openai/gpt-5.4",
71
- openRouterResolve: "openrouter/openai/gpt-5.4",
72
- hidden: true
69
+ // gpt-5.6's balanced mid-tier (Sol/Terra/Luna are durable capability tiers,
70
+ // not version bumps). selectable on its own and doubles as `gpt`'s cheaper
71
+ // lens-fanout subagent replaces the old hidden gpt-5.4 subagent target.
72
+ "gpt-terra": {
73
+ displayName: "GPT Terra",
74
+ resolve: "openai/gpt-5.6-terra",
75
+ openRouterResolve: "openrouter/openai/gpt-5.6-terra"
73
76
  },
74
77
  "gpt-mini": {
75
- displayName: "GPT Mini",
76
- resolve: "openai/gpt-5.4-mini",
77
- openRouterResolve: "openrouter/openai/gpt-5.4-mini"
78
+ displayName: "GPT Luna",
79
+ resolve: "openai/gpt-5.6-luna",
80
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna"
78
81
  },
79
82
  // legacy aliases — openai unified the codex line into the main GPT family
80
83
  // and is shutting down every "-codex" snapshot on 2026-07-23. transparently
81
84
  // upgrade existing users via the fallback chain. UI display sites resolve
82
85
  // to the terminal alias's label (so dropdown trigger + PR footers show
83
- // "GPT" / "GPT Mini", not the historical name).
86
+ // "GPT Sol" / "GPT Luna", not the historical name).
84
87
  "gpt-codex": {
85
88
  displayName: "GPT Codex",
86
89
  resolve: "openai/gpt-5.3-codex",
@@ -93,6 +96,13 @@ var providers = {
93
96
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
94
97
  fallback: "openai/gpt-mini"
95
98
  },
99
+ // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
100
+ "gpt-5.4": {
101
+ displayName: "GPT 5.4",
102
+ resolve: "openai/gpt-5.4",
103
+ openRouterResolve: "openrouter/openai/gpt-5.4",
104
+ fallback: "openai/gpt"
105
+ },
96
106
  o3: {
97
107
  displayName: "O3",
98
108
  resolve: "openai/o3",
@@ -222,28 +232,29 @@ var providers = {
222
232
  openRouterResolve: "openrouter/anthropic/claude-haiku-4.5"
223
233
  },
224
234
  gpt: {
225
- displayName: "GPT",
226
- resolve: "opencode/gpt-5.5",
227
- openRouterResolve: "openrouter/openai/gpt-5.5",
228
- subagentModel: "gpt-5.4"
235
+ displayName: "GPT Sol",
236
+ resolve: "opencode/gpt-5.6-sol",
237
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
238
+ subagentModel: "gpt-terra"
229
239
  },
240
+ // see openai/gpt-pro — Zen has no -pro id, so direct resolves to plain Sol.
230
241
  "gpt-pro": {
231
- displayName: "GPT Pro",
232
- resolve: "opencode/gpt-5.5-pro",
233
- openRouterResolve: "openrouter/openai/gpt-5.5-pro",
242
+ displayName: "GPT Sol Pro",
243
+ description: "Maximum reasoning effort",
244
+ resolve: "opencode/gpt-5.6-sol",
245
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
234
246
  subagentModel: "gpt"
235
247
  },
236
- // hidden subagent target — see openai provider above for context.
237
- "gpt-5.4": {
238
- displayName: "GPT 5.4",
239
- resolve: "opencode/gpt-5.4",
240
- openRouterResolve: "openrouter/openai/gpt-5.4",
241
- hidden: true
248
+ // gpt-5.6 balanced mid-tierselectable + `gpt`'s subagent. see openai above.
249
+ "gpt-terra": {
250
+ displayName: "GPT Terra",
251
+ resolve: "opencode/gpt-5.6-terra",
252
+ openRouterResolve: "openrouter/openai/gpt-5.6-terra"
242
253
  },
243
254
  "gpt-mini": {
244
- displayName: "GPT Mini",
245
- resolve: "opencode/gpt-5.4-mini",
246
- openRouterResolve: "openrouter/openai/gpt-5.4-mini"
255
+ displayName: "GPT Luna",
256
+ resolve: "opencode/gpt-5.6-luna",
257
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna"
247
258
  },
248
259
  // legacy aliases — see openai provider above for context.
249
260
  "gpt-codex": {
@@ -258,6 +269,13 @@ var providers = {
258
269
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
259
270
  fallback: "opencode/gpt-mini"
260
271
  },
272
+ // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
273
+ "gpt-5.4": {
274
+ displayName: "GPT 5.4",
275
+ resolve: "opencode/gpt-5.4",
276
+ openRouterResolve: "openrouter/openai/gpt-5.4",
277
+ fallback: "opencode/gpt"
278
+ },
261
279
  "gemini-pro": {
262
280
  displayName: "Gemini Pro",
263
281
  resolve: "opencode/gemini-3.1-pro",
@@ -374,29 +392,34 @@ var providers = {
374
392
  resolve: "openrouter/~anthropic/claude-haiku-latest",
375
393
  openRouterResolve: "openrouter/~anthropic/claude-haiku-latest"
376
394
  },
395
+ // pinned to the explicit gpt-5.6 tiers (not the ~openai/gpt-latest rolling
396
+ // alias): after the Sol/Terra/Luna rename, ~gpt-mini-latest no longer maps
397
+ // to Luna, so rolling aliases would silently diverge `gpt`/`gpt-mini` from
398
+ // the chosen tiers across funding paths.
377
399
  gpt: {
378
- displayName: "GPT",
379
- resolve: "openrouter/~openai/gpt-latest",
380
- openRouterResolve: "openrouter/~openai/gpt-latest",
381
- subagentModel: "gpt-5.4"
400
+ displayName: "GPT Sol",
401
+ resolve: "openrouter/openai/gpt-5.6-sol",
402
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
403
+ subagentModel: "gpt-terra"
382
404
  },
405
+ // see openai/gpt-pro. openrouter serves sol-pro directly on both routes.
383
406
  "gpt-pro": {
384
- displayName: "GPT Pro",
385
- resolve: "openrouter/openai/gpt-5.5-pro",
386
- openRouterResolve: "openrouter/openai/gpt-5.5-pro",
407
+ displayName: "GPT Sol Pro",
408
+ description: "Maximum reasoning effort",
409
+ resolve: "openrouter/openai/gpt-5.6-sol-pro",
410
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
387
411
  subagentModel: "gpt"
388
412
  },
389
- // hidden subagent target — see openai provider above for context.
390
- "gpt-5.4": {
391
- displayName: "GPT 5.4",
392
- resolve: "openrouter/openai/gpt-5.4",
393
- openRouterResolve: "openrouter/openai/gpt-5.4",
394
- hidden: true
413
+ // gpt-5.6 balanced mid-tierselectable + `gpt`'s subagent. see openai above.
414
+ "gpt-terra": {
415
+ displayName: "GPT Terra",
416
+ resolve: "openrouter/openai/gpt-5.6-terra",
417
+ openRouterResolve: "openrouter/openai/gpt-5.6-terra"
395
418
  },
396
419
  "gpt-mini": {
397
- displayName: "GPT Mini",
398
- resolve: "openrouter/~openai/gpt-mini-latest",
399
- openRouterResolve: "openrouter/~openai/gpt-mini-latest"
420
+ displayName: "GPT Luna",
421
+ resolve: "openrouter/openai/gpt-5.6-luna",
422
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna"
400
423
  },
401
424
  // legacy aliases — see openai provider for context.
402
425
  "gpt-codex": {
@@ -411,6 +434,13 @@ var providers = {
411
434
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
412
435
  fallback: "openrouter/gpt-mini"
413
436
  },
437
+ // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
438
+ "gpt-5.4": {
439
+ displayName: "GPT 5.4",
440
+ resolve: "openrouter/openai/gpt-5.4",
441
+ openRouterResolve: "openrouter/openai/gpt-5.4",
442
+ fallback: "openrouter/gpt"
443
+ },
414
444
  "o4-mini": {
415
445
  displayName: "O4 Mini",
416
446
  resolve: "openrouter/openai/o4-mini",
@@ -499,6 +529,7 @@ var modelAliases = Object.entries(providers).flatMap(
499
529
  slug: `${providerKey}/${modelId}`,
500
530
  provider: providerKey,
501
531
  displayName: def.displayName,
532
+ description: def.description,
502
533
  resolve: def.resolve,
503
534
  openRouterResolve: def.openRouterResolve,
504
535
  preferred: def.preferred ?? false,
@@ -1245,26 +1276,6 @@ function stripExistingFooter(body) {
1245
1276
  return body.substring(0, dividerIndex).trimEnd();
1246
1277
  }
1247
1278
 
1248
- // utils/checksGate.ts
1249
- var OK_CONCLUSIONS = /* @__PURE__ */ new Set(["success", "neutral", "skipped"]);
1250
- var PULLFROG_CHECKS = /* @__PURE__ */ new Set(["pullfrog", "pullfrog-approval"]);
1251
- function checkRunsGate(params) {
1252
- for (const run of params.checkRuns) {
1253
- if (PULLFROG_CHECKS.has(run.name.toLowerCase())) continue;
1254
- if (run.status !== "completed")
1255
- return { ok: false, reason: `check "${run.name}" ${run.status}` };
1256
- if (!OK_CONCLUSIONS.has(run.conclusion ?? "")) {
1257
- return { ok: false, reason: `check "${run.name}" concluded ${run.conclusion}` };
1258
- }
1259
- }
1260
- return { ok: true, reason: "all checks passed" };
1261
- }
1262
- function hasVerifiedCheck(params) {
1263
- return params.checkRuns.some(
1264
- (r) => !PULLFROG_CHECKS.has(r.name.toLowerCase()) && r.status === "completed"
1265
- );
1266
- }
1267
-
1268
1279
  // utils/codexOAuth.ts
1269
1280
  var CODEX_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
1270
1281
  var CODEX_OAUTH_TOKEN_URL = "https://auth.openai.com/oauth/token";
@@ -1492,7 +1503,6 @@ export {
1492
1503
  PULLFROG_DIVIDER,
1493
1504
  TIMEOUT_DISABLED,
1494
1505
  buildPullfrogFooter,
1495
- checkRunsGate,
1496
1506
  createLeapingProgressComment,
1497
1507
  decodeJwtExpMs,
1498
1508
  defaultAutoTier,
@@ -1503,7 +1513,6 @@ export {
1503
1513
  getModelProvider,
1504
1514
  getProgressComment,
1505
1515
  getProviderDisplayName,
1506
- hasVerifiedCheck,
1507
1516
  isAutoTier,
1508
1517
  isCardGatedModel,
1509
1518
  isLeapingIntoActionCommentBody,
package/dist/models.d.ts CHANGED
@@ -28,6 +28,9 @@ export interface ModelAlias {
28
28
  provider: string;
29
29
  /** human-readable name shown in dropdowns */
30
30
  displayName: string;
31
+ /** optional one-line picker sub-label clarifying what the alias is (e.g.
32
+ * gpt-pro = "Maximum reasoning effort"). undefined for most aliases. */
33
+ description: string | undefined;
31
34
  /** concrete models.dev specifier, e.g. "anthropic/claude-opus-4-6". sentinel for routing entries — never passed to a CLI directly. */
32
35
  resolve: string;
33
36
  /** full models.dev specifier for the OpenRouter equivalent (undefined for free models and routing entries) */
@@ -48,12 +51,14 @@ export interface ModelAlias {
48
51
  * use as its lens-fanout subagent. e.g. claude-opus → "claude-sonnet". */
49
52
  subagentModel: string | undefined;
50
53
  /** hide from selectable lists (UI dropdowns, CLI pickers). does NOT affect
51
- * resolution — for that use `fallback`. used for internal-only tier targets
52
- * (e.g. gpt-5.4 as a subagent target without exposing it to users). */
54
+ * resolution — for that use `fallback`. used to keep a redundant alias out of
55
+ * pickers (e.g. the free `minimax-m2.5-free` duplicate). */
53
56
  hidden: boolean;
54
57
  }
55
58
  interface ModelDef {
56
59
  displayName: string;
60
+ /** optional one-line picker sub-label (e.g. "Maximum reasoning effort"). */
61
+ description?: string;
57
62
  /** concrete models.dev specifier, e.g. "anthropic/claude-opus-4-6" */
58
63
  resolve: string;
59
64
  /** full models.dev specifier for the OpenRouter equivalent, e.g. "openrouter/anthropic/claude-opus-4.6" */