pullfrog 0.0.202 → 0.0.204
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/postRun.d.ts +66 -0
- package/dist/agents/reviewer.d.ts +32 -0
- package/dist/agents/sessionLabeler.d.ts +77 -0
- package/dist/agents/shared.d.ts +22 -3
- package/dist/cli.mjs +1231 -339
- package/dist/external.d.ts +6 -3
- package/dist/index.js +1146 -306
- package/dist/internal/index.d.ts +3 -1
- package/dist/internal.js +381 -70
- package/dist/mcp/comment.d.ts +6 -3
- package/dist/mcp/git.d.ts +2 -0
- package/dist/mcp/review.d.ts +35 -0
- package/dist/mcp/reviewComments.d.ts +29 -0
- package/dist/mcp/server.d.ts +9 -2
- package/dist/models.d.ts +17 -0
- package/dist/skills/git-archaeology/SKILL.md +188 -0
- package/dist/utils/payload.d.ts +8 -2
- package/dist/utils/progressComment.d.ts +146 -0
- package/dist/utils/runContext.d.ts +17 -0
- package/dist/utils/runContextData.d.ts +2 -1
- package/dist/utils/skills.d.ts +10 -0
- package/package.json +1 -1
package/dist/mcp/comment.d.ts
CHANGED
|
@@ -39,12 +39,15 @@ export declare const ReportProgress: import("arktype/internal/variants/object.ts
|
|
|
39
39
|
/**
|
|
40
40
|
* Report progress to a GitHub comment.
|
|
41
41
|
*
|
|
42
|
-
*
|
|
42
|
+
* progressComment has three states:
|
|
43
43
|
* - undefined: no comment yet — will create one if an issue/PR target exists
|
|
44
|
-
* -
|
|
44
|
+
* - object: active comment — will update it in place via the right REST endpoint for its type
|
|
45
45
|
* - null: deliberately deleted (e.g. after submitting a PR review) — skips silently
|
|
46
46
|
*
|
|
47
47
|
* The body is always tracked in lastProgressBody for the job summary regardless of comment state.
|
|
48
|
+
*
|
|
49
|
+
* The "existing plan comment" path always targets a top-level issue comment (plan comments are
|
|
50
|
+
* created by create_issue_comment with type:"Plan", never as review-thread replies).
|
|
48
51
|
*/
|
|
49
52
|
export declare function reportProgress(ctx: ToolContext, params: {
|
|
50
53
|
body: string;
|
|
@@ -66,7 +69,7 @@ export declare function ReportProgressTool(ctx: ToolContext): import("fastmcp").
|
|
|
66
69
|
* Delete the progress comment if it exists.
|
|
67
70
|
* Used by main.ts for stranded-comment cleanup (orphaned "Leaping into action" or
|
|
68
71
|
* checklist left by the todo tracker when the agent didn't call report_progress).
|
|
69
|
-
* Sets
|
|
72
|
+
* Sets progressComment to null so subsequent report_progress calls are no-ops.
|
|
70
73
|
*/
|
|
71
74
|
export declare function deleteProgressComment(ctx: ToolContext): Promise<boolean>;
|
|
72
75
|
export declare const ReplyToReviewComment: import("arktype/internal/variants/object.ts").ObjectType<{
|
package/dist/mcp/git.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare const PushBranch: import("arktype/internal/variants/object.ts").O
|
|
|
6
6
|
force: import("arktype/internal/attributes.ts").Default<boolean, false>;
|
|
7
7
|
branchName?: string;
|
|
8
8
|
}, {}>;
|
|
9
|
+
export type PushErrorKind = "concurrent-push" | "transient" | "unknown";
|
|
10
|
+
export declare function classifyPushError(msg: string): PushErrorKind;
|
|
9
11
|
export declare function PushBranchTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
|
|
10
12
|
branchName?: string;
|
|
11
13
|
force?: boolean;
|
package/dist/mcp/review.d.ts
CHANGED
|
@@ -36,6 +36,41 @@ export type ReviewSkipDecision = {
|
|
|
36
36
|
kind: "empty-downgraded-approve";
|
|
37
37
|
reason: string;
|
|
38
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* decision returned by duplicateReviewDecision when a session has already
|
|
41
|
+
* submitted a review and the current call would be a duplicate.
|
|
42
|
+
*/
|
|
43
|
+
export type DuplicateReviewDecision = {
|
|
44
|
+
kind: "already-submitted";
|
|
45
|
+
reviewId: number;
|
|
46
|
+
reason: string;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* decide whether a second create_pull_request_review call in the same session
|
|
50
|
+
* is a duplicate of an earlier submission.
|
|
51
|
+
*
|
|
52
|
+
* the agent is instructed to call create_pull_request_review exactly once per
|
|
53
|
+
* Review-mode session (see action/modes.ts), but in practice it sometimes
|
|
54
|
+
* submits twice — once with substantive feedback, then again with the
|
|
55
|
+
* canonical "Reviewed — no issues found." body when the prompt's branch
|
|
56
|
+
* logic re-classifies non-blocking observations. the second submission is
|
|
57
|
+
* always redundant: the first review is the record, and the duplicate just
|
|
58
|
+
* adds noise to the PR.
|
|
59
|
+
*
|
|
60
|
+
* legitimate follow-up reviews after new commits ARE allowed: the
|
|
61
|
+
* new-commits-mid-review path advances toolState.checkoutSha past the
|
|
62
|
+
* previously reviewed sha, and a subsequent checkout_pr advances it again.
|
|
63
|
+
* any call where checkoutSha has moved past the prior reviewedSha is a real
|
|
64
|
+
* follow-up and goes through. anything else — same sha, or no checkoutSha
|
|
65
|
+
* to compare against — is a duplicate.
|
|
66
|
+
*/
|
|
67
|
+
export declare function duplicateReviewDecision(params: {
|
|
68
|
+
existing: {
|
|
69
|
+
id: number;
|
|
70
|
+
reviewedSha: string | undefined;
|
|
71
|
+
} | undefined;
|
|
72
|
+
currentCheckoutSha: string | undefined;
|
|
73
|
+
}): DuplicateReviewDecision | null;
|
|
39
74
|
/**
|
|
40
75
|
* decide whether to skip a review submission before any network call.
|
|
41
76
|
*
|
|
@@ -97,6 +97,35 @@ interface GetReviewDataInput {
|
|
|
97
97
|
reviewId: number;
|
|
98
98
|
approvedBy?: string | undefined;
|
|
99
99
|
}
|
|
100
|
+
export interface FormatReviewDataInput {
|
|
101
|
+
review: ReviewResponse;
|
|
102
|
+
threads: ReviewThread[];
|
|
103
|
+
prFiles: ReviewPrFile[];
|
|
104
|
+
pullNumber: number;
|
|
105
|
+
reviewId: number;
|
|
106
|
+
}
|
|
107
|
+
export type ReviewResponse = {
|
|
108
|
+
body: string | null | undefined;
|
|
109
|
+
user: {
|
|
110
|
+
login: string;
|
|
111
|
+
} | null | undefined;
|
|
112
|
+
};
|
|
113
|
+
export type ReviewPrFile = {
|
|
114
|
+
filename: string;
|
|
115
|
+
patch?: string | undefined;
|
|
116
|
+
};
|
|
117
|
+
export declare function formatReviewData(input: FormatReviewDataInput): {
|
|
118
|
+
threadBlocks: Array<{
|
|
119
|
+
path: string;
|
|
120
|
+
lineRange: string;
|
|
121
|
+
content: string[];
|
|
122
|
+
}>;
|
|
123
|
+
reviewer: string;
|
|
124
|
+
formatted: {
|
|
125
|
+
toc: string;
|
|
126
|
+
content: string;
|
|
127
|
+
};
|
|
128
|
+
} | undefined;
|
|
100
129
|
export declare function getReviewData(input: GetReviewDataInput): Promise<{
|
|
101
130
|
threadBlocks: Array<{
|
|
102
131
|
path: string;
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ import type { PrepResult } from "../prep/index.ts";
|
|
|
6
6
|
import type { DiffCoverageState } from "../utils/diffCoverage.ts";
|
|
7
7
|
import type { OctokitWithPlugins } from "../utils/github.ts";
|
|
8
8
|
import type { ResolvedPayload } from "../utils/payload.ts";
|
|
9
|
+
import { type ProgressComment, type ProgressCommentType } from "../utils/progressComment.ts";
|
|
10
|
+
import type { AccountPlan } from "../utils/runContext.ts";
|
|
9
11
|
import type { RunContextData } from "../utils/runContextData.ts";
|
|
10
12
|
import type { TodoTracker } from "../utils/todoTracking.ts";
|
|
11
13
|
import type { CommentableLines } from "./review.ts";
|
|
@@ -48,7 +50,7 @@ export interface ToolState {
|
|
|
48
50
|
promise: Promise<PrepResult[]> | undefined;
|
|
49
51
|
results: PrepResult[] | undefined;
|
|
50
52
|
};
|
|
51
|
-
|
|
53
|
+
progressComment: ProgressComment | null | undefined;
|
|
52
54
|
hadProgressComment: boolean;
|
|
53
55
|
lastProgressBody?: string;
|
|
54
56
|
wasUpdated?: boolean;
|
|
@@ -63,7 +65,10 @@ export interface ToolState {
|
|
|
63
65
|
diffCoverage?: DiffCoverageState | undefined;
|
|
64
66
|
}
|
|
65
67
|
interface InitToolStateParams {
|
|
66
|
-
|
|
68
|
+
progressComment: {
|
|
69
|
+
id: string;
|
|
70
|
+
type: ProgressCommentType;
|
|
71
|
+
} | undefined;
|
|
67
72
|
}
|
|
68
73
|
export declare function initToolState(params: InitToolStateParams): ToolState;
|
|
69
74
|
export interface ToolContext {
|
|
@@ -84,6 +89,8 @@ export interface ToolContext {
|
|
|
84
89
|
jobId: string | undefined;
|
|
85
90
|
mcpServerUrl: string;
|
|
86
91
|
tmpdir: string;
|
|
92
|
+
oss: boolean;
|
|
93
|
+
plan: AccountPlan;
|
|
87
94
|
resolvedModel: string | undefined;
|
|
88
95
|
}
|
|
89
96
|
type JsonSchema = Record<string, unknown>;
|
package/dist/models.d.ts
CHANGED
|
@@ -60,10 +60,27 @@ export declare function getModelEnvVars(slug: string): string[];
|
|
|
60
60
|
export declare const modelAliases: ModelAlias[];
|
|
61
61
|
/** resolve a model slug to its concrete models.dev specifier (e.g. "anthropic/claude-opus-4-6") */
|
|
62
62
|
export declare function resolveModelSlug(slug: string): string | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* walk the fallback chain to the terminal (non-deprecated) alias.
|
|
65
|
+
* returns undefined if the chain is broken, exhausted, or cyclic.
|
|
66
|
+
*
|
|
67
|
+
* use this in UI display sites (dropdown trigger labels, PR-comment footers,
|
|
68
|
+
* etc.) so a deprecated stored slug renders as the model the user actually
|
|
69
|
+
* runs against — not the historical name. selectable lists should still hide
|
|
70
|
+
* deprecated aliases by filtering on `!a.fallback`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function resolveDisplayAlias(slug: string): ModelAlias | undefined;
|
|
63
73
|
/**
|
|
64
74
|
* resolve a model slug to the CLI-ready model string, following the fallback
|
|
65
75
|
* chain when a model is deprecated. returns the first non-deprecated resolve
|
|
66
76
|
* target, or undefined if the chain is exhausted or broken.
|
|
67
77
|
*/
|
|
68
78
|
export declare function resolveCliModel(slug: string): string | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* resolve a model slug to the OpenRouter-ready model string, following the
|
|
81
|
+
* fallback chain when a model is deprecated. returns undefined if the chain
|
|
82
|
+
* is exhausted/broken or the terminal alias has no openrouter equivalent
|
|
83
|
+
* (e.g. free opencode models).
|
|
84
|
+
*/
|
|
85
|
+
export declare function resolveOpenRouterModel(slug: string): string | undefined;
|
|
69
86
|
export {};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-archaeology
|
|
3
|
+
description: Investigate how code reached its current state — when a line, function, import, or whole file was changed or deleted, who removed it, and what it looked like before. Use when `git blame` came up empty, when content has been refactored away, or when you need the full evolution of a function across commits.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Git history archaeology
|
|
7
|
+
|
|
8
|
+
`git blame` only sees what's still in the working tree. For anything that was
|
|
9
|
+
deleted, moved, or refactored away, you need the commands below. Most agents
|
|
10
|
+
under-use them and end up scrolling through `git log -p` instead.
|
|
11
|
+
|
|
12
|
+
## Output discipline (read first)
|
|
13
|
+
|
|
14
|
+
`git log -p` on a long-lived file can dump tens of thousands of lines and blow
|
|
15
|
+
the context window. Always:
|
|
16
|
+
|
|
17
|
+
1. **Start narrow.** Use `--oneline` or `--stat` to get a list of candidate
|
|
18
|
+
commits.
|
|
19
|
+
2. **Drill in.** Use `git show <sha> -- <path>` for the diff of one specific
|
|
20
|
+
commit.
|
|
21
|
+
3. **Scope the search.** Add `--since="3 months ago"`, `-n 20`, or a path
|
|
22
|
+
restriction (`-- <path>`) so output stays manageable.
|
|
23
|
+
4. **Avoid `git log -p` without a path filter** on any non-trivial repo.
|
|
24
|
+
|
|
25
|
+
## Decision tree (by agent intent)
|
|
26
|
+
|
|
27
|
+
### "When did this exact line, string, or import disappear?"
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git log -S'<exact-string>' --oneline -- <file>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The pickaxe. Returns commits that **changed the count** of that string in the
|
|
34
|
+
file. The most recent hit is typically the removal commit. Add `-p` only after
|
|
35
|
+
you've narrowed to a few candidates.
|
|
36
|
+
|
|
37
|
+
Notes:
|
|
38
|
+
- `-S` is exact-string by default. Add `--pickaxe-regex` to make it a regex.
|
|
39
|
+
- The argument is "cuddled" with `-S` (`-S'foo bar'`), no space.
|
|
40
|
+
- `-S` will not detect pure in-file moves (count unchanged). Use `-G` for that.
|
|
41
|
+
- `--pickaxe-all` shows the entire changeset of matching commits, useful when
|
|
42
|
+
a commit changes both a definition and its call sites in other files.
|
|
43
|
+
|
|
44
|
+
### "When did the diff stop matching this regex?"
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git log -G'<regex>' --oneline -- <file>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Like `-S` but matches any added or removed hunk line against the regex. Use
|
|
51
|
+
`-G` when:
|
|
52
|
+
- You don't know the exact string but know a pattern.
|
|
53
|
+
- You want to catch in-file moves (`-S` won't).
|
|
54
|
+
- You want to find any diff that touched a pattern, even if the count was
|
|
55
|
+
preserved (e.g., a refactor that changed call sites without removing the
|
|
56
|
+
function).
|
|
57
|
+
|
|
58
|
+
### "How did this function evolve over time?"
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
git log -L :<function-name>:<file>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Every commit that touched the function, with diffs scoped to just the function
|
|
65
|
+
body. Works for languages git understands (most mainstream ones).
|
|
66
|
+
|
|
67
|
+
### "How did lines N–M evolve?"
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git log -L <N>,<M>:<file>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### "What's the full history of this file, including across renames?"
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
git log --follow --oneline -- <file> # overview
|
|
77
|
+
git log --follow -p -- <file> # with diffs (use sparingly)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`--follow` only works for a single file, not directories.
|
|
81
|
+
|
|
82
|
+
### "Where was a now-deleted line last present?"
|
|
83
|
+
|
|
84
|
+
Two-step pattern when you have an exact deleted string:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# 1. find a historical commit that contained the string
|
|
88
|
+
git log -S'<deleted-string>' --oneline --all -- <file>
|
|
89
|
+
|
|
90
|
+
# 2. reverse-blame from that commit to find the last commit it survived in
|
|
91
|
+
git blame --reverse <old-sha>..HEAD -- <file>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The reverse blame tells you, for each line, the last commit it survived in
|
|
95
|
+
before being modified or deleted. Pinpoints the exact deletion commit.
|
|
96
|
+
|
|
97
|
+
### "This file no longer exists — when was it deleted, and what was in it?"
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# find all commits that touched the path, even on other branches
|
|
101
|
+
git log --all --full-history --oneline -- <deleted-path>
|
|
102
|
+
|
|
103
|
+
# the most recent of those is usually the deletion. confirm:
|
|
104
|
+
git show <sha> --stat
|
|
105
|
+
|
|
106
|
+
# view the file's contents at any commit where it existed
|
|
107
|
+
git show <sha>^:<deleted-path>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
If you don't know the path, find it from filename alone:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# list all delete events with paths
|
|
114
|
+
git log --all --diff-filter=D --summary | grep -i '<filename>'
|
|
115
|
+
|
|
116
|
+
# or glob across all branches
|
|
117
|
+
git log --all --oneline -- '**/<filename>.*'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### "Who deleted it, in one shot?"
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git rev-list -n 1 HEAD -- <deleted-path> # the deletion commit
|
|
124
|
+
git show $(git rev-list -n 1 HEAD -- <deleted-path>) -- <deleted-path>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### "Restore a deleted file (locally, no commit)"
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
git restore --source=<deletion-sha>^ -- <deleted-path>
|
|
131
|
+
# or, on older git:
|
|
132
|
+
git checkout <deletion-sha>^ -- <deleted-path>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The `^` is critical — at the deletion commit the file is already gone, so we
|
|
136
|
+
read from its parent.
|
|
137
|
+
|
|
138
|
+
### "Search commit messages, not content"
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
git log --all --grep='<text>' --oneline
|
|
142
|
+
git log --all --grep='<text>' -i --oneline # case-insensitive
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Orthogonal to `-S`/`-G`, which only see the diff.
|
|
146
|
+
|
|
147
|
+
## Standard workflow for "why does this code look like this"
|
|
148
|
+
|
|
149
|
+
1. `git log --follow --oneline -- <file>` — overview of commits touching it.
|
|
150
|
+
2. If a recent commit looks suspicious: `git show <sha> -- <file>`.
|
|
151
|
+
3. If you expected to find something and it's missing:
|
|
152
|
+
`git log -S'<expected-string>' --oneline -- <file>`.
|
|
153
|
+
4. For a specific function's full lifecycle:
|
|
154
|
+
`git log -L :<fn>:<file>`.
|
|
155
|
+
5. For the deletion point of a known string: pickaxe to find an old commit
|
|
156
|
+
that contained it, then `git blame --reverse <old-sha>..HEAD -- <file>`.
|
|
157
|
+
|
|
158
|
+
## Useful flags reference
|
|
159
|
+
|
|
160
|
+
| Flag | Effect |
|
|
161
|
+
|------|--------|
|
|
162
|
+
| `--all` | Search all refs, not just the current branch. Use when investigating something that may have lived only on a feature branch. |
|
|
163
|
+
| `--full-history` | Keeps commits that history-simplification would otherwise drop. Needed for accurate history across merges. |
|
|
164
|
+
| `--follow` | Track a single file across renames. Single-file only. |
|
|
165
|
+
| `-M` / `-C` | Detect renames (`-M`) and copies (`-C`) when reading diffs. |
|
|
166
|
+
| `--diff-filter=D` | Restrict to commits that **deleted** something. `A`=added, `M`=modified, `R`=renamed. |
|
|
167
|
+
| `--source` | When combined with `--all`, annotate each commit with the ref it was reached from. |
|
|
168
|
+
| `--pickaxe-all` | With `-S`/`-G`, show all files in the matching commit, not just the matching file. |
|
|
169
|
+
| `--pickaxe-regex` | Treat the `-S` argument as a regex. |
|
|
170
|
+
| `--since` / `--until` | Time-bound the search. Cheap perf win on big repos. |
|
|
171
|
+
| `-n <count>` | Cap result count. |
|
|
172
|
+
| `--stat` | Per-commit file stats instead of full patches. Good first pass. |
|
|
173
|
+
|
|
174
|
+
## Notes and pitfalls
|
|
175
|
+
|
|
176
|
+
- Always include `--` before paths to disambiguate from refs (e.g.
|
|
177
|
+
`git log -S'foo' -- src/auth.ts`).
|
|
178
|
+
- `-S` triggers on **count change**. A pure refactor that moves a line within
|
|
179
|
+
the same file will not match. Use `-G` for those.
|
|
180
|
+
- `-G` runs diff twice and greps; it's slower than `-S`. Scope with paths and
|
|
181
|
+
`--since` on big repos.
|
|
182
|
+
- Without `--all`, `git log -- <path>` shows nothing if the path never existed
|
|
183
|
+
on the current branch. When in doubt, add `--all`.
|
|
184
|
+
- `git log --full-history -- <path>` alone has had bugs in some git versions
|
|
185
|
+
for deleted files; pair with `--all` for reliability.
|
|
186
|
+
- For files that were renamed, `git log -- <new-path>` only shows post-rename
|
|
187
|
+
history. Use `--follow` (one file) or `git log --all -- <old-path>` when
|
|
188
|
+
hunting across rename events.
|
package/dist/utils/payload.d.ts
CHANGED
|
@@ -9,7 +9,10 @@ export declare const JsonPayload: import("arktype/internal/variants/object.ts").
|
|
|
9
9
|
eventInstructions?: string;
|
|
10
10
|
event?: object;
|
|
11
11
|
timeout?: string | undefined;
|
|
12
|
-
|
|
12
|
+
progressComment?: {
|
|
13
|
+
id: string;
|
|
14
|
+
type: "issue" | "review";
|
|
15
|
+
} | undefined;
|
|
13
16
|
}, {}>;
|
|
14
17
|
export declare const Inputs: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
15
18
|
prompt: string;
|
|
@@ -33,7 +36,10 @@ export declare function resolvePayload(resolvedPromptInput: ResolvedPromptInput,
|
|
|
33
36
|
event: PayloadEvent;
|
|
34
37
|
timeout: string | undefined;
|
|
35
38
|
cwd: string | undefined;
|
|
36
|
-
|
|
39
|
+
progressComment: {
|
|
40
|
+
id: string;
|
|
41
|
+
type: "issue" | "review";
|
|
42
|
+
} | undefined;
|
|
37
43
|
push: import("../external.ts").PushPermission;
|
|
38
44
|
shell: import("../external.ts").ShellPermission;
|
|
39
45
|
proxyModel: string | undefined;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for reading, updating, deleting, and creating "progress comments" —
|
|
3
|
+
* the GitHub comments Pullfrog uses to surface a run's status.
|
|
4
|
+
*
|
|
5
|
+
* A progress comment can be one of two distinct GitHub entities with non-overlapping IDs and
|
|
6
|
+
* distinct REST endpoints:
|
|
7
|
+
* - "issue": a top-level issue/PR timeline comment (octokit.rest.issues.*Comment)
|
|
8
|
+
* - "review": an inline PR review-thread comment (octokit.rest.pulls.*ReviewComment)
|
|
9
|
+
*
|
|
10
|
+
* Callers carry a `ProgressComment` (id + type) value end-to-end so the right endpoint is always
|
|
11
|
+
* picked. Adding a third comment type later means one new branch in this file, not six.
|
|
12
|
+
*/
|
|
13
|
+
export type ProgressCommentType = "issue" | "review";
|
|
14
|
+
export type ProgressComment = {
|
|
15
|
+
id: number;
|
|
16
|
+
type: ProgressCommentType;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Parse the on-the-wire `{ id: string; type }` shape (the form carried in `JsonPayload`)
|
|
20
|
+
* into the in-memory `ProgressComment` shape. Returns undefined when the id isn't a
|
|
21
|
+
* positive integer so callers can short-circuit cleanly. Callers handle logging.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseProgressComment(raw: {
|
|
24
|
+
id: string;
|
|
25
|
+
type: ProgressCommentType;
|
|
26
|
+
} | null | undefined): ProgressComment | undefined;
|
|
27
|
+
interface CommentResponse {
|
|
28
|
+
data: {
|
|
29
|
+
id: number;
|
|
30
|
+
body?: string | null | undefined;
|
|
31
|
+
html_url: string;
|
|
32
|
+
node_id?: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export interface ProgressCommentOctokit {
|
|
36
|
+
rest: {
|
|
37
|
+
issues: {
|
|
38
|
+
createComment: (params: {
|
|
39
|
+
owner: string;
|
|
40
|
+
repo: string;
|
|
41
|
+
issue_number: number;
|
|
42
|
+
body: string;
|
|
43
|
+
}) => Promise<CommentResponse>;
|
|
44
|
+
getComment: (params: {
|
|
45
|
+
owner: string;
|
|
46
|
+
repo: string;
|
|
47
|
+
comment_id: number;
|
|
48
|
+
}) => Promise<CommentResponse>;
|
|
49
|
+
updateComment: (params: {
|
|
50
|
+
owner: string;
|
|
51
|
+
repo: string;
|
|
52
|
+
comment_id: number;
|
|
53
|
+
body: string;
|
|
54
|
+
}) => Promise<CommentResponse>;
|
|
55
|
+
deleteComment: (params: {
|
|
56
|
+
owner: string;
|
|
57
|
+
repo: string;
|
|
58
|
+
comment_id: number;
|
|
59
|
+
}) => Promise<unknown>;
|
|
60
|
+
};
|
|
61
|
+
pulls: {
|
|
62
|
+
createReplyForReviewComment: (params: {
|
|
63
|
+
owner: string;
|
|
64
|
+
repo: string;
|
|
65
|
+
pull_number: number;
|
|
66
|
+
comment_id: number;
|
|
67
|
+
body: string;
|
|
68
|
+
}) => Promise<CommentResponse>;
|
|
69
|
+
getReviewComment: (params: {
|
|
70
|
+
owner: string;
|
|
71
|
+
repo: string;
|
|
72
|
+
comment_id: number;
|
|
73
|
+
}) => Promise<CommentResponse>;
|
|
74
|
+
updateReviewComment: (params: {
|
|
75
|
+
owner: string;
|
|
76
|
+
repo: string;
|
|
77
|
+
comment_id: number;
|
|
78
|
+
body: string;
|
|
79
|
+
}) => Promise<CommentResponse>;
|
|
80
|
+
deleteReviewComment: (params: {
|
|
81
|
+
owner: string;
|
|
82
|
+
repo: string;
|
|
83
|
+
comment_id: number;
|
|
84
|
+
}) => Promise<unknown>;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
interface ApiCtx {
|
|
89
|
+
octokit: ProgressCommentOctokit;
|
|
90
|
+
owner: string;
|
|
91
|
+
repo: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Fetch a progress comment via the appropriate REST endpoint for its type.
|
|
95
|
+
* Returns the common subset of fields callers actually use.
|
|
96
|
+
*/
|
|
97
|
+
export declare function getProgressComment(ctx: ApiCtx, comment: ProgressComment): Promise<{
|
|
98
|
+
id: number;
|
|
99
|
+
body: string | undefined;
|
|
100
|
+
html_url: string;
|
|
101
|
+
}>;
|
|
102
|
+
/**
|
|
103
|
+
* Update a progress comment in place via the appropriate REST endpoint.
|
|
104
|
+
* Returns the common subset of fields callers actually use.
|
|
105
|
+
*/
|
|
106
|
+
export declare function updateProgressComment(ctx: ApiCtx, comment: ProgressComment, body: string): Promise<{
|
|
107
|
+
id: number;
|
|
108
|
+
body: string | undefined;
|
|
109
|
+
html_url: string;
|
|
110
|
+
node_id: string | undefined;
|
|
111
|
+
}>;
|
|
112
|
+
/**
|
|
113
|
+
* Delete a progress comment via the appropriate REST endpoint.
|
|
114
|
+
* Lower-level than `deleteProgressComment` in mcp/comment.ts — that one also clears
|
|
115
|
+
* tool state. Callers that don't have a ToolContext (post cleanup, error handlers)
|
|
116
|
+
* should use this directly; the higher-level wrapper delegates here.
|
|
117
|
+
*/
|
|
118
|
+
export declare function deleteProgressCommentApi(ctx: ApiCtx, comment: ProgressComment): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Discriminated target for `createLeapingProgressComment`. The two variants map to the two
|
|
121
|
+
* distinct GitHub create endpoints; review-reply additionally needs the parent comment ID.
|
|
122
|
+
*/
|
|
123
|
+
export type CreateProgressCommentTarget = {
|
|
124
|
+
kind: "issue";
|
|
125
|
+
issueNumber: number;
|
|
126
|
+
} | {
|
|
127
|
+
kind: "reviewReply";
|
|
128
|
+
pullNumber: number;
|
|
129
|
+
replyToCommentId: number;
|
|
130
|
+
};
|
|
131
|
+
export interface CreatedProgressComment {
|
|
132
|
+
comment: ProgressComment;
|
|
133
|
+
body: string | undefined;
|
|
134
|
+
html_url: string;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Create the initial "Leaping into action..." progress comment.
|
|
138
|
+
*
|
|
139
|
+
* Reliability: when `kind: "reviewReply"` fails (e.g. the parent comment was deleted or the
|
|
140
|
+
* thread is otherwise unreachable), falls back to a top-level issue comment on the same PR
|
|
141
|
+
* rather than leaving the run with no progress surface. The fallback is logged.
|
|
142
|
+
*
|
|
143
|
+
* (PR # === issue # in GitHub's number space, so `pullNumber` doubles as the fallback target.)
|
|
144
|
+
*/
|
|
145
|
+
export declare function createLeapingProgressComment(ctx: ApiCtx, target: CreateProgressCommentTarget, body: string): Promise<CreatedProgressComment>;
|
|
146
|
+
export {};
|
|
@@ -12,6 +12,7 @@ export interface RepoSettings {
|
|
|
12
12
|
setupScript: string | null;
|
|
13
13
|
postCheckoutScript: string | null;
|
|
14
14
|
prepushScript: string | null;
|
|
15
|
+
stopScript: string | null;
|
|
15
16
|
push: PushPermission;
|
|
16
17
|
shell: ShellPermission;
|
|
17
18
|
prApproveEnabled: boolean;
|
|
@@ -19,10 +20,26 @@ export interface RepoSettings {
|
|
|
19
20
|
learnings: string | null;
|
|
20
21
|
envAllowlist: string | null;
|
|
21
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Account-level billing plan. Orthogonal to repo-level OSS status. Mirrors
|
|
25
|
+
* the server's `AccountPlan` in `utils/billing.ts`. `"none"` = free tier,
|
|
26
|
+
* `"payg"` = card on file / pay-as-you-go.
|
|
27
|
+
*/
|
|
28
|
+
export type AccountPlan = "none" | "payg";
|
|
29
|
+
/**
|
|
30
|
+
* "Is Pullfrog absorbing marginal infra cost for this repo?" — composite
|
|
31
|
+
* predicate over the two orthogonal dimensions (repo-level OSS, account-level
|
|
32
|
+
* plan). Mirrors `isInfraCovered` in the server's `utils/billing.ts`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isInfraCovered(params: {
|
|
35
|
+
isOss: boolean;
|
|
36
|
+
plan: AccountPlan;
|
|
37
|
+
}): boolean;
|
|
22
38
|
export interface RunContext {
|
|
23
39
|
settings: RepoSettings;
|
|
24
40
|
apiToken: string;
|
|
25
41
|
oss: boolean;
|
|
42
|
+
plan: AccountPlan;
|
|
26
43
|
proxyModel?: string | undefined;
|
|
27
44
|
dbSecrets?: Record<string, string> | undefined;
|
|
28
45
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Octokit } from "@octokit/rest";
|
|
2
2
|
import { type OctokitWithPlugins } from "./github.ts";
|
|
3
|
-
import { type RepoSettings } from "./runContext.ts";
|
|
3
|
+
import { type AccountPlan, type RepoSettings } from "./runContext.ts";
|
|
4
4
|
export interface RunContextData {
|
|
5
5
|
repo: {
|
|
6
6
|
owner: string;
|
|
@@ -10,6 +10,7 @@ export interface RunContextData {
|
|
|
10
10
|
repoSettings: RepoSettings;
|
|
11
11
|
apiToken: string;
|
|
12
12
|
oss: boolean;
|
|
13
|
+
plan: AccountPlan;
|
|
13
14
|
proxyModel?: string | undefined;
|
|
14
15
|
dbSecrets?: Record<string, string> | undefined;
|
|
15
16
|
}
|
package/dist/utils/skills.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* write all bundled skills into the fake HOME so OpenCode / Claude Code discover
|
|
3
|
+
* them via their auto-scan directories.
|
|
4
|
+
*
|
|
5
|
+
* called once per agent run from each agent's `run()`. cheap (small file
|
|
6
|
+
* writes), no network, idempotent.
|
|
7
|
+
*/
|
|
8
|
+
export declare function installBundledSkills(params: {
|
|
9
|
+
home: string;
|
|
10
|
+
}): void;
|
|
1
11
|
/**
|
|
2
12
|
* install a skill globally via the `skills` CLI.
|
|
3
13
|
*
|