pullfrog 0.1.29 → 0.1.31

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.
Files changed (60) hide show
  1. package/dist/agents/claudePretoolGate.d.ts +5 -1
  2. package/dist/agents/opencodePlugin.d.ts +2 -2
  3. package/dist/agents/postRun.d.ts +8 -31
  4. package/dist/agents/shared.d.ts +6 -0
  5. package/dist/agents/subagentToolGates.d.ts +22 -40
  6. package/dist/cli.mjs +63989 -59666
  7. package/dist/external.d.ts +45 -2
  8. package/dist/index.js +62509 -58186
  9. package/dist/internal/index.d.ts +2 -2
  10. package/dist/internal.js +99 -33
  11. package/dist/mcp/checkSuite.d.ts +3 -1
  12. package/dist/mcp/checkout.d.ts +4 -2
  13. package/dist/mcp/comment.d.ts +12 -4
  14. package/dist/mcp/commitInfo.d.ts +3 -1
  15. package/dist/mcp/dependencies.d.ts +6 -2
  16. package/dist/mcp/git.d.ts +32 -6
  17. package/dist/mcp/issue.d.ts +26 -1
  18. package/dist/mcp/issueComments.d.ts +3 -1
  19. package/dist/mcp/issueEvents.d.ts +3 -1
  20. package/dist/mcp/issueInfo.d.ts +3 -1
  21. package/dist/mcp/labels.d.ts +16 -1
  22. package/dist/mcp/output.d.ts +6 -2
  23. package/dist/mcp/pr.d.ts +19 -2
  24. package/dist/mcp/prInfo.d.ts +3 -1
  25. package/dist/mcp/resolveRepoCtx.d.ts +34 -0
  26. package/dist/mcp/review.d.ts +9 -3
  27. package/dist/mcp/reviewComments.d.ts +9 -3
  28. package/dist/mcp/selectMode.d.ts +3 -1
  29. package/dist/mcp/server.d.ts +7 -1
  30. package/dist/mcp/shared.d.ts +18 -1
  31. package/dist/mcp/shell.d.ts +6 -2
  32. package/dist/mcp/upload.d.ts +3 -1
  33. package/dist/mcp/xrepo.d.ts +15 -0
  34. package/dist/models.d.ts +58 -5
  35. package/dist/modes.d.ts +1 -1
  36. package/dist/toolState.d.ts +66 -16
  37. package/dist/utils/apiCommit.d.ts +40 -0
  38. package/dist/utils/apiKeys.d.ts +19 -0
  39. package/dist/utils/buildPullfrogFooter.d.ts +27 -0
  40. package/dist/utils/claudeSubscription.d.ts +30 -0
  41. package/dist/utils/errorReport.d.ts +2 -2
  42. package/dist/utils/github.d.ts +28 -2
  43. package/dist/utils/instructions.d.ts +11 -0
  44. package/dist/utils/isTransientNetworkError.d.ts +10 -0
  45. package/dist/utils/learnings.d.ts +14 -0
  46. package/dist/utils/modelAccess.d.ts +64 -0
  47. package/dist/utils/openCodeModels.d.ts +2 -2
  48. package/dist/utils/payload.d.ts +16 -0
  49. package/dist/utils/proxy.d.ts +3 -5
  50. package/dist/utils/runContext.d.ts +4 -0
  51. package/dist/utils/runContextData.d.ts +10 -0
  52. package/dist/utils/runErrorRenderer.d.ts +2 -2
  53. package/dist/utils/setup.d.ts +18 -3
  54. package/dist/utils/token.d.ts +22 -3
  55. package/dist/yes/index.d.ts +32 -0
  56. package/dist/yes/standard-schema.d.ts +117 -0
  57. package/dist/yes.js +1244 -0
  58. package/package.json +19 -10
  59. package/dist/utils/byokFallback.d.ts +0 -44
  60. package/dist/utils/retry.d.ts +0 -13
@@ -2,8 +2,8 @@
2
2
  * Internal entrypoint for the root app.
3
3
  * Re-exports shared types, values, and utilities needed by the Next.js app.
4
4
  */
5
- export type { AuthorPermission, ModelAlias, ModelProvider, Payload, PayloadEvent, ProviderConfig, PushPermission, ShellPermission, ToolPermission, WriteablePayload, } from "../external.ts";
6
- export { DEFAULT_PROXY_MODEL, getAutoSelectHintModel, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, modelAliases, parseModel, providers, pullfrogMcpName, resolveCliModel, resolveDisplayAlias, resolveModelSlug, resolveOpenRouterModel, } from "../external.ts";
5
+ export type { AuthorPermission, AutoTier, ModelAlias, ModelProvider, Payload, PayloadEvent, ProviderConfig, PushPermission, ShellPermission, ToolPermission, WriteablePayload, XrepoConfig, } from "../external.ts";
6
+ export { AUTO_EFFICIENT, AUTO_INTELLIGENT, DEFAULT_PROXY_MODEL, defaultAutoTier, getAutoSelectHintModel, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, isAutoTier, isCardGatedModel, modelAliases, parseModel, providers, pullfrogMcpName, resolveAutoTier, resolveCliModel, resolveDisplayAlias, resolveModelSlug, resolveOpenRouterModel, } from "../external.ts";
7
7
  export type { Mode } from "../modes.ts";
8
8
  export { modes } from "../modes.ts";
9
9
  export type { BuildPullfrogFooterParams, WorkflowRunFooterInfo, } from "../utils/buildPullfrogFooter.ts";
package/dist/internal.js CHANGED
@@ -9,6 +9,17 @@ var providers = {
9
9
  displayName: "Anthropic",
10
10
  envVars: ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"],
11
11
  models: {
12
+ // claude-fable-5 is disabled globally — access has been revoked, so it
13
+ // can't run as-is anywhere (BYOK, Claude Code, or Router). the fallback
14
+ // redirects all resolution to opus and hides it from pickers; opus is the
15
+ // universally-available flagship, the AUTO_INTELLIGENT tier target, and
16
+ // the recommended pick. clear the fallback if fable access returns (#959).
17
+ "claude-fable": {
18
+ displayName: "Claude Fable",
19
+ resolve: "anthropic/claude-fable-5",
20
+ fallback: "anthropic/claude-opus",
21
+ subagentModel: "claude-sonnet"
22
+ },
12
23
  "claude-opus": {
13
24
  displayName: "Claude Opus",
14
25
  resolve: "anthropic/claude-opus-4-8",
@@ -79,7 +90,8 @@ var providers = {
79
90
  },
80
91
  o3: {
81
92
  displayName: "O3",
82
- resolve: "openai/o3"
93
+ resolve: "openai/o3",
94
+ openRouterResolve: "openrouter/openai/o3"
83
95
  }
84
96
  }
85
97
  }),
@@ -171,8 +183,8 @@ var providers = {
171
183
  models: {
172
184
  "kimi-k2": {
173
185
  displayName: "Kimi K2",
174
- resolve: "moonshotai/kimi-k2.6",
175
- openRouterResolve: "openrouter/moonshotai/kimi-k2.6",
186
+ resolve: "moonshotai/kimi-k2.7-code",
187
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code",
176
188
  preferred: true
177
189
  }
178
190
  }
@@ -254,8 +266,10 @@ var providers = {
254
266
  },
255
267
  "kimi-k2": {
256
268
  displayName: "Kimi K2",
269
+ // opencode Zen serves only up to k2.6; the OpenRouter fallback (used for
270
+ // router/oss proxy runs) takes the newer k2.7-code.
257
271
  resolve: "opencode/kimi-k2.6",
258
- openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
272
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
259
273
  },
260
274
  "minimax-m2.5": {
261
275
  displayName: "MiniMax M2",
@@ -290,9 +304,14 @@ var providers = {
290
304
  models: {
291
305
  "glm-5.1": {
292
306
  displayName: "GLM 5.1",
293
- resolve: "opencode-go/glm-5.1",
294
- openRouterResolve: "openrouter/z-ai/glm-5.1",
307
+ resolve: "opencode-go/glm-5.2",
308
+ openRouterResolve: "openrouter/z-ai/glm-5.2",
295
309
  preferred: true
310
+ },
311
+ "kimi-k2": {
312
+ displayName: "Kimi K2",
313
+ resolve: "opencode-go/kimi-k2.7-code",
314
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
296
315
  }
297
316
  }
298
317
  }),
@@ -428,8 +447,8 @@ var providers = {
428
447
  },
429
448
  "kimi-k2": {
430
449
  displayName: "Kimi K2",
431
- resolve: "openrouter/moonshotai/kimi-k2.6",
432
- openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
450
+ resolve: "openrouter/moonshotai/kimi-k2.7-code",
451
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
433
452
  },
434
453
  "minimax-m2.5": {
435
454
  displayName: "MiniMax M2",
@@ -488,21 +507,31 @@ var modelAliases = Object.entries(providers).flatMap(
488
507
  hidden: def.hidden ?? false
489
508
  }))
490
509
  );
491
- var defaultProxyAlias = modelAliases.find((a) => a.slug === "deepseek/deepseek-pro");
492
- if (!defaultProxyAlias?.openRouterResolve) {
493
- throw new Error("DEFAULT_PROXY_MODEL: deepseek/deepseek-pro missing openRouterResolve");
510
+ var AUTO_EFFICIENT = "auto/efficient";
511
+ var AUTO_INTELLIGENT = "auto/intelligent";
512
+ var AUTO_TIER_TARGET = {
513
+ [AUTO_EFFICIENT]: "moonshotai/kimi-k2",
514
+ [AUTO_INTELLIGENT]: "anthropic/claude-opus"
515
+ };
516
+ function isAutoTier(slug) {
517
+ return slug === AUTO_EFFICIENT || slug === AUTO_INTELLIGENT;
494
518
  }
495
- var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
496
- var defaultProxyDisplayName = defaultProxyAlias.displayName;
497
- function getAutoSelectHintModel() {
498
- return defaultProxyDisplayName;
519
+ function defaultAutoTier(hasCard) {
520
+ return hasCard ? AUTO_INTELLIGENT : AUTO_EFFICIENT;
521
+ }
522
+ function resolveAutoTier(params) {
523
+ if (!params.hasCard) return AUTO_EFFICIENT;
524
+ return isAutoTier(params.model) ? params.model : defaultAutoTier(params.hasCard);
525
+ }
526
+ function isCardGatedModel(slug) {
527
+ return resolveOpenRouterModel(slug) !== void 0;
499
528
  }
500
529
  function resolveModelSlug(slug) {
501
530
  return modelAliases.find((a) => a.slug === slug)?.resolve;
502
531
  }
503
532
  var MAX_FALLBACK_DEPTH = 10;
504
533
  function resolveDisplayAlias(slug) {
505
- let current = slug;
534
+ let current = isAutoTier(slug) ? AUTO_TIER_TARGET[slug] : slug;
506
535
  const visited = /* @__PURE__ */ new Set();
507
536
  for (let i = 0; i < MAX_FALLBACK_DEPTH; i++) {
508
537
  if (visited.has(current)) return void 0;
@@ -520,6 +549,15 @@ function resolveCliModel(slug) {
520
549
  function resolveOpenRouterModel(slug) {
521
550
  return resolveDisplayAlias(slug)?.openRouterResolve;
522
551
  }
552
+ var defaultProxyAlias = resolveDisplayAlias(AUTO_EFFICIENT);
553
+ if (!defaultProxyAlias?.openRouterResolve) {
554
+ throw new Error(`DEFAULT_PROXY_MODEL: ${AUTO_EFFICIENT} has no openRouterResolve`);
555
+ }
556
+ var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
557
+ var defaultProxyDisplayName = defaultProxyAlias.displayName;
558
+ function getAutoSelectHintModel() {
559
+ return defaultProxyDisplayName;
560
+ }
523
561
 
524
562
  // external.ts
525
563
  var pullfrogMcpName = "pullfrog";
@@ -679,8 +717,10 @@ Inline comments use the same severity framing as body \`### \` sections, scaled
679
717
  - **Don't repeat diff content**, don't include raw \`+123 / -45\` stats, don't include a changelog section, don't use horizontal rules (\`---\`).
680
718
  - **Pull file/commit counts from \`checkout_pr\` metadata** \u2014 never count manually.
681
719
  - **Legacy headings REMOVED.** Do not use \`### Key changes\`, \`### Issues found\`, \`<b>TL;DR</b>\`, or \`<sub><b>Summary</b>\`. The new structure subsumes them.`;
682
- function computeModes(agentId) {
720
+ function computeModes(agentId, signedCommits = false) {
683
721
  const t = (toolName) => formatMcpToolRef(agentId, toolName);
722
+ const commitStep = signedCommits ? `commit via \`${t("commit_changes")}\` \u2014 it lands a GitHub-signed commit directly on the remote branch (no push step)` : `commit locally via shell (\`git add . && git commit -m "..."\`)`;
723
+ const finalizeStep = signedCommits ? `confirm a clean working tree (\`git status\`) \u2014 your \`${t("commit_changes")}\` calls already landed the work on the remote` : `confirm a clean working tree, then push via \`${t("push_branch")}\``;
684
724
  return [
685
725
  {
686
726
  name: "Build",
@@ -751,10 +791,10 @@ function computeModes(agentId) {
751
791
  - Do NOT defect-hunt the diff yourself in parallel with the subagent. Your role is dispatch + evaluation; doing the review yourself reintroduces the implementation bias the subagent is meant to mitigate.
752
792
  - For diffs that rely on third-party API contracts, SDK semantics, framework directives, or DB engine specifics, instruct the subagent to verify load-bearing claims via web search and quote source URLs rather than trust training data \u2014 this is the single most common review-quality failure mode.
753
793
 
754
- Be **discerning** about what comes back. The reviewer is an AI subagent and is fallible \u2014 treat every finding as a hypothesis, not a directive, and **verify each one yourself** against the diff and the code before deciding whether to apply. You are searching for a solution that is **complete, minimal, and elegant** \u2014 you may need to think hard to find it. Do not over-engineer, do not be over-defensive, **do not write AI slop**. Reviewers bias toward *recommending additions*, and that bias has a recognizable slop texture: defensive checks for cases that cannot happen, extra logging, new abstractions used once, comments restating code, tests asserting tautologies, "just-in-case" guards, error handlers for cases the type system already rules out. Reject those. For each surviving finding, ask: would applying it leave the code more sound, correct, AND elegant? Two-out-of-three means look harder for a fix that gets all three before settling. After applying the fixes you accept, re-read your diff and be discerning about what *you just changed*: if any fix turned out to be bloat in context, revert it. Then verify only intended changes are present, no debug artifacts or commented-out code remain, no unrelated files were modified. Commit locally via shell (\`git add . && git commit -m "..."\`).
794
+ Be **discerning** about what comes back. The reviewer is an AI subagent and is fallible \u2014 treat every finding as a hypothesis, not a directive, and **verify each one yourself** against the diff and the code before deciding whether to apply. You are searching for a solution that is **complete, minimal, and elegant** \u2014 you may need to think hard to find it. Do not over-engineer, do not be over-defensive, **do not write AI slop**. Reviewers bias toward *recommending additions*, and that bias has a recognizable slop texture: defensive checks for cases that cannot happen, extra logging, new abstractions used once, comments restating code, tests asserting tautologies, "just-in-case" guards, error handlers for cases the type system already rules out. Reject those. For each surviving finding, ask: would applying it leave the code more sound, correct, AND elegant? Two-out-of-three means look harder for a fix that gets all three before settling. After applying the fixes you accept, re-read your diff and be discerning about what *you just changed*: if any fix turned out to be bloat in context, revert it. Then verify only intended changes are present, no debug artifacts or commented-out code remain, no unrelated files were modified. Then ${commitStep}.
755
795
 
756
796
  6. **finalize**:
757
- - confirm a clean working tree, then push via \`${t("push_branch")}\` (see *SYSTEM* Git rules if this fails \u2014 prepush errors are usually the repo's tests/lint, not infra timeouts)
797
+ - ${finalizeStep} (see *SYSTEM* Git rules if this fails \u2014 prepush errors are usually the repo's tests/lint, not infra timeouts)
758
798
  - create a PR via \`${t("create_pull_request")}\`
759
799
  - call \`${t("report_progress")}\` with the PR link or the exact error if push/PR failed
760
800
 
@@ -782,12 +822,12 @@ For simple, well-defined tasks, skip the plan phase and go straight to build.`
782
822
 
783
823
  5. Quality check:
784
824
  - test changes, then review the diff before committing \u2014 verify only intended changes are present, no debug artifacts remain, no fix turned out to be bloat in context (revert any that did), and the changes are clean enough that a senior engineer would approve without hesitation
785
- - commit locally via shell (\`git add . && git commit -m "..."\`)
825
+ - ${commitStep}
786
826
 
787
827
  6. Finalize. Reply + resolve are paired write actions: do BOTH or NEITHER for each thread.
788
- - confirm a clean working tree, then push via \`${t("push_branch")}\` (same push/prepush guidance as Build mode in *SYSTEM*)
789
- - **if push fails**, call \`${t("report_progress")}\` with the exact error and STOP \u2014 do NOT reply or resolve any thread until the fix is live on the remote. Resolving a thread without the fix landing misleads the reviewer.
790
- - **on push success**, for each thread you acted on:
828
+ - ${finalizeStep} (same push/prepush guidance as Build mode in *SYSTEM*)
829
+ - **if the push/commit fails**, call \`${t("report_progress")}\` with the exact error and STOP \u2014 do NOT reply or resolve any thread until the fix is live on the remote. Resolving a thread without the fix landing misleads the reviewer.
830
+ - **once the fix is live on the remote**, for each thread you acted on:
791
831
  - reply ONCE via \`${t("reply_to_review_comment")}\`. The \`comment_id\` parameter takes the root comment's numeric \`id=\` (from the first \`comment author=...\` tag in the \`${t("get_review_comments")}\` output) \u2014 NOT the \`thread=\` value; that's a separate GraphQL ID used by resolve. The runtime dedupes identical bodies within a session.
792
832
  - **immediately** call \`${t("resolve_review_thread")}\` with that thread's \`thread=\` value as \`thread_id\`. Resolve every thread where you (a) made the requested code change in full \u2014 partial fixes leave the thread open \u2014 OR (b) replied with a substantive answer the user explicitly asked for. Do NOT resolve threads where you pushed back on the request and the disagreement is unresolved; leave those open for the human to mediate.
793
833
  - call \`${t("report_progress")}\` with a brief summary`
@@ -1062,10 +1102,10 @@ ${PR_SUMMARY_FORMAT}`
1062
1102
  - fix the issue using your native file and shell tools
1063
1103
  - verify the fix by re-running the exact CI command
1064
1104
  - review the diff before committing \u2014 verify only the fix is present, no debug artifacts, no unrelated changes. the fix should be clean enough that a senior engineer would approve without hesitation.
1065
- - commit locally via shell (\`git add . && git commit -m "..."\`)
1105
+ - ${commitStep}
1066
1106
 
1067
1107
  6. Finalize:
1068
- - confirm a clean working tree, then push via \`${t("push_branch")}\` (same push/prepush guidance as Build mode in *SYSTEM*)
1108
+ - ${finalizeStep} (same push/prepush guidance as Build mode in *SYSTEM*)
1069
1109
  - call \`${t("report_progress")}\` with the diagnosis and fix summary (or the exact push error if push failed)`
1070
1110
  },
1071
1111
  {
@@ -1081,8 +1121,8 @@ ${PR_SUMMARY_FORMAT}`
1081
1121
  - Call \`${t("git_fetch")}\` to fetch the base branch.
1082
1122
 
1083
1123
  3. **Merge Attempt**:
1084
- - Run \`git merge origin/<base_branch>\` via shell.
1085
- - If it succeeds automatically, confirm a clean working tree, push via \`${t("push_branch")}\` (same push/prepush guidance as Build mode in *SYSTEM*), and call \`${t("report_progress")}\` with a brief success note or the exact push error if push failed \u2014 **then stop; do not run steps 4\u20135.**
1124
+ - Run \`git merge ${signedCommits ? "--no-commit " : ""}origin/<base_branch>\` via shell.
1125
+ - If it succeeds automatically, ${signedCommits ? `conclude it via \`${t("commit_changes")}\` (it turns the pending merge into a signed merge commit on the remote)` : `confirm a clean working tree, push via \`${t("push_branch")}\` (same push/prepush guidance as Build mode in *SYSTEM*)`}, and call \`${t("report_progress")}\` with a brief success note or the exact error if it failed \u2014 **then stop; do not run steps 4\u20135.**
1086
1126
  - If it fails (conflicts), resolve them manually (continue to steps 4\u20135).
1087
1127
 
1088
1128
  4. **Resolve Conflicts**:
@@ -1092,8 +1132,8 @@ ${PR_SUMMARY_FORMAT}`
1092
1132
 
1093
1133
  5. **Finalize**:
1094
1134
  - Run a final verification (build/test) to ensure the resolution works.
1095
- - \`git add . && git commit -m "resolve merge conflicts"\`
1096
- - confirm a clean working tree, then push via \`${t("push_branch")}\` (same push/prepush guidance as Build mode in *SYSTEM*)
1135
+ - ${signedCommits ? `\`git add .\`, then conclude via \`${t("commit_changes")}\` with message "resolve merge conflicts"` : `\`git add . && git commit -m "resolve merge conflicts"\``}
1136
+ - ${finalizeStep} (same push/prepush guidance as Build mode in *SYSTEM*)
1097
1137
  - Call \`${t("report_progress")}\` with a summary of what was resolved (or the exact push error if push failed)`
1098
1138
  },
1099
1139
  {
@@ -1112,7 +1152,7 @@ ${PR_SUMMARY_FORMAT}`
1112
1152
  - if code changes are needed: review your own diff before committing \u2014 verify only intended changes are present, no debug artifacts remain, and the changes are clean enough that a senior engineer would approve without hesitation
1113
1153
 
1114
1154
  4. Finalize:
1115
- - if code changes were made, push to a pull request (new or existing) using \`${t("push_branch")}\` and \`${t("create_pull_request")}\` as needed. \`git status\` must be clean before you finish (see *SYSTEM* Git rules if push fails).
1155
+ - if code changes were made, get them onto a pull request (new or existing) using ${signedCommits ? `\`${t("commit_changes")}\`` : `\`${t("push_branch")}\``} and \`${t("create_pull_request")}\` as needed. \`git status\` must be clean before you finish (see *SYSTEM* Git rules if this fails).
1116
1156
  - call \`${t("report_progress")}\` once with results \u2014 include exact tool errors if push or PR creation failed
1117
1157
  - if the task involved labeling, commenting, or other GitHub operations, perform those directly`
1118
1158
  }
@@ -1143,11 +1183,25 @@ function formatModelLabel(params) {
1143
1183
  return `\`${displayName}\` (free via [Pullfrog for OSS](https://pullfrog.com/for-oss))`;
1144
1184
  }
1145
1185
  const base = alias?.isFree ? `\`${displayName}\` (free)` : `\`${displayName}\``;
1146
- if (!params.fallbackFrom) return base;
1147
- return `${base} (credentials for ${providerDisplayName(params.fallbackFrom)} not configured)`;
1186
+ if (params.fallbackFrom) {
1187
+ return `${base} (credentials for ${providerDisplayName(params.fallbackFrom)} not configured)`;
1188
+ }
1189
+ if (params.clamped) {
1190
+ const target = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
1191
+ 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)`;
1192
+ }
1193
+ if (params.unselectedProxyDefault) {
1194
+ return `${base} (default \u2014 [pick a model](https://docs.pullfrog.com/models) for stronger reviews)`;
1195
+ }
1196
+ return base;
1148
1197
  }
1149
1198
  function buildPullfrogFooter(params) {
1150
1199
  const parts = [];
1200
+ if (params.shaPinned) {
1201
+ parts.push(
1202
+ "\u26A0\uFE0F this action is pinned to a commit SHA, which [freezes the cleanup step](https://docs.pullfrog.com/versioning) \u2014 switch to `@v0` or keep the SHA fresh with Dependabot"
1203
+ );
1204
+ }
1151
1205
  if (params.customParts) {
1152
1206
  parts.push(...params.customParts);
1153
1207
  }
@@ -1163,7 +1217,13 @@ function buildPullfrogFooter(params) {
1163
1217
  }
1164
1218
  if (params.model) {
1165
1219
  parts.push(
1166
- `Using ${formatModelLabel({ model: params.model, fallbackFrom: params.fallbackFrom, oss: params.oss })}`
1220
+ `Using ${formatModelLabel({
1221
+ model: params.model,
1222
+ fallbackFrom: params.fallbackFrom,
1223
+ clamped: params.clamped,
1224
+ unselectedProxyDefault: params.unselectedProxyDefault,
1225
+ oss: params.oss
1226
+ })}`
1167
1227
  );
1168
1228
  }
1169
1229
  const allParts = [...parts, "[\u{1D54F}](https://x.com/pullfrogai)"];
@@ -1398,6 +1458,8 @@ function isValidTimeString(input) {
1398
1458
  return parseTimeString(input) !== null;
1399
1459
  }
1400
1460
  export {
1461
+ AUTO_EFFICIENT,
1462
+ AUTO_INTELLIGENT,
1401
1463
  DEFAULT_PROXY_MODEL,
1402
1464
  LEAPING_INTO_ACTION_PREFIX,
1403
1465
  MAX_LEARNINGS_LENGTH,
@@ -1407,6 +1469,7 @@ export {
1407
1469
  buildPullfrogFooter,
1408
1470
  createLeapingProgressComment,
1409
1471
  decodeJwtExpMs,
1472
+ defaultAutoTier,
1410
1473
  deleteProgressCommentApi,
1411
1474
  getAutoSelectHintModel,
1412
1475
  getModelEnvVars,
@@ -1414,6 +1477,8 @@ export {
1414
1477
  getModelProvider,
1415
1478
  getProgressComment,
1416
1479
  getProviderDisplayName,
1480
+ isAutoTier,
1481
+ isCardGatedModel,
1417
1482
  isLeapingIntoActionCommentBody,
1418
1483
  isValidTimeString,
1419
1484
  modelAliases,
@@ -1424,6 +1489,7 @@ export {
1424
1489
  providers,
1425
1490
  pullfrogMcpName,
1426
1491
  refreshCodexAuthBody,
1492
+ resolveAutoTier,
1427
1493
  resolveCliModel,
1428
1494
  resolveDisplayAlias,
1429
1495
  resolveModelSlug,
@@ -6,4 +6,6 @@ export declare function GetCheckSuiteLogsTool(ctx: ToolContext): import("fastmcp
6
6
  check_suite_id: number;
7
7
  }, {
8
8
  check_suite_id: number;
9
- }>>;
9
+ }>> & {
10
+ mutates?: boolean;
11
+ };
@@ -64,7 +64,7 @@ type CheckoutPrBranchParams = GitContext & {
64
64
  /**
65
65
  * Shared helper to checkout a PR branch and configure fork remotes.
66
66
  * Assumes origin remote is already configured with authentication.
67
- * Updates toolState.issueNumber, toolState.checkoutSha, and toolState.pushUrl (for fork PRs).
67
+ * Updates the primary repo state's issueNumber, checkoutSha, and pushUrl (for fork PRs).
68
68
  */
69
69
  export declare function checkoutPrBranch(pr: PrData, params: CheckoutPrBranchParams): Promise<{
70
70
  hookWarning?: string | undefined;
@@ -73,5 +73,7 @@ export declare function CheckoutPrTool(ctx: ToolContext): import("fastmcp").Tool
73
73
  pull_number: number;
74
74
  }, {
75
75
  pull_number: number;
76
- }>>;
76
+ }>> & {
77
+ mutates?: boolean;
78
+ };
77
79
  export {};
@@ -14,7 +14,9 @@ export declare function CreateCommentTool(ctx: ToolContext): import("fastmcp").T
14
14
  issueNumber: number;
15
15
  body: string;
16
16
  type?: "Plan" | "Comment";
17
- }>>;
17
+ }>> & {
18
+ mutates?: boolean;
19
+ };
18
20
  export declare const EditComment: import("arktype/internal/variants/object.ts").ObjectType<{
19
21
  commentId: number;
20
22
  body: string;
@@ -25,7 +27,9 @@ export declare function EditCommentTool(ctx: ToolContext): import("fastmcp").Too
25
27
  }, {
26
28
  commentId: number;
27
29
  body: string;
28
- }>>;
30
+ }>> & {
31
+ mutates?: boolean;
32
+ };
29
33
  export declare const ReportProgress: import("arktype/internal/variants/object.ts").ObjectType<{
30
34
  body: string;
31
35
  target_plan_comment?: boolean;
@@ -60,7 +64,9 @@ export declare function ReportProgressTool(ctx: ToolContext): import("fastmcp").
60
64
  }, {
61
65
  body: string;
62
66
  target_plan_comment?: boolean;
63
- }>>;
67
+ }>> & {
68
+ mutates?: boolean;
69
+ };
64
70
  /**
65
71
  * Delete the progress comment if it exists.
66
72
  * Used by main.ts for stranded-comment cleanup (orphaned "Leaping into action" or
@@ -116,4 +122,6 @@ export declare function ReplyToReviewCommentTool(ctx: ToolContext): import("fast
116
122
  pull_number: number;
117
123
  comment_id: number;
118
124
  body: string;
119
- }>>;
125
+ }>> & {
126
+ mutates?: boolean;
127
+ };
@@ -6,4 +6,6 @@ export declare function CommitInfoTool(ctx: ToolContext): import("fastmcp").Tool
6
6
  sha: string;
7
7
  }, {
8
8
  sha: string;
9
- }>>;
9
+ }>> & {
10
+ mutates?: boolean;
11
+ };
@@ -4,5 +4,9 @@ import type { ToolContext } from "./server.ts";
4
4
  * called eagerly from main.ts at startup and also available via MCP tools.
5
5
  */
6
6
  export declare function startInstallation(ctx: ToolContext): void;
7
- export declare function StartDependencyInstallationTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<object, object>>;
8
- export declare function AwaitDependencyInstallationTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<object, object>>;
7
+ export declare function StartDependencyInstallationTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<object, object>> & {
8
+ mutates?: boolean;
9
+ };
10
+ export declare function AwaitDependencyInstallationTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<object, object>> & {
11
+ mutates?: boolean;
12
+ };
package/dist/mcp/git.d.ts CHANGED
@@ -5,42 +5,68 @@ export declare function validateTagName(tag: string): void;
5
5
  export declare const PushBranch: import("arktype/internal/variants/object.ts").ObjectType<{
6
6
  force: import("arktype/internal/attributes.ts").Default<boolean, false>;
7
7
  branchName?: string;
8
+ repo?: string;
8
9
  }, {}>;
9
- export type PushErrorKind = "concurrent-push" | "transient" | "unknown";
10
+ export type PushErrorKind = "concurrent-push" | "transient" | "transient-auth" | "unknown";
10
11
  export declare function classifyPushError(msg: string): PushErrorKind;
11
12
  export declare function PushBranchTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
12
13
  branchName?: string;
14
+ repo?: string;
13
15
  force?: boolean;
14
16
  }, {
15
17
  branchName?: string;
18
+ repo?: string;
16
19
  force?: boolean;
17
- }>>;
20
+ }>> & {
21
+ mutates?: boolean;
22
+ };
23
+ export declare function CommitChangesTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
24
+ message: string;
25
+ files?: string[];
26
+ }, {
27
+ message: string;
28
+ files?: string[];
29
+ }>> & {
30
+ mutates?: boolean;
31
+ };
18
32
  export declare const AUTH_REQUIRED_REDIRECT: Record<string, string>;
19
33
  export declare const NOSHELL_BLOCKED_SUBCOMMANDS: Record<string, string>;
20
34
  export declare const NOSHELL_BLOCKED_ARGS: string[];
21
35
  export declare function GitTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
22
36
  command: string;
23
37
  args?: string[];
38
+ repo?: string;
24
39
  }, {
25
40
  command: string;
26
41
  args?: string[];
27
- }>>;
42
+ repo?: string;
43
+ }>> & {
44
+ mutates?: boolean;
45
+ };
28
46
  export declare function GitFetchTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
29
47
  ref: string;
30
48
  depth?: number;
49
+ repo?: string;
31
50
  }, {
32
51
  ref: string;
33
52
  depth?: number;
34
- }>>;
53
+ repo?: string;
54
+ }>> & {
55
+ mutates?: boolean;
56
+ };
35
57
  export declare function DeleteBranchTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
36
58
  branchName: string;
37
59
  }, {
38
60
  branchName: string;
39
- }>>;
61
+ }>> & {
62
+ mutates?: boolean;
63
+ };
40
64
  export declare function PushTagsTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
41
65
  tag: string;
42
66
  force?: boolean;
43
67
  }, {
44
68
  tag: string;
45
69
  force?: boolean;
46
- }>>;
70
+ }>> & {
71
+ mutates?: boolean;
72
+ };
@@ -15,4 +15,29 @@ export declare function IssueTool(ctx: ToolContext): import("fastmcp").Tool<any,
15
15
  body: string;
16
16
  labels?: string[];
17
17
  assignees?: string[];
18
- }>>;
18
+ }>> & {
19
+ mutates?: boolean;
20
+ };
21
+ export declare const CloseIssue: import("arktype/internal/variants/object.ts").ObjectType<{
22
+ issue_number: number;
23
+ state_reason: "completed" | "not_planned" | "duplicate";
24
+ }, {}>;
25
+ export declare function CloseIssueTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
26
+ issue_number: number;
27
+ state_reason: "completed" | "not_planned" | "duplicate";
28
+ }, {
29
+ issue_number: number;
30
+ state_reason: "completed" | "not_planned" | "duplicate";
31
+ }>> & {
32
+ mutates?: boolean;
33
+ };
34
+ export declare const ReopenIssue: import("arktype/internal/variants/object.ts").ObjectType<{
35
+ issue_number: number;
36
+ }, {}>;
37
+ export declare function ReopenIssueTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
38
+ issue_number: number;
39
+ }, {
40
+ issue_number: number;
41
+ }>> & {
42
+ mutates?: boolean;
43
+ };
@@ -6,4 +6,6 @@ export declare function GetIssueCommentsTool(ctx: ToolContext): import("fastmcp"
6
6
  issue_number: number;
7
7
  }, {
8
8
  issue_number: number;
9
- }>>;
9
+ }>> & {
10
+ mutates?: boolean;
11
+ };
@@ -6,4 +6,6 @@ export declare function GetIssueEventsTool(ctx: ToolContext): import("fastmcp").
6
6
  issue_number: number;
7
7
  }, {
8
8
  issue_number: number;
9
- }>>;
9
+ }>> & {
10
+ mutates?: boolean;
11
+ };
@@ -6,4 +6,6 @@ export declare function IssueInfoTool(ctx: ToolContext): import("fastmcp").Tool<
6
6
  issue_number: number;
7
7
  }, {
8
8
  issue_number: number;
9
- }>>;
9
+ }>> & {
10
+ mutates?: boolean;
11
+ };
@@ -9,4 +9,19 @@ export declare function AddLabelsTool(ctx: ToolContext): import("fastmcp").Tool<
9
9
  }, {
10
10
  issue_number: number;
11
11
  labels: string[];
12
- }>>;
12
+ }>> & {
13
+ mutates?: boolean;
14
+ };
15
+ export declare const RemoveLabelsParams: import("arktype/internal/variants/object.ts").ObjectType<{
16
+ issue_number: number;
17
+ labels: string[];
18
+ }, {}>;
19
+ export declare function RemoveLabelsTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
20
+ issue_number: number;
21
+ labels: string[];
22
+ }, {
23
+ issue_number: number;
24
+ labels: string[];
25
+ }>> & {
26
+ mutates?: boolean;
27
+ };
@@ -4,9 +4,13 @@ export declare const SetOutputParams: import("arktype/internal/variants/object.t
4
4
  value: string;
5
5
  }, {}>;
6
6
  type JsonSchema = Record<string, unknown>;
7
- export declare function SetOutputTool(ctx: ToolContext, outputSchema?: JsonSchema): import("fastmcp").Tool<any, StandardSchemaV1<any, any>> | import("fastmcp").Tool<any, StandardSchemaV1<{
7
+ export declare function SetOutputTool(ctx: ToolContext, outputSchema?: JsonSchema): (import("fastmcp").Tool<any, StandardSchemaV1<any, any>> & {
8
+ mutates?: boolean;
9
+ }) | (import("fastmcp").Tool<any, StandardSchemaV1<{
8
10
  value: string;
9
11
  }, {
10
12
  value: string;
11
- }>>;
13
+ }>> & {
14
+ mutates?: boolean;
15
+ });
12
16
  export {};
package/dist/mcp/pr.d.ts CHANGED
@@ -4,7 +4,18 @@ export declare const PullRequest: import("arktype/internal/variants/object.ts").
4
4
  body: string;
5
5
  base: string;
6
6
  draft?: boolean;
7
+ repo?: string;
7
8
  }, {}>;
9
+ export declare const ClosePullRequest: import("arktype/internal/variants/object.ts").ObjectType<{
10
+ pull_number: number;
11
+ }, {}>;
12
+ export declare function ClosePullRequestTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
13
+ pull_number: number;
14
+ }, {
15
+ pull_number: number;
16
+ }>> & {
17
+ mutates?: boolean;
18
+ };
8
19
  export declare const UpdatePullRequestBody: import("arktype/internal/variants/object.ts").ObjectType<{
9
20
  pull_number: number;
10
21
  body: string;
@@ -15,15 +26,21 @@ export declare function UpdatePullRequestBodyTool(ctx: ToolContext): import("fas
15
26
  }, {
16
27
  pull_number: number;
17
28
  body: string;
18
- }>>;
29
+ }>> & {
30
+ mutates?: boolean;
31
+ };
19
32
  export declare function CreatePullRequestTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
20
33
  title: string;
21
34
  body: string;
22
35
  base: string;
23
36
  draft?: boolean;
37
+ repo?: string;
24
38
  }, {
25
39
  title: string;
26
40
  body: string;
27
41
  base: string;
28
42
  draft?: boolean;
29
- }>>;
43
+ repo?: string;
44
+ }>> & {
45
+ mutates?: boolean;
46
+ };
@@ -6,4 +6,6 @@ export declare function PullRequestInfoTool(ctx: ToolContext): import("fastmcp")
6
6
  pull_number: number;
7
7
  }, {
8
8
  pull_number: number;
9
- }>>;
9
+ }>> & {
10
+ mutates?: boolean;
11
+ };