pullfrog 0.1.49 → 0.1.50

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.
@@ -3,7 +3,7 @@
3
3
  * Re-exports shared types, values, and utilities needed by the Next.js app.
4
4
  */
5
5
  export type { AuthorPermission, AutoTier, EffortPosition, ModelAlias, ModelProvider, Payload, PayloadEvent, ProviderConfig, PushPermission, ShellPermission, ToolPermission, WriteablePayload, XrepoConfig, } from "../external.ts";
6
- export { AUTO_EFFICIENT, AUTO_INTELLIGENT, DEFAULT_EFFORT_POSITION, DEFAULT_PROXY_MODEL, defaultAutoTier, EFFORT_ALIASES, getAutoSelectHintModel, getModelEffortLevels, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, isAutoTier, isCardGatedModel, isEffortPosition, modelAliases, offeredRungs, parseEffortPosition, parseModel, providers, pullfrogMcpName, resolveAutoTier, resolveCliModel, resolveDisplayAlias, resolveModelRung, resolveModelSlug, resolveOpenRouterModel, resolveRung, rungLabel, rungPosition, } from "../external.ts";
6
+ export { AUTO_EFFICIENT, AUTO_INTELLIGENT, DEFAULT_EFFORT_POSITION, DEFAULT_PROXY_MODEL, defaultAutoTier, EFFORT_ALIASES, getAutoSelectHintModel, getModelEffortLevels, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, isAutoTier, isCardGatedModel, isEffortPosition, modelAliases, modelHasStoredAuth, offeredRungs, parseEffortPosition, parseModel, providers, pullfrogMcpName, resolveAutoTier, resolveCliModel, resolveDisplayAlias, resolveModelRung, resolveModelSlug, resolveOpenRouterModel, resolveRung, rungLabel, rungPosition, } from "../external.ts";
7
7
  export type { Mode } from "../modes.ts";
8
8
  export { modes } from "../modes.ts";
9
9
  export { commercialPaywallBody } from "../utils/billingErrors.ts";
@@ -12,6 +12,7 @@ export { buildPullfrogFooter, PULLFROG_DIVIDER, stripExistingFooter, } from "../
12
12
  export type { CodexAuthBody } from "../utils/codexOAuth.ts";
13
13
  export { decodeJwtExpMs, OAuthInvalidGrantError, parseCodexAuthBody, refreshCodexAuthBody, stringifyCodexAuthBody, } from "../utils/codexOAuth.ts";
14
14
  export type { ResourceUsage, UsageSummary } from "../utils/github.ts";
15
+ export { isPullfrog } from "../utils/isPullfrog.ts";
15
16
  export { isLeapingIntoActionCommentBody, LEAPING_INTO_ACTION_PREFIX, } from "../utils/leapingComment.ts";
16
17
  export { MAX_LEARNINGS_LENGTH, truncateAtLineBoundary } from "../utils/learningsTruncate.ts";
17
18
  export type { CreateProgressCommentTarget, ProgressComment, ProgressCommentType, } from "../utils/progressComment.ts";
package/dist/internal.js CHANGED
@@ -659,6 +659,11 @@ function getModelManagedCredentials(slug) {
659
659
  const providerConfig = providers[parsed.provider];
660
660
  return providerConfig?.managedCredentials?.slice() ?? [];
661
661
  }
662
+ function modelHasStoredAuth(params) {
663
+ const slug = resolveDisplayAlias(params.model)?.slug ?? params.model;
664
+ const authVars = [...getModelEnvVars(slug), ...getModelManagedCredentials(slug)];
665
+ return authVars.some((v) => params.secretNames.includes(v));
666
+ }
662
667
  var modelAliases = Object.entries(providers).flatMap(
663
668
  ([providerKey, config]) => Object.entries(config.models).map(([modelId, def]) => ({
664
669
  slug: `${providerKey}/${modelId}`,
@@ -1338,6 +1343,12 @@ function stringifyCodexAuthBody(body) {
1338
1343
  `;
1339
1344
  }
1340
1345
 
1346
+ // utils/isPullfrog.ts
1347
+ function isPullfrog(actor) {
1348
+ actor = actor?.toLowerCase().replace("[bot]", "");
1349
+ return !!actor && (actor === "pullfrog" || actor === "pullfrogdev");
1350
+ }
1351
+
1341
1352
  // utils/leapingComment.ts
1342
1353
  var LEAPING_INTO_ACTION_PREFIX = "Leaping into action";
1343
1354
  function isLeapingIntoActionCommentBody(body) {
@@ -1456,8 +1467,8 @@ async function createLeapingProgressComment(ctx, target, body) {
1456
1467
  }
1457
1468
 
1458
1469
  // utils/runStatusCheck.ts
1459
- var RUN_STATUS_CHECK_NAME = "Pullfrog";
1460
- var APPROVAL_CHECK_NAME = "Pullfrog approval";
1470
+ var RUN_STATUS_CHECK_NAME = "pullfrog";
1471
+ var APPROVAL_CHECK_NAME = "pullfrog-approval";
1461
1472
  var IN_PROGRESS_OUTPUT = {
1462
1473
  title: "Pullfrog is running",
1463
1474
  summary: "Pullfrog is working on this pull request. This check updates when the run finishes."
@@ -1608,8 +1619,10 @@ export {
1608
1619
  isCardGatedModel,
1609
1620
  isEffortPosition,
1610
1621
  isLeapingIntoActionCommentBody,
1622
+ isPullfrog,
1611
1623
  isValidTimeString,
1612
1624
  modelAliases,
1625
+ modelHasStoredAuth,
1613
1626
  modes,
1614
1627
  offeredRungs,
1615
1628
  parseCodexAuthBody,
@@ -24,6 +24,7 @@ export interface ToolContext {
24
24
  prApproveEnabled: boolean;
25
25
  autoMergeEnabled: boolean;
26
26
  signedCommits: boolean;
27
+ repoIntelligence: boolean;
27
28
  modeInstructions: Record<string, string>;
28
29
  toolState: ToolState;
29
30
  runId: number | undefined;
@@ -0,0 +1,11 @@
1
+ import type { ToolContext } from "./server.ts";
2
+ export declare const SimilarIssues: import("arktype/internal/variants/object.ts").ObjectType<{
3
+ issue_number: number;
4
+ }, {}>;
5
+ export declare function SimilarIssuesTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
6
+ issue_number: number;
7
+ }, {
8
+ issue_number: number;
9
+ }>> & {
10
+ mutates?: boolean;
11
+ };
package/dist/models.d.ts CHANGED
@@ -128,6 +128,16 @@ export declare function getModelEnvVars(slug: string): string[];
128
128
  * a manual-paste option in `init` or the AgentSettings env-var button row.
129
129
  * see `provider.managedCredentials` and wiki/codex-auth.md. */
130
130
  export declare function getModelManagedCredentials(slug: string): string[];
131
+ /**
132
+ * Whether one of `secretNames` can run `model` — the Router opt-out predicate,
133
+ * shared so every caller decides the same way. Auto-tier sentinels and
134
+ * deprecated aliases resolve first; `getModelEnvVars("auto/intelligent")` is
135
+ * `[]` otherwise.
136
+ */
137
+ export declare function modelHasStoredAuth(params: {
138
+ model: string;
139
+ secretNames: string[];
140
+ }): boolean;
131
141
  export declare const modelAliases: ModelAlias[];
132
142
  /**
133
143
  * `repo.model` sentinels for the two managed auto tiers. stored verbatim in
@@ -16,6 +16,31 @@ export declare const DEFAULT_ACTIVITY_TIMEOUT_MS = 300000;
16
16
  * genuinely hung run is only GitHub Actions minutes, not tokens.
17
17
  */
18
18
  export declare const AGENT_ACTIVITY_TIMEOUT_MS = 900000;
19
+ /**
20
+ * Budget for the window before the agent's FIRST streamed event, which the flat
21
+ * budget above cannot justify: no tool has been called yet, so there is no
22
+ * in-flight tool call to protect (#1120).
23
+ *
24
+ * The window it guards is a provider that accepts the request and then never
25
+ * completes the stream. Reproduced against a stalling endpoint: the request goes
26
+ * out (81KB of prompt accepted), and opencode emits neither `part.updated` nor
27
+ * `session.error` — so the run looks alive while doing nothing. A per-request
28
+ * client timeout does NOT help; measured, opencode reacts to one by silently
29
+ * RETRYING (4 requests in 85s against an 8s budget vs 1 with none), so only a
30
+ * total-elapsed bound ends it.
31
+ *
32
+ * Sized off a direct measurement of time-to-first-model-part over 83 successful
33
+ * runs across 60+ repos (2026-07-30 onward): p50 5.6s, p90 8.4s, max 39.0s, and
34
+ * ZERO runs above 60s. 120s is ~3x the observed max and ~14x p90.
35
+ *
36
+ * Note this is NOT the "520s legitimate outlier" figure quoted in #1120 — that
37
+ * measured time to the first LOGGED line (`» thinking` is emitted when the
38
+ * reasoning block *ends*, carrying its own duration), on a runner concurrently
39
+ * busy with `npm ci`. The clock here starts on the first streamed part, which
40
+ * lands much earlier. Upstream's own proposal for this bug used a 30s
41
+ * first-byte budget (anomalyco/opencode#29420), so 120s stays conservative.
42
+ */
43
+ export declare const AGENT_FIRST_EVENT_TIMEOUT_MS = 120000;
19
44
  export declare const DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5000;
20
45
  export declare const ACTIVITY_NOISE_PATTERNS: readonly RegExp[];
21
46
  export declare function isActivityNoise(chunk: string | Uint8Array): boolean;
@@ -18,6 +18,19 @@ export type AgentDiagnostic = {
18
18
  lastProviderError: string | undefined;
19
19
  /** count of stdout events successfully parsed before the failure. */
20
20
  eventCount: number;
21
+ /**
22
+ * idle span the watchdog measured, in seconds. set structurally because the
23
+ * opencode harness's error string carries only prose — re-parsing it dropped
24
+ * the duration from the rendered explanation entirely.
25
+ */
26
+ idleSec: number | undefined;
27
+ /**
28
+ * whether the model produced a part of its own before the stall. `eventCount`
29
+ * cannot answer this: it counts every SSE event, and our own prompt echo plus
30
+ * session lifecycle events land before the provider is contacted, so it is
31
+ * never 0 on a live stream.
32
+ */
33
+ sawModelOutput: boolean;
21
34
  };
22
35
  /**
23
36
  * Build a user-facing markdown body for an agent hang or failure.
@@ -12,6 +12,9 @@ interface InstructionsContext {
12
12
  /** commits are created via the GitHub API (commit_changes tool) so GitHub
13
13
  * signs them — flips the Git instructions to the signed-commits flow. */
14
14
  signedCommits: boolean;
15
+ /** the account is allowlisted for issue indexing, so `find_similar_issues`
16
+ * is registered on issue runs — adds the duplicate-check instruction. */
17
+ repoIntelligence: boolean;
15
18
  /** absolute path to the seeded learnings tmpfile, or null when the file
16
19
  * couldn't be seeded for some reason. main.ts always seeds, so in
17
20
  * practice this is always set; the null case keeps the type honest. */
@@ -0,0 +1,4 @@
1
+ /**
2
+ * true when a GitHub login belongs to Pullfrog's production or development app.
3
+ */
4
+ export declare function isPullfrog(actor: string | null | undefined): boolean;
@@ -44,12 +44,6 @@ export declare const Inputs: import("arktype/internal/variants/object.ts").Objec
44
44
  export type Inputs = typeof Inputs.infer;
45
45
  export type ResolvedPromptInput = string | typeof JsonPayload.infer;
46
46
  export declare function resolvePromptInput(): ResolvedPromptInput;
47
- /**
48
- * true when `actor` is Pullfrog's own GitHub identity — the bot login
49
- * (`pullfrog[bot]` / `pullfrogdev[bot]`) or the bare account. used to skip
50
- * self-triggered events and to recognize Pullfrog-originated review threads.
51
- */
52
- export declare const isPullfrog: (actor: string | null | undefined) => boolean;
53
47
  export declare function resolvePayload(resolvedPromptInput: ResolvedPromptInput, repoSettings: RepoSettings): {
54
48
  "~pullfrog": true;
55
49
  version: string;
@@ -34,6 +34,7 @@ export interface RepoSettings {
34
34
  prApproveEnabled: boolean;
35
35
  autoMergeEnabled: boolean;
36
36
  signedCommits: boolean;
37
+ repoIntelligence: boolean;
37
38
  progressComments: boolean;
38
39
  statusChecks: boolean;
39
40
  modeInstructions: Record<string, string>;
@@ -23,12 +23,17 @@
23
23
  */
24
24
  /**
25
25
  * the run-lifecycle check. verdict-agnostic — it reports that a run happened, not what it
26
- * found. this string IS the branch-protection identifier, so changing it silently breaks
27
- * any repo that required the old name.
26
+ * found.
27
+ *
28
+ * **DO NOT RENAME.** A check run has no separate display name, so this string is also the
29
+ * context branch protection matches on. Renaming it on 2026-08-02 stopped the old context
30
+ * reporting and blocked merges on four customer repos; it was reverted. Most installs'
31
+ * branch protection is unreadable to us, so the blast radius cannot even be measured.
32
+ * See wiki/review-approval.md.
28
33
  */
29
- export declare const RUN_STATUS_CHECK_NAME = "Pullfrog";
34
+ export declare const RUN_STATUS_CHECK_NAME = "pullfrog";
30
35
  /** the review-verdict check. opt-in, terminal-only, and deliberately separate from the above. */
31
- export declare const APPROVAL_CHECK_NAME = "Pullfrog approval";
36
+ export declare const APPROVAL_CHECK_NAME = "pullfrog-approval";
32
37
  /**
33
38
  * The terminal states we report. Exactly GitHub's check-run `conclusion` enum, which
34
39
  * happens to be `WorkflowRunStatus` minus `running` — so the server can map a finished
@@ -1,6 +1,6 @@
1
1
  import type { ToolContext } from "../mcp/server.ts";
2
2
  /**
3
- * post the `Pullfrog` (run lifecycle) and `Pullfrog approval` (review verdict)
3
+ * post the `pullfrog` (run lifecycle) and `pullfrog-approval` (review verdict)
4
4
  * commit-status check-runs.
5
5
  *
6
6
  * - `Pullfrog` is on by default (`Repo.statusChecks`). the server already created it
@@ -8,7 +8,7 @@ import type { ToolContext } from "../mcp/server.ts";
8
8
  * see `runStatusCheck.ts` for why a second create would leave two contradictory rows.
9
9
  * the terminal-create fallback covers a payload with no `checkRun` (older server
10
10
  * build mid-rolling-deploy, or a workflow driven outside Pullfrog's dispatch path).
11
- * - `Pullfrog approval` stays opt-in (`status_checks: enabled`) and terminal-only:
11
+ * - `pullfrog-approval` stays opt-in (`status_checks: enabled`) and terminal-only:
12
12
  * it asserts a review verdict, which only exists once a run produces one. anchored
13
13
  * to the exact reviewed sha so a mid-run push leaves the new head unapproved until
14
14
  * a follow-up re-review reports.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pullfrog",
3
- "version": "0.1.49",
3
+ "version": "0.1.50",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "pullfrog": "dist/cli.mjs",