🚀. Socket Launch Week Day 2:Introducing Manifest Alerts.Learn more
Sign In

@codeyam-editor/codeyam-editor

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@codeyam-editor/codeyam-editor - npm Package Compare versions

Comparing version
0.1.0-staging.27ed016
to
0.1.0-staging.2b41530
ui/dist/assets/EditorShell-apa7PmSB.js

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

+1
import{j as c}from"./markdown-v0F0UEt3.js";import{b as o}from"./react-CSS0HapR.js";import{S as m}from"./ScenarioDataPanel-BujcFaQj.js";import"./useEvents-DggWrtHe.js";import"./xterm--24IGk-x.js";import"./index-DlYjR4o_.js";function S({slug:t}){const[r,i]=o.useState(void 0);return o.useEffect(()=>{let n=!1;return fetch(`/api/scenarios/${encodeURIComponent(t)}`).then(e=>e.ok?e.json():null).then(e=>{if(n||!e)return;const a=typeof e=="object"&&e!==null&&"name"in e?String(e.name):void 0;i(a),a&&(document.title=`${a} · data`)}).catch(()=>{}),()=>{n=!0}},[t]),c.jsx(m,{slug:t,scenarioName:r,variant:"fullPage"})}export{S as ScenarioDataPanelFullPage};

Sorry, the diff of this file is too big to display

+5
-2
#!/usr/bin/env node
const { spawn } = require("child_process");
const { ensureBinary, uiDistDir } = require("./utils");
const { ensureBinary } = require("./utils");
const binary = ensureBinary();
// The Rust binary embeds `ui/dist` at build time, so no `CODEYAM_EDITOR_UI_DIR`
// is required. Devs who want to override the bundle can still export the env
// var manually — the binary's resolver checks it first.
const child = spawn(binary, process.argv.slice(2), {
stdio: "inherit",
cwd: process.cwd(),
env: { ...process.env, CODEYAM_EDITOR_UI_DIR: uiDistDir() },
env: process.env,
});

@@ -13,0 +16,0 @@

@@ -11,8 +11,22 @@ #!/usr/bin/env node

const { ensureServer, rootDir, killChildProcess } = require("./utils");
const {
ensureServer,
rootDir,
killChildProcess,
readMergedEditorConfig,
resolveLauncherPort,
} = require("./utils");
const { open } = require("./open");
const PORT = 14199;
async function main() {
// Same resolution order as the editor launcher: env var
// (CODEYAM_EDITOR_PORT) → merged editor.json + editor.local.json
// (proxy.controlPort) → hard fallback (14199).
const merged = readMergedEditorConfig(rootDir);
const PORT = resolveLauncherPort(
process.env.CODEYAM_EDITOR_PORT,
merged.proxy && merged.proxy.controlPort,
14199,
);
async function main() {
const serverChild = await ensureServer(PORT);

@@ -19,0 +33,0 @@ const url = `http://localhost:${PORT}`;

@@ -21,4 +21,12 @@ #!/usr/bin/env node

const path = require("path");
const fs = require("fs");
const { ensureServer, restartServer, waitForPort, ensureBinary, uiDistDir, rootDir, killChildProcess } = require("./utils");
const {
ensureServer,
restartServer,
waitForPort,
ensureBinary,
rootDir,
killChildProcess,
readMergedEditorConfig,
resolveLauncherPort,
} = require("./utils");
const { open } = require("./open");

@@ -66,3 +74,3 @@

cwd: process.cwd(),
env: { ...process.env, CODEYAM_EDITOR_UI_DIR: uiDistDir() },
env: process.env,
});

@@ -74,15 +82,4 @@ child.on("exit", (code) => {

// --- Launcher mode: build everything, start server, open browser ---
const SERVER_PORT = 14199;
const shouldRestart = args.includes("--restart");
const readProjectPort = () => {
try {
const configPath = path.join(process.cwd(), ".codeyam", "editor.json");
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
return config.port || 3000;
} catch {
return 3000;
}
};
const launcherMain = async () => {

@@ -93,2 +90,20 @@ const projectDir = process.cwd();

// Editor server's control port is owned by the editor repo's
// merged config (rootDir), not the target project's. The target
// project's own `editor.local.json` only contributes to the
// app/dev-server port below.
const editorMerged = readMergedEditorConfig(rootDir);
const SERVER_PORT = resolveLauncherPort(
process.env.CODEYAM_EDITOR_PORT,
editorMerged.proxy && editorMerged.proxy.controlPort,
14199,
);
// Target project's dev-server port comes from its own
// editor.json + editor.local.json (developers iterating on the
// editor against a real client project rely on the override
// file here too).
const projectMerged = readMergedEditorConfig(projectDir);
const appPort = resolveLauncherPort(undefined, projectMerged.port, 3000);
buildBinary();

@@ -108,3 +123,2 @@

const appPort = readProjectPort();
const viteInternalPort = appPort + 1;

@@ -111,0 +125,0 @@ console.error(`Waiting for dev server on port ${viteInternalPort}...`);

@@ -19,10 +19,16 @@ #!/usr/bin/env node

const path = require("path");
const { ensureServer, stopServer, isPortInUse, waitForPort, rootDir, killChildProcess } = require("./utils");
const {
ensureServer,
stopServer,
waitForPort,
rootDir,
killChildProcess,
readMergedEditorConfig,
resolveLauncherPort,
classifyPortHolder,
formatForeignListenerError,
formatCrossProjectError,
} = require("./utils");
const { open } = require("./open");
const SERVER_PORT = parseInt(process.env.CODEYAM_EDITOR_PORT || "14199", 10);
const VITE_PORT = parseInt(process.env.PORT || "5173", 10);
// The reverse proxy sits on VITE_PORT; the actual Vite dev server runs on
// VITE_PORT + 1. We need to wait for the real Vite server, not the proxy.
const VITE_INTERNAL_PORT = VITE_PORT + 1;
const shouldRestart = process.argv.includes("--restart");

@@ -103,22 +109,19 @@

async function main() {
// Sync ports to editor.json so the Rust backend uses them
const editorJsonPath = path.join(rootDir, ".codeyam", "editor.json");
if (fs.existsSync(editorJsonPath)) {
const editorJson = JSON.parse(fs.readFileSync(editorJsonPath, "utf8"));
editorJson.port = VITE_PORT;
editorJson.startCommand = `cd ui && npx vite --port ${VITE_PORT}`;
const uiApp = editorJson.apps?.find(a => a.dir === "ui");
if (uiApp) {
uiApp.port = VITE_PORT;
uiApp.startCommand = `npx vite --port ${VITE_PORT}`;
}
if (editorJson.proxy) {
editorJson.proxy.controlPort = SERVER_PORT;
editorJson.proxy.httpPort = SERVER_PORT - 99;
editorJson.proxy.dbPort = SERVER_PORT - 98;
}
fs.writeFileSync(editorJsonPath, JSON.stringify(editorJson, null, 2));
}
// Read ports from the merged editor config (editor.json + per-developer
// editor.local.json). The Rust backend reads the same merged config on
// its own — we resolve here so the launcher's log lines, `waitForPort`
// calls, and `--port` arg agree with what the binary will actually
// bind. Env vars still win for scripted/CI invocations
// (CODEYAM_EDITOR_PORT, PORT), then the merged config, then a hard
// fallback for fresh checkouts with no override file.
const merged = readMergedEditorConfig(rootDir);
const SERVER_PORT = resolveLauncherPort(
process.env.CODEYAM_EDITOR_PORT,
merged.proxy && merged.proxy.controlPort,
14199,
);
const VITE_PORT = resolveLauncherPort(process.env.PORT, merged.port, 5173);
// The reverse proxy sits on VITE_PORT; the actual Vite dev server runs on
// VITE_PORT + 1. We need to wait for the real Vite server, not the proxy.
const VITE_INTERNAL_PORT = VITE_PORT + 1;

@@ -150,7 +153,23 @@ // Rebuild the Rust binary so code changes are picked up on restart.

// server (configured via startCommand in editor.json) for Live Preview HMR.
// On --restart: stop the existing server first, sweep stale artifacts while
// target/ is idle (no process holding files open), then start fresh.
if (shouldRestart && (await isPortInUse(SERVER_PORT))) {
console.error(`Stopping existing server on port ${SERVER_PORT}...`);
await stopServer(SERVER_PORT);
// On --restart: identity-check first, then stop the existing server,
// sweep stale artifacts while target/ is idle, then start fresh.
//
// Stopping someone else's editor server on `--restart` is the worst
// possible outcome of a port collision — only stop the listener if
// the identity probe confirms it's this project's server.
if (shouldRestart) {
const holder = await classifyPortHolder(SERVER_PORT);
if (holder.kind === "foreign") {
console.error(formatForeignListenerError(SERVER_PORT));
process.exit(1);
}
if (holder.kind === "cross-project") {
console.error(formatCrossProjectError(SERVER_PORT, holder, "restart"));
process.exit(1);
}
if (holder.kind === "same-project") {
console.error(`Stopping existing server on port ${SERVER_PORT}...`);
await stopServer(SERVER_PORT);
}
// holder.kind === "free": nothing to stop, fall through to ensureServer.
}

@@ -157,0 +176,0 @@ if (shouldRestart) {

@@ -83,3 +83,6 @@ #!/usr/bin/env node

page.on("requestfailed", (request) => {
pushIssue(issues, handleRequestFailed(request));
const issue = handleRequestFailed(request);
if (issue) {
pushIssue(issues, issue);
}
});

@@ -86,0 +89,0 @@

@@ -59,7 +59,18 @@ const { createIssue } = require("./scenario-issues");

function handleRequestFailed(request) {
return createIssue(
"requestfailed",
request.failure()?.errorText || "Request failed",
{ url: request.url() }
);
const errorText = request.failure()?.errorText || "Request failed";
// Filter benign request cancellations. `net::ERR_ABORTED` is what Playwright
// emits when a request is in-flight at the moment the page is closed (or the
// iframe is destroyed). For scenarios whose pages fetch large payloads (the
// editor's own EditorShell mounts a 2.2MB `/api/tests` fetch), the
// browser.close() at the end of capture races the fetch and produces this
// event AFTER the screenshot has already been taken — there is no real
// failure to surface. Genuine network failures arrive under different
// codes (net::ERR_CONNECTION_REFUSED, net::ERR_NAME_NOT_RESOLVED, etc.)
// and continue to be reported.
if (errorText.includes("net::ERR_ABORTED")) {
return null;
}
return createIssue("requestfailed", errorText, { url: request.url() });
}

@@ -66,0 +77,0 @@

@@ -144,2 +144,118 @@ const { execSync, spawn, spawnSync } = require("child_process");

function isPlainJsonObject(value) {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
// Mirrors `deep_merge_json` in crates/types/src/config.rs:1284.
// Objects merge by key (`null` in overlay removes the key); arrays merge
// by index (extra overlay items appended, base items past overlay length
// retained); scalars replace. The JS and Rust sides MUST match — any
// divergence shows up as "the CLI sees port X but `npm run editor`
// opens port Y", which is exactly the bug this whole helper exists to
// prevent.
function deepMergeJson(base, overlay) {
if (isPlainJsonObject(base) && isPlainJsonObject(overlay)) {
for (const k of Object.keys(overlay)) {
const v = overlay[k];
if (v === null) {
delete base[k];
} else if (Object.prototype.hasOwnProperty.call(base, k)) {
base[k] = deepMergeJson(base[k], v);
} else {
base[k] = v;
}
}
return base;
}
if (Array.isArray(base) && Array.isArray(overlay)) {
for (let i = 0; i < overlay.length; i++) {
if (i < base.length) {
base[i] = deepMergeJson(base[i], overlay[i]);
} else {
base.push(overlay[i]);
}
}
return base;
}
return overlay;
}
// Mirrors the post-merge strip in `merged_config_value`
// (crates/types/src/config.rs:1272). Any top-level key starting with
// `_` is documentation-only (`_README`, `_examples`, …) and is removed
// before the merged config is used by the launcher or handed to the
// Rust binary. Mutates in place; returns the same object for chaining.
function stripUnderscoreTopLevelKeys(value) {
if (isPlainJsonObject(value)) {
for (const k of Object.keys(value)) {
if (k.startsWith("_")) delete value[k];
}
}
return value;
}
/**
* Read `<projectDir>/.codeyam/editor.json` and deep-merge an optional
* sibling `editor.local.json` on top, returning the merged plain object.
*
* This is the JS-side equivalent of `merged_config_value` in
* crates/types/src/config.rs — same merge rules, same underscore-prefix
* strip. Launcher scripts call this *before* the Rust binary is built
* (they invoke `cargo build` themselves), so shelling out to
* `codeyam-editor editor config-show` is not an option.
*
* Returns `{}` if the base file is missing (a freshly cloned repo with
* no `.codeyam/` directory should not throw at require-time). Throws
* on malformed JSON, naming the offending file path so the user knows
* which file to fix.
*/
function readMergedEditorConfig(projectDir = rootDir) {
const basePath = path.join(projectDir, ".codeyam", "editor.json");
if (!fs.existsSync(basePath)) return {};
let merged;
try {
merged = JSON.parse(fs.readFileSync(basePath, "utf8"));
} catch (e) {
throw new Error(`Failed to parse ${basePath}: ${e.message}`);
}
if (!isPlainJsonObject(merged)) merged = {};
const overlayPath = path.join(projectDir, ".codeyam", "editor.local.json");
if (fs.existsSync(overlayPath)) {
let overlay;
try {
overlay = JSON.parse(fs.readFileSync(overlayPath, "utf8"));
} catch (e) {
throw new Error(`Failed to parse ${overlayPath}: ${e.message}`);
}
if (isPlainJsonObject(overlay)) {
deepMergeJson(merged, overlay);
}
}
return stripUnderscoreTopLevelKeys(merged);
}
/**
* Resolve a port for a launcher in priority order:
* explicit env var → merged-config value → hard fallback.
*
* Exported so each launcher's port resolution can be unit-tested
* without spawning a process. The fallback is the historical hard-coded
* value (14199 / 5173 / 3000 depending on which slot the caller is
* resolving) and exists so a fresh checkout with no override file and
* no env var still works.
*/
function resolveLauncherPort(envValue, mergedValue, fallback) {
if (envValue !== undefined && envValue !== null && envValue !== "") {
const parsed = parseInt(envValue, 10);
if (Number.isFinite(parsed)) return parsed;
}
if (typeof mergedValue === "number" && Number.isFinite(mergedValue)) {
return mergedValue;
}
return fallback;
}
/** Try to connect to a specific host:port. Returns true if something is listening. */

@@ -202,2 +318,6 @@ function tryConnect(port, host) {

// Default ports across stopServer / restartServer / ensureServer /
// requestServerShutdown are a backstop for any future caller that
// forgets to pass an explicit port. Every production call site now
// resolves the port from `readMergedEditorConfig` + `resolveLauncherPort`.
async function requestServerShutdown(port = 14199, timeoutMs = 1500) {

@@ -220,2 +340,117 @@ const controller = new AbortController();

/**
* GET /api/codeyam-server-identity from the listener on `port` with a
* sub-second timeout. Returns the parsed `{projectDir, pid, version,
* startedAt}` body on a 2xx response, or `null` on any failure
* (timeout, non-200, parse failure, connection refused).
*
* `null` carries two distinct meanings that the caller must
* disambiguate by also checking `isPortInUse`:
* - port is free → no listener at all
* - port is in use → something is listening, but it's not a
* codeyam-editor server (or it's an old build that predates this
* endpoint).
*/
async function fetchServerIdentity(port, timeoutMs = 500) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
try {
const resp = await fetch(`http://127.0.0.1:${port}/api/codeyam-server-identity`, {
method: "GET",
signal: controller.signal,
});
if (!resp.ok) return null;
const body = await resp.json();
if (!body || typeof body !== "object" || typeof body.projectDir !== "string") {
return null;
}
return body;
} catch {
return null;
} finally {
clearTimeout(timeout);
}
}
/**
* Resolve the canonical (symlink-followed) path for `dir`, falling back to
* `dir` if `fs.realpath` fails (e.g. the path no longer exists). Both
* sides of the identity check route through this so a `~/work/foo`
* symlink and a `/Volumes/dev/foo` direct path compare equal.
*/
async function canonicalisePath(dir) {
try {
return await fs.promises.realpath(dir);
} catch {
return dir;
}
}
/**
* Build the "port held by a non-codeyam-editor process" error string.
* Lives next to `classifyPortHolder` so the wording is tested without
* a running server — both launchers (`ensureServer` and `editor.js`'s
* `--restart`) print this exact message on a "foreign" classification.
*/
function formatForeignListenerError(port) {
return (
`Port ${port} is in use, but no codeyam-editor server responded ` +
`at /api/codeyam-server-identity. Free the port or change ` +
`controlPort in .codeyam/editor.local.json.`
);
}
/**
* Build the "another project's editor is on this port" error string.
* `verb` is the action the launcher would have taken ("attach" /
* "restart"); the wording is otherwise identical so both launcher
* paths share the same advice.
*/
function formatCrossProjectError(port, holder, verb) {
const pidNote = Number.isInteger(holder.identity && holder.identity.pid)
? ` (pid ${holder.identity.pid})`
: "";
return (
`Refusing to ${verb} a codeyam-editor server for a different project.\n` +
` This project: ${holder.wantDir}\n` +
` Server on port ${port}${pidNote}: ${holder.haveDir}\n` +
`\n` +
`Change controlPort in .codeyam/editor.local.json, e.g.:\n` +
` codeyam-editor editor config-override proxy.controlPort 14399`
);
}
/**
* Classify whatever is listening on `port` relative to `projectDir`.
* Returns one of:
* - `{ kind: "free" }` — nothing on the port
* - `{ kind: "foreign" }` — port held by a non-editor process
* - `{ kind: "cross-project", wantDir, haveDir, identity }`
* — held by another project's editor
* - `{ kind: "same-project", identity }` — held by THIS project's editor
*
* Pure: every effect (network, fs) is bounded; no console output, no
* process.exit. The launcher decides what to do with each kind. Splitting
* the policy (what to print, when to exit) from the classification keeps
* the helper testable without mocking process.exit, and lets `ensureServer`
* and `editor.js`'s `--restart` block share the same logic with different
* wording.
*/
async function classifyPortHolder(port, projectDir = process.cwd()) {
if (!(await isPortInUse(port))) {
return { kind: "free" };
}
const identity = await fetchServerIdentity(port);
if (identity === null) {
return { kind: "foreign" };
}
const wantDir = await canonicalisePath(projectDir);
const haveDir = await canonicalisePath(identity.projectDir);
if (wantDir !== haveDir) {
return { kind: "cross-project", wantDir, haveDir, identity };
}
return { kind: "same-project", identity };
}
function tryKillPid(pid) {

@@ -312,10 +547,33 @@ try {

/** Start the Rust backend server if not already running. Returns the child process (or null if already running). */
/**
* Start the Rust backend server if not already running, refusing to attach
* if the existing listener belongs to a different project (or to a foreign
* process that doesn't speak the identity endpoint at all). Returns the
* spawned child on a fresh start, or `null` when we attached to an
* already-running same-project server. Exits the process non-zero on a
* mismatch — silently choosing a different port would just relocate the
* surprise.
*/
async function ensureServer(port = 14199) {
if (await isPortInUse(port)) {
console.error(`Server already running on port ${port}`);
return null;
const holder = await classifyPortHolder(port);
switch (holder.kind) {
case "foreign":
console.error(formatForeignListenerError(port));
process.exit(1);
break;
case "cross-project":
console.error(formatCrossProjectError(port, holder, "attach"));
process.exit(1);
break;
case "same-project":
console.error(`Server already running on port ${port}`);
return null;
case "free":
default:
break;
}
const binary = ensureBinary();
// UI bundle is embedded in the Rust binary; CODEYAM_EDITOR_UI_DIR is
// now an explicit dev-override only.
const child = spawn(binary, ["start", "--no-open", "--port", String(port)], {

@@ -325,3 +583,3 @@ stdio: "inherit",

detached: false,
env: { ...process.env, CODEYAM_EDITOR_UI_DIR: uiDistDir() },
env: process.env,
});

@@ -355,2 +613,7 @@

requestServerShutdown,
fetchServerIdentity,
canonicalisePath,
classifyPortHolder,
formatForeignListenerError,
formatCrossProjectError,
tryKillPid,

@@ -362,2 +625,6 @@ findListeningPids,

killChildProcess,
deepMergeJson,
stripUnderscoreTopLevelKeys,
readMergedEditorConfig,
resolveLauncherPort,
};
{
"name": "@codeyam-editor/codeyam-editor",
"version": "0.1.0-staging.27ed016",
"version": "0.1.0-staging.2b41530",
"description": "Language-agnostic managed execution sandbox for scenario-driven development",

@@ -12,6 +12,6 @@ "bin": {

"optionalDependencies": {
"@codeyam-editor/codeyam-editor-darwin-arm64": "0.1.0-staging.27ed016",
"@codeyam-editor/codeyam-editor-darwin-x64": "0.1.0-staging.27ed016",
"@codeyam-editor/codeyam-editor-linux-x64": "0.1.0-staging.27ed016",
"@codeyam-editor/codeyam-editor-win32-x64": "0.1.0-staging.27ed016"
"@codeyam-editor/codeyam-editor-darwin-arm64": "0.1.0-staging.2b41530",
"@codeyam-editor/codeyam-editor-darwin-x64": "0.1.0-staging.2b41530",
"@codeyam-editor/codeyam-editor-linux-x64": "0.1.0-staging.2b41530",
"@codeyam-editor/codeyam-editor-win32-x64": "0.1.0-staging.2b41530"
},

@@ -18,0 +18,0 @@ "keywords": [

@@ -8,6 +8,6 @@ <!DOCTYPE html>

<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<script type="module" crossorigin src="/assets/index-6jueUhB_.js"></script>
<script type="module" crossorigin src="/assets/index-DlYjR4o_.js"></script>
<link rel="modulepreload" crossorigin href="/assets/react-CSS0HapR.js">
<link rel="modulepreload" crossorigin href="/assets/markdown-v0F0UEt3.js">
<link rel="stylesheet" crossorigin href="/assets/index-Bik6WLGP.css">
<link rel="stylesheet" crossorigin href="/assets/index-CL9DurHP.css">
</head>

@@ -14,0 +14,0 @@ <body>

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

import{j as c}from"./markdown-v0F0UEt3.js";import{b as o}from"./react-CSS0HapR.js";import{S as m}from"./ScenarioDataPanel-Bb7egwjC.js";import"./useEvents-DggWrtHe.js";import"./xterm--24IGk-x.js";import"./index-6jueUhB_.js";function S({slug:t}){const[r,i]=o.useState(void 0);return o.useEffect(()=>{let n=!1;return fetch(`/api/scenarios/${encodeURIComponent(t)}`).then(e=>e.ok?e.json():null).then(e=>{if(n||!e)return;const a=typeof e=="object"&&e!==null&&"name"in e?String(e.name):void 0;i(a),a&&(document.title=`${a} · data`)}).catch(()=>{}),()=>{n=!0}},[t]),c.jsx(m,{slug:t,scenarioName:r,variant:"fullPage"})}export{S as ScenarioDataPanelFullPage};
import{j as e}from"./markdown-v0F0UEt3.js";import{b as d}from"./react-CSS0HapR.js";import{c as xe,C as L,S as H,f as ue,T as F,e as me,N as D,b as pe,a as A,r as he,d as _,R as k,p as be,g as $,I as ve,h as fe,i as ge,j as je,k as ye,l as Se,m as Ne,n as Pe,o as Ce,q as we,s as Te,t as Re,u as Ee,v as De,w as ke,x as Be,y as Me,E as Oe,z as Ie,A as Le,B as He,D as Fe,F as Ae,G as _e,H as $e,J as Ve,K as Je,L as Ge,M as qe,P as ze,O as Ue,Q as We,U as Ke,V as Qe,W as Ye,X as Xe,Y as Ze,Z as et,_ as tt,$ as at,a0 as st,a1 as rt,a2 as nt,a3 as ot,a4 as it,a5 as lt,a6 as ct,a7 as dt,a8 as xt,a9 as ut,aa as mt,ab as pt,ac as ht,ad as bt,ae as vt,af as ft,ag as gt,ah as jt,ai as yt,aj as St,ak as Nt,al as Pt,am as Ct,an as wt,ao as Tt,ap as Rt,aq as Et,ar as Dt,as as kt,at as Bt,au as Mt,av as Ot,aw as It,ax as Lt,ay as Ht,az as Ft,aA as At,aB as _t,aC as $t,aD as Vt,aE as Jt,aF as Gt,aG as qt,aH as zt,aI as Ut,aJ as Wt,aK as Kt,aL as Qt,aM as Yt,aN as Xt,aO as Zt,aP as ea,aQ as ta,aR as aa,aS as sa,aT as ra,aU as na,aV as oa,aW as ia,aX as la,aY as ca,aZ as da,a_ as xa,a$ as ua,b0 as ma,b1 as pa,b2 as ha,b3 as ba,b4 as va,b5 as fa,b6 as ga,b7 as ja,b8 as ya,b9 as Sa,ba as Na,bb as Pa,bc as Ca,bd as wa,be as Ta,bf as Ra,bg as Ea,bh as Da,bi as ka,bj as Ba,bk as Ma,bl as Oa,bm as Ia,bn as La,bo as Ha,bp as Fa,bq as Aa,br as _a,bs as $a,bt as Va,bu as Ja,bv as Ga,bw as qa,bx as za,by as Ua,bz as Wa,bA as Ka,bB as Qa,bC as Ya,bD as Xa,bE as Za,bF as es,bG as ts,bH as as,bI as ss,bJ as rs,bK as ns,bL as os,bM as is,bN as ls,bO as cs,bP as ds,bQ as xs,bR as us,bS as ms,bT as ps,bU as hs,bV as bs,bW as vs,bX as fs,bY as gs,bZ as js,b_ as ys,b$ as Ss,c0 as Ns,c1 as Ps,c2 as Cs,c3 as B,c4 as ws,c5 as Ts,c6 as Rs,c7 as Es,c8 as Ds,c9 as ks,ca as Bs,cb as Ms,cc as Os,cd as Is,ce as Ls,cf as Hs,cg as Fs,ch as As,ci as _s,cj as $s,ck as Vs,cl as Js,cm as Gs,cn as qs,co as zs,cp as Us,cq as Ws,cr as Ks,cs as Qs,ct as Ys,cu as Xs,cv as Zs,cw as er,cx as tr,cy as ar,cz as sr,cA as rr,cB as nr,cC as or,cD as ir,cE as lr,cF as cr,cG as dr,cH as xr,cI as ur,cJ as mr,cK as pr,cL as hr,cM as br,cN as vr,cO as fr,cP as gr,cQ as jr,cR as yr,cS as Sr,cT as Nr,cU as Pr,cV as Cr,cW as wr,cX as Tr,cY as Rr,cZ as Er,c_ as Dr,c$ as kr,d0 as Br,d1 as Mr,d2 as Or,d3 as Ir,d4 as Lr,d5 as Hr,d6 as Fr,d7 as Ar,d8 as _r,d9 as $r,da as Vr,db as Jr,dc as Gr,dd as qr,de as zr,df as Ur}from"./EditorShell-1FTR28BA.js";import{S as Wr,a as Kr,b as Qr,c as Yr}from"./StepsSimulator-CRtmlyNZ.js";import{M as V}from"./Markdown-BHBqz-Mj.js";import{S as Xr,B as w,M as P,a as E,t as S,I as Zr,b as en,c as tn,d as an,e as sn,f as rn,g as nn,h as on,i as ln,j as cn,k as dn,C as xn,l as un}from"./ContainerInspector-CVhTYjTR.js";import{S as J,M as G,f as mn,a as q,b as pn,J as hn,c as bn,d as vn,e as fn,g as gn,h as jn,i as yn,j as Sn,k as Nn,l as Pn,m as Cn,n as wn,o as Tn,p as Rn,q as En,r as Dn,s as kn,t as Bn,u as Mn,v as On,w as In,x as Ln,y as Hn,z as Fn,A as An,B as _n,C as $n,D as Vn,E as Jn,F as Gn,G as qn,H as zn,I as Un,T as Wn,K as Kn,L as Qn,N as Yn,O as Xn}from"./ScenarioDataPanel-Bb7egwjC.js";import{ScenarioDataPanelFullPage as Zn}from"./ScenarioDataPanelFullPage-I0tbkDlL.js";import"./index-6jueUhB_.js";import"./useEvents-DggWrtHe.js";import"./xterm--24IGk-x.js";function z({files:t}){if(t.length===0)return null;const{added:a,modified:s,deleted:r}=xe(t);return e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:[a>0&&e.jsxs("span",{className:"text-[var(--accent-green)]",children:["+",a," "]}),s>0&&e.jsxs("span",{className:"text-[var(--accent-orange)]",children:["~",s," "]}),r>0&&e.jsxs("span",{className:"text-[var(--accent-red)]",children:["-",r," "]}),"file",t.length!==1?"s":""]})}function v({label:t,children:a}){return e.jsxs("div",{className:"mb-2",children:[e.jsx("p",{className:"text-xs font-medium mb-1",style:{color:"var(--text-muted)"},children:t}),e.jsx("div",{className:"mt-0.5",children:a})]})}function U({files:t}){return t.length===0?null:e.jsx("div",{className:"max-h-32 overflow-y-auto",children:t.map(a=>e.jsxs("p",{className:"font-mono text-xs text-[var(--text-muted)]",children:[e.jsx(W,{status:a.status})," ",a.path]},a.path))})}function W({status:t}){const a=t==="added"?"text-[var(--accent-green)]":t==="deleted"?"text-[var(--accent-red)]":"text-[var(--accent-orange)]",s=t==="added"?"+":t==="deleted"?"-":"~";return e.jsx("span",{className:a,children:s})}function K({entry:t}){return e.jsxs("div",{className:"mt-3 pt-3",style:{borderTop:"1px solid var(--border-default)"},children:[t.userRequest&&e.jsx(v,{label:"Request",children:e.jsx(L,{children:t.userRequest})}),e.jsx(v,{label:"Description",children:e.jsx(V,{variant:"compact",children:t.description})}),t.scenarioScreenshots.length>0&&e.jsx(v,{label:"Scenarios",children:e.jsx(H,{screenshots:t.scenarioScreenshots})}),t.modifiedFiles.length>0&&e.jsx(v,{label:"Modified Files",children:e.jsx(U,{files:t.modifiedFiles})}),t.commitSha&&e.jsxs("p",{className:"text-xs",style:{color:"var(--text-dim)"},children:["Commit: ",e.jsx("span",{className:"font-mono",children:t.commitSha.slice(0,7)}),t.commitMessage&&` — ${t.commitMessage}`]})]})}function Q({entry:t}){const[a,s]=d.useState(!1);return e.jsxs("div",{className:"rounded-lg border p-4",style:{borderColor:"var(--border-default)",background:"var(--bg-surface)"},children:[e.jsxs("button",{onClick:()=>s(!a),className:"flex w-full items-start gap-3 text-left",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Y,{type:t.type}),e.jsx("h3",{className:"text-sm font-medium",style:{color:"var(--text-secondary)"},children:t.title})]}),e.jsxs("div",{className:"mt-1 flex items-center gap-3",children:[e.jsx("span",{className:"text-xs",style:{color:"var(--text-dim)"},children:ue(t.timestamp)}),t.testResults&&e.jsx(F,{total:t.testResults.total,passed:t.testResults.passed,failed:t.testResults.failed}),e.jsx(z,{files:t.modifiedFiles})]})]}),e.jsx("span",{className:"text-xs mt-1",style:{color:"var(--text-dim)"},children:a?"▼":"▶"})]}),a&&e.jsx(K,{entry:t})]})}function Y({type:t}){return e.jsx("span",{className:`text-xs font-medium ${me(t)}`,children:t})}function eo({entries:t,total:a,hasMore:s,loading:r,loadingMore:n,error:i,onLoadMore:l}){if(r)return e.jsx("div",{className:"py-12 text-center text-[var(--text-muted)]",children:"Loading journal..."});if(i)return e.jsxs("div",{className:"py-12 text-center text-[var(--accent-red)]",children:["Failed to load journal: ",i]});if(t.length===0)return e.jsxs("div",{className:"py-12 text-center text-[var(--text-dim)]",children:[e.jsx("p",{children:"No journal entries yet."}),e.jsx("p",{className:"mt-2 text-sm text-[var(--text-dim)]",children:"Journal entries capture what was requested, what changed, and the state of tests and scenarios."})]});const c=Math.max(a,t.length);return e.jsxs("div",{className:"overflow-y-auto px-6 py-4",style:{maxHeight:"calc(100vh - 110px)"},children:[e.jsxs("p",{className:"mb-4 text-sm text-[var(--text-muted)]",children:[t.length," of ",c," journal entr",c===1?"y":"ies"]}),e.jsx("div",{className:"flex flex-col gap-3",children:t.map(o=>e.jsx(Q,{entry:o},o.timestamp))}),s?e.jsx("div",{className:"mt-4 flex justify-center",children:e.jsx("button",{type:"button",onClick:l,disabled:n,className:"rounded border border-[var(--border)] px-3 py-1 text-sm text-[var(--text-muted)] hover:bg-[var(--bg-subtle)] disabled:opacity-50",children:n?"Loading...":"Load older entries"})}):null]})}function to({apps:t,selected:a,onChange:s}){return t.length===0?null:e.jsxs("div",{className:"flex gap-1",children:[t.map(r=>e.jsx(D,{href:pe(r.dir),onNavigate:()=>s(r.dir),className:`rounded-md px-3 py-1 text-sm ${a===r.dir?"bg-[var(--bg-input)] text-[var(--text-primary)]":"text-[var(--text-muted)] hover:text-[var(--text-secondary)]"}`,children:r.name},r.dir)),e.jsx(D,{href:"/apps",onNavigate:()=>s(null),className:`rounded-md px-3 py-1 text-sm ${a===null?"bg-[var(--bg-input)] text-[var(--text-primary)]":"text-[var(--text-muted)] hover:text-[var(--text-secondary)]"}`,children:"All"})]})}function ao({segments:t}){return t.length===0?null:e.jsx("span",{className:"text-sm",style:{color:"var(--text-muted)"},children:t.map((a,s)=>e.jsxs("span",{children:[e.jsx("span",{style:{color:"var(--text-dim)"},children:" / "}),a]},s))})}function so(){return e.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-slate-500 space-y-4 px-10 text-center",children:[e.jsx("div",{className:"text-lg font-medium text-slate-400",children:"Ready to build"}),e.jsx("p",{className:"max-w-md",children:"Your first session will start automatically. You can queue changes or wait for the project to initialize."})]})}const ro={http_request:"#3fb950",db_query:"#58a6ff",process_output:"#6e7681",health_check:"#d29922",hook_execution:"#bc8cff",error:"#f85149",scenario_switch:"#d29922"};function no(t){const a=ro[t.type]??"#6e7681";switch(t.type){case"http_request":{const s=t.status??"";return{label:"HTTP",detail:`${t.method} ${t.url} ${s} ${t.durationMs}ms`,badge:t.mocked?"MOCKED":"LIVE",color:a}}case"db_query":return{label:"DB",detail:`${t.query} (${t.durationMs}ms)`,badge:t.mocked?"MOCKED":"LIVE",color:a};case"process_output":return{label:"Process",detail:`[${t.stream}] ${t.line}`,color:a};case"health_check":return{label:"Health",detail:t.healthy?"healthy":"unhealthy",color:a};case"hook_execution":return{label:"Hook",detail:`${t.hook} exit=${t.exitCode} ${t.durationMs}ms`,color:a};case"error":return{label:"Error",detail:`${t.source}: ${t.message}`,color:a};case"scenario_switch":return{label:"Scenario",detail:`${t.from??"(none)"} → ${t.to}`,color:a}}}function X({event:t}){const{label:a,detail:s,badge:r,color:n}=no(t);return e.jsxs("div",{className:"my-1 rounded-md bg-[var(--bg-surface)] px-3 py-2 font-mono text-sm",style:{borderLeft:`3px solid ${n}`},children:[e.jsx("span",{className:"mr-2 font-semibold",children:a}),e.jsx("span",{className:"text-[var(--text-secondary)]",children:s}),r&&e.jsx("span",{className:`ml-2 text-xs ${r==="MOCKED"?"text-[var(--accent-green)]":"text-[var(--text-muted)]"}`,children:r})]})}function oo({events:t}){return t.length===0?e.jsx("div",{className:"py-12 text-center text-[var(--text-dim)]",children:"Waiting for events..."}):e.jsx("div",{className:"overflow-y-auto px-6 py-2",style:{maxHeight:"calc(100vh - 110px)"},children:t.map(a=>e.jsx(X,{event:a},a.id))})}function Z({passed:t,failed:a,total:s}){return a>0?e.jsxs("span",{className:"rounded bg-[var(--accent-red)]/20 px-2 py-0.5 text-xs text-[var(--accent-red)]",children:[a," failed"]}):t===s&&s>0?e.jsxs("span",{className:"rounded bg-[var(--accent-green)]/20 px-2 py-0.5 text-xs text-[var(--accent-green)]",children:[t," passed"]}):e.jsxs("span",{className:"text-xs text-[var(--text-dim)]",children:["(",s,")"]})}function ee({group:t}){const[a,s]=d.useState(!0),r=t.tests.filter(l=>l.status==="passed").length,n=t.tests.filter(l=>l.status==="failed").length,i=t.tests.length;return e.jsxs("div",{className:"mb-4",children:[e.jsxs("button",{onClick:()=>s(!a),className:"flex w-full items-center gap-2 text-left text-sm font-medium text-[var(--text-secondary)] hover:text-[var(--text-primary)]",children:[e.jsx("span",{className:"text-[var(--text-dim)]",children:a?"▼":"▶"}),e.jsx("span",{children:t.feature}),e.jsx(Z,{passed:r,failed:n,total:i})]}),a&&e.jsx("div",{className:"ml-5 mt-1 border-l border-[var(--border-default)] pl-3",children:t.tests.map((l,c)=>e.jsx(A,{test:l},c))})]})}function io({filters:t,active:a,onChange:s}){return e.jsx("div",{className:"flex gap-2 border-b px-6 py-3",style:{borderColor:"var(--border-default)"},children:t.map(r=>e.jsx("button",{onClick:()=>s(r),className:"rounded-md border px-3 py-1 text-sm",style:r===a?{borderColor:"var(--accent-active)",background:"var(--accent-active)",color:"var(--bg-nav)"}:{borderColor:"var(--border-default)",background:"var(--bg-surface)",color:"var(--text-secondary)"},children:r},r))})}function te({scenario:t,onPreview:a}){const s=t.screenshotPaths.length>0,[r,n]=d.useState(!1),i=s&&!r;return e.jsxs("div",{className:`rounded-lg border border-[var(--border-default)] bg-[var(--bg-surface)] p-3 ${a?"cursor-pointer hover:border-[var(--border-subtle)]":""}`,onClick:a,children:[i?e.jsx("img",{src:he(t.screenshotPaths[0]),alt:t.name,className:"mb-2 w-full rounded border border-[var(--border-default)]",onError:()=>n(!0)}):e.jsx("div",{className:"mb-2 flex h-32 items-center justify-center rounded border border-dashed border-[var(--border-default)] text-sm text-[var(--text-dim)]",children:"No screenshot"}),e.jsx("p",{className:"text-sm font-medium text-[var(--text-secondary)]",children:t.name}),e.jsxs("div",{className:"mt-1 flex gap-1",children:[t.hasMocks&&e.jsx("span",{className:"rounded bg-[var(--accent-blue)]/20 px-1.5 py-0.5 text-xs text-[var(--accent-blue)]",children:"mocks"}),t.hasSeed&&e.jsx("span",{className:"rounded bg-[var(--accent-purple)]/20 px-1.5 py-0.5 text-xs text-[var(--accent-purple)]",children:"seed"}),t.dimensions.map(l=>e.jsx("span",{className:"rounded bg-[var(--bg-input)] px-1.5 py-0.5 text-xs text-[var(--text-muted)]",children:l},l))]})]})}function ae({group:t,onPreviewScenario:a}){const[s,r]=d.useState(!0);return e.jsxs("div",{className:"mb-6",children:[e.jsxs("button",{onClick:()=>r(!s),className:"flex w-full items-center gap-2 text-left text-sm font-medium text-[var(--text-secondary)] hover:text-[var(--text-primary)]",children:[e.jsx("span",{className:"text-[var(--text-dim)]",children:s?"▼":"▶"}),e.jsx("span",{className:"font-mono",children:t.route}),e.jsxs("span",{className:"text-[var(--text-dim)]",children:["(",t.scenarios.length,")"]})]}),s&&e.jsx("div",{className:"mt-2 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3",children:t.scenarios.map(n=>e.jsx(te,{scenario:n,onPreview:a?()=>a(n.slug):void 0},n.slug))})]})}function se({fileName:t,dirPath:a}){return e.jsxs("div",{className:"flex items-center gap-3 rounded-md px-3 py-2 text-left bg-[var(--bg-card)] border border-[var(--border-subtle)] hover:border-[var(--border-default)] transition",children:[e.jsx("span",{className:"text-xs text-[var(--text-secondary)]",children:t}),e.jsxs("span",{className:"font-mono text-[10px] text-[var(--text-dim)]",children:[a,"/"]})]})}function lo({slug:t,name:a,url:s,componentName:r,props:n,mocks:i,seed:l,localStorage:c,dimensions:o}){const[u,f]=d.useState(!1),b=Object.keys((i==null?void 0:i.http)??{}).length,p=Object.keys((i==null?void 0:i.db)??{}).length,h=Object.keys(c??{});return e.jsxs("div",{className:"space-y-3 text-sm",children:[e.jsx("h3",{className:"font-medium text-[var(--text-secondary)]",children:a}),s&&e.jsx(v,{label:"URL",children:e.jsx("span",{className:"font-mono text-xs text-[var(--text-muted)]",children:s})}),r&&e.jsx(v,{label:"Component",children:e.jsx("span",{className:"font-mono text-xs text-[var(--accent-blue)]",children:r})}),n&&e.jsx(v,{label:"Props",children:e.jsx("pre",{className:"max-h-32 overflow-auto rounded bg-[var(--bg-input)] p-2 font-mono text-xs text-[var(--text-muted)]",children:JSON.stringify(n,null,2)})}),b>0&&e.jsxs(v,{label:"Mocks",children:[t?e.jsxs("button",{type:"button",onClick:()=>f(!0),className:"text-xs text-[var(--accent-blue)] hover:underline bg-transparent border-none cursor-pointer p-0",children:[b," HTTP mock",b!==1?"s":""," →"]}):e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:[b," HTTP mock",b!==1?"s":""]}),p>0&&e.jsxs("span",{className:"ml-2 text-xs text-[var(--text-muted)]",children:[p," DB mock",p!==1?"s":""]})]}),l&&e.jsx(v,{label:"Seed",children:l.command&&e.jsx("span",{className:"font-mono text-xs text-[var(--text-muted)]",children:l.command})}),h.length>0&&e.jsx(v,{label:"localStorage",children:h.map(m=>e.jsxs("p",{className:"font-mono text-xs text-[var(--text-muted)]",children:[m,": ",c[m]]},m))}),o.length>0&&e.jsx(v,{label:"Dimensions",children:e.jsx("div",{className:"flex gap-1",children:o.map(m=>e.jsx("span",{className:"rounded bg-[var(--bg-input)] px-1.5 py-0.5 text-xs text-[var(--text-muted)]",children:m},m))})}),u&&t&&e.jsx(J,{slug:t,scenarioName:a,initialSection:"mocks",onClose:()=>f(!1)})]})}function re({value:t,onChange:a=()=>{},parseError:s,onParseError:r=()=>{}}){return d.useEffect(()=>{if(t.trim()===""){r(null);return}try{JSON.parse(t),r(null)}catch(n){r(n instanceof Error?n.message:"Invalid JSON")}},[t,r]),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-xs text-[var(--text-muted)]",children:"Body (JSON)"}),e.jsx("textarea",{value:t,onChange:n=>a(n.target.value),rows:8,spellCheck:!1,className:`w-full rounded border bg-[var(--bg-surface)] px-2 py-1 text-xs font-mono resize-y ${s?"border-red-500":"border-[var(--border-default)]"}`}),s&&e.jsx("p",{className:"text-xs text-red-400 font-mono",children:s})]})}function ne({initialStatus:t,initialBody:a,initialHeaders:s,onSave:r,onCancel:n}){const i=d.useMemo(()=>{if(a==null)return"";try{return JSON.stringify(a,null,2)}catch{return""}},[a]),[l,c]=d.useState(t),[o,u]=d.useState(i),[f,b]=d.useState(null),[p,h]=d.useState(()=>Object.entries(s).map(([x,C])=>({name:x,value:C}))),[m,j]=d.useState(!0),y=f!==null||m;function g(){const x=o.trim()===""?null:JSON.parse(o),C={};for(const R of p)R.name.trim()&&(C[R.name.trim()]=R.value);r({status:l,body:x,headers:C})}return e.jsxs("div",{className:"mt-2 border border-[var(--border-subtle)] rounded bg-[var(--bg-input)] p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("label",{className:"text-xs text-[var(--text-muted)]",children:"Status"}),e.jsx("input",{type:"number",value:l,onChange:x=>{j(!1),c(Number(x.target.value))},className:"w-20 rounded border border-[var(--border-default)] bg-[var(--bg-surface)] px-2 py-1 text-xs font-mono"})]}),e.jsx(G,{headers:p,onChange:x=>{j(!1),h(x)}}),e.jsx(re,{value:o,parseError:f,onChange:x=>{j(!1),u(x)},onParseError:b}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:n,className:"px-3 py-1 text-xs rounded border border-[var(--border-default)] bg-transparent text-[var(--text-muted)] hover:text-[var(--text-primary)] cursor-pointer",children:"Cancel"}),e.jsx("button",{type:"button",onClick:g,disabled:y,className:"px-3 py-1 text-xs rounded border border-[var(--accent-blue)] bg-[var(--accent-blue)]/10 text-[var(--accent-blue)] hover:bg-[var(--accent-blue)]/20 disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer",children:"Save"})]})]})}function oe({entry:t,scenarioHasDefaultFallback:a,editing:s,onToggleEdit:r,onPromoteDefaultToScenario:n,onRemove:i,onPassthrough:l,onCaptureLive:c}){const[o,u]=d.useState(!1),[f,b]=d.useState(null);async function p(){u(!0),b(null);try{await c()}catch(m){b(m instanceof Error?m.message:"Capture failed")}finally{u(!1)}}const h="px-2 py-0.5 rounded border border-[var(--border-default)] bg-transparent text-[var(--text-muted)] hover:text-[var(--text-primary)] cursor-pointer text-[10px]";return e.jsxs("div",{className:"flex flex-wrap gap-1 pt-1",children:[t.source==="scenario"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:r,className:h,children:s?"Close":"Edit"}),a&&e.jsx("button",{onClick:i,className:h,title:"Revert to default",children:"Revert to default"}),e.jsx("button",{onClick:l,className:h,children:"Mark passthrough"})]}),t.source==="default"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:n,className:"px-2 py-0.5 rounded border border-emerald-500/50 bg-emerald-500/10 text-emerald-300 hover:bg-emerald-500/20 cursor-pointer text-[10px]",title:"Copy default body into this scenario",children:"Promote to scenario"}),e.jsx("button",{onClick:l,className:h,children:"Mark passthrough"})]}),t.source==="catalog-only"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:p,disabled:o,className:"px-2 py-0.5 rounded border border-blue-500/50 bg-blue-500/10 text-blue-300 hover:bg-blue-500/20 disabled:opacity-50 disabled:cursor-wait cursor-pointer text-[10px]",title:"Write last-observed body as this scenario's mock",children:o?"Capturing…":"Capture from live"}),f&&e.jsx("span",{className:"text-red-400 text-[10px]",children:f})]}),t.source==="passthrough"&&e.jsx("button",{onClick:i,className:h,children:"Undo passthrough"})]})}const M={GET:"text-emerald-400 border-emerald-400/40",POST:"text-blue-400 border-blue-400/40",PUT:"text-amber-400 border-amber-400/40",PATCH:"text-purple-400 border-purple-400/40",DELETE:"text-red-400 border-red-400/40"};function ie({entry:t}){const a=M[t.method]??M.GET,s=t.status??t.lastObservedStatus,r=t.lastObservedMs?mn(t.lastObservedMs,Date.now()):null;return e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:`px-1.5 py-0.5 rounded border font-mono ${a}`,children:t.method}),e.jsx("span",{className:"font-mono text-[var(--text-primary)] break-all",children:t.pathPattern}),e.jsx(q,{source:t.source}),s!==void 0&&e.jsx("span",{className:"px-1.5 py-0.5 rounded border border-[var(--border-default)] text-[var(--text-muted)] font-mono",children:s}),t.observedCount>0&&e.jsxs("span",{className:"ml-auto text-[var(--text-dim)]",children:[t.observedCount,"× ",r?`· ${r}`:""]})]})}function le({entry:t,scenarioHasDefaultFallback:a,onSave:s,onRemove:r,onPassthrough:n,onCaptureLive:i}){const[l,c]=d.useState(!1),o=`${t.method} ${t.pathPattern}`;return e.jsxs("div",{className:"border border-[var(--border-subtle)] rounded p-2 text-xs space-y-1",children:[e.jsx(ie,{entry:t}),t.variants.length>1&&e.jsxs("div",{className:"text-[10px] text-[var(--text-dim)] font-mono",children:["variants: ",t.variants.filter(u=>u!==o).join(", ")]}),e.jsx(oe,{entry:t,scenarioHasDefaultFallback:a,editing:l,onToggleEdit:()=>c(u=>!u),onPromoteDefaultToScenario:()=>s({routeKey:o,status:t.status??200,body:t.body,headers:t.headers??{}}),onRemove:()=>r(o),onPassthrough:()=>n(o),onCaptureLive:()=>i(t.method,t.pathPattern)}),l&&e.jsx(ne,{initialStatus:t.status??200,initialBody:t.body,initialHeaders:t.headers??{},onCancel:()=>c(!1),onSave:async u=>{await s({routeKey:o,...u}),c(!1)}})]})}const T=async()=>{};function co({label:t,entries:a,defaultEndpointKeys:s=[],onSave:r=T,onRemove:n=T,onPassthrough:i=T,onCaptureLive:l=T}){if(a.length===0)return null;const c=s instanceof Set?s:new Set(s);return e.jsxs("section",{className:"space-y-2",children:[e.jsxs("h3",{className:"text-[10px] font-semibold uppercase tracking-wide text-[var(--text-dim)]",children:[t," (",a.length,")"]}),e.jsx("div",{className:"space-y-2",children:a.map(o=>e.jsx(le,{entry:o,scenarioHasDefaultFallback:c.has(`${o.method} ${o.pathPattern}`),onSave:r,onRemove:n,onPassthrough:i,onCaptureLive:l},`${o.method} ${o.pathPattern}`))})]})}function xo({scenarioName:t,defaultSlug:a,onClose:s}){return e.jsxs("header",{className:"sticky top-0 z-10 flex items-center justify-between gap-2 border-b border-[var(--border-subtle)] bg-[var(--bg-deep)] px-4 py-3",children:[e.jsxs("div",{children:[e.jsxs("h2",{className:"text-sm font-medium text-[var(--text-primary)]",children:["Mocks for ",t]}),a&&e.jsxs("p",{className:"text-xs text-[var(--text-dim)]",children:["Defaults inherited from ",e.jsx("span",{className:"font-mono",children:a})]})]}),e.jsx("button",{onClick:s,className:"rounded border border-[var(--border-default)] bg-transparent px-2 py-1 text-xs text-[var(--text-muted)] hover:text-[var(--text-primary)] cursor-pointer",children:"Close"})]})}function uo({total:t,passed:a,failed:s,discovered:r}){if(t===0&&(r??0)>0)return e.jsxs("span",{className:"text-[var(--text-dim)]",children:[r," ",r===1?"test":"tests"," (not run)"]});if(t===0)return e.jsx("span",{className:"text-[var(--text-dim)]",children:"No tests"});const n=(r??t)>t?(r??t)-t:0;return n>0?e.jsxs("span",{children:[e.jsxs("span",{className:"text-[var(--accent-green)]",children:[a," passed"]}),s>0&&e.jsxs("span",{className:"text-[var(--accent-red)]",children:[" · ",s," failed"]}),e.jsxs("span",{className:"text-[var(--text-dim)]",children:[" · ",n," not run"]})]}):s>0?e.jsxs("span",{className:"text-[var(--accent-red)]",children:[a,"/",t," passed"]}):e.jsxs("span",{className:"text-[var(--accent-green)]",children:[a,"/",t," passed"]})}function mo({groups:t,loading:a,error:s,totalScenarios:r,onPreviewScenario:n}){return a?e.jsx("div",{className:"py-12 text-center text-[var(--text-muted)]",children:"Loading scenarios..."}):s?e.jsxs("div",{className:"py-12 text-center text-[var(--accent-red)]",children:["Failed to load scenarios: ",s]}):t.length===0?e.jsxs("div",{className:"py-12 text-center text-[var(--text-dim)]",children:[e.jsx("p",{children:"No scenarios defined yet."}),e.jsx("p",{className:"mt-2 text-sm text-[var(--text-dim)]",children:"Create scenario JSON files in .codeyam/scenarios/"})]}):e.jsxs("div",{className:"overflow-y-auto px-6 py-4",style:{maxHeight:"calc(100vh - 110px)"},children:[e.jsxs("p",{className:"mb-4 text-sm text-[var(--text-muted)]",children:[r," scenarios across ",t.length," routes"]}),t.map(i=>e.jsx(ae,{group:i,onPreviewScenario:n},i.route))]})}function po({groups:t,loading:a,error:s,cached:r,totalTests:n,passedTests:i,coverage:l,onRefresh:c}){return a?e.jsx("div",{className:"py-12 text-center text-[var(--text-muted)]",children:"Loading tests..."}):s?e.jsxs("div",{className:"py-12 text-center text-[var(--accent-red)]",children:["Failed to load tests: ",s]}):t.length===0?e.jsx("div",{className:"py-12 text-center text-[var(--text-dim)]",children:"No tests found"}):e.jsxs("div",{className:"overflow-y-auto px-6 py-4",style:{maxHeight:"calc(100vh - 110px)"},children:[e.jsxs("div",{className:"mb-4 flex items-center gap-3 text-sm text-[var(--text-muted)]",children:[e.jsxs("span",{children:[i,"/",n," passed across ",t.length," features"]}),e.jsx(_,{coverage:l,testId:"tests-view-coverage",className:"rounded bg-[var(--bg-input)] px-2 py-0.5 text-xs font-medium text-[var(--text-secondary)]"}),r&&e.jsx("span",{className:"rounded bg-[var(--bg-input)] px-2 py-0.5 text-xs text-[var(--text-muted)]",children:"cached"}),e.jsx("button",{onClick:c,disabled:a,className:"rounded bg-[var(--bg-input)] px-2 py-0.5 text-xs text-[var(--text-muted)] hover:bg-[var(--bg-surface)] hover:text-[var(--text-secondary)] disabled:opacity-50",children:a?"Running...":"Run Tests"})]}),t.map(o=>e.jsx(ee,{group:o},o.feature))]})}function ho({tabs:t,active:a,onChange:s}){return e.jsx("div",{className:"flex gap-0",children:t.map(r=>e.jsx("button",{onClick:()=>s(r.key),className:`px-3 py-2 text-sm transition-colors border-b-2 ${a===r.key?"font-medium":"border-transparent hover:text-[var(--text-primary)]"}`,style:a===r.key?{color:"var(--accent-active)",borderBottomColor:"var(--accent-active)"}:{color:"var(--text-muted)"},children:r.label},r.key))})}function bo({restartCount:t}){return e.jsx("div",{className:"absolute inset-0 bg-white/90 dark:bg-gray-900/90 backdrop-blur-sm flex flex-col items-center justify-center z-50 animate-in fade-in duration-300",children:e.jsxs("div",{className:"flex flex-col items-center space-y-4 text-center max-w-md p-6",children:[e.jsx(k,{restartCount:t}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-gray-100",children:"Dev Server Restarting"}),e.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:"The Live Preview server crashed unexpectedly. CodeYam is automatically recovering it..."})]}),t>2&&e.jsx("div",{className:"pt-2",children:e.jsx("p",{className:"text-xs text-amber-600 dark:text-amber-400 font-medium",children:"Recovery is taking longer than usual..."})})]})})}function vo(){return e.jsx("div",{className:"absolute inset-0 bg-white/90 dark:bg-gray-900/90 backdrop-blur-sm flex flex-col items-center justify-center z-50 animate-in fade-in duration-300",children:e.jsxs("div",{className:"flex flex-col items-center space-y-4 text-center max-w-md p-6",children:[e.jsx(k,{restartCount:0}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-gray-100",children:"Starting Dev Server"}),e.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:"Waiting for the development server to start..."})]})]})})}function fo(){return e.jsx("div",{className:"absolute inset-0 bg-white/90 dark:bg-gray-900/90 backdrop-blur-sm flex flex-col items-center justify-center z-50 animate-in fade-in duration-300",children:e.jsxs("div",{className:"flex flex-col items-center space-y-4 text-center max-w-md p-6",children:[e.jsx("div",{className:"w-12 h-12 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center",children:e.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",className:"w-6 h-6 text-gray-500 dark:text-gray-400","aria-hidden":"true",children:[e.jsx("rect",{x:"6",y:"5",width:"4",height:"14",rx:"1"}),e.jsx("rect",{x:"14",y:"5",width:"4",height:"14",rx:"1"})]})}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-gray-100",children:"Dev Server Not Running"}),e.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:"Starting automatically…"})]})]})})}function go({title:t,count:a,children:s}){return e.jsxs("div",{className:"mt-5",children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between gap-4",children:[e.jsx("p",{className:"text-xs font-semibold uppercase tracking-[0.18em] text-[var(--text-dim)]",children:t}),e.jsxs("p",{className:"text-xs text-[var(--text-dim)]",children:[a," total"]})]}),s]})}function ce(){return e.jsx("div",{className:"rounded-xl border border-dashed border-[var(--border-default)] px-4 py-5 text-sm text-[var(--text-dim)]",children:"No direct imports were found for this route file."})}function jo({directImports:t}){return t.length===0?e.jsx(ce,{}):e.jsx("div",{className:"grid grid-cols-1 gap-1",children:t.map(a=>{const{fileName:s,dirPath:r}=be(a);return e.jsx(se,{fileName:s,dirPath:r},a)})})}function yo({routeEntity:t}){return e.jsxs("div",{className:"rounded-xl border border-[var(--border-default)] bg-[var(--bg-elevated)] px-4 py-4",children:[e.jsx("p",{className:"text-xs font-semibold uppercase tracking-[0.18em] text-[var(--text-dim)]",children:"Route"}),e.jsx("p",{className:"mt-2 text-lg font-semibold text-[var(--text-primary)]",children:t.displayName}),e.jsx("p",{className:"mt-1 font-mono text-xs text-[var(--accent-blue)]",children:t.route}),t.pageFilePath?e.jsx("p",{className:"mt-3 text-sm text-[var(--text-muted)]",children:t.pageFilePath}):e.jsx("p",{className:"mt-3 text-sm text-[var(--text-dim)]",children:"No source file is linked to this route yet."})]})}function So({tabs:t,activeTable:a,onSelectTable:s,onClose:r}){return e.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1.5 bg-[var(--bg-card)] border-b border-[var(--border-default)] flex-wrap",children:[t.map(n=>e.jsx(No,{tab:n,isActive:a===n.dataKey,onClick:()=>s(n.dataKey)},n.dataKey)),e.jsx("div",{className:"flex-1"}),e.jsx("button",{onClick:r,className:"w-5 h-5 flex items-center justify-center text-[var(--text-dim)] hover:text-[var(--text-primary)] bg-[var(--bg-input)] hover:bg-[var(--border-default)] rounded-full border-none cursor-pointer text-xs transition-colors",title:"Close",children:"×"})]})}function No({tab:t,isActive:a,onClick:s}){const r=t.category==="datastore"?a?"text-[var(--accent-active)] bg-[var(--accent-active)]/15 border-[var(--accent-active)]/40":"text-[var(--accent-active)]/60 bg-transparent border-transparent hover:text-[var(--accent-active)]/80":t.category==="mock-api"?a?"text-blue-400 bg-blue-400/15 border-blue-400/40":"text-blue-400/60 bg-transparent border-transparent hover:text-blue-400/80":a?"text-[var(--text-primary)] bg-[var(--border-default)] border-[var(--border-default)]":"text-[var(--text-dim)] bg-transparent border-transparent hover:text-[var(--text-secondary)]";return e.jsx("button",{onClick:s,className:`px-2.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider rounded cursor-pointer border transition-colors ${r}`,children:t.label})}function Po({featureName:t,onClose:a}){return e.jsx("div",{className:"absolute inset-0 z-10 flex items-center justify-center",style:{background:"rgba(30, 30, 30, 0.90)"},children:e.jsx($,{featureName:t,onClose:a})})}function O(){return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,padding:16,background:"#0d1117",color:"#c9d1d9",fontFamily:"'SF Mono', Menlo, monospace",fontSize:13},children:[e.jsx(Xr,{title:"Section Header Example"}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx(w,{color:"#238636",children:"ACTIVE"}),e.jsx(w,{color:"#d29922",children:"WARNING"}),e.jsx(w,{color:"#da3633",children:"ERROR"}),e.jsx(w,{color:"#58a6ff",children:"INFO"})]}),e.jsxs("div",{style:{display:"flex",gap:12},children:[e.jsx(P,{method:"GET"}),e.jsx(P,{method:"POST"}),e.jsx(P,{method:"PUT"}),e.jsx(P,{method:"DELETE"}),e.jsx(P,{method:"PATCH"})]}),e.jsx(E,{color:"#238636",children:"Success status message"}),e.jsx(E,{color:"#d29922",children:"Warning status message"}),e.jsx(E,{color:"#8b949e",children:"Neutral status message"})]})}const Co=[{type:"http_request",id:"evt-1",timestampMs:Date.now(),method:"GET",url:"/api/tasks",status:200,durationMs:2,mocked:!0},{type:"http_request",id:"evt-2",timestampMs:Date.now(),method:"POST",url:"/api/users/register",status:201,durationMs:145,mocked:!1}];function I({events:t}){const a=t??Co;return e.jsx("div",{style:{background:"#0d1117",padding:16},children:e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12,fontFamily:"'SF Mono', Menlo, monospace",color:"#c9d1d9"},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{borderBottom:"1px solid #30363d"},children:[e.jsx("th",{style:S,children:"Time"}),e.jsx("th",{style:S,children:"Method"}),e.jsx("th",{style:{...S,textAlign:"left"},children:"URL"}),e.jsx("th",{style:S,children:"Status"}),e.jsx("th",{style:S,children:"Duration"}),e.jsx("th",{style:S,children:"Source"})]})}),e.jsx("tbody",{children:a.map(s=>e.jsx(Zr,{event:s},s.id))})]})})}function wo(){return e.jsx("div",{"aria-hidden":"true",className:"pointer-events-none absolute inset-0",style:{background:"repeating-linear-gradient(45deg, transparent 0 24px, rgba(255,255,255,0.025) 24px 48px)"}})}function de({error:t}){return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--bg-deep)] text-[var(--accent-red)]",children:e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg",children:"Seed Error"}),e.jsx("p",{className:"mt-2 text-sm",children:t}),e.jsx("p",{className:"mt-2 text-xs text-[var(--text-muted)]",children:"The database state shown may not match this scenario."})]})})}const To={AppCard:Ur,AppDetail:zr,AppOverview:qr,BuildTab:Gr,BuildTabLayout:Jr,BuildTabPane:Vr,BuildTabPaneLayout:$r,BuildTabRecoveryPanel:_r,BuildTabSessionContent:Ar,BuildTabStartupError:Fr,BuildTabReadyToBuildPlaceholder:so,BuildTabTerminalSession:Hr,AppSelector:to,AppTypeBadge:Lr,BreadcrumbNav:ao,BuildingPreviewOverlay:Ir,ConnectionBadge:un,DebugModeButton:Or,DebugModal:Mr,DebugModalElementPreview:Br,DebugModalInfoPanel:kr,DebugOverlay:Dr,DebugAncestryList:Er,DebugAncestrySection:Rr,DebugPropsChips:Tr,DebugFreezePill:wr,OpenInEditorErrorToast:Cr,CyLogo:Pr,DeviceIcon:Nr,EditorNavBar:Sr,IdleBanner:yr,EditorSessionRecoveryActionButton:jr,EditorSessionRecoveryDialog:gr,EditorSessionRecoveryHeader:fr,EditorSessionRecovery:vr,EditorSessionRecoverySummaryRow:br,EditorSessionRecoverySummary:hr,EditorShellHomeTabContent:pr,EditorShellBuildLayer:mr,EditorShellLayout:ur,EditorShellLeftPane:xr,EditorShellPlanLayer:dr,EditorShellPreviewPane:B,EditorShellTabLayer:cr,GearIcon:lr,EventCard:X,EventStream:oo,EntryTypeBadge:Y,CollapsibleMarkdown:L,FeatureNameButton:ir,FeatureGroupView:ee,FileChangeSummary:z,FileStatusIndicator:W,FileStatusIndicatorStandalone:or,HistoryTab:nr,HistoryEntryCard:rr,CommitOnlyHistoryRow:sr,NotificationSettingsPopover:ar,DebugNotificationsButton:tr,IdleTriggerCheckbox:er,JournalEntryCard:Q,JournalEntryDetails:K,JournalView:eo,LabeledSection:v,FilterBar:io,LeftPanel:Zs,ModifiedFilesList:U,NavLink:D,StepProgressBar:Xs,TestRunnerStatsBar:Ys,TestsSummaryCard:Qs,NarrativeSection:Ks,PreNarrativeFallback:Ws,ModifiedFilesSection:Us,Markdown:V,NewProjectQuestionnaire:zs,QuestionnaireIntroBanner:qs,QuestionnaireDeviceSelector:Gs,QuestionnaireNavButtons:Js,QuestionnaireOptionCard:Vs,PanelDivider:$s,PromptDropdownPanel:_s,PreviewCanvas:As,PreviewEmptyState:Fs,PreviewFrame:Hs,BackendResultsPanelView:Ls,PlanPreviewPanelView:Is,PlanPreviewEmptyState:Os,PlanPreviewHeader:Ms,ProjectSetupPreviewView:Bs,ProjectSetupHeader:ks,ProjectSetupDescriptionCard:Ds,ProjectSetupProgressList:Es,ProjectSetupProgressRow:Rs,ProjectSetupFooterHint:Ts,LiveIframeHealthPill:ws,PreviewPanel:B,QuestionnaireStepNav:Cs,QuestionnaireStepPanel:Ps,AppDetailContent:Ns,AppDetailContentError:Ss,AppDetailContentLoading:ys,AppDetailHeader:js,RouteDependencyCard:gs,RouteDependencyCardHeader:fs,RouteDependencyEmptyState:vs,RouteDependencyList:bs,RouteDependencyScenarioStrip:hs,RouteEntityDetail:ps,RouteEntityDetailContent:ms,RouteFunctionCard:us,RouteFunctionEmptyState:xs,RouteFunctionList:ds,RouteEntityDetailHeader:cs,RouteEntityTabs:ls,RouteGroupView:ae,RouteImportRow:se,RouteList:is,RouteListCardThumbnail:os,RouteScenarioList:ns,ScenarioCard:te,ScenarioRow:rs,ScenarioDetailPanel:lo,MockBodyEditor:ne,MockBodyHeadersEditor:G,MockBodyJsonTextarea:re,MockPanelGroup:co,MockPanelHeader:xo,MockPanelRow:le,MockPanelRowActions:oe,MockPanelRowHeader:ie,MockSourceBadge:q,ScenarioThumbnailGrid:H,StatusBadge:Z,StepIndicatorBar:ss,StepIndicatorDropdownItem:as,TabPane:ts,TestItem:A,TestGroupHeader:es,TestGroupList:Za,TestGroupRow:Xa,TestResultsBadge:F,TestSummary:uo,TestStatusIcon:Ya,ThumbnailStrip:Qa,CollapseToggleButton:Ka,DimensionInput:Wa,EditorShell:Ua,FillPreviewButton:za,OpenInNewTabButton:qa,PlaceholderPane:Ga,PlanTab:Ja,PlanTabHeader:Va,PlanNextChangeButton:$a,PlanAuthoringChat:_a,PlanRow:Aa,PlanRowDependencyEntry:Fa,PlanRowEditButton:Ha,PlanRowEditChatButton:La,PlanRowExpandedBody:Ia,PlanRowExpandedChat:Oa,PlanRowExpandedDependencies:Ma,PlanRowExpandedEdit:Ba,PlanRowExpandedView:ka,PlanRunButton:Da,PlanRunBlockedModal:Ea,PlanRunDependenciesModal:Ra,QueuedChangesSection:Ta,SortablePlanRow:wa,RecentPlansSection:Ca,CompletedPlanRow:Pa,CompletedPlanExpandedBody:Na,TabScrollPanel:Sa,BuildLaunchModal:ya,PostPushTransition:ja,PostPushTransitionDialog:ga,SelectPlanModal:fa,SelectPlanCard:va,PlanCompleteDialog:ba,PlanCompleteTransition:ha,ScenarioRenderer:Oo,ScenariosView:mo,TerminalEmulator:pa,TerminalDropOverlay:ma,TerminalDropToast:ua,TerminalDisconnectOverlay:Xn,TerminalConnectingHint:Yn,TerminalReconnectingBanner:Qn,TerminalFailedBanner:Kn,TerminalServerStoppedBanner:Wn,TestsView:po,NavigationBar:xa,PagePill:da,PagePickerDropdown:ca,StatesDropdown:la,CreateStatePlaceholderModal:ia,StatesPillButton:oa,EditDataButton:na,EditDataPopover:ra,EditDataPopoverBody:sa,EditDataPopoverDescribeInput:aa,EditDataPopoverHeader:ta,EditDataPopoverResizeHandleLeft:ea,EditDataPopoverSaveCancelClose:Zt,EditDataPopoverSearchInput:Xt,EditDataPopoverSectionSelector:Yt,EditDataPopoverTabStrip:Qt,ScenarioDataPanelMainProps:Kt,ScenarioDataPanelPropsEditor:Wt,ViewportPresetButton:Ut,PagePickerTabButton:zt,PagePickerEmptyMessage:qt,PagePickerScenarioThumbnail:Gt,PagePickerRouteSection:Jt,StatesDropdownRow:Vt,ComponentGlyph:$t,DropdownChevron:_t,PageGlyph:At,ViewTabs:ho,SessionResultsPanel:Ft,SessionResultsPanelHeader:Ht,BackendResultsPage:Lt,BackendConnectionStatusBadge:It,BackendConnectionLogEntryRow:Ot,BackendConnectionLogSection:Mt,NarrativeTestStatusIcon:Bt,CoverageBadge:_,CoverageBar:kt,CoverageWarningsBanner:Dt,FunctionsCoverageSection:Et,CoverageSectionHeader:Rt,OrphanedFileRow:Tt,FunctionsCoverageEmptyState:wt,ProjectWideCoverageRollup:Ct,CoverageDetailsModal:Pt,CoverageFileDrilldown:Nt,CoverageDetailsEntriesSection:St,CoverageDetailsEntryRow:yt,CoverageDetailsOrphanedSection:jt,CoverageDetailsDirectoriesSection:gt,CoverageDetailsDirectoryGroup:ft,CoverageDetailsDirectoryFileRow:vt,CoverageLineRow:bt,AppCardFooter:ht,RunTestsButton:pt,TestBar:mt,AppCardHeader:ut,AppCardScenarioStrip:xt,AppOverviewEmptyState:dt,AppOverviewEmptyStateBuildingPanel:ct,AppOverviewEmptyStateNoAppPanel:lt,OpenBuildTabButton:it,AppOverviewGrid:ot,AppOverviewHeader:nt,CopyButton:rt,CrashLogFooter:st,CrashLogFooterMessage:at,CrashLogHeader:tt,CrashLogViewer:et,DevServerCrashLog:Ze,DevServerRestartingOverlay:bo,DevServerStartingOverlay:vo,DevServerStoppedOverlay:fo,PreviewUnhealthyOverlay:Xe,PreviewErrorOverlay:Ye,PreviewErrorOverlayHeader:Qe,PreviewErrorOverlayFooter:Ke,PreviewErrorList:We,PreviewErrorRow:Ue,PreviewErrorBadge:ze,BuildSpinner:qe,RestartSpinner:k,RouteEntitySection:go,RouteImportEmptyState:ce,RouteImportList:jo,RouteListCard:Ge,RouteListEmptyState:Je,RouteListSectionHeader:Ve,RouteScenarioEmptyState:$e,RouteSummaryCard:yo,SafeScreenshot:_e,ScenarioRowMeta:Ae,ScenarioRowOverrideBadge:Fe,ScenarioRowThumbnail:He,SidebarGroupOverrideHeader:Un,SidebarInheritedSection:zn,DataViewerCategoryBadge:qn,DataViewerCellEditor:Gn,DataViewerTabBar:So,DataViewerTable:Jn,ScenarioDataPanel:J,ScenarioDataPanelCloseButton:Vn,ScenarioDataPanelEditChatButton:$n,ScenarioDataPanelEmptyState:_n,ScenarioDataPanelFullPage:Zn,ScenarioDataPanelHeader:An,ScenarioDataPanelInspectButton:Fn,ScenarioDataPanelMainMock:Hn,ScenarioDataPanelMainMockEditable:Ln,ScenarioDataPanelMainMockHeader:In,ScenarioDataPanelMainMockReadOnly:On,ScenarioDataPanelMainTable:Mn,ScenarioDataPanelOpenInNewButton:Bn,ScenarioDataPanelMockDataBadge:kn,ScenarioDataPanelMockDataStrip:Dn,ScenarioDataPanelSidebar:En,SaveScopeChoiceRow:Rn,SaveScopeModal:Tn,SidebarMockEntryRow:wn,MockSharedSlugBadge:Cn,ScenarioDraftBar:Pn,JsonBodyActions:Nn,JsonTreeAddKeyInput:Sn,JsonTreeArrayNode:yn,JsonTreeEditor:jn,JsonTreeNode:gn,JsonTreeNodeLine:fn,JsonTreeObjectNode:vn,JsonTreePrimitiveEditor:bn,JsonTreePrimitiveNode:hn,ScenarioRenameForm:Le,ScenarioRowActions:Ie,MiniAgentChat:pn,EnvelopeIcon:Oe,SendTranscriptModal:$,SendTranscriptOverlay:Po,ContainerInspector:xn,InspectorScenarioSection:dn,InspectorRouteTable:cn,InspectorTrafficSection:ln,InspectorExplainerSection:on,InspectorExplainerResult:nn,InspectorPrimitivesShowcase:O,InspectorTrafficRowShowcase:I,InspectorTrafficDetail:rn,InspectorTrafficFilterBar:sn,InspectorTrafficTable:an,InspectorTrafficUrlChips:tn,InspectorUrlGlossary:en,InspectorPrimitives:O,InspectorTrafficRow:I,StepsSimulator:Yr,StepsSimulatorStepList:Qr,StepsSimulatorVariableControl:Kr,StepsSimulatorInstructionsPanel:Wr,SeedErrorBanner:Me,SeedLoadingOverlay:Be,StaleDbStripeOverlay:wo,ScenarioSeedErrorView:de,CoverageThresholdsPanel:ke,CoverageThresholdsEmptyState:De,CoverageThresholdsHeader:Ee,CoverageThresholdsDefaultNotice:Re,CoverageThresholdsPassSummary:Te,CoverageThresholdsFailureList:we,CoverageThresholdFailureGroup:Ce,InspectModeRibbon:Pe,IframeClickThroughErrorCard:Ne,InspectResultCard:Se,InspectResultCardBackdrop:ye,InspectResultCardBody:je,InspectResultCardHeader:ge,InspectResultCardMatchButton:fe,InspectResultCardMatchList:ve};function Ro(t){const a={};for(const[s,r]of Object.entries(t))a[s]=N(r);return a}const Eo=new Set(["div","span","p","strong","em","code","pre","h1","h2","h3","h4","h5","h6","ul","ol","li","a","br","hr","img","section","header","footer","nav","article","button"]);function N(t){if(t==="__noop__")return()=>{};if(t==null||typeof t!="object")return t;if(Array.isArray(t))return t.map(N);if(t.__type==="noop")return()=>{};if(t.__type==="undefined")return;if(t.__type==="Ref")return{current:null};if(t.__type==="Date"&&typeof t.value=="string")return new Date(t.value);if(t.__type==="Set"&&Array.isArray(t.values))return new Set(t.values.map(N));if(t.__type==="ReactNode"){if(typeof t.text=="string")return t.text;if(typeof t.element=="string"){if(!Eo.has(t.element))return null;const s=t.children!=null?N(t.children):void 0;return d.createElement(t.element,t.props||null,s)}}if(t.__type==="Map"&&typeof t.entries=="object"&&t.entries!==null){const s=new Map;for(const[r,n]of Object.entries(t.entries))s.set(r,N(n));return s}const a={};for(const[s,r]of Object.entries(t))a[s]=N(r);return a}function Do(t){if(!t||typeof t!="object")return!1;const a=t,s=a.http?Object.keys(a.http).length:0,r=a.db?Object.keys(a.db).length:0;return s>0||r>0}const ko=new Set(["EditorShell"]);function Bo(t){return t?To[t]??null:null}function Mo(t){const[a,s]=d.useState({Component:null,props:{},name:"",loading:!0,error:null,needsRouter:!1,displayHints:null,seed:null,scenarioType:null,hasMocks:!1});return d.useEffect(()=>{let r=!1;return s(n=>({...n,loading:!0,error:null})),fetch(`/api/scenarios/${encodeURIComponent(t)}`).then(n=>n.json()).then(n=>{if(r)return;if(n.error){s({Component:null,props:{},name:"",loading:!1,error:n.error,needsRouter:!1,displayHints:null,seed:null,scenarioType:null,hasMocks:!1});return}const i=Bo(n.componentName),l=n.scenarioType==="application"||n.scenarioType==="component"?n.scenarioType:null,c=n.seed??null,o=Do(n.mocks);if(!i&&n.componentName){s({Component:null,props:{},name:n.name??"",loading:!1,error:`Component "${n.componentName}" not found in registry`,needsRouter:!1,displayHints:null,seed:c,scenarioType:l,hasMocks:o});return}s({Component:i,props:Ro(n.props??{}),name:n.name??"",loading:!1,error:null,needsRouter:ko.has(n.componentName??""),displayHints:n.displayHints??null,seed:c,scenarioType:l,hasMocks:o})}).catch(n=>{r||s({Component:null,props:{},name:"",loading:!1,error:n.message,needsRouter:!1,displayHints:null,seed:null,scenarioType:null,hasMocks:!1})}),()=>{r=!0}},[t]),a}function Oo({slug:t}){const{Component:a,props:s,name:r,loading:n,error:i,needsRouter:l,displayHints:c,seed:o,scenarioType:u,hasMocks:f}=Mo(t),[b,p]=d.useState(!1),[h,m]=d.useState(null);if(d.useEffect(()=>{if(n)return;let y=!1;return p(!1),m(null),u==="component"&&o==null&&!f?(p(!0),()=>{y=!0}):(fetch("/api/editor-activate-scenario",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({slug:t})}).then(async g=>{const x=await g.json().catch(()=>null);y||(x&&(x.seedError||x.success===!1)&&(o!=null?m(x.seedError||x.error||"scenario activation failed"):console.warn("[scenario] activation returned failure for no-seed scenario; ignoring",x)),p(!0))}).catch(g=>{y||(o!=null?m(g instanceof Error?g.message:String(g)):console.warn("[scenario] activation request failed for no-seed scenario; ignoring",g),p(!0))}),()=>{y=!0,fetch("/api/editor-deactivate-scenario",{method:"POST"}).catch(()=>{})})},[t,n,o,u,f]),n||!b)return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--bg-deep)] text-[var(--text-muted)]",children:"Loading scenario..."});if(h)return e.jsx(de,{error:h});if(i)return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--bg-deep)] text-[var(--accent-red)]",children:e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg",children:"Scenario Error"}),e.jsx("p",{className:"mt-2 text-sm",children:i})]})});if(!a)return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--bg-deep)] text-[var(--text-muted)]",children:e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg",children:r}),e.jsx("p",{className:"mt-2 text-sm",children:"No component specified for this scenario"})]})});const j=e.jsx(a,{...s});return l?j:e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--bg-deep)] p-4",children:e.jsx("div",{className:"w-full",style:c!=null&&c.maxWidth?{maxWidth:c.maxWidth}:void 0,children:j})})}export{Oo as ScenarioRenderer};