ridgeline 0.7.21 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/core/builder.md +15 -0
- package/dist/cli.js +91 -42
- package/dist/cli.js.map +1 -1
- package/dist/commands/build.js +0 -1
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.d.ts +1 -5
- package/dist/commands/check.js +2 -60
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/create.d.ts +0 -1
- package/dist/commands/create.js +0 -18
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/design.d.ts +0 -1
- package/dist/commands/design.js +1 -2
- package/dist/commands/design.js.map +1 -1
- package/dist/commands/refine.d.ts +0 -1
- package/dist/commands/refine.js +0 -1
- package/dist/commands/refine.js.map +1 -1
- package/dist/commands/research.d.ts +0 -1
- package/dist/commands/research.js +0 -2
- package/dist/commands/research.js.map +1 -1
- package/dist/commands/retrospective.d.ts +0 -1
- package/dist/commands/retrospective.js +1 -2
- package/dist/commands/retrospective.js.map +1 -1
- package/dist/commands/shape.d.ts +30 -1
- package/dist/commands/shape.js +16 -5
- package/dist/commands/shape.js.map +1 -1
- package/dist/commands/spec.d.ts +0 -1
- package/dist/commands/spec.js +0 -1
- package/dist/commands/spec.js.map +1 -1
- package/dist/commands/ui.d.ts +7 -0
- package/dist/commands/ui.js +96 -0
- package/dist/commands/ui.js.map +1 -0
- package/dist/config.js +0 -1
- package/dist/config.js.map +1 -1
- package/dist/engine/claude/claude.exec.js +1 -1
- package/dist/engine/claude/claude.exec.js.map +1 -1
- package/dist/engine/detect/index.d.ts +15 -0
- package/dist/engine/detect/index.js +160 -0
- package/dist/engine/detect/index.js.map +1 -0
- package/dist/engine/discovery/agent.registry.d.ts +5 -6
- package/dist/engine/discovery/agent.registry.js +20 -54
- package/dist/engine/discovery/agent.registry.js.map +1 -1
- package/dist/engine/discovery/skill.check.d.ts +3 -3
- package/dist/engine/discovery/skill.check.js +4 -4
- package/dist/engine/discovery/skill.check.js.map +1 -1
- package/dist/engine/index.d.ts +0 -1
- package/dist/engine/index.js +1 -3
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/pipeline/build.exec.js +19 -6
- package/dist/engine/pipeline/build.exec.js.map +1 -1
- package/dist/engine/pipeline/ensemble.exec.js +1 -2
- package/dist/engine/pipeline/ensemble.exec.js.map +1 -1
- package/dist/engine/pipeline/phase.sequence.js +88 -1
- package/dist/engine/pipeline/phase.sequence.js.map +1 -1
- package/dist/engine/pipeline/pipeline.shared.js +1 -2
- package/dist/engine/pipeline/pipeline.shared.js.map +1 -1
- package/dist/engine/pipeline/refine.exec.d.ts +0 -1
- package/dist/engine/pipeline/refine.exec.js +1 -2
- package/dist/engine/pipeline/refine.exec.js.map +1 -1
- package/dist/engine/pipeline/research.exec.d.ts +0 -1
- package/dist/engine/pipeline/research.exec.js +1 -2
- package/dist/engine/pipeline/research.exec.js.map +1 -1
- package/dist/engine/pipeline/review.exec.js +1 -2
- package/dist/engine/pipeline/review.exec.js.map +1 -1
- package/dist/engine/pipeline/sensors.collect.d.ts +6 -0
- package/dist/engine/pipeline/sensors.collect.js +34 -0
- package/dist/engine/pipeline/sensors.collect.js.map +1 -0
- package/dist/engine/pipeline/specify.exec.d.ts +0 -1
- package/dist/engine/pipeline/specify.exec.js +1 -2
- package/dist/engine/pipeline/specify.exec.js.map +1 -1
- package/dist/sensors/a11y.d.ts +36 -0
- package/dist/sensors/a11y.js +134 -0
- package/dist/sensors/a11y.js.map +1 -0
- package/dist/sensors/contrast.d.ts +3 -0
- package/dist/sensors/contrast.js +117 -0
- package/dist/sensors/contrast.js.map +1 -0
- package/dist/sensors/index.d.ts +27 -0
- package/dist/sensors/index.js +3 -0
- package/dist/sensors/index.js.map +1 -0
- package/dist/sensors/playwright.d.ts +69 -0
- package/dist/sensors/playwright.js +266 -0
- package/dist/sensors/playwright.js.map +1 -0
- package/dist/sensors/vision.d.ts +18 -0
- package/dist/sensors/vision.js +125 -0
- package/dist/sensors/vision.js.map +1 -0
- package/dist/stores/settings.d.ts +0 -1
- package/dist/stores/settings.js.map +1 -1
- package/dist/types.d.ts +0 -1
- package/dist/ui/color.d.ts +16 -0
- package/dist/ui/color.js +46 -0
- package/dist/ui/color.js.map +1 -0
- package/dist/ui/contrast.d.ts +2 -0
- package/dist/ui/contrast.js +94 -0
- package/dist/ui/contrast.js.map +1 -0
- package/dist/ui/dashboard/client.d.ts +1 -0
- package/dist/ui/dashboard/client.js +281 -0
- package/dist/ui/dashboard/client.js.map +1 -0
- package/dist/ui/dashboard/css.d.ts +1 -0
- package/dist/ui/dashboard/css.js +341 -0
- package/dist/ui/dashboard/css.js.map +1 -0
- package/dist/ui/dashboard/events.d.ts +15 -0
- package/dist/ui/dashboard/events.js +40 -0
- package/dist/ui/dashboard/events.js.map +1 -0
- package/dist/ui/dashboard/favicon.d.ts +2 -0
- package/dist/ui/dashboard/favicon.js +20 -0
- package/dist/ui/dashboard/favicon.js.map +1 -0
- package/dist/ui/dashboard/hex.d.ts +7 -0
- package/dist/ui/dashboard/hex.js +16 -0
- package/dist/ui/dashboard/hex.js.map +1 -0
- package/dist/ui/dashboard/html.d.ts +7 -0
- package/dist/ui/dashboard/html.js +69 -0
- package/dist/ui/dashboard/html.js.map +1 -0
- package/dist/ui/dashboard/server.d.ts +26 -0
- package/dist/ui/dashboard/server.js +257 -0
- package/dist/ui/dashboard/server.js.map +1 -0
- package/dist/ui/dashboard/snapshot.d.ts +29 -0
- package/dist/ui/dashboard/snapshot.js +71 -0
- package/dist/ui/dashboard/snapshot.js.map +1 -0
- package/dist/ui/dashboard/tokens.d.ts +19 -0
- package/dist/ui/dashboard/tokens.js +25 -0
- package/dist/ui/dashboard/tokens.js.map +1 -0
- package/dist/ui/dashboard/watcher.d.ts +13 -0
- package/dist/ui/dashboard/watcher.js +238 -0
- package/dist/ui/dashboard/watcher.js.map +1 -0
- package/dist/ui/output.js +3 -2
- package/dist/ui/output.js.map +1 -1
- package/dist/ui/preflight.d.ts +15 -0
- package/dist/ui/preflight.js +147 -0
- package/dist/ui/preflight.js.map +1 -0
- package/dist/ui/spinner.d.ts +0 -6
- package/dist/ui/spinner.js +25 -6
- package/dist/ui/spinner.js.map +1 -1
- package/dist/ui/transcript.js +2 -3
- package/dist/ui/transcript.js.map +1 -1
- package/dist/utils/flavour-removed.d.ts +12 -0
- package/dist/utils/flavour-removed.js +44 -0
- package/dist/utils/flavour-removed.js.map +1 -0
- package/package.json +16 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a11y.js","sourceRoot":"","sources":["../../src/sensors/a11y.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const fs = __importStar(require("node:fs"));
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
const wcag_contrast_1 = require("wcag-contrast");
|
|
39
|
+
const WCAG_AA_NORMAL = 4.5;
|
|
40
|
+
const HEX_TOKEN = /#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\b/g;
|
|
41
|
+
const HEX_VALIDATE = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
|
42
|
+
const normalizeHex = (value) => {
|
|
43
|
+
const trimmed = value.trim();
|
|
44
|
+
if (!trimmed.startsWith("#"))
|
|
45
|
+
return `#${trimmed}`;
|
|
46
|
+
return trimmed;
|
|
47
|
+
};
|
|
48
|
+
const isValidHex = (value) => HEX_VALIDATE.test(value);
|
|
49
|
+
const extractPairsFromMarkdown = (content) => {
|
|
50
|
+
const pairs = [];
|
|
51
|
+
const lines = content.split(/\r?\n/);
|
|
52
|
+
for (const line of lines) {
|
|
53
|
+
const tokens = line.match(HEX_TOKEN);
|
|
54
|
+
if (!tokens || tokens.length < 2)
|
|
55
|
+
continue;
|
|
56
|
+
const [bg, fg] = tokens;
|
|
57
|
+
pairs.push({ background: bg, foreground: fg });
|
|
58
|
+
}
|
|
59
|
+
return pairs;
|
|
60
|
+
};
|
|
61
|
+
const discoverPairs = (input) => {
|
|
62
|
+
if (input.contrastPairs && input.contrastPairs.length > 0) {
|
|
63
|
+
return [...input.contrastPairs];
|
|
64
|
+
}
|
|
65
|
+
const ridgelineDir = input.ridgelineDir ?? path.join(input.cwd, ".ridgeline");
|
|
66
|
+
const designPath = path.join(ridgelineDir, "design.md");
|
|
67
|
+
if (!fs.existsSync(designPath))
|
|
68
|
+
return [];
|
|
69
|
+
const content = fs.readFileSync(designPath, "utf-8");
|
|
70
|
+
return extractPairsFromMarkdown(content);
|
|
71
|
+
};
|
|
72
|
+
const scorePair = (pair) => {
|
|
73
|
+
const background = normalizeHex(pair.background);
|
|
74
|
+
const foreground = normalizeHex(pair.foreground);
|
|
75
|
+
if (!isValidHex(background) || !isValidHex(foreground)) {
|
|
76
|
+
return {
|
|
77
|
+
kind: "contrast",
|
|
78
|
+
summary: `invalid hex pair ${foreground} / ${background}`,
|
|
79
|
+
severity: "warning",
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
let ratio;
|
|
83
|
+
try {
|
|
84
|
+
ratio = (0, wcag_contrast_1.hex)(foreground, background);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return {
|
|
88
|
+
kind: "contrast",
|
|
89
|
+
summary: `invalid hex pair ${foreground} / ${background}`,
|
|
90
|
+
severity: "warning",
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const label = pair.name ? `${pair.name} (${foreground} on ${background})` : `${foreground} on ${background}`;
|
|
94
|
+
if (ratio < WCAG_AA_NORMAL) {
|
|
95
|
+
return {
|
|
96
|
+
kind: "contrast",
|
|
97
|
+
summary: `${label}: contrast ${ratio.toFixed(2)}:1 below WCAG AA 4.5:1`,
|
|
98
|
+
severity: "error",
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
kind: "contrast",
|
|
103
|
+
summary: `${label}: contrast ${ratio.toFixed(2)}:1 meets WCAG AA`,
|
|
104
|
+
severity: "info",
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
const contrastSensor = {
|
|
108
|
+
name: "contrast",
|
|
109
|
+
async run(input) {
|
|
110
|
+
const pairs = discoverPairs(input);
|
|
111
|
+
if (pairs.length === 0)
|
|
112
|
+
return [];
|
|
113
|
+
return pairs.map(scorePair);
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
exports.default = contrastSensor;
|
|
117
|
+
//# sourceMappingURL=contrast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contrast.js","sourceRoot":"","sources":["../../src/sensors/contrast.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SensorName } from "../engine/detect";
|
|
2
|
+
export interface SensorFinding {
|
|
3
|
+
kind: "screenshot" | "a11y" | "contrast" | "vision";
|
|
4
|
+
path?: string;
|
|
5
|
+
summary: string;
|
|
6
|
+
severity: "info" | "warning" | "error";
|
|
7
|
+
}
|
|
8
|
+
export interface ColorPair {
|
|
9
|
+
name?: string;
|
|
10
|
+
foreground: string;
|
|
11
|
+
background: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SensorInput {
|
|
14
|
+
cwd: string;
|
|
15
|
+
ridgelineDir?: string;
|
|
16
|
+
buildDir?: string;
|
|
17
|
+
shapeMdPath?: string;
|
|
18
|
+
artifactsDir?: string;
|
|
19
|
+
model?: string;
|
|
20
|
+
url?: string;
|
|
21
|
+
screenshotPath?: string;
|
|
22
|
+
contrastPairs?: readonly ColorPair[];
|
|
23
|
+
}
|
|
24
|
+
export interface SensorAdapter {
|
|
25
|
+
readonly name: SensorName;
|
|
26
|
+
run(input: SensorInput): Promise<SensorFinding[]>;
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sensors/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { SensorAdapter, SensorFinding, SensorInput } from "./index";
|
|
2
|
+
export declare const PROBE_PORTS: readonly number[];
|
|
3
|
+
type PortResult = {
|
|
4
|
+
source: "shape-md";
|
|
5
|
+
port: number;
|
|
6
|
+
} | {
|
|
7
|
+
source: "probe";
|
|
8
|
+
port: number;
|
|
9
|
+
attempts: readonly number[];
|
|
10
|
+
} | {
|
|
11
|
+
source: "none";
|
|
12
|
+
attempts: readonly number[];
|
|
13
|
+
reason: "no-probe-match" | "malformed-declaration";
|
|
14
|
+
};
|
|
15
|
+
interface ParseResult {
|
|
16
|
+
port: number | null;
|
|
17
|
+
malformed: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare const parsePortFromShape: (content: string) => ParseResult;
|
|
20
|
+
interface ProbeOptions {
|
|
21
|
+
timeoutPerProbeMs?: number;
|
|
22
|
+
totalTimeoutMs?: number;
|
|
23
|
+
probe?: (port: number, timeoutMs: number) => Promise<boolean>;
|
|
24
|
+
ports?: readonly number[];
|
|
25
|
+
}
|
|
26
|
+
export declare const probeDevServer: (options?: ProbeOptions) => Promise<{
|
|
27
|
+
port: number | null;
|
|
28
|
+
attempts: readonly number[];
|
|
29
|
+
}>;
|
|
30
|
+
export declare const resolveDevServerPort: (input: SensorInput, options?: ProbeOptions) => Promise<PortResult>;
|
|
31
|
+
interface PlaywrightModule {
|
|
32
|
+
chromium: {
|
|
33
|
+
launch(options: {
|
|
34
|
+
args?: string[];
|
|
35
|
+
timeout?: number;
|
|
36
|
+
headless?: boolean;
|
|
37
|
+
}): Promise<PlaywrightBrowser>;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
interface PlaywrightBrowser {
|
|
41
|
+
newPage(): Promise<PlaywrightPage>;
|
|
42
|
+
close(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
interface PlaywrightPage {
|
|
45
|
+
goto(url: string, options?: {
|
|
46
|
+
timeout?: number;
|
|
47
|
+
waitUntil?: string;
|
|
48
|
+
}): Promise<unknown>;
|
|
49
|
+
screenshot(options: {
|
|
50
|
+
path: string;
|
|
51
|
+
fullPage?: boolean;
|
|
52
|
+
}): Promise<Buffer>;
|
|
53
|
+
close(): Promise<void>;
|
|
54
|
+
addScriptTag(options: {
|
|
55
|
+
path: string;
|
|
56
|
+
}): Promise<unknown>;
|
|
57
|
+
evaluate<R>(fn: string | (() => R)): Promise<R>;
|
|
58
|
+
}
|
|
59
|
+
type LoadPlaywright = () => PlaywrightModule;
|
|
60
|
+
interface PlaywrightRunInternals {
|
|
61
|
+
loadPlaywright?: LoadPlaywright;
|
|
62
|
+
isSandboxed?: () => boolean;
|
|
63
|
+
isResolvable?: () => boolean;
|
|
64
|
+
probeOptions?: ProbeOptions;
|
|
65
|
+
launchTimeoutMs?: number;
|
|
66
|
+
}
|
|
67
|
+
export declare const runPlaywrightSensor: (input: SensorInput, internals?: PlaywrightRunInternals) => Promise<SensorFinding[]>;
|
|
68
|
+
declare const playwrightSensor: SensorAdapter;
|
|
69
|
+
export default playwrightSensor;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runPlaywrightSensor = exports.resolveDevServerPort = exports.probeDevServer = exports.parsePortFromShape = exports.PROBE_PORTS = void 0;
|
|
37
|
+
const fs = __importStar(require("node:fs"));
|
|
38
|
+
const http = __importStar(require("node:http"));
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const PLAYWRIGHT_INSTALL_HINT = "npm install --save-dev playwright && npx playwright install chromium";
|
|
41
|
+
const isPlaywrightResolvable = () => {
|
|
42
|
+
try {
|
|
43
|
+
require.resolve("playwright");
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const LAUNCH_TIMEOUT_MS = 10_000;
|
|
51
|
+
const DEFAULT_PROBE_TIMEOUT_MS = 250;
|
|
52
|
+
const DEFAULT_TOTAL_PROBE_MS = 1_000;
|
|
53
|
+
const RUNTIME_BLOCK_RE = /^##\s+Runtime\s*$([\s\S]*?)(?=^##\s+|$(?![\r\n]))/m;
|
|
54
|
+
const DEV_PORT_LINE_RE = /^\s*-\s*\*\*Dev server port:\*\*\s+(\d+)\s*$/m;
|
|
55
|
+
const DEV_PORT_LINE_GLOBAL = new RegExp(DEV_PORT_LINE_RE.source, "gm");
|
|
56
|
+
exports.PROBE_PORTS = [5173, 3000, 8080, 4321];
|
|
57
|
+
const parsePortFromShape = (content) => {
|
|
58
|
+
const runtimeBlocks = [];
|
|
59
|
+
const blockRe = new RegExp(RUNTIME_BLOCK_RE.source, "gm");
|
|
60
|
+
let match;
|
|
61
|
+
while ((match = blockRe.exec(content)) !== null) {
|
|
62
|
+
runtimeBlocks.push(match[1] ?? "");
|
|
63
|
+
}
|
|
64
|
+
if (runtimeBlocks.length === 0)
|
|
65
|
+
return { port: null, malformed: false };
|
|
66
|
+
if (runtimeBlocks.length > 1)
|
|
67
|
+
return { port: null, malformed: true };
|
|
68
|
+
const block = runtimeBlocks[0];
|
|
69
|
+
const ports = [];
|
|
70
|
+
let m;
|
|
71
|
+
const globalRe = new RegExp(DEV_PORT_LINE_GLOBAL.source, "gm");
|
|
72
|
+
while ((m = globalRe.exec(block)) !== null) {
|
|
73
|
+
const n = parseInt(m[1], 10);
|
|
74
|
+
if (Number.isFinite(n) && n >= 1 && n <= 65535) {
|
|
75
|
+
ports.push(n);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return { port: null, malformed: true };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (ports.length === 0)
|
|
82
|
+
return { port: null, malformed: false };
|
|
83
|
+
if (ports.length > 1)
|
|
84
|
+
return { port: null, malformed: true };
|
|
85
|
+
return { port: ports[0], malformed: false };
|
|
86
|
+
};
|
|
87
|
+
exports.parsePortFromShape = parsePortFromShape;
|
|
88
|
+
const headProbe = (port, timeoutMs) => new Promise((resolve) => {
|
|
89
|
+
const req = http.request({ host: "127.0.0.1", port, method: "HEAD", path: "/", timeout: timeoutMs }, (res) => {
|
|
90
|
+
res.resume();
|
|
91
|
+
resolve(true);
|
|
92
|
+
});
|
|
93
|
+
req.on("timeout", () => {
|
|
94
|
+
req.destroy();
|
|
95
|
+
resolve(false);
|
|
96
|
+
});
|
|
97
|
+
req.on("error", () => resolve(false));
|
|
98
|
+
req.end();
|
|
99
|
+
});
|
|
100
|
+
const probeDevServer = async (options = {}) => {
|
|
101
|
+
const perProbe = options.timeoutPerProbeMs ?? DEFAULT_PROBE_TIMEOUT_MS;
|
|
102
|
+
const total = options.totalTimeoutMs ?? DEFAULT_TOTAL_PROBE_MS;
|
|
103
|
+
const probeFn = options.probe ?? headProbe;
|
|
104
|
+
const ports = options.ports ?? exports.PROBE_PORTS;
|
|
105
|
+
const attempts = [];
|
|
106
|
+
const start = Date.now();
|
|
107
|
+
for (const port of ports) {
|
|
108
|
+
if (Date.now() - start >= total)
|
|
109
|
+
break;
|
|
110
|
+
attempts.push(port);
|
|
111
|
+
const ok = await probeFn(port, perProbe).catch(() => false);
|
|
112
|
+
if (ok)
|
|
113
|
+
return { port, attempts };
|
|
114
|
+
}
|
|
115
|
+
return { port: null, attempts };
|
|
116
|
+
};
|
|
117
|
+
exports.probeDevServer = probeDevServer;
|
|
118
|
+
const readShapeMd = (input) => {
|
|
119
|
+
const candidate = input.shapeMdPath ??
|
|
120
|
+
(input.buildDir ? path.join(input.buildDir, "shape.md") : null);
|
|
121
|
+
if (!candidate)
|
|
122
|
+
return null;
|
|
123
|
+
if (!fs.existsSync(candidate))
|
|
124
|
+
return null;
|
|
125
|
+
try {
|
|
126
|
+
return fs.readFileSync(candidate, "utf-8");
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const logWarn = (line) => {
|
|
133
|
+
process.stderr.write(`${line}\n`);
|
|
134
|
+
};
|
|
135
|
+
const resolveDevServerPort = async (input, options = {}) => {
|
|
136
|
+
const shape = readShapeMd(input);
|
|
137
|
+
if (shape) {
|
|
138
|
+
const parsed = (0, exports.parsePortFromShape)(shape);
|
|
139
|
+
if (parsed.port !== null) {
|
|
140
|
+
return { source: "shape-md", port: parsed.port };
|
|
141
|
+
}
|
|
142
|
+
if (parsed.malformed) {
|
|
143
|
+
logWarn(`[ridgeline] WARN: shape.md ## Runtime has malformed dev-server port; falling back to probing`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const { port, attempts } = await (0, exports.probeDevServer)(options);
|
|
147
|
+
if (port === null) {
|
|
148
|
+
return { source: "none", attempts, reason: "no-probe-match" };
|
|
149
|
+
}
|
|
150
|
+
return { source: "probe", port, attempts };
|
|
151
|
+
};
|
|
152
|
+
exports.resolveDevServerPort = resolveDevServerPort;
|
|
153
|
+
const isSandboxDetected = (env = process.env) => {
|
|
154
|
+
if (env.RIDGELINE_SANDBOX)
|
|
155
|
+
return true;
|
|
156
|
+
if (env.GREYWALL_ACTIVE)
|
|
157
|
+
return true;
|
|
158
|
+
if (env.BWRAP_DETECTED)
|
|
159
|
+
return true;
|
|
160
|
+
if (env.container)
|
|
161
|
+
return true;
|
|
162
|
+
return false;
|
|
163
|
+
};
|
|
164
|
+
const defaultLoadPlaywright = () => require("playwright");
|
|
165
|
+
const unresolvableFinding = () => ({
|
|
166
|
+
kind: "screenshot",
|
|
167
|
+
severity: "warning",
|
|
168
|
+
summary: `Playwright is not installed. Install with: ${PLAYWRIGHT_INSTALL_HINT}`,
|
|
169
|
+
});
|
|
170
|
+
const launchFailureFinding = (message) => ({
|
|
171
|
+
kind: "screenshot",
|
|
172
|
+
severity: "warning",
|
|
173
|
+
summary: `Chromium launch failed — sandbox-incompatible (${message})`,
|
|
174
|
+
});
|
|
175
|
+
const noDevServerFinding = (attempts) => ({
|
|
176
|
+
kind: "screenshot",
|
|
177
|
+
severity: "warning",
|
|
178
|
+
summary: `no dev server detected (probed ports: ${attempts.join(", ") || "none"})`,
|
|
179
|
+
});
|
|
180
|
+
const runPlaywrightSensor = async (input, internals = {}) => {
|
|
181
|
+
const resolvable = (internals.isResolvable ?? isPlaywrightResolvable)();
|
|
182
|
+
if (!resolvable) {
|
|
183
|
+
return [unresolvableFinding()];
|
|
184
|
+
}
|
|
185
|
+
const port = await (0, exports.resolveDevServerPort)(input, internals.probeOptions).catch(() => ({
|
|
186
|
+
source: "none",
|
|
187
|
+
attempts: [],
|
|
188
|
+
reason: "no-probe-match",
|
|
189
|
+
}));
|
|
190
|
+
if (port.source === "none") {
|
|
191
|
+
return [noDevServerFinding(port.attempts)];
|
|
192
|
+
}
|
|
193
|
+
const load = internals.loadPlaywright ?? defaultLoadPlaywright;
|
|
194
|
+
const sandboxed = (internals.isSandboxed ?? isSandboxDetected)();
|
|
195
|
+
const launchTimeout = internals.launchTimeoutMs ?? LAUNCH_TIMEOUT_MS;
|
|
196
|
+
const launchArgs = sandboxed ? ["--no-sandbox", "--disable-setuid-sandbox"] : [];
|
|
197
|
+
let playwright;
|
|
198
|
+
try {
|
|
199
|
+
playwright = load();
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
203
|
+
if (message.toLowerCase().includes("cannot find module")) {
|
|
204
|
+
return [unresolvableFinding()];
|
|
205
|
+
}
|
|
206
|
+
return [launchFailureFinding(message)];
|
|
207
|
+
}
|
|
208
|
+
let browser;
|
|
209
|
+
try {
|
|
210
|
+
browser = await playwright.chromium.launch({
|
|
211
|
+
args: launchArgs,
|
|
212
|
+
timeout: launchTimeout,
|
|
213
|
+
headless: true,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
218
|
+
if (/executable doesn.?t exist|browser not found|playwright install/i.test(message)) {
|
|
219
|
+
return [unresolvableFinding()];
|
|
220
|
+
}
|
|
221
|
+
return [launchFailureFinding(message)];
|
|
222
|
+
}
|
|
223
|
+
const artifactsDir = input.artifactsDir ??
|
|
224
|
+
(input.buildDir ? path.join(input.buildDir, "artifacts") : path.join(input.cwd, ".ridgeline", "artifacts"));
|
|
225
|
+
try {
|
|
226
|
+
fs.mkdirSync(artifactsDir, { recursive: true });
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
// directory creation failed — fall through; screenshot will fail non-fatally
|
|
230
|
+
}
|
|
231
|
+
const screenshotPath = path.join(artifactsDir, `screenshot-${Date.now()}.png`);
|
|
232
|
+
const url = input.url ?? `http://127.0.0.1:${port.port}`;
|
|
233
|
+
try {
|
|
234
|
+
const page = await browser.newPage();
|
|
235
|
+
await page.goto(url, { waitUntil: "load", timeout: launchTimeout });
|
|
236
|
+
await page.screenshot({ path: screenshotPath, fullPage: true });
|
|
237
|
+
await page.close();
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
await browser.close().catch(() => { });
|
|
241
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
242
|
+
return [
|
|
243
|
+
{
|
|
244
|
+
kind: "screenshot",
|
|
245
|
+
severity: "warning",
|
|
246
|
+
summary: `screenshot failed at ${url}: ${message}`,
|
|
247
|
+
},
|
|
248
|
+
];
|
|
249
|
+
}
|
|
250
|
+
await browser.close().catch(() => { });
|
|
251
|
+
return [
|
|
252
|
+
{
|
|
253
|
+
kind: "screenshot",
|
|
254
|
+
severity: "info",
|
|
255
|
+
path: screenshotPath,
|
|
256
|
+
summary: `captured screenshot of ${url} (port source: ${port.source})`,
|
|
257
|
+
},
|
|
258
|
+
];
|
|
259
|
+
};
|
|
260
|
+
exports.runPlaywrightSensor = runPlaywrightSensor;
|
|
261
|
+
const playwrightSensor = {
|
|
262
|
+
name: "playwright",
|
|
263
|
+
run: (input) => (0, exports.runPlaywrightSensor)(input),
|
|
264
|
+
};
|
|
265
|
+
exports.default = playwrightSensor;
|
|
266
|
+
//# sourceMappingURL=playwright.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.js","sourceRoot":"","sources":["../../src/sensors/playwright.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA6B;AAC7B,gDAAiC;AACjC,gDAAiC;AAGjC,MAAM,uBAAuB,GAC3B,sEAAsE,CAAA;AAExE,MAAM,sBAAsB,GAAG,GAAY,EAAE;IAC3C,IAAI,CAAC;QACH,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;QAC7B,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC,CAAA;AAED,MAAM,iBAAiB,GAAG,MAAM,CAAA;AAChC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AACpC,MAAM,sBAAsB,GAAG,KAAK,CAAA;AACpC,MAAM,gBAAgB,GAAG,oDAAoD,CAAA;AAC7E,MAAM,gBAAgB,GAAG,+CAA+C,CAAA;AACxE,MAAM,oBAAoB,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;AAEzD,QAAA,WAAW,GAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;AAY/D,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAAe,EAAE;IACjE,MAAM,aAAa,GAAa,EAAE,CAAA;IAClC,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IACzD,IAAI,KAA6B,CAAA;IACjC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAChD,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IACpC,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;IACvE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;IAEpE,MAAM,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;IAC9B,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,CAAyB,CAAA;IAC7B,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAC9D,OAAO,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAC5B,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACf,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;QACxC,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;IAC/D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;IAC5D,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;AAC7C,CAAC,CAAA;AAzBY,QAAA,kBAAkB,sBAyB9B;AAED,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,SAAiB,EAAoB,EAAE,CACtE,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;IACtB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,EAC1E,CAAC,GAAG,EAAE,EAAE;QACN,GAAG,CAAC,MAAM,EAAE,CAAA;QACZ,OAAO,CAAC,IAAI,CAAC,CAAA;IACf,CAAC,CACF,CAAA;IACD,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QACrB,GAAG,CAAC,OAAO,EAAE,CAAA;QACb,OAAO,CAAC,KAAK,CAAC,CAAA;IAChB,CAAC,CAAC,CAAA;IACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;IACrC,GAAG,CAAC,GAAG,EAAE,CAAA;AACX,CAAC,CAAC,CAAA;AASG,MAAM,cAAc,GAAG,KAAK,EACjC,UAAwB,EAAE,EACqC,EAAE;IACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,iBAAiB,IAAI,wBAAwB,CAAA;IACtE,MAAM,KAAK,GAAG,OAAO,CAAC,cAAc,IAAI,sBAAsB,CAAA;IAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,SAAS,CAAA;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,mBAAW,CAAA;IAE1C,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACxB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,KAAK;YAAE,MAAK;QACtC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnB,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAA;QAC3D,IAAI,EAAE;YAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;IACnC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;AACjC,CAAC,CAAA;AAjBY,QAAA,cAAc,kBAiB1B;AAED,MAAM,WAAW,GAAG,CAAC,KAAkB,EAAiB,EAAE;IACxD,MAAM,SAAS,GACb,KAAK,CAAC,WAAW;QACjB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IACjE,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAA;IAC3B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAA;IAC1C,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED,MAAM,OAAO,GAAG,CAAC,IAAY,EAAQ,EAAE;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAA;AACnC,CAAC,CAAA;AAEM,MAAM,oBAAoB,GAAG,KAAK,EACvC,KAAkB,EAClB,UAAwB,EAAE,EACL,EAAE;IACvB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAA;IAChC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,MAAM,GAAG,IAAA,0BAAkB,EAAC,KAAK,CAAC,CAAA;QACxC,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAA;QAClD,CAAC;QACD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,OAAO,CACL,8FAA8F,CAC/F,CAAA;QACH,CAAC;IACH,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAA,sBAAc,EAAC,OAAO,CAAC,CAAA;IACxD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAA;IAC/D,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;AAC5C,CAAC,CAAA;AArBY,QAAA,oBAAoB,wBAqBhC;AAED,MAAM,iBAAiB,GAAG,CAAC,MAAyB,OAAO,CAAC,GAAG,EAAW,EAAE;IAC1E,IAAI,GAAG,CAAC,iBAAiB;QAAE,OAAO,IAAI,CAAA;IACtC,IAAI,GAAG,CAAC,eAAe;QAAE,OAAO,IAAI,CAAA;IACpC,IAAI,GAAG,CAAC,cAAc;QAAE,OAAO,IAAI,CAAA;IACnC,IAAI,GAAG,CAAC,SAAS;QAAE,OAAO,IAAI,CAAA;IAC9B,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AA2BD,MAAM,qBAAqB,GAAmB,GAAG,EAAE,CACjD,OAAO,CAAC,YAAY,CAAqB,CAAA;AAE3C,MAAM,mBAAmB,GAAG,GAAkB,EAAE,CAAC,CAAC;IAChD,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,8CAA8C,uBAAuB,EAAE;CACjF,CAAC,CAAA;AAEF,MAAM,oBAAoB,GAAG,CAAC,OAAe,EAAiB,EAAE,CAAC,CAAC;IAChE,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,kDAAkD,OAAO,GAAG;CACtE,CAAC,CAAA;AAEF,MAAM,kBAAkB,GAAG,CAAC,QAA2B,EAAiB,EAAE,CAAC,CAAC;IAC1E,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,yCAAyC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG;CACnF,CAAC,CAAA;AAUK,MAAM,mBAAmB,GAAG,KAAK,EACtC,KAAkB,EAClB,YAAoC,EAAE,EACZ,EAAE;IAC5B,MAAM,UAAU,GAAG,CAAC,SAAS,CAAC,YAAY,IAAI,sBAAsB,CAAC,EAAE,CAAA;IACvE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAA;IAChC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,IAAA,4BAAoB,EAAC,KAAK,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAClF,MAAM,EAAE,MAAe;QACvB,QAAQ,EAAE,EAAuB;QACjC,MAAM,EAAE,gBAAyB;KAClC,CAAC,CAAC,CAAA;IAEH,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC5C,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,cAAc,IAAI,qBAAqB,CAAA;IAC9D,MAAM,SAAS,GAAG,CAAC,SAAS,CAAC,WAAW,IAAI,iBAAiB,CAAC,EAAE,CAAA;IAChE,MAAM,aAAa,GAAG,SAAS,CAAC,eAAe,IAAI,iBAAiB,CAAA;IACpE,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAEhF,IAAI,UAA4B,CAAA;IAChC,IAAI,CAAC;QACH,UAAU,GAAG,IAAI,EAAE,CAAA;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChE,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACzD,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAA;QAChC,CAAC;QACD,OAAO,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,OAA0B,CAAA;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;YACzC,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,aAAa;YACtB,QAAQ,EAAE,IAAI;SACf,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChE,IAAI,iEAAiE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACpF,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAA;QAChC,CAAC;QACD,OAAO,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAA;IACxC,CAAC;IAED,MAAM,YAAY,GAChB,KAAK,CAAC,YAAY;QAClB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC,CAAA;IAC7G,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;IAC/E,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IAC9E,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,oBAAoB,IAAI,CAAC,IAAI,EAAE,CAAA;IAExD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;QACpC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAA;QACnE,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;QAC/D,MAAM,IAAI,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACrC,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChE,OAAO;YACL;gBACE,IAAI,EAAE,YAAY;gBAClB,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,wBAAwB,GAAG,KAAK,OAAO,EAAE;aACnD;SACF,CAAA;IACH,CAAC;IAED,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IAErC,OAAO;QACL;YACE,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,0BAA0B,GAAG,kBAAkB,IAAI,CAAC,MAAM,GAAG;SACvE;KACF,CAAA;AACH,CAAC,CAAA;AAzFY,QAAA,mBAAmB,uBAyF/B;AAED,MAAM,gBAAgB,GAAkB;IACtC,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,CAAC,KAAkB,EAA4B,EAAE,CAAC,IAAA,2BAAmB,EAAC,KAAK,CAAC;CAClF,CAAA;AAED,kBAAe,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SensorAdapter, SensorFinding, SensorInput } from "./index";
|
|
2
|
+
type InvokeVision = (args: {
|
|
3
|
+
systemPrompt: string;
|
|
4
|
+
userPrompt: string;
|
|
5
|
+
model: string;
|
|
6
|
+
cwd: string;
|
|
7
|
+
imagePath: string;
|
|
8
|
+
}) => Promise<{
|
|
9
|
+
result: string;
|
|
10
|
+
}>;
|
|
11
|
+
interface VisionRunInternals {
|
|
12
|
+
invokeVision?: InvokeVision;
|
|
13
|
+
existsSync?: (p: string) => boolean;
|
|
14
|
+
isResolvable?: () => boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare const runVisionSensor: (input: SensorInput, internals?: VisionRunInternals) => Promise<SensorFinding[]>;
|
|
17
|
+
declare const visionSensor: SensorAdapter;
|
|
18
|
+
export default visionSensor;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runVisionSensor = void 0;
|
|
37
|
+
const fs = __importStar(require("node:fs"));
|
|
38
|
+
const claude_exec_1 = require("../engine/claude/claude.exec");
|
|
39
|
+
const PLAYWRIGHT_INSTALL_HINT = "npm install --save-dev playwright && npx playwright install chromium";
|
|
40
|
+
const isPlaywrightResolvable = () => {
|
|
41
|
+
try {
|
|
42
|
+
require.resolve("playwright");
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const VISION_SYSTEM_PROMPT = "You are a visual-analysis assistant. Describe the rendered UI at the given screenshot path: "
|
|
50
|
+
+ "layout, visible elements, color usage, obvious visual defects. Respond in 3-5 short bullet points. "
|
|
51
|
+
+ "Read the image file with the Read tool.";
|
|
52
|
+
const VISION_TIMEOUT_MS = 2 * 60 * 1000;
|
|
53
|
+
const defaultInvokeVision = async (args) => {
|
|
54
|
+
const result = await (0, claude_exec_1.invokeClaude)({
|
|
55
|
+
systemPrompt: args.systemPrompt,
|
|
56
|
+
userPrompt: args.userPrompt,
|
|
57
|
+
model: args.model,
|
|
58
|
+
allowedTools: ["Read"],
|
|
59
|
+
cwd: args.cwd,
|
|
60
|
+
timeoutMs: VISION_TIMEOUT_MS,
|
|
61
|
+
});
|
|
62
|
+
return { result: result.result };
|
|
63
|
+
};
|
|
64
|
+
const unresolvableFinding = () => ({
|
|
65
|
+
kind: "vision",
|
|
66
|
+
severity: "warning",
|
|
67
|
+
summary: `Playwright is not installed. Install with: ${PLAYWRIGHT_INSTALL_HINT}`,
|
|
68
|
+
});
|
|
69
|
+
const runVisionSensor = async (input, internals = {}) => {
|
|
70
|
+
const resolvable = (internals.isResolvable ?? isPlaywrightResolvable)();
|
|
71
|
+
if (!resolvable) {
|
|
72
|
+
return [unresolvableFinding()];
|
|
73
|
+
}
|
|
74
|
+
const imagePath = input.screenshotPath;
|
|
75
|
+
const exists = internals.existsSync ?? fs.existsSync;
|
|
76
|
+
if (!imagePath || !exists(imagePath)) {
|
|
77
|
+
return [
|
|
78
|
+
{
|
|
79
|
+
kind: "vision",
|
|
80
|
+
severity: "warning",
|
|
81
|
+
summary: imagePath
|
|
82
|
+
? `screenshot not found at ${imagePath}`
|
|
83
|
+
: "no screenshot path provided for vision analysis",
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
const invoke = internals.invokeVision ?? defaultInvokeVision;
|
|
88
|
+
const model = input.model ?? "opus";
|
|
89
|
+
const userPrompt = `Analyze the UI screenshot at: ${imagePath}\n\nRead the image with the Read tool, then respond with 3-5 short observations.`;
|
|
90
|
+
try {
|
|
91
|
+
const { result } = await invoke({
|
|
92
|
+
systemPrompt: VISION_SYSTEM_PROMPT,
|
|
93
|
+
userPrompt,
|
|
94
|
+
model,
|
|
95
|
+
cwd: input.cwd,
|
|
96
|
+
imagePath,
|
|
97
|
+
});
|
|
98
|
+
return [
|
|
99
|
+
{
|
|
100
|
+
kind: "vision",
|
|
101
|
+
severity: "info",
|
|
102
|
+
path: imagePath,
|
|
103
|
+
summary: result.trim() || "(vision returned empty analysis)",
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
109
|
+
return [
|
|
110
|
+
{
|
|
111
|
+
kind: "vision",
|
|
112
|
+
severity: "warning",
|
|
113
|
+
path: imagePath,
|
|
114
|
+
summary: `vision analysis failed: ${message}`,
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
exports.runVisionSensor = runVisionSensor;
|
|
120
|
+
const visionSensor = {
|
|
121
|
+
name: "vision",
|
|
122
|
+
run: (input) => (0, exports.runVisionSensor)(input),
|
|
123
|
+
};
|
|
124
|
+
exports.default = visionSensor;
|
|
125
|
+
//# sourceMappingURL=vision.js.map
|