@gaunt-sloth/review 2.0.0-alpha.36 → 2.0.0-alpha.38
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 +8 -3
- package/dist/modules/reviewHeading.d.ts +30 -0
- package/dist/modules/reviewHeading.js +77 -0
- package/dist/modules/reviewHeading.js.map +1 -0
- package/dist/modules/reviewModule.js +27 -2
- package/dist/modules/reviewModule.js.map +1 -1
- package/dist/tools/ghReadFileTool.d.ts +11 -2
- package/dist/tools/ghReadFileTool.js +40 -6
- package/dist/tools/ghReadFileTool.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -67,9 +67,14 @@ await review('embedded-review', preamble, diff, config);
|
|
|
67
67
|
process.exit(process.exitCode ?? 0);
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
The review text is written to stdout
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
The review text is written to stdout, opening with a fixed `## Gaunt Sloth: Code Review` heading and
|
|
71
|
+
one line naming the review mode and the model that served the run. An embedder gets that attribution
|
|
72
|
+
by default, so anything posting this output identifies its reviewer without adding a header of its
|
|
73
|
+
own; `output.header: "none"` on the config you pass to `review()` is the one setting that removes
|
|
74
|
+
it, for a caller piping the review into a template of their own. With rating enabled, `review()`
|
|
75
|
+
sets `process.exitCode = 1` when the rating comes back below `passThreshold` (or when the model
|
|
76
|
+
fails to produce a rating), so the script exits non-zero exactly when `gth review` would. Those
|
|
77
|
+
two — the attributed text on stdout and the exit code — are the whole embed contract.
|
|
73
78
|
Configuration (provider, prompts, rating thresholds) is the standard Gaunt Sloth config, see
|
|
74
79
|
[the configuration guide](https://github.com/pukeko-robotics/gaunt-sloth/blob/main/docs/configuration/index.md).
|
|
75
80
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The heading, verbatim. Markdown `##` because the primary surfaces — a PR comment and the
|
|
3
|
+
* `writeOutputToFile` report — are markdown; the terminal shows it literally, exactly as it already
|
|
4
|
+
* shows every markdown heading a model writes.
|
|
5
|
+
*/
|
|
6
|
+
export declare const REVIEW_HEADING = "## Gaunt Sloth: Code Review";
|
|
7
|
+
/**
|
|
8
|
+
* The review mode, as the attribution line names it. `review` / `pr` are one-shot: the diff goes in,
|
|
9
|
+
* the verdict comes out, and nothing carries over between runs — which is what makes a verdict
|
|
10
|
+
* impossible to argue down across a conversation, and why the mode is worth naming.
|
|
11
|
+
*/
|
|
12
|
+
export declare const REVIEW_MODE_LABEL = "stateless review";
|
|
13
|
+
/**
|
|
14
|
+
* Build the heading block: the heading, a blank line, the attribution line, and a trailing newline
|
|
15
|
+
* so the review body does not start flush against it.
|
|
16
|
+
*
|
|
17
|
+
* The model half is the SHARED `model (provider)` spelling ({@link modelProviderLabel}), the same
|
|
18
|
+
* one the launch banner renders, rather than a second spelling of the same fact.
|
|
19
|
+
*
|
|
20
|
+
* Both halves of the model are allowed to be missing, and neither prints a placeholder:
|
|
21
|
+
*
|
|
22
|
+
* - **No provider** — a `.gsloth.config.js` module config hands the loader an already-built
|
|
23
|
+
* `BaseChatModel` and legitimately has no provider string. The bare model prints; there is no
|
|
24
|
+
* `(unknown)` and no empty `()`.
|
|
25
|
+
* - **No model** — the label is dropped entirely and the line is just the mode. A provider name on
|
|
26
|
+
* its own would sit exactly where a model name sits and read as one, and a misidentified model in
|
|
27
|
+
* a review someone later quotes is worse than an absent one. That is the same drop-rather-than-
|
|
28
|
+
* mislead rule the banner applies to a version that does not fit.
|
|
29
|
+
*/
|
|
30
|
+
export declare function reviewHeadingBlock(model?: string, provider?: string): string;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module reviewHeading
|
|
3
|
+
* REL-12 — the two lines every `gth review` / `gth pr` run opens with, so a reader of the output
|
|
4
|
+
* knows whose review it is.
|
|
5
|
+
*
|
|
6
|
+
* User-facing CLI feedback, so it is governed by `maintenance/ux-guidelines.md` § Review
|
|
7
|
+
* attribution, and it serves three of the Design Language principles: **DL-4** (transparency — a
|
|
8
|
+
* reader of the output knows what produced it), **DL-6** (cross-surface consistency — the model half
|
|
9
|
+
* reuses the launch banner's one `model (provider)` spelling rather than a second one), and **DL-7**
|
|
10
|
+
* (graceful degradation — drop the label rather than mislead, exactly as the banner drops a version
|
|
11
|
+
* that will not fit).
|
|
12
|
+
*
|
|
13
|
+
* ## Why the product emits this and not the workflow
|
|
14
|
+
*
|
|
15
|
+
* The review is usually read somewhere the command is not visible: a PR comment posted by a bot
|
|
16
|
+
* account, a `review.md` attached to a ticket, a CI log. Stripped of the invocation, an unlabelled
|
|
17
|
+
* AI review on a pull request is simply assumed to be whichever AI reviewer the reader already
|
|
18
|
+
* knows. Putting the attribution in the CLI's own output means any workflow that runs `gth` and
|
|
19
|
+
* posts what it produced carries it, with no wiring of its own.
|
|
20
|
+
*
|
|
21
|
+
* ## Why the heading is a constant and the mode is not in it
|
|
22
|
+
*
|
|
23
|
+
* {@link REVIEW_HEADING} is the same string on every run, because its one job is to be recognisable
|
|
24
|
+
* to someone who has never heard of this tool. The MODE lives on the attribution line below it
|
|
25
|
+
* instead: a heading that named the mode would have to change when a second review mode landed,
|
|
26
|
+
* turning the constant into a branch, and the reader gains nothing from a distinction they cannot
|
|
27
|
+
* make. The attribution line is dynamic anyway — it renders the live model.
|
|
28
|
+
*
|
|
29
|
+
* ## Why it is two lines and no more, and when it is none
|
|
30
|
+
*
|
|
31
|
+
* A review is read for its findings. Everything above the first finding pushes that finding down,
|
|
32
|
+
* so the block is a heading plus one line: no rule, no box, no timestamp, no version, no restated
|
|
33
|
+
* repo/branch/PR. The cost of a bigger banner is paid by every reader of every review.
|
|
34
|
+
*
|
|
35
|
+
* It is not, however, unconditional. `output.header: none` drops it (the gate is at the emission
|
|
36
|
+
* site in `reviewModule.ts`, not here — this module builds the block and does not decide whether it
|
|
37
|
+
* is shown), because a caller piping a review into their own template needs a byte-clean stream.
|
|
38
|
+
* That rung is opt-in precisely so the reasoning above survives for everyone who does not set it.
|
|
39
|
+
*/
|
|
40
|
+
import { modelProviderLabel } from '@gaunt-sloth/core/core/launchBanner.js';
|
|
41
|
+
/**
|
|
42
|
+
* The heading, verbatim. Markdown `##` because the primary surfaces — a PR comment and the
|
|
43
|
+
* `writeOutputToFile` report — are markdown; the terminal shows it literally, exactly as it already
|
|
44
|
+
* shows every markdown heading a model writes.
|
|
45
|
+
*/
|
|
46
|
+
export const REVIEW_HEADING = '## Gaunt Sloth: Code Review';
|
|
47
|
+
/**
|
|
48
|
+
* The review mode, as the attribution line names it. `review` / `pr` are one-shot: the diff goes in,
|
|
49
|
+
* the verdict comes out, and nothing carries over between runs — which is what makes a verdict
|
|
50
|
+
* impossible to argue down across a conversation, and why the mode is worth naming.
|
|
51
|
+
*/
|
|
52
|
+
export const REVIEW_MODE_LABEL = 'stateless review';
|
|
53
|
+
/** Separates the mode from the model on the attribution line. */
|
|
54
|
+
const ATTRIBUTION_SEPARATOR = ' · ';
|
|
55
|
+
/**
|
|
56
|
+
* Build the heading block: the heading, a blank line, the attribution line, and a trailing newline
|
|
57
|
+
* so the review body does not start flush against it.
|
|
58
|
+
*
|
|
59
|
+
* The model half is the SHARED `model (provider)` spelling ({@link modelProviderLabel}), the same
|
|
60
|
+
* one the launch banner renders, rather than a second spelling of the same fact.
|
|
61
|
+
*
|
|
62
|
+
* Both halves of the model are allowed to be missing, and neither prints a placeholder:
|
|
63
|
+
*
|
|
64
|
+
* - **No provider** — a `.gsloth.config.js` module config hands the loader an already-built
|
|
65
|
+
* `BaseChatModel` and legitimately has no provider string. The bare model prints; there is no
|
|
66
|
+
* `(unknown)` and no empty `()`.
|
|
67
|
+
* - **No model** — the label is dropped entirely and the line is just the mode. A provider name on
|
|
68
|
+
* its own would sit exactly where a model name sits and read as one, and a misidentified model in
|
|
69
|
+
* a review someone later quotes is worse than an absent one. That is the same drop-rather-than-
|
|
70
|
+
* mislead rule the banner applies to a version that does not fit.
|
|
71
|
+
*/
|
|
72
|
+
export function reviewHeadingBlock(model, provider) {
|
|
73
|
+
const label = model?.trim() ? modelProviderLabel(model, provider) : undefined;
|
|
74
|
+
const attribution = label ? REVIEW_MODE_LABEL + ATTRIBUTION_SEPARATOR + label : REVIEW_MODE_LABEL;
|
|
75
|
+
return `${REVIEW_HEADING}\n\n${attribution}\n`;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=reviewHeading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewHeading.js","sourceRoot":"","sources":["../../src/modules/reviewHeading.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAE5E;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,6BAA6B,CAAC;AAE5D;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAEpD,iEAAiE;AACjE,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAEpC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc,EAAE,QAAiB;IAClE,MAAM,KAAK,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,iBAAiB,GAAG,qBAAqB,GAAG,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC;IAClG,OAAO,GAAG,cAAc,OAAO,WAAW,IAAI,CAAC;AACjD,CAAC"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isGhReadFileToolEnabled } from '@gaunt-sloth/core/config.js';
|
|
2
|
+
import { defaultStatusCallback, display, displayDebug, displayError, displayInfo, displaySuccess, displayWarning, flushSessionLog, initSessionLogging, stopSessionLogging, } from '@gaunt-sloth/core/utils/consoleUtils.js';
|
|
3
|
+
import { reviewHeadingBlock } from '#src/modules/reviewHeading.js';
|
|
2
4
|
import { getCommandOutputFilePath } from '#src/utils/fileUtils.js';
|
|
3
5
|
import { HumanMessage } from '@langchain/core/messages';
|
|
4
6
|
import { GthAgentRunner } from '@gaunt-sloth/core/core/GthAgentRunner.js';
|
|
@@ -50,6 +52,23 @@ _preamble, diff, config, command = 'review', resolvers, reviewContext) {
|
|
|
50
52
|
if (filePath) {
|
|
51
53
|
initSessionLogging(filePath, config.streamSessionInferenceLog);
|
|
52
54
|
}
|
|
55
|
+
// REL-12: head the review with its attribution. It sits AFTER `initSessionLogging` on purpose —
|
|
56
|
+
// the session log is a capture of console output, so this ordering is the whole reason one
|
|
57
|
+
// emission covers both surfaces: the terminal AND the `writeOutputToFile` report a workflow
|
|
58
|
+
// reads back and posts. Emitted BEFORE the agent runs so it is the first thing in both.
|
|
59
|
+
//
|
|
60
|
+
// Through the ordinary `display` helper, never `headerStatus`: this is not the agent's
|
|
61
|
+
// technical preamble but the first line of the review document, so it survives the `compact`
|
|
62
|
+
// rung that strips the preamble — and on that rung it IS the attribution, which is why the
|
|
63
|
+
// agent emits no `Gaunt Sloth: <verb>` line for `review`/`pr`.
|
|
64
|
+
//
|
|
65
|
+
// GS2-93: `none` is the one rung that reaches it, and it silences the block outright. That
|
|
66
|
+
// deliberately reverses REL-12 for a user who asks for it: a caller piping a review into their
|
|
67
|
+
// own template or diffing captured stdout needs a byte-clean stream, and nobody loses
|
|
68
|
+
// attribution without setting this key.
|
|
69
|
+
if (config.output?.header !== 'none') {
|
|
70
|
+
display(reviewHeadingBlock(config.modelDisplayName, config.modelProviderType));
|
|
71
|
+
}
|
|
53
72
|
const rateConfig = config.commands?.[command]?.rating;
|
|
54
73
|
if (rateConfig && rateConfig.enabled !== false) {
|
|
55
74
|
const confMiddleware = config.middleware || [];
|
|
@@ -137,6 +156,9 @@ _preamble, diff, config, command = 'review', resolvers, reviewContext) {
|
|
|
137
156
|
*
|
|
138
157
|
* The tool reads file contents via the GitHub API (`gh api`), never the workspace filesystem, so
|
|
139
158
|
* it remains safe under `pull_request_target` CI where the untrusted PR head is not checked out.
|
|
159
|
+
*
|
|
160
|
+
* CFG-52 — it is also gated on the unified `builtInTools` registry, resolved per-command first and
|
|
161
|
+
* then root by {@link isGhReadFileToolEnabled}. Absence means enabled, so this stays opt-OUT.
|
|
140
162
|
*/
|
|
141
163
|
function maybeAddGhReadFileTool(config, command, prId) {
|
|
142
164
|
const commandConfig = config.commands?.[command];
|
|
@@ -144,6 +166,9 @@ function maybeAddGhReadFileTool(config, command, prId) {
|
|
|
144
166
|
if (contentSource !== 'github') {
|
|
145
167
|
return;
|
|
146
168
|
}
|
|
169
|
+
if (!isGhReadFileToolEnabled(config, command)) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
147
172
|
// config.tools is a union (StructuredToolInterface[] | BaseToolkit[] | ServerTool[]); the
|
|
148
173
|
// gh read-file tool is a StructuredToolInterface, so we only append into a structured-tool list.
|
|
149
174
|
const existingTools = (Array.isArray(config.tools) ? config.tools : []);
|
|
@@ -152,7 +177,7 @@ function maybeAddGhReadFileTool(config, command, prId) {
|
|
|
152
177
|
if (alreadyPresent) {
|
|
153
178
|
return;
|
|
154
179
|
}
|
|
155
|
-
config.tools = [...existingTools, getGhReadFileTool(config, prId)];
|
|
180
|
+
config.tools = [...existingTools, getGhReadFileTool(config, prId, command)];
|
|
156
181
|
}
|
|
157
182
|
function handleRatingResult(rateConfig, command) {
|
|
158
183
|
if (!rateConfig || rateConfig.enabled === false) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewModule.js","sourceRoot":"","sources":["../../src/modules/reviewModule.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reviewModule.js","sourceRoot":"","sources":["../../src/modules/reviewModule.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
3
3
|
import type { GthConfig } from '@gaunt-sloth/core/config.js';
|
|
4
|
+
import { type GhReadFileCommand } from '@gaunt-sloth/core/config.js';
|
|
4
5
|
declare const toolSchema: z.ZodObject<{
|
|
5
6
|
path: z.ZodString;
|
|
6
7
|
}, z.core.$strip>;
|
|
@@ -22,15 +23,23 @@ export declare function resolvePrRepoContext(prId: string | undefined): Promise<
|
|
|
22
23
|
* Fetches the full contents of a single file from GitHub via the `gh api` CLI and decodes it.
|
|
23
24
|
* Returns the decoded text, or a human/agent-readable explanation string on any failure
|
|
24
25
|
* (graceful skip — never throws). owner/repo/ref come from the resolved PR context, not the LLM.
|
|
26
|
+
*
|
|
27
|
+
* CFG-52 — the decoded text is capped at `maxBytes`. Over the cap it is truncated rather than
|
|
28
|
+
* refused (a truncated file still reviews better than no file), and the result says so in its
|
|
29
|
+
* heading AND in a trailing marker naming the tool and the cap, so the model cannot silently
|
|
30
|
+
* reason about a file it only half received.
|
|
25
31
|
*/
|
|
26
|
-
export declare function ghReadFileImpl(args: GhReadFileArgs, context: PrRepoContext): Promise<string>;
|
|
32
|
+
export declare function ghReadFileImpl(args: GhReadFileArgs, context: PrRepoContext, maxBytes?: number): Promise<string>;
|
|
27
33
|
/**
|
|
28
34
|
* Built-in tool factory matching the repo's `get(config)` tool idiom (see gthWebFetchTool).
|
|
29
35
|
*
|
|
30
36
|
* `prId` identifies the PR under review (undefined in `gth pr` discovery mode → current branch).
|
|
31
37
|
* The owner/repo/ref are resolved from it once, lazily, and memoised for the run, so the agent
|
|
32
38
|
* cannot read files from any repo other than the one being reviewed.
|
|
39
|
+
*
|
|
40
|
+
* CFG-52 — `command` selects which `builtInTools` registry the byte cap is read from, so
|
|
41
|
+
* `commands.pr` and `commands.review` each configure their own run.
|
|
33
42
|
*/
|
|
34
|
-
export declare function get(
|
|
43
|
+
export declare function get(config: GthConfig, prId?: string, command?: GhReadFileCommand): StructuredToolInterface;
|
|
35
44
|
export declare const GTH_GH_READ_FILE_TOOL_NAME = "gth_gh_read_file";
|
|
36
45
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { tool } from '@langchain/core/tools';
|
|
3
|
+
import { GH_READ_FILE_DEFAULT_MAX_BYTES, GH_READ_FILE_TOOL_NAME, getGhReadFileMaxBytes, } from '@gaunt-sloth/core/config.js';
|
|
3
4
|
import { execAsync } from '@gaunt-sloth/core/utils/systemUtils.js';
|
|
4
5
|
import { debugLog } from '@gaunt-sloth/core/utils/debugUtils.js';
|
|
5
6
|
/**
|
|
@@ -21,6 +22,10 @@ import { debugLog } from '@gaunt-sloth/core/utils/debugUtils.js';
|
|
|
21
22
|
* into the review. Binding them to the PR context also closes the footgun of reading arbitrary
|
|
22
23
|
* files from any public repo the model can name.
|
|
23
24
|
*
|
|
25
|
+
* It is configured through the unified `builtInTools` registry (CFG-52) and is **opt-out**: absent
|
|
26
|
+
* from the registry it is ON, `{ "gth_gh_read_file": false }` turns it off, and
|
|
27
|
+
* `{ "gth_gh_read_file": { "maxBytes": N } }` sets the ceiling on the decoded text it returns.
|
|
28
|
+
*
|
|
24
29
|
* The tool is OPTIONAL and self-guarding:
|
|
25
30
|
* - The path is strictly validated so nothing LLM-supplied can inject shell metacharacters
|
|
26
31
|
* into the `gh api` invocation; the resolved owner/repo/ref are validated too.
|
|
@@ -28,7 +33,7 @@ import { debugLog } from '@gaunt-sloth/core/utils/debugUtils.js';
|
|
|
28
33
|
* gracefully and returns an explanatory string instead of throwing, so the agent can simply
|
|
29
34
|
* continue with the (truncated) diff it already has.
|
|
30
35
|
*/
|
|
31
|
-
const TOOL_NAME =
|
|
36
|
+
const TOOL_NAME = GH_READ_FILE_TOOL_NAME;
|
|
32
37
|
// PR ids reach us from the CLI; keep strict so nothing but a number can reach execAsync.
|
|
33
38
|
const PR_ID_PATTERN = /^\d+$/;
|
|
34
39
|
// owner/repo segments: GitHub login/repo naming, conservative allow-list (no shell metachars).
|
|
@@ -39,6 +44,19 @@ const REF_PATTERN = /^[A-Za-z0-9-_./]+$/;
|
|
|
39
44
|
// Repo-relative path. Allow slashes and common filename characters, but no shell metachars,
|
|
40
45
|
// no whitespace, and no parent-directory traversal.
|
|
41
46
|
const PATH_PATTERN = /^[A-Za-z0-9-_./]+$/;
|
|
47
|
+
/**
|
|
48
|
+
* CFG-52 — cut `text` down to at most `maxBytes` UTF-8 bytes without leaving a split multi-byte
|
|
49
|
+
* character at the end. Slicing a Buffer at an arbitrary byte boundary can land mid-sequence, and
|
|
50
|
+
* decoding that produces a replacement character that is itself WIDER than the bytes it replaced —
|
|
51
|
+
* so the result is re-measured and trimmed until it genuinely fits the cap.
|
|
52
|
+
*/
|
|
53
|
+
function truncateToBytes(text, maxBytes) {
|
|
54
|
+
let out = Buffer.from(text, 'utf8').subarray(0, maxBytes).toString('utf8');
|
|
55
|
+
while (out.length > 0 && Buffer.byteLength(out, 'utf8') > maxBytes) {
|
|
56
|
+
out = out.slice(0, -1);
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
42
60
|
const toolSchema = z.object({
|
|
43
61
|
path: z
|
|
44
62
|
.string()
|
|
@@ -88,8 +106,13 @@ export async function resolvePrRepoContext(prId) {
|
|
|
88
106
|
* Fetches the full contents of a single file from GitHub via the `gh api` CLI and decodes it.
|
|
89
107
|
* Returns the decoded text, or a human/agent-readable explanation string on any failure
|
|
90
108
|
* (graceful skip — never throws). owner/repo/ref come from the resolved PR context, not the LLM.
|
|
109
|
+
*
|
|
110
|
+
* CFG-52 — the decoded text is capped at `maxBytes`. Over the cap it is truncated rather than
|
|
111
|
+
* refused (a truncated file still reviews better than no file), and the result says so in its
|
|
112
|
+
* heading AND in a trailing marker naming the tool and the cap, so the model cannot silently
|
|
113
|
+
* reason about a file it only half received.
|
|
91
114
|
*/
|
|
92
|
-
export async function ghReadFileImpl(args, context) {
|
|
115
|
+
export async function ghReadFileImpl(args, context, maxBytes = GH_READ_FILE_DEFAULT_MAX_BYTES) {
|
|
93
116
|
const { path } = args;
|
|
94
117
|
const { owner, repo, ref } = context;
|
|
95
118
|
if (!PATH_PATTERN.test(path) || path.includes('..')) {
|
|
@@ -133,7 +156,12 @@ export async function ghReadFileImpl(args, context) {
|
|
|
133
156
|
}
|
|
134
157
|
const decoded = Buffer.from(parsed.content, 'base64').toString('utf8');
|
|
135
158
|
const label = `${owner}/${repo}/${path}${ref ? `@${ref}` : ''}`;
|
|
136
|
-
|
|
159
|
+
if (Buffer.byteLength(decoded, 'utf8') <= maxBytes) {
|
|
160
|
+
return `Full contents of ${label}:\n\n${decoded}`;
|
|
161
|
+
}
|
|
162
|
+
return (`Partial contents of ${label} (truncated):\n\n${truncateToBytes(decoded, maxBytes)}` +
|
|
163
|
+
`\n... [${TOOL_NAME}: file truncated at the ${maxBytes}-byte cap ` +
|
|
164
|
+
`(builtInTools.${TOOL_NAME}.maxBytes) — this file is INCOMPLETE, the rest was not returned] ...`);
|
|
137
165
|
}
|
|
138
166
|
catch (error) {
|
|
139
167
|
// Graceful skip: gh missing/unauthenticated, file not found, or no GitHub context.
|
|
@@ -149,8 +177,12 @@ export async function ghReadFileImpl(args, context) {
|
|
|
149
177
|
* `prId` identifies the PR under review (undefined in `gth pr` discovery mode → current branch).
|
|
150
178
|
* The owner/repo/ref are resolved from it once, lazily, and memoised for the run, so the agent
|
|
151
179
|
* cannot read files from any repo other than the one being reviewed.
|
|
180
|
+
*
|
|
181
|
+
* CFG-52 — `command` selects which `builtInTools` registry the byte cap is read from, so
|
|
182
|
+
* `commands.pr` and `commands.review` each configure their own run.
|
|
152
183
|
*/
|
|
153
|
-
export function get(
|
|
184
|
+
export function get(config, prId, command = 'pr') {
|
|
185
|
+
const maxBytes = getGhReadFileMaxBytes(config, command);
|
|
154
186
|
let contextPromise;
|
|
155
187
|
const getContext = () => {
|
|
156
188
|
if (!contextPromise) {
|
|
@@ -163,14 +195,16 @@ export function get(_, prId) {
|
|
|
163
195
|
if (typeof context === 'string') {
|
|
164
196
|
return context; // resolution failed — return the explanation as a graceful skip.
|
|
165
197
|
}
|
|
166
|
-
return ghReadFileImpl(args, context);
|
|
198
|
+
return ghReadFileImpl(args, context, maxBytes);
|
|
167
199
|
}, {
|
|
168
200
|
name: TOOL_NAME,
|
|
169
201
|
description: 'Read the FULL contents of a single file from the pull request under review via the ' +
|
|
170
202
|
'GitHub API. Use this when the PR diff is truncated and you need to see the complete ' +
|
|
171
203
|
'file. Supply only the repository-relative path; the repository and ref are bound to ' +
|
|
172
204
|
'the PR automatically. Reads through the GitHub API, not the local filesystem, so it is ' +
|
|
173
|
-
|
|
205
|
+
`safe in pull_request_target CI. At most ${maxBytes} bytes of file text are returned: a ` +
|
|
206
|
+
'larger file may come back truncated, and says so in its heading and in a trailing marker ' +
|
|
207
|
+
'when it does. A very large file may not be readable through this endpoint at all.',
|
|
174
208
|
schema: toolSchema,
|
|
175
209
|
});
|
|
176
210
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ghReadFileTool.js","sourceRoot":"","sources":["../../src/tools/ghReadFileTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAG7C,OAAO,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AAEjE
|
|
1
|
+
{"version":3,"file":"ghReadFileTool.js","sourceRoot":"","sources":["../../src/tools/ghReadFileTool.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaunt-sloth/review",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.38",
|
|
4
4
|
"description": "Review functionality for Gaunt Sloth",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Andrew Kondratev",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@langchain/langgraph": "^1.4.9",
|
|
39
39
|
"langchain": "^1.5.5",
|
|
40
40
|
"zod": "^4.4.3",
|
|
41
|
-
"@gaunt-sloth/core": "2.0.0-alpha.
|
|
41
|
+
"@gaunt-sloth/core": "2.0.0-alpha.38"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
44
44
|
"./dist/*",
|