@joeytheman/gemini-mcp-tool 1.3.0 → 2.2.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 +123 -34
- package/dist/__tests__/ask-gemini.test.js +99 -37
- package/dist/__tests__/ask-gemini.test.js.map +1 -1
- package/dist/__tests__/live-pass.test.d.ts +2 -0
- package/dist/__tests__/live-pass.test.d.ts.map +1 -0
- package/dist/__tests__/live-pass.test.js +725 -0
- package/dist/__tests__/live-pass.test.js.map +1 -0
- package/dist/__tests__/screen-review.test.d.ts +2 -0
- package/dist/__tests__/screen-review.test.d.ts.map +1 -0
- package/dist/__tests__/screen-review.test.js +444 -0
- package/dist/__tests__/screen-review.test.js.map +1 -0
- package/dist/__tests__/server.test.js +17 -12
- package/dist/__tests__/server.test.js.map +1 -1
- package/dist/__tests__/simple-tools.test.d.ts +2 -0
- package/dist/__tests__/simple-tools.test.d.ts.map +1 -0
- package/dist/__tests__/simple-tools.test.js +25 -0
- package/dist/__tests__/simple-tools.test.js.map +1 -0
- package/dist/__tests__/tools.test.js +63 -0
- package/dist/__tests__/tools.test.js.map +1 -1
- package/dist/__tests__/utils/agyExecutor.test.d.ts +2 -0
- package/dist/__tests__/utils/agyExecutor.test.d.ts.map +1 -0
- package/dist/__tests__/utils/agyExecutor.test.js +616 -0
- package/dist/__tests__/utils/agyExecutor.test.js.map +1 -0
- package/dist/__tests__/utils/agyTranscriptRecovery.test.d.ts +2 -0
- package/dist/__tests__/utils/agyTranscriptRecovery.test.d.ts.map +1 -0
- package/dist/__tests__/utils/agyTranscriptRecovery.test.js +127 -0
- package/dist/__tests__/utils/agyTranscriptRecovery.test.js.map +1 -0
- package/dist/__tests__/utils/chunkCache.test.js +26 -2
- package/dist/__tests__/utils/chunkCache.test.js.map +1 -1
- package/dist/__tests__/utils/commandExecutor.test.js +30 -6
- package/dist/__tests__/utils/commandExecutor.test.js.map +1 -1
- package/dist/__tests__/utils/fileReferences.test.d.ts +2 -0
- package/dist/__tests__/utils/fileReferences.test.d.ts.map +1 -0
- package/dist/__tests__/utils/fileReferences.test.js +87 -0
- package/dist/__tests__/utils/fileReferences.test.js.map +1 -0
- package/dist/__tests__/utils/gitStatusGuard.test.d.ts +2 -0
- package/dist/__tests__/utils/gitStatusGuard.test.d.ts.map +1 -0
- package/dist/__tests__/utils/gitStatusGuard.test.js +106 -0
- package/dist/__tests__/utils/gitStatusGuard.test.js.map +1 -0
- package/dist/__tests__/utils/responseCache.test.js +31 -11
- package/dist/__tests__/utils/responseCache.test.js.map +1 -1
- package/dist/__tests__/utils/test-helpers.d.ts +4 -0
- package/dist/__tests__/utils/test-helpers.d.ts.map +1 -1
- package/dist/__tests__/utils/test-helpers.js +16 -0
- package/dist/__tests__/utils/test-helpers.js.map +1 -1
- package/dist/constants.d.ts +68 -26
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +69 -28
- package/dist/constants.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/tools/ask-gemini.tool.d.ts +34 -0
- package/dist/tools/ask-gemini.tool.d.ts.map +1 -1
- package/dist/tools/ask-gemini.tool.js +38 -22
- package/dist/tools/ask-gemini.tool.js.map +1 -1
- package/dist/tools/brainstorm.tool.d.ts.map +1 -1
- package/dist/tools/brainstorm.tool.js +5 -4
- package/dist/tools/brainstorm.tool.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/live-pass.tool.d.ts +183 -0
- package/dist/tools/live-pass.tool.d.ts.map +1 -0
- package/dist/tools/live-pass.tool.js +548 -0
- package/dist/tools/live-pass.tool.js.map +1 -0
- package/dist/tools/registry.d.ts +4 -2
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +12 -9
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/screen-review.tool.d.ts +121 -0
- package/dist/tools/screen-review.tool.d.ts.map +1 -0
- package/dist/tools/screen-review.tool.js +415 -0
- package/dist/tools/screen-review.tool.js.map +1 -0
- package/dist/tools/simple-tools.d.ts.map +1 -1
- package/dist/tools/simple-tools.js +4 -2
- package/dist/tools/simple-tools.js.map +1 -1
- package/dist/utils/agyExecutor.d.ts +68 -0
- package/dist/utils/agyExecutor.d.ts.map +1 -0
- package/dist/utils/agyExecutor.js +443 -0
- package/dist/utils/agyExecutor.js.map +1 -0
- package/dist/utils/agyReport.d.ts +19 -0
- package/dist/utils/agyReport.d.ts.map +1 -0
- package/dist/utils/agyReport.js +62 -0
- package/dist/utils/agyReport.js.map +1 -0
- package/dist/utils/agyTranscriptRecovery.d.ts +16 -0
- package/dist/utils/agyTranscriptRecovery.d.ts.map +1 -0
- package/dist/utils/agyTranscriptRecovery.js +149 -0
- package/dist/utils/agyTranscriptRecovery.js.map +1 -0
- package/dist/utils/chunkCache.d.ts.map +1 -1
- package/dist/utils/chunkCache.js +19 -5
- package/dist/utils/chunkCache.js.map +1 -1
- package/dist/utils/commandExecutor.d.ts.map +1 -1
- package/dist/utils/commandExecutor.js +15 -7
- package/dist/utils/commandExecutor.js.map +1 -1
- package/dist/utils/fileReferences.d.ts +45 -0
- package/dist/utils/fileReferences.d.ts.map +1 -0
- package/dist/utils/fileReferences.js +169 -0
- package/dist/utils/fileReferences.js.map +1 -0
- package/dist/utils/gitStatusGuard.d.ts +35 -0
- package/dist/utils/gitStatusGuard.d.ts.map +1 -0
- package/dist/utils/gitStatusGuard.js +82 -0
- package/dist/utils/gitStatusGuard.js.map +1 -0
- package/dist/utils/responseCache.d.ts +3 -3
- package/dist/utils/responseCache.d.ts.map +1 -1
- package/dist/utils/responseCache.js +11 -6
- package/dist/utils/responseCache.js.map +1 -1
- package/package.json +10 -9
- package/dist/__tests__/utils/geminiExecutor.test.d.ts +0 -2
- package/dist/__tests__/utils/geminiExecutor.test.d.ts.map +0 -1
- package/dist/__tests__/utils/geminiExecutor.test.js +0 -337
- package/dist/__tests__/utils/geminiExecutor.test.js.map +0 -1
- package/dist/utils/geminiExecutor.d.ts +0 -17
- package/dist/utils/geminiExecutor.d.ts.map +0 -1
- package/dist/utils/geminiExecutor.js +0 -238
- package/dist/utils/geminiExecutor.js.map +0 -1
package/dist/tools/registry.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { ZodError } from "zod";
|
|
2
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
1
|
+
import { z, ZodError } from "zod";
|
|
3
2
|
export const toolRegistry = [];
|
|
4
3
|
export function toolExists(toolName) {
|
|
5
4
|
return toolRegistry.some(t => t.name === toolName);
|
|
6
5
|
}
|
|
7
6
|
export function getToolDefinitions() {
|
|
8
7
|
return toolRegistry.map(tool => {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
// io: 'input' so a field with a default is advertised as optional, not
|
|
9
|
+
// required — the default is applied here, not by the client.
|
|
10
|
+
const jsonSchema = z.toJSONSchema(tool.zodSchema, { io: 'input' });
|
|
11
11
|
const inputSchema = {
|
|
12
12
|
type: "object",
|
|
13
|
-
properties:
|
|
14
|
-
required:
|
|
13
|
+
properties: jsonSchema.properties || {},
|
|
14
|
+
required: jsonSchema.required || [],
|
|
15
15
|
};
|
|
16
16
|
return {
|
|
17
17
|
name: tool.name,
|
|
@@ -22,7 +22,7 @@ export function getToolDefinitions() {
|
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
function extractPromptArguments(zodSchema) {
|
|
25
|
-
const jsonSchema =
|
|
25
|
+
const jsonSchema = z.toJSONSchema(zodSchema, { io: 'input' });
|
|
26
26
|
const properties = jsonSchema.properties || {};
|
|
27
27
|
const required = jsonSchema.required || [];
|
|
28
28
|
return Object.entries(properties).map(([name, prop]) => ({
|
|
@@ -40,6 +40,10 @@ export function getPromptDefinitions() {
|
|
|
40
40
|
arguments: tool.prompt.arguments || extractPromptArguments(tool.zodSchema),
|
|
41
41
|
}));
|
|
42
42
|
}
|
|
43
|
+
/** Zod issues as `path: message` lines, for error text and schema-mismatch reports. */
|
|
44
|
+
export function formatZodIssues(error) {
|
|
45
|
+
return error.issues.map(issue => `${issue.path.join('.')}: ${issue.message}`);
|
|
46
|
+
}
|
|
43
47
|
export async function executeTool(toolName, args, onProgress) {
|
|
44
48
|
const tool = toolRegistry.find(t => t.name === toolName);
|
|
45
49
|
if (!tool) {
|
|
@@ -51,8 +55,7 @@ export async function executeTool(toolName, args, onProgress) {
|
|
|
51
55
|
}
|
|
52
56
|
catch (error) {
|
|
53
57
|
if (error instanceof ZodError) {
|
|
54
|
-
|
|
55
|
-
throw new Error(`Invalid arguments for ${toolName}: ${issues}`);
|
|
58
|
+
throw new Error(`Invalid arguments for ${toolName}: ${formatZodIssues(error).join(', ')}`);
|
|
56
59
|
}
|
|
57
60
|
throw error;
|
|
58
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { UnifiedTool } from './registry.js';
|
|
3
|
+
import { type AgyJsonEnvelope } from '../utils/agyExecutor.js';
|
|
4
|
+
import { type WorkingTreeDiff } from '../utils/gitStatusGuard.js';
|
|
5
|
+
export declare const screenReviewArgsSchema: z.ZodObject<{
|
|
6
|
+
mode: z.ZodEnum<{
|
|
7
|
+
review: "review";
|
|
8
|
+
plan: "plan";
|
|
9
|
+
}>;
|
|
10
|
+
instructions: z.ZodString;
|
|
11
|
+
context: z.ZodOptional<z.ZodString>;
|
|
12
|
+
workingDirectory: z.ZodString;
|
|
13
|
+
images: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
14
|
+
changedRoutes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
15
|
+
routeFile: z.ZodOptional<z.ZodString>;
|
|
16
|
+
model: z.ZodDefault<z.ZodString>;
|
|
17
|
+
printTimeout: z.ZodDefault<z.ZodString>;
|
|
18
|
+
yolo: z.ZodDefault<z.ZodBoolean>;
|
|
19
|
+
conversationId: z.ZodOptional<z.ZodString>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
export type ScreenReviewArgs = z.infer<typeof screenReviewArgsSchema>;
|
|
22
|
+
export declare const screenReviewResultSchema: z.ZodObject<{
|
|
23
|
+
verdict: z.ZodEnum<{
|
|
24
|
+
APPROVE: "APPROVE";
|
|
25
|
+
REQUEST_CHANGES: "REQUEST_CHANGES";
|
|
26
|
+
}>;
|
|
27
|
+
screens: z.ZodArray<z.ZodObject<{
|
|
28
|
+
file: z.ZodString;
|
|
29
|
+
subject: z.ZodString;
|
|
30
|
+
route_file: z.ZodString;
|
|
31
|
+
inventory: z.ZodArray<z.ZodString>;
|
|
32
|
+
findings: z.ZodArray<z.ZodObject<{
|
|
33
|
+
severity: z.ZodEnum<{
|
|
34
|
+
BLOCKER: "BLOCKER";
|
|
35
|
+
MAJOR: "MAJOR";
|
|
36
|
+
MINOR: "MINOR";
|
|
37
|
+
}>;
|
|
38
|
+
confirmed: z.ZodBoolean;
|
|
39
|
+
location: z.ZodString;
|
|
40
|
+
observed: z.ZodString;
|
|
41
|
+
rule: z.ZodString;
|
|
42
|
+
fix: z.ZodString;
|
|
43
|
+
}, z.core.$strip>>;
|
|
44
|
+
}, z.core.$strip>>;
|
|
45
|
+
cross_screen_findings: z.ZodArray<z.ZodObject<{
|
|
46
|
+
severity: z.ZodEnum<{
|
|
47
|
+
BLOCKER: "BLOCKER";
|
|
48
|
+
MAJOR: "MAJOR";
|
|
49
|
+
MINOR: "MINOR";
|
|
50
|
+
}>;
|
|
51
|
+
confirmed: z.ZodBoolean;
|
|
52
|
+
location: z.ZodString;
|
|
53
|
+
observed: z.ZodString;
|
|
54
|
+
rule: z.ZodString;
|
|
55
|
+
fix: z.ZodString;
|
|
56
|
+
}, z.core.$strip>>;
|
|
57
|
+
summary: z.ZodString;
|
|
58
|
+
}, z.core.$strip>;
|
|
59
|
+
export declare const screenPlanResultSchema: z.ZodObject<{
|
|
60
|
+
route_file: z.ZodString;
|
|
61
|
+
controls: z.ZodArray<z.ZodObject<{
|
|
62
|
+
control: z.ZodString;
|
|
63
|
+
primitive: z.ZodString;
|
|
64
|
+
placement: z.ZodString;
|
|
65
|
+
promoted: z.ZodBoolean;
|
|
66
|
+
verb_today: z.ZodString;
|
|
67
|
+
verb_per_rule: z.ZodString;
|
|
68
|
+
operation: z.ZodString;
|
|
69
|
+
capability: z.ZodString;
|
|
70
|
+
scope: z.ZodString;
|
|
71
|
+
}, z.core.$strip>>;
|
|
72
|
+
top_slot_priority: z.ZodArray<z.ZodString>;
|
|
73
|
+
hand_rolls_to_delete: z.ZodArray<z.ZodObject<{
|
|
74
|
+
line: z.ZodString;
|
|
75
|
+
primitive: z.ZodString;
|
|
76
|
+
}, z.core.$strip>>;
|
|
77
|
+
notes: z.ZodString;
|
|
78
|
+
}, z.core.$strip>;
|
|
79
|
+
export type ScreenReviewResult = z.infer<typeof screenReviewResultSchema>;
|
|
80
|
+
export type ScreenPlanResult = z.infer<typeof screenPlanResultSchema>;
|
|
81
|
+
export declare const SCREEN_REVIEW_RESULT_JSON_SCHEMA: Record<string, unknown>;
|
|
82
|
+
export declare const SCREEN_PLAN_RESULT_JSON_SCHEMA: Record<string, unknown>;
|
|
83
|
+
export declare function buildScreenReviewPrompt(config: {
|
|
84
|
+
mode: 'review' | 'plan';
|
|
85
|
+
instructions: string;
|
|
86
|
+
context?: string;
|
|
87
|
+
images?: string[];
|
|
88
|
+
routeFile?: string;
|
|
89
|
+
changedRoutes?: string[];
|
|
90
|
+
}): string;
|
|
91
|
+
export interface ReviewDecision {
|
|
92
|
+
verdict: 'APPROVE' | 'REQUEST_CHANGES';
|
|
93
|
+
reported: string;
|
|
94
|
+
reasons: string[];
|
|
95
|
+
unreviewed: string[];
|
|
96
|
+
unknownFiles: string[];
|
|
97
|
+
downgraded: number;
|
|
98
|
+
coverage: {
|
|
99
|
+
route: string;
|
|
100
|
+
image: string | null;
|
|
101
|
+
}[];
|
|
102
|
+
warnings: string[];
|
|
103
|
+
}
|
|
104
|
+
/** Gemini's verdict is advisory; unconfirmed MAJORs are downgraded, unreviewed images always block. */
|
|
105
|
+
export declare function deriveReviewVerdict(result: ScreenReviewResult, images: string[], changedRoutes?: string[]): ReviewDecision;
|
|
106
|
+
export declare function formatScreenReviewReport(input: {
|
|
107
|
+
envelope: AgyJsonEnvelope;
|
|
108
|
+
result: ScreenReviewResult;
|
|
109
|
+
decision: ReviewDecision;
|
|
110
|
+
deniedActions: string;
|
|
111
|
+
workingTree: WorkingTreeDiff;
|
|
112
|
+
}): string;
|
|
113
|
+
export declare function formatScreenPlanReport(input: {
|
|
114
|
+
envelope: AgyJsonEnvelope;
|
|
115
|
+
result: ScreenPlanResult;
|
|
116
|
+
routeFile: string;
|
|
117
|
+
deniedActions: string;
|
|
118
|
+
workingTree: WorkingTreeDiff;
|
|
119
|
+
}): string;
|
|
120
|
+
export declare const screenReviewTool: UnifiedTool;
|
|
121
|
+
//# sourceMappingURL=screen-review.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen-review.tool.d.ts","sourceRoot":"","sources":["../../src/tools/screen-review.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAmB,MAAM,eAAe,CAAC;AAC7D,OAAO,EAML,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAwC,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAgBxG,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;iBAwDjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAatE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAWnC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;iBAgBjC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC1E,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,gCAAgC,yBAA4C,CAAC;AAC1F,eAAO,MAAM,8BAA8B,yBAA0C,CAAC;AAQtF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,MAAM,CA4CT;AAID,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,SAAS,GAAG,iBAAiB,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IACpD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAwBD,uGAAuG;AACvG,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,MAAM,EAAE,EAChB,aAAa,GAAE,MAAM,EAAO,GAC3B,cAAc,CAyDhB;AAWD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,eAAe,CAAC;CAC9B,GAAG,MAAM,CA+CT;AAOD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,eAAe,CAAC;CAC9B,GAAG,MAAM,CAqCT;AAID,eAAO,MAAM,gBAAgB,EAAE,WA+F9B,CAAC"}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { formatZodIssues } from './registry.js';
|
|
5
|
+
import { deniedActionsSummary, executeAgyJson, formatAgyUsageLine, formatConversationLine, toAgyJsonSchema, } from '../utils/agyExecutor.js';
|
|
6
|
+
import { bulletList, section, renderUnparsableEnvelope, formatWorkingTreeSection, failWithWorkingTree } from '../utils/agyReport.js';
|
|
7
|
+
import { isWithin, resolveWorkingDirectory, realpathOfExistingPrefix } from '../utils/fileReferences.js';
|
|
8
|
+
import { snapshotWorkingTree, diffWorkingTree } from '../utils/gitStatusGuard.js';
|
|
9
|
+
import { ERROR_MESSAGES, LIVE_PASS, MODELS, MODEL_CHOICE_DESCRIPTION } from '../constants.js';
|
|
10
|
+
const IMAGE_EXTENSIONS = /\.(png|jpe?g)$/i;
|
|
11
|
+
const WHITESPACE = /\s/;
|
|
12
|
+
// ---------------------------------------------------------------- arguments
|
|
13
|
+
function fileExists(candidate) {
|
|
14
|
+
try {
|
|
15
|
+
return fs.statSync(candidate).isFile();
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export const screenReviewArgsSchema = z.object({
|
|
22
|
+
mode: z.enum(['review', 'plan']).describe("'review' judges screenshots after a live pass. 'plan' inventories a route file before any screenshot exists and returns no verdict."),
|
|
23
|
+
instructions: z.string().min(1).describe("The caller's reviewer prompt, verbatim. Passed through unchanged so rule citations stay exact."),
|
|
24
|
+
context: z.string().optional().describe("Optional extra context: composition contract, changed-file list, issue text."),
|
|
25
|
+
workingDirectory: z.string().min(1).describe("Absolute path to the checkout the instructions cite. Used as the agy cwd and workspace root, so repository-relative rule paths resolve."),
|
|
26
|
+
images: z.array(z.string()).optional().describe("review mode only: absolute paths to the PNG/JPEG frames to judge. Each must exist."),
|
|
27
|
+
changedRoutes: z.array(z.string()).optional().describe("review mode: repo-relative route/component files the diff touched (from `git diff --name-only`). Every changed screen file (under an `app/` directory) that no image shows makes the review REQUEST_CHANGES; a changed file under `components/` only warns."),
|
|
28
|
+
routeFile: z.string().optional().describe("plan mode only: absolute path to the route/screen source file to inventory. Must exist inside workingDirectory."),
|
|
29
|
+
model: z.string().default(MODELS.MEDIUM).describe(`${MODEL_CHOICE_DESCRIPTION} Defaults to '${MODELS.MEDIUM}'.`),
|
|
30
|
+
printTimeout: z.string().default(LIVE_PASS.SCREEN_REVIEW_PRINT_TIMEOUT).describe("agy --print-timeout for the review."),
|
|
31
|
+
yolo: z.boolean().default(false).describe("Pass --dangerously-skip-permissions. Defaults to false because a review only reads. Set it to true when the instructions ask Gemini to read repository files that are not passed as images: it reaches for a shell to do that, headless agy denies the shell, and the call then fails naming the denied action."),
|
|
32
|
+
conversationId: z.string().min(1).optional().describe("Resume a previous review so round 2 keeps round 1's visual analysis."),
|
|
33
|
+
}).superRefine((value, ctx) => {
|
|
34
|
+
if (value.mode === 'review') {
|
|
35
|
+
if (value.routeFile) {
|
|
36
|
+
ctx.addIssue({ code: 'custom', message: 'routeFile is plan mode only', path: ['routeFile'] });
|
|
37
|
+
}
|
|
38
|
+
if (!value.images || value.images.length === 0) {
|
|
39
|
+
ctx.addIssue({ code: 'custom', message: ERROR_MESSAGES.SCREEN_REVIEW_NO_IMAGES, path: ['images'] });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
value.images.forEach((image, index) => {
|
|
43
|
+
if (!path.isAbsolute(image)) {
|
|
44
|
+
ctx.addIssue({ code: 'custom', message: `image path must be absolute: ${image}`, path: ['images', index] });
|
|
45
|
+
}
|
|
46
|
+
else if (WHITESPACE.test(image)) {
|
|
47
|
+
ctx.addIssue({ code: 'custom', message: `${ERROR_MESSAGES.UNREFERENCEABLE_PATH}: ${image}`, path: ['images', index] });
|
|
48
|
+
}
|
|
49
|
+
else if (!fileExists(image)) {
|
|
50
|
+
ctx.addIssue({ code: 'custom', message: `${ERROR_MESSAGES.SCREEN_REVIEW_IMAGE_MISSING}: ${image}`, path: ['images', index] });
|
|
51
|
+
}
|
|
52
|
+
else if (!IMAGE_EXTENSIONS.test(image)) {
|
|
53
|
+
ctx.addIssue({ code: 'custom', message: `image must be a PNG or JPEG: ${image}`, path: ['images', index] });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (value.images) {
|
|
59
|
+
ctx.addIssue({ code: 'custom', message: 'images is review mode only', path: ['images'] });
|
|
60
|
+
}
|
|
61
|
+
const routeFile = value.routeFile;
|
|
62
|
+
if (!routeFile || !path.isAbsolute(routeFile) || !fileExists(routeFile)) {
|
|
63
|
+
ctx.addIssue({ code: 'custom', message: ERROR_MESSAGES.SCREEN_REVIEW_ROUTE_FILE, path: ['routeFile'] });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (WHITESPACE.test(routeFile)) {
|
|
67
|
+
ctx.addIssue({ code: 'custom', message: `${ERROR_MESSAGES.UNREFERENCEABLE_PATH}: ${routeFile}`, path: ['routeFile'] });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// Realpath'd on both sides: execute resolves workingDirectory the same way,
|
|
71
|
+
// so a symlinked spelling must not reject a route file that is really inside.
|
|
72
|
+
if (!isWithin(realpathOfExistingPrefix(value.workingDirectory), realpathOfExistingPrefix(routeFile))) {
|
|
73
|
+
ctx.addIssue({
|
|
74
|
+
code: 'custom',
|
|
75
|
+
message: `${ERROR_MESSAGES.SCREEN_REVIEW_ROUTE_FILE}. '${routeFile}' is outside the working directory.`,
|
|
76
|
+
path: ['routeFile'],
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// ----------------------------------------------------------- result schemas
|
|
81
|
+
const reviewFindingSchema = z.object({
|
|
82
|
+
severity: z.enum(['BLOCKER', 'MAJOR', 'MINOR']),
|
|
83
|
+
confirmed: z.boolean().describe("True only when you read the line or pixel yourself and it is really there. When unsure, file it MINOR instead of guessing."),
|
|
84
|
+
location: z.string().describe("Where it is: the region of the screen, and the file:line when you verified one."),
|
|
85
|
+
observed: z.string().describe("What the image shows. This is the first thing the reader sees, so describe the image, not the rule."),
|
|
86
|
+
rule: z.string().describe("The rule or contract this violates, cited as the instructions cite it."),
|
|
87
|
+
fix: z.string(),
|
|
88
|
+
});
|
|
89
|
+
export const screenReviewResultSchema = z.object({
|
|
90
|
+
verdict: z.enum(['APPROVE', 'REQUEST_CHANGES']),
|
|
91
|
+
screens: z.array(z.object({
|
|
92
|
+
file: z.string().describe("The image path you were given, copied exactly."),
|
|
93
|
+
subject: z.string().describe("Which screen and state this image shows."),
|
|
94
|
+
route_file: z.string().describe("Repo-relative path of the route or screen source file this image shows, chosen from the changed files when one fits. Empty string when you genuinely cannot tell."),
|
|
95
|
+
inventory: z.array(z.string()).describe("Every control, label and region visible in this image. Enumerate before judging."),
|
|
96
|
+
findings: z.array(reviewFindingSchema),
|
|
97
|
+
})),
|
|
98
|
+
cross_screen_findings: z.array(reviewFindingSchema),
|
|
99
|
+
summary: z.string(),
|
|
100
|
+
});
|
|
101
|
+
export const screenPlanResultSchema = z.object({
|
|
102
|
+
route_file: z.string(),
|
|
103
|
+
controls: z.array(z.object({
|
|
104
|
+
control: z.string(),
|
|
105
|
+
primitive: z.string(),
|
|
106
|
+
placement: z.string(),
|
|
107
|
+
promoted: z.boolean(),
|
|
108
|
+
verb_today: z.string(),
|
|
109
|
+
verb_per_rule: z.string(),
|
|
110
|
+
operation: z.string(),
|
|
111
|
+
capability: z.string(),
|
|
112
|
+
scope: z.string(),
|
|
113
|
+
})),
|
|
114
|
+
top_slot_priority: z.array(z.string()),
|
|
115
|
+
hand_rolls_to_delete: z.array(z.object({ line: z.string(), primitive: z.string() })),
|
|
116
|
+
notes: z.string(),
|
|
117
|
+
});
|
|
118
|
+
export const SCREEN_REVIEW_RESULT_JSON_SCHEMA = toAgyJsonSchema(screenReviewResultSchema);
|
|
119
|
+
export const SCREEN_PLAN_RESULT_JSON_SCHEMA = toAgyJsonSchema(screenPlanResultSchema);
|
|
120
|
+
const SCHEMA_TEXT = {
|
|
121
|
+
review: JSON.stringify(SCREEN_REVIEW_RESULT_JSON_SCHEMA),
|
|
122
|
+
plan: JSON.stringify(SCREEN_PLAN_RESULT_JSON_SCHEMA),
|
|
123
|
+
};
|
|
124
|
+
// ------------------------------------------------------------------- prompt
|
|
125
|
+
export function buildScreenReviewPrompt(config) {
|
|
126
|
+
// The heading is explicit and always present: a reviewer checklist that files
|
|
127
|
+
// "no composition contract" as a finding must be able to see that one WAS
|
|
128
|
+
// supplied (or that none was) rather than infer it from silence.
|
|
129
|
+
const contextSection = `\n## Context supplied by the caller (composition contract, changed files)\n` +
|
|
130
|
+
`${config.context?.trim() || 'No context supplied.'}\n`;
|
|
131
|
+
if (config.mode === 'plan') {
|
|
132
|
+
return `# Screen plan
|
|
133
|
+
|
|
134
|
+
Read this route file and inventory the actions it exposes. There is no screenshot and no verdict: this runs before anything is built.
|
|
135
|
+
|
|
136
|
+
@${config.routeFile}
|
|
137
|
+
|
|
138
|
+
## Instructions
|
|
139
|
+
${config.instructions}
|
|
140
|
+
${contextSection}## Contract
|
|
141
|
+
- Cover this route only. Do not wander into other routes or shared components except to name the primitive a control should use.
|
|
142
|
+
- Every control that is visible or reachable on this route gets a row, including ones hidden behind a menu.
|
|
143
|
+
- Your answer is ONLY the schema JSON. No prose before or after it, no markdown fences.`;
|
|
144
|
+
}
|
|
145
|
+
const changed = config.changedRoutes ?? [];
|
|
146
|
+
const changedSection = changed.length > 0
|
|
147
|
+
? `\n## Changed files in this diff\n${changed.map(route => `- ${route}`).join('\n')}\n`
|
|
148
|
+
: '\n';
|
|
149
|
+
const imageRefs = (config.images ?? []).map(image => `@${image}`).join('\n');
|
|
150
|
+
return `# Screen review
|
|
151
|
+
|
|
152
|
+
Open every image below before reading any code. You are the second pair of eyes on frames someone else captured; the caller never opens them, so every judgement must be grounded in a sentence about what an image shows.
|
|
153
|
+
|
|
154
|
+
${imageRefs}
|
|
155
|
+
|
|
156
|
+
## Instructions
|
|
157
|
+
${config.instructions}
|
|
158
|
+
${contextSection}${changedSection}## Contract
|
|
159
|
+
- Enumerate what is in each image (every control, label and region) BEFORE judging it. Fill "inventory" first.
|
|
160
|
+
- Set each screen's "route_file" to the repo-relative path of the route or screen source file that image shows, choosing from the changed files above when one of them fits. Use "" only when you genuinely cannot tell — the caller uses this to check that every changed screen has a screenshot.
|
|
161
|
+
- Each finding's "observed" clause describes what the image shows; "rule" cites the rule it breaks.
|
|
162
|
+
- Set "confirmed": true only when you read the line or pixel yourself and it is really there. When unsure, file it MINOR.
|
|
163
|
+
- One "screens" entry per image above, and set its "file" to that image's absolute path copied verbatim from the @ line — character for character, no renaming, no relative path, no basename. The caller matches your entries back to the paths it gave you.
|
|
164
|
+
- If you could not open an image, say so in "summary" and leave it out of "screens".
|
|
165
|
+
- Your answer is ONLY the schema JSON. No prose before or after it, no markdown fences, no image data, no base64.`;
|
|
166
|
+
}
|
|
167
|
+
function normalizeRoute(route) {
|
|
168
|
+
return route.trim().replace(/\\/g, '/').replace(/^\.\//, '').replace(/^\/+/, '');
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* A reported route_file claims a changed file when it names that exact path, or
|
|
172
|
+
* is an absolute/longer spelling of it. A TRUNCATED report is never accepted:
|
|
173
|
+
* `app/orders.tsx` would otherwise claim both `apps/admin/app/orders.tsx` and
|
|
174
|
+
* `apps/customer/app/orders.tsx`, letting one image cover two changed screens.
|
|
175
|
+
*/
|
|
176
|
+
function claimsRoute(routeFile, changedRoute) {
|
|
177
|
+
const reported = normalizeRoute(routeFile);
|
|
178
|
+
const changed = normalizeRoute(changedRoute);
|
|
179
|
+
if (!reported || !changed)
|
|
180
|
+
return false;
|
|
181
|
+
return reported === changed || reported.endsWith(`/${changed}`);
|
|
182
|
+
}
|
|
183
|
+
// git paths are repo-relative, so `app/orders.tsx` has no leading slash to match on.
|
|
184
|
+
function isUnderDirectory(route, directory) {
|
|
185
|
+
return `/${normalizeRoute(route)}`.includes(`/${directory}/`);
|
|
186
|
+
}
|
|
187
|
+
/** Gemini's verdict is advisory; unconfirmed MAJORs are downgraded, unreviewed images always block. */
|
|
188
|
+
export function deriveReviewVerdict(result, images, changedRoutes = []) {
|
|
189
|
+
const reasons = [];
|
|
190
|
+
const warnings = [];
|
|
191
|
+
let downgraded = 0;
|
|
192
|
+
const allFindings = [
|
|
193
|
+
...result.screens.flatMap(screen => screen.findings.map(finding => ({ ...finding, where: screen.file }))),
|
|
194
|
+
...result.cross_screen_findings.map(finding => ({ ...finding, where: 'cross-screen' })),
|
|
195
|
+
];
|
|
196
|
+
for (const finding of allFindings) {
|
|
197
|
+
if (finding.severity === 'BLOCKER') {
|
|
198
|
+
reasons.push(`BLOCKER (${finding.where}): ${finding.observed}`);
|
|
199
|
+
}
|
|
200
|
+
else if (finding.severity === 'MAJOR' && finding.confirmed) {
|
|
201
|
+
reasons.push(`MAJOR confirmed (${finding.where}): ${finding.observed}`);
|
|
202
|
+
}
|
|
203
|
+
else if (finding.severity === 'MAJOR') {
|
|
204
|
+
downgraded += 1;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Compare resolved paths: Gemini may echo a realpath'd or ./-stripped
|
|
208
|
+
// spelling of the same image, and treating that as "not reviewed" would fail
|
|
209
|
+
// a review that actually happened.
|
|
210
|
+
const reviewedFiles = new Map(result.screens.map(screen => [realpathOfExistingPrefix(screen.file), screen.file]));
|
|
211
|
+
const unreviewed = images.filter(image => !reviewedFiles.has(realpathOfExistingPrefix(image)));
|
|
212
|
+
for (const image of unreviewed) {
|
|
213
|
+
reasons.push(`not reviewed: ${image}`);
|
|
214
|
+
}
|
|
215
|
+
const imageKeys = new Set(images.map(realpathOfExistingPrefix));
|
|
216
|
+
const unknownFiles = [...reviewedFiles]
|
|
217
|
+
.filter(([key]) => !imageKeys.has(key))
|
|
218
|
+
.map(([, reported]) => reported);
|
|
219
|
+
// Partial screenshot coverage is as unreviewed as no screenshot at all.
|
|
220
|
+
const coverage = changedRoutes.map(route => ({
|
|
221
|
+
route,
|
|
222
|
+
image: result.screens.find(screen => claimsRoute(screen.route_file, route))?.file ?? null,
|
|
223
|
+
}));
|
|
224
|
+
for (const entry of coverage.filter(entry => !entry.image)) {
|
|
225
|
+
if (isUnderDirectory(entry.route, 'app')) {
|
|
226
|
+
reasons.push(`no evidence for changed screen ${entry.route}`);
|
|
227
|
+
}
|
|
228
|
+
else if (isUnderDirectory(entry.route, 'components')) {
|
|
229
|
+
warnings.push(`changed component with no frame showing it: ${entry.route}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
verdict: reasons.length > 0 ? 'REQUEST_CHANGES' : 'APPROVE',
|
|
234
|
+
reported: result.verdict,
|
|
235
|
+
reasons,
|
|
236
|
+
unreviewed,
|
|
237
|
+
unknownFiles,
|
|
238
|
+
downgraded,
|
|
239
|
+
coverage,
|
|
240
|
+
warnings,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
// ------------------------------------------------------------------ reports
|
|
244
|
+
function renderFinding(finding) {
|
|
245
|
+
const severity = finding.severity === 'MAJOR' && !finding.confirmed
|
|
246
|
+
? 'MINOR (unconfirmed, downgraded)'
|
|
247
|
+
: finding.severity;
|
|
248
|
+
return `${severity} — ${finding.observed}\n location: ${finding.location}\n rule: ${finding.rule}\n fix: ${finding.fix}`;
|
|
249
|
+
}
|
|
250
|
+
export function formatScreenReviewReport(input) {
|
|
251
|
+
const { envelope, result, decision } = input;
|
|
252
|
+
const headline = decision.verdict === decision.reported
|
|
253
|
+
? `# Screen review: ${decision.verdict}`
|
|
254
|
+
: `# Screen review: ${decision.verdict} (Gemini reported ${decision.reported})`;
|
|
255
|
+
const parts = [];
|
|
256
|
+
if (envelope.conversation_id)
|
|
257
|
+
parts.push(formatConversationLine(envelope.conversation_id));
|
|
258
|
+
parts.push(headline);
|
|
259
|
+
parts.push(formatAgyUsageLine(envelope));
|
|
260
|
+
parts.push(section('Why', bulletList(decision.reasons)));
|
|
261
|
+
if (decision.coverage.length > 0) {
|
|
262
|
+
parts.push(section('Screenshot coverage', decision.coverage
|
|
263
|
+
.map(entry => `- ${entry.route} → ${entry.image ?? 'MISSING'}`)
|
|
264
|
+
.join('\n')));
|
|
265
|
+
}
|
|
266
|
+
for (const screen of result.screens) {
|
|
267
|
+
parts.push(section(`${screen.subject}`, [
|
|
268
|
+
`file: ${screen.file}`,
|
|
269
|
+
screen.route_file ? `route: ${screen.route_file}` : 'route: not identified',
|
|
270
|
+
`inventory: ${screen.inventory.join(', ') || 'none reported'}`,
|
|
271
|
+
`findings:`,
|
|
272
|
+
bulletList(screen.findings.map(renderFinding)),
|
|
273
|
+
].join('\n')));
|
|
274
|
+
}
|
|
275
|
+
parts.push(section('Cross-screen findings', bulletList(result.cross_screen_findings.map(renderFinding))));
|
|
276
|
+
parts.push(section('Summary', result.summary || '- not reported'));
|
|
277
|
+
const notes = [...decision.warnings];
|
|
278
|
+
if (decision.downgraded > 0) {
|
|
279
|
+
notes.push(`${decision.downgraded} unconfirmed MAJOR finding(s) shown as MINOR`);
|
|
280
|
+
}
|
|
281
|
+
if (decision.unknownFiles.length > 0) {
|
|
282
|
+
notes.push(`answer named images that were not supplied: ${decision.unknownFiles.join(', ')}`);
|
|
283
|
+
}
|
|
284
|
+
if (input.deniedActions) {
|
|
285
|
+
notes.push(`agy denied actions: ${input.deniedActions}`);
|
|
286
|
+
}
|
|
287
|
+
if (notes.length > 0)
|
|
288
|
+
parts.push(section('Notes', bulletList(notes)));
|
|
289
|
+
const workingTreeSection = formatWorkingTreeSection(input.workingTree);
|
|
290
|
+
if (workingTreeSection)
|
|
291
|
+
parts.push(workingTreeSection);
|
|
292
|
+
return parts.join('\n\n');
|
|
293
|
+
}
|
|
294
|
+
const PLAN_COLUMNS = [
|
|
295
|
+
'control', 'primitive', 'placement', 'promoted', 'verb today', 'verb per rule',
|
|
296
|
+
'operation', 'capability', 'scope',
|
|
297
|
+
];
|
|
298
|
+
export function formatScreenPlanReport(input) {
|
|
299
|
+
const { envelope, result, routeFile } = input;
|
|
300
|
+
const rows = result.controls.map(control => `| ${[
|
|
301
|
+
control.control, control.primitive, control.placement, String(control.promoted),
|
|
302
|
+
control.verb_today, control.verb_per_rule, control.operation, control.capability, control.scope,
|
|
303
|
+
].join(' | ')} |`);
|
|
304
|
+
const table = [
|
|
305
|
+
`| ${PLAN_COLUMNS.join(' | ')} |`,
|
|
306
|
+
`|${PLAN_COLUMNS.map(() => '---').join('|')}|`,
|
|
307
|
+
...rows,
|
|
308
|
+
].join('\n');
|
|
309
|
+
const parts = [];
|
|
310
|
+
if (envelope.conversation_id)
|
|
311
|
+
parts.push(formatConversationLine(envelope.conversation_id));
|
|
312
|
+
parts.push(`# Screen plan: ${routeFile}`);
|
|
313
|
+
parts.push(formatAgyUsageLine(envelope));
|
|
314
|
+
parts.push(section('Controls', result.controls.length > 0 ? table : '- none reported'));
|
|
315
|
+
parts.push(section('Top slot priority', bulletList(result.top_slot_priority)));
|
|
316
|
+
parts.push(section('Hand-rolls to delete', bulletList(result.hand_rolls_to_delete.map(item => `${item.line} → ${item.primitive}`))));
|
|
317
|
+
parts.push(section('Notes', result.notes || '- none'));
|
|
318
|
+
const warnings = [];
|
|
319
|
+
if (result.route_file && path.resolve(result.route_file) !== path.resolve(routeFile)) {
|
|
320
|
+
warnings.push(`answer named route_file '${result.route_file}' but the request was '${routeFile}'`);
|
|
321
|
+
}
|
|
322
|
+
if (input.deniedActions) {
|
|
323
|
+
warnings.push(`agy denied actions: ${input.deniedActions}`);
|
|
324
|
+
}
|
|
325
|
+
if (warnings.length > 0)
|
|
326
|
+
parts.push(section('Warnings', bulletList(warnings)));
|
|
327
|
+
const workingTreeSection = formatWorkingTreeSection(input.workingTree);
|
|
328
|
+
if (workingTreeSection)
|
|
329
|
+
parts.push(workingTreeSection);
|
|
330
|
+
return parts.join('\n\n');
|
|
331
|
+
}
|
|
332
|
+
// ------------------------------------------------------------------ execute
|
|
333
|
+
export const screenReviewTool = {
|
|
334
|
+
name: "screen-review",
|
|
335
|
+
description: "Delegate screen review to Gemini: in 'review' mode it opens the given PNGs, inventories what each shows, and returns findings with an APPROVE / REQUEST_CHANGES verdict; in 'plan' mode it inventories the controls of a route file before anything is built. Text only — no image reaches the caller's context.",
|
|
336
|
+
zodSchema: screenReviewArgsSchema,
|
|
337
|
+
prompt: {
|
|
338
|
+
description: "Have Gemini judge captured screens against a reviewer prompt (review mode), or inventory a route file's controls before implementation (plan mode).",
|
|
339
|
+
},
|
|
340
|
+
category: 'gemini',
|
|
341
|
+
annotations: {
|
|
342
|
+
title: "Screen Review",
|
|
343
|
+
readOnlyHint: true,
|
|
344
|
+
openWorldHint: true,
|
|
345
|
+
},
|
|
346
|
+
execute: async (args, onProgress) => {
|
|
347
|
+
const input = screenReviewArgsSchema.parse(args);
|
|
348
|
+
const workingDirectory = resolveWorkingDirectory(input.workingDirectory);
|
|
349
|
+
const isPlan = input.mode === 'plan';
|
|
350
|
+
// agy resolves an @reference only under a workspace directory, so every
|
|
351
|
+
// image's parent has to be added explicitly.
|
|
352
|
+
const imageDirs = [...new Set((input.images ?? []).map(image => path.dirname(image)))];
|
|
353
|
+
const before = input.yolo ? await snapshotWorkingTree(workingDirectory) : null;
|
|
354
|
+
const afterWorkingTree = async () => diffWorkingTree(before, input.yolo ? await snapshotWorkingTree(workingDirectory) : null);
|
|
355
|
+
let envelope;
|
|
356
|
+
try {
|
|
357
|
+
envelope = await executeAgyJson(buildScreenReviewPrompt({
|
|
358
|
+
mode: input.mode,
|
|
359
|
+
instructions: input.instructions,
|
|
360
|
+
context: input.context,
|
|
361
|
+
images: input.images,
|
|
362
|
+
routeFile: input.routeFile,
|
|
363
|
+
changedRoutes: input.changedRoutes,
|
|
364
|
+
}), {
|
|
365
|
+
model: input.model,
|
|
366
|
+
yolo: input.yolo,
|
|
367
|
+
printTimeout: input.printTimeout,
|
|
368
|
+
conversationId: input.conversationId,
|
|
369
|
+
includeDirectories: [workingDirectory, ...imageDirs],
|
|
370
|
+
cwd: workingDirectory,
|
|
371
|
+
jsonSchema: isPlan ? SCHEMA_TEXT.plan : SCHEMA_TEXT.review,
|
|
372
|
+
noCache: true,
|
|
373
|
+
}, onProgress);
|
|
374
|
+
}
|
|
375
|
+
catch (error) {
|
|
376
|
+
// A timeout or CLI failure can land after Gemini has used the shell yolo
|
|
377
|
+
// gave it, so the warning travels with the error.
|
|
378
|
+
failWithWorkingTree(error, await afterWorkingTree());
|
|
379
|
+
}
|
|
380
|
+
const deniedActions = deniedActionsSummary(envelope);
|
|
381
|
+
// Both modes and both exits: yolo gave Gemini a shell either way.
|
|
382
|
+
const workingTree = await afterWorkingTree();
|
|
383
|
+
if (isPlan) {
|
|
384
|
+
const parsed = screenPlanResultSchema.safeParse(envelope.structured_output);
|
|
385
|
+
if (!parsed.success) {
|
|
386
|
+
return [
|
|
387
|
+
renderUnparsableEnvelope(envelope, '# Screen plan: no usable answer', formatZodIssues(parsed.error)),
|
|
388
|
+
formatWorkingTreeSection(workingTree),
|
|
389
|
+
].filter(Boolean).join('\n\n');
|
|
390
|
+
}
|
|
391
|
+
return formatScreenPlanReport({
|
|
392
|
+
envelope,
|
|
393
|
+
result: parsed.data,
|
|
394
|
+
routeFile: input.routeFile,
|
|
395
|
+
deniedActions,
|
|
396
|
+
workingTree,
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
const parsed = screenReviewResultSchema.safeParse(envelope.structured_output);
|
|
400
|
+
if (!parsed.success) {
|
|
401
|
+
return [
|
|
402
|
+
renderUnparsableEnvelope(envelope, '# Screen review: no usable answer', formatZodIssues(parsed.error)),
|
|
403
|
+
formatWorkingTreeSection(workingTree),
|
|
404
|
+
].filter(Boolean).join('\n\n');
|
|
405
|
+
}
|
|
406
|
+
return formatScreenReviewReport({
|
|
407
|
+
envelope,
|
|
408
|
+
result: parsed.data,
|
|
409
|
+
decision: deriveReviewVerdict(parsed.data, input.images ?? [], input.changedRoutes ?? []),
|
|
410
|
+
deniedActions,
|
|
411
|
+
workingTree,
|
|
412
|
+
});
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
//# sourceMappingURL=screen-review.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen-review.tool.js","sourceRoot":"","sources":["../../src/tools/screen-review.tool.ts"],"names":[],"mappings":"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"}
|