@qaick/runner 0.2.0-alpha.8 → 0.28.0-alpha.5
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 +9 -1
- package/package-dist/package.json +10 -7
- package/package-dist/src/build-info.d.ts +1 -0
- package/package-dist/src/build-info.d.ts.map +1 -1
- package/package-dist/src/build-info.js +6 -3
- package/package-dist/src/build-info.js.map +1 -1
- package/package-dist/src/demo/RunnerWalkthrough.d.ts +0 -1
- package/package-dist/src/demo/RunnerWalkthrough.d.ts.map +1 -1
- package/package-dist/src/demo/RunnerWalkthrough.js +2 -2
- package/package-dist/src/demo/RunnerWalkthrough.js.map +1 -1
- package/package-dist/src/runner/RunnerModule.d.ts.map +1 -1
- package/package-dist/src/runner/RunnerModule.js +28 -13
- package/package-dist/src/runner/RunnerModule.js.map +1 -1
- package/package-dist/src/runner/catalog.js +1 -1
- package/package-dist/src/runner/fixture.js +1 -1
- package/package-dist/src/runner/history.js +1 -1
- package/package-dist/src/runner/package-loader.js +4 -4
- package/package-dist/src/runner/result-export.js +1 -1
- package/package-dist/src/runner/studio-artifact-loader.js +41 -6
- package/package-dist/src/runner/studio-artifact-loader.js.map +1 -1
- package/package-dist/src/runner/types.d.ts +1 -1
- package/package-dist/src/runner/types.js +1 -1
- package/package-dist/styles.css +84 -51
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -48,7 +48,15 @@ The visible loop hierarchy demo is stored at
|
|
|
48
48
|
|
|
49
49
|
Runner also accepts Studio schema 7 Flow artifact envelopes (`artifactKind: "flow"`). A representative fixture is [`fixtures/studio-flow-v7.qaick.json`](fixtures/studio-flow-v7.qaick.json). Operation catalog resolution and a canonical artifact exported directly from Studio remain conformance work.
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
The supported standalone desktop Runner is built and launched from this
|
|
52
|
+
repository with `npm run desktop:run`. It executes `http.*` Actions through its
|
|
53
|
+
Electron host and the shared Runtime/HTTP Executor with native Node transport.
|
|
54
|
+
Explicit request cookies, response cookies, headers and bodies therefore have
|
|
55
|
+
the same semantics as QAick Studio Desktop. The published npm package provides
|
|
56
|
+
the Runner UI and host adapter; it does not contain an Electron binary or host.
|
|
57
|
+
The static Vite build remains available for browser-only scenarios; it uses
|
|
58
|
+
`fetch`, requires browser CORS, and cannot send an explicit `Cookie` request
|
|
59
|
+
header.
|
|
52
60
|
|
|
53
61
|
If Runner reports that a Studio project uses an outdated schema, open that project in QAick Studio, save it, and load the newly saved file in Runner.
|
|
54
62
|
# QAick Runner
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qaick/runner",
|
|
3
3
|
"description": "Reusable QAick Runner module and standalone execution application.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.28.0-alpha.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"package-dist",
|
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
"pack:tarball": "npm run build:package && npm pack",
|
|
39
39
|
"publish:alpha": "npm run check:package && npm publish --tag alpha",
|
|
40
40
|
"package:standalone": "npm run build && node scripts/package-standalone.mjs",
|
|
41
|
+
"electron:build": "tsc -p tsconfig.electron.json && node scripts/copy-electron-preload.mjs",
|
|
42
|
+
"desktop:run": "npm run build && npm run electron:build && electron electron-dist/electron/main.js",
|
|
41
43
|
"smoke": "node scripts/smoke-check.mjs",
|
|
42
44
|
"smoke:deployment": "node scripts/smoke-check.mjs --deployment",
|
|
43
45
|
"lint": "oxlint",
|
|
@@ -52,10 +54,10 @@
|
|
|
52
54
|
"typecheck": "tsc -b"
|
|
53
55
|
},
|
|
54
56
|
"dependencies": {
|
|
55
|
-
"@qaick/contract": "0.2.
|
|
56
|
-
"@qaick/executor": "0.1.0-alpha.
|
|
57
|
-
"@qaick/http-executor": "0.1.0-alpha.
|
|
58
|
-
"@qaick/runtime": "0.1.0-alpha.
|
|
57
|
+
"@qaick/contract": "0.2.11",
|
|
58
|
+
"@qaick/executor": "0.1.0-alpha.2",
|
|
59
|
+
"@qaick/http-executor": "^0.1.0-alpha.9",
|
|
60
|
+
"@qaick/runtime": "0.1.0-alpha.6",
|
|
59
61
|
"zustand": "^5.0.15"
|
|
60
62
|
},
|
|
61
63
|
"peerDependencies": {
|
|
@@ -63,18 +65,19 @@
|
|
|
63
65
|
"react-dom": ">=19.0.0"
|
|
64
66
|
},
|
|
65
67
|
"devDependencies": {
|
|
66
|
-
"@vitejs/plugin-react": "^6.1.1",
|
|
67
68
|
"@testing-library/dom": "^10.4.2",
|
|
68
69
|
"@testing-library/react": "^16.3.3",
|
|
69
70
|
"@types/node": "^24.13.3",
|
|
70
71
|
"@types/react": "^19.2.18",
|
|
71
72
|
"@types/react-dom": "^19.2.7",
|
|
73
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
72
74
|
"jsdom": "^30.0.1",
|
|
73
75
|
"oxlint": "^1.81.0",
|
|
74
76
|
"react": "^19.2.8",
|
|
75
77
|
"react-dom": "^19.2.8",
|
|
76
78
|
"typescript": "~6.0.2",
|
|
77
79
|
"vite": "^8.3.0",
|
|
78
|
-
"vitest": "^5.0.0"
|
|
80
|
+
"vitest": "^5.0.0",
|
|
81
|
+
"electron": "^44.4.5"
|
|
79
82
|
}
|
|
80
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-info.d.ts","sourceRoot":"","sources":["../../src/build-info.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,QAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"build-info.d.ts","sourceRoot":"","sources":["../../src/build-info.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,QAAsB,CAAC;AAGlD,eAAO,MAAM,iBAAiB,QAA0B,CAAC;AACzD,eAAO,MAAM,eAAe,KAAuE,CAAC;AACpG,eAAO,MAAM,kBAAkB,QAA6B,CAAC"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import packageJson from '../package.json';
|
|
1
|
+
import packageJson from '../package.json' with { type: 'json' };
|
|
2
2
|
export const RUNNER_VERSION = packageJson.version;
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/** Product release label used in the application chrome. */
|
|
4
|
+
const alphaRelease = /^0\.\d+\.\d+-alpha\.(\d+)$/.exec(RUNNER_VERSION)?.[1] ?? RUNNER_VERSION;
|
|
5
|
+
export const RUNNER_UI_VERSION = `Alpha ${alphaRelease}`;
|
|
6
|
+
export const RUNNER_BUILD_ID = import.meta.env?.VITE_BUILD_ID ?? import.meta.env?.MODE ?? 'unknown';
|
|
7
|
+
export const RUNNER_BUILD_LABEL = `build ${RUNNER_BUILD_ID}`;
|
|
5
8
|
//# sourceMappingURL=build-info.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-info.js","sourceRoot":"","sources":["../../src/build-info.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,MAAM,CAAC,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC;AAClD,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,
|
|
1
|
+
{"version":3,"file":"build-info.js","sourceRoot":"","sources":["../../src/build-info.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,MAAM,CAAC,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC;AAClD,4DAA4D;AAC5D,MAAM,YAAY,GAAG,4BAA4B,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC;AAC9F,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,YAAY,EAAE,CAAC;AACzD,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,SAAS,CAAC;AACpG,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,eAAe,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunnerWalkthrough.d.ts","sourceRoot":"","sources":["../../../src/demo/RunnerWalkthrough.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RunnerWalkthrough.d.ts","sourceRoot":"","sources":["../../../src/demo/RunnerWalkthrough.tsx"],"names":[],"mappings":"AAgCA,wBAAgB,iBAAiB,gCAIhC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import '
|
|
3
|
+
import { RUNNER_UI_VERSION } from '../build-info.js';
|
|
4
4
|
const steps = [
|
|
5
5
|
{ id: 'overview', title: 'Runner overview', action: 'Start with the loaded execution package.', detail: 'Runner loads a durable QAick artifact, lets you choose a target, executes it, and presents structured evidence.' },
|
|
6
6
|
{ id: 'package', title: 'Load and select a package', action: 'Choose a Project or Flow target.', detail: 'The package selector lists the available target. Load package accepts the serialized file produced by Studio.' },
|
|
@@ -13,7 +13,7 @@ const steps = [
|
|
|
13
13
|
function Balloon({ className, title, children }) { return _jsxs("div", { className: `runner-demo-balloon ${className}`, children: [_jsx("strong", { children: title }), _jsx("span", { children: children })] }); }
|
|
14
14
|
function RunnerScreen({ step }) {
|
|
15
15
|
const focus = step.id === 'overview' ? 'focus-all' : `focus-${step.id}`;
|
|
16
|
-
return _jsxs("div", { className: `runner-demo-screen ${focus}`, children: [_jsxs("div", { className: "runner-demo-top", children: [_jsx("b", { children: "QAick Runner" }), _jsx("span", { children:
|
|
16
|
+
return _jsxs("div", { className: `runner-demo-screen ${focus}`, children: [_jsxs("div", { className: "runner-demo-top", children: [_jsx("b", { children: "QAick Runner" }), _jsx("span", { children: RUNNER_UI_VERSION }), _jsx("span", { className: "runner-demo-menu", children: "Execution Package\u3000 Projects\u3000 Flows\u3000 Run History" }), _jsx("span", { children: "\u2193 Customer Checkout" }), _jsx("button", { children: "Pre-run validation" })] }), _jsxs("div", { className: "runner-demo-body", children: [_jsxs("div", { className: "runner-demo-nav", children: [_jsx("b", { children: "Execution" }), _jsx("b", { children: "Projects" }), _jsx("b", { children: "Flows" }), _jsx("b", { children: "History" })] }), _jsxs("div", { className: "runner-demo-left", children: [_jsx("small", { children: "PACKAGE" }), _jsx("strong", { children: "checkout-project.qaick.json" }), _jsx("button", { children: "Open demo" }), _jsx("small", { children: "TARGET" }), _jsx("div", { className: "is-selected", children: "Customer Checkout" }), _jsx("small", { children: "CONFIGURATION" }), _jsx("div", { children: "Environment\u3000test" }), _jsx("div", { children: "Timeout\u3000none" }), _jsx("div", { children: "Inputs\u30003 values" })] }), _jsxs("div", { className: "runner-demo-main", children: [_jsxs("div", { className: "runner-demo-heading", children: [_jsx("small", { children: "LIVE EXECUTION" }), _jsx("b", { children: "Customer Checkout" }), _jsx("span", { children: "\u25CF completed" })] }), _jsxs("div", { className: "runner-demo-rows", children: [_jsxs("div", { className: "runner-demo-row operation", children: [_jsx("i", { children: "\u2713" }), _jsx("b", { children: "Create Payment Context" }), _jsx("em", { children: "operation \u00B7 finished \u00B7 142 ms" })] }), _jsxs("div", { className: "runner-demo-loop", children: [_jsxs("header", { children: [_jsx("i", { children: "\u21BB" }), _jsx("b", { children: "Ten checkout checks" }), _jsx("span", { children: "LOOP \u00B7 10 / 10 \u00B7 1.7 s" })] }), _jsxs("div", { className: "runner-demo-row nested", children: [_jsx("i", { children: "\u2713" }), _jsx("b", { children: "Get Payment Status" }), _jsx("em", { children: "action \u00B7 finished \u00B7 48 ms" })] }), _jsxs("div", { className: "runner-demo-row nested alt", children: [_jsx("i", { children: "\u2713" }), _jsx("b", { children: "Verify Record" }), _jsx("em", { children: "action \u00B7 finished \u00B7 34 ms" })] }), _jsx("div", { className: "runner-demo-bar", children: _jsx("span", { style: { width: '100%' } }) })] }), _jsxs("div", { className: "runner-demo-row operation", children: [_jsx("i", { children: "\u2713" }), _jsx("b", { children: "Verify Settlement" }), _jsx("em", { children: "operation \u00B7 finished \u00B7 86 ms" })] })] })] }), _jsxs("div", { className: "runner-demo-right", children: [_jsx("b", { children: step.id === 'preflight' ? 'Pre-run validation' : step.id === 'events' ? 'Event Log' : step.id === 'results' ? 'Run History' : 'Execution Details' }), step.id === 'preflight' ? _jsxs(_Fragment, { children: [_jsx("div", { className: "demo-error", children: "\u2713 0 issues found" }), _jsx("small", { children: "Adapters have not been invoked." })] }) : step.id === 'events' ? _jsxs(_Fragment, { children: [_jsx("div", { className: "demo-filter", children: "Search events\u3000\u3000Failures \u25BE" }), _jsx("div", { className: "demo-event", children: "STEP_FINISHED\u3000Verify Record" }), _jsx("div", { className: "demo-event", children: "PARALLEL_PROGRESS\u300010 / 10" })] }) : step.id === 'results' ? _jsxs(_Fragment, { children: [_jsx("div", { className: "demo-history", children: "Customer Checkout\u3000completed" }), _jsx("div", { className: "demo-history", children: "Export result JSON\u3000\u2197" })] }) : _jsxs(_Fragment, { children: [_jsx("small", { children: "Run outcome" }), _jsx("strong", { children: "COMPLETED" }), _jsx("small", { children: "Outputs" }), _jsx("div", { className: "demo-output", children: "paymentId = pay_demo" })] })] })] }), _jsxs("div", { className: "runner-demo-bottom", children: [_jsx("b", { children: step.id === 'preflight' ? 'PRE-RUN VALIDATION' : 'RUN RESULT' }), _jsx("span", { children: step.id === 'events' ? '3 events shown' : step.id === 'results' ? '2 stored runs' : 'Ready' })] }), _jsx("div", { className: "runner-demo-callouts", children: step.id === 'overview' ? _jsxs(_Fragment, { children: [_jsx(Balloon, { className: "demo-callout-left", title: "Package", children: "Load serialized artifacts here." }), _jsx(Balloon, { className: "demo-callout-canvas", title: "Execution hierarchy", children: "Observe nested steps and loops." }), _jsx(Balloon, { className: "demo-callout-right", title: "Inspector", children: "Inspect structured evidence." })] }) : _jsx(Balloon, { className: `demo-callout-${step.id}`, title: step.title, children: step.detail }) })] });
|
|
17
17
|
}
|
|
18
18
|
export function RunnerWalkthrough() {
|
|
19
19
|
const [index, setIndex] = useState(0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunnerWalkthrough.js","sourceRoot":"","sources":["../../../src/demo/RunnerWalkthrough.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"RunnerWalkthrough.js","sourceRoot":"","sources":["../../../src/demo/RunnerWalkthrough.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunnerModule.d.ts","sourceRoot":"","sources":["../../../src/runner/RunnerModule.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"RunnerModule.d.ts","sourceRoot":"","sources":["../../../src/runner/RunnerModule.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAiB5D,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AASD,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,QAAoC,EAAE,MAAM,EAAE,EAAE,iBAAiB,+BAEvG"}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { checkoutNestedPackage, checkoutPackage, checkoutProjectPackage } from './fixture';
|
|
4
|
-
import { loadExecutionPackage, PackageLoadError } from './package-loader';
|
|
5
|
-
import { PackageCatalog } from './catalog';
|
|
6
|
-
import { RUNNER_CONTRACT_VERSION } from './types';
|
|
7
|
-
import { RunnerWalkthrough } from '../demo/RunnerWalkthrough';
|
|
8
|
-
import { RUNNER_BUILD_LABEL } from '../build-info';
|
|
9
|
-
import { collectSecretValues, redactExecutionEvent, redactExecutionResult, redactKeyValuePairs } from './redaction';
|
|
10
|
-
import { createResultExport } from './result-export';
|
|
11
|
-
import { persistRunHistory } from './history';
|
|
3
|
+
import { checkoutNestedPackage, checkoutPackage, checkoutProjectPackage } from './fixture.js';
|
|
4
|
+
import { loadExecutionPackage, PackageLoadError } from './package-loader.js';
|
|
5
|
+
import { PackageCatalog } from './catalog.js';
|
|
6
|
+
import { RUNNER_CONTRACT_VERSION } from './types.js';
|
|
7
|
+
import { RunnerWalkthrough } from '../demo/RunnerWalkthrough.js';
|
|
8
|
+
import { RUNNER_BUILD_LABEL, RUNNER_UI_VERSION } from '../build-info.js';
|
|
9
|
+
import { collectSecretValues, redactExecutionEvent, redactExecutionResult, redactKeyValuePairs } from './redaction.js';
|
|
10
|
+
import { createResultExport } from './result-export.js';
|
|
11
|
+
import { persistRunHistory } from './history.js';
|
|
12
12
|
const HISTORY_KEY = 'qaick-runner.history.v1';
|
|
13
13
|
const HISTORY_RETENTION_KEY = 'qaick-runner.history-retention.v1';
|
|
14
14
|
const IMPORTED_PACKAGE_KEY = 'qaick-runner.imported-package.v1';
|
|
15
|
+
const THEME_STORAGE_KEY = 'qaick-studio-theme';
|
|
15
16
|
function readRunHistory() { try {
|
|
16
17
|
const stored = localStorage.getItem(HISTORY_KEY);
|
|
17
18
|
if (!stored)
|
|
@@ -38,6 +39,12 @@ function readImportedPackage() { try {
|
|
|
38
39
|
catch {
|
|
39
40
|
return undefined;
|
|
40
41
|
} }
|
|
42
|
+
function readTheme() { try {
|
|
43
|
+
return localStorage.getItem(THEME_STORAGE_KEY) === 'light' ? 'light' : 'dark';
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return 'dark';
|
|
47
|
+
} }
|
|
41
48
|
const packageCatalog = new PackageCatalog();
|
|
42
49
|
packageCatalog.addPackage(checkoutPackage);
|
|
43
50
|
packageCatalog.addPackage(checkoutProjectPackage);
|
|
@@ -50,7 +57,7 @@ export function RunnerModule({ client, showDemo = standaloneDemoRequested(), onE
|
|
|
50
57
|
}
|
|
51
58
|
function standaloneDemoRequested() { return typeof window !== 'undefined' && new URLSearchParams(window.location.search).has('demo'); }
|
|
52
59
|
function RunnerApp({ client, onExit }) {
|
|
53
|
-
const [theme, setTheme] = useState(
|
|
60
|
+
const [theme, setTheme] = useState(readTheme);
|
|
54
61
|
const [showAbout, setShowAbout] = useState(false);
|
|
55
62
|
const [environment, setEnvironment] = useState('test');
|
|
56
63
|
const [executionPackage, setExecutionPackage] = useState(restoredImportedPackage ?? checkoutPackage);
|
|
@@ -208,20 +215,28 @@ function RunnerApp({ client, onExit }) {
|
|
|
208
215
|
}
|
|
209
216
|
}
|
|
210
217
|
const statusLabel = runState === 'ready' ? 'Ready' : runState[0].toUpperCase() + runState.slice(1);
|
|
211
|
-
useEffect(() => {
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
document.documentElement.dataset.theme = theme;
|
|
220
|
+
document.documentElement.style.colorScheme = theme;
|
|
221
|
+
try {
|
|
222
|
+
localStorage.setItem(THEME_STORAGE_KEY, theme);
|
|
223
|
+
}
|
|
224
|
+
catch { /* storage may be unavailable */ }
|
|
225
|
+
return () => { delete document.documentElement.dataset.theme; document.documentElement.style.colorScheme = ''; };
|
|
226
|
+
}, [theme]);
|
|
212
227
|
useEffect(() => { const close = () => setContextMenu(undefined); const keydown = (event) => { if (event.key === 'Escape')
|
|
213
228
|
close(); }; document.addEventListener('click', close); document.addEventListener('keydown', keydown); return () => { document.removeEventListener('click', close); document.removeEventListener('keydown', keydown); }; }, []);
|
|
214
229
|
useEffect(() => { if (runState !== 'preflighting' && runState !== 'running')
|
|
215
230
|
return undefined; const timer = window.setInterval(() => setClock(Date.now()), 250); return () => window.clearInterval(timer); }, [runState]);
|
|
216
231
|
useEffect(() => { const navigateIssue = (event) => { const target = event.target; const issue = target.closest('.validation-issue'); const stepId = issue?.dataset.stepId; const eventRow = target.closest('.event-row'); const index = stepId ? displaySteps.findIndex(step => step.id === stepId || step.id.endsWith(`.${stepId}`)) : eventRow ? displaySteps.findIndex(step => eventRow.textContent?.includes(step.name)) : -1; if (index >= 0)
|
|
217
232
|
setSelectedStep(index); }; document.addEventListener('click', navigateIssue); return () => document.removeEventListener('click', navigateIssue); }, [displaySteps]);
|
|
218
|
-
return _jsxs("div", { className: "runner-shell", children: [_jsxs("header", { className: "runner-header", children: [_jsxs("div", { className: "runner-brand", children: [_jsx("span", { className: "runner-brand-mark", children: "QAICK" }), _jsx("span", { className: "runner-brand-product", children: "Runner" }), _jsx("span", { className: "alpha-label", children:
|
|
233
|
+
return _jsxs("div", { className: "runner-shell", children: [_jsxs("header", { className: "runner-header", children: [_jsxs("div", { className: "runner-brand", children: [_jsx("span", { className: "runner-brand-mark", children: "QAICK" }), _jsx("span", { className: "runner-brand-product", children: "Runner" }), _jsx("span", { className: "alpha-label", children: RUNNER_UI_VERSION }), onExit && _jsx("button", { className: "about-button", onClick: onExit, children: "Studio" })] }), _jsx("span", { className: "header-spacer" }), _jsx("a", { className: "demo-entry", href: "?demo", children: "View demo" }), _jsx("button", { className: "about-button", onClick: () => setShowAbout(true), children: "About" }), _jsxs("label", { className: "theme-picker", children: ["Theme", _jsxs("select", { value: theme, onChange: event => setTheme(event.target.value), children: [_jsx("option", { value: "light", children: "Light" }), _jsx("option", { value: "dark", children: "Dark" })] })] })] }), _jsxs("main", { className: "runner-main", children: [_jsxs("nav", { className: "runner-nav", children: [_jsx("p", { className: "nav-label", children: "Workspace" }), _jsx(NavItem, { active: true, icon: "\u25C8", text: "Execution Package" }), _jsx(NavItem, { icon: "\u25A1", text: "Projects" }), _jsx(NavItem, { icon: "\u2318", text: "Flows" }), _jsx(NavItem, { icon: "\u21B6", text: "Run History" }), _jsxs("div", { className: "package-card", children: [_jsx("small", { children: "Loaded package" }), _jsxs("strong", { children: [executionPackage.packageId, ".qaick.json"] }), _jsxs("small", { children: ["Schema ", executionPackage.schemaVersion, " \u00B7 ", executionPackage.definitions.length, " definitions"] })] })] }), _jsxs("section", { className: "runner-workspace", children: [_jsx("div", { className: "eyebrow", children: "EXECUTION PACKAGE" }), _jsx("h1", { children: executionPackage.target.name }), _jsxs("p", { className: "description", children: ["Execute the selected QAick ", executionPackage.target.kind === 'project' ? 'Project' : 'Flow', " and capture structured evidence."] }), _jsxs("div", { className: "run-controls", children: [_jsxs("label", { children: ["Target", _jsx("select", { value: executionPackage.packageId, onChange: event => { const next = packageCatalog.get(event.target.value); setExecutionPackage(next); setBreakpoints(new Set()); breakpointsRef.current = new Set(); setStopAfterStepId(undefined); setLoadError(undefined); setLoadIssues([]); setRuntimeValues(Object.fromEntries((next.runtimeRequirements ?? []).map(name => [name, '']))); setStepStates((next.target.kind === 'project' ? next.flows?.flatMap(flow => flattenDisplaySteps(flow.steps)) ?? [] : flattenDisplaySteps(next.steps)).map(() => 'pending')); setLoopProgress(loopProgressFor(next.target.kind === 'project' ? next.flows?.flatMap(flow => flow.steps) ?? [] : next.steps)); setSelectedStep(0); setResult(undefined); setEvents([]); setRunState('ready'); }, children: packageCatalog.targets().map(item => _jsx("option", { value: item.packageId, children: item.target.name }, item.packageId)) })] }), _jsxs("label", { children: ["Environment", _jsxs("select", { value: environment, onChange: event => setEnvironment(event.target.value), children: [_jsx("option", { children: "test" }), _jsx("option", { children: "local" }), _jsx("option", { children: "staging" })] })] }), _jsxs("label", { children: ["Timeout", _jsxs("select", { value: timeoutMs, onChange: event => setTimeoutMs(event.target.value), children: [_jsx("option", { value: "none", children: "None" }), _jsx("option", { value: "1000", children: "1 second" }), _jsx("option", { value: "3000", children: "3 seconds" }), _jsx("option", { value: "10000", children: "10 seconds" })] })] }), _jsxs("label", { children: ["Run configuration", _jsxs("select", { defaultValue: "Default", children: [_jsx("option", { children: "Default" }), _jsx("option", { children: "Debug" })] })] }), _jsxs("label", { className: "file-button", children: ["Load package", _jsx("input", { type: "file", accept: "application/json,.json", onChange: event => void loadPackage(event.target.files?.[0]) })] }), _jsx("button", { className: "button", onClick: () => setEditingInputs(value => !value), children: editingInputs ? 'Done inputs' : 'Edit inputs' }), _jsx("button", { className: "button primary", onClick: () => void run(), disabled: runState === 'preflighting' || runState === 'running', children: "\u25B6\u00A0 Run" }), _jsx("button", { className: "button dry-run", onClick: () => void run(true), disabled: runState === "preflighting" || runState === "running", children: "\u25CE\u00A0 Pre-run validation" }), _jsx("button", { className: "button stop", onClick: () => void stop(), disabled: runState !== 'preflighting' && runState !== 'running', children: "\u25A0\u00A0 Stop" }), _jsx("button", { className: "button", onClick: () => void pause(), disabled: controlState !== 'running', children: "\u2161\u00A0 Pause" }), _jsx("button", { className: `button ${controlState === 'paused' ? 'resume-highlight' : ''}`, onClick: () => void resume(), disabled: controlState !== 'paused', children: "\u25B6\u00A0 Resume" }), _jsx("button", { className: "button", onClick: () => void stepExecution(), disabled: controlState !== 'paused', children: "\u21A6\u00A0 Step" }), breakpoints.size > 0 && _jsxs("span", { className: "debug-session-badge", children: [breakpoints.size, " breakpoint", breakpoints.size === 1 ? "" : "s", " armed"] })] }), viewingHistoryEntry && _jsxs("div", { className: "history-view-banner", children: ["Viewing stored results \u00B7 ", viewingHistoryEntry] }), loadError && _jsx("p", { className: "load-error", children: loadError }), loadIssues.length > 0 && _jsx(PreRunValidation, { issues: loadIssues, title: "Artifact validation" }), result?.issues !== undefined && _jsx(PreRunValidation, { issues: result.issues }), result?.warnings !== undefined && result.warnings.length > 0 && _jsx(PreRunValidation, { issues: result.warnings, title: "Browser execution warnings" }), editingInputs && _jsxs("section", { className: "inputs-panel panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Invocation Inputs" }), _jsx("span", { className: "panel-spacer" }), _jsx("span", { className: "input-hint", children: "Values are sent with the next run" })] }), _jsxs("div", { className: "input-grid", children: [_jsx(InputField, { label: "customerId", value: String(inputs.customerId ?? ''), onChange: value => setInputs(previous => ({ ...previous, customerId: value })) }), _jsx(InputField, { label: "orderId", value: String(inputs.orderId ?? ''), onChange: value => setInputs(previous => ({ ...previous, orderId: value })) }), _jsx(InputField, { label: "amount", value: String(inputs.amount ?? ''), onChange: value => setInputs(previous => ({ ...previous, amount: value })) }), (executionPackage.requiredInputs ?? []).filter(name => !['customerId', 'orderId', 'amount'].includes(name)).map(name => _jsx(InputField, { label: name, value: String(inputs[name] ?? ''), onChange: value => setInputs(previous => ({ ...previous, [name]: value })) }, name)), (executionPackage.runtimeRequirements ?? []).map(name => _jsx(InputField, { label: `Runtime · ${name}`, value: runtimeValues[name] ?? '', onChange: value => setRuntimeValues(previous => ({ ...previous, [name]: value })) }, name))] })] }), _jsxs("section", { className: "panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Live Execution" }), _jsx("span", { className: "panel-spacer" }), _jsxs("span", { className: "execution-menu-label", children: ["Right-click a row to manage its breakpoint \u00B7 Selected: ", displaySteps[selectedStep]?.name ?? 'None'] }), _jsxs("span", { className: runState === 'running' ? 'running' : runState === 'failed' ? 'stopped' : 'run-status', children: ["\u25CF ", statusLabel] })] }), hasNestedSteps && _jsxs("div", { className: "hierarchy-hint", children: [_jsx("strong", { children: "Nested execution" }), _jsx("span", { children: "Use \u2212 / + to collapse or expand nested Operations, Control Blocks, and loops." }), _jsx("button", { className: "hierarchy-action", onClick: () => setAllCollapsed(true), children: "Collapse all" }), _jsx("button", { className: "hierarchy-action", onClick: () => setAllCollapsed(false), children: "Expand all" })] }), _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "#" }), _jsx("th", { children: "Step hierarchy" }), _jsx("th", { children: "Status" }), _jsx("th", { children: "Start time" }), _jsx("th", { children: "Duration" })] }) }), _jsx("tbody", { children: displaySteps.map((step, index) => { const progress = step.loopTotal ? loopProgress[step.id] ?? { current: 0, total: step.loopTotal } : undefined; const percent = progress ? Math.round(progress.current / progress.total * 100) : 0; const isLoop = Boolean(step.loopTotal); const displayState = displayResults[index]?.state ?? stepStates[index] ?? 'pending'; const isLoopContent = Boolean(step.loopId); const isLoopEnd = isLoopContent && displaySteps[index + 1]?.loopId !== step.loopId; const elapsed = step.loopId && loopStartedAt[step.loopId] ? formatElapsed(clock - loopStartedAt[step.loopId]) : undefined; return _jsxs("tr", { className: `${selectedStep === index ? 'selected ' : ''}${isLoop ? 'loop-row ' : ''}${isLoopContent ? 'loop-content ' : ''}${isLoopEnd ? 'loop-end ' : ''}${step.depth > 0 ? 'nested-row' : 'parent-row'}`, tabIndex: 0, onKeyDown: event => { if (event.key === "ArrowDown") {
|
|
219
234
|
event.preventDefault();
|
|
220
235
|
setSelectedStep(Math.min(displaySteps.length - 1, index + 1));
|
|
221
236
|
} if (event.key === "ArrowUp") {
|
|
222
237
|
event.preventDefault();
|
|
223
238
|
setSelectedStep(Math.max(0, index - 1));
|
|
224
|
-
} }, onClick: () => setSelectedStep(index), onContextMenu: event => { event.preventDefault(); setSelectedStep(index); setContextMenu({ x: event.clientX, y: event.clientY, stepId: step.id }); }, children: [_jsx("td", { children: index + 1 }), _jsxs("td", { children: [_jsx("span", { className: `step-icon ${isLoop ? 'loop-icon' : displayState}`, children: isLoop ? '↻' : displayState === 'finished' ? '✓' : displayState === 'waiting' ? '◷' : displayState === 'skipped' ? '–' : '' }), _jsxs("span", { className: "hierarchy-name", style: { paddingLeft: `${step.depth * 18}px` }, children: [step.depth > 0 && _jsx("span", { className: "branch-marker", children: "\u2514" }), step.hasChildren && _jsx("button", { className: "collapse-toggle", "aria-label": `${collapsedSteps.has(step.id) ? 'Expand' : 'Collapse'} ${step.name}`, onClick: event => { event.stopPropagation(); toggleStep(step.id); }, children: collapsedSteps.has(step.id) ? '+' : '−' }), _jsx("span", { children: step.name }), breakpoints.has(step.id) && _jsx("small", { className: "breakpoint-marker", "aria-label": "Breakpoint armed", title: "Breakpoint armed", children: "STOP" }), isLoop && _jsx("small", { className: "kind-label loop-label", children: "LOOP" }), step.depth > 0 ? _jsx("small", { className: "kind-label nested-label", children: "NESTED STEP" }) : !isLoop && _jsx("small", { className: "kind-label", children: step.kind.toUpperCase() })] }), selectedStep === index && _jsx("small", { className: "selected-label", children: "SELECTED" })] }), _jsxs("td", { children: [progress && _jsxs("div", { className: "loop-progress", children: [_jsxs("strong", { children: ["REPEAT LOOP \u00B7 ITERATION ", progress.current, " OF ", progress.total] }), _jsx("span", { className: "loop-bar", children: _jsx("i", { style: { width: `${percent}%` } }) }), _jsx("small", { children: elapsed ? `Elapsed ${elapsed}` : 'Waiting to start' })] }), _jsx("span", { className: `status ${displayState}`, children: isLoop ? 'LOOP' : displayState.toUpperCase() })] }), _jsx("td", { children: displayResults[index] ? new Date(result?.finishedAt ?? '').toLocaleTimeString() : '—' }), _jsx("td", { children: displayResults[index] ? `${displayResults[index].durationMs} ms` : '—' })] }, `${step.id}-${index}`); }) })] }), contextMenu && _jsxs("div", { className: "runner-context-menu", style: { left: contextMenu.x, top: contextMenu.y }, onClick: event => event.stopPropagation(), onContextMenu: event => event.preventDefault(), children: [_jsx("strong", { children: "Breakpoint" }), breakpoints.has(contextMenu.stepId) ? _jsx("button", { onClick: () => { toggleBreakpoint(contextMenu.stepId); setContextMenu(undefined); }, children: "Remove breakpoint" }) : _jsx("button", { onClick: () => { toggleBreakpoint(contextMenu.stepId); setContextMenu(undefined); }, children: "Add breakpoint" })] })] }), _jsxs("section", { className: "panel event-panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Event Log" }), _jsx("span", { className: "panel-spacer" }), _jsx("input", { className: "event-search", "aria-label": "Search event log", placeholder: "Search events", value: eventSearch, onChange: event => setEventSearch(event.target.value) }), _jsxs("select", { className: "event-filter", value: eventFilter, onChange: event => setEventFilter(event.target.value), children: [_jsx("option", { value: "all", children: "All events" }), _jsx("option", { value: "steps", children: "Step events" }), _jsx("option", { value: "parallel", children: "Parallel groups" }), _jsx("option", { value: "lifecycle", children: "Lifecycle" }), _jsx("option", { value: "failures", children: "Failures" })] })] }), _jsx("table", { children: _jsx("tbody", { children: visibleEvents.map(event => _jsxs("tr", { className: "event-row", children: [_jsx("td", { children: new Date(event.timestamp).toLocaleTimeString() }), _jsx("td", { children: event.state.toUpperCase() }), _jsx("td", { children: _jsx("code", { children: event.type.toUpperCase() }) }), _jsxs("td", { children: [event.message, event.parallel && _jsxs("small", { className: "parallel-event", children: [" \u00B7 Parallel ", event.parallel.completed, "/", event.parallel.total, " (", event.parallel.join, ")"] })] })] }, event.sequence)) }) }), events.length > 0 && visibleEvents.length === 0 && _jsx("p", { className: "empty-state", children: "No events match the current filter." })] }), _jsx(HistoryPanel, { entries: runHistory, onReload: reloadHistoryEntry, retention: historyRetention, onRetentionChange: changeHistoryRetention, onClear: clearHistory, onDelete: deleteHistoryEntry, onExport: exportResult })] }), _jsxs("aside", { className: "inspector", children: [_jsx("h2", { children: "Selected execution" }), _jsx("p", { className: "selected-detail-name", children: _jsx("strong", { children: displaySteps[selectedStep]?.name ?? 'No step selected' }) }), _jsxs("p", { className: "run-id", children: ["Run ID: ", requestId ?? 'No run started'] }), _jsx(InspectorSection, { title: "Artifact summary", children: _jsx(KeyValues, { values: ["Target", executionPackage.target.name, "Type", executionPackage.target.kind, "Package", executionPackage.packageId, "Artifact schema", String(executionPackage.schemaVersion), "Definitions", String(executionPackage.definitions.length), "Required inputs", (executionPackage.requiredInputs ?? []).join(", ") || "None", "Runtime values", (executionPackage.runtimeRequirements ?? []).join(", ") || "None"] }) }), _jsx(InspectorSection, { title: "Run outcome", children: _jsxs("div", { className: "notice", children: [_jsx("strong", { children: result?.terminalReason?.toUpperCase() ?? 'NOT STARTED' }), _jsx("br", {}), result ? `${result.environment} · ${result.state}` : 'Run the package to inspect its terminal outcome.'] }) }), _jsx(InspectorSection, { title: "Selected step inputs", children: _jsx(KeyValues, { values: Object.entries(displayResults[selectedStep]?.inputs ?? inputs).flatMap(([key, value]) => [key, String(value)]) }) }), _jsx(InspectorSection, { title: "Selected step outputs", children: _jsx(KeyValues, { values: displayResults[selectedStep]?.outputs ? Object.entries(displayResults[selectedStep]?.outputs ?? {}).flatMap(([key, value]) => [key, String(value)]) : ['—', 'Available after execution'] }) }), (result?.error || displayResults[selectedStep]?.error) && _jsx(InspectorSection, { title: "Error", children: _jsxs("div", { className: "error-notice", children: [_jsx("strong", { children: displayResults[selectedStep]?.error?.code ?? result?.error?.code }), _jsx("br", {}), displayResults[selectedStep]?.error?.message ?? result?.error?.message] }) }), result?.issues !== undefined && _jsx(InspectorSection, { title: "Pre-run validation", children: _jsx(PreRunValidation, { issues: result.issues }) }), _jsx(InspectorSection, { title: "Invocation path", children: _jsx("div", { className: "notice", children: displayResults[selectedStep]?.invocationPath?.join(" › ") ?? "No invocation path available." }) }), _jsx(InspectorSection, { title: "Iteration history", children: _jsx(IterationHistory, { result: displayResults[selectedStep] }) }), _jsx(InspectorSection, { title: "Execution timing", children: _jsxs("div", { className: "timing-details", children: [_jsxs("span", { children: ["Wall ", result?.executionTiming?.wallDurationMs ?? "—", " ms"] }), _jsxs("span", { children: ["Active ", result?.executionTiming?.activeDurationMs ?? "—", " ms"] }), _jsxs("span", { children: ["Paused ", result?.executionTiming?.pausedDurationMs ?? "—", " ms"] })] }) }), _jsx(InspectorSection, { title: "Selected step attempts", children: _jsx("div", { className: "attempt-history", children: displayResults[selectedStep]?.attempts?.map(attempt => _jsxs("div", { className: "iteration-entry", children: [_jsxs("strong", { children: ["Attempt ", attempt.attempt] }), _jsxs("span", { children: [attempt.kind.toUpperCase(), " \u00B7 ", attempt.state.toUpperCase(), " \u00B7 ", attempt.durationMs, " ms"] })] }, `${attempt.attempt}-${attempt.kind}`)) ?? _jsx("div", { className: "notice", children: "No retry attempts recorded." }) }) }), _jsxs(InspectorSection, { title: "Selected step", children: [_jsxs("div", { className: "notice", children: [_jsx("strong", { children: displaySteps[selectedStep]?.name ?? 'No step selected' }), _jsx("br", {}), displayResults[selectedStep] ? displayResults[selectedStep].error ? 'This step failed. See the error details above.' : `Completed in ${displayResults[selectedStep].durationMs} ms.` : 'Run the package to inspect execution details.', _jsxs("div", { className: "inspector-actions", children: [_jsx("button", { className: "button", onClick: () => void retrySelected(), disabled: !displayResults[selectedStep] || (!displayResults[selectedStep]?.error && runState !== "completed"), children: "Retry Action" }), _jsx("button", { className: `button ${stopAfterStepId === displaySteps[selectedStep]?.id ? "active" : ""}`, onClick: () => displaySteps[selectedStep] && toggleStopAfter(displaySteps[selectedStep].id), disabled: !displaySteps[selectedStep], children: "Stop After" }), _jsx("button", { className: "button", onClick: () => void runFromSelected(), disabled: !displayResults[selectedStep] || runState === "running", children: "Run From Here" })] })] }), _jsxs("div", { className: "selection-nav", children: [_jsx("button", { className: "button", disabled: selectedStep <= 0, onClick: () => setSelectedStep(index => Math.max(0, index - 1)), children: "\u2039 Previous" }), _jsx("span", { children: displaySteps.length ? `${selectedStep + 1} / ${displaySteps.length}` : '0 / 0' }), _jsx("button", { className: "button", disabled: selectedStep >= displaySteps.length - 1, onClick: () => setSelectedStep(index => Math.min(displaySteps.length - 1, index + 1)), children: "Next \u203A" })] })] })] })] }), showAbout && _jsx("div", { className: "about-backdrop", onClick: () => setShowAbout(false), children: _jsxs("section", { className: "about-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "about-title", onClick: event => event.stopPropagation(), children: [_jsx("button", { className: "about-close", onClick: () => setShowAbout(false), "aria-label": "Close About", children: "\u00D7" }), _jsx("div", { className: "runner-logo", children: "\u25B6" }), _jsx("h2", { id: "about-title", children: "QAick Runner" }), _jsx("p", { children: "Standalone execution and evidence viewer for QAick packages." }), _jsxs("small", { children: ["Alpha 7 \u00B7 ", RUNNER_BUILD_LABEL, " \u00B7 QAick contract"] }), _jsx("footer", { children: "\u00A9 2006\u20132026 QAick. All rights reserved." })] }) }), _jsx("div", { className: "draft-badge", children: "SHARED EXECUTOR \u00B7 ALPHA 7" })] });
|
|
239
|
+
} }, onClick: () => setSelectedStep(index), onContextMenu: event => { event.preventDefault(); setSelectedStep(index); setContextMenu({ x: event.clientX, y: event.clientY, stepId: step.id }); }, children: [_jsx("td", { children: index + 1 }), _jsxs("td", { children: [_jsx("span", { className: `step-icon ${isLoop ? 'loop-icon' : displayState}`, children: isLoop ? '↻' : displayState === 'finished' ? '✓' : displayState === 'waiting' ? '◷' : displayState === 'skipped' ? '–' : '' }), _jsxs("span", { className: "hierarchy-name", style: { paddingLeft: `${step.depth * 18}px` }, children: [step.depth > 0 && _jsx("span", { className: "branch-marker", children: "\u2514" }), step.hasChildren && _jsx("button", { className: "collapse-toggle", "aria-label": `${collapsedSteps.has(step.id) ? 'Expand' : 'Collapse'} ${step.name}`, onClick: event => { event.stopPropagation(); toggleStep(step.id); }, children: collapsedSteps.has(step.id) ? '+' : '−' }), _jsx("span", { children: step.name }), breakpoints.has(step.id) && _jsx("small", { className: "breakpoint-marker", "aria-label": "Breakpoint armed", title: "Breakpoint armed", children: "STOP" }), isLoop && _jsx("small", { className: "kind-label loop-label", children: "LOOP" }), step.depth > 0 ? _jsx("small", { className: "kind-label nested-label", children: "NESTED STEP" }) : !isLoop && _jsx("small", { className: "kind-label", children: step.kind.toUpperCase() })] }), selectedStep === index && _jsx("small", { className: "selected-label", children: "SELECTED" })] }), _jsxs("td", { children: [progress && _jsxs("div", { className: "loop-progress", children: [_jsxs("strong", { children: ["REPEAT LOOP \u00B7 ITERATION ", progress.current, " OF ", progress.total] }), _jsx("span", { className: "loop-bar", children: _jsx("i", { style: { width: `${percent}%` } }) }), _jsx("small", { children: elapsed ? `Elapsed ${elapsed}` : 'Waiting to start' })] }), _jsx("span", { className: `status ${displayState}`, children: isLoop ? 'LOOP' : displayState.toUpperCase() })] }), _jsx("td", { children: displayResults[index] ? new Date(result?.finishedAt ?? '').toLocaleTimeString() : '—' }), _jsx("td", { children: displayResults[index] ? `${displayResults[index].durationMs} ms` : '—' })] }, `${step.id}-${index}`); }) })] }), contextMenu && _jsxs("div", { className: "runner-context-menu", style: { left: contextMenu.x, top: contextMenu.y }, onClick: event => event.stopPropagation(), onContextMenu: event => event.preventDefault(), children: [_jsx("strong", { children: "Breakpoint" }), breakpoints.has(contextMenu.stepId) ? _jsx("button", { onClick: () => { toggleBreakpoint(contextMenu.stepId); setContextMenu(undefined); }, children: "Remove breakpoint" }) : _jsx("button", { onClick: () => { toggleBreakpoint(contextMenu.stepId); setContextMenu(undefined); }, children: "Add breakpoint" })] })] }), _jsxs("section", { className: "panel event-panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Event Log" }), _jsx("span", { className: "panel-spacer" }), _jsx("input", { className: "event-search", "aria-label": "Search event log", placeholder: "Search events", value: eventSearch, onChange: event => setEventSearch(event.target.value) }), _jsxs("select", { className: "event-filter", value: eventFilter, onChange: event => setEventFilter(event.target.value), children: [_jsx("option", { value: "all", children: "All events" }), _jsx("option", { value: "steps", children: "Step events" }), _jsx("option", { value: "parallel", children: "Parallel groups" }), _jsx("option", { value: "lifecycle", children: "Lifecycle" }), _jsx("option", { value: "failures", children: "Failures" })] })] }), _jsx("table", { children: _jsx("tbody", { children: visibleEvents.map(event => _jsxs("tr", { className: "event-row", children: [_jsx("td", { children: new Date(event.timestamp).toLocaleTimeString() }), _jsx("td", { children: event.state.toUpperCase() }), _jsx("td", { children: _jsx("code", { children: event.type.toUpperCase() }) }), _jsxs("td", { children: [event.message, event.parallel && _jsxs("small", { className: "parallel-event", children: [" \u00B7 Parallel ", event.parallel.completed, "/", event.parallel.total, " (", event.parallel.join, ")"] })] })] }, event.sequence)) }) }), events.length > 0 && visibleEvents.length === 0 && _jsx("p", { className: "empty-state", children: "No events match the current filter." })] }), _jsx(HistoryPanel, { entries: runHistory, onReload: reloadHistoryEntry, retention: historyRetention, onRetentionChange: changeHistoryRetention, onClear: clearHistory, onDelete: deleteHistoryEntry, onExport: exportResult })] }), _jsxs("aside", { className: "inspector", children: [_jsx("h2", { children: "Selected execution" }), _jsx("p", { className: "selected-detail-name", children: _jsx("strong", { children: displaySteps[selectedStep]?.name ?? 'No step selected' }) }), _jsxs("p", { className: "run-id", children: ["Run ID: ", requestId ?? 'No run started'] }), _jsx(InspectorSection, { title: "Artifact summary", children: _jsx(KeyValues, { values: ["Target", executionPackage.target.name, "Type", executionPackage.target.kind, "Package", executionPackage.packageId, "Artifact schema", String(executionPackage.schemaVersion), "Definitions", String(executionPackage.definitions.length), "Required inputs", (executionPackage.requiredInputs ?? []).join(", ") || "None", "Runtime values", (executionPackage.runtimeRequirements ?? []).join(", ") || "None"] }) }), _jsx(InspectorSection, { title: "Run outcome", children: _jsxs("div", { className: "notice", children: [_jsx("strong", { children: result?.terminalReason?.toUpperCase() ?? 'NOT STARTED' }), _jsx("br", {}), result ? `${result.environment} · ${result.state}` : 'Run the package to inspect its terminal outcome.'] }) }), _jsx(InspectorSection, { title: "Selected step inputs", children: _jsx(KeyValues, { values: Object.entries(displayResults[selectedStep]?.inputs ?? inputs).flatMap(([key, value]) => [key, String(value)]) }) }), _jsx(InspectorSection, { title: "Selected step outputs", children: _jsx(KeyValues, { values: displayResults[selectedStep]?.outputs ? Object.entries(displayResults[selectedStep]?.outputs ?? {}).flatMap(([key, value]) => [key, String(value)]) : ['—', 'Available after execution'] }) }), (result?.error || displayResults[selectedStep]?.error) && _jsx(InspectorSection, { title: "Error", children: _jsxs("div", { className: "error-notice", children: [_jsx("strong", { children: displayResults[selectedStep]?.error?.code ?? result?.error?.code }), _jsx("br", {}), displayResults[selectedStep]?.error?.message ?? result?.error?.message] }) }), result?.issues !== undefined && _jsx(InspectorSection, { title: "Pre-run validation", children: _jsx(PreRunValidation, { issues: result.issues }) }), _jsx(InspectorSection, { title: "Invocation path", children: _jsx("div", { className: "notice", children: displayResults[selectedStep]?.invocationPath?.join(" › ") ?? "No invocation path available." }) }), _jsx(InspectorSection, { title: "Iteration history", children: _jsx(IterationHistory, { result: displayResults[selectedStep] }) }), _jsx(InspectorSection, { title: "Execution timing", children: _jsxs("div", { className: "timing-details", children: [_jsxs("span", { children: ["Wall ", result?.executionTiming?.wallDurationMs ?? "—", " ms"] }), _jsxs("span", { children: ["Active ", result?.executionTiming?.activeDurationMs ?? "—", " ms"] }), _jsxs("span", { children: ["Paused ", result?.executionTiming?.pausedDurationMs ?? "—", " ms"] })] }) }), _jsx(InspectorSection, { title: "Selected step attempts", children: _jsx("div", { className: "attempt-history", children: displayResults[selectedStep]?.attempts?.map(attempt => _jsxs("div", { className: "iteration-entry", children: [_jsxs("strong", { children: ["Attempt ", attempt.attempt] }), _jsxs("span", { children: [attempt.kind.toUpperCase(), " \u00B7 ", attempt.state.toUpperCase(), " \u00B7 ", attempt.durationMs, " ms"] })] }, `${attempt.attempt}-${attempt.kind}`)) ?? _jsx("div", { className: "notice", children: "No retry attempts recorded." }) }) }), _jsxs(InspectorSection, { title: "Selected step", children: [_jsxs("div", { className: "notice", children: [_jsx("strong", { children: displaySteps[selectedStep]?.name ?? 'No step selected' }), _jsx("br", {}), displayResults[selectedStep] ? displayResults[selectedStep].error ? 'This step failed. See the error details above.' : `Completed in ${displayResults[selectedStep].durationMs} ms.` : 'Run the package to inspect execution details.', _jsxs("div", { className: "inspector-actions", children: [_jsx("button", { className: "button", onClick: () => void retrySelected(), disabled: !displayResults[selectedStep] || (!displayResults[selectedStep]?.error && runState !== "completed"), children: "Retry Action" }), _jsx("button", { className: `button ${stopAfterStepId === displaySteps[selectedStep]?.id ? "active" : ""}`, onClick: () => displaySteps[selectedStep] && toggleStopAfter(displaySteps[selectedStep].id), disabled: !displaySteps[selectedStep], children: "Stop After" }), _jsx("button", { className: "button", onClick: () => void runFromSelected(), disabled: !displayResults[selectedStep] || runState === "running", children: "Run From Here" })] })] }), _jsxs("div", { className: "selection-nav", children: [_jsx("button", { className: "button", disabled: selectedStep <= 0, onClick: () => setSelectedStep(index => Math.max(0, index - 1)), children: "\u2039 Previous" }), _jsx("span", { children: displaySteps.length ? `${selectedStep + 1} / ${displaySteps.length}` : '0 / 0' }), _jsx("button", { className: "button", disabled: selectedStep >= displaySteps.length - 1, onClick: () => setSelectedStep(index => Math.min(displaySteps.length - 1, index + 1)), children: "Next \u203A" })] })] })] })] }), showAbout && _jsx("div", { className: "about-backdrop", onClick: () => setShowAbout(false), children: _jsxs("section", { className: "about-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "about-title", onClick: event => event.stopPropagation(), children: [_jsx("button", { className: "about-close", onClick: () => setShowAbout(false), "aria-label": "Close About", children: "\u00D7" }), _jsx("div", { className: "runner-logo", children: "\u25B6" }), _jsx("h2", { id: "about-title", children: "QAick Runner" }), _jsx("p", { children: "Standalone execution and evidence viewer for QAICK packages." }), _jsxs("small", { children: [RUNNER_UI_VERSION, " \u00B7 ", RUNNER_BUILD_LABEL, " \u00B7 QAick contract"] }), _jsx("footer", { children: "\u00A9 2006\u20132026 QAick. All rights reserved." })] }) })] });
|
|
225
240
|
}
|
|
226
241
|
function NavItem({ icon, text, active = false }) { const scrollTarget = text === 'Run History' ? '.history-panel' : text === 'Flows' ? '.runner-workspace table' : '.runner-workspace'; return _jsxs("a", { className: `nav-item ${active ? 'active' : ''}`, href: `#${text.toLowerCase().replaceAll(' ', '-')}`, onClick: event => { event.preventDefault(); document.querySelector(scrollTarget)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, children: [_jsx("span", { children: icon }), text] }); }
|
|
227
242
|
function HistoryPanel({ entries, retention, onRetentionChange, onClear, onDelete, onExport, onReload }) { return _jsxs("section", { className: "panel history-panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Run History" }), _jsx("span", { className: "panel-spacer" }), _jsxs("label", { className: "history-retention", children: ["Keep", _jsxs("select", { "aria-label": "Run history retention", value: retention, onChange: event => onRetentionChange(Number(event.target.value)), children: [_jsx("option", { value: "10", children: "10 runs" }), _jsx("option", { value: "20", children: "20 runs" }), _jsx("option", { value: "50", children: "50 runs" }), _jsx("option", { value: "100", children: "100 runs" })] })] }), _jsx("button", { className: "button", onClick: onClear, disabled: !entries.length, children: "Clear history" })] }), entries.length ? _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Target" }), _jsx("th", { children: "Started" }), _jsx("th", { children: "State" }), _jsx("th", { children: "Duration" }), _jsx("th", { children: "Result" })] }) }), _jsx("tbody", { children: entries.map(entry => _jsxs("tr", { children: [_jsxs("td", { children: [entry.target, _jsxs("small", { className: "history-meta", children: [entry.result.provenance ? 'Run From Here' : entry.result.steps.some(step => step.attempts?.some(attempt => attempt.kind === 'interactive')) ? 'Interactive retry' : 'Normal run', " \u00B7 ", entry.packageId ?? 'legacy result', " \u00B7 schema ", entry.artifactSchemaVersion ?? '—', _jsx("br", {}), "hash ", entry.result.artifactHash ?? 'legacy result'] })] }), _jsx("td", { children: new Date(entry.startedAt).toLocaleString() }), _jsx("td", { children: _jsx("span", { className: `status ${entry.state}`, children: entry.state.toUpperCase() }) }), _jsxs("td", { children: [entry.durationMs, " ms"] }), _jsxs("td", { children: [_jsx("button", { className: "button", onClick: () => onReload(entry), children: "View results" }), _jsx("button", { className: "button", onClick: () => onExport(entry.result, entry.packageId, entry.artifactSchemaVersion), children: "Export JSON" }), _jsx("button", { className: "button history-delete", onClick: () => onDelete(entry.requestId), children: "Delete" })] })] }, entry.requestId)) })] }) : _jsx("p", { className: "empty-state", children: "Completed and failed runs will be kept here in this browser." })] }); }
|