@cam5/baby-bird 0.1.0
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/README.md +205 -0
- package/dist/chunk-RWSCST2I.js +1753 -0
- package/dist/chunk-RWSCST2I.js.map +1 -0
- package/dist/cli.js +326 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +648 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Core data model for baby-bird. Everything here is plain, serializable data so
|
|
5
|
+
* that any renderer (CLI today, curses/web later) can consume a Tour without
|
|
6
|
+
* touching git or an LLM.
|
|
7
|
+
*/
|
|
8
|
+
type LineType = 'add' | 'del' | 'ctx';
|
|
9
|
+
interface HunkLine {
|
|
10
|
+
type: LineType;
|
|
11
|
+
/** Line number in the old file (absent for added lines). */
|
|
12
|
+
oldNo?: number;
|
|
13
|
+
/** Line number in the new file (absent for deleted lines). */
|
|
14
|
+
newNo?: number;
|
|
15
|
+
/** Line content without the leading +/-/space. */
|
|
16
|
+
text: string;
|
|
17
|
+
}
|
|
18
|
+
interface Hunk {
|
|
19
|
+
/** Stable id used in prompts, e.g. "F3.H2". */
|
|
20
|
+
id: string;
|
|
21
|
+
oldStart: number;
|
|
22
|
+
oldLines: number;
|
|
23
|
+
newStart: number;
|
|
24
|
+
newLines: number;
|
|
25
|
+
/** Text after the second @@ (function context), may be empty. */
|
|
26
|
+
header: string;
|
|
27
|
+
lines: HunkLine[];
|
|
28
|
+
}
|
|
29
|
+
type FileStatus = 'added' | 'deleted' | 'modified' | 'renamed';
|
|
30
|
+
interface DiffFile {
|
|
31
|
+
/** Stable id used in prompts, e.g. "F3". */
|
|
32
|
+
id: string;
|
|
33
|
+
/** New path (or old path for deletions). */
|
|
34
|
+
path: string;
|
|
35
|
+
/** Old path when renamed. */
|
|
36
|
+
oldPath?: string;
|
|
37
|
+
status: FileStatus;
|
|
38
|
+
binary: boolean;
|
|
39
|
+
additions: number;
|
|
40
|
+
deletions: number;
|
|
41
|
+
hunks: Hunk[];
|
|
42
|
+
}
|
|
43
|
+
interface ParsedDiff {
|
|
44
|
+
files: DiffFile[];
|
|
45
|
+
}
|
|
46
|
+
interface CommitInfo {
|
|
47
|
+
sha: string;
|
|
48
|
+
subject: string;
|
|
49
|
+
}
|
|
50
|
+
interface PullRequestInfo {
|
|
51
|
+
number: number;
|
|
52
|
+
title: string;
|
|
53
|
+
body: string;
|
|
54
|
+
url: string;
|
|
55
|
+
baseRefName: string;
|
|
56
|
+
headRefName: string;
|
|
57
|
+
}
|
|
58
|
+
type RangeResolvedBy = 'explicit' | 'pull-request' | 'ancestor-branch' | 'default-branch';
|
|
59
|
+
type WorkingResolvedBy = 'explicit' | 'dirty-tree';
|
|
60
|
+
type TourSource = {
|
|
61
|
+
kind: 'range';
|
|
62
|
+
/** Human label for the base, e.g. "main" or "origin/main". */
|
|
63
|
+
base: string;
|
|
64
|
+
/** Human label for the head, e.g. "feat/x" or "HEAD". */
|
|
65
|
+
head: string;
|
|
66
|
+
baseSha: string;
|
|
67
|
+
headSha: string;
|
|
68
|
+
/** Set when the base was taken at the merge-base (three-dot semantics). */
|
|
69
|
+
mergeBase?: string;
|
|
70
|
+
resolvedBy: RangeResolvedBy;
|
|
71
|
+
} | {
|
|
72
|
+
kind: 'working';
|
|
73
|
+
headSha: string;
|
|
74
|
+
staged: boolean;
|
|
75
|
+
resolvedBy: WorkingResolvedBy;
|
|
76
|
+
};
|
|
77
|
+
interface TourStats {
|
|
78
|
+
files: number;
|
|
79
|
+
additions: number;
|
|
80
|
+
deletions: number;
|
|
81
|
+
}
|
|
82
|
+
interface Excerpt {
|
|
83
|
+
file: string;
|
|
84
|
+
/** The hunk this excerpt was sliced from. */
|
|
85
|
+
hunkId: string;
|
|
86
|
+
/** One-line caption from the model. */
|
|
87
|
+
note?: string;
|
|
88
|
+
oldStart: number;
|
|
89
|
+
newStart: number;
|
|
90
|
+
lines: HunkLine[];
|
|
91
|
+
}
|
|
92
|
+
interface Section {
|
|
93
|
+
id: string;
|
|
94
|
+
title: string;
|
|
95
|
+
description: string;
|
|
96
|
+
/** Paths this section is about. Sections may share files. */
|
|
97
|
+
files: string[];
|
|
98
|
+
stats: TourStats;
|
|
99
|
+
excerpts: Excerpt[];
|
|
100
|
+
}
|
|
101
|
+
interface TourGenerator {
|
|
102
|
+
preset: string | null;
|
|
103
|
+
command: string[];
|
|
104
|
+
}
|
|
105
|
+
interface Tour {
|
|
106
|
+
version: 1;
|
|
107
|
+
generatedAt: string;
|
|
108
|
+
source: TourSource;
|
|
109
|
+
generator: TourGenerator;
|
|
110
|
+
pullRequest?: {
|
|
111
|
+
number: number;
|
|
112
|
+
title: string;
|
|
113
|
+
url: string;
|
|
114
|
+
};
|
|
115
|
+
title: string;
|
|
116
|
+
summary: string;
|
|
117
|
+
stats: TourStats;
|
|
118
|
+
sections: Section[];
|
|
119
|
+
}
|
|
120
|
+
/** Everything gathered from git/code host before we talk to the model. */
|
|
121
|
+
interface TourContext {
|
|
122
|
+
source: TourSource;
|
|
123
|
+
branch: string | null;
|
|
124
|
+
diff: ParsedDiff;
|
|
125
|
+
commits: CommitInfo[];
|
|
126
|
+
pullRequest?: PullRequestInfo;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
declare const LlmTourOutputSchema: z.ZodObject<{
|
|
130
|
+
title: z.ZodString;
|
|
131
|
+
summary: z.ZodString;
|
|
132
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
133
|
+
title: z.ZodString;
|
|
134
|
+
description: z.ZodString;
|
|
135
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
136
|
+
excerpts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
137
|
+
hunk: z.ZodString;
|
|
138
|
+
lines: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
139
|
+
note: z.ZodOptional<z.ZodString>;
|
|
140
|
+
}, z.core.$strip>>>;
|
|
141
|
+
}, z.core.$strip>>;
|
|
142
|
+
}, z.core.$strip>;
|
|
143
|
+
type LlmTourOutput = z.infer<typeof LlmTourOutputSchema>;
|
|
144
|
+
declare const TourSchema: z.ZodObject<{
|
|
145
|
+
version: z.ZodLiteral<1>;
|
|
146
|
+
generatedAt: z.ZodString;
|
|
147
|
+
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
148
|
+
kind: z.ZodLiteral<"range">;
|
|
149
|
+
base: z.ZodString;
|
|
150
|
+
head: z.ZodString;
|
|
151
|
+
baseSha: z.ZodString;
|
|
152
|
+
headSha: z.ZodString;
|
|
153
|
+
mergeBase: z.ZodOptional<z.ZodString>;
|
|
154
|
+
resolvedBy: z.ZodEnum<{
|
|
155
|
+
explicit: "explicit";
|
|
156
|
+
"pull-request": "pull-request";
|
|
157
|
+
"ancestor-branch": "ancestor-branch";
|
|
158
|
+
"default-branch": "default-branch";
|
|
159
|
+
}>;
|
|
160
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
161
|
+
kind: z.ZodLiteral<"working">;
|
|
162
|
+
headSha: z.ZodString;
|
|
163
|
+
staged: z.ZodBoolean;
|
|
164
|
+
resolvedBy: z.ZodEnum<{
|
|
165
|
+
explicit: "explicit";
|
|
166
|
+
"dirty-tree": "dirty-tree";
|
|
167
|
+
}>;
|
|
168
|
+
}, z.core.$strip>], "kind">;
|
|
169
|
+
generator: z.ZodObject<{
|
|
170
|
+
preset: z.ZodNullable<z.ZodString>;
|
|
171
|
+
command: z.ZodArray<z.ZodString>;
|
|
172
|
+
}, z.core.$strip>;
|
|
173
|
+
pullRequest: z.ZodOptional<z.ZodObject<{
|
|
174
|
+
number: z.ZodNumber;
|
|
175
|
+
title: z.ZodString;
|
|
176
|
+
url: z.ZodString;
|
|
177
|
+
}, z.core.$strip>>;
|
|
178
|
+
title: z.ZodString;
|
|
179
|
+
summary: z.ZodString;
|
|
180
|
+
stats: z.ZodObject<{
|
|
181
|
+
files: z.ZodNumber;
|
|
182
|
+
additions: z.ZodNumber;
|
|
183
|
+
deletions: z.ZodNumber;
|
|
184
|
+
}, z.core.$strip>;
|
|
185
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
186
|
+
id: z.ZodString;
|
|
187
|
+
title: z.ZodString;
|
|
188
|
+
description: z.ZodString;
|
|
189
|
+
files: z.ZodArray<z.ZodString>;
|
|
190
|
+
stats: z.ZodObject<{
|
|
191
|
+
files: z.ZodNumber;
|
|
192
|
+
additions: z.ZodNumber;
|
|
193
|
+
deletions: z.ZodNumber;
|
|
194
|
+
}, z.core.$strip>;
|
|
195
|
+
excerpts: z.ZodArray<z.ZodObject<{
|
|
196
|
+
file: z.ZodString;
|
|
197
|
+
hunkId: z.ZodString;
|
|
198
|
+
note: z.ZodOptional<z.ZodString>;
|
|
199
|
+
oldStart: z.ZodNumber;
|
|
200
|
+
newStart: z.ZodNumber;
|
|
201
|
+
lines: z.ZodArray<z.ZodObject<{
|
|
202
|
+
type: z.ZodEnum<{
|
|
203
|
+
add: "add";
|
|
204
|
+
del: "del";
|
|
205
|
+
ctx: "ctx";
|
|
206
|
+
}>;
|
|
207
|
+
oldNo: z.ZodOptional<z.ZodNumber>;
|
|
208
|
+
newNo: z.ZodOptional<z.ZodNumber>;
|
|
209
|
+
text: z.ZodString;
|
|
210
|
+
}, z.core.$strip>>;
|
|
211
|
+
}, z.core.$strip>>;
|
|
212
|
+
}, z.core.$strip>>;
|
|
213
|
+
}, z.core.$strip>;
|
|
214
|
+
declare function formatIssues(error: z.ZodError): string;
|
|
215
|
+
|
|
216
|
+
type PromptVia = 'stdin' | 'arg';
|
|
217
|
+
interface LlmPreset {
|
|
218
|
+
/** argv; when promptVia is "arg", any "{prompt}" token is replaced with the prompt. */
|
|
219
|
+
command: string[];
|
|
220
|
+
promptVia?: PromptVia;
|
|
221
|
+
description?: string;
|
|
222
|
+
}
|
|
223
|
+
declare const BUILTIN_PRESETS: Readonly<Record<string, LlmPreset>>;
|
|
224
|
+
declare const ConfigSchema: z.ZodObject<{
|
|
225
|
+
llm: z.ZodObject<{
|
|
226
|
+
preset: z.ZodString;
|
|
227
|
+
presets: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
228
|
+
command: z.ZodArray<z.ZodString>;
|
|
229
|
+
promptVia: z.ZodOptional<z.ZodEnum<{
|
|
230
|
+
stdin: "stdin";
|
|
231
|
+
arg: "arg";
|
|
232
|
+
}>>;
|
|
233
|
+
description: z.ZodOptional<z.ZodString>;
|
|
234
|
+
}, z.core.$strip>>;
|
|
235
|
+
args: z.ZodArray<z.ZodString>;
|
|
236
|
+
command: z.ZodNullable<z.ZodArray<z.ZodString>>;
|
|
237
|
+
promptVia: z.ZodNullable<z.ZodEnum<{
|
|
238
|
+
stdin: "stdin";
|
|
239
|
+
arg: "arg";
|
|
240
|
+
}>>;
|
|
241
|
+
timeoutMs: z.ZodNumber;
|
|
242
|
+
maxPromptBytes: z.ZodNumber;
|
|
243
|
+
env: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
244
|
+
}, z.core.$strip>;
|
|
245
|
+
codehost: z.ZodObject<{
|
|
246
|
+
provider: z.ZodEnum<{
|
|
247
|
+
gh: "gh";
|
|
248
|
+
none: "none";
|
|
249
|
+
}>;
|
|
250
|
+
}, z.core.$strip>;
|
|
251
|
+
git: z.ZodObject<{
|
|
252
|
+
defaultBranch: z.ZodNullable<z.ZodString>;
|
|
253
|
+
exclude: z.ZodArray<z.ZodString>;
|
|
254
|
+
}, z.core.$strip>;
|
|
255
|
+
render: z.ZodObject<{
|
|
256
|
+
color: z.ZodEnum<{
|
|
257
|
+
never: "never";
|
|
258
|
+
auto: "auto";
|
|
259
|
+
always: "always";
|
|
260
|
+
}>;
|
|
261
|
+
pager: z.ZodEnum<{
|
|
262
|
+
never: "never";
|
|
263
|
+
auto: "auto";
|
|
264
|
+
always: "always";
|
|
265
|
+
}>;
|
|
266
|
+
maxExcerptLines: z.ZodNumber;
|
|
267
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
268
|
+
}, z.core.$strip>;
|
|
269
|
+
cache: z.ZodObject<{
|
|
270
|
+
enabled: z.ZodBoolean;
|
|
271
|
+
dir: z.ZodNullable<z.ZodString>;
|
|
272
|
+
}, z.core.$strip>;
|
|
273
|
+
}, z.core.$strip>;
|
|
274
|
+
type Config = z.infer<typeof ConfigSchema>;
|
|
275
|
+
declare const PartialConfigSchema: z.ZodObject<{
|
|
276
|
+
llm: z.ZodOptional<z.ZodObject<{
|
|
277
|
+
preset: z.ZodOptional<z.ZodString>;
|
|
278
|
+
presets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
279
|
+
command: z.ZodArray<z.ZodString>;
|
|
280
|
+
promptVia: z.ZodOptional<z.ZodEnum<{
|
|
281
|
+
stdin: "stdin";
|
|
282
|
+
arg: "arg";
|
|
283
|
+
}>>;
|
|
284
|
+
description: z.ZodOptional<z.ZodString>;
|
|
285
|
+
}, z.core.$strip>>>;
|
|
286
|
+
args: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
287
|
+
command: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
288
|
+
promptVia: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
289
|
+
stdin: "stdin";
|
|
290
|
+
arg: "arg";
|
|
291
|
+
}>>>;
|
|
292
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
293
|
+
maxPromptBytes: z.ZodOptional<z.ZodNumber>;
|
|
294
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
295
|
+
}, z.core.$strip>>;
|
|
296
|
+
codehost: z.ZodOptional<z.ZodObject<{
|
|
297
|
+
provider: z.ZodOptional<z.ZodEnum<{
|
|
298
|
+
gh: "gh";
|
|
299
|
+
none: "none";
|
|
300
|
+
}>>;
|
|
301
|
+
}, z.core.$strip>>;
|
|
302
|
+
git: z.ZodOptional<z.ZodObject<{
|
|
303
|
+
defaultBranch: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
304
|
+
exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
305
|
+
}, z.core.$strip>>;
|
|
306
|
+
render: z.ZodOptional<z.ZodObject<{
|
|
307
|
+
color: z.ZodOptional<z.ZodEnum<{
|
|
308
|
+
never: "never";
|
|
309
|
+
auto: "auto";
|
|
310
|
+
always: "always";
|
|
311
|
+
}>>;
|
|
312
|
+
pager: z.ZodOptional<z.ZodEnum<{
|
|
313
|
+
never: "never";
|
|
314
|
+
auto: "auto";
|
|
315
|
+
always: "always";
|
|
316
|
+
}>>;
|
|
317
|
+
maxExcerptLines: z.ZodOptional<z.ZodNumber>;
|
|
318
|
+
width: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
319
|
+
}, z.core.$strip>>;
|
|
320
|
+
cache: z.ZodOptional<z.ZodObject<{
|
|
321
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
322
|
+
dir: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
323
|
+
}, z.core.$strip>>;
|
|
324
|
+
}, z.core.$strip>;
|
|
325
|
+
type PartialConfig = z.infer<typeof PartialConfigSchema>;
|
|
326
|
+
declare const DEFAULT_CONFIG: Config;
|
|
327
|
+
declare function userConfigPath(env?: NodeJS.ProcessEnv): string;
|
|
328
|
+
declare function defaultCacheDir(env?: NodeJS.ProcessEnv): string;
|
|
329
|
+
declare function projectConfigPath(gitRoot: string): string;
|
|
330
|
+
type LayerName = 'defaults' | 'user' | 'project' | 'env' | 'flags';
|
|
331
|
+
interface ConfigLayer {
|
|
332
|
+
name: LayerName;
|
|
333
|
+
/** File path for file-backed layers. */
|
|
334
|
+
path?: string;
|
|
335
|
+
/** Whether the layer contributed anything (file existed, env vars set, flags passed). */
|
|
336
|
+
found: boolean;
|
|
337
|
+
/** Short human description of what was applied (e.g. env var names). */
|
|
338
|
+
detail?: string;
|
|
339
|
+
data: PartialConfig;
|
|
340
|
+
}
|
|
341
|
+
interface LoadConfigOptions {
|
|
342
|
+
/** Git root for project-level config; null/undefined skips the project layer. */
|
|
343
|
+
gitRoot?: string | null;
|
|
344
|
+
env?: NodeJS.ProcessEnv;
|
|
345
|
+
/** CLI flag overrides, applied last. */
|
|
346
|
+
overrides?: PartialConfig;
|
|
347
|
+
}
|
|
348
|
+
interface LoadedConfig {
|
|
349
|
+
config: Config;
|
|
350
|
+
layers: ConfigLayer[];
|
|
351
|
+
cacheDir: string;
|
|
352
|
+
}
|
|
353
|
+
/** Objects merge recursively; arrays and scalars replace. `undefined` never overrides. */
|
|
354
|
+
declare function deepMerge<T>(base: T, patch: unknown): T;
|
|
355
|
+
declare function loadConfig(opts?: LoadConfigOptions): Promise<LoadedConfig>;
|
|
356
|
+
interface ResolvedLlm {
|
|
357
|
+
command: string[];
|
|
358
|
+
promptVia: PromptVia;
|
|
359
|
+
/** Preset name, or null when a custom command is in use. */
|
|
360
|
+
preset: string | null;
|
|
361
|
+
timeoutMs: number;
|
|
362
|
+
maxPromptBytes: number;
|
|
363
|
+
env: Record<string, string>;
|
|
364
|
+
}
|
|
365
|
+
declare function allPresets(config: Config): Record<string, LlmPreset>;
|
|
366
|
+
declare function resolveLlm(config: Config): ResolvedLlm;
|
|
367
|
+
/** Minimal POSIX-ish shell splitting: whitespace separated, single/double quotes, backslash escapes. */
|
|
368
|
+
declare function shellSplit(input: string): string[];
|
|
369
|
+
|
|
370
|
+
declare class BbError extends Error {
|
|
371
|
+
readonly exitCode: number;
|
|
372
|
+
readonly hint: string | undefined;
|
|
373
|
+
constructor(message: string, opts?: {
|
|
374
|
+
exitCode?: number;
|
|
375
|
+
hint?: string;
|
|
376
|
+
cause?: unknown;
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
declare class UsageError extends BbError {
|
|
380
|
+
constructor(message: string, hint?: string);
|
|
381
|
+
}
|
|
382
|
+
declare class ConfigError extends BbError {
|
|
383
|
+
constructor(message: string, hint?: string);
|
|
384
|
+
}
|
|
385
|
+
declare class NotARepoError extends BbError {
|
|
386
|
+
constructor(cwd: string);
|
|
387
|
+
}
|
|
388
|
+
declare class GitError extends BbError {
|
|
389
|
+
constructor(message: string, opts?: {
|
|
390
|
+
hint?: string;
|
|
391
|
+
cause?: unknown;
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
declare class NoChangesError extends BbError {
|
|
395
|
+
constructor(message: string, hint?: string);
|
|
396
|
+
}
|
|
397
|
+
declare class LlmFailedError extends BbError {
|
|
398
|
+
constructor(message: string, opts?: {
|
|
399
|
+
hint?: string;
|
|
400
|
+
cause?: unknown;
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
declare class BadLlmOutputError extends BbError {
|
|
404
|
+
readonly raw: string;
|
|
405
|
+
constructor(message: string, raw: string, hint?: string);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
interface CacheEntry {
|
|
409
|
+
key: string;
|
|
410
|
+
path: string;
|
|
411
|
+
tour: Tour;
|
|
412
|
+
}
|
|
413
|
+
/** Content-addressed store of generated tours: <dir>/tours/<sha256>.json */
|
|
414
|
+
declare class TourCache {
|
|
415
|
+
readonly dir: string;
|
|
416
|
+
readonly toursDir: string;
|
|
417
|
+
constructor(dir: string);
|
|
418
|
+
static keyFor(prompt: string, command: string[]): string;
|
|
419
|
+
pathFor(key: string): string;
|
|
420
|
+
get(key: string): Promise<Tour | null>;
|
|
421
|
+
put(key: string, tour: Tour): Promise<string>;
|
|
422
|
+
list(): Promise<CacheEntry[]>;
|
|
423
|
+
clear(): Promise<number>;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Pull a JSON object out of model output that may be wrapped in prose, code
|
|
428
|
+
* fences, or a CLI's own JSON envelope (e.g. `claude --output-format json`).
|
|
429
|
+
*/
|
|
430
|
+
declare function extractJson(text: string): unknown;
|
|
431
|
+
|
|
432
|
+
interface MaterializeInput {
|
|
433
|
+
output: LlmTourOutput;
|
|
434
|
+
diff: ParsedDiff;
|
|
435
|
+
source: TourSource;
|
|
436
|
+
generator: TourGenerator;
|
|
437
|
+
pullRequest?: PullRequestInfo;
|
|
438
|
+
maxExcerptLines: number;
|
|
439
|
+
warn?: (msg: string) => void;
|
|
440
|
+
now?: () => Date;
|
|
441
|
+
}
|
|
442
|
+
declare const OTHER_CHANGES_TITLE = "Other changes";
|
|
443
|
+
/**
|
|
444
|
+
* Turn the model's section/reference output into a self-contained Tour by
|
|
445
|
+
* slicing excerpts out of the real diff and computing all counts locally.
|
|
446
|
+
*/
|
|
447
|
+
declare function materializeTour(input: MaterializeInput): Tour;
|
|
448
|
+
/**
|
|
449
|
+
* Narrow a hunk to a [start, end] range of new-file line numbers. Deleted lines
|
|
450
|
+
* are attributed to the new-file position where they would have been, so a
|
|
451
|
+
* range keeps the removals that sit inside it.
|
|
452
|
+
*/
|
|
453
|
+
declare function sliceHunk(hunk: Hunk, range: [number, number] | undefined, maxLines: number): HunkLine[];
|
|
454
|
+
|
|
455
|
+
interface PromptInput {
|
|
456
|
+
source: TourSource;
|
|
457
|
+
branch: string | null;
|
|
458
|
+
diff: ParsedDiff;
|
|
459
|
+
commits: CommitInfo[];
|
|
460
|
+
pullRequest?: PullRequestInfo;
|
|
461
|
+
/** Soft budget for the whole prompt, in bytes. */
|
|
462
|
+
maxBytes: number;
|
|
463
|
+
}
|
|
464
|
+
interface TruncationReport {
|
|
465
|
+
/** Files whose diff was cut down to the start of their first hunk. */
|
|
466
|
+
truncated: string[];
|
|
467
|
+
/** Files whose diff was left out entirely (names and stats only). */
|
|
468
|
+
omitted: string[];
|
|
469
|
+
}
|
|
470
|
+
interface BuiltPrompt {
|
|
471
|
+
prompt: string;
|
|
472
|
+
truncation: TruncationReport;
|
|
473
|
+
}
|
|
474
|
+
declare function buildPrompt(input: PromptInput): BuiltPrompt;
|
|
475
|
+
declare function describeSource(source: TourSource, branch: string | null): string;
|
|
476
|
+
|
|
477
|
+
/** Bump whenever the prompt text or its assembly changes materially; it is part of the cache key. */
|
|
478
|
+
declare const PROMPT_VERSION = 2;
|
|
479
|
+
|
|
480
|
+
interface CodeHost {
|
|
481
|
+
readonly name: string;
|
|
482
|
+
/** The pull request for the current branch, or null when there is none (or the host is unavailable). */
|
|
483
|
+
currentPullRequest(cwd: string): Promise<PullRequestInfo | null>;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
interface GhOptions {
|
|
487
|
+
timeoutMs?: number;
|
|
488
|
+
debug?: (msg: string) => void;
|
|
489
|
+
}
|
|
490
|
+
/** Reads the current branch's PR through the `gh` CLI. Never throws: any failure means "no PR". */
|
|
491
|
+
declare class GhCodeHost implements CodeHost {
|
|
492
|
+
readonly name = "gh";
|
|
493
|
+
private readonly timeoutMs;
|
|
494
|
+
private readonly debug;
|
|
495
|
+
constructor(opts?: GhOptions);
|
|
496
|
+
currentPullRequest(cwd: string): Promise<PullRequestInfo | null>;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
declare class NoCodeHost implements CodeHost {
|
|
500
|
+
readonly name = "none";
|
|
501
|
+
currentPullRequest(): Promise<null>;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
declare function createCodeHost(config: Config, opts?: {
|
|
505
|
+
debug?: (msg: string) => void;
|
|
506
|
+
}): CodeHost;
|
|
507
|
+
|
|
508
|
+
interface RangeRequest {
|
|
509
|
+
/** Explicit range argument: "A..B", "A...B" or a single ref. */
|
|
510
|
+
arg?: string;
|
|
511
|
+
working?: boolean;
|
|
512
|
+
staged?: boolean;
|
|
513
|
+
}
|
|
514
|
+
interface ResolveOptions {
|
|
515
|
+
cwd: string;
|
|
516
|
+
exclude: string[];
|
|
517
|
+
/** Configured default branch; null means auto-detect. */
|
|
518
|
+
defaultBranch: string | null;
|
|
519
|
+
codehost: CodeHost;
|
|
520
|
+
debug?: (msg: string) => void;
|
|
521
|
+
}
|
|
522
|
+
interface ResolvedRange {
|
|
523
|
+
source: TourSource;
|
|
524
|
+
branch: string | null;
|
|
525
|
+
pullRequest?: PullRequestInfo;
|
|
526
|
+
}
|
|
527
|
+
declare function resolveRange(req: RangeRequest, opts: ResolveOptions): Promise<ResolvedRange>;
|
|
528
|
+
declare function detectDefaultBranch(configured: string | null, cwd: string): Promise<string | null>;
|
|
529
|
+
|
|
530
|
+
interface LlmProvider {
|
|
531
|
+
/** Human-readable description of how the model is invoked, for headers and debug output. */
|
|
532
|
+
describe(): string;
|
|
533
|
+
/** Send a prompt and return the raw text the model produced. */
|
|
534
|
+
complete(prompt: string): Promise<string>;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
interface CommandProviderOptions {
|
|
538
|
+
command: string[];
|
|
539
|
+
promptVia: 'stdin' | 'arg';
|
|
540
|
+
timeoutMs: number;
|
|
541
|
+
env?: Record<string, string>;
|
|
542
|
+
cwd?: string;
|
|
543
|
+
debug?: (msg: string) => void;
|
|
544
|
+
}
|
|
545
|
+
/** Runs any CLI as the model: prompt in via stdin (or a {prompt} argv token), completion out via stdout. */
|
|
546
|
+
declare class CommandProvider implements LlmProvider {
|
|
547
|
+
private readonly opts;
|
|
548
|
+
constructor(opts: CommandProviderOptions);
|
|
549
|
+
describe(): string;
|
|
550
|
+
complete(prompt: string): Promise<string>;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
declare function createProvider(llm: ResolvedLlm, opts?: {
|
|
554
|
+
cwd?: string;
|
|
555
|
+
debug?: (msg: string) => void;
|
|
556
|
+
}): LlmProvider;
|
|
557
|
+
|
|
558
|
+
interface TourOptions {
|
|
559
|
+
/** Git root (or any directory inside the repository). */
|
|
560
|
+
cwd: string;
|
|
561
|
+
config: Config;
|
|
562
|
+
cacheDir: string;
|
|
563
|
+
range?: RangeRequest;
|
|
564
|
+
/** Ignore a cached tour but still store the new one. */
|
|
565
|
+
refresh?: boolean;
|
|
566
|
+
/** Neither read nor write the cache. */
|
|
567
|
+
noCache?: boolean;
|
|
568
|
+
debug?: (msg: string) => void;
|
|
569
|
+
warn?: (msg: string) => void;
|
|
570
|
+
/** Injectable for tests. */
|
|
571
|
+
provider?: LlmProvider;
|
|
572
|
+
codehost?: CodeHost;
|
|
573
|
+
}
|
|
574
|
+
interface PreparedTour {
|
|
575
|
+
context: TourContext;
|
|
576
|
+
built: BuiltPrompt;
|
|
577
|
+
command: string[];
|
|
578
|
+
preset: string | null;
|
|
579
|
+
cacheKey: string;
|
|
580
|
+
}
|
|
581
|
+
interface TourResult {
|
|
582
|
+
tour: Tour;
|
|
583
|
+
fromCache: boolean;
|
|
584
|
+
cacheKey: string | null;
|
|
585
|
+
cachePath: string | null;
|
|
586
|
+
prompt: string;
|
|
587
|
+
}
|
|
588
|
+
/** Everything up to (but not including) the model call: git, code host, prompt, cache key. */
|
|
589
|
+
declare function prepareTour(opts: TourOptions): Promise<PreparedTour>;
|
|
590
|
+
declare function generateTour(opts: TourOptions, prepared?: PreparedTour): Promise<TourResult>;
|
|
591
|
+
|
|
592
|
+
interface CollectOptions {
|
|
593
|
+
cwd: string;
|
|
594
|
+
exclude: string[];
|
|
595
|
+
warn?: (msg: string) => void;
|
|
596
|
+
}
|
|
597
|
+
/** Collect and parse the diff for a resolved source. */
|
|
598
|
+
declare function collectDiff(source: TourSource, opts: CollectOptions): Promise<ParsedDiff>;
|
|
599
|
+
declare function collectCommits(source: TourSource, cwd: string, limit?: number): Promise<CommitInfo[]>;
|
|
600
|
+
|
|
601
|
+
declare function gitRoot(cwd: string): Promise<string>;
|
|
602
|
+
/** Resolve a ref to a full commit sha; null when it doesn't resolve. */
|
|
603
|
+
declare function revParse(ref: string, cwd: string): Promise<string | null>;
|
|
604
|
+
/** Current branch name, or null when HEAD is detached. */
|
|
605
|
+
declare function currentBranch(cwd: string): Promise<string | null>;
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Parse `git diff` output (with a/ b/ prefixes) into files, hunks and numbered lines.
|
|
609
|
+
* Tolerant of mode-only changes, pure renames, binary files and "\ No newline" markers.
|
|
610
|
+
*/
|
|
611
|
+
declare function parseDiff(raw: string): ParsedDiff;
|
|
612
|
+
declare function diffStats(diff: ParsedDiff): {
|
|
613
|
+
files: number;
|
|
614
|
+
additions: number;
|
|
615
|
+
deletions: number;
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
interface RenderOptions {
|
|
619
|
+
/** Emit ANSI colors. */
|
|
620
|
+
color: boolean;
|
|
621
|
+
/** Target width in columns. */
|
|
622
|
+
width: number;
|
|
623
|
+
/** Render only this 1-based section (header still included). */
|
|
624
|
+
section?: number;
|
|
625
|
+
/** Whether the tour came from the cache, for the header note. */
|
|
626
|
+
fromCache?: boolean;
|
|
627
|
+
}
|
|
628
|
+
interface Renderer {
|
|
629
|
+
render(tour: Tour, opts: RenderOptions): string;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/** Static, pager-friendly rendering of a Tour for a terminal. */
|
|
633
|
+
declare class CliRenderer implements Renderer {
|
|
634
|
+
render(tour: Tour, opts: RenderOptions): string;
|
|
635
|
+
}
|
|
636
|
+
declare function wrap(text: string, width: number): string[];
|
|
637
|
+
declare function relativeTime(iso: string, now?: Date): string;
|
|
638
|
+
|
|
639
|
+
interface PagerOptions {
|
|
640
|
+
mode: 'auto' | 'always' | 'never';
|
|
641
|
+
isTTY: boolean;
|
|
642
|
+
rows: number;
|
|
643
|
+
env?: NodeJS.ProcessEnv;
|
|
644
|
+
}
|
|
645
|
+
/** Write output to stdout, through $PAGER (default `less -RFX`) when it would not fit the screen. */
|
|
646
|
+
declare function writeMaybePaged(output: string, opts: PagerOptions): Promise<void>;
|
|
647
|
+
|
|
648
|
+
export { BUILTIN_PRESETS, BadLlmOutputError, BbError, type BuiltPrompt, type CacheEntry, CliRenderer, type CodeHost, CommandProvider, type CommitInfo, type Config, ConfigError, type ConfigLayer, ConfigSchema, DEFAULT_CONFIG, type DiffFile, type Excerpt, type FileStatus, GhCodeHost, GitError, type Hunk, type HunkLine, type LineType, LlmFailedError, type LlmPreset, type LlmProvider, type LlmTourOutput, LlmTourOutputSchema, type LoadedConfig, NoChangesError, NoCodeHost, NotARepoError, OTHER_CHANGES_TITLE, PROMPT_VERSION, type ParsedDiff, type PartialConfig, PartialConfigSchema, type PreparedTour, type PromptInput, type PullRequestInfo, type RangeRequest, type RangeResolvedBy, type RenderOptions, type Renderer, type ResolveOptions, type ResolvedLlm, type ResolvedRange, type Section, type Tour, TourCache, type TourContext, type TourGenerator, type TourOptions, type TourResult, TourSchema, type TourSource, type TourStats, type TruncationReport, UsageError, type WorkingResolvedBy, allPresets, buildPrompt, collectCommits, collectDiff, createCodeHost, createProvider, currentBranch, deepMerge, defaultCacheDir, describeSource, detectDefaultBranch, diffStats, extractJson, formatIssues, generateTour, gitRoot, loadConfig, materializeTour, parseDiff, prepareTour, projectConfigPath, relativeTime, resolveLlm, resolveRange, revParse, shellSplit, sliceHunk, userConfigPath, wrap, writeMaybePaged };
|