pullfrog 0.1.5 → 0.1.7
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 +21 -0
- package/dist/agents/sessionLabeler.d.ts +38 -18
- package/dist/agents/subagentModels.d.ts +19 -0
- package/dist/cli.mjs +678 -278
- package/dist/index.js +662 -264
- package/dist/internal.js +151 -59
- package/dist/models.d.ts +63 -3
- package/dist/utils/agent.d.ts +5 -2
- package/dist/utils/apiKeys.d.ts +18 -0
- package/dist/utils/instructions.d.ts +19 -0
- package/dist/utils/learnings.d.ts +20 -9
- package/dist/utils/normalizeEnv.d.ts +21 -1
- package/dist/utils/runContext.d.ts +16 -0
- package/dist/utils/subprocess.d.ts +40 -0
- package/dist/utils/timer.d.ts +11 -0
- package/package.json +1 -1
|
@@ -4,23 +4,34 @@
|
|
|
4
4
|
* back into future runs as durable context. Modeled on the PR-summary tmpfile
|
|
5
5
|
* pattern (see action/utils/prSummary.ts):
|
|
6
6
|
*
|
|
7
|
-
* 1. server seeds `pullfrog-learnings.md`
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* 1. server seeds `pullfrog-learnings.md` with the verbatim body of
|
|
8
|
+
* `Repo.learnings` (or empty for fresh repos), and parses headings
|
|
9
|
+
* server-side (`utils/learningsToc.ts`) — the parsed TOC is rendered
|
|
10
|
+
* into the LEARNINGS prompt section, not into the file
|
|
11
|
+
* 2. the agent reads the TOC in the prompt and uses listed line ranges
|
|
12
|
+
* to read just the sections relevant to the current task — file can
|
|
13
|
+
* grow large, but only targeted ranges hit the agent's context
|
|
14
|
+
* 3. agent edits the file in place at end-of-run during the reflection
|
|
15
|
+
* turn (see action/agents/postRun.ts buildLearningsReflectionPrompt)
|
|
16
|
+
* 4. main.ts reads the file back at end-of-run and PATCHes
|
|
17
|
+
* `/api/repo/[owner]/[repo]/learnings` if the body changed
|
|
14
18
|
*
|
|
15
19
|
* Edit-in-place avoids stuffing the entire learnings list into both the
|
|
16
20
|
* prompt context and an `update_learnings` MCP tool call (which previously
|
|
17
21
|
* required passing the FULL merged list as a string parameter — an
|
|
18
22
|
* output-token tax that grew linearly with the learnings size).
|
|
23
|
+
*
|
|
24
|
+
* Section structure is agent-curated. The reflection prompt teaches
|
|
25
|
+
* hierarchy + a soft 300-line-per-section cap to keep TOC ranges
|
|
26
|
+
* agent-targetable on long-lived repos; there is no fixed taxonomy.
|
|
19
27
|
*/
|
|
20
28
|
export declare const LEARNINGS_FILE_NAME = "pullfrog-learnings.md";
|
|
21
29
|
export declare function learningsFilePath(tmpdir: string): string;
|
|
22
|
-
/** seed the learnings
|
|
23
|
-
*
|
|
30
|
+
/** seed the rolling learnings tmpfile with the verbatim DB body (or empty
|
|
31
|
+
* string for fresh repos). returns the absolute path. the parsed TOC is
|
|
32
|
+
* carried separately via `RepoSettings.learningsHeadings` and rendered
|
|
33
|
+
* into the prompt by `resolveInstructions`, so the file on disk is just
|
|
34
|
+
* the body — no markers, no scaffold, no in-file TOC. */
|
|
24
35
|
export declare function seedLearningsFile(params: {
|
|
25
36
|
tmpdir: string;
|
|
26
37
|
current: string | null;
|
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trim surrounding whitespace from a sensitive value and register it as a
|
|
3
|
+
* GitHub Actions log mask. Trailing newlines from terminal-copy paste are a
|
|
4
|
+
* common footgun: the value travels through GH Actions logs and any tool
|
|
5
|
+
* that re-emits parts of it leaks the unmasked tail. Trimming canonicalises
|
|
6
|
+
* the value so the mask matches exactly what downstream tools will print.
|
|
7
|
+
*
|
|
8
|
+
* Masking is delegated to `core.setSecret` (not raw `console.log`) so the
|
|
9
|
+
* toolkit percent-encodes `\r`/`\n`; the runner V2 parser decodes them and
|
|
10
|
+
* registers the full value plus every non-empty line as separate masks. That
|
|
11
|
+
* keeps us safe for embedded-newline values (PEMs, kubeconfigs, JSON blobs)
|
|
12
|
+
* even though they aren't currently used.
|
|
13
|
+
*
|
|
14
|
+
* Returns the trimmed value, or `null` when the input was whitespace-only —
|
|
15
|
+
* callers must leave `process.env` untouched in that case so a misconfigured
|
|
16
|
+
* value surfaces as a clear "missing key" downstream rather than silently
|
|
17
|
+
* mutating to the empty string.
|
|
18
|
+
*/
|
|
19
|
+
export declare function sanitizeSecret(key: string, value: string): string | null;
|
|
1
20
|
/**
|
|
2
21
|
* Normalize environment variables to uppercase.
|
|
3
22
|
* This handles case-insensitive env var names (e.g., `anthropic_api_key` -> `ANTHROPIC_API_KEY`).
|
|
@@ -5,6 +24,7 @@
|
|
|
5
24
|
* If there are conflicts (same key with different capitalizations but different values),
|
|
6
25
|
* logs a warning and keeps the uppercase version.
|
|
7
26
|
*
|
|
8
|
-
* Also
|
|
27
|
+
* Also trims and masks sensitive values so accidental trailing whitespace
|
|
28
|
+
* doesn't defeat GitHub Actions log masking.
|
|
9
29
|
*/
|
|
10
30
|
export declare function normalizeEnv(): void;
|
|
@@ -6,6 +6,21 @@ export interface Mode {
|
|
|
6
6
|
description: string;
|
|
7
7
|
prompt: string;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* server-parsed TOC entry for `Repo.learnings`. depth is 1-6 (h1-h6),
|
|
11
|
+
* line numbers are 1-indexed against the raw body. computed by
|
|
12
|
+
* `parseLearningsHeadings` in `utils/learningsToc.ts` (server side) and
|
|
13
|
+
* shipped over the run-context JSON boundary; the canonical declaration
|
|
14
|
+
* lives there. duplicated here because the action runtime can't reach
|
|
15
|
+
* across into the proprietary root-level codebase, and the JSON wire
|
|
16
|
+
* means typecheck can't enforce shape equality across both sides.
|
|
17
|
+
*/
|
|
18
|
+
export interface LearningsHeading {
|
|
19
|
+
depth: 1 | 2 | 3 | 4 | 5 | 6;
|
|
20
|
+
title: string;
|
|
21
|
+
startLine: number;
|
|
22
|
+
endLine: number;
|
|
23
|
+
}
|
|
9
24
|
export interface RepoSettings {
|
|
10
25
|
model: string | null;
|
|
11
26
|
modes: Mode[];
|
|
@@ -18,6 +33,7 @@ export interface RepoSettings {
|
|
|
18
33
|
prApproveEnabled: boolean;
|
|
19
34
|
modeInstructions: Record<string, string>;
|
|
20
35
|
learnings: string | null;
|
|
36
|
+
learningsHeadings: LearningsHeading[];
|
|
21
37
|
envAllowlist: string | null;
|
|
22
38
|
}
|
|
23
39
|
/**
|
|
@@ -14,6 +14,27 @@ export declare function trackChild(options: TrackChildOptions): void;
|
|
|
14
14
|
export declare function untrackChild(child: ChildProcess): void;
|
|
15
15
|
export declare function setSignalHandler(handler: SignalHandler | null): void;
|
|
16
16
|
export declare function killTrackedChildren(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Controls what the wrapper retains in memory across the child's lifetime
|
|
19
|
+
* for the post-hoc `SpawnResult.stdout` / `SpawnResult.stderr` snapshots.
|
|
20
|
+
*
|
|
21
|
+
* Streaming callbacks (`onStdout` / `onStderr`) fire regardless — `retain`
|
|
22
|
+
* only governs the buffered snapshot returned in `SpawnResult`.
|
|
23
|
+
*
|
|
24
|
+
* - `"tail"` (default): keep the last `maxRetainedBytes` UTF-16 code units
|
|
25
|
+
* of each stream. Once the cap is exceeded, oldest bytes are sliced off
|
|
26
|
+
* and the result is prefixed with a `... [N MiB truncated] ...` sentinel.
|
|
27
|
+
* Right default for short-lived commands whose failure mode is in their
|
|
28
|
+
* final output (git errors, install failures, hook scripts).
|
|
29
|
+
* - `"none"`: skip the buffer entirely. `SpawnResult.stdout` / `.stderr`
|
|
30
|
+
* are empty strings. Use this for long-lived streaming agents that already
|
|
31
|
+
* drain via `onStdout` / `onStderr` and never read the buffered snapshot.
|
|
32
|
+
*
|
|
33
|
+
* Default cap is 8 MiB — well below V8's ~1 GiB `kMaxLength` so `+= chunk`
|
|
34
|
+
* can never throw `RangeError: Invalid string length`.
|
|
35
|
+
*/
|
|
36
|
+
export type RetainMode = "tail" | "none";
|
|
37
|
+
export declare const DEFAULT_MAX_RETAINED_BYTES: number;
|
|
17
38
|
export interface SpawnOptions {
|
|
18
39
|
cmd: string;
|
|
19
40
|
args: string[];
|
|
@@ -27,6 +48,25 @@ export interface SpawnOptions {
|
|
|
27
48
|
onStdout?: (chunk: string) => void;
|
|
28
49
|
onStderr?: (chunk: string) => void;
|
|
29
50
|
killGroup?: boolean;
|
|
51
|
+
retain?: RetainMode;
|
|
52
|
+
maxRetainedBytes?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Bounded string accumulator that keeps the tail of appended chunks.
|
|
56
|
+
* Once the cap is exceeded, oldest bytes are sliced off and `toString()`
|
|
57
|
+
* prefixes the survivors with a sentinel describing the elided byte count.
|
|
58
|
+
*
|
|
59
|
+
* Exported because long-lived agent runtimes (opencode, claude) also
|
|
60
|
+
* accumulate per-run narration strings independently of the spawn wrapper
|
|
61
|
+
* and need the same protection against V8's `kMaxLength`.
|
|
62
|
+
*/
|
|
63
|
+
export declare class TailBuffer {
|
|
64
|
+
private readonly cap;
|
|
65
|
+
private buffer;
|
|
66
|
+
private truncatedBytes;
|
|
67
|
+
constructor(cap: number);
|
|
68
|
+
append(chunk: string): void;
|
|
69
|
+
toString(): string;
|
|
30
70
|
}
|
|
31
71
|
export interface SpawnResult {
|
|
32
72
|
stdout: string;
|
package/dist/utils/timer.d.ts
CHANGED
|
@@ -4,9 +4,20 @@ export declare class Timer {
|
|
|
4
4
|
constructor();
|
|
5
5
|
checkpoint(name: string): void;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Measures wall-clock gap between the last tool_result and the next tool_call,
|
|
9
|
+
* surfacing it as a "thought for Xs" log when over `THINKING_THRESHOLD`.
|
|
10
|
+
*
|
|
11
|
+
* Use one instance per logical session (orchestrator, each subagent) — sharing
|
|
12
|
+
* a single timer across sessions conflates cross-session interleaving as
|
|
13
|
+
* thinking time. The optional `formatLine` lets the caller prefix output with
|
|
14
|
+
* a session label so attribution is visible in the merged log stream.
|
|
15
|
+
*/
|
|
7
16
|
export declare class ThinkingTimer {
|
|
8
17
|
private readonly durationFormatter;
|
|
9
18
|
private lastToolResultTimestamp;
|
|
19
|
+
private readonly formatLine;
|
|
20
|
+
constructor(formatLine?: (line: string) => string);
|
|
10
21
|
markToolResult(): void;
|
|
11
22
|
markToolCall(): void;
|
|
12
23
|
}
|