pullfrog 0.1.30 → 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 (53) 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 +63441 -59740
  7. package/dist/external.d.ts +45 -2
  8. package/dist/index.js +61939 -58238
  9. package/dist/internal/index.d.ts +2 -2
  10. package/dist/internal.js +89 -22
  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 +26 -7
  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 +6 -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/toolState.d.ts +69 -16
  36. package/dist/utils/apiKeys.d.ts +4 -0
  37. package/dist/utils/buildPullfrogFooter.d.ts +34 -0
  38. package/dist/utils/errorReport.d.ts +2 -2
  39. package/dist/utils/github.d.ts +1 -1
  40. package/dist/utils/instructions.d.ts +8 -0
  41. package/dist/utils/isTransientNetworkError.d.ts +10 -0
  42. package/dist/utils/learnings.d.ts +14 -0
  43. package/dist/utils/modelAccess.d.ts +64 -0
  44. package/dist/utils/payload.d.ts +16 -0
  45. package/dist/utils/runContext.d.ts +3 -0
  46. package/dist/utils/runContextData.d.ts +10 -0
  47. package/dist/utils/setup.d.ts +18 -3
  48. package/dist/utils/token.d.ts +10 -2
  49. package/dist/yes/index.d.ts +32 -0
  50. package/dist/yes/standard-schema.d.ts +117 -0
  51. package/dist/yes.js +1244 -0
  52. package/package.json +19 -10
  53. 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,20 +9,22 @@ 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 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).
16
17
  "claude-fable": {
17
18
  displayName: "Claude Fable",
18
19
  resolve: "anthropic/claude-fable-5",
19
- preferred: true,
20
+ fallback: "anthropic/claude-opus",
20
21
  subagentModel: "claude-sonnet"
21
22
  },
22
23
  "claude-opus": {
23
24
  displayName: "Claude Opus",
24
25
  resolve: "anthropic/claude-opus-4-8",
25
26
  openRouterResolve: "openrouter/anthropic/claude-opus-4.8",
27
+ preferred: true,
26
28
  subagentModel: "claude-sonnet"
27
29
  },
28
30
  "claude-sonnet": {
@@ -181,8 +183,8 @@ var providers = {
181
183
  models: {
182
184
  "kimi-k2": {
183
185
  displayName: "Kimi K2",
184
- resolve: "moonshotai/kimi-k2.6",
185
- openRouterResolve: "openrouter/moonshotai/kimi-k2.6",
186
+ resolve: "moonshotai/kimi-k2.7-code",
187
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code",
186
188
  preferred: true
187
189
  }
188
190
  }
@@ -264,8 +266,10 @@ var providers = {
264
266
  },
265
267
  "kimi-k2": {
266
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.
267
271
  resolve: "opencode/kimi-k2.6",
268
- openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
272
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
269
273
  },
270
274
  "minimax-m2.5": {
271
275
  displayName: "MiniMax M2",
@@ -300,9 +304,14 @@ var providers = {
300
304
  models: {
301
305
  "glm-5.1": {
302
306
  displayName: "GLM 5.1",
303
- resolve: "opencode-go/glm-5.1",
304
- openRouterResolve: "openrouter/z-ai/glm-5.1",
307
+ resolve: "opencode-go/glm-5.2",
308
+ openRouterResolve: "openrouter/z-ai/glm-5.2",
305
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"
306
315
  }
307
316
  }
308
317
  }),
@@ -438,8 +447,8 @@ var providers = {
438
447
  },
439
448
  "kimi-k2": {
440
449
  displayName: "Kimi K2",
441
- resolve: "openrouter/moonshotai/kimi-k2.6",
442
- openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
450
+ resolve: "openrouter/moonshotai/kimi-k2.7-code",
451
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
443
452
  },
444
453
  "minimax-m2.5": {
445
454
  displayName: "MiniMax M2",
@@ -498,21 +507,31 @@ var modelAliases = Object.entries(providers).flatMap(
498
507
  hidden: def.hidden ?? false
499
508
  }))
500
509
  );
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");
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;
504
518
  }
505
- var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
506
- var defaultProxyDisplayName = defaultProxyAlias.displayName;
507
- function getAutoSelectHintModel() {
508
- 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;
509
528
  }
510
529
  function resolveModelSlug(slug) {
511
530
  return modelAliases.find((a) => a.slug === slug)?.resolve;
512
531
  }
513
532
  var MAX_FALLBACK_DEPTH = 10;
514
533
  function resolveDisplayAlias(slug) {
515
- let current = slug;
534
+ let current = isAutoTier(slug) ? AUTO_TIER_TARGET[slug] : slug;
516
535
  const visited = /* @__PURE__ */ new Set();
517
536
  for (let i = 0; i < MAX_FALLBACK_DEPTH; i++) {
518
537
  if (visited.has(current)) return void 0;
@@ -530,6 +549,15 @@ function resolveCliModel(slug) {
530
549
  function resolveOpenRouterModel(slug) {
531
550
  return resolveDisplayAlias(slug)?.openRouterResolve;
532
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
+ }
533
561
 
534
562
  // external.ts
535
563
  var pullfrogMcpName = "pullfrog";
@@ -1135,6 +1163,15 @@ var modes = computeModes("opencode");
1135
1163
  // utils/buildPullfrogFooter.ts
1136
1164
  var PULLFROG_DIVIDER = "<!-- PULLFROG_DIVIDER_DO_NOT_REMOVE_PLZ -->";
1137
1165
  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>`;
1166
+ function providerDisplayName(slug) {
1167
+ try {
1168
+ const key = getModelProvider(slug);
1169
+ const meta = providers[key];
1170
+ return meta?.displayName ?? key;
1171
+ } catch {
1172
+ return slug;
1173
+ }
1174
+ }
1138
1175
  function formatModelLabel(params) {
1139
1176
  const alias = resolveDisplayAlias(params.model) ?? // reverse-lookup: when the caller passes an effective model (proxy or
1140
1177
  // resolved target like "openrouter/anthropic/claude-opus-4.7") instead of
@@ -1145,10 +1182,26 @@ function formatModelLabel(params) {
1145
1182
  if (params.oss) {
1146
1183
  return `\`${displayName}\` (free via [Pullfrog for OSS](https://pullfrog.com/for-oss))`;
1147
1184
  }
1148
- return alias?.isFree ? `\`${displayName}\` (free)` : `\`${displayName}\``;
1185
+ const base = alias?.isFree ? `\`${displayName}\` (free)` : `\`${displayName}\``;
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;
1149
1197
  }
1150
1198
  function buildPullfrogFooter(params) {
1151
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
+ }
1152
1205
  if (params.customParts) {
1153
1206
  parts.push(...params.customParts);
1154
1207
  }
@@ -1163,7 +1216,15 @@ function buildPullfrogFooter(params) {
1163
1216
  parts.push("via [Pullfrog](https://pullfrog.com)");
1164
1217
  }
1165
1218
  if (params.model) {
1166
- parts.push(`Using ${formatModelLabel({ model: params.model, oss: params.oss })}`);
1219
+ parts.push(
1220
+ `Using ${formatModelLabel({
1221
+ model: params.model,
1222
+ fallbackFrom: params.fallbackFrom,
1223
+ clamped: params.clamped,
1224
+ unselectedProxyDefault: params.unselectedProxyDefault,
1225
+ oss: params.oss
1226
+ })}`
1227
+ );
1167
1228
  }
1168
1229
  const allParts = [...parts, "[\u{1D54F}](https://x.com/pullfrogai)"];
1169
1230
  return `
@@ -1397,6 +1458,8 @@ function isValidTimeString(input) {
1397
1458
  return parseTimeString(input) !== null;
1398
1459
  }
1399
1460
  export {
1461
+ AUTO_EFFICIENT,
1462
+ AUTO_INTELLIGENT,
1400
1463
  DEFAULT_PROXY_MODEL,
1401
1464
  LEAPING_INTO_ACTION_PREFIX,
1402
1465
  MAX_LEARNINGS_LENGTH,
@@ -1406,6 +1469,7 @@ export {
1406
1469
  buildPullfrogFooter,
1407
1470
  createLeapingProgressComment,
1408
1471
  decodeJwtExpMs,
1472
+ defaultAutoTier,
1409
1473
  deleteProgressCommentApi,
1410
1474
  getAutoSelectHintModel,
1411
1475
  getModelEnvVars,
@@ -1413,6 +1477,8 @@ export {
1413
1477
  getModelProvider,
1414
1478
  getProgressComment,
1415
1479
  getProviderDisplayName,
1480
+ isAutoTier,
1481
+ isCardGatedModel,
1416
1482
  isLeapingIntoActionCommentBody,
1417
1483
  isValidTimeString,
1418
1484
  modelAliases,
@@ -1423,6 +1489,7 @@ export {
1423
1489
  providers,
1424
1490
  pullfrogMcpName,
1425
1491
  refreshCodexAuthBody,
1492
+ resolveAutoTier,
1426
1493
  resolveCliModel,
1427
1494
  resolveDisplayAlias,
1428
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,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;
@@ -1,5 +1,5 @@
1
1
  import type { RestEndpointMethodTypes } from "@octokit/rest";
2
- import type { CommentableLines } from "../toolState.ts";
2
+ import { type CommentableLines } from "../toolState.ts";
3
3
  import type { ToolContext } from "./server.ts";
4
4
  export type { CommentableLines };
5
5
  /**
@@ -69,7 +69,7 @@ export type DuplicateReviewDecision = {
69
69
  * adds noise to the PR.
70
70
  *
71
71
  * legitimate follow-up reviews after new commits ARE allowed: the
72
- * new-commits-mid-review path advances toolState.checkoutSha past the
72
+ * new-commits-mid-review path advances the primary repo state's checkoutSha past the
73
73
  * previously reviewed sha, and a subsequent checkout_pr advances it again.
74
74
  * any call where checkoutSha has moved past the prior reviewedSha is a real
75
75
  * follow-up and goes through. anything else — same sha, or no checkoutSha
@@ -103,6 +103,7 @@ export declare function duplicateReviewDecision(params: {
103
103
  */
104
104
  export declare function reviewSkipDecision(params: {
105
105
  approved: boolean;
106
+ requestChanges?: boolean;
106
107
  body: string | null | undefined;
107
108
  hasComments: boolean;
108
109
  prApproveEnabled: boolean;
@@ -112,6 +113,7 @@ export declare const CreatePullRequestReview: import("arktype/internal/variants/
112
113
  pull_number: number;
113
114
  body?: string;
114
115
  approved?: boolean;
116
+ request_changes?: boolean;
115
117
  commit_id?: string;
116
118
  comments?: {
117
119
  path: string;
@@ -126,6 +128,7 @@ export declare function CreatePullRequestReviewTool(ctx: ToolContext): import("f
126
128
  pull_number: number;
127
129
  body?: string;
128
130
  approved?: boolean;
131
+ request_changes?: boolean;
129
132
  commit_id?: string;
130
133
  comments?: {
131
134
  path: string;
@@ -139,6 +142,7 @@ export declare function CreatePullRequestReviewTool(ctx: ToolContext): import("f
139
142
  pull_number: number;
140
143
  body?: string;
141
144
  approved?: boolean;
145
+ request_changes?: boolean;
142
146
  commit_id?: string;
143
147
  comments?: {
144
148
  path: string;
@@ -148,7 +152,9 @@ export declare function CreatePullRequestReviewTool(ctx: ToolContext): import("f
148
152
  suggestion?: string;
149
153
  start_line?: number;
150
154
  }[];
151
- }>>;
155
+ }>> & {
156
+ mutates?: boolean;
157
+ };
152
158
  /**
153
159
  * clear a pending review draft stranded on the PR by a prior hard-killed run
154
160
  * (workflow timeout, OOM) so the next createReview can succeed.