@codeyam-editor/codeyam-editor 0.1.0-staging.g83619a4 → 0.1.0-staging.gbaebe71

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/npm/cloud.js CHANGED
@@ -965,11 +965,25 @@ function buildGcloudArgs(verb, cfg = {}, extras = {}) {
965
965
  // real use. Unit tests pin their exports so a refactor cannot drop them.
966
966
  // =============================================================================
967
967
 
968
+ // Per-call wall-clock budget for a single gcloud / SSH invocation. A hung
969
+ // `gcloud describe` (metadata / IAP hiccup) used to block the whole
970
+ // `cloud:reconcile-ingress` sweep forever — the only timeout in the reconcile
971
+ // path was the outer 10-minute exec budget in the dashboard, and that never
972
+ // cascaded to the orphaned descendants. Bounding every per-call spawn well under
973
+ // that outer budget means a single hang trips HERE first: the call returns a
974
+ // timed-out result (formatGcloudFailure renders it), the sweep skips that VM,
975
+ // and no descendant is left hanging to pile up. Shared by runGcloud and the two
976
+ // reconcile spawnSync sites (status probe, per-BES timeout converge) so all three
977
+ // reference one value. 2 min is generous for any single describe/update/SSH probe
978
+ // yet comfortably under the 600000 ms outer reconcile budget.
979
+ const GCLOUD_CALL_TIMEOUT_MS = 120000;
980
+
968
981
  function runGcloud(args, opts = {}) {
969
982
  return spawnSync("gcloud", args, {
970
983
  stdio: opts.stdio || "inherit",
971
984
  input: opts.input,
972
985
  encoding: opts.encoding || "utf8",
986
+ timeout: opts.timeout != null ? opts.timeout : GCLOUD_CALL_TIMEOUT_MS,
973
987
  });
974
988
  }
975
989
 
@@ -4040,9 +4054,15 @@ async function cmdReconcileIngress(args, projectDir = rootDir) {
4040
4054
  zone: cfg.zone,
4041
4055
  slug,
4042
4056
  });
4057
+ // Bound the per-VM status probe: a hung `bash vm-ingress.sh <N> status`
4058
+ // (its gcloud describes stalling on an IAP/metadata hiccup) must not stall the
4059
+ // whole sweep. On timeout res.stdout is empty, so parseIngressStatusVerdict
4060
+ // returns null → an `unknown` verdict → selectIngressReconcileTargets SKIPS
4061
+ // this VM and the sweep continues to the next one.
4043
4062
  const res = spawnSync(inv.command, inv.args, {
4044
4063
  env: { ...process.env, ...inv.env },
4045
4064
  encoding: "utf8",
4065
+ timeout: GCLOUD_CALL_TIMEOUT_MS,
4046
4066
  });
4047
4067
  return { vmNumber: n, slug, verdict: parseIngressStatusVerdict(res.stdout || "") };
4048
4068
  });
@@ -4097,7 +4117,13 @@ async function cmdReconcileIngress(args, projectDir = rootDir) {
4097
4117
  for (const surface of gi.SURFACES) {
4098
4118
  const bes = gi.backendServiceName(n, surface);
4099
4119
  const inv = backendServiceTimeoutInvocation({ bes, project: cfg.project });
4100
- const res = spawnSync(inv.command, inv.args, { encoding: "utf8" });
4120
+ // Bound the per-BES converge too: a hung `gcloud backend-services update`
4121
+ // returns a non-zero (timed-out) result, so it falls into the skip branch
4122
+ // below and the sweep moves on to the next BES rather than stalling.
4123
+ const res = spawnSync(inv.command, inv.args, {
4124
+ encoding: "utf8",
4125
+ timeout: GCLOUD_CALL_TIMEOUT_MS,
4126
+ });
4101
4127
  if (res.status === 0) {
4102
4128
  console.error(` ${bes}: timeout → 86400`);
4103
4129
  } else {
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const fc = require('./fleet-cleanup');
4
+ const { parseRosterMarkers } = require('./fleet-early-roster');
4
5
 
5
6
  // npm/fleet-add-failure.js — pure classifier for a FAILED fleet-dashboard `add`
6
7
  // provision. Before this, every failed add rendered an identical red "add error"
@@ -60,6 +61,16 @@ function lastNonEmptyLines(text, maxLines = 50) {
60
61
  return lines.join('\n');
61
62
  }
62
63
 
64
+ // True iff the provision transcript reached the early-roster marker (`CY_ROSTER
65
+ // <n>`) — i.e. the instance exists and the container gate passed, so the VM is
66
+ // rostered. Reuses parseRosterMarkers (npm/fleet-early-roster.js) so the
67
+ // `CY_ROSTER` grammar has a single owner rather than a second inlined regex. Any
68
+ // valid marker means "rostered"; the specific VM number is irrelevant here — a
69
+ // provision transcript only ever carries its own VM's marker. Never throws.
70
+ function transcriptRostered(logTail) {
71
+ return parseRosterMarkers(String(logTail || '')).length > 0;
72
+ }
73
+
63
74
  // Build a verdict, stamping `retryable` from the single-source-of-truth Set so it
64
75
  // can never drift from the category.
65
76
  function buildFailureVerdict(category, headline, recovery, extra) {
@@ -144,7 +155,25 @@ function classifyAddFailure({ logTail, exitCode } = {}) {
144
155
  'The provision was interrupted (killed or out of memory), so the VM state is unknown. Reconcile or destroy this VM before re-adding.');
145
156
  }
146
157
 
147
- // 7. unknown — fallback. Never invite an unproven retry.
158
+ // 7. converging — the add reached the early-roster marker (`CY_ROSTER`): the
159
+ // container gate passed, the instance is real, and the VM is rostered, yet it
160
+ // exited non-zero WITHOUT matching any specific hard-failure signature above.
161
+ // By construction of the provision script, every genuine hard failure (drift,
162
+ // instance-vanished, container-stuck, incomplete-workspace, cloud-up-failed,
163
+ // interrupted) is printed BEFORE `CY_ROSTER`, so a rostered transcript that
164
+ // fell through to here is a still-wiring box owned by the detached
165
+ // wire-add-tail / reconcile-ingress — NOT an add failure. Surface it as an
166
+ // honest in-flight state instead of the scary red `unknown`. Not retryable:
167
+ // the VM exists and its detached wiring owns finishing it, so a one-click
168
+ // retry could duplicate/orphan a live box. Tested LAST so a hard-failure
169
+ // signature (all printed pre-roster) always wins — `converging` can never
170
+ // shadow a proven failure.
171
+ if (transcriptRostered(log)) {
172
+ return buildFailureVerdict('converging', 'Add still converging',
173
+ 'The container is up and the VM is rostered; the LB ingress is still wiring in the background. This resolves on its own once the editor is reachable over the LB — no action needed unless it persists past the wiring deadline.');
174
+ }
175
+
176
+ // 8. unknown — fallback. Never invite an unproven retry.
148
177
  return buildFailureVerdict('unknown', 'Add failed',
149
178
  'The add failed for an unclassified reason — inspect the transcript below, then reconcile or destroy this VM before re-adding.');
150
179
  }
@@ -163,4 +192,16 @@ function canRetryAdd({ n, job } = {}) {
163
192
  return { ok: true, reason: null };
164
193
  }
165
194
 
166
- module.exports = { classifyAddFailure, extractDriftFiles, lastNonEmptyLines, canRetryAdd, ADD_FAILURE_RETRYABLE };
195
+ // Pure badge-hold predicate for deriveStatus (server.js): hold the calm in-flight
196
+ // `add-converging` card — instead of the red add-failed — ONLY when the add was
197
+ // classified `converging` AND its detached first-wiring is still in flight. Once
198
+ // the wire-add-tail fails/deadlines (`addTailFailed`) or is gone (`addTailInflight`
199
+ // false), or the category is anything else, return false so the caller falls
200
+ // through to the red add-failed status — the operator-chosen escalation. Kept pure
201
+ // (like canRetryAdd / canClearBadge) so the badge decision is unit-tested without a
202
+ // live dashboard.
203
+ function holdConvergingBadge({ category, addTailInflight, addTailFailed } = {}) {
204
+ return category === 'converging' && !!addTailInflight && !addTailFailed;
205
+ }
206
+
207
+ module.exports = { classifyAddFailure, extractDriftFiles, lastNonEmptyLines, canRetryAdd, transcriptRostered, holdConvergingBadge, ADD_FAILURE_RETRYABLE };
@@ -32,6 +32,40 @@ function classifyDestroyBlock({ authDegraded, fleetWide } = {}) {
32
32
  return { blocked: false, reason: null };
33
33
  }
34
34
 
35
+ // Classify a non-Force destroy's unpushed-commit INTENT decision from the WARM
36
+ // ahead-count the dashboard reads off /api/session-info, mirroring the pure
37
+ // decision shape of classifyDestroyBlock. The three outcomes:
38
+ // ahead number > 0 → REFUSE: unpushed work exists (Force-recoverable)
39
+ // ahead number === 0 → PROCEED: verified clean
40
+ // ahead null / undefined → REFUSE: could NOT verify (editor unreachable /
41
+ // field absent) — a DISTINCT refusal, never conflated
42
+ // with "VM down", and Force-recoverable
43
+ // Returns { refuse, forceable, outcome, msg }: `outcome` is the
44
+ // logDestroyDecision attribution token (null when proceeding); `msg` is the
45
+ // operator-facing refusal text (null when proceeding). Pure — the caller owns the
46
+ // warm probe, the cached fallback, the logging, and the return; this only maps
47
+ // ahead → decision so it is unit-testable in isolation (the way the cold-SSH
48
+ // version never was).
49
+ function classifyUnpushedDestroy({ n, ahead } = {}) {
50
+ if (typeof ahead === 'number' && ahead > 0) {
51
+ return {
52
+ refuse: true,
53
+ forceable: true,
54
+ outcome: 'REFUSED:unpushed',
55
+ msg: `VM-${n} has ${ahead} unpushed commit(s) — not destroying. Use Force to override.`,
56
+ };
57
+ }
58
+ if (ahead === 0) {
59
+ return { refuse: false, forceable: false, outcome: null, msg: null };
60
+ }
61
+ return {
62
+ refuse: true,
63
+ forceable: true,
64
+ outcome: 'REFUSED:unverifiable',
65
+ msg: `VM-${n} — could not verify unpushed commits (editor unreachable). Use Force to destroy anyway.`,
66
+ };
67
+ }
68
+
35
69
  // Build the single attributable destroy-decision log line. Mirrors the
36
70
  // performAutoReset "confirmed … not fleet-wide" template so every destroy —
37
71
  // proceed OR refused, across every trigger source — is diagnosable from one
@@ -49,7 +83,21 @@ function formatDestroyDecision(info = {}) {
49
83
  );
50
84
  }
51
85
 
86
+ // Build the single TERMINAL-OUTCOME journal line for a completed destroy JOB —
87
+ // the sibling of formatDestroyDecision, which records the up-front DECISION. The
88
+ // decision line alone was a blind spot: diagnosing the VM-8 silent refusal
89
+ // surfaced only `destroy-decision … → proceed:delete`, nothing about how the job
90
+ // itself ended, so a job that refused/errored after the decision was invisible.
91
+ // With this line a completed destroy's fate is one `grep destroy-outcome` away.
92
+ // `outcome` is the caller-computed terminal string: `done`, `refused:<kind>`, or
93
+ // `error code=<n>`. Pure format only — the caller owns the classification.
94
+ function formatDestroyOutcome(info = {}) {
95
+ return `destroy-outcome: VM-${info.n} ${info.outcome}`;
96
+ }
97
+
52
98
  module.exports = {
53
99
  classifyDestroyBlock,
100
+ classifyUnpushedDestroy,
54
101
  formatDestroyDecision,
102
+ formatDestroyOutcome,
55
103
  };
@@ -25,6 +25,14 @@ const MARKER_PUBLISH_SKIPPED = 'CY_BINARY_PUBLISH_SKIPPED'; // pacer will NOT pu
25
25
  const MARKER_PATH_PULL = 'CY_PROVISION_PATH pull'; // this VM pulled a prebuilt image (~2 min fast path)
26
26
  const MARKER_PATH_COMPILE = 'CY_PROVISION_PATH compile'; // this VM compiled from source (~10 min slow path)
27
27
 
28
+ // Markers scripts/cloud-refresh-binary.sh emits into the between-session
29
+ // refresh log (/tmp/dash-refresh-binary-vm-<n>.log, or the systemd journal when
30
+ // the timer runs it unattended). Same stable-contract rule as the four above.
31
+ const MARKER_REFRESHED = 'CY_BINARY_REFRESHED'; // pulled + swapped a newer published binary, container restarted
32
+ const MARKER_REFRESH_CURRENT = 'CY_BINARY_CURRENT'; // already on the newest published binary; nothing to do
33
+ const MARKER_REFRESH_DEFERRED = 'CY_BINARY_REFRESH_DEFERRED'; // newer binary exists but a session is live (or state unknown)
34
+ const MARKER_REFRESH_DEGRADED = 'CY_DEGRADED binary-refresh'; // the refresh could NOT complete — this VM may be running stale
35
+
28
36
  // Mirror scripts/gcp-bootstrap.sh's BRANCH_SLUG: '/' → '-', lowercased, capped
29
37
  // at 128 chars. The dashboard and the VM MUST agree on the slug or the probe
30
38
  // checks different tags than the bootstrap pulls. Empty / missing branch → the
@@ -171,11 +179,57 @@ function pushTokenDiagnostic({ hasPushToken } = {}) {
171
179
  };
172
180
  }
173
181
 
182
+ // What did the last between-session binary refresh do? Parsed from the refresh
183
+ // log for the VM card, so an operator can tell "up to date" from "could not
184
+ // update" without opening a log.
185
+ //
186
+ // Returns 'refreshed' | 'current' | 'deferred' | 'degraded' | null (no refresh
187
+ // has reported yet).
188
+ //
189
+ // The LAST marker wins, for the same reason provisionPath() takes the last one:
190
+ // a tick that defers and a later tick that refreshes must read as refreshed,
191
+ // not stay stuck on the older verdict. Ordering — not precedence between marker
192
+ // kinds — is what makes this correct across repeated timer runs.
193
+ //
194
+ // `degraded` is deliberately a distinct state from `deferred`. Deferring is the
195
+ // mechanism working as designed (a session is live, so we wait). Degraded means
196
+ // the VM wanted a newer binary and could NOT get one — the silent-staleness
197
+ // case this whole mechanism exists to make visible, and the only one that
198
+ // warrants an operator's attention.
199
+ function binaryRefreshState(logText) {
200
+ if (!logText || typeof logText !== 'string') return null;
201
+ const at = (marker) => logText.lastIndexOf(marker);
202
+ const candidates = [
203
+ ['refreshed', at(MARKER_REFRESHED)],
204
+ ['current', at(MARKER_REFRESH_CURRENT)],
205
+ ['deferred', at(MARKER_REFRESH_DEFERRED)],
206
+ ['degraded', at(MARKER_REFRESH_DEGRADED)],
207
+ ].filter(([, idx]) => idx >= 0);
208
+ if (!candidates.length) return null;
209
+ return candidates.reduce((best, cur) => (cur[1] > best[1] ? cur : best))[0];
210
+ }
211
+
212
+ // Operator-facing one-liner for a refresh state, for the VM card. null state →
213
+ // null (render nothing — a VM that has never run a refresh is not a problem).
214
+ function binaryRefreshLabel(state) {
215
+ if (state === 'refreshed') return 'editor binary refreshed to the newest published build';
216
+ if (state === 'current') return 'editor binary up to date';
217
+ if (state === 'deferred') return 'newer editor binary available — waiting for the session to end';
218
+ if (state === 'degraded') return 'could NOT refresh the editor binary — may be running stale';
219
+ return null;
220
+ }
221
+
174
222
  module.exports = {
175
223
  MARKER_PUBLISHED,
176
224
  MARKER_PUBLISH_SKIPPED,
177
225
  MARKER_PATH_PULL,
178
226
  MARKER_PATH_COMPILE,
227
+ MARKER_REFRESHED,
228
+ MARKER_REFRESH_CURRENT,
229
+ MARKER_REFRESH_DEFERRED,
230
+ MARKER_REFRESH_DEGRADED,
231
+ binaryRefreshState,
232
+ binaryRefreshLabel,
179
233
  branchSlug,
180
234
  usableImageTags,
181
235
  decideBatchPrewarm,
@@ -224,6 +224,23 @@ function selectIngressGrantOnlyTargets(statuses) {
224
224
  return statuses.filter((s) => s && s.verdict === 'wired');
225
225
  }
226
226
 
227
+ /** Compute the `process.kill` target that reaps a timed-out reconcile's ENTIRE
228
+ * process group. The dashboard spawns `cloud:reconcile-ingress` detached, so the
229
+ * child shell leads its own process group (pgid === child.pid) and a negative-pid
230
+ * signal reaps every descendant — `node cloud.js` → `bash vm-ingress.sh` →
231
+ * `gcloud` — instead of only the immediate `sh -c` child (what an exec/SIGTERM
232
+ * timeout does, orphaning the descendants to init where they pile up and wedge the
233
+ * dashboard). Returns `-pid` for a real detached child, or `null` when the pid is
234
+ * missing / already reaped or would be catastrophic to negate. The `> 1` guard is
235
+ * load-bearing: `process.kill(-1, …)` signals EVERY process the user owns and
236
+ * `process.kill(0, …)`/`-0` targets the caller's OWN group — a missing pid must
237
+ * never be turned into a fleet-wide or self-directed SIGKILL. Pure: pid in, target
238
+ * out, so the timeout-kill decision is unit-testable without spawning a process. */
239
+ function reconcileGroupKillTarget(childPid) {
240
+ if (!Number.isInteger(childPid) || childPid <= 1) return null;
241
+ return -childPid;
242
+ }
243
+
227
244
  /** Pick the genuine orphans from the VM numbers that currently HAVE LB ingress
228
245
  * resources (`ingressVmNumbers`, derived from the live backend-service AND NEG
229
246
  * names). A number is an orphan iff it has ingress but is NOT in the roster,
@@ -685,6 +702,7 @@ module.exports = {
685
702
  parseIngressTeardownVerdict,
686
703
  selectIngressReconcileTargets,
687
704
  selectIngressGrantOnlyTargets,
705
+ reconcileGroupKillTarget,
688
706
  selectOrphanIngressTargets,
689
707
  classifyOrphanDownResult,
690
708
  parseOrphanSweepSummary,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codeyam-editor/codeyam-editor",
3
- "version": "0.1.0-staging.g83619a4",
3
+ "version": "0.1.0-staging.gbaebe71",
4
4
  "description": "Language-agnostic managed execution sandbox for scenario-driven development",
5
5
  "bin": {
6
6
  "codeyam-editor": "./npm/cli.js"
@@ -9,10 +9,10 @@
9
9
  "playwright": "^1.58.2"
10
10
  },
11
11
  "optionalDependencies": {
12
- "@codeyam-editor/codeyam-editor-darwin-arm64": "0.1.0-staging.g83619a4",
13
- "@codeyam-editor/codeyam-editor-darwin-x64": "0.1.0-staging.g83619a4",
14
- "@codeyam-editor/codeyam-editor-linux-x64": "0.1.0-staging.g83619a4",
15
- "@codeyam-editor/codeyam-editor-win32-x64": "0.1.0-staging.g83619a4"
12
+ "@codeyam-editor/codeyam-editor-darwin-arm64": "0.1.0-staging.gbaebe71",
13
+ "@codeyam-editor/codeyam-editor-darwin-x64": "0.1.0-staging.gbaebe71",
14
+ "@codeyam-editor/codeyam-editor-linux-x64": "0.1.0-staging.gbaebe71",
15
+ "@codeyam-editor/codeyam-editor-win32-x64": "0.1.0-staging.gbaebe71"
16
16
  },
17
17
  "keywords": [
18
18
  "codeyam",
@@ -1,2 +1,2 @@
1
- import{j as e}from"./markdown-C9tbsVHX.js";import{b as a}from"./react-nrLBr15I.js";import{u as O}from"./useEvents-S3Qk1Y_d.js";import{b as E}from"./index-3Jd_sXhk.js";function P({connected:t}){return e.jsx("span",{className:`inline-block rounded-full px-2 py-0.5 text-xs font-medium text-[var(--text-primary)] ${t?"bg-[var(--accent-green)]":"bg-[var(--accent-red)]"}`,children:t?"connected":"reconnecting…"})}const re=Object.freeze(Object.defineProperty({__proto__:null,ConnectionBadge:P},Symbol.toStringTag,{value:"Module"}));function N(){const[t,r]=a.useState(null),[o,s]=a.useState(!0),{events:l}=O(),n=a.useCallback(async()=>{try{const c=await(await fetch("/api/inspector/status")).json();r(c)}catch{}finally{s(!1)}},[]);return a.useEffect(()=>{n()},[n]),a.useEffect(()=>{const i=l[l.length-1];i&&i.type==="scenario_switch"&&n()},[l,n]),{scenario:(t==null?void 0:t.scenario)??null,previewScenario:(t==null?void 0:t.previewScenario)??null,routes:(t==null?void 0:t.routes)??[],routeCount:(t==null?void 0:t.routeCount)??0,loading:o,refetch:n}}function v({title:t}){return e.jsx("h2",{style:{fontSize:14,fontWeight:600,color:"#f0f6fc",margin:"0 0 8px 0",borderBottom:"1px solid #30363d",paddingBottom:8},children:t})}function f({color:t,children:r}){return e.jsx("span",{style:{background:`${t}22`,color:t,border:`1px solid ${t}55`,borderRadius:4,padding:"2px 8px",fontSize:11,fontWeight:600,letterSpacing:"0.5px",whiteSpace:"nowrap"},children:r})}const $={GET:"#D7FF63",POST:"#238636",PUT:"#d29922",DELETE:"#da3633",PATCH:"#bc8cff"};function k({method:t}){const r=$[t.toUpperCase()]??"#8b949e";return e.jsx("span",{style:{color:r,fontWeight:600,fontSize:11,minWidth:48,display:"inline-block"},children:t.toUpperCase()})}function C({color:t,children:r}){return e.jsx("div",{style:{padding:"12px 16px",borderRadius:6,border:`1px solid ${t}44`,background:`${t}11`,color:t},children:r})}const u={padding:"8px 12px",textAlign:"center",color:"#8b949e",fontWeight:500,fontSize:11,textTransform:"uppercase",letterSpacing:"0.5px"},h={padding:"6px 12px"},S={background:"#161b22",border:"1px solid #30363d",borderRadius:6,color:"#c9d1d9",padding:"6px 12px",fontSize:13,fontFamily:"inherit"},R={...S,appearance:"none",paddingRight:24,backgroundImage:`url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%238b949e' d='M6 8L1 3h10z'/%3E%3C/svg%3E")`,backgroundRepeat:"no-repeat",backgroundPosition:"right 8px center"},oe=Object.freeze(Object.defineProperty({__proto__:null,Badge:f,MethodBadge:k,SectionHeader:v,StatusBox:C,inputStyle:S,selectStyle:R,tdStyle:h,thStyle:u},Symbol.toStringTag,{value:"Module"}));function z({routes:t}){return e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{borderBottom:"1px solid #30363d"},children:[e.jsx("th",{style:u,children:"Method"}),e.jsx("th",{style:{...u,textAlign:"left"},children:"Pattern"}),e.jsx("th",{style:u,children:"Status"})]})}),e.jsx("tbody",{children:t.map((r,o)=>e.jsxs("tr",{style:{borderBottom:"1px solid #21262d"},children:[e.jsx("td",{style:{...h,textAlign:"center"},children:e.jsx(k,{method:r.method})}),e.jsx("td",{style:h,children:r.pattern}),e.jsx("td",{style:{...h,textAlign:"center",color:"#8b949e"},children:r.status})]},o))})]})}const se=Object.freeze(Object.defineProperty({__proto__:null,InspectorRouteTable:z},Symbol.toStringTag,{value:"Module"}));function A(){const{scenario:t,previewScenario:r,routes:o,routeCount:s,loading:l}=N();return e.jsxs("section",{children:[e.jsx(v,{title:"Active Scenario"}),l?e.jsx(C,{color:"#8b949e",children:"Loading..."}):t?e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(f,{color:"#238636",children:"ACTIVE"}),e.jsx("span",{style:{color:"#f0f6fc",fontWeight:500},children:t.name}),e.jsxs("span",{style:{color:"#8b949e"},children:["(",t.slug,")"]})]}),e.jsxs("div",{style:{color:"#8b949e",fontSize:12},children:[s," mock route",s!==1?"s":""," loaded"]}),o.length>0&&e.jsx(z,{routes:o})]}):r?e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(f,{color:"#D7FF63",children:"PREVIEW"}),e.jsx("span",{style:{color:"#f0f6fc",fontWeight:500},children:r.name}),e.jsxs("span",{style:{color:"#8b949e"},children:["(",r.slug,")"]})]}),e.jsx("div",{style:{color:"#8b949e",fontSize:12},children:"Component preview — no HTTP mocks active"})]}):e.jsx(C,{color:"#d29922",children:"No scenario active — all requests pass through to upstream"})]})}const ne=Object.freeze(Object.defineProperty({__proto__:null,InspectorScenarioSection:A},Symbol.toStringTag,{value:"Module"}));function F({textUrlFilter:t,onTextUrlFilterChange:r,methodFilter:o,onMethodFilterChange:s,sourceFilter:l,onSourceFilterChange:n}){return e.jsxs("div",{style:{display:"flex",gap:8,marginBottom:12,alignItems:"center"},children:[e.jsx("input",{type:"text",placeholder:"Filter by URL...",value:t,onChange:i=>r(i.target.value),style:{...S,flex:1,minWidth:0}}),e.jsxs("select",{value:o,onChange:i=>s(i.target.value),style:R,children:[e.jsx("option",{value:"ALL",children:"All Methods"}),e.jsx("option",{value:"GET",children:"GET"}),e.jsx("option",{value:"POST",children:"POST"}),e.jsx("option",{value:"PUT",children:"PUT"}),e.jsx("option",{value:"DELETE",children:"DELETE"}),e.jsx("option",{value:"PATCH",children:"PATCH"})]}),e.jsxs("select",{value:l,onChange:i=>n(i.target.value),style:R,children:[e.jsx("option",{value:"ALL",children:"All Sources"}),e.jsx("option",{value:"MOCKED",children:"Mocked"}),e.jsx("option",{value:"PASSTHROUGH",children:"Passthrough"})]})]})}const ie=Object.freeze(Object.defineProperty({__proto__:null,InspectorTrafficFilterBar:F},Symbol.toStringTag,{value:"Module"})),G={color:"#8b949e",fontSize:11,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.5px",marginBottom:4},M={background:"#161b22",border:"1px solid #30363d",borderRadius:4,padding:"8px 12px",margin:0,fontSize:11,color:"#c9d1d9",fontFamily:"monospace",maxHeight:200,overflow:"auto",whiteSpace:"pre-wrap",wordBreak:"break-all"};function _({label:t,children:r}){return e.jsxs("div",{style:{marginBottom:12},children:[e.jsx("div",{style:G,children:t}),r]})}function B({event:t}){let r=[];try{const n=new URL(t.url,"http://localhost");r=Array.from(n.searchParams.entries())}catch{}const o=t.requestHeaders&&Object.keys(t.requestHeaders).length>0,s=t.requestBody!=null,l=t.responseBody!=null;return e.jsxs("div",{style:{background:"#0d1117",padding:"12px 16px",borderTop:"1px solid #30363d"},children:[r.length>0&&e.jsx(_,{label:"Query Parameters",children:e.jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"2px 12px",fontSize:12},children:r.map(([n,i],c)=>e.jsxs("div",{style:{display:"contents"},children:[e.jsx("span",{style:{color:"#D7FF63",fontFamily:"monospace"},children:n}),e.jsx("span",{style:{color:"#c9d1d9",fontFamily:"monospace"},children:i})]},c))})}),o&&e.jsx(_,{label:"Request Headers",children:e.jsx("pre",{style:M,children:Object.entries(t.requestHeaders).map(([n,i])=>`${n}: ${i}`).join(`
1
+ import{j as e}from"./markdown-C9tbsVHX.js";import{b as a}from"./react-nrLBr15I.js";import{u as O}from"./useEvents-S3Qk1Y_d.js";import{b as E}from"./index-Mui6rJUD.js";function P({connected:t}){return e.jsx("span",{className:`inline-block rounded-full px-2 py-0.5 text-xs font-medium text-[var(--text-primary)] ${t?"bg-[var(--accent-green)]":"bg-[var(--accent-red)]"}`,children:t?"connected":"reconnecting…"})}const re=Object.freeze(Object.defineProperty({__proto__:null,ConnectionBadge:P},Symbol.toStringTag,{value:"Module"}));function N(){const[t,r]=a.useState(null),[o,s]=a.useState(!0),{events:l}=O(),n=a.useCallback(async()=>{try{const c=await(await fetch("/api/inspector/status")).json();r(c)}catch{}finally{s(!1)}},[]);return a.useEffect(()=>{n()},[n]),a.useEffect(()=>{const i=l[l.length-1];i&&i.type==="scenario_switch"&&n()},[l,n]),{scenario:(t==null?void 0:t.scenario)??null,previewScenario:(t==null?void 0:t.previewScenario)??null,routes:(t==null?void 0:t.routes)??[],routeCount:(t==null?void 0:t.routeCount)??0,loading:o,refetch:n}}function v({title:t}){return e.jsx("h2",{style:{fontSize:14,fontWeight:600,color:"#f0f6fc",margin:"0 0 8px 0",borderBottom:"1px solid #30363d",paddingBottom:8},children:t})}function f({color:t,children:r}){return e.jsx("span",{style:{background:`${t}22`,color:t,border:`1px solid ${t}55`,borderRadius:4,padding:"2px 8px",fontSize:11,fontWeight:600,letterSpacing:"0.5px",whiteSpace:"nowrap"},children:r})}const $={GET:"#D7FF63",POST:"#238636",PUT:"#d29922",DELETE:"#da3633",PATCH:"#bc8cff"};function k({method:t}){const r=$[t.toUpperCase()]??"#8b949e";return e.jsx("span",{style:{color:r,fontWeight:600,fontSize:11,minWidth:48,display:"inline-block"},children:t.toUpperCase()})}function C({color:t,children:r}){return e.jsx("div",{style:{padding:"12px 16px",borderRadius:6,border:`1px solid ${t}44`,background:`${t}11`,color:t},children:r})}const u={padding:"8px 12px",textAlign:"center",color:"#8b949e",fontWeight:500,fontSize:11,textTransform:"uppercase",letterSpacing:"0.5px"},h={padding:"6px 12px"},S={background:"#161b22",border:"1px solid #30363d",borderRadius:6,color:"#c9d1d9",padding:"6px 12px",fontSize:13,fontFamily:"inherit"},R={...S,appearance:"none",paddingRight:24,backgroundImage:`url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%238b949e' d='M6 8L1 3h10z'/%3E%3C/svg%3E")`,backgroundRepeat:"no-repeat",backgroundPosition:"right 8px center"},oe=Object.freeze(Object.defineProperty({__proto__:null,Badge:f,MethodBadge:k,SectionHeader:v,StatusBox:C,inputStyle:S,selectStyle:R,tdStyle:h,thStyle:u},Symbol.toStringTag,{value:"Module"}));function z({routes:t}){return e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{borderBottom:"1px solid #30363d"},children:[e.jsx("th",{style:u,children:"Method"}),e.jsx("th",{style:{...u,textAlign:"left"},children:"Pattern"}),e.jsx("th",{style:u,children:"Status"})]})}),e.jsx("tbody",{children:t.map((r,o)=>e.jsxs("tr",{style:{borderBottom:"1px solid #21262d"},children:[e.jsx("td",{style:{...h,textAlign:"center"},children:e.jsx(k,{method:r.method})}),e.jsx("td",{style:h,children:r.pattern}),e.jsx("td",{style:{...h,textAlign:"center",color:"#8b949e"},children:r.status})]},o))})]})}const se=Object.freeze(Object.defineProperty({__proto__:null,InspectorRouteTable:z},Symbol.toStringTag,{value:"Module"}));function A(){const{scenario:t,previewScenario:r,routes:o,routeCount:s,loading:l}=N();return e.jsxs("section",{children:[e.jsx(v,{title:"Active Scenario"}),l?e.jsx(C,{color:"#8b949e",children:"Loading..."}):t?e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(f,{color:"#238636",children:"ACTIVE"}),e.jsx("span",{style:{color:"#f0f6fc",fontWeight:500},children:t.name}),e.jsxs("span",{style:{color:"#8b949e"},children:["(",t.slug,")"]})]}),e.jsxs("div",{style:{color:"#8b949e",fontSize:12},children:[s," mock route",s!==1?"s":""," loaded"]}),o.length>0&&e.jsx(z,{routes:o})]}):r?e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(f,{color:"#D7FF63",children:"PREVIEW"}),e.jsx("span",{style:{color:"#f0f6fc",fontWeight:500},children:r.name}),e.jsxs("span",{style:{color:"#8b949e"},children:["(",r.slug,")"]})]}),e.jsx("div",{style:{color:"#8b949e",fontSize:12},children:"Component preview — no HTTP mocks active"})]}):e.jsx(C,{color:"#d29922",children:"No scenario active — all requests pass through to upstream"})]})}const ne=Object.freeze(Object.defineProperty({__proto__:null,InspectorScenarioSection:A},Symbol.toStringTag,{value:"Module"}));function F({textUrlFilter:t,onTextUrlFilterChange:r,methodFilter:o,onMethodFilterChange:s,sourceFilter:l,onSourceFilterChange:n}){return e.jsxs("div",{style:{display:"flex",gap:8,marginBottom:12,alignItems:"center"},children:[e.jsx("input",{type:"text",placeholder:"Filter by URL...",value:t,onChange:i=>r(i.target.value),style:{...S,flex:1,minWidth:0}}),e.jsxs("select",{value:o,onChange:i=>s(i.target.value),style:R,children:[e.jsx("option",{value:"ALL",children:"All Methods"}),e.jsx("option",{value:"GET",children:"GET"}),e.jsx("option",{value:"POST",children:"POST"}),e.jsx("option",{value:"PUT",children:"PUT"}),e.jsx("option",{value:"DELETE",children:"DELETE"}),e.jsx("option",{value:"PATCH",children:"PATCH"})]}),e.jsxs("select",{value:l,onChange:i=>n(i.target.value),style:R,children:[e.jsx("option",{value:"ALL",children:"All Sources"}),e.jsx("option",{value:"MOCKED",children:"Mocked"}),e.jsx("option",{value:"PASSTHROUGH",children:"Passthrough"})]})]})}const ie=Object.freeze(Object.defineProperty({__proto__:null,InspectorTrafficFilterBar:F},Symbol.toStringTag,{value:"Module"})),G={color:"#8b949e",fontSize:11,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.5px",marginBottom:4},M={background:"#161b22",border:"1px solid #30363d",borderRadius:4,padding:"8px 12px",margin:0,fontSize:11,color:"#c9d1d9",fontFamily:"monospace",maxHeight:200,overflow:"auto",whiteSpace:"pre-wrap",wordBreak:"break-all"};function _({label:t,children:r}){return e.jsxs("div",{style:{marginBottom:12},children:[e.jsx("div",{style:G,children:t}),r]})}function B({event:t}){let r=[];try{const n=new URL(t.url,"http://localhost");r=Array.from(n.searchParams.entries())}catch{}const o=t.requestHeaders&&Object.keys(t.requestHeaders).length>0,s=t.requestBody!=null,l=t.responseBody!=null;return e.jsxs("div",{style:{background:"#0d1117",padding:"12px 16px",borderTop:"1px solid #30363d"},children:[r.length>0&&e.jsx(_,{label:"Query Parameters",children:e.jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"2px 12px",fontSize:12},children:r.map(([n,i],c)=>e.jsxs("div",{style:{display:"contents"},children:[e.jsx("span",{style:{color:"#D7FF63",fontFamily:"monospace"},children:n}),e.jsx("span",{style:{color:"#c9d1d9",fontFamily:"monospace"},children:i})]},c))})}),o&&e.jsx(_,{label:"Request Headers",children:e.jsx("pre",{style:M,children:Object.entries(t.requestHeaders).map(([n,i])=>`${n}: ${i}`).join(`
2
2
  `)})}),s&&e.jsx(_,{label:"Request Body",children:e.jsx("pre",{style:M,children:typeof t.requestBody=="string"?t.requestBody:JSON.stringify(t.requestBody,null,2)})}),l&&e.jsx(_,{label:"Response Body",children:e.jsx("pre",{style:M,children:typeof t.responseBody=="string"?t.responseBody:JSON.stringify(t.responseBody,null,2)})}),r.length===0&&!o&&!s&&!l&&e.jsx("div",{style:{color:"#8b949e",fontSize:12},children:"No additional details available for this request"})]})}const le=Object.freeze(Object.defineProperty({__proto__:null,DetailSection:_,InspectorTrafficDetail:B},Symbol.toStringTag,{value:"Module"}));function L({event:t}){const[r,o]=a.useState(!1),s=new Date(t.timestampMs).toLocaleTimeString(),l=t.mocked;return e.jsxs(e.Fragment,{children:[e.jsxs("tr",{onClick:()=>o(!r),style:{borderBottom:"1px solid #21262d",background:l?"transparent":"rgba(210, 153, 34, 0.05)",cursor:"pointer"},children:[e.jsxs("td",{style:{...h,color:"#8b949e",textAlign:"center"},children:[e.jsx("span",{style:{display:"inline-block",width:12,marginRight:4,fontSize:10,color:"#8b949e",transition:"transform 0.15s",transform:r?"rotate(90deg)":"rotate(0deg)"},children:"▶"}),s]}),e.jsx("td",{style:{...h,textAlign:"center"},children:e.jsx(k,{method:t.method})}),e.jsx("td",{style:{...h,maxWidth:400,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.url}),e.jsx("td",{style:{...h,textAlign:"center",color:"#8b949e"},children:t.status??"---"}),e.jsxs("td",{style:{...h,textAlign:"center",color:"#8b949e"},children:[t.durationMs,"ms"]}),e.jsx("td",{style:{...h,textAlign:"center"},children:l?t.mockSource==="default"?e.jsx(f,{color:"#1f6feb",children:"MOCKED (default)"}):e.jsx(f,{color:"#238636",children:"MOCKED (scenario)"}):e.jsx(f,{color:"#d29922",children:"PASSTHROUGH"})})]}),r&&e.jsx("tr",{children:e.jsx("td",{colSpan:6,style:{padding:0},children:e.jsx(B,{event:t})})})]})}const ae=Object.freeze(Object.defineProperty({__proto__:null,InspectorTrafficRow:L},Symbol.toStringTag,{value:"Module"}));function D({events:t}){return e.jsx("div",{style:{maxHeight:300,overflowY:"auto",border:"1px solid #30363d",borderRadius:6},children:e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{borderBottom:"1px solid #30363d",position:"sticky",top:0,background:"#0d1117"},children:[e.jsx("th",{style:u,children:"Time"}),e.jsx("th",{style:u,children:"Method"}),e.jsx("th",{style:{...u,textAlign:"left"},children:"URL"}),e.jsx("th",{style:u,children:"Status"}),e.jsx("th",{style:u,children:"Duration"}),e.jsx("th",{style:u,children:"Source"})]})}),e.jsx("tbody",{children:t.map(r=>e.jsx(L,{event:r},r.id))})]})})}const ce=Object.freeze(Object.defineProperty({__proto__:null,InspectorTrafficTable:D},Symbol.toStringTag,{value:"Module"}));function K(t){if(t===void 0)return"checked";if(t==="checked")return"excluded"}function I({chips:t,chipStates:r,onChipStatesChange:o}){if(t.length===0)return null;const s=n=>{const i=new Map(r),c=K(i.get(n));c===void 0?i.delete(n):i.set(n,c),o(i)},l=()=>{o(new Map)};return e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:6,marginBottom:12},children:[r.size>0&&e.jsx("button",{onClick:l,style:{background:"#da363322",color:"#da3633",border:"1px solid #da363355",borderRadius:4,padding:"2px 8px",fontSize:11,fontWeight:600,cursor:"pointer",fontFamily:"inherit"},children:"Clear all"}),t.map(({path:n,count:i})=>{const c=r.get(n),d=c==="checked",g=c==="excluded";let m="#30363d",b="#8b949e",T="#30363d",y="";return d?(m="#D7FF6322",b="#D7FF63",T="#D7FF6355",y="✓ "):g&&(m="#da363322",b="#da3633",T="#da363355",y="✗ "),e.jsxs("button",{onClick:()=>s(n),style:{background:m,color:b,border:`1px solid ${T}`,borderRadius:4,padding:"2px 8px",fontSize:11,fontFamily:"monospace",cursor:"pointer",whiteSpace:"nowrap"},children:[y,n,e.jsxs("span",{style:{marginLeft:4,opacity:.6,fontFamily:"inherit"},children:["(",i,")"]})]},n)})]})}const de=Object.freeze(Object.defineProperty({__proto__:null,InspectorTrafficUrlChips:I},Symbol.toStringTag,{value:"Module"}));function H(){const{events:t}=O(),[r,o]=a.useState(""),[s,l]=a.useState(()=>new Map),[n,i]=a.useState("ALL"),[c,d]=a.useState("ALL"),g=t.filter(p=>p.type==="http_request"),m=a.useMemo(()=>{const p=new Map;for(const x of g){const j=E(x.url);p.set(j,(p.get(j)||0)+1)}return Array.from(p.entries()).sort((x,j)=>j[1]-x[1]).slice(0,10).map(([x,j])=>({path:x,count:j}))},[g]),b=a.useMemo(()=>Array.from(s.values()).some(p=>p==="checked"),[s]),y=g.filter(p=>{if(r&&!p.url.toLowerCase().includes(r.toLowerCase()))return!1;const x=E(p.url);return!(s.get(x)==="excluded"||b&&s.get(x)!=="checked"||n!=="ALL"&&p.method.toUpperCase()!==n||c==="MOCKED"&&!p.mocked||c==="PASSTHROUGH"&&p.mocked)}).slice(-50).reverse();return e.jsxs("section",{children:[e.jsx(v,{title:"Live Traffic"}),e.jsx(F,{textUrlFilter:r,onTextUrlFilterChange:o,methodFilter:n,onMethodFilterChange:i,sourceFilter:c,onSourceFilterChange:p=>d(p)}),e.jsx(I,{chips:m,chipStates:s,onChipStatesChange:l}),y.length===0?e.jsx(C,{color:"#8b949e",children:g.length>0?"No matching traffic — try adjusting the filters":"No HTTP traffic yet — requests will appear here in real-time"}):e.jsx(D,{events:y})]})}const pe=Object.freeze(Object.defineProperty({__proto__:null,InspectorTrafficSection:H},Symbol.toStringTag,{value:"Module"}));function J(){const[t,r]=a.useState(null),[o,s]=a.useState(!1);return{explain:a.useCallback(async(n,i)=>{s(!0);try{const d=await(await fetch("/api/inspector/explain",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({method:n,url:i})})).json();r(d)}catch{}finally{s(!1)}},[]),result:t,loading:o}}function U({result:t}){return e.jsxs("div",{style:{border:"1px solid #30363d",borderRadius:6,padding:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:12},children:[e.jsxs("span",{style:{color:"#f0f6fc",fontWeight:500},children:[t.method," ",t.url]}),t.wouldMatch?e.jsx(f,{color:"#238636",children:"WOULD MATCH"}):e.jsx(f,{color:"#da3633",children:"NO MATCH"})]}),t.attempts.length===0?e.jsx("div",{style:{color:"#8b949e"},children:"No routes loaded to match against"}):e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:6},children:t.attempts.map((r,o)=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,padding:"4px 8px",borderRadius:4,background:r.failure?"transparent":"rgba(35, 134, 54, 0.1)"},children:[e.jsx("span",{style:{color:r.failure?"#da3633":"#238636",fontWeight:600,width:16},children:r.failure?"x":"v"}),e.jsx(k,{method:r.method}),e.jsx("span",{children:r.pattern}),r.failure&&e.jsx("span",{style:{color:"#8b949e",fontSize:11},children:r.failure.reason==="methodMismatch"?`method: expected ${r.failure.expected}, got ${r.failure.actual}`:`path "${r.failure.path}" does not match "${r.failure.pattern}"`})]},o))})]})}const ue=Object.freeze(Object.defineProperty({__proto__:null,InspectorExplainerResult:U},Symbol.toStringTag,{value:"Module"}));function W(){const{explain:t,result:r,loading:o}=J(),[s,l]=a.useState("GET"),[n,i]=a.useState(""),c=d=>{d.preventDefault(),n.trim()&&t(s,n.trim())};return e.jsxs("section",{children:[e.jsx(v,{title:"Match Explainer"}),e.jsxs("form",{onSubmit:c,style:{display:"flex",gap:8,marginBottom:12},children:[e.jsx("select",{value:s,onChange:d=>l(d.target.value),style:{...S,width:100},children:["GET","POST","PUT","DELETE","PATCH"].map(d=>e.jsx("option",{value:d,children:d},d))}),e.jsx("input",{type:"text",value:n,onChange:d=>i(d.target.value),placeholder:"/api/users",style:{...S,flex:1}}),e.jsx("button",{type:"submit",disabled:o||!n.trim(),style:{background:"#238636",color:"#fff",border:"none",borderRadius:6,padding:"6px 16px",cursor:"pointer",fontSize:12,fontWeight:500,opacity:o||!n.trim()?.5:1},children:o?"Checking...":"Explain"})]}),r&&e.jsx(U,{result:r})]})}const he=Object.freeze(Object.defineProperty({__proto__:null,InspectorExplainerSection:W},Symbol.toStringTag,{value:"Module"})),w={"/api/health":"Health check — confirms the proxy and mock engine are running","/api/events":"SSE stream of real-time events (traffic, errors) powering this Inspector","/api/config":"Returns current CodeYam configuration for the project","/api/editor-dev-server":"Polls/controls the dev server status (start, stop, restart)","/api/inspector/status":"Returns active scenario and loaded mock routes","/api/inspector/explain":"Tests which mock route would match a given method + URL","/api/scenarios":"Lists all defined scenarios with metadata","/api/tests":"Returns the AI-maintained test registry joined with per-test-evidence, grouped by file","/api/test-results":"Returns latest test execution results","/api/screenshots/*":"Serves captured scenario screenshots","/api/session-info":"Returns current editor session metadata","/api/data-structure":"Returns the app's data structure definition","/api/dependency-graph":"Returns the project's component dependency graph","/api/app-route-entities":"Lists app routes and their associated entities","/api/glossary":"Returns the project's component glossary","/api/step":"Returns current editor workflow step","/api/editor-commands":"Lists available editor commands"};function V(t){if(w[t])return w[t];for(const[r,o]of Object.entries(w))if(r.endsWith("/*")){const s=r.slice(0,-1);if(t.startsWith(s))return o}}function Y(t){const r=new Set([...t,...Object.keys(w)]),o=[];for(const s of Array.from(r).sort()){if(s.endsWith("/*"))continue;const l=V(s);o.push({path:s,description:l??"Application endpoint"})}return o}function q(){const{events:t}=O(),r=a.useMemo(()=>{const o=[];for(const s of t)s.type==="http_request"&&o.push(E(s.url));return Y(o)},[t]);return r.length===0?null:e.jsxs("section",{children:[e.jsx(v,{title:"URL Glossary"}),e.jsx("div",{style:{border:"1px solid #30363d",borderRadius:6,overflow:"hidden"},children:e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{borderBottom:"1px solid #30363d",background:"#161b22"},children:[e.jsx("th",{style:{padding:"6px 12px",textAlign:"left",color:"#8b949e",fontWeight:500,fontSize:11,textTransform:"uppercase",letterSpacing:"0.5px",width:"30%"},children:"Path"}),e.jsx("th",{style:{padding:"6px 12px",textAlign:"left",color:"#8b949e",fontWeight:500,fontSize:11,textTransform:"uppercase",letterSpacing:"0.5px"},children:"Description"})]})}),e.jsx("tbody",{children:r.map(({path:o,description:s})=>e.jsxs("tr",{style:{borderBottom:"1px solid #21262d"},children:[e.jsx("td",{style:{padding:"4px 12px",fontFamily:"monospace",color:"#D7FF63",fontSize:11},children:o}),e.jsx("td",{style:{padding:"4px 12px",color:"#8b949e"},children:s})]},o))})]})})]})}const xe=Object.freeze(Object.defineProperty({__proto__:null,InspectorUrlGlossary:q},Symbol.toStringTag,{value:"Module"}));function Q(){const{connected:t}=O();return e.jsxs("div",{style:{background:"#0d1117",color:"#c9d1d9",minHeight:"100vh",fontFamily:"'SF Mono', 'Fira Code', 'Cascadia Code', Menlo, monospace",fontSize:13,padding:24,display:"flex",flexDirection:"column",gap:24},children:[e.jsxs("header",{style:{display:"flex",alignItems:"center",gap:12},children:[e.jsx("h1",{style:{fontSize:18,fontWeight:600,color:"#f0f6fc",margin:0},children:"Container Inspector"}),e.jsx("span",{style:{color:"#8b949e",fontSize:12},children:"Read-only view of proxy and mock engine state"}),e.jsx(P,{connected:t})]}),e.jsx(A,{}),e.jsx(H,{}),e.jsx(W,{}),e.jsx(q,{})]})}const fe=Object.freeze(Object.defineProperty({__proto__:null,ContainerInspector:Q},Symbol.toStringTag,{value:"Module"}));export{f as B,Q as C,_ as D,L as I,k as M,v as S,xe as _,C as a,q as b,I as c,D as d,F as e,B as f,U as g,W as h,H as i,z as j,A as k,P as l,de as m,ce as n,pe as o,ae as p,ie as q,le as r,ne as s,u as t,se as u,oe as v,he as w,ue as x,fe as y,re as z};