@gaunt-sloth/review 0.1.8 → 2.0.0-alpha.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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from '@gaunt-sloth/core/config.js';
2
2
  export * from '#src/modules/reviewModule.js';
3
- export * from '#src/modules/questionAnsweringModule.js';
4
3
  export * from '#src/commands/commandUtils.js';
4
+ export * from '#src/tools/ghReadFileTool.js';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from '@gaunt-sloth/core/config.js';
2
2
  export * from '#src/modules/reviewModule.js';
3
- export * from '#src/modules/questionAnsweringModule.js';
4
3
  export * from '#src/commands/commandUtils.js';
4
+ export * from '#src/tools/ghReadFileTool.js';
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yCAAyC,CAAC;AACxD,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC"}
@@ -1,3 +1,8 @@
1
1
  import type { GthConfig } from '@gaunt-sloth/core/config.js';
2
2
  import type { AgentResolvers } from '@gaunt-sloth/core/core/types.js';
3
- export declare function review(source: string, preamble: string, diff: string, config: GthConfig, command?: 'pr' | 'review', resolvers?: AgentResolvers): Promise<void>;
3
+ /** Extra context about the review, used to bind GitHub-only tools to the PR under review. */
4
+ export interface ReviewContext {
5
+ /** PR number under review; undefined in `gth pr` discovery mode (current branch's PR). */
6
+ prId?: string;
7
+ }
8
+ export declare function review(source: string, preamble: string, diff: string, config: GthConfig, command?: 'pr' | 'review', resolvers?: AgentResolvers, reviewContext?: ReviewContext): Promise<void>;
@@ -7,9 +7,15 @@ import { ProgressIndicator } from '@gaunt-sloth/core/utils/ProgressIndicator.js'
7
7
  import { createReviewRateMiddleware, REVIEW_RATE_ARTIFACT_KEY, } from '#src/middleware/reviewRateMiddleware.js';
8
8
  import { deleteArtifact, getArtifact } from '@gaunt-sloth/core/state/artifactStore.js';
9
9
  import { setExitCode } from '@gaunt-sloth/core/utils/systemUtils.js';
10
- export async function review(source, preamble, diff, config, command = 'review', resolvers) {
10
+ import { get as getGhReadFileTool, GTH_GH_READ_FILE_TOOL_NAME } from '#src/tools/ghReadFileTool.js';
11
+ export async function review(source, preamble, diff, config, command = 'review', resolvers, reviewContext) {
11
12
  const progressIndicator = config.streamOutput ? undefined : new ProgressIndicator('Reviewing.');
12
13
  const messages = [new SystemMessage(preamble), new HumanMessage(diff)];
14
+ // REL-2: optionally give the review agent a `gh api` file-read tool so it can fetch the FULL
15
+ // contents of a file when the PR diff truncates large changes. Only added in a GitHub PR
16
+ // context (the content source resolves to GitHub); a graceful no-op otherwise. Reads through
17
+ // the GitHub API rather than the workspace filesystem, so it is safe under pull_request_target.
18
+ maybeAddGhReadFileTool(config, command, reviewContext?.prId);
13
19
  // Prepare logging path (if enabled by config)
14
20
  const filePath = getCommandOutputFilePath(config, source);
15
21
  if (filePath) {
@@ -28,8 +34,9 @@ export async function review(source, preamble, diff, config, command = 'review',
28
34
  const reviewRateMiddleware = await createReviewRateMiddleware(rateConfig, config);
29
35
  config.middleware = [...middlewareWithoutReviewRate, reviewRateMiddleware];
30
36
  }
31
- // When no resolvers are provided (e.g. standalone CLI without @gaunt-sloth/tools),
32
- // supply a minimal middleware resolver that passes through already-resolved middleware.
37
+ // When no resolvers are provided (e.g. standalone review CLI, without @gaunt-sloth/agent's
38
+ // resolvers), supply a minimal middleware resolver that passes through already-resolved
39
+ // middleware. The full `gaunt-sloth` CLI injects @gaunt-sloth/agent's resolvers instead.
33
40
  const effectiveResolvers = resolvers ?? {
34
41
  resolveMiddleware: async (middleware) => middleware ?? [],
35
42
  };
@@ -62,6 +69,36 @@ export async function review(source, preamble, diff, config, command = 'review',
62
69
  }
63
70
  deleteArtifact(REVIEW_RATE_ARTIFACT_KEY);
64
71
  }
72
+ /**
73
+ * REL-2: conditionally inject the optional `gh api` file-read tool into the review agent's tools.
74
+ *
75
+ * Guarded so it is only active in a GitHub PR context, i.e. when the command's content source
76
+ * resolves to GitHub. For local/file/text reviews this is a no-op, keeping the tool optional and
77
+ * avoiding adding a GitHub-only capability where it cannot apply.
78
+ *
79
+ * The tool reads file contents via the GitHub API (`gh api`), never the workspace filesystem, so
80
+ * it remains safe under `pull_request_target` CI where the untrusted PR head is not checked out.
81
+ */
82
+ function maybeAddGhReadFileTool(config, command, prId) {
83
+ const commandConfig = config.commands?.[command];
84
+ // Honor deprecated alias too: contentProvider.
85
+ const contentSource = commandConfig?.contentSource ??
86
+ commandConfig?.contentProvider ??
87
+ config.contentSource ??
88
+ config.contentProvider;
89
+ if (contentSource !== 'github') {
90
+ return;
91
+ }
92
+ // config.tools is a union (StructuredToolInterface[] | BaseToolkit[] | ServerTool[]); the
93
+ // gh read-file tool is a StructuredToolInterface, so we only append into a structured-tool list.
94
+ const existingTools = (Array.isArray(config.tools) ? config.tools : []);
95
+ // Avoid duplicate registration if the tool is already present (e.g. via custom config).
96
+ const alreadyPresent = existingTools.some((t) => typeof t === 'object' && t !== null && 'name' in t && t.name === GTH_GH_READ_FILE_TOOL_NAME);
97
+ if (alreadyPresent) {
98
+ return;
99
+ }
100
+ config.tools = [...existingTools, getGhReadFileTool(config, prId)];
101
+ }
65
102
  function handleRatingResult(rateConfig, command) {
66
103
  if (!rateConfig || rateConfig.enabled === false) {
67
104
  // No rating enabled - no need to handle the result
@@ -1 +1 @@
1
- {"version":3,"file":"reviewModule.js","sourceRoot":"","sources":["../../src/modules/reviewModule.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AACjF,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,GAEzB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAGrE,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,MAAc,EACd,QAAgB,EAChB,IAAY,EACZ,MAAiB,EACjB,UAA2B,QAAQ,EACnC,SAA0B;IAE1B,MAAM,iBAAiB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAChG,MAAM,QAAQ,GAAG,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAEvE,8CAA8C;IAC9C,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,IAAI,QAAQ,EAAE,CAAC;QACb,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,yBAAyB,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IACtD,IAAI,UAAU,IAAI,UAAU,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAC/C,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QAC/C,MAAM,2BAA2B,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YAC/D,OAAO,CAAC,CACN,OAAO,EAAE,KAAK,QAAQ;gBACtB,EAAE,KAAK,IAAI;gBACX,MAAM,IAAI,EAAE;gBACX,EAAwB,CAAC,IAAI,KAAK,aAAa,CACjD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,iFAAiF;QACjF,MAAM,oBAAoB,GAAG,MAAM,0BAA0B,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClF,MAAM,CAAC,UAAU,GAAG,CAAC,GAAG,2BAA2B,EAAE,oBAAoB,CAAC,CAAC;IAC7E,CAAC;IAED,mFAAmF;IACnF,wFAAwF;IACxF,MAAM,kBAAkB,GAAmB,SAAS,IAAI;QACtD,iBAAiB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,EAAE;KAC1D,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,CAAC;IAC7E,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC,CAAC;QACtD,MAAM,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,YAAY,CACV,MAAM,CAAC,CAAC,CAAC,uCAAuC,MAAM,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAC9F,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAE1B,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAExC,yCAAyC;IACzC,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YACH,eAAe,EAAE,CAAC;YAClB,kBAAkB,EAAE,CAAC;YACrB,cAAc,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC7D,YAAY,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,cAAc,CAAC,wBAAwB,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,kBAAkB,CAAC,UAAoC,EAAE,OAAwB;IACxF,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAChD,mDAAmD;QACnD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAuB,wBAAwB,CAAC,CAAC;IAC3E,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,cAAc,CAAC,gDAAgD,OAAO,WAAW,CAAC,CAAC;QACnF,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,4EAA4E;QAC5F,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,UAAU,CAAC,aAAa,IAAI,MAAM,CAAC,aAAa,CAAC;IACnE,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;IAC3D,MAAM,WAAW,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,SAAS,gBAAgB,SAAS,GAAG,CAAC;IAC5E,WAAW,CAAC,iBAAiB,CAAC,CAAC;IAE/B,IAAI,MAAM,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,cAAc,CAAC,QAAQ,WAAW,EAAE,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,QAAQ,WAAW,EAAE,CAAC,CAAC;QACpC,IAAI,UAAU,CAAC,iBAAiB,IAAI,IAAI,EAAE,CAAC;YACzC,WAAW,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"reviewModule.js","sourceRoot":"","sources":["../../src/modules/reviewModule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { z } from 'zod';
2
+ import type { StructuredToolInterface } from '@langchain/core/tools';
3
+ import type { GthConfig } from '@gaunt-sloth/core/config.js';
4
+ declare const toolSchema: z.ZodObject<{
5
+ path: z.ZodString;
6
+ }, z.core.$strip>;
7
+ type GhReadFileArgs = z.infer<typeof toolSchema>;
8
+ /** owner/repo/ref of the PR under review — the binding the model is NOT allowed to supply. */
9
+ export interface PrRepoContext {
10
+ owner: string;
11
+ repo: string;
12
+ ref?: string;
13
+ }
14
+ /**
15
+ * Resolves the owner/repo and head ref of the PR under review from the GitHub CLI, so the file
16
+ * read is bound to the PR's own repository rather than anything the model supplies. With a prId
17
+ * the PR is addressed explicitly; without one `gh pr view` resolves the current branch's PR
18
+ * (the `gth pr` discovery mode). Returns the context, or an explanatory string on any failure.
19
+ */
20
+ export declare function resolvePrRepoContext(prId: string | undefined): Promise<PrRepoContext | string>;
21
+ /**
22
+ * Fetches the full contents of a single file from GitHub via the `gh api` CLI and decodes it.
23
+ * Returns the decoded text, or a human/agent-readable explanation string on any failure
24
+ * (graceful skip — never throws). owner/repo/ref come from the resolved PR context, not the LLM.
25
+ */
26
+ export declare function ghReadFileImpl(args: GhReadFileArgs, context: PrRepoContext): Promise<string>;
27
+ /**
28
+ * Built-in tool factory matching the repo's `get(config)` tool idiom (see gthWebFetchTool).
29
+ *
30
+ * `prId` identifies the PR under review (undefined in `gth pr` discovery mode → current branch).
31
+ * The owner/repo/ref are resolved from it once, lazily, and memoised for the run, so the agent
32
+ * cannot read files from any repo other than the one being reviewed.
33
+ */
34
+ export declare function get(_: GthConfig, prId?: string): StructuredToolInterface;
35
+ export declare const GTH_GH_READ_FILE_TOOL_NAME = "gth_gh_read_file";
36
+ export {};
@@ -0,0 +1,178 @@
1
+ import { z } from 'zod';
2
+ import { tool } from '@langchain/core/tools';
3
+ import { execAsync } from '@gaunt-sloth/core/utils/systemUtils.js';
4
+ import { debugLog } from '@gaunt-sloth/core/utils/debugUtils.js';
5
+ /**
6
+ * Optional `gh api` file-read tool for the `review`/`pr` flow.
7
+ *
8
+ * When a PR diff truncates large changes, the review agent can use this tool to fetch the
9
+ * FULL contents of a file straight from the GitHub REST contents endpoint
10
+ * (`/repos/{owner}/{repo}/contents/{path}`) via the authenticated `gh` CLI, decode the
11
+ * base64 payload, and read it as text.
12
+ *
13
+ * This deliberately reads through the GitHub API rather than the workspace filesystem, which
14
+ * makes it safe to use under `pull_request_target` CI: the untrusted PR head is never checked
15
+ * out, and no local fs access is required to inspect the changed files.
16
+ *
17
+ * The agent only supplies the repo-relative `path`. The owner/repo and the ref to read at are
18
+ * bound to the PR under review (resolved from `gh pr view`), NOT supplied by the model — an
19
+ * earlier version let the LLM pass owner/repo and it hallucinated them (e.g. reading
20
+ * `pulumi/pulumi` for an integration-tests workflow), returning plausible-but-wrong content
21
+ * into the review. Binding them to the PR context also closes the footgun of reading arbitrary
22
+ * files from any public repo the model can name.
23
+ *
24
+ * The tool is OPTIONAL and self-guarding:
25
+ * - The path is strictly validated so nothing LLM-supplied can inject shell metacharacters
26
+ * into the `gh api` invocation; the resolved owner/repo/ref are validated too.
27
+ * - When `gh` is missing/unauthenticated, or there is no PR/GitHub context, the call fails
28
+ * gracefully and returns an explanatory string instead of throwing, so the agent can simply
29
+ * continue with the (truncated) diff it already has.
30
+ */
31
+ const TOOL_NAME = 'gth_gh_read_file';
32
+ // PR ids reach us from the CLI; keep strict so nothing but a number can reach execAsync.
33
+ const PR_ID_PATTERN = /^\d+$/;
34
+ // owner/repo segments: GitHub login/repo naming, conservative allow-list (no shell metachars).
35
+ const OWNER_PATTERN = /^[A-Za-z0-9-_.]+$/;
36
+ const REPO_PATTERN = /^[A-Za-z0-9-_.]+$/;
37
+ // A git ref (branch, tag, or commit SHA). Disallow shell metacharacters and whitespace.
38
+ const REF_PATTERN = /^[A-Za-z0-9-_./]+$/;
39
+ // Repo-relative path. Allow slashes and common filename characters, but no shell metachars,
40
+ // no whitespace, and no parent-directory traversal.
41
+ const PATH_PATTERN = /^[A-Za-z0-9-_./]+$/;
42
+ const toolSchema = z.object({
43
+ path: z
44
+ .string()
45
+ .describe('Repository-relative path to the file, e.g. "src/index.ts" (no leading slash)'),
46
+ });
47
+ /**
48
+ * Resolves the owner/repo and head ref of the PR under review from the GitHub CLI, so the file
49
+ * read is bound to the PR's own repository rather than anything the model supplies. With a prId
50
+ * the PR is addressed explicitly; without one `gh pr view` resolves the current branch's PR
51
+ * (the `gth pr` discovery mode). Returns the context, or an explanatory string on any failure.
52
+ */
53
+ export async function resolvePrRepoContext(prId) {
54
+ if (prId !== undefined && !PR_ID_PATTERN.test(prId)) {
55
+ return `Invalid pull request id "${prId}"; expected a numeric string.`;
56
+ }
57
+ const prSelector = prId ? ` ${prId}` : '';
58
+ const ghCommand = `gh pr view${prSelector} --json headRefName,headRepository,headRepositoryOwner`;
59
+ let raw;
60
+ try {
61
+ raw = await execAsync(ghCommand);
62
+ }
63
+ catch (error) {
64
+ const reason = error instanceof Error ? error.message : String(error);
65
+ return (`Could not resolve the pull request repository via the GitHub API: ${reason}\n` +
66
+ `This tool needs an authenticated gh CLI (https://cli.github.com/) with access to the repository. ` +
67
+ `Continue the review using the diff you already have.`);
68
+ }
69
+ if (!raw) {
70
+ return `No pull request metadata returned${prId ? ` for #${prId}` : ' for the current branch'}.`;
71
+ }
72
+ let parsed;
73
+ try {
74
+ parsed = JSON.parse(raw);
75
+ }
76
+ catch (parseError) {
77
+ debugLog(`Failed to parse gh pr view output as JSON:\n${raw}`);
78
+ return `Failed to parse GitHub PR metadata: ${parseError instanceof Error ? parseError.message : String(parseError)}`;
79
+ }
80
+ const owner = parsed.headRepositoryOwner?.login;
81
+ const repo = parsed.headRepository?.name;
82
+ if (!owner || !repo) {
83
+ return `GitHub PR metadata did not include the head repository owner/name; cannot read files for this PR.`;
84
+ }
85
+ return { owner, repo, ref: parsed.headRefName };
86
+ }
87
+ /**
88
+ * Fetches the full contents of a single file from GitHub via the `gh api` CLI and decodes it.
89
+ * Returns the decoded text, or a human/agent-readable explanation string on any failure
90
+ * (graceful skip — never throws). owner/repo/ref come from the resolved PR context, not the LLM.
91
+ */
92
+ export async function ghReadFileImpl(args, context) {
93
+ const { path } = args;
94
+ const { owner, repo, ref } = context;
95
+ if (!PATH_PATTERN.test(path) || path.includes('..')) {
96
+ return `Invalid file path "${path}"; expected a repository-relative path without traversal.`;
97
+ }
98
+ // Defence-in-depth: the resolved owner/repo/ref are interpolated into the gh command too.
99
+ if (!OWNER_PATTERN.test(owner)) {
100
+ return `Invalid repository owner "${owner}"; expected a GitHub login/organisation name.`;
101
+ }
102
+ if (!REPO_PATTERN.test(repo)) {
103
+ return `Invalid repository name "${repo}".`;
104
+ }
105
+ if (ref !== undefined && !REF_PATTERN.test(ref)) {
106
+ return `Invalid git ref "${ref}".`;
107
+ }
108
+ // -q is intentionally avoided so we can decode base64 ourselves and keep behaviour explicit.
109
+ const refQuery = ref ? `?ref=${ref}` : '';
110
+ const ghCommand = `gh api /repos/${owner}/${repo}/contents/${path}${refQuery}`;
111
+ try {
112
+ const raw = await execAsync(ghCommand);
113
+ if (!raw) {
114
+ return `No content returned for ${owner}/${repo}/${path}${ref ? `@${ref}` : ''}.`;
115
+ }
116
+ let parsed;
117
+ try {
118
+ parsed = JSON.parse(raw);
119
+ }
120
+ catch (parseError) {
121
+ debugLog(`Failed to parse gh api contents output as JSON:\n${raw}`);
122
+ return `Failed to parse GitHub API response for ${owner}/${repo}/${path}: ${parseError instanceof Error ? parseError.message : String(parseError)}`;
123
+ }
124
+ if (Array.isArray(parsed)) {
125
+ return `"${path}" is a directory, not a file. Provide a path to a single file.`;
126
+ }
127
+ if (parsed.type && parsed.type !== 'file') {
128
+ return `"${path}" is not a regular file (type: ${parsed.type}).`;
129
+ }
130
+ if (parsed.encoding !== 'base64' || typeof parsed.content !== 'string') {
131
+ // Large files (>1MB) are not returned inline by the contents endpoint.
132
+ return `GitHub did not return inline base64 content for "${path}" (it may be too large to read via the contents endpoint).`;
133
+ }
134
+ const decoded = Buffer.from(parsed.content, 'base64').toString('utf8');
135
+ const label = `${owner}/${repo}/${path}${ref ? `@${ref}` : ''}`;
136
+ return `Full contents of ${label}:\n\n${decoded}`;
137
+ }
138
+ catch (error) {
139
+ // Graceful skip: gh missing/unauthenticated, file not found, or no GitHub context.
140
+ const reason = error instanceof Error ? error.message : String(error);
141
+ return (`Could not read "${owner}/${repo}/${path}" via the GitHub API: ${reason}\n` +
142
+ `This tool needs an authenticated gh CLI (https://cli.github.com/) with access to the repository. ` +
143
+ `Continue the review using the diff you already have.`);
144
+ }
145
+ }
146
+ /**
147
+ * Built-in tool factory matching the repo's `get(config)` tool idiom (see gthWebFetchTool).
148
+ *
149
+ * `prId` identifies the PR under review (undefined in `gth pr` discovery mode → current branch).
150
+ * The owner/repo/ref are resolved from it once, lazily, and memoised for the run, so the agent
151
+ * cannot read files from any repo other than the one being reviewed.
152
+ */
153
+ export function get(_, prId) {
154
+ let contextPromise;
155
+ const getContext = () => {
156
+ if (!contextPromise) {
157
+ contextPromise = resolvePrRepoContext(prId);
158
+ }
159
+ return contextPromise;
160
+ };
161
+ return tool(async (args) => {
162
+ const context = await getContext();
163
+ if (typeof context === 'string') {
164
+ return context; // resolution failed — return the explanation as a graceful skip.
165
+ }
166
+ return ghReadFileImpl(args, context);
167
+ }, {
168
+ name: TOOL_NAME,
169
+ description: 'Read the FULL contents of a single file from the pull request under review via the ' +
170
+ 'GitHub API. Use this when the PR diff is truncated and you need to see the complete ' +
171
+ 'file. Supply only the repository-relative path; the repository and ref are bound to ' +
172
+ 'the PR automatically. Reads through the GitHub API, not the local filesystem, so it is ' +
173
+ 'safe in pull_request_target CI.',
174
+ schema: toolSchema,
175
+ });
176
+ }
177
+ export const GTH_GH_READ_FILE_TOOL_NAME = TOOL_NAME;
178
+ //# sourceMappingURL=ghReadFileTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ghReadFileTool.js","sourceRoot":"","sources":["../../src/tools/ghReadFileTool.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1 @@
1
1
  export * from '@gaunt-sloth/core/utils/fileUtils.js';
2
- /**
3
- * Reads multiple files from the current directory and returns their contents
4
- * @param fileNames - Array of file names to read
5
- * @returns Combined content of all files with proper formatting, each file is wrapped in random block like <file-abvesde>
6
- */
7
- export declare function readMultipleFilesFromProjectDir(fileNames: string | string[]): string;
@@ -1,20 +1,2 @@
1
1
  export * from '@gaunt-sloth/core/utils/fileUtils.js';
2
- import { readFileFromProjectDir } from '@gaunt-sloth/core/utils/fileUtils.js';
3
- import { wrapContent } from '@gaunt-sloth/core/utils/llmUtils.js';
4
- /**
5
- * Reads multiple files from the current directory and returns their contents
6
- * @param fileNames - Array of file names to read
7
- * @returns Combined content of all files with proper formatting, each file is wrapped in random block like <file-abvesde>
8
- */
9
- export function readMultipleFilesFromProjectDir(fileNames) {
10
- if (!Array.isArray(fileNames)) {
11
- return wrapContent(readFileFromProjectDir(fileNames), 'file', `file ${fileNames}`, true);
12
- }
13
- return fileNames
14
- .map((fileName) => {
15
- const content = readFileFromProjectDir(fileName);
16
- return `${wrapContent(content, 'file', `file ${fileName}`, true)}`;
17
- })
18
- .join('\n\n');
19
- }
20
2
  //# sourceMappingURL=fileUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fileUtils.js","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAElE;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAAC,SAA4B;IAC1E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,WAAW,CAAC,sBAAsB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,SAAS,EAAE,EAAE,IAAI,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO,SAAS;SACb,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChB,MAAM,OAAO,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QACjD,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,QAAQ,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;IACrE,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"fileUtils.js","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC"}
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@gaunt-sloth/review",
3
- "version": "0.1.8",
3
+ "version": "2.0.0-alpha.0",
4
4
  "description": "Review functionality for Gaunt Sloth",
5
5
  "license": "MIT",
6
6
  "author": "Andrew Kondratev",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/Galvanized-Pukeko/gaunt-sloth-assistant.git",
9
+ "url": "git+https://github.com/Galvanized-Pukeko/gaunt-sloth.git",
10
10
  "directory": "packages/review"
11
11
  },
12
12
  "bugs": {
13
- "url": "https://github.com/Galvanized-Pukeko/gaunt-sloth-assistant/issues"
13
+ "url": "https://github.com/Galvanized-Pukeko/gaunt-sloth/issues"
14
14
  },
15
- "homepage": "https://github.com/Galvanized-Pukeko/gaunt-sloth-assistant/tree/main/packages/review#readme",
15
+ "homepage": "https://github.com/Galvanized-Pukeko/gaunt-sloth/tree/main/packages/review#readme",
16
16
  "keywords": [
17
17
  "ai",
18
18
  "agent",
@@ -34,15 +34,7 @@
34
34
  "#src/*.js": "./dist/*.js"
35
35
  },
36
36
  "dependencies": {
37
- "@gaunt-sloth/core": "0.1.8"
38
- },
39
- "peerDependencies": {
40
- "@gaunt-sloth/tools": "0.1.8"
41
- },
42
- "peerDependenciesMeta": {
43
- "@gaunt-sloth/tools": {
44
- "optional": true
45
- }
37
+ "@gaunt-sloth/core": "2.0.0-alpha.0"
46
38
  },
47
39
  "files": [
48
40
  "./dist/*",
@@ -50,5 +42,8 @@
50
42
  ],
51
43
  "scripts": {
52
44
  "build": "tsc"
45
+ },
46
+ "publishConfig": {
47
+ "tag": "alpha"
53
48
  }
54
49
  }
@@ -1,9 +0,0 @@
1
- import type { GthConfig } from '@gaunt-sloth/core/config.js';
2
- import type { AgentResolvers } from '@gaunt-sloth/core/core/types.js';
3
- /**
4
- * Ask a question and get an answer from the LLM
5
- * @param source - The source of the question (used for file naming)
6
- * @param preamble - The preamble to send to the LLM
7
- * @param content - The content of the question
8
- */
9
- export declare function askQuestion(source: string, preamble: string, content: string, config: GthConfig, resolvers?: AgentResolvers): Promise<void>;
@@ -1,49 +0,0 @@
1
- import { defaultStatusCallback, display, displayError, displaySuccess, flushSessionLog, initSessionLogging, stopSessionLogging, } from '@gaunt-sloth/core/utils/consoleUtils.js';
2
- import { getCommandOutputFilePath } from '#src/utils/fileUtils.js';
3
- import { GthAgentRunner } from '@gaunt-sloth/core/core/GthAgentRunner.js';
4
- import { MemorySaver } from '@langchain/langgraph';
5
- import { HumanMessage, SystemMessage } from '@langchain/core/messages';
6
- import { ProgressIndicator } from '@gaunt-sloth/core/utils/ProgressIndicator.js';
7
- /**
8
- * Ask a question and get an answer from the LLM
9
- * @param source - The source of the question (used for file naming)
10
- * @param preamble - The preamble to send to the LLM
11
- * @param content - The content of the question
12
- */
13
- export async function askQuestion(source, preamble, content, config, resolvers) {
14
- const progressIndicator = config.streamOutput ? undefined : new ProgressIndicator('Thinking.');
15
- const messages = [new SystemMessage(preamble), new HumanMessage(content)];
16
- // Resolve output path and initialize session logging if enabled
17
- const filePath = getCommandOutputFilePath(config, source);
18
- if (filePath) {
19
- initSessionLogging(filePath, config.streamSessionInferenceLog);
20
- }
21
- // Run via Agent Runner (consistent with interactive session)
22
- const runner = new GthAgentRunner(defaultStatusCallback, resolvers);
23
- try {
24
- await runner.init('ask', config, new MemorySaver());
25
- await runner.processMessages(messages);
26
- }
27
- catch (err) {
28
- displayError(`Failed to get answer: ${err instanceof Error ? err.message : String(err)}`);
29
- }
30
- finally {
31
- await runner.cleanup();
32
- }
33
- progressIndicator?.stop();
34
- if (config.writeOutputToFile === false) {
35
- display('\n'); // something going on in some terminals, they swallow last line of output
36
- }
37
- if (filePath) {
38
- try {
39
- flushSessionLog();
40
- stopSessionLogging();
41
- displaySuccess(`\n\nThis report can be found in ${filePath}`);
42
- }
43
- catch (error) {
44
- displayError(`Failed to write answer to file: ${filePath}`);
45
- displayError(error instanceof Error ? error.message : String(error));
46
- }
47
- }
48
- }
49
- //# sourceMappingURL=questionAnsweringModule.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"questionAnsweringModule.js","sourceRoot":"","sources":["../../src/modules/questionAnsweringModule.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,OAAO,EACP,YAAY,EACZ,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AAGjF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,QAAgB,EAChB,OAAe,EACf,MAAiB,EACjB,SAA0B;IAE1B,MAAM,iBAAiB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC/F,MAAM,QAAQ,GAAG,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;IAE1E,gEAAgE;IAChE,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,IAAI,QAAQ,EAAE,CAAC;QACb,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,yBAAyB,CAAC,CAAC;IACjE,CAAC;IAED,6DAA6D;IAC7D,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC,CAAC;QACpD,MAAM,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,YAAY,CAAC,yBAAyB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAE1B,IAAI,MAAM,CAAC,iBAAiB,KAAK,KAAK,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,yEAAyE;IAC1F,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YACH,eAAe,EAAE,CAAC;YAClB,kBAAkB,EAAE,CAAC;YACrB,cAAc,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;YAC5D,YAAY,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC"}