pullfrog 0.1.30 → 0.1.32

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 (56) hide show
  1. package/README.md +17 -1
  2. package/dist/agents/claudePretoolGate.d.ts +5 -1
  3. package/dist/agents/opencodePlugin.d.ts +2 -2
  4. package/dist/agents/postRun.d.ts +8 -31
  5. package/dist/agents/shared.d.ts +6 -0
  6. package/dist/agents/subagentToolGates.d.ts +22 -40
  7. package/dist/cli.mjs +63822 -59863
  8. package/dist/external.d.ts +45 -2
  9. package/dist/index.js +62340 -58381
  10. package/dist/internal/index.d.ts +2 -2
  11. package/dist/internal.js +98 -26
  12. package/dist/mcp/checkSuite.d.ts +3 -1
  13. package/dist/mcp/checkout.d.ts +4 -2
  14. package/dist/mcp/comment.d.ts +12 -4
  15. package/dist/mcp/commitInfo.d.ts +3 -1
  16. package/dist/mcp/dependencies.d.ts +6 -2
  17. package/dist/mcp/git.d.ts +26 -7
  18. package/dist/mcp/issue.d.ts +26 -1
  19. package/dist/mcp/issueComments.d.ts +3 -1
  20. package/dist/mcp/issueEvents.d.ts +3 -1
  21. package/dist/mcp/issueInfo.d.ts +3 -1
  22. package/dist/mcp/labels.d.ts +16 -1
  23. package/dist/mcp/output.d.ts +6 -2
  24. package/dist/mcp/pr.d.ts +19 -2
  25. package/dist/mcp/prInfo.d.ts +3 -1
  26. package/dist/mcp/resolveRepoCtx.d.ts +34 -0
  27. package/dist/mcp/review.d.ts +50 -3
  28. package/dist/mcp/reviewComments.d.ts +9 -3
  29. package/dist/mcp/selectMode.d.ts +3 -1
  30. package/dist/mcp/server.d.ts +6 -1
  31. package/dist/mcp/shared.d.ts +18 -1
  32. package/dist/mcp/shell.d.ts +6 -2
  33. package/dist/mcp/upload.d.ts +3 -1
  34. package/dist/mcp/xrepo.d.ts +15 -0
  35. package/dist/models.d.ts +58 -5
  36. package/dist/toolState.d.ts +73 -16
  37. package/dist/utils/agent.d.ts +3 -1
  38. package/dist/utils/apiKeys.d.ts +4 -0
  39. package/dist/utils/buildPullfrogFooter.d.ts +34 -0
  40. package/dist/utils/errorReport.d.ts +2 -2
  41. package/dist/utils/github.d.ts +1 -1
  42. package/dist/utils/instructions.d.ts +8 -0
  43. package/dist/utils/isTransientNetworkError.d.ts +19 -0
  44. package/dist/utils/learnings.d.ts +14 -0
  45. package/dist/utils/modelAccess.d.ts +64 -0
  46. package/dist/utils/payload.d.ts +26 -1
  47. package/dist/utils/runContext.d.ts +3 -0
  48. package/dist/utils/runContextData.d.ts +10 -0
  49. package/dist/utils/setup.d.ts +18 -3
  50. package/dist/utils/statusChecks.d.ts +25 -0
  51. package/dist/utils/token.d.ts +10 -2
  52. package/dist/yes/index.d.ts +58 -0
  53. package/dist/yes/standard-schema.d.ts +117 -0
  54. package/dist/yes.js +1281 -0
  55. package/package.json +19 -10
  56. 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,26 +9,33 @@ var providers = {
9
9
  displayName: "Anthropic",
10
10
  envVars: ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"],
11
11
  models: {
12
- // OpenRouter serves claude-fable-5, but models.dev's OpenRouter mirror
13
- // hasn't indexed it yet (shipped 2026-06-09), so the catalog drift gate
14
- // can't validate an openRouterResolve. omit it until the mirror catches
15
- // up; direct BYOK / Claude Code resolves anthropic/claude-fable-5 fine.
12
+ // claude-fable-5 is selectable but not recommended/auto-selected — it's
13
+ // moving to usage-credits-only billing and isn't broadly available yet, so
14
+ // opus stays the universally-available flagship, the AUTO_INTELLIGENT tier
15
+ // target, and the recommended pick. an explicit fable pick hits the real
16
+ // API and is access-gated: it errors for accounts without access today and
17
+ // just works once usage credits are live — no silent opus fallback, the
18
+ // API is the source of truth (#959).
16
19
  "claude-fable": {
17
20
  displayName: "Claude Fable",
18
21
  resolve: "anthropic/claude-fable-5",
19
- preferred: true,
22
+ // rolling alias: models.dev's OpenRouter mirror lags brand-new pinned
23
+ // versions (claude-fable-5 isn't indexed yet), so track ~…-latest to
24
+ // stay catalog-valid and auto-follow version bumps.
25
+ openRouterResolve: "openrouter/~anthropic/claude-fable-latest",
20
26
  subagentModel: "claude-sonnet"
21
27
  },
22
28
  "claude-opus": {
23
29
  displayName: "Claude Opus",
24
30
  resolve: "anthropic/claude-opus-4-8",
25
31
  openRouterResolve: "openrouter/anthropic/claude-opus-4.8",
32
+ preferred: true,
26
33
  subagentModel: "claude-sonnet"
27
34
  },
28
35
  "claude-sonnet": {
29
36
  displayName: "Claude Sonnet",
30
- resolve: "anthropic/claude-sonnet-4-6",
31
- openRouterResolve: "openrouter/anthropic/claude-sonnet-4.6"
37
+ resolve: "anthropic/claude-sonnet-5",
38
+ openRouterResolve: "openrouter/anthropic/claude-sonnet-5"
32
39
  },
33
40
  "claude-haiku": {
34
41
  displayName: "Claude Haiku",
@@ -181,8 +188,8 @@ var providers = {
181
188
  models: {
182
189
  "kimi-k2": {
183
190
  displayName: "Kimi K2",
184
- resolve: "moonshotai/kimi-k2.6",
185
- openRouterResolve: "openrouter/moonshotai/kimi-k2.6",
191
+ resolve: "moonshotai/kimi-k2.7-code",
192
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code",
186
193
  preferred: true
187
194
  }
188
195
  }
@@ -206,8 +213,8 @@ var providers = {
206
213
  },
207
214
  "claude-sonnet": {
208
215
  displayName: "Claude Sonnet",
209
- resolve: "opencode/claude-sonnet-4-6",
210
- openRouterResolve: "openrouter/anthropic/claude-sonnet-4.6"
216
+ resolve: "opencode/claude-sonnet-5",
217
+ openRouterResolve: "openrouter/anthropic/claude-sonnet-5"
211
218
  },
212
219
  "claude-haiku": {
213
220
  displayName: "Claude Haiku",
@@ -264,8 +271,10 @@ var providers = {
264
271
  },
265
272
  "kimi-k2": {
266
273
  displayName: "Kimi K2",
274
+ // opencode Zen serves only up to k2.6; the OpenRouter fallback (used for
275
+ // router/oss proxy runs) takes the newer k2.7-code.
267
276
  resolve: "opencode/kimi-k2.6",
268
- openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
277
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
269
278
  },
270
279
  "minimax-m2.5": {
271
280
  displayName: "MiniMax M2",
@@ -300,9 +309,14 @@ var providers = {
300
309
  models: {
301
310
  "glm-5.1": {
302
311
  displayName: "GLM 5.1",
303
- resolve: "opencode-go/glm-5.1",
304
- openRouterResolve: "openrouter/z-ai/glm-5.1",
312
+ resolve: "opencode-go/glm-5.2",
313
+ openRouterResolve: "openrouter/z-ai/glm-5.2",
305
314
  preferred: true
315
+ },
316
+ "kimi-k2": {
317
+ displayName: "Kimi K2",
318
+ resolve: "opencode-go/kimi-k2.7-code",
319
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
306
320
  }
307
321
  }
308
322
  }),
@@ -438,8 +452,8 @@ var providers = {
438
452
  },
439
453
  "kimi-k2": {
440
454
  displayName: "Kimi K2",
441
- resolve: "openrouter/moonshotai/kimi-k2.6",
442
- openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
455
+ resolve: "openrouter/moonshotai/kimi-k2.7-code",
456
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
443
457
  },
444
458
  "minimax-m2.5": {
445
459
  displayName: "MiniMax M2",
@@ -498,21 +512,31 @@ var modelAliases = Object.entries(providers).flatMap(
498
512
  hidden: def.hidden ?? false
499
513
  }))
500
514
  );
501
- var defaultProxyAlias = modelAliases.find((a) => a.slug === "deepseek/deepseek-pro");
502
- if (!defaultProxyAlias?.openRouterResolve) {
503
- throw new Error("DEFAULT_PROXY_MODEL: deepseek/deepseek-pro missing openRouterResolve");
515
+ var AUTO_EFFICIENT = "auto/efficient";
516
+ var AUTO_INTELLIGENT = "auto/intelligent";
517
+ var AUTO_TIER_TARGET = {
518
+ [AUTO_EFFICIENT]: "moonshotai/kimi-k2",
519
+ [AUTO_INTELLIGENT]: "anthropic/claude-opus"
520
+ };
521
+ function isAutoTier(slug) {
522
+ return slug === AUTO_EFFICIENT || slug === AUTO_INTELLIGENT;
504
523
  }
505
- var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
506
- var defaultProxyDisplayName = defaultProxyAlias.displayName;
507
- function getAutoSelectHintModel() {
508
- return defaultProxyDisplayName;
524
+ function defaultAutoTier(hasCard) {
525
+ return hasCard ? AUTO_INTELLIGENT : AUTO_EFFICIENT;
526
+ }
527
+ function resolveAutoTier(params) {
528
+ if (!params.hasCard) return AUTO_EFFICIENT;
529
+ return isAutoTier(params.model) ? params.model : defaultAutoTier(params.hasCard);
530
+ }
531
+ function isCardGatedModel(slug) {
532
+ return resolveOpenRouterModel(slug) !== void 0;
509
533
  }
510
534
  function resolveModelSlug(slug) {
511
535
  return modelAliases.find((a) => a.slug === slug)?.resolve;
512
536
  }
513
537
  var MAX_FALLBACK_DEPTH = 10;
514
538
  function resolveDisplayAlias(slug) {
515
- let current = slug;
539
+ let current = isAutoTier(slug) ? AUTO_TIER_TARGET[slug] : slug;
516
540
  const visited = /* @__PURE__ */ new Set();
517
541
  for (let i = 0; i < MAX_FALLBACK_DEPTH; i++) {
518
542
  if (visited.has(current)) return void 0;
@@ -530,6 +554,15 @@ function resolveCliModel(slug) {
530
554
  function resolveOpenRouterModel(slug) {
531
555
  return resolveDisplayAlias(slug)?.openRouterResolve;
532
556
  }
557
+ var defaultProxyAlias = resolveDisplayAlias(AUTO_EFFICIENT);
558
+ if (!defaultProxyAlias?.openRouterResolve) {
559
+ throw new Error(`DEFAULT_PROXY_MODEL: ${AUTO_EFFICIENT} has no openRouterResolve`);
560
+ }
561
+ var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
562
+ var defaultProxyDisplayName = defaultProxyAlias.displayName;
563
+ function getAutoSelectHintModel() {
564
+ return defaultProxyDisplayName;
565
+ }
533
566
 
534
567
  // external.ts
535
568
  var pullfrogMcpName = "pullfrog";
@@ -1135,6 +1168,15 @@ var modes = computeModes("opencode");
1135
1168
  // utils/buildPullfrogFooter.ts
1136
1169
  var PULLFROG_DIVIDER = "<!-- PULLFROG_DIVIDER_DO_NOT_REMOVE_PLZ -->";
1137
1170
  var FROG_LOGO = `<a href="https://pullfrog.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pullfrog.com/logos/frog-white-full-18px.png"><img src="https://pullfrog.com/logos/frog-green-full-18px.png" width="9px" height="9px" style="vertical-align: middle; " alt="Pullfrog"></picture></a>`;
1171
+ function providerDisplayName(slug) {
1172
+ try {
1173
+ const key = getModelProvider(slug);
1174
+ const meta = providers[key];
1175
+ return meta?.displayName ?? key;
1176
+ } catch {
1177
+ return slug;
1178
+ }
1179
+ }
1138
1180
  function formatModelLabel(params) {
1139
1181
  const alias = resolveDisplayAlias(params.model) ?? // reverse-lookup: when the caller passes an effective model (proxy or
1140
1182
  // resolved target like "openrouter/anthropic/claude-opus-4.7") instead of
@@ -1145,10 +1187,26 @@ function formatModelLabel(params) {
1145
1187
  if (params.oss) {
1146
1188
  return `\`${displayName}\` (free via [Pullfrog for OSS](https://pullfrog.com/for-oss))`;
1147
1189
  }
1148
- return alias?.isFree ? `\`${displayName}\` (free)` : `\`${displayName}\``;
1190
+ const base = alias?.isFree ? `\`${displayName}\` (free)` : `\`${displayName}\``;
1191
+ if (params.fallbackFrom) {
1192
+ return `${base} (credentials for ${providerDisplayName(params.fallbackFrom)} not configured)`;
1193
+ }
1194
+ if (params.clamped) {
1195
+ const target = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
1196
+ 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)`;
1197
+ }
1198
+ if (params.unselectedProxyDefault) {
1199
+ return `${base} (default \u2014 [pick a model](https://docs.pullfrog.com/models) for stronger reviews)`;
1200
+ }
1201
+ return base;
1149
1202
  }
1150
1203
  function buildPullfrogFooter(params) {
1151
1204
  const parts = [];
1205
+ if (params.shaPinned) {
1206
+ parts.push(
1207
+ "\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"
1208
+ );
1209
+ }
1152
1210
  if (params.customParts) {
1153
1211
  parts.push(...params.customParts);
1154
1212
  }
@@ -1163,7 +1221,15 @@ function buildPullfrogFooter(params) {
1163
1221
  parts.push("via [Pullfrog](https://pullfrog.com)");
1164
1222
  }
1165
1223
  if (params.model) {
1166
- parts.push(`Using ${formatModelLabel({ model: params.model, oss: params.oss })}`);
1224
+ parts.push(
1225
+ `Using ${formatModelLabel({
1226
+ model: params.model,
1227
+ fallbackFrom: params.fallbackFrom,
1228
+ clamped: params.clamped,
1229
+ unselectedProxyDefault: params.unselectedProxyDefault,
1230
+ oss: params.oss
1231
+ })}`
1232
+ );
1167
1233
  }
1168
1234
  const allParts = [...parts, "[\u{1D54F}](https://x.com/pullfrogai)"];
1169
1235
  return `
@@ -1397,6 +1463,8 @@ function isValidTimeString(input) {
1397
1463
  return parseTimeString(input) !== null;
1398
1464
  }
1399
1465
  export {
1466
+ AUTO_EFFICIENT,
1467
+ AUTO_INTELLIGENT,
1400
1468
  DEFAULT_PROXY_MODEL,
1401
1469
  LEAPING_INTO_ACTION_PREFIX,
1402
1470
  MAX_LEARNINGS_LENGTH,
@@ -1406,6 +1474,7 @@ export {
1406
1474
  buildPullfrogFooter,
1407
1475
  createLeapingProgressComment,
1408
1476
  decodeJwtExpMs,
1477
+ defaultAutoTier,
1409
1478
  deleteProgressCommentApi,
1410
1479
  getAutoSelectHintModel,
1411
1480
  getModelEnvVars,
@@ -1413,6 +1482,8 @@ export {
1413
1482
  getModelProvider,
1414
1483
  getProgressComment,
1415
1484
  getProviderDisplayName,
1485
+ isAutoTier,
1486
+ isCardGatedModel,
1416
1487
  isLeapingIntoActionCommentBody,
1417
1488
  isValidTimeString,
1418
1489
  modelAliases,
@@ -1423,6 +1494,7 @@ export {
1423
1494
  providers,
1424
1495
  pullfrogMcpName,
1425
1496
  refreshCodexAuthBody,
1497
+ resolveAutoTier,
1426
1498
  resolveCliModel,
1427
1499
  resolveDisplayAlias,
1428
1500
  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,49 +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
+ };
18
23
  export declare function CommitChangesTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
19
24
  message: string;
20
25
  files?: string[];
21
26
  }, {
22
27
  message: string;
23
28
  files?: string[];
24
- }>>;
29
+ }>> & {
30
+ mutates?: boolean;
31
+ };
25
32
  export declare const AUTH_REQUIRED_REDIRECT: Record<string, string>;
26
33
  export declare const NOSHELL_BLOCKED_SUBCOMMANDS: Record<string, string>;
27
34
  export declare const NOSHELL_BLOCKED_ARGS: string[];
28
35
  export declare function GitTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
29
36
  command: string;
30
37
  args?: string[];
38
+ repo?: string;
31
39
  }, {
32
40
  command: string;
33
41
  args?: string[];
34
- }>>;
42
+ repo?: string;
43
+ }>> & {
44
+ mutates?: boolean;
45
+ };
35
46
  export declare function GitFetchTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
36
47
  ref: string;
37
48
  depth?: number;
49
+ repo?: string;
38
50
  }, {
39
51
  ref: string;
40
52
  depth?: number;
41
- }>>;
53
+ repo?: string;
54
+ }>> & {
55
+ mutates?: boolean;
56
+ };
42
57
  export declare function DeleteBranchTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
43
58
  branchName: string;
44
59
  }, {
45
60
  branchName: string;
46
- }>>;
61
+ }>> & {
62
+ mutates?: boolean;
63
+ };
47
64
  export declare function PushTagsTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
48
65
  tag: string;
49
66
  force?: boolean;
50
67
  }, {
51
68
  tag: string;
52
69
  force?: boolean;
53
- }>>;
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
+ };
@@ -0,0 +1,34 @@
1
+ import { type RepoAccess } from "../toolState.ts";
2
+ import { type OctokitWithPlugins } from "../utils/github.ts";
3
+ import type { ToolContext } from "./server.ts";
4
+ /**
5
+ * per-repo execution context for a single tool call. resolved from the
6
+ * optional `repo` param (a bare repo name — owner-implicit, same account as
7
+ * the primary). carries the correct token tier + working directory so a tool
8
+ * can talk to GitHub and run git against the right checkout.
9
+ */
10
+ export interface RepoCtx {
11
+ owner: string;
12
+ name: string;
13
+ /** working tree: primary = process.cwd(); secondary = ctx.tmpdir/xrepo/<name> */
14
+ dir: string;
15
+ access: RepoAccess;
16
+ /** octokit scoped to the repo's tier (write tokens for primary/write, read token for read) */
17
+ octokit: OctokitWithPlugins;
18
+ /** git token scoped to the repo's tier */
19
+ gitToken: string;
20
+ /** re-mint this tier's git token on an auth-class push failure (push retries) */
21
+ refreshGitToken: ((stale: string) => Promise<string>) | undefined;
22
+ }
23
+ /**
24
+ * resolve the execution context for a `repo`-scoped tool call.
25
+ *
26
+ * - omitted / primary name → the primary ctx (unchanged single-repo path).
27
+ * - a `write`-tier secondary → the same write-scoped tokens as the primary
28
+ * (mcpToken + gitToken are minted over the write set ∪ primary).
29
+ * - a `read`-tier secondary → the contents:read token (clone-for-reference).
30
+ *
31
+ * throws when `repo` isn't a registered checkout — secondaries must be cloned
32
+ * via `checkout_repo` first, which is what populates `toolState.repos`.
33
+ */
34
+ export declare function resolveRepoCtx(ctx: ToolContext, repo?: string | undefined): RepoCtx;