@equinor/fusion-framework-cli-plugin-copilot 2.0.2 → 2.0.4
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 +16 -0
- package/dist/esm/commands/app/{session-logger.js → attach-session-logger.js} +16 -2
- package/dist/esm/commands/app/attach-session-logger.js.map +1 -0
- package/dist/esm/commands/app/{command.js → copilot-command.js} +22 -11
- package/dist/esm/commands/app/copilot-command.js.map +1 -0
- package/dist/esm/commands/app/{eval.js → create-session.js} +7 -5
- package/dist/esm/commands/app/create-session.js.map +1 -0
- package/dist/esm/commands/app/format-plan.js +24 -0
- package/dist/esm/commands/app/format-plan.js.map +1 -0
- package/dist/esm/commands/app/format-step-result.js +14 -0
- package/dist/esm/commands/app/format-step-result.js.map +1 -0
- package/dist/esm/commands/app/format-verdict.js +38 -0
- package/dist/esm/commands/app/format-verdict.js.map +1 -0
- package/dist/esm/commands/app/prompts/{system.dev-server.prompt.js → create-dev-server-context.js} +1 -1
- package/dist/esm/commands/app/prompts/create-dev-server-context.js.map +1 -0
- package/dist/esm/commands/app/prompts/{execute-step.prompt.js → create-execute-step-prompt.js} +1 -1
- package/dist/esm/commands/app/prompts/create-execute-step-prompt.js.map +1 -0
- package/dist/esm/commands/app/prompts/{judge.prompt.js → create-judge-prompt.js} +5 -1
- package/dist/esm/commands/app/prompts/create-judge-prompt.js.map +1 -0
- package/dist/esm/commands/app/prompts/{plan.prompt.js → create-plan-prompt.js} +1 -1
- package/dist/esm/commands/app/prompts/create-plan-prompt.js.map +1 -0
- package/dist/esm/commands/app/prompts/{step.prompt.js → create-step-prompt.js} +3 -2
- package/dist/esm/commands/app/prompts/create-step-prompt.js.map +1 -0
- package/dist/esm/commands/app/prompts/{system.prompt.js → create-system-prompt.js} +1 -1
- package/dist/esm/commands/app/prompts/create-system-prompt.js.map +1 -0
- package/dist/esm/commands/app/{login.js → run-login.js} +5 -1
- package/dist/esm/commands/app/run-login.js.map +1 -0
- package/dist/esm/commands/app/{server.js → start-app-server.js} +7 -1
- package/dist/esm/commands/app/start-app-server.js.map +1 -0
- package/dist/esm/commands/app/status-icon.js +18 -0
- package/dist/esm/commands/app/status-icon.js.map +1 -0
- package/dist/esm/commands/app/tools/{registry.js → AgentBrowserToolRegistry.js} +1 -1
- package/dist/esm/commands/app/tools/AgentBrowserToolRegistry.js.map +1 -0
- package/dist/esm/commands/app/tools/{write-file.js → create-append-file-tool.js} +5 -38
- package/dist/esm/commands/app/tools/create-append-file-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{click.js → create-click-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-click-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{errors.js → create-errors-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-errors-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{eval-js.js → create-eval-js-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-eval-js-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{fill.js → create-fill-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-fill-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{find.js → create-find-tool.js} +4 -1
- package/dist/esm/commands/app/tools/create-find-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{get-styles.js → create-get-styles-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-get-styles-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{get-url.js → create-get-url-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-get-url-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{go-back.js → create-go-back-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-go-back-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{hover.js → create-hover-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-hover-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{navigate.js → create-navigate-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-navigate-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{press-key.js → create-press-key-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-press-key-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{read-file.js → create-read-file-tool.js} +4 -2
- package/dist/esm/commands/app/tools/create-read-file-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{reload.js → create-reload-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-reload-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{screenshot.js → create-screenshot-tool.js} +7 -1
- package/dist/esm/commands/app/tools/create-screenshot-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{scroll.js → create-scroll-tool.js} +3 -1
- package/dist/esm/commands/app/tools/create-scroll-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{select.js → create-select-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-select-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{snapshot.js → create-snapshot-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-snapshot-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{type-text.js → create-type-text-tool.js} +1 -1
- package/dist/esm/commands/app/tools/create-type-text-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/{wait.js → create-wait-tool.js} +5 -1
- package/dist/esm/commands/app/tools/create-wait-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/create-write-file-tool.js +65 -0
- package/dist/esm/commands/app/tools/create-write-file-tool.js.map +1 -0
- package/dist/esm/commands/app/tools/index.js +19 -19
- package/dist/esm/commands/app/tools/index.js.map +1 -1
- package/dist/esm/commands/app/truncate.js +11 -0
- package/dist/esm/commands/app/truncate.js.map +1 -0
- package/dist/esm/commands/app/try-format-message.js +39 -0
- package/dist/esm/commands/app/try-format-message.js.map +1 -0
- package/dist/esm/exit-with-resolution-error.js +16 -0
- package/dist/esm/exit-with-resolution-error.js.map +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/resolve-eval-command-input.js +37 -0
- package/dist/esm/resolve-eval-command-input.js.map +1 -0
- package/dist/esm/resolve-eval-files.js +49 -0
- package/dist/esm/resolve-eval-files.js.map +1 -0
- package/dist/esm/utils/ab-error-message.js +34 -0
- package/dist/esm/utils/ab-error-message.js.map +1 -0
- package/dist/esm/utils/{agent-browser.js → ab.js} +3 -32
- package/dist/esm/utils/ab.js.map +1 -0
- package/dist/esm/utils/create-run-dir.js +24 -0
- package/dist/esm/utils/create-run-dir.js.map +1 -0
- package/dist/esm/utils/{process.js → helpers.js} +28 -11
- package/dist/esm/utils/helpers.js.map +1 -0
- package/dist/esm/utils/index.js +8 -5
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/{browser-poll.js → poll-console.js} +5 -3
- package/dist/esm/utils/poll-console.js.map +1 -0
- package/dist/esm/utils/{daemon.js → reset-daemon.js} +5 -14
- package/dist/esm/utils/reset-daemon.js.map +1 -0
- package/dist/esm/utils/resolve-app-key.js +20 -0
- package/dist/esm/utils/resolve-app-key.js.map +1 -0
- package/dist/esm/utils/wait-for-server.js +26 -0
- package/dist/esm/utils/wait-for-server.js.map +1 -0
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/commands/app/format-plan.d.ts +8 -0
- package/dist/types/commands/app/format-step-result.d.ts +8 -0
- package/dist/types/commands/app/format-verdict.d.ts +8 -0
- package/dist/types/commands/app/prompts/{step.prompt.d.ts → create-step-prompt.d.ts} +1 -1
- package/dist/types/commands/app/status-icon.d.ts +8 -0
- package/dist/types/commands/app/tools/create-append-file-tool.d.ts +10 -0
- package/dist/types/commands/app/tools/{write-file.d.ts → create-write-file-tool.d.ts} +0 -9
- package/dist/types/commands/app/truncate.d.ts +8 -0
- package/dist/types/commands/app/try-format-message.d.ts +10 -0
- package/dist/types/exit-with-resolution-error.d.ts +8 -0
- package/dist/types/{eval-resolve.d.ts → resolve-eval-command-input.d.ts} +0 -8
- package/dist/types/resolve-eval-files.d.ts +8 -0
- package/dist/types/utils/ab-error-message.d.ts +11 -0
- package/dist/types/utils/{agent-browser.d.ts → ab.d.ts} +0 -13
- package/dist/types/utils/create-run-dir.d.ts +8 -0
- package/dist/types/utils/{process.d.ts → helpers.d.ts} +13 -6
- package/dist/types/utils/index.d.ts +8 -5
- package/dist/types/utils/{daemon.d.ts → reset-daemon.d.ts} +0 -5
- package/dist/types/utils/resolve-app-key.d.ts +9 -0
- package/dist/types/utils/wait-for-server.d.ts +9 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +5 -5
- package/src/commands/app/{session-logger.ts → attach-session-logger.ts} +15 -1
- package/src/commands/app/{command.ts → copilot-command.ts} +21 -12
- package/src/commands/app/{eval.ts → create-session.ts} +6 -4
- package/src/commands/app/format-plan.ts +26 -0
- package/src/commands/app/format-step-result.ts +16 -0
- package/src/commands/app/format-verdict.ts +43 -0
- package/src/commands/app/prompts/{judge.prompt.ts → create-judge-prompt.ts} +4 -0
- package/src/commands/app/prompts/{step.prompt.ts → create-step-prompt.ts} +2 -1
- package/src/commands/app/{login.ts → run-login.ts} +4 -0
- package/src/commands/app/{server.ts → start-app-server.ts} +6 -0
- package/src/commands/app/status-icon.ts +16 -0
- package/src/commands/app/tools/{write-file.ts → create-append-file-tool.ts} +4 -39
- package/src/commands/app/tools/{find.ts → create-find-tool.ts} +3 -0
- package/src/commands/app/tools/{read-file.ts → create-read-file-tool.ts} +3 -1
- package/src/commands/app/tools/{screenshot.ts → create-screenshot-tool.ts} +6 -0
- package/src/commands/app/tools/{scroll.ts → create-scroll-tool.ts} +2 -0
- package/src/commands/app/tools/{wait.ts → create-wait-tool.ts} +4 -0
- package/src/commands/app/tools/create-write-file-tool.ts +69 -0
- package/src/commands/app/tools/index.ts +19 -19
- package/src/commands/app/truncate.ts +10 -0
- package/src/commands/app/try-format-message.ts +42 -0
- package/src/exit-with-resolution-error.ts +15 -0
- package/src/index.ts +1 -1
- package/src/resolve-eval-command-input.ts +59 -0
- package/src/resolve-eval-files.ts +57 -0
- package/src/utils/ab-error-message.ts +31 -0
- package/src/utils/{agent-browser.ts → ab.ts} +2 -30
- package/src/utils/create-run-dir.ts +24 -0
- package/src/utils/{process.ts → helpers.ts} +28 -10
- package/src/utils/index.ts +8 -5
- package/src/utils/{browser-poll.ts → poll-console.ts} +4 -2
- package/src/utils/{daemon.ts → reset-daemon.ts} +4 -13
- package/src/utils/resolve-app-key.ts +20 -0
- package/src/utils/wait-for-server.ts +24 -0
- package/src/version.ts +1 -1
- package/dist/esm/commands/app/command.js.map +0 -1
- package/dist/esm/commands/app/eval.js.map +0 -1
- package/dist/esm/commands/app/format.js +0 -93
- package/dist/esm/commands/app/format.js.map +0 -1
- package/dist/esm/commands/app/login.js.map +0 -1
- package/dist/esm/commands/app/prompts/execute-step.prompt.js.map +0 -1
- package/dist/esm/commands/app/prompts/judge.prompt.js.map +0 -1
- package/dist/esm/commands/app/prompts/plan.prompt.js.map +0 -1
- package/dist/esm/commands/app/prompts/step.prompt.js.map +0 -1
- package/dist/esm/commands/app/prompts/system.dev-server.prompt.js.map +0 -1
- package/dist/esm/commands/app/prompts/system.prompt.js.map +0 -1
- package/dist/esm/commands/app/server.js.map +0 -1
- package/dist/esm/commands/app/session-logger.js.map +0 -1
- package/dist/esm/commands/app/tools/click.js.map +0 -1
- package/dist/esm/commands/app/tools/errors.js.map +0 -1
- package/dist/esm/commands/app/tools/eval-js.js.map +0 -1
- package/dist/esm/commands/app/tools/fill.js.map +0 -1
- package/dist/esm/commands/app/tools/find.js.map +0 -1
- package/dist/esm/commands/app/tools/get-styles.js.map +0 -1
- package/dist/esm/commands/app/tools/get-url.js.map +0 -1
- package/dist/esm/commands/app/tools/go-back.js.map +0 -1
- package/dist/esm/commands/app/tools/hover.js.map +0 -1
- package/dist/esm/commands/app/tools/navigate.js.map +0 -1
- package/dist/esm/commands/app/tools/press-key.js.map +0 -1
- package/dist/esm/commands/app/tools/read-file.js.map +0 -1
- package/dist/esm/commands/app/tools/registry.js.map +0 -1
- package/dist/esm/commands/app/tools/reload.js.map +0 -1
- package/dist/esm/commands/app/tools/screenshot.js.map +0 -1
- package/dist/esm/commands/app/tools/scroll.js.map +0 -1
- package/dist/esm/commands/app/tools/select.js.map +0 -1
- package/dist/esm/commands/app/tools/snapshot.js.map +0 -1
- package/dist/esm/commands/app/tools/type-text.js.map +0 -1
- package/dist/esm/commands/app/tools/wait.js.map +0 -1
- package/dist/esm/commands/app/tools/write-file.js.map +0 -1
- package/dist/esm/eval-resolve.js +0 -83
- package/dist/esm/eval-resolve.js.map +0 -1
- package/dist/esm/utils/agent-browser.js.map +0 -1
- package/dist/esm/utils/browser-poll.js.map +0 -1
- package/dist/esm/utils/daemon.js.map +0 -1
- package/dist/esm/utils/process.js.map +0 -1
- package/dist/esm/utils/server.js +0 -65
- package/dist/esm/utils/server.js.map +0 -1
- package/dist/types/commands/app/format.d.ts +0 -14
- package/dist/types/utils/server.d.ts +0 -26
- package/src/commands/app/format.ts +0 -110
- package/src/eval-resolve.ts +0 -113
- package/src/utils/server.ts +0 -66
- /package/dist/types/commands/app/{session-logger.d.ts → attach-session-logger.d.ts} +0 -0
- /package/dist/types/commands/app/{command.d.ts → copilot-command.d.ts} +0 -0
- /package/dist/types/commands/app/{eval.d.ts → create-session.d.ts} +0 -0
- /package/dist/types/commands/app/prompts/{system.dev-server.prompt.d.ts → create-dev-server-context.d.ts} +0 -0
- /package/dist/types/commands/app/prompts/{execute-step.prompt.d.ts → create-execute-step-prompt.d.ts} +0 -0
- /package/dist/types/commands/app/prompts/{judge.prompt.d.ts → create-judge-prompt.d.ts} +0 -0
- /package/dist/types/commands/app/prompts/{plan.prompt.d.ts → create-plan-prompt.d.ts} +0 -0
- /package/dist/types/commands/app/prompts/{system.prompt.d.ts → create-system-prompt.d.ts} +0 -0
- /package/dist/types/commands/app/{login.d.ts → run-login.d.ts} +0 -0
- /package/dist/types/commands/app/{server.d.ts → start-app-server.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{registry.d.ts → AgentBrowserToolRegistry.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{click.d.ts → create-click-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{errors.d.ts → create-errors-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{eval-js.d.ts → create-eval-js-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{fill.d.ts → create-fill-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{find.d.ts → create-find-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{get-styles.d.ts → create-get-styles-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{get-url.d.ts → create-get-url-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{go-back.d.ts → create-go-back-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{hover.d.ts → create-hover-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{navigate.d.ts → create-navigate-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{press-key.d.ts → create-press-key-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{read-file.d.ts → create-read-file-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{reload.d.ts → create-reload-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{screenshot.d.ts → create-screenshot-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{scroll.d.ts → create-scroll-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{select.d.ts → create-select-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{snapshot.d.ts → create-snapshot-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{type-text.d.ts → create-type-text-tool.d.ts} +0 -0
- /package/dist/types/commands/app/tools/{wait.d.ts → create-wait-tool.d.ts} +0 -0
- /package/dist/types/utils/{browser-poll.d.ts → poll-console.d.ts} +0 -0
- /package/src/commands/app/prompts/{system.dev-server.prompt.ts → create-dev-server-context.ts} +0 -0
- /package/src/commands/app/prompts/{execute-step.prompt.ts → create-execute-step-prompt.ts} +0 -0
- /package/src/commands/app/prompts/{plan.prompt.ts → create-plan-prompt.ts} +0 -0
- /package/src/commands/app/prompts/{system.prompt.ts → create-system-prompt.ts} +0 -0
- /package/src/commands/app/tools/{registry.ts → AgentBrowserToolRegistry.ts} +0 -0
- /package/src/commands/app/tools/{click.ts → create-click-tool.ts} +0 -0
- /package/src/commands/app/tools/{errors.ts → create-errors-tool.ts} +0 -0
- /package/src/commands/app/tools/{eval-js.ts → create-eval-js-tool.ts} +0 -0
- /package/src/commands/app/tools/{fill.ts → create-fill-tool.ts} +0 -0
- /package/src/commands/app/tools/{get-styles.ts → create-get-styles-tool.ts} +0 -0
- /package/src/commands/app/tools/{get-url.ts → create-get-url-tool.ts} +0 -0
- /package/src/commands/app/tools/{go-back.ts → create-go-back-tool.ts} +0 -0
- /package/src/commands/app/tools/{hover.ts → create-hover-tool.ts} +0 -0
- /package/src/commands/app/tools/{navigate.ts → create-navigate-tool.ts} +0 -0
- /package/src/commands/app/tools/{press-key.ts → create-press-key-tool.ts} +0 -0
- /package/src/commands/app/tools/{reload.ts → create-reload-tool.ts} +0 -0
- /package/src/commands/app/tools/{select.ts → create-select-tool.ts} +0 -0
- /package/src/commands/app/tools/{snapshot.ts → create-snapshot-tool.ts} +0 -0
- /package/src/commands/app/tools/{type-text.ts → create-type-text-tool.ts} +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Plan } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Renders a structured plan as a human-readable summary.
|
|
4
|
+
*
|
|
5
|
+
* @param plan - The plan to render, containing a summary and ordered steps.
|
|
6
|
+
* @returns A multi-line string suitable for console output.
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatPlan(plan: Plan): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StepResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Renders a single step execution result.
|
|
4
|
+
*
|
|
5
|
+
* @param result - The step result to render, including its outcome, note, and evidence.
|
|
6
|
+
* @returns A formatted two-line string describing the step outcome.
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatStepResult(result: StepResult): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Verdict } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Renders the final verdict as a full-width coloured report.
|
|
4
|
+
*
|
|
5
|
+
* @param verdict - The verdict to render, including per-step results, reasoning, and UX feedback.
|
|
6
|
+
* @returns A multi-line string suitable for console output.
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatVerdict(verdict: Verdict): string;
|
|
@@ -9,4 +9,4 @@ import type { PlanStep, RuntimeExecutionContext } from '../types.js';
|
|
|
9
9
|
* @param ctx - Runtime context with output directory and app URL
|
|
10
10
|
* @returns The fully interpolated prompt string
|
|
11
11
|
*/
|
|
12
|
-
export declare const createStepPrompt: (step: PlanStep,
|
|
12
|
+
export declare const createStepPrompt: (step: PlanStep, _ctx: RuntimeExecutionContext) => string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders a status glyph for a step or verdict outcome.
|
|
3
|
+
*
|
|
4
|
+
* @param ok - Outcome value: `true` (pass), `false` (fail), or a string label
|
|
5
|
+
* such as `'blocked'` or `'flaky'` for anything in between.
|
|
6
|
+
* @returns A single coloured glyph representing the outcome.
|
|
7
|
+
*/
|
|
8
|
+
export declare function statusIcon(ok: boolean | string): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DefineTool } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates the append-file tool so the agent can append lines
|
|
4
|
+
* to artifacts like executions.jsonl.
|
|
5
|
+
*
|
|
6
|
+
* @param baseDir - The run output directory that scopes all writes
|
|
7
|
+
* @param defineTool - Copilot SDK helper used to declare tools
|
|
8
|
+
* @returns Copilot tool definition for appending to a file
|
|
9
|
+
*/
|
|
10
|
+
export declare function createAppendFileTool(baseDir: string, defineTool: DefineTool): import("node_modules/@github/copilot-sdk/dist/types.js").Tool<unknown>;
|
|
@@ -8,12 +8,3 @@ import type { DefineTool } from './types.js';
|
|
|
8
8
|
* @returns Copilot tool definition for writing a file
|
|
9
9
|
*/
|
|
10
10
|
export declare function createWriteFileTool(baseDir: string, defineTool: DefineTool): import("node_modules/@github/copilot-sdk/dist/types.js").Tool<unknown>;
|
|
11
|
-
/**
|
|
12
|
-
* Creates the append-file tool so the agent can append lines
|
|
13
|
-
* to artifacts like executions.jsonl.
|
|
14
|
-
*
|
|
15
|
-
* @param baseDir - The run output directory that scopes all writes
|
|
16
|
-
* @param defineTool - Copilot SDK helper used to declare tools
|
|
17
|
-
* @returns Copilot tool definition for appending to a file
|
|
18
|
-
*/
|
|
19
|
-
export declare function createAppendFileTool(baseDir: string, defineTool: DefineTool): import("node_modules/@github/copilot-sdk/dist/types.js").Tool<unknown>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Truncates a string to a maximum length, appending an ellipsis when cut.
|
|
3
|
+
*
|
|
4
|
+
* @param str - The string to truncate.
|
|
5
|
+
* @param max - Maximum length of the returned string, including the ellipsis.
|
|
6
|
+
* @returns The original string, or a shortened version ending in `…`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function truncate(str: string, max: number): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempts to detect the JSON shape of an assistant message and format it.
|
|
3
|
+
*
|
|
4
|
+
* Returns `null` when the content is not a recognised structure, so the
|
|
5
|
+
* caller can fall back to plain-text rendering.
|
|
6
|
+
*
|
|
7
|
+
* @param content - Raw assistant message content, expected to be a JSON string.
|
|
8
|
+
* @returns A formatted string for a recognised plan, step result, or verdict, or `null` otherwise.
|
|
9
|
+
*/
|
|
10
|
+
export declare function tryFormatMessage(content: string): string | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prints a CLI resolution error and exits the current process.
|
|
3
|
+
*
|
|
4
|
+
* @param message - Primary error message.
|
|
5
|
+
* @param detail - Optional follow-up detail shown on the next line.
|
|
6
|
+
* @returns This function never returns because the process exits.
|
|
7
|
+
*/
|
|
8
|
+
export declare function exitWithResolutionError(message: string, detail?: string): never;
|
|
@@ -21,11 +21,3 @@ export interface EvalCommandInput {
|
|
|
21
21
|
* @returns Normalized application path and optional direct eval file path.
|
|
22
22
|
*/
|
|
23
23
|
export declare function resolveEvalCommandInput(inputPath: string): EvalCommandInput;
|
|
24
|
-
/**
|
|
25
|
-
* Resolves eval markdown files for a Fusion application.
|
|
26
|
-
*
|
|
27
|
-
* @param appPath - Path to the Fusion application directory
|
|
28
|
-
* @param evalOpt - Value of the `--eval` CLI option (name, path, or `undefined`)
|
|
29
|
-
* @returns Array of absolute paths to eval markdown files
|
|
30
|
-
*/
|
|
31
|
-
export declare function resolveEvalFiles(appPath: string, evalOpt?: string): string[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves eval markdown files for a Fusion application.
|
|
3
|
+
*
|
|
4
|
+
* @param appPath - Path to the Fusion application directory
|
|
5
|
+
* @param evalOpt - Value of the `--eval` CLI option (name, path, or `undefined`)
|
|
6
|
+
* @returns Array of absolute paths to eval markdown files
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveEvalFiles(appPath: string, evalOpt?: string): string[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts the user-facing error message from an agent-browser failure.
|
|
3
|
+
*
|
|
4
|
+
* Strips ANSI escape codes from stderr and returns only the diagnostic
|
|
5
|
+
* lines prefixed with `✗` or `⚠`. Falls back to the first 200 characters
|
|
6
|
+
* of the error message when no diagnostic lines are found.
|
|
7
|
+
*
|
|
8
|
+
* @param err - The caught error (typically from {@link ab})
|
|
9
|
+
* @returns A single-line summary suitable for console output
|
|
10
|
+
*/
|
|
11
|
+
export declare function abErrorMessage(err: unknown): string;
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/** Persistent Chrome profile directory used across agent-browser sessions. */
|
|
2
|
-
export declare const PROFILE_DIR: string;
|
|
3
1
|
/**
|
|
4
2
|
* Runs an agent-browser command with the persistent Chrome profile.
|
|
5
3
|
*
|
|
@@ -13,14 +11,3 @@ export declare const PROFILE_DIR: string;
|
|
|
13
11
|
* @throws {Error} When `agent-browser` exits with a non-zero code or times out
|
|
14
12
|
*/
|
|
15
13
|
export declare function ab(args: string[], timeoutMs?: number): string;
|
|
16
|
-
/**
|
|
17
|
-
* Extracts the user-facing error message from an agent-browser failure.
|
|
18
|
-
*
|
|
19
|
-
* Strips ANSI escape codes from stderr and returns only the diagnostic
|
|
20
|
-
* lines prefixed with `✗` or `⚠`. Falls back to the first 200 characters
|
|
21
|
-
* of the error message when no diagnostic lines are found.
|
|
22
|
-
*
|
|
23
|
-
* @param err - The caught error (typically from {@link ab})
|
|
24
|
-
* @returns A single-line summary suitable for console output
|
|
25
|
-
*/
|
|
26
|
-
export declare function abErrorMessage(err: unknown): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a timestamped, run-specific output directory for eval artifacts.
|
|
3
|
+
*
|
|
4
|
+
* @param title - Human label used as the directory name prefix (slugified)
|
|
5
|
+
* @param baseDir - Optional parent directory override
|
|
6
|
+
* @returns Absolute path to the newly created directory
|
|
7
|
+
*/
|
|
8
|
+
export declare function createRunDir(title: string, baseDir?: string): string;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { ChildProcess } from 'node:child_process';
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
* @param proc - The child process to terminate (no-op when `undefined` or already killed)
|
|
6
|
-
*/
|
|
7
|
-
export declare function cleanup(proc?: ChildProcess): void;
|
|
2
|
+
/** Persistent Chrome profile directory used across agent-browser sessions. */
|
|
3
|
+
export declare const PROFILE_DIR: string;
|
|
8
4
|
/**
|
|
9
5
|
* Returns a promise that resolves after the given delay.
|
|
10
6
|
*
|
|
@@ -19,3 +15,14 @@ export declare function sleep(ms: number): Promise<void>;
|
|
|
19
15
|
* @returns The input string with all ANSI escape sequences removed
|
|
20
16
|
*/
|
|
21
17
|
export declare function stripAnsi(s: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Sends `SIGTERM` to a child process if it is still running.
|
|
20
|
+
*
|
|
21
|
+
* @param proc - The child process to terminate (no-op when `undefined` or already killed)
|
|
22
|
+
*/
|
|
23
|
+
export declare function cleanup(proc?: ChildProcess): void;
|
|
24
|
+
/**
|
|
25
|
+
* Clears the MSAL `interaction.status` flag from `sessionStorage` in the
|
|
26
|
+
* running browser via `agent-browser eval`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function clearMsalInteraction(): void;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
export { ab
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
1
|
+
export { ab } from './ab.js';
|
|
2
|
+
export { abErrorMessage } from './ab-error-message.js';
|
|
3
|
+
export { PROFILE_DIR, sleep, stripAnsi, cleanup, clearMsalInteraction } from './helpers.js';
|
|
4
|
+
export { resetDaemon } from './reset-daemon.js';
|
|
5
|
+
export { createRunDir } from './create-run-dir.js';
|
|
6
|
+
export { resolveAppKey } from './resolve-app-key.js';
|
|
7
|
+
export { waitForServer } from './wait-for-server.js';
|
|
8
|
+
export { pollConsole } from './poll-console.js';
|
|
@@ -9,8 +9,3 @@
|
|
|
9
9
|
* 4. Delete Session Storage to clear stuck MSAL `interaction.status` flags
|
|
10
10
|
*/
|
|
11
11
|
export declare function resetDaemon(): void;
|
|
12
|
-
/**
|
|
13
|
-
* Clears the MSAL `interaction.status` flag from `sessionStorage` in the
|
|
14
|
-
* running browser via `agent-browser eval`.
|
|
15
|
-
*/
|
|
16
|
-
export declare function clearMsalInteraction(): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the Fusion `appKey` by running `ffc app manifest --silent`
|
|
3
|
+
* in the given application directory and parsing the JSON output.
|
|
4
|
+
*
|
|
5
|
+
* @param appDir - Absolute path to the Fusion application
|
|
6
|
+
* @returns The `appKey` string from the manifest
|
|
7
|
+
* @throws {Error} When `ffc app manifest` fails or returns invalid JSON
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveAppKey(appDir: string): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polls a server URL until it responds with a non-5xx status or the
|
|
3
|
+
* timeout is reached.
|
|
4
|
+
*
|
|
5
|
+
* @param url - The URL to poll (e.g. `http://localhost:3000`)
|
|
6
|
+
* @param timeoutSeconds - Maximum number of seconds to wait
|
|
7
|
+
* @returns `true` if the server responded before timeout, `false` otherwise
|
|
8
|
+
*/
|
|
9
|
+
export declare function waitForServer(url: string, timeoutSeconds: number): Promise<boolean>;
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.0.
|
|
1
|
+
export declare const version = "2.0.4";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-cli-plugin-copilot",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "Copilot SDK powered evaluation plugin for Fusion Framework CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/esm/index.js",
|
|
@@ -38,17 +38,17 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@github/copilot-sdk": "^1.0.0",
|
|
41
|
-
"chalk": "^
|
|
41
|
+
"chalk": "^6.0.0",
|
|
42
42
|
"commander": "^15.0.0",
|
|
43
43
|
"ora": "^9.3.0",
|
|
44
44
|
"rxjs": "^7.8.2"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@equinor/fusion-framework-cli": "^15.
|
|
47
|
+
"@equinor/fusion-framework-cli": "^15.2.2"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"typescript": "^
|
|
51
|
-
"@equinor/fusion-framework-cli": "^15.
|
|
50
|
+
"typescript": "^7.0.2",
|
|
51
|
+
"@equinor/fusion-framework-cli": "^15.2.2"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "tsc -b",
|
|
@@ -3,7 +3,7 @@ import ora from 'ora';
|
|
|
3
3
|
|
|
4
4
|
import type { CopilotSession } from '@github/copilot-sdk';
|
|
5
5
|
|
|
6
|
-
import { tryFormatMessage } from './format.js';
|
|
6
|
+
import { tryFormatMessage } from './try-format-message.js';
|
|
7
7
|
|
|
8
8
|
const TOOL_ICONS: Record<string, string> = {
|
|
9
9
|
browser_screenshot: '📷',
|
|
@@ -31,7 +31,9 @@ export function attachSessionLogger(
|
|
|
31
31
|
let spinner: ReturnType<typeof ora> | null = null;
|
|
32
32
|
|
|
33
33
|
function syncSpinner(): void {
|
|
34
|
+
// No pending tools means the spinner has nothing left to show
|
|
34
35
|
if (pendingTools.size === 0) {
|
|
36
|
+
// Stop the spinner only if one was actually running
|
|
35
37
|
if (spinner) {
|
|
36
38
|
spinner.stop();
|
|
37
39
|
spinner = null;
|
|
@@ -39,6 +41,7 @@ export function attachSessionLogger(
|
|
|
39
41
|
return;
|
|
40
42
|
}
|
|
41
43
|
const text = [...pendingTools.values()].join(chalk.dim(' | '));
|
|
44
|
+
// Reuse the existing spinner instance rather than starting a second one
|
|
42
45
|
if (spinner) {
|
|
43
46
|
spinner.text = text;
|
|
44
47
|
} else {
|
|
@@ -47,6 +50,7 @@ export function attachSessionLogger(
|
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
function pauseSpinner(): void {
|
|
53
|
+
// Only stop the spinner if one is actually running
|
|
50
54
|
if (spinner) {
|
|
51
55
|
spinner.stop();
|
|
52
56
|
spinner = null;
|
|
@@ -61,6 +65,7 @@ export function attachSessionLogger(
|
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
session.on((event) => {
|
|
68
|
+
// Dispatch on the Copilot SDK session event type to render the right log line
|
|
64
69
|
switch (event.type) {
|
|
65
70
|
case 'tool.execution_start': {
|
|
66
71
|
const { toolCallId, toolName, arguments: args } = event.data;
|
|
@@ -74,6 +79,7 @@ export function attachSessionLogger(
|
|
|
74
79
|
}
|
|
75
80
|
case 'tool.execution_complete': {
|
|
76
81
|
const label = pendingTools.get(event.data.toolCallId);
|
|
82
|
+
// Only log completion for tools we actually tracked the start of
|
|
77
83
|
if (label) {
|
|
78
84
|
pendingTools.delete(event.data.toolCallId);
|
|
79
85
|
logCompletion(label, event.data.success);
|
|
@@ -82,6 +88,7 @@ export function attachSessionLogger(
|
|
|
82
88
|
}
|
|
83
89
|
case 'external_tool.completed': {
|
|
84
90
|
const label = pendingTools.get(event.data.requestId);
|
|
91
|
+
// Only log completion for tools we actually tracked the start of
|
|
85
92
|
if (label) {
|
|
86
93
|
pendingTools.delete(event.data.requestId);
|
|
87
94
|
logCompletion(label, true);
|
|
@@ -95,9 +102,11 @@ export function attachSessionLogger(
|
|
|
95
102
|
break;
|
|
96
103
|
}
|
|
97
104
|
case 'assistant.message': {
|
|
105
|
+
// Skip empty assistant messages (e.g. tool-only turns)
|
|
98
106
|
if (event.data.content) {
|
|
99
107
|
pauseSpinner();
|
|
100
108
|
const formatted = tryFormatMessage(event.data.content);
|
|
109
|
+
// Prefer the structured plan/verdict/step-result rendering when recognised
|
|
101
110
|
if (formatted) {
|
|
102
111
|
console.log(formatted);
|
|
103
112
|
} else {
|
|
@@ -119,6 +128,7 @@ export function attachSessionLogger(
|
|
|
119
128
|
}
|
|
120
129
|
case 'permission.completed': {
|
|
121
130
|
const label = pendingTools.get(event.data.requestId);
|
|
131
|
+
// Only log completion for permissions we actually tracked the request of
|
|
122
132
|
if (label) {
|
|
123
133
|
const approved = event.data.result?.kind === 'approved';
|
|
124
134
|
pendingTools.delete(event.data.requestId);
|
|
@@ -128,8 +138,10 @@ export function attachSessionLogger(
|
|
|
128
138
|
}
|
|
129
139
|
case 'session.tools_updated': {
|
|
130
140
|
const negotiatedModel = event.data.model as string | undefined;
|
|
141
|
+
// Only log tooling info once the server has actually negotiated a model
|
|
131
142
|
if (negotiatedModel) {
|
|
132
143
|
console.log(chalk.dim(`💾 ${negotiatedModel}`));
|
|
144
|
+
// Warn the user when the server picked a different model than requested
|
|
133
145
|
if (options?.requestedModel && negotiatedModel !== options.requestedModel) {
|
|
134
146
|
console.log(
|
|
135
147
|
chalk.yellow(
|
|
@@ -157,6 +169,7 @@ export function attachSessionLogger(
|
|
|
157
169
|
}
|
|
158
170
|
case 'session.info': {
|
|
159
171
|
const { message } = event.data as { message?: string };
|
|
172
|
+
// Skip empty info events
|
|
160
173
|
if (message) {
|
|
161
174
|
pauseSpinner();
|
|
162
175
|
console.log(chalk.dim(`ℹ️ ${message}`));
|
|
@@ -166,6 +179,7 @@ export function attachSessionLogger(
|
|
|
166
179
|
}
|
|
167
180
|
case 'assistant.intent': {
|
|
168
181
|
const { intent } = event.data as { intent?: string };
|
|
182
|
+
// Skip empty intent events
|
|
169
183
|
if (intent) {
|
|
170
184
|
pauseSpinner();
|
|
171
185
|
console.log(chalk.yellow(`🎯 ${intent}`));
|
|
@@ -2,17 +2,18 @@ import { createCommand } from 'commander';
|
|
|
2
2
|
import { basename } from 'node:path';
|
|
3
3
|
|
|
4
4
|
import { resetDaemon, cleanup, createRunDir } from '../../utils/index.js';
|
|
5
|
-
import { runLogin } from './login.js';
|
|
6
|
-
import { resolveEvalCommandInput
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
5
|
+
import { runLogin } from './run-login.js';
|
|
6
|
+
import { resolveEvalCommandInput } from '../../resolve-eval-command-input.js';
|
|
7
|
+
import { resolveEvalFiles } from '../../resolve-eval-files.js';
|
|
8
|
+
import { createSession } from './create-session.js';
|
|
9
|
+
import { startAppServer } from './start-app-server.js';
|
|
10
|
+
import { attachSessionLogger } from './attach-session-logger.js';
|
|
10
11
|
import type { CopilotEvalOptions, Plan, Verdict } from './types.js';
|
|
11
|
-
import { formatVerdict } from './format.js';
|
|
12
|
+
import { formatVerdict } from './format-verdict.js';
|
|
12
13
|
import { existsSync, readFileSync } from 'node:fs';
|
|
13
|
-
import { createPlanPrompt } from './prompts/plan
|
|
14
|
-
import { createStepPrompt } from './prompts/step
|
|
15
|
-
import { createJudgePrompt } from './prompts/judge
|
|
14
|
+
import { createPlanPrompt } from './prompts/create-plan-prompt.js';
|
|
15
|
+
import { createStepPrompt } from './prompts/create-step-prompt.js';
|
|
16
|
+
import { createJudgePrompt } from './prompts/create-judge-prompt.js';
|
|
16
17
|
import chalk from 'chalk';
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -58,6 +59,7 @@ const _appEvalCommand = createCommand('eval')
|
|
|
58
59
|
const port = parseInt(options.port, 10);
|
|
59
60
|
const verbose = options.verbose;
|
|
60
61
|
|
|
62
|
+
// Reject ambiguous input that selects an eval two different ways
|
|
61
63
|
if (resolvedInput.evalFile && options.eval) {
|
|
62
64
|
console.error('❌ Do not combine a positional eval markdown file with --eval');
|
|
63
65
|
process.exit(1);
|
|
@@ -73,9 +75,9 @@ const _appEvalCommand = createCommand('eval')
|
|
|
73
75
|
const evalFiles = resolvedInput.evalFile
|
|
74
76
|
? [resolvedInput.evalFile]
|
|
75
77
|
: resolveEvalFiles(absAppPath, options.eval);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
);
|
|
78
|
+
// Summarize which eval files were discovered before the run starts
|
|
79
|
+
const evalFileNames = evalFiles.map((f) => basename(f)).join(', ');
|
|
80
|
+
console.log(`📋 Found ${evalFiles.length} eval(s): ${evalFileNames}`);
|
|
79
81
|
|
|
80
82
|
// Start the app dev server (unless --url provides an already-running URL)
|
|
81
83
|
const { serverProcess, appUrl } = await startAppServer(absAppPath, {
|
|
@@ -103,6 +105,7 @@ const _appEvalCommand = createCommand('eval')
|
|
|
103
105
|
|
|
104
106
|
let failures = 0;
|
|
105
107
|
try {
|
|
108
|
+
// Run every resolved eval file sequentially so output stays readable
|
|
106
109
|
for (const evalFilePath of evalFiles) {
|
|
107
110
|
const evalName = basename(evalFilePath, '.md');
|
|
108
111
|
const query = readFileSync(evalFilePath, 'utf-8').trim();
|
|
@@ -129,6 +132,7 @@ const _appEvalCommand = createCommand('eval')
|
|
|
129
132
|
await session.sendAndWait({ prompt: createPlanPrompt(query, ctx) }, 300_000);
|
|
130
133
|
|
|
131
134
|
const planPath = `${runDir}/plan.json`;
|
|
135
|
+
// Bail out of this eval when the planning phase produced no plan file
|
|
132
136
|
if (!existsSync(planPath)) {
|
|
133
137
|
console.error(
|
|
134
138
|
chalk.red(
|
|
@@ -138,6 +142,7 @@ const _appEvalCommand = createCommand('eval')
|
|
|
138
142
|
session.disconnect();
|
|
139
143
|
logger.stop();
|
|
140
144
|
failures++;
|
|
145
|
+
// Skip execution/judging phases; this eval already failed at planning
|
|
141
146
|
continue;
|
|
142
147
|
}
|
|
143
148
|
|
|
@@ -147,6 +152,7 @@ const _appEvalCommand = createCommand('eval')
|
|
|
147
152
|
// ── Phase 2: Execute + Evaluate each step ──────────────────
|
|
148
153
|
for (const step of plan.steps) {
|
|
149
154
|
console.log(chalk.cyan(`\n── Scenario: ${step.scenario}`));
|
|
155
|
+
// Print each acceptance criterion the agent will be judged against
|
|
150
156
|
for (const c of step.criteria) {
|
|
151
157
|
console.log(chalk.dim(` • ${c}`));
|
|
152
158
|
}
|
|
@@ -162,9 +168,11 @@ const _appEvalCommand = createCommand('eval')
|
|
|
162
168
|
|
|
163
169
|
// Print the verdict
|
|
164
170
|
const verdictPath = `${runDir}/verdict.json`;
|
|
171
|
+
// Only report a verdict when the judge phase actually produced one
|
|
165
172
|
if (existsSync(verdictPath)) {
|
|
166
173
|
const verdict = JSON.parse(readFileSync(verdictPath, 'utf-8')) as Verdict;
|
|
167
174
|
console.log(formatVerdict(verdict));
|
|
175
|
+
// A failing verdict counts toward the overall exit-code failure total
|
|
168
176
|
if (!verdict.pass) failures++;
|
|
169
177
|
} else {
|
|
170
178
|
console.error(chalk.red(`❌ Judge did not produce ${verdictPath}.`));
|
|
@@ -174,6 +182,7 @@ const _appEvalCommand = createCommand('eval')
|
|
|
174
182
|
logger?.stop();
|
|
175
183
|
const msg = err instanceof Error ? err.message : String(err);
|
|
176
184
|
console.error(chalk.red(`\n❌ Eval "${evalName}" failed: ${msg}`));
|
|
185
|
+
// Print the stack trace too when one is available for debugging
|
|
177
186
|
if (err instanceof Error && err.stack) {
|
|
178
187
|
console.error(chalk.dim(err.stack));
|
|
179
188
|
}
|
|
@@ -3,12 +3,13 @@ import { join } from 'node:path';
|
|
|
3
3
|
|
|
4
4
|
import { ab, abErrorMessage } from '../../utils/index.js';
|
|
5
5
|
import { createAgentBrowserTools } from './tools/index.js';
|
|
6
|
-
import { createWriteFileTool
|
|
7
|
-
import {
|
|
6
|
+
import { createWriteFileTool } from './tools/create-write-file-tool.js';
|
|
7
|
+
import { createAppendFileTool } from './tools/create-append-file-tool.js';
|
|
8
|
+
import { createReadFileTool } from './tools/create-read-file-tool.js';
|
|
8
9
|
import type { RuntimeExecutionContext } from './types.js';
|
|
9
10
|
import type { CopilotSession, SessionConfig } from '@github/copilot-sdk';
|
|
10
|
-
import { createSystemPrompt } from './prompts/system
|
|
11
|
-
import { createDevServerContext } from './prompts/
|
|
11
|
+
import { createSystemPrompt } from './prompts/create-system-prompt.js';
|
|
12
|
+
import { createDevServerContext } from './prompts/create-dev-server-context.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Lazily imports the Copilot SDK to avoid module resolution errors at CLI startup.
|
|
@@ -44,6 +45,7 @@ export const createSession = async (options: SessionOptions): Promise<CopilotSes
|
|
|
44
45
|
createAppendFileTool(ctx.outDir, defineTool),
|
|
45
46
|
];
|
|
46
47
|
|
|
48
|
+
// Combine built-in browser and file tools with any caller-supplied tools
|
|
47
49
|
const tools = [
|
|
48
50
|
...createBrowserTools(defineTool, {
|
|
49
51
|
cwd: ctx.outDir,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
import type { Plan } from './types.js';
|
|
4
|
+
import { truncate } from './truncate.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Renders a structured plan as a human-readable summary.
|
|
8
|
+
*
|
|
9
|
+
* @param plan - The plan to render, containing a summary and ordered steps.
|
|
10
|
+
* @returns A multi-line string suitable for console output.
|
|
11
|
+
*/
|
|
12
|
+
export function formatPlan(plan: Plan): string {
|
|
13
|
+
const lines = [
|
|
14
|
+
'',
|
|
15
|
+
chalk.bold(`📋 ${plan.summary}`),
|
|
16
|
+
'',
|
|
17
|
+
...plan.steps.flatMap((s, si) => [
|
|
18
|
+
` ${chalk.dim(`${si + 1}.`)} ${s.scenario}`,
|
|
19
|
+
...s.criteria
|
|
20
|
+
// Truncate each criterion so long descriptions don't wrap the terminal
|
|
21
|
+
.map((c) => chalk.dim(` • ${truncate(c, 70)}`)),
|
|
22
|
+
]),
|
|
23
|
+
'',
|
|
24
|
+
];
|
|
25
|
+
return lines.join('\n');
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
import type { StepResult } from './types.js';
|
|
4
|
+
import { statusIcon } from './status-icon.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Renders a single step execution result.
|
|
8
|
+
*
|
|
9
|
+
* @param result - The step result to render, including its outcome, note, and evidence.
|
|
10
|
+
* @returns A formatted two-line string describing the step outcome.
|
|
11
|
+
*/
|
|
12
|
+
export function formatStepResult(result: StepResult): string {
|
|
13
|
+
const icon = statusIcon(result.ok);
|
|
14
|
+
const files = result.evidence.length ? chalk.dim(` [${result.evidence.join(', ')}]`) : '';
|
|
15
|
+
return ` ${icon} ${result.criterion}\n${chalk.dim(` ${result.note}`)}${files}`;
|
|
16
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
import type { Verdict } from './types.js';
|
|
4
|
+
import { statusIcon } from './status-icon.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Renders the final verdict as a full-width coloured report.
|
|
8
|
+
*
|
|
9
|
+
* @param verdict - The verdict to render, including per-step results, reasoning, and UX feedback.
|
|
10
|
+
* @returns A multi-line string suitable for console output.
|
|
11
|
+
*/
|
|
12
|
+
export function formatVerdict(verdict: Verdict): string {
|
|
13
|
+
const bar = '═'.repeat(60);
|
|
14
|
+
const banner = verdict.pass
|
|
15
|
+
? chalk.bgGreen.black.bold(' ✅ PASS ')
|
|
16
|
+
: chalk.bgRed.white.bold(' ❌ FAIL ');
|
|
17
|
+
|
|
18
|
+
const lines = [
|
|
19
|
+
'',
|
|
20
|
+
bar,
|
|
21
|
+
` ${banner}`,
|
|
22
|
+
bar,
|
|
23
|
+
'',
|
|
24
|
+
...verdict.steps
|
|
25
|
+
// Render each step's outcome as a status glyph, criterion, and note
|
|
26
|
+
.map((s) => ` ${statusIcon(s.ok)} ${s.criterion}\n${chalk.dim(` ${s.note}`)}`),
|
|
27
|
+
'',
|
|
28
|
+
chalk.dim(` ${verdict.reasoning}`),
|
|
29
|
+
'',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// Append optional UX feedback only when the judge actually provided any
|
|
33
|
+
if (verdict.ux && verdict.ux.length > 0) {
|
|
34
|
+
lines.push(chalk.bold(' 💡 UX Feedback'), '');
|
|
35
|
+
// List every UX hint as its own bullet line
|
|
36
|
+
for (const hint of verdict.ux) {
|
|
37
|
+
lines.push(chalk.yellow(` • ${hint}`));
|
|
38
|
+
}
|
|
39
|
+
lines.push('');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return lines.join('\n');
|
|
43
|
+
}
|
|
@@ -19,6 +19,7 @@ function collectEvidence(outDir: string): string {
|
|
|
19
19
|
|
|
20
20
|
// ── executions.jsonl ──
|
|
21
21
|
const execPath = join(outDir, 'executions.jsonl');
|
|
22
|
+
// Fall back to a placeholder note when the executions log is missing
|
|
22
23
|
if (existsSync(execPath)) {
|
|
23
24
|
parts.push('### executions.jsonl', readFileSync(execPath, 'utf-8').trim());
|
|
24
25
|
} else {
|
|
@@ -27,10 +28,13 @@ function collectEvidence(outDir: string): string {
|
|
|
27
28
|
|
|
28
29
|
// ── evidence/ directory ──
|
|
29
30
|
const evidenceDir = join(outDir, 'evidence');
|
|
31
|
+
// Only scan for evidence files when the directory actually exists
|
|
30
32
|
if (existsSync(evidenceDir)) {
|
|
31
33
|
const files = readdirSync(evidenceDir).sort();
|
|
34
|
+
// Inline readable text evidence; list binary evidence by name only
|
|
32
35
|
for (const file of files) {
|
|
33
36
|
const ext = extname(file).toLowerCase();
|
|
37
|
+
// Inline the content of readable text extensions; list other files by name only
|
|
34
38
|
if (TEXT_EXTENSIONS.has(ext)) {
|
|
35
39
|
const content = readFileSync(join(evidenceDir, file), 'utf-8').trim();
|
|
36
40
|
parts.push(`### evidence/${file}`, content);
|
|
@@ -10,8 +10,9 @@ import type { PlanStep, RuntimeExecutionContext } from '../types.js';
|
|
|
10
10
|
* @param ctx - Runtime context with output directory and app URL
|
|
11
11
|
* @returns The fully interpolated prompt string
|
|
12
12
|
*/
|
|
13
|
-
export const createStepPrompt = (step: PlanStep,
|
|
13
|
+
export const createStepPrompt = (step: PlanStep, _ctx: RuntimeExecutionContext): string => {
|
|
14
14
|
const slug = slugify(step.scenario);
|
|
15
|
+
// Render each criterion with its expected pass/fail evidence for the prompt
|
|
15
16
|
const criteriaBlock = step.criteria
|
|
16
17
|
.map((c, i) => `${i + 1}. ${c}\n Pass: ${step.pass[i] ?? ''}\n Fail: ${step.fail[i] ?? ''}`)
|
|
17
18
|
.join('\n');
|