@equinor/fusion-framework-cli-plugin-copilot 1.0.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/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/dist/esm/commands/app/command.js +176 -0
- package/dist/esm/commands/app/command.js.map +1 -0
- package/dist/esm/commands/app/eval.js +92 -0
- package/dist/esm/commands/app/eval.js.map +1 -0
- package/dist/esm/commands/app/format.js +93 -0
- package/dist/esm/commands/app/format.js.map +1 -0
- package/dist/esm/commands/app/login.js +71 -0
- package/dist/esm/commands/app/login.js.map +1 -0
- package/dist/esm/commands/app/prompts/execute-step.prompt.js +44 -0
- package/dist/esm/commands/app/prompts/execute-step.prompt.js.map +1 -0
- package/dist/esm/commands/app/prompts/judge.prompt.js +116 -0
- package/dist/esm/commands/app/prompts/judge.prompt.js.map +1 -0
- package/dist/esm/commands/app/prompts/plan.prompt.js +47 -0
- package/dist/esm/commands/app/prompts/plan.prompt.js.map +1 -0
- package/dist/esm/commands/app/prompts/step.prompt.js +42 -0
- package/dist/esm/commands/app/prompts/step.prompt.js.map +1 -0
- package/dist/esm/commands/app/prompts/system.dev-server.prompt.js +21 -0
- package/dist/esm/commands/app/prompts/system.dev-server.prompt.js.map +1 -0
- package/dist/esm/commands/app/prompts/system.prompt.js +77 -0
- package/dist/esm/commands/app/prompts/system.prompt.js.map +1 -0
- package/dist/esm/commands/app/server.js +83 -0
- package/dist/esm/commands/app/server.js.map +1 -0
- package/dist/esm/commands/app/session-logger.js +171 -0
- package/dist/esm/commands/app/session-logger.js.map +1 -0
- package/dist/esm/commands/app/tools/click.js +27 -0
- package/dist/esm/commands/app/tools/click.js.map +1 -0
- package/dist/esm/commands/app/tools/errors.js +24 -0
- package/dist/esm/commands/app/tools/errors.js.map +1 -0
- package/dist/esm/commands/app/tools/eval-js.js +36 -0
- package/dist/esm/commands/app/tools/eval-js.js.map +1 -0
- package/dist/esm/commands/app/tools/fill.js +28 -0
- package/dist/esm/commands/app/tools/fill.js.map +1 -0
- package/dist/esm/commands/app/tools/find.js +44 -0
- package/dist/esm/commands/app/tools/find.js.map +1 -0
- package/dist/esm/commands/app/tools/get-styles.js +36 -0
- package/dist/esm/commands/app/tools/get-styles.js.map +1 -0
- package/dist/esm/commands/app/tools/get-url.js +24 -0
- package/dist/esm/commands/app/tools/get-url.js.map +1 -0
- package/dist/esm/commands/app/tools/go-back.js +15 -0
- package/dist/esm/commands/app/tools/go-back.js.map +1 -0
- package/dist/esm/commands/app/tools/hover.js +24 -0
- package/dist/esm/commands/app/tools/hover.js.map +1 -0
- package/dist/esm/commands/app/tools/index.js +32 -0
- package/dist/esm/commands/app/tools/index.js.map +1 -0
- package/dist/esm/commands/app/tools/navigate.js +31 -0
- package/dist/esm/commands/app/tools/navigate.js.map +1 -0
- package/dist/esm/commands/app/tools/press-key.js +24 -0
- package/dist/esm/commands/app/tools/press-key.js.map +1 -0
- package/dist/esm/commands/app/tools/read-file.js +98 -0
- package/dist/esm/commands/app/tools/read-file.js.map +1 -0
- package/dist/esm/commands/app/tools/registry.js +34 -0
- package/dist/esm/commands/app/tools/registry.js.map +1 -0
- package/dist/esm/commands/app/tools/reload.js +15 -0
- package/dist/esm/commands/app/tools/reload.js.map +1 -0
- package/dist/esm/commands/app/tools/screenshot.js +133 -0
- package/dist/esm/commands/app/tools/screenshot.js.map +1 -0
- package/dist/esm/commands/app/tools/scroll.js +41 -0
- package/dist/esm/commands/app/tools/scroll.js.map +1 -0
- package/dist/esm/commands/app/tools/select.js +25 -0
- package/dist/esm/commands/app/tools/select.js.map +1 -0
- package/dist/esm/commands/app/tools/snapshot.js +24 -0
- package/dist/esm/commands/app/tools/snapshot.js.map +1 -0
- package/dist/esm/commands/app/tools/type-text.js +29 -0
- package/dist/esm/commands/app/tools/type-text.js.map +1 -0
- package/dist/esm/commands/app/tools/types.js +2 -0
- package/dist/esm/commands/app/tools/types.js.map +1 -0
- package/dist/esm/commands/app/tools/wait.js +39 -0
- package/dist/esm/commands/app/tools/wait.js.map +1 -0
- package/dist/esm/commands/app/tools/write-file.js +98 -0
- package/dist/esm/commands/app/tools/write-file.js.map +1 -0
- package/dist/esm/commands/app/types.js +2 -0
- package/dist/esm/commands/app/types.js.map +1 -0
- package/dist/esm/eval-resolve.js +83 -0
- package/dist/esm/eval-resolve.js.map +1 -0
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/utils/agent-browser.js +67 -0
- package/dist/esm/utils/agent-browser.js.map +1 -0
- package/dist/esm/utils/browser-poll.js +26 -0
- package/dist/esm/utils/browser-poll.js.map +1 -0
- package/dist/esm/utils/daemon.js +83 -0
- package/dist/esm/utils/daemon.js.map +1 -0
- package/dist/esm/utils/index.js +6 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/esm/utils/process.js +30 -0
- package/dist/esm/utils/process.js.map +1 -0
- package/dist/esm/utils/server.js +65 -0
- package/dist/esm/utils/server.js.map +1 -0
- package/dist/esm/version.js +3 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/commands/app/command.d.ts +7 -0
- package/dist/types/commands/app/eval.d.ts +9 -0
- package/dist/types/commands/app/format.d.ts +14 -0
- package/dist/types/commands/app/login.d.ts +14 -0
- package/dist/types/commands/app/prompts/execute-step.prompt.d.ts +13 -0
- package/dist/types/commands/app/prompts/judge.prompt.d.ts +15 -0
- package/dist/types/commands/app/prompts/plan.prompt.d.ts +13 -0
- package/dist/types/commands/app/prompts/step.prompt.d.ts +12 -0
- package/dist/types/commands/app/prompts/system.dev-server.prompt.d.ts +12 -0
- package/dist/types/commands/app/prompts/system.prompt.d.ts +12 -0
- package/dist/types/commands/app/server.d.ts +26 -0
- package/dist/types/commands/app/session-logger.d.ts +14 -0
- package/dist/types/commands/app/tools/click.d.ts +9 -0
- package/dist/types/commands/app/tools/errors.d.ts +9 -0
- package/dist/types/commands/app/tools/eval-js.d.ts +13 -0
- package/dist/types/commands/app/tools/fill.d.ts +9 -0
- package/dist/types/commands/app/tools/find.d.ts +9 -0
- package/dist/types/commands/app/tools/get-styles.d.ts +13 -0
- package/dist/types/commands/app/tools/get-url.d.ts +9 -0
- package/dist/types/commands/app/tools/go-back.d.ts +9 -0
- package/dist/types/commands/app/tools/hover.d.ts +9 -0
- package/dist/types/commands/app/tools/index.d.ts +9 -0
- package/dist/types/commands/app/tools/navigate.d.ts +9 -0
- package/dist/types/commands/app/tools/press-key.d.ts +9 -0
- package/dist/types/commands/app/tools/read-file.d.ts +13 -0
- package/dist/types/commands/app/tools/registry.d.ts +28 -0
- package/dist/types/commands/app/tools/reload.d.ts +9 -0
- package/dist/types/commands/app/tools/screenshot.d.ts +9 -0
- package/dist/types/commands/app/tools/scroll.d.ts +9 -0
- package/dist/types/commands/app/tools/select.d.ts +9 -0
- package/dist/types/commands/app/tools/snapshot.d.ts +9 -0
- package/dist/types/commands/app/tools/type-text.d.ts +9 -0
- package/dist/types/commands/app/tools/types.d.ts +12 -0
- package/dist/types/commands/app/tools/wait.d.ts +9 -0
- package/dist/types/commands/app/tools/write-file.d.ts +19 -0
- package/dist/types/commands/app/types.d.ts +68 -0
- package/dist/types/eval-resolve.d.ts +31 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/utils/agent-browser.d.ts +26 -0
- package/dist/types/utils/browser-poll.d.ts +9 -0
- package/dist/types/utils/daemon.d.ts +16 -0
- package/dist/types/utils/index.d.ts +5 -0
- package/dist/types/utils/process.d.ts +21 -0
- package/dist/types/utils/server.d.ts +26 -0
- package/dist/types/version.d.ts +1 -0
- package/package.json +57 -0
- package/src/commands/app/command.ts +204 -0
- package/src/commands/app/eval.ts +114 -0
- package/src/commands/app/format.ts +110 -0
- package/src/commands/app/login.ts +92 -0
- package/src/commands/app/prompts/execute-step.prompt.ts +48 -0
- package/src/commands/app/prompts/judge.prompt.ts +121 -0
- package/src/commands/app/prompts/plan.prompt.ts +48 -0
- package/src/commands/app/prompts/step.prompt.ts +45 -0
- package/src/commands/app/prompts/system.dev-server.prompt.ts +22 -0
- package/src/commands/app/prompts/system.prompt.ts +78 -0
- package/src/commands/app/server.ts +105 -0
- package/src/commands/app/session-logger.ts +187 -0
- package/src/commands/app/tools/click.ts +28 -0
- package/src/commands/app/tools/errors.ts +26 -0
- package/src/commands/app/tools/eval-js.ts +40 -0
- package/src/commands/app/tools/fill.ts +29 -0
- package/src/commands/app/tools/find.ts +49 -0
- package/src/commands/app/tools/get-styles.ts +40 -0
- package/src/commands/app/tools/get-url.ts +26 -0
- package/src/commands/app/tools/go-back.ts +16 -0
- package/src/commands/app/tools/hover.ts +25 -0
- package/src/commands/app/tools/index.ts +57 -0
- package/src/commands/app/tools/navigate.ts +32 -0
- package/src/commands/app/tools/press-key.ts +25 -0
- package/src/commands/app/tools/read-file.ts +113 -0
- package/src/commands/app/tools/registry.ts +38 -0
- package/src/commands/app/tools/reload.ts +16 -0
- package/src/commands/app/tools/screenshot.ts +168 -0
- package/src/commands/app/tools/scroll.ts +45 -0
- package/src/commands/app/tools/select.ts +26 -0
- package/src/commands/app/tools/snapshot.ts +27 -0
- package/src/commands/app/tools/type-text.ts +30 -0
- package/src/commands/app/tools/types.ts +15 -0
- package/src/commands/app/tools/wait.ts +43 -0
- package/src/commands/app/tools/write-file.ts +104 -0
- package/src/commands/app/types.ts +76 -0
- package/src/eval-resolve.ts +113 -0
- package/src/index.ts +20 -0
- package/src/utils/agent-browser.ts +66 -0
- package/src/utils/browser-poll.ts +27 -0
- package/src/utils/daemon.ts +84 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/process.ts +33 -0
- package/src/utils/server.ts +66 -0
- package/src/version.ts +2 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { basename, extname, isAbsolute, join } from 'node:path';
|
|
3
|
+
/** Image extensions that should be returned as vision-capable binary results. */
|
|
4
|
+
const IMAGE_EXTENSIONS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.webp']);
|
|
5
|
+
/** MIME types for supported image formats. */
|
|
6
|
+
const IMAGE_MIME = {
|
|
7
|
+
'.png': 'image/png',
|
|
8
|
+
'.jpg': 'image/jpeg',
|
|
9
|
+
'.jpeg': 'image/jpeg',
|
|
10
|
+
'.gif': 'image/gif',
|
|
11
|
+
'.webp': 'image/webp',
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Resolves a path within a base directory, rejecting escapes.
|
|
15
|
+
*
|
|
16
|
+
* @param baseDir - The allowed root directory
|
|
17
|
+
* @param input - The user-provided path (relative or absolute within baseDir)
|
|
18
|
+
* @returns The resolved absolute path
|
|
19
|
+
* @throws {Error} When the path escapes the base directory
|
|
20
|
+
*/
|
|
21
|
+
function resolveSafe(baseDir, input) {
|
|
22
|
+
const relative = isAbsolute(input)
|
|
23
|
+
? input.startsWith(baseDir + '/') || input.startsWith(baseDir + '\\')
|
|
24
|
+
? input.slice(baseDir.length + 1)
|
|
25
|
+
: (() => {
|
|
26
|
+
throw new Error(`Absolute path outside output directory: ${input}`);
|
|
27
|
+
})()
|
|
28
|
+
: input;
|
|
29
|
+
const resolved = join(baseDir, relative);
|
|
30
|
+
if (!resolved.startsWith(baseDir)) {
|
|
31
|
+
throw new Error(`Path escapes the output directory: ${input}`);
|
|
32
|
+
}
|
|
33
|
+
return resolved;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates the read-file tool so the judge agent can inspect evidence artifacts.
|
|
37
|
+
*
|
|
38
|
+
* For image files the tool returns a `ToolBinaryResult` with base64-encoded
|
|
39
|
+
* data that multimodal models can view directly. Text files are returned
|
|
40
|
+
* as plain text. Directories return a listing of their contents.
|
|
41
|
+
*
|
|
42
|
+
* @param baseDir - The run output directory that scopes all reads
|
|
43
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
44
|
+
* @returns Copilot tool definition for reading evidence files
|
|
45
|
+
*/
|
|
46
|
+
export function createReadFileTool(baseDir, defineTool) {
|
|
47
|
+
return defineTool('read_file', {
|
|
48
|
+
description: 'Read a file or list a directory from the output directory. ' +
|
|
49
|
+
'Image files (png, jpg, jpeg, gif, webp) are returned as inline images the model can see. ' +
|
|
50
|
+
'Text files are returned as plain text. Directories return a file listing.',
|
|
51
|
+
parameters: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
path: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'File or directory path relative to the output directory (e.g. "evidence/step-hello.png" or "executions.jsonl")',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
required: ['path'],
|
|
60
|
+
},
|
|
61
|
+
handler: async (args) => {
|
|
62
|
+
const { path } = args;
|
|
63
|
+
const resolved = resolveSafe(baseDir, path);
|
|
64
|
+
if (!existsSync(resolved)) {
|
|
65
|
+
return `File not found: ${path}`;
|
|
66
|
+
}
|
|
67
|
+
const stat = statSync(resolved);
|
|
68
|
+
// ── Directory listing ──
|
|
69
|
+
if (stat.isDirectory()) {
|
|
70
|
+
const entries = readdirSync(resolved).sort();
|
|
71
|
+
return entries.length > 0
|
|
72
|
+
? `Directory ${path}/:\n${entries.join('\n')}`
|
|
73
|
+
: `Directory ${path}/ is empty`;
|
|
74
|
+
}
|
|
75
|
+
const ext = extname(resolved).toLowerCase();
|
|
76
|
+
// ── Image: return as binary vision result ──
|
|
77
|
+
if (IMAGE_EXTENSIONS.has(ext)) {
|
|
78
|
+
const mime = IMAGE_MIME[ext] ?? 'application/octet-stream';
|
|
79
|
+
return {
|
|
80
|
+
textResultForLlm: `Image file: ${path} (${mime}, ${stat.size} bytes). Inspect the attached image.`,
|
|
81
|
+
binaryResultsForLlm: [
|
|
82
|
+
{
|
|
83
|
+
data: readFileSync(resolved, 'base64'),
|
|
84
|
+
mimeType: mime,
|
|
85
|
+
type: 'image',
|
|
86
|
+
description: `Evidence artifact: ${basename(resolved)}`,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
resultType: 'success',
|
|
90
|
+
toolTelemetry: {},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// ── Text file ──
|
|
94
|
+
return readFileSync(resolved, 'utf-8');
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=read-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-file.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/read-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ordered collection of agent-browser tool registrations for a Copilot session.
|
|
3
|
+
*
|
|
4
|
+
* Tools are exposed to the model in insertion order. Use {@link addTools} to
|
|
5
|
+
* register multiple tools at once during session setup.
|
|
6
|
+
*/
|
|
7
|
+
export class AgentBrowserToolRegistry {
|
|
8
|
+
tools = [];
|
|
9
|
+
/**
|
|
10
|
+
* Adds a tool to the registry.
|
|
11
|
+
*
|
|
12
|
+
* @param tool - Tool definition created with the Copilot SDK `defineTool` helper
|
|
13
|
+
*/
|
|
14
|
+
addTool(tool) {
|
|
15
|
+
this.tools.push(tool);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Adds multiple tools to the registry in order.
|
|
19
|
+
*
|
|
20
|
+
* @param tools - Tool definitions created with the Copilot SDK `defineTool` helper
|
|
21
|
+
*/
|
|
22
|
+
addTools(...tools) {
|
|
23
|
+
this.tools.push(...tools);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns a shallow copy of the registered tools in insertion order.
|
|
27
|
+
*
|
|
28
|
+
* @returns The registered Copilot SDK tool list
|
|
29
|
+
*/
|
|
30
|
+
getTools() {
|
|
31
|
+
return [...this.tools];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/registry.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAO,wBAAwB;IAClB,KAAK,GAAyB,EAAE,CAAC;IAElD;;;;OAIG;IACH,OAAO,CAAC,IAAkC;QACxC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,GAAG,KAA2B;QACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,QAAQ;QACN,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the page reload tool.
|
|
3
|
+
*
|
|
4
|
+
* @param context - Shared browser tool execution context
|
|
5
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
6
|
+
* @returns Copilot tool definition for reloading the current page
|
|
7
|
+
*/
|
|
8
|
+
export function createReloadTool(context, defineTool) {
|
|
9
|
+
return defineTool('browser_reload', {
|
|
10
|
+
description: 'Reload the current page.',
|
|
11
|
+
parameters: { type: 'object', properties: {} },
|
|
12
|
+
handler: async () => context.invoke(['reload']),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=reload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reload.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/reload.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgC,EAAE,UAAsB;IACvF,OAAO,UAAU,CAAC,gBAAgB,EAAE;QAClC,WAAW,EAAE,0BAA0B;QACvC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,UAAU,EAAE,EAAE,EAAE;QACvD,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC;KAChD,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { basename, extname, join, relative, resolve, sep } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the requested screenshot format to a supported CLI value.
|
|
5
|
+
*
|
|
6
|
+
* @param format - Optional model-provided image format
|
|
7
|
+
* @returns Validated format string, defaulting to `jpeg`
|
|
8
|
+
*/
|
|
9
|
+
function resolveScreenshotFormat(format) {
|
|
10
|
+
return format === 'png' ? 'png' : 'jpeg';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Ensures the screenshot artifact filename extension matches the selected image format.
|
|
14
|
+
*
|
|
15
|
+
* @param requestedPath - Optional model-provided filename
|
|
16
|
+
* @param format - Selected image format
|
|
17
|
+
* @returns Safe filename with the correct extension, or `undefined` when no path was provided
|
|
18
|
+
*/
|
|
19
|
+
function resolveScreenshotArtifactName(requestedPath, format) {
|
|
20
|
+
if (!requestedPath)
|
|
21
|
+
return undefined;
|
|
22
|
+
const fileName = basename(requestedPath);
|
|
23
|
+
const currentExtension = extname(fileName).toLowerCase();
|
|
24
|
+
const expectedExtension = format === 'jpeg' ? '.jpg' : '.png';
|
|
25
|
+
if (currentExtension === expectedExtension) {
|
|
26
|
+
return fileName;
|
|
27
|
+
}
|
|
28
|
+
if (currentExtension.length > 0) {
|
|
29
|
+
return `${fileName.slice(0, -currentExtension.length)}${expectedExtension}`;
|
|
30
|
+
}
|
|
31
|
+
return `${fileName}${expectedExtension}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolves an optional screenshot directory to a safe location within the eval evidence directory.
|
|
35
|
+
*
|
|
36
|
+
* @param evidenceDir - Base evidence directory for the current eval run
|
|
37
|
+
* @param requestedDirectory - Optional model-provided screenshot directory
|
|
38
|
+
* @returns Absolute screenshot directory constrained to the evidence directory tree
|
|
39
|
+
*/
|
|
40
|
+
function resolveScreenshotDirectory(evidenceDir, requestedDirectory) {
|
|
41
|
+
if (!requestedDirectory) {
|
|
42
|
+
return evidenceDir;
|
|
43
|
+
}
|
|
44
|
+
const resolvedDirectory = resolve(evidenceDir, requestedDirectory);
|
|
45
|
+
const relativeDirectory = relative(evidenceDir, resolvedDirectory);
|
|
46
|
+
const isOutsideEvidenceDirectory = relativeDirectory === '..' || relativeDirectory.startsWith(`..${sep}`);
|
|
47
|
+
return isOutsideEvidenceDirectory ? evidenceDir : resolvedDirectory;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Builds a binary screenshot tool result that multimodal models can inspect directly.
|
|
51
|
+
*
|
|
52
|
+
* @param screenshotPath - Saved screenshot artifact path
|
|
53
|
+
* @param format - Image format used for the screenshot
|
|
54
|
+
* @returns Tool result object containing both text and inline image data
|
|
55
|
+
*/
|
|
56
|
+
function buildScreenshotResult(screenshotPath, format) {
|
|
57
|
+
return {
|
|
58
|
+
textResultForLlm: `Saved screenshot to ${screenshotPath}. Inspect the attached image for visual evidence.`,
|
|
59
|
+
binaryResultsForLlm: [
|
|
60
|
+
{
|
|
61
|
+
data: readFileSync(screenshotPath, 'base64'),
|
|
62
|
+
mimeType: format === 'jpeg' ? 'image/jpeg' : 'image/png',
|
|
63
|
+
type: 'image',
|
|
64
|
+
description: `Screenshot artifact: ${basename(screenshotPath)}`,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
resultType: 'success',
|
|
68
|
+
toolTelemetry: {},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates the screenshot capture tool.
|
|
73
|
+
*
|
|
74
|
+
* @param context - Shared browser tool execution context
|
|
75
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
76
|
+
* @returns Copilot tool definition for saving an image screenshot and returning it to the model
|
|
77
|
+
*/
|
|
78
|
+
export function createScreenshotTool(context, defineTool) {
|
|
79
|
+
return defineTool('browser_screenshot', {
|
|
80
|
+
description: 'Capture a screenshot of the current page and return the image to the model. Use this for visual assertions such as colors, spacing, and layout.',
|
|
81
|
+
parameters: {
|
|
82
|
+
type: 'object',
|
|
83
|
+
properties: {
|
|
84
|
+
path: {
|
|
85
|
+
type: 'string',
|
|
86
|
+
description: 'Optional filename for the screenshot artifact (for example: "landing-page.jpg")',
|
|
87
|
+
},
|
|
88
|
+
annotate: {
|
|
89
|
+
type: 'boolean',
|
|
90
|
+
description: 'Overlay numbered labels on interactive elements in the screenshot.',
|
|
91
|
+
},
|
|
92
|
+
format: {
|
|
93
|
+
type: 'string',
|
|
94
|
+
description: 'Image format: "jpeg" (default) or "png"',
|
|
95
|
+
},
|
|
96
|
+
quality: {
|
|
97
|
+
type: 'number',
|
|
98
|
+
description: 'JPEG quality from 0-100. Recommended/default is 60 when format is "jpeg".',
|
|
99
|
+
},
|
|
100
|
+
screenshotDir: {
|
|
101
|
+
type: 'string',
|
|
102
|
+
description: 'Default screenshot output directory, scoped inside the eval evidence folder.',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
handler: async (args) => {
|
|
107
|
+
const { path, annotate, format, quality, screenshotDir } = args;
|
|
108
|
+
const screenshotFormat = resolveScreenshotFormat(format);
|
|
109
|
+
const screenshotDirectory = resolveScreenshotDirectory(context.outDir, screenshotDir);
|
|
110
|
+
mkdirSync(screenshotDirectory, { recursive: true });
|
|
111
|
+
const artifactName = resolveScreenshotArtifactName(path, screenshotFormat);
|
|
112
|
+
const screenshotPath = join(screenshotDirectory, artifactName ?? `screenshot-${Date.now()}.${screenshotFormat === 'jpeg' ? 'jpg' : 'png'}`);
|
|
113
|
+
const command = [
|
|
114
|
+
'screenshot',
|
|
115
|
+
'--screenshot-format',
|
|
116
|
+
screenshotFormat,
|
|
117
|
+
'--screenshot-dir',
|
|
118
|
+
screenshotDirectory,
|
|
119
|
+
];
|
|
120
|
+
if (annotate) {
|
|
121
|
+
command.push('--annotate');
|
|
122
|
+
}
|
|
123
|
+
if (screenshotFormat === 'jpeg') {
|
|
124
|
+
const screenshotQuality = Math.min(100, Math.max(0, quality ?? 60));
|
|
125
|
+
command.push('--screenshot-quality', String(screenshotQuality));
|
|
126
|
+
}
|
|
127
|
+
command.push(screenshotPath);
|
|
128
|
+
context.invoke(command, 60_000);
|
|
129
|
+
return buildScreenshotResult(screenshotPath, screenshotFormat);
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=screenshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/screenshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the scroll tool.
|
|
3
|
+
*
|
|
4
|
+
* @param context - Shared browser tool execution context
|
|
5
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
6
|
+
* @returns Copilot tool definition for page scrolling or scrolling an element into view
|
|
7
|
+
*/
|
|
8
|
+
export function createScrollTool(context, defineTool) {
|
|
9
|
+
return defineTool('browser_scroll', {
|
|
10
|
+
description: 'Scroll the page or scroll an element into view.',
|
|
11
|
+
parameters: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
direction: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Scroll direction: "up" or "down"',
|
|
17
|
+
},
|
|
18
|
+
amount: {
|
|
19
|
+
type: 'number',
|
|
20
|
+
description: 'Pixels to scroll (default: one viewport height)',
|
|
21
|
+
},
|
|
22
|
+
target: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Element ref to scroll into view (overrides direction/amount)',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
handler: async (args) => {
|
|
29
|
+
const { direction, amount, target } = args;
|
|
30
|
+
if (target) {
|
|
31
|
+
return context.invoke(['scrollintoview', target]);
|
|
32
|
+
}
|
|
33
|
+
const scrollDirection = direction ?? 'down';
|
|
34
|
+
const command = ['scroll', scrollDirection];
|
|
35
|
+
if (amount)
|
|
36
|
+
command.push(String(amount));
|
|
37
|
+
return context.invoke(command);
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=scroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/scroll.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgC,EAAE,UAAsB;IACvF,OAAO,UAAU,CAAC,gBAAgB,EAAE;QAClC,WAAW,EAAE,iDAAiD;QAC9D,UAAU,EAAE;YACV,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kCAAkC;iBAChD;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,iDAAiD;iBAC/D;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8DAA8D;iBAC5E;aACF;SACF;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACtB,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAIrC,CAAC;YACF,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,eAAe,GAAG,SAAS,IAAI,MAAM,CAAC;YAC5C,MAAM,OAAO,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;YAC5C,IAAI,MAAM;gBAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YACzC,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the select interaction tool.
|
|
3
|
+
*
|
|
4
|
+
* @param context - Shared browser tool execution context
|
|
5
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
6
|
+
* @returns Copilot tool definition for choosing an option in a select element
|
|
7
|
+
*/
|
|
8
|
+
export function createSelectTool(context, defineTool) {
|
|
9
|
+
return defineTool('browser_select', {
|
|
10
|
+
description: 'Select an option from a dropdown/select element.',
|
|
11
|
+
parameters: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
target: { type: 'string', description: 'Element ref or CSS selector for the select' },
|
|
15
|
+
value: { type: 'string', description: 'Value or label of the option to select' },
|
|
16
|
+
},
|
|
17
|
+
required: ['target', 'value'],
|
|
18
|
+
},
|
|
19
|
+
handler: async (args) => {
|
|
20
|
+
const { target, value } = args;
|
|
21
|
+
return context.invoke(['select', target, value]);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/select.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgC,EAAE,UAAsB;IACvF,OAAO,UAAU,CAAC,gBAAgB,EAAE;QAClC,WAAW,EAAE,kDAAkD;QAC/D,UAAU,EAAE;YACV,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4CAA4C,EAAE;gBACrF,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wCAAwC,EAAE;aACjF;YACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;SAC9B;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACtB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAyC,CAAC;YACpE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QACnD,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Creates the accessibility snapshot tool.
|
|
5
|
+
*
|
|
6
|
+
* @param context - Shared browser tool execution context
|
|
7
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
8
|
+
* @returns Copilot tool definition for capturing the current page snapshot
|
|
9
|
+
*/
|
|
10
|
+
export function createSnapshotTool(context, defineTool) {
|
|
11
|
+
return defineTool('browser_snapshot', {
|
|
12
|
+
description: 'Capture an accessibility snapshot of the current page. Returns a text representation of all visible elements with ref identifiers (e.g. @e1, @e2) that can be used in other commands.',
|
|
13
|
+
parameters: {
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: {},
|
|
16
|
+
},
|
|
17
|
+
handler: async () => {
|
|
18
|
+
const output = context.invoke(['snapshot', '-ci']);
|
|
19
|
+
writeFileSync(join(context.outDir, 'snapshot.txt'), output, 'utf-8');
|
|
20
|
+
return output;
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAgC,EAAE,UAAsB;IACzF,OAAO,UAAU,CAAC,kBAAkB,EAAE;QACpC,WAAW,EACT,uLAAuL;QACzL,UAAU,EAAE;YACV,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE,EAAE;SACf;QACD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;YACnD,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YACrE,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the text typing tool.
|
|
3
|
+
*
|
|
4
|
+
* @param context - Shared browser tool execution context
|
|
5
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
6
|
+
* @returns Copilot tool definition for typing text into the focused element or a target
|
|
7
|
+
*/
|
|
8
|
+
export function createTypeTextTool(context, defineTool) {
|
|
9
|
+
return defineTool('browser_type', {
|
|
10
|
+
description: 'Type text character by character (useful for inputs that respond to keystrokes).',
|
|
11
|
+
parameters: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
target: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Element ref or CSS selector (omit to type into focused element)',
|
|
17
|
+
},
|
|
18
|
+
text: { type: 'string', description: 'Text to type' },
|
|
19
|
+
},
|
|
20
|
+
required: ['text'],
|
|
21
|
+
},
|
|
22
|
+
handler: async (args) => {
|
|
23
|
+
const { target, text } = args;
|
|
24
|
+
const command = target ? ['type', target, text] : ['keyboard', 'type', text];
|
|
25
|
+
return context.invoke(command);
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=type-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-text.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/type-text.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAgC,EAAE,UAAsB;IACzF,OAAO,UAAU,CAAC,cAAc,EAAE;QAChC,WAAW,EAAE,kFAAkF;QAC/F,UAAU,EAAE;YACV,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,iEAAiE;iBAC/E;gBACD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE;aACtD;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;SACnB;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACtB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAyC,CAAC;YACnE,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YAC7E,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the wait tool.
|
|
3
|
+
*
|
|
4
|
+
* @param context - Shared browser tool execution context
|
|
5
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
6
|
+
* @returns Copilot tool definition for waiting on load state, text, elements, or time
|
|
7
|
+
*/
|
|
8
|
+
export function createWaitTool(context, defineTool) {
|
|
9
|
+
return defineTool('browser_wait', {
|
|
10
|
+
description: 'Wait for a condition: page load (networkidle), text to appear, an element, or a timeout in ms.',
|
|
11
|
+
parameters: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
text: { type: 'string', description: 'Wait for this text to appear on the page' },
|
|
15
|
+
selector: { type: 'string', description: 'Wait for this element ref or CSS selector' },
|
|
16
|
+
load: {
|
|
17
|
+
type: 'string',
|
|
18
|
+
description: 'Wait for page load state: "networkidle", "domcontentloaded", or "load"',
|
|
19
|
+
},
|
|
20
|
+
timeout: { type: 'number', description: 'Wait for this many milliseconds' },
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
handler: async (args) => {
|
|
24
|
+
const { text, selector, load, timeout } = args;
|
|
25
|
+
if (text)
|
|
26
|
+
return context.invoke(['wait', '--text', text], 60_000);
|
|
27
|
+
if (load)
|
|
28
|
+
return context.invoke(['wait', '--load', load], 60_000);
|
|
29
|
+
if (selector)
|
|
30
|
+
return context.invoke(['wait', selector], 60_000);
|
|
31
|
+
if (timeout) {
|
|
32
|
+
await new Promise((resolve) => setTimeout(resolve, timeout));
|
|
33
|
+
return `Waited ${timeout}ms`;
|
|
34
|
+
}
|
|
35
|
+
return context.invoke(['wait', '--load', 'networkidle'], 60_000);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=wait.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/wait.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgC,EAAE,UAAsB;IACrF,OAAO,UAAU,CAAC,cAAc,EAAE;QAChC,WAAW,EACT,gGAAgG;QAClG,UAAU,EAAE;YACV,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0CAA0C,EAAE;gBACjF,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2CAA2C,EAAE;gBACtF,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wEAAwE;iBACtF;gBACD,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iCAAiC,EAAE;aAC5E;SACF;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACtB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAKzC,CAAC;YACF,IAAI,IAAI;gBAAE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;YAClE,IAAI,IAAI;gBAAE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;YAClE,IAAI,QAAQ;gBAAE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;YAChE,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC7D,OAAO,UAAU,OAAO,IAAI,CAAC;YAC/B,CAAC;YACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;QACnE,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { appendFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, isAbsolute, join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves a path within a base directory, rejecting escapes.
|
|
5
|
+
*
|
|
6
|
+
* Accepts both relative paths and absolute paths that fall within
|
|
7
|
+
* the base directory. Strips the base prefix from absolute paths
|
|
8
|
+
* before resolving to handle models that echo full paths from prompts.
|
|
9
|
+
*
|
|
10
|
+
* @param baseDir - The allowed root directory
|
|
11
|
+
* @param input - The user-provided path (relative or absolute within baseDir)
|
|
12
|
+
* @returns The resolved absolute path
|
|
13
|
+
* @throws {Error} When the path escapes the base directory
|
|
14
|
+
*/
|
|
15
|
+
function resolveSafe(baseDir, input) {
|
|
16
|
+
// If the model echoed the full absolute path from the prompt, strip the base prefix.
|
|
17
|
+
const relative = isAbsolute(input)
|
|
18
|
+
? input.startsWith(baseDir + '/') || input.startsWith(baseDir + '\\')
|
|
19
|
+
? input.slice(baseDir.length + 1)
|
|
20
|
+
: (() => {
|
|
21
|
+
throw new Error(`Absolute path outside output directory: ${input}`);
|
|
22
|
+
})()
|
|
23
|
+
: input;
|
|
24
|
+
const resolved = join(baseDir, relative);
|
|
25
|
+
if (!resolved.startsWith(baseDir)) {
|
|
26
|
+
throw new Error(`Path escapes the output directory: ${input}`);
|
|
27
|
+
}
|
|
28
|
+
return resolved;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates the write-file tool so the agent can save artifacts
|
|
32
|
+
* (plan.json, verdict.json, etc.) to the run output directory.
|
|
33
|
+
*
|
|
34
|
+
* @param baseDir - The run output directory that scopes all writes
|
|
35
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
36
|
+
* @returns Copilot tool definition for writing a file
|
|
37
|
+
*/
|
|
38
|
+
export function createWriteFileTool(baseDir, defineTool) {
|
|
39
|
+
return defineTool('write_file', {
|
|
40
|
+
description: 'Write content to a file in the output directory. Creates parent directories as needed.',
|
|
41
|
+
parameters: {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
path: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
description: 'File path relative to the output directory (e.g. "plan.json")',
|
|
47
|
+
},
|
|
48
|
+
content: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: 'The full file content to write',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
required: ['path', 'content'],
|
|
54
|
+
},
|
|
55
|
+
handler: async (args) => {
|
|
56
|
+
const { path, content } = args;
|
|
57
|
+
const resolved = resolveSafe(baseDir, path);
|
|
58
|
+
mkdirSync(dirname(resolved), { recursive: true });
|
|
59
|
+
writeFileSync(resolved, content);
|
|
60
|
+
return `Wrote ${content.length} bytes to ${path}`;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Creates the append-file tool so the agent can append lines
|
|
66
|
+
* to artifacts like executions.jsonl.
|
|
67
|
+
*
|
|
68
|
+
* @param baseDir - The run output directory that scopes all writes
|
|
69
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
70
|
+
* @returns Copilot tool definition for appending to a file
|
|
71
|
+
*/
|
|
72
|
+
export function createAppendFileTool(baseDir, defineTool) {
|
|
73
|
+
return defineTool('append_file', {
|
|
74
|
+
description: 'Append content to a file in the output directory. Creates the file if it does not exist.',
|
|
75
|
+
parameters: {
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties: {
|
|
78
|
+
path: {
|
|
79
|
+
type: 'string',
|
|
80
|
+
description: 'File path relative to the output directory (e.g. "executions.jsonl")',
|
|
81
|
+
},
|
|
82
|
+
content: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
description: 'Content to append (a trailing newline is added automatically)',
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
required: ['path', 'content'],
|
|
88
|
+
},
|
|
89
|
+
handler: async (args) => {
|
|
90
|
+
const { path, content } = args;
|
|
91
|
+
const resolved = resolveSafe(baseDir, path);
|
|
92
|
+
mkdirSync(dirname(resolved), { recursive: true });
|
|
93
|
+
appendFileSync(resolved, content.endsWith('\n') ? content : content + '\n');
|
|
94
|
+
return `Appended to ${path}`;
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=write-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-file.js","sourceRoot":"","sources":["../../../../../src/commands/app/tools/write-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/commands/app/types.ts"],"names":[],"mappings":""}
|