opendevbrowser 0.0.24 → 0.0.25

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.
Files changed (46) hide show
  1. package/README.md +1 -1
  2. package/dist/browser/fingerprint/canary.d.ts.map +1 -1
  3. package/dist/{chunk-5I6TZRVS.js → chunk-7U63PZ4W.js} +708 -323
  4. package/dist/chunk-7U63PZ4W.js.map +1 -0
  5. package/dist/{chunk-K2TEHJCV.js → chunk-Z6ENAZUN.js} +2848 -693
  6. package/dist/chunk-Z6ENAZUN.js.map +1 -0
  7. package/dist/cli/commands/inspiredesign.d.ts.map +1 -1
  8. package/dist/cli/daemon-client.d.ts +13 -0
  9. package/dist/cli/daemon-client.d.ts.map +1 -1
  10. package/dist/cli/daemon-commands.d.ts.map +1 -1
  11. package/dist/cli/daemon.d.ts +7 -2
  12. package/dist/cli/daemon.d.ts.map +1 -1
  13. package/dist/cli/help.d.ts.map +1 -1
  14. package/dist/cli/index.js +16 -15
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/cli/remote-manager.d.ts +8 -6
  17. package/dist/cli/remote-manager.d.ts.map +1 -1
  18. package/dist/index.js +44 -24
  19. package/dist/index.js.map +1 -1
  20. package/dist/inspiredesign/brief-expansion.d.ts +41 -0
  21. package/dist/inspiredesign/brief-expansion.d.ts.map +1 -0
  22. package/dist/inspiredesign/handoff.d.ts +3 -1
  23. package/dist/inspiredesign/handoff.d.ts.map +1 -1
  24. package/dist/opendevbrowser.js +44 -24
  25. package/dist/opendevbrowser.js.map +1 -1
  26. package/dist/providers/inspiredesign-capture-mode.d.ts +3 -0
  27. package/dist/providers/inspiredesign-capture-mode.d.ts.map +1 -0
  28. package/dist/providers/inspiredesign-capture.d.ts +8 -1
  29. package/dist/providers/inspiredesign-capture.d.ts.map +1 -1
  30. package/dist/providers/inspiredesign-contract.d.ts +30 -0
  31. package/dist/providers/inspiredesign-contract.d.ts.map +1 -1
  32. package/dist/providers/renderer.d.ts +2 -1
  33. package/dist/providers/renderer.d.ts.map +1 -1
  34. package/dist/providers/workflows.d.ts +2 -0
  35. package/dist/providers/workflows.d.ts.map +1 -1
  36. package/dist/{providers-6YVHKTOJ.js → providers-CYEJZVXB.js} +2 -2
  37. package/dist/tools/inspiredesign_run.d.ts.map +1 -1
  38. package/extension/manifest.json +1 -1
  39. package/package.json +1 -1
  40. package/skills/opendevbrowser-best-practices/SKILL.md +3 -2
  41. package/skills/opendevbrowser-design-agent/SKILL.md +1 -0
  42. package/skills/opendevbrowser-design-agent/assets/templates/inspiredesign-advanced-brief.v1.json +1370 -0
  43. package/skills/opendevbrowser-design-agent/scripts/validate-skill-assets.sh +2 -0
  44. package/dist/chunk-5I6TZRVS.js.map +0 -1
  45. package/dist/chunk-K2TEHJCV.js.map +0 -1
  46. /package/dist/{providers-6YVHKTOJ.js.map → providers-CYEJZVXB.js.map} +0 -0
@@ -8,6 +8,25 @@ import {
8
8
  applyRuntimePreviewBridge
9
9
  } from "./chunk-Y2KL55OG.js";
10
10
  import {
11
+ CANVAS_BROWSER_VALIDATION_MODES,
12
+ CANVAS_GENERATION_PLAN_REQUIRED_FIELDS,
13
+ CANVAS_GOVERNANCE_BLOCK_KEYS,
14
+ CANVAS_INTERACTION_STATES,
15
+ CANVAS_KEYBOARD_NAVIGATION_MODES,
16
+ CANVAS_MOTION_LEVELS,
17
+ CANVAS_NAVIGATION_MODELS,
18
+ CANVAS_OPTIONAL_INHERITED_GOVERNANCE_KEYS,
19
+ CANVAS_PLAN_THEMES,
20
+ CANVAS_PLAN_VIEWPORTS,
21
+ CANVAS_PUBLIC_WARNING_CLASSES,
22
+ CANVAS_REDUCED_MOTION_POLICIES,
23
+ CANVAS_REQUIRED_MUTATION_GOVERNANCE_KEYS,
24
+ CANVAS_REQUIRED_SAVE_GOVERNANCE_KEYS,
25
+ CANVAS_SCHEMA_VERSION,
26
+ CANVAS_SESSION_MODES,
27
+ CANVAS_THEME_STRATEGIES,
28
+ CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES,
29
+ CANVAS_VISUAL_DIRECTION_PROFILES,
11
30
  ChallengeOrchestrator,
12
31
  buildBlockerArtifacts,
13
32
  buildMacroResolveSuccessHandoff,
@@ -28,7 +47,7 @@ import {
28
47
  runResearchWorkflow,
29
48
  runShoppingWorkflow,
30
49
  toSnippet
31
- } from "./chunk-K2TEHJCV.js";
50
+ } from "./chunk-Z6ENAZUN.js";
32
51
  import {
33
52
  ProviderRuntimeError
34
53
  } from "./chunk-FUSXMW3G.js";
@@ -1147,7 +1166,7 @@ function shouldRetry(error) {
1147
1166
  return !/missing|invalid|unknown ref|no active target/i.test(message);
1148
1167
  }
1149
1168
  function sleep(ms) {
1150
- return new Promise((resolve8) => setTimeout(resolve8, ms));
1169
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
1151
1170
  }
1152
1171
 
1153
1172
  // src/annotate/agent-inbox-store.ts
@@ -1907,7 +1926,7 @@ var buildCommandFailureMessage = (file, args2, stderr, signal) => {
1907
1926
  }
1908
1927
  return signal ? `Command failed: ${command} (${signal})` : `Command failed: ${command}`;
1909
1928
  };
1910
- var spawnFileAsync = (file, args2 = [], options = {}) => new Promise((resolve8, reject) => {
1929
+ var spawnFileAsync = (file, args2 = [], options = {}) => new Promise((resolve9, reject) => {
1911
1930
  const encoding = options.encoding ?? "utf8";
1912
1931
  const maxBuffer = options.maxBuffer ?? MAX_PROCESS_OUTPUT_BYTES;
1913
1932
  const child = spawn(file, [...args2], { stdio: ["ignore", "pipe", "pipe"] });
@@ -1952,7 +1971,7 @@ var spawnFileAsync = (file, args2 = [], options = {}) => new Promise((resolve8,
1952
1971
  child.on("error", fail);
1953
1972
  child.on("close", (code, signal) => {
1954
1973
  if (code === 0) {
1955
- settle(() => resolve8({
1974
+ settle(() => resolve9({
1956
1975
  stdout: decodeProcessOutput(stdout, encoding),
1957
1976
  stderr: decodeProcessOutput(stderr, encoding)
1958
1977
  }));
@@ -2684,14 +2703,14 @@ var OpsClient = class _OpsClient {
2684
2703
  if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
2685
2704
  this.clearReconnectTimer();
2686
2705
  this.socket = new WebSocket(this.url);
2687
- await new Promise((resolve8, reject) => {
2706
+ await new Promise((resolve9, reject) => {
2688
2707
  if (!this.socket) {
2689
2708
  reject(new Error("Ops socket not created"));
2690
2709
  return;
2691
2710
  }
2692
2711
  const onOpen = () => {
2693
2712
  cleanup();
2694
- resolve8();
2713
+ resolve9();
2695
2714
  };
2696
2715
  const onError = (error) => {
2697
2716
  cleanup();
@@ -2718,13 +2737,13 @@ var OpsClient = class _OpsClient {
2718
2737
  version: OPS_PROTOCOL_VERSION,
2719
2738
  maxPayloadBytes: this.maxPayloadBytes
2720
2739
  };
2721
- const ack = await new Promise((resolve8, reject) => {
2740
+ const ack = await new Promise((resolve9, reject) => {
2722
2741
  const timeoutId = setTimeout(() => {
2723
2742
  reject(new Error("Ops handshake timeout"));
2724
2743
  }, this.handshakeTimeoutMs);
2725
2744
  const handler = (message) => {
2726
2745
  clearTimeout(timeoutId);
2727
- resolve8(message);
2746
+ resolve9(message);
2728
2747
  };
2729
2748
  this.waitForHelloAck(handler, reject);
2730
2749
  try {
@@ -2775,7 +2794,7 @@ var OpsClient = class _OpsClient {
2775
2794
  if (!socket || socket.readyState === WebSocket.CLOSED) {
2776
2795
  return;
2777
2796
  }
2778
- this.disconnectPromise = new Promise((resolve8) => {
2797
+ this.disconnectPromise = new Promise((resolve9) => {
2779
2798
  let settled = false;
2780
2799
  const finalize = () => {
2781
2800
  if (settled) return;
@@ -2784,7 +2803,7 @@ var OpsClient = class _OpsClient {
2784
2803
  socket.removeListener("close", onClose);
2785
2804
  socket.removeListener("error", onError);
2786
2805
  this.disconnectPromise = null;
2787
- resolve8();
2806
+ resolve9();
2788
2807
  };
2789
2808
  const onClose = () => {
2790
2809
  finalize();
@@ -2830,7 +2849,7 @@ var OpsClient = class _OpsClient {
2830
2849
  if (Buffer.byteLength(serialized) > this.maxPayloadBytes) {
2831
2850
  throw new Error("Ops request payload exceeded max size");
2832
2851
  }
2833
- return await new Promise((resolve8, reject) => {
2852
+ return await new Promise((resolve9, reject) => {
2834
2853
  const timeoutId = setTimeout(() => {
2835
2854
  this.pendingRequests.delete(requestId);
2836
2855
  reject(new OpsRequestTimeoutError({
@@ -2841,7 +2860,7 @@ var OpsClient = class _OpsClient {
2841
2860
  ...typeof leaseId === "string" ? { leaseId } : {}
2842
2861
  }));
2843
2862
  }, timeoutMs);
2844
- const resolvePending = (value) => resolve8(value);
2863
+ const resolvePending = (value) => resolve9(value);
2845
2864
  this.pendingRequests.set(requestId, { resolve: resolvePending, reject, timeoutId });
2846
2865
  try {
2847
2866
  this.sendRaw(serialized);
@@ -2988,12 +3007,12 @@ var OpsClient = class _OpsClient {
2988
3007
  }
2989
3008
  const id2 = randomUUID5();
2990
3009
  const ping = { type: "ops_ping", id: id2 };
2991
- return await new Promise((resolve8, reject) => {
3010
+ return await new Promise((resolve9, reject) => {
2992
3011
  const timeoutId = setTimeout(() => {
2993
3012
  this.pendingPings.delete(id2);
2994
3013
  reject(new Error("Ops ping timed out"));
2995
3014
  }, this.pingTimeoutMs);
2996
- this.pendingPings.set(id2, { resolve: resolve8, reject, timeoutId });
3015
+ this.pendingPings.set(id2, { resolve: resolve9, reject, timeoutId });
2997
3016
  try {
2998
3017
  this.send(ping);
2999
3018
  } catch (error) {
@@ -3184,7 +3203,7 @@ var shouldAttachExtensionStartUrl = (request) => request.source === "social" ||
3184
3203
  var SOCIAL_EXTENSION_MODE_ATTEMPTS = 3;
3185
3204
  var resolveSocialExtensionModeAttempts = (request, preferredMode) => preferredMode === "extension" && request.source === "social" ? SOCIAL_EXTENSION_MODE_ATTEMPTS : 1;
3186
3205
  var waitForSocialExtensionRetryGap = async () => {
3187
- await new Promise((resolve8) => setTimeout(resolve8, SOCIAL_EXTENSION_RETRY_DELAY_MS));
3206
+ await new Promise((resolve9) => setTimeout(resolve9, SOCIAL_EXTENSION_RETRY_DELAY_MS));
3188
3207
  };
3189
3208
  var resolveFallbackNavigationWaitUntil = (source, mode) => source === "shopping" && mode === "managed_headed" ? "domcontentloaded" : "load";
3190
3209
  var normalizeExtensionAttachUrl = (value) => {
@@ -3417,7 +3436,7 @@ var waitForFallbackCaptureDelay = async (delayMs, waitForTimeout) => {
3417
3436
  await waitForTimeout(delayMs);
3418
3437
  return;
3419
3438
  }
3420
- await new Promise((resolve8) => setTimeout(resolve8, delayMs));
3439
+ await new Promise((resolve9) => setTimeout(resolve9, delayMs));
3421
3440
  };
3422
3441
  var waitForFallbackPageToSettle = async (manager, sessionId, _source, timeoutMs) => {
3423
3442
  if (typeof manager.waitForLoad !== "function") return;
@@ -5937,13 +5956,14 @@ function pushCanarySample(state, policy, sample) {
5937
5956
  const samples = [...state.samples, sample].slice(-windowSize);
5938
5957
  const averageScore = average(samples.map((entry) => Math.max(0, Math.min(100, entry.score))));
5939
5958
  const minSamples = Math.max(1, policy.minSamples);
5959
+ const hadEligibleWindow = state.samples.length >= minSamples;
5940
5960
  let action = "none";
5941
5961
  let level = state.level;
5942
5962
  if (samples.length >= minSamples) {
5943
- if (averageScore >= policy.promoteThreshold) {
5963
+ if (averageScore >= policy.promoteThreshold && (!hadEligibleWindow || state.averageScore < policy.promoteThreshold)) {
5944
5964
  level += 1;
5945
5965
  action = "promote";
5946
- } else if (averageScore <= policy.rollbackThreshold) {
5966
+ } else if (averageScore <= policy.rollbackThreshold && (!hadEligibleWindow || state.averageScore > policy.rollbackThreshold)) {
5947
5967
  level = Math.max(0, level - 1);
5948
5968
  action = "rollback";
5949
5969
  }
@@ -6408,14 +6428,14 @@ var TargetManager = class {
6408
6428
  }
6409
6429
  };
6410
6430
  var readWithTimeout = async (reader, timeoutMs = TARGET_INFO_TIMEOUT_MS) => {
6411
- return await new Promise((resolve8) => {
6412
- const timeoutId = setTimeout(() => resolve8(void 0), timeoutMs);
6431
+ return await new Promise((resolve9) => {
6432
+ const timeoutId = setTimeout(() => resolve9(void 0), timeoutMs);
6413
6433
  reader().then((value) => {
6414
6434
  clearTimeout(timeoutId);
6415
- resolve8(value);
6435
+ resolve9(value);
6416
6436
  }).catch(() => {
6417
6437
  clearTimeout(timeoutId);
6418
- resolve8(void 0);
6438
+ resolve9(void 0);
6419
6439
  });
6420
6440
  });
6421
6441
  };
@@ -10328,13 +10348,13 @@ var BrowserManager = class {
10328
10348
  state.inflight += 1;
10329
10349
  return;
10330
10350
  }
10331
- await new Promise((resolve8, reject) => {
10351
+ await new Promise((resolve9, reject) => {
10332
10352
  const enqueuedAt = Date.now();
10333
10353
  const waiter = {
10334
10354
  targetId,
10335
10355
  enqueuedAt,
10336
10356
  timeoutMs,
10337
- resolve: resolve8,
10357
+ resolve: resolve9,
10338
10358
  reject,
10339
10359
  timer: null
10340
10360
  };
@@ -10379,8 +10399,8 @@ var BrowserManager = class {
10379
10399
  const previous = this.targetQueues.get(queueKey) ?? Promise.resolve();
10380
10400
  let releaseQueue = () => {
10381
10401
  };
10382
- const gate = new Promise((resolve8) => {
10383
- releaseQueue = resolve8;
10402
+ const gate = new Promise((resolve9) => {
10403
+ releaseQueue = resolve9;
10384
10404
  });
10385
10405
  const tail = previous.then(() => gate, () => gate);
10386
10406
  this.targetQueues.set(queueKey, tail);
@@ -10587,14 +10607,14 @@ var BrowserManager = class {
10587
10607
  };
10588
10608
  const pendingClick = {
10589
10609
  dialogOpened: false,
10590
- dialogHandled: new Promise((resolve8) => {
10591
- resolveDialogHandled = resolve8;
10610
+ dialogHandled: new Promise((resolve9) => {
10611
+ resolveDialogHandled = resolve9;
10592
10612
  }),
10593
10613
  resolveDialogHandled: () => {
10594
10614
  resolveDialogHandled();
10595
10615
  },
10596
- completed: new Promise((resolve8) => {
10597
- resolveCompleted = resolve8;
10616
+ completed: new Promise((resolve9) => {
10617
+ resolveCompleted = resolve9;
10598
10618
  }),
10599
10619
  resolveCompleted: () => {
10600
10620
  resolveCompleted();
@@ -11454,7 +11474,7 @@ function isExtensionRelayDisconnectError(detail) {
11454
11474
  function isExtensionRelaySingleClientError(detail) {
11455
11475
  return detail.toLowerCase().includes("only one cdp client supported");
11456
11476
  }
11457
- var delay2 = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
11477
+ var delay2 = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
11458
11478
  function truncateText(value, maxChars) {
11459
11479
  if (value.length <= maxChars) {
11460
11480
  return { text: value, truncated: false };
@@ -12490,7 +12510,7 @@ var OpsBrowserManager = class {
12490
12510
  }
12491
12511
  } catch {
12492
12512
  }
12493
- await new Promise((resolve8) => setTimeout(resolve8, 250));
12513
+ await new Promise((resolve9) => setTimeout(resolve9, 250));
12494
12514
  }
12495
12515
  return false;
12496
12516
  }
@@ -13017,9 +13037,9 @@ async function runDirectAnnotate(manager, assets, request) {
13017
13037
  await ensureAnnotationReady(page);
13018
13038
  let readySeen = false;
13019
13039
  const completionHandlers = getCompletionMap(page);
13020
- const responsePromise = new Promise((resolve8) => {
13040
+ const responsePromise = new Promise((resolve9) => {
13021
13041
  completionHandlers.set(requestId, (message) => {
13022
- resolve8(mapCompletionToResponse(message, requestId));
13042
+ resolve9(mapCompletionToResponse(message, requestId));
13023
13043
  });
13024
13044
  });
13025
13045
  const startResponse = await dispatchMessage(page, {
@@ -13037,10 +13057,10 @@ async function runDirectAnnotate(manager, assets, request) {
13037
13057
  completionHandlers.delete(requestId);
13038
13058
  throw new Error("Annotation start acknowledgement missing active bridge.");
13039
13059
  }
13040
- const timeoutPromise = new Promise((resolve8) => {
13060
+ const timeoutPromise = new Promise((resolve9) => {
13041
13061
  const timeoutId = setTimeout(() => {
13042
13062
  clearTimeout(timeoutId);
13043
- resolve8({
13063
+ resolve9({
13044
13064
  version: 1,
13045
13065
  requestId,
13046
13066
  status: "error",
@@ -13048,10 +13068,10 @@ async function runDirectAnnotate(manager, assets, request) {
13048
13068
  });
13049
13069
  }, timeoutMs);
13050
13070
  });
13051
- const abortPromise = new Promise((resolve8) => {
13071
+ const abortPromise = new Promise((resolve9) => {
13052
13072
  if (!request.signal) return;
13053
13073
  if (request.signal.aborted) {
13054
- resolve8({
13074
+ resolve9({
13055
13075
  version: 1,
13056
13076
  requestId,
13057
13077
  status: "cancelled",
@@ -13060,7 +13080,7 @@ async function runDirectAnnotate(manager, assets, request) {
13060
13080
  return;
13061
13081
  }
13062
13082
  const onAbort = () => {
13063
- resolve8({
13083
+ resolve9({
13064
13084
  version: 1,
13065
13085
  requestId,
13066
13086
  status: "cancelled",
@@ -13483,7 +13503,7 @@ var AnnotationManager = class {
13483
13503
  socket.close(1e3, "Annotation complete");
13484
13504
  }
13485
13505
  };
13486
- const responsePromise = new Promise((resolve8, reject) => {
13506
+ const responsePromise = new Promise((resolve9, reject) => {
13487
13507
  socket.on("message", (data) => {
13488
13508
  const message = parseJson2(data);
13489
13509
  if (!message || typeof message !== "object") return;
@@ -13492,7 +13512,7 @@ var AnnotationManager = class {
13492
13512
  const response = record;
13493
13513
  if (response.payload?.requestId === requestId) {
13494
13514
  terminalResponse = response.payload;
13495
- resolve8(response.payload);
13515
+ resolve9(response.payload);
13496
13516
  }
13497
13517
  } else if (record.type === "annotationEvent") {
13498
13518
  const event = record;
@@ -13507,11 +13527,11 @@ var AnnotationManager = class {
13507
13527
  socket.on("error", (error) => reject(error));
13508
13528
  socket.on("close", () => {
13509
13529
  if (terminalResponse) {
13510
- resolve8(terminalResponse);
13530
+ resolve9(terminalResponse);
13511
13531
  return;
13512
13532
  }
13513
13533
  if (commandName === "start" && readySeen) {
13514
- resolve8({
13534
+ resolve9({
13515
13535
  version: 1,
13516
13536
  requestId,
13517
13537
  status: "cancelled",
@@ -13523,11 +13543,11 @@ var AnnotationManager = class {
13523
13543
  });
13524
13544
  });
13525
13545
  let timedOut = false;
13526
- const timeoutPromise = new Promise((resolve8) => {
13546
+ const timeoutPromise = new Promise((resolve9) => {
13527
13547
  const id2 = setTimeout(() => {
13528
13548
  clearTimeout(id2);
13529
13549
  timedOut = true;
13530
- resolve8({
13550
+ resolve9({
13531
13551
  version: 1,
13532
13552
  requestId,
13533
13553
  status: "error",
@@ -13536,11 +13556,11 @@ var AnnotationManager = class {
13536
13556
  }, timeoutMs);
13537
13557
  });
13538
13558
  let locallyAborted = false;
13539
- const abortPromise = new Promise((resolve8) => {
13559
+ const abortPromise = new Promise((resolve9) => {
13540
13560
  if (!options.signal) return;
13541
13561
  if (options.signal.aborted) {
13542
13562
  locallyAborted = true;
13543
- resolve8({
13563
+ resolve9({
13544
13564
  version: 1,
13545
13565
  requestId,
13546
13566
  status: "cancelled",
@@ -13550,7 +13570,7 @@ var AnnotationManager = class {
13550
13570
  }
13551
13571
  const onAbort = () => {
13552
13572
  locallyAborted = true;
13553
- resolve8({
13573
+ resolve9({
13554
13574
  version: 1,
13555
13575
  requestId,
13556
13576
  status: "cancelled",
@@ -13581,13 +13601,13 @@ var AnnotationManager = class {
13581
13601
  }
13582
13602
  };
13583
13603
  var waitForSocketOpen = (socket, timeoutMs) => {
13584
- return new Promise((resolve8, reject) => {
13604
+ return new Promise((resolve9, reject) => {
13585
13605
  const timeout = setTimeout(() => {
13586
13606
  reject(new Error("Annotation socket open timed out"));
13587
13607
  }, timeoutMs);
13588
13608
  socket.once("open", () => {
13589
13609
  clearTimeout(timeout);
13590
- resolve8();
13610
+ resolve9();
13591
13611
  });
13592
13612
  socket.once("error", (error) => {
13593
13613
  clearTimeout(timeout);
@@ -13676,7 +13696,7 @@ var CanvasClient = class {
13676
13696
  if (!this.socket || this.socket.readyState !== WebSocket3.OPEN) {
13677
13697
  this.clearReconnectTimer();
13678
13698
  this.socket = new WebSocket3(this.url);
13679
- await new Promise((resolve8, reject) => {
13699
+ await new Promise((resolve9, reject) => {
13680
13700
  if (!this.socket) {
13681
13701
  reject(new Error("Canvas socket not created"));
13682
13702
  return;
@@ -13691,7 +13711,7 @@ var CanvasClient = class {
13691
13711
  }, this.handshakeTimeoutMs);
13692
13712
  const onOpen = () => {
13693
13713
  cleanup();
13694
- resolve8();
13714
+ resolve9();
13695
13715
  };
13696
13716
  const onError = (error) => {
13697
13717
  cleanup();
@@ -13726,7 +13746,7 @@ var CanvasClient = class {
13726
13746
  version: CANVAS_PROTOCOL_VERSION,
13727
13747
  maxPayloadBytes: this.maxPayloadBytes
13728
13748
  };
13729
- const ack = await new Promise((resolve8, reject) => {
13749
+ const ack = await new Promise((resolve9, reject) => {
13730
13750
  const cleanup = () => {
13731
13751
  clearTimeout(timeoutId);
13732
13752
  this.socket?.removeListener("canvas_hello_ack", onAck);
@@ -13743,7 +13763,7 @@ var CanvasClient = class {
13743
13763
  }, this.handshakeTimeoutMs);
13744
13764
  const onAck = (message) => {
13745
13765
  cleanup();
13746
- resolve8(message);
13766
+ resolve9(message);
13747
13767
  };
13748
13768
  const onError = (message) => {
13749
13769
  cleanup();
@@ -13819,13 +13839,13 @@ var CanvasClient = class {
13819
13839
  if (Buffer.byteLength(serialized) > this.maxPayloadBytes) {
13820
13840
  throw new Error("Canvas request payload exceeded max size");
13821
13841
  }
13822
- return await new Promise((resolve8, reject) => {
13842
+ return await new Promise((resolve9, reject) => {
13823
13843
  const timeoutId = setTimeout(() => {
13824
13844
  this.pendingRequests.delete(requestId);
13825
13845
  reject(new Error("Canvas request timed out"));
13826
13846
  }, timeoutMs);
13827
13847
  timeoutId.unref?.();
13828
- this.pendingRequests.set(requestId, { resolve: (value) => resolve8(value), reject, timeoutId });
13848
+ this.pendingRequests.set(requestId, { resolve: (value) => resolve9(value), reject, timeoutId });
13829
13849
  try {
13830
13850
  this.sendRaw(serialized);
13831
13851
  } catch (error) {
@@ -13954,7 +13974,7 @@ var CanvasClient = class {
13954
13974
  }
13955
13975
  const id2 = randomUUID14();
13956
13976
  const ping = { type: "canvas_ping", id: id2 };
13957
- await new Promise((resolve8, reject) => {
13977
+ await new Promise((resolve9, reject) => {
13958
13978
  const timeoutId = setTimeout(() => {
13959
13979
  this.pendingPings.delete(id2);
13960
13980
  this.missedPongs += 1;
@@ -13964,7 +13984,7 @@ var CanvasClient = class {
13964
13984
  reject(new Error("Canvas ping timed out"));
13965
13985
  }, this.pingTimeoutMs);
13966
13986
  timeoutId.unref?.();
13967
- this.pendingPings.set(id2, { resolve: resolve8, reject, timeoutId });
13987
+ this.pendingPings.set(id2, { resolve: resolve9, reject, timeoutId });
13968
13988
  try {
13969
13989
  this.send(ping);
13970
13990
  } catch (error) {
@@ -15301,17 +15321,17 @@ var Doc = class _Doc extends ObservableV2 {
15301
15321
  this.isLoaded = false;
15302
15322
  this.isSynced = false;
15303
15323
  this.isDestroyed = false;
15304
- this.whenLoaded = create4((resolve8) => {
15324
+ this.whenLoaded = create4((resolve9) => {
15305
15325
  this.on("load", () => {
15306
15326
  this.isLoaded = true;
15307
- resolve8(this);
15327
+ resolve9(this);
15308
15328
  });
15309
15329
  });
15310
- const provideSyncedPromise = () => create4((resolve8) => {
15330
+ const provideSyncedPromise = () => create4((resolve9) => {
15311
15331
  const eventHandler = (isSynced) => {
15312
15332
  if (isSynced === void 0 || isSynced === true) {
15313
15333
  this.off("sync", eventHandler);
15314
- resolve8();
15334
+ resolve9();
15315
15335
  }
15316
15336
  };
15317
15337
  this.on("sync", eventHandler);
@@ -21497,133 +21517,6 @@ if (glo[importIdentifier] === true) {
21497
21517
  }
21498
21518
  glo[importIdentifier] = true;
21499
21519
 
21500
- // src/canvas/types.ts
21501
- var CANVAS_SCHEMA_VERSION = "1.0.0";
21502
- var CANVAS_SESSION_MODES = ["low-fi-wireframe", "high-fi-live-edit", "dual-track", "document-only"];
21503
- var CANVAS_GOVERNANCE_BLOCK_KEYS = [
21504
- "intent",
21505
- "generationPlan",
21506
- "designLanguage",
21507
- "contentModel",
21508
- "layoutSystem",
21509
- "typographySystem",
21510
- "colorSystem",
21511
- "surfaceSystem",
21512
- "iconSystem",
21513
- "motionSystem",
21514
- "responsiveSystem",
21515
- "accessibilityPolicy",
21516
- "libraryPolicy",
21517
- "runtimeBudgets"
21518
- ];
21519
- var CANVAS_REQUIRED_MUTATION_GOVERNANCE_KEYS = [
21520
- "intent",
21521
- "generationPlan",
21522
- "designLanguage",
21523
- "contentModel",
21524
- "layoutSystem",
21525
- "typographySystem",
21526
- "motionSystem",
21527
- "responsiveSystem",
21528
- "accessibilityPolicy"
21529
- ];
21530
- var CANVAS_REQUIRED_SAVE_GOVERNANCE_KEYS = [
21531
- "intent",
21532
- "generationPlan",
21533
- "designLanguage",
21534
- "contentModel",
21535
- "layoutSystem",
21536
- "typographySystem",
21537
- "colorSystem",
21538
- "surfaceSystem",
21539
- "iconSystem",
21540
- "motionSystem",
21541
- "responsiveSystem",
21542
- "accessibilityPolicy",
21543
- "libraryPolicy",
21544
- "runtimeBudgets"
21545
- ];
21546
- var CANVAS_OPTIONAL_INHERITED_GOVERNANCE_KEYS = [
21547
- "colorSystem",
21548
- "surfaceSystem",
21549
- "iconSystem",
21550
- "libraryPolicy",
21551
- "runtimeBudgets"
21552
- ];
21553
- var CANVAS_GENERATION_PLAN_REQUIRED_FIELDS = [
21554
- "targetOutcome",
21555
- "visualDirection",
21556
- "layoutStrategy",
21557
- "contentStrategy",
21558
- "componentStrategy",
21559
- "motionPosture",
21560
- "responsivePosture",
21561
- "accessibilityPosture",
21562
- "validationTargets"
21563
- ];
21564
- var CANVAS_VISUAL_DIRECTION_PROFILES = [
21565
- "clean-room",
21566
- "cinematic-minimal",
21567
- "product-story",
21568
- "commerce-system",
21569
- "control-room",
21570
- "ops-control",
21571
- "auth-focused",
21572
- "settings-system",
21573
- "documentation"
21574
- ];
21575
- var CANVAS_THEME_STRATEGIES = ["single-theme", "light-dark-parity", "multi-theme-system"];
21576
- var CANVAS_NAVIGATION_MODELS = ["global-header", "sidebar", "tabbed", "contextual", "immersive"];
21577
- var CANVAS_INTERACTION_STATES = [
21578
- "default",
21579
- "hover",
21580
- "focus",
21581
- "active",
21582
- "disabled",
21583
- "loading",
21584
- "empty",
21585
- "error",
21586
- "success",
21587
- "selected"
21588
- ];
21589
- var CANVAS_PLAN_VIEWPORTS = ["desktop", "tablet", "mobile"];
21590
- var CANVAS_PLAN_THEMES = ["light", "dark"];
21591
- var CANVAS_MOTION_LEVELS = ["none", "minimal", "subtle", "expressive"];
21592
- var CANVAS_REDUCED_MOTION_POLICIES = ["respect-user-preference", "static-alternative"];
21593
- var CANVAS_KEYBOARD_NAVIGATION_MODES = ["full", "core-flows"];
21594
- var CANVAS_BROWSER_VALIDATION_MODES = ["required", "optional"];
21595
- var CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES = [
21596
- "missing-generation-plan",
21597
- "invalid-generation-plan",
21598
- "missing-governance-block",
21599
- "missing-intent",
21600
- "missing-design-language",
21601
- "missing-content-model",
21602
- "missing-typography-system",
21603
- "missing-color-role",
21604
- "missing-surface-policy",
21605
- "missing-state-coverage",
21606
- "missing-reduced-motion-policy",
21607
- "missing-responsive-policy",
21608
- "overflow",
21609
- "token-missing",
21610
- "broken-asset-reference",
21611
- "contrast-failure",
21612
- "hierarchy-weak",
21613
- "asset-provenance-missing",
21614
- "font-policy-missing",
21615
- "font-load-failure",
21616
- "reduced-motion-violation",
21617
- "unresolved-component-binding",
21618
- "icon-policy-violation",
21619
- "library-policy-violation",
21620
- "responsive-mismatch",
21621
- "runtime-budget-exceeded",
21622
- "unsupported-target",
21623
- "export-warning"
21624
- ];
21625
- var CANVAS_PUBLIC_WARNING_CLASSES = CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES;
21626
-
21627
21520
  // src/canvas/token-references.ts
21628
21521
  var TOKEN_CSS_PREFIX = "--odb-token-";
21629
21522
  function isRecord5(value) {
@@ -32047,8 +31940,8 @@ var CanvasManager = class {
32047
31940
  }
32048
31941
  continue;
32049
31942
  }
32050
- const awaited = await new Promise((resolve8) => {
32051
- subscription.waiters.push(resolve8);
31943
+ const awaited = await new Promise((resolve9) => {
31944
+ subscription.waiters.push(resolve9);
32052
31945
  });
32053
31946
  if (awaited) {
32054
31947
  yield awaited;
@@ -32077,14 +31970,14 @@ var CanvasManager = class {
32077
31970
  reason: "subscription_replaced"
32078
31971
  };
32079
31972
  }
32080
- return await new Promise((resolve8) => {
31973
+ return await new Promise((resolve9) => {
32081
31974
  let timeoutHandle = null;
32082
31975
  const resolveWaiter = (event) => {
32083
31976
  if (timeoutHandle) {
32084
31977
  clearTimeout(timeoutHandle);
32085
31978
  }
32086
31979
  if (!event) {
32087
- resolve8({
31980
+ resolve9({
32088
31981
  eventType: "feedback.complete",
32089
31982
  cursor: subscription.cursor,
32090
31983
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -32092,7 +31985,7 @@ var CanvasManager = class {
32092
31985
  });
32093
31986
  return;
32094
31987
  }
32095
- resolve8(event);
31988
+ resolve9(event);
32096
31989
  };
32097
31990
  subscription.waiters.push(resolveWaiter);
32098
31991
  if (timeoutMs === void 0) {
@@ -32104,7 +31997,7 @@ var CanvasManager = class {
32104
31997
  subscription.waiters.splice(waiterIndex, 1);
32105
31998
  }
32106
31999
  subscription.lastHeartbeatAt = Date.now();
32107
- resolve8({
32000
+ resolve9({
32108
32001
  eventType: "feedback.heartbeat",
32109
32002
  cursor: subscription.cursor,
32110
32003
  ts: new Date(subscription.lastHeartbeatAt).toISOString(),
@@ -34723,10 +34616,10 @@ var RelayServer = class _RelayServer {
34723
34616
  }
34724
34617
  socket.destroy();
34725
34618
  });
34726
- await new Promise((resolve8, reject) => {
34619
+ await new Promise((resolve9, reject) => {
34727
34620
  this.server?.once("error", reject);
34728
34621
  this.server?.listen(port, "127.0.0.1", () => {
34729
- resolve8();
34622
+ resolve9();
34730
34623
  });
34731
34624
  });
34732
34625
  const address = this.server.address();
@@ -34842,15 +34735,15 @@ var RelayServer = class _RelayServer {
34842
34735
  error: { code: "invalid_request", message: "Duplicate annotation requestId." }
34843
34736
  };
34844
34737
  }
34845
- return await new Promise((resolve8) => {
34738
+ return await new Promise((resolve9) => {
34846
34739
  const pending = {
34847
- resolve: resolve8,
34740
+ resolve: resolve9,
34848
34741
  timeout: null,
34849
34742
  readySeen: false
34850
34743
  };
34851
34744
  const timeout = setTimeout(() => {
34852
34745
  this.annotationDirectPending.delete(command.requestId);
34853
- resolve8({
34746
+ resolve9({
34854
34747
  version: 1,
34855
34748
  requestId: command.requestId,
34856
34749
  status: "error",
@@ -35064,10 +34957,10 @@ var RelayServer = class _RelayServer {
35064
34957
  response.writeHead(404);
35065
34958
  response.end();
35066
34959
  });
35067
- await new Promise((resolve8, reject) => {
34960
+ await new Promise((resolve9, reject) => {
35068
34961
  this.discoveryServer?.once("error", reject);
35069
34962
  this.discoveryServer?.listen(this.configuredDiscoveryPort, "127.0.0.1", () => {
35070
- resolve8();
34963
+ resolve9();
35071
34964
  });
35072
34965
  });
35073
34966
  const address = this.discoveryServer.address();
@@ -36104,6 +35997,7 @@ import { createHash as createHash6, timingSafeEqual as timingSafeEqual2 } from "
36104
35997
  import { mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3, unlinkSync, existsSync as existsSync6 } from "fs";
36105
35998
  import { homedir as homedir7 } from "os";
36106
35999
  import { join as join16, resolve as resolve7 } from "path";
36000
+ import { fileURLToPath as fileURLToPath2 } from "url";
36107
36001
 
36108
36002
  // src/cli/daemon-commands.ts
36109
36003
  import { randomUUID as randomUUID22 } from "crypto";
@@ -36346,6 +36240,11 @@ function getBoolean(value) {
36346
36240
  var INSPIREDESIGN_CAPTURE_TIMEOUT_MS = 3e4;
36347
36241
  var INSPIREDESIGN_CAPTURE_MAX_CHARS = 12e3;
36348
36242
  var ACTIVE_SESSION_COOKIE_REUSE_UNAVAILABLE_MESSAGE = "Deep capture only honors configured provider cookie sources; active session cookies are not reused.";
36243
+ var DOM_CAPTURE_HELPER_UNAVAILABLE_MESSAGE = "DOM capture helper unavailable in this execution lane.";
36244
+ var SNAPSHOT_CAPTURE_EMPTY_MESSAGE = "Snapshot capture returned empty content.";
36245
+ var CLONE_CAPTURE_EMPTY_MESSAGE = "Clone capture returned empty component and CSS previews.";
36246
+ var DOM_CAPTURE_EMPTY_MESSAGE = "DOM capture returned empty HTML.";
36247
+ var SKIPPED_AFTER_TRANSPORT_TIMEOUT_SUFFIX = "transport timeout.";
36349
36248
  var createRemainingCaptureTimeout = (timeoutMs) => {
36350
36249
  const startedAtMs = Date.now();
36351
36250
  return () => Math.max(1, timeoutMs - Math.max(0, Date.now() - startedAtMs));
@@ -36354,17 +36253,62 @@ var clampInspiredesignCaptureTimeout = (timeoutMs) => {
36354
36253
  if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs)) return INSPIREDESIGN_CAPTURE_TIMEOUT_MS;
36355
36254
  return Math.max(1, Math.min(timeoutMs, INSPIREDESIGN_CAPTURE_TIMEOUT_MS));
36356
36255
  };
36357
- var sanitizeInspiredesignCaptureText = (value) => {
36358
- if (!value) return void 0;
36256
+ function sanitizeInspiredesignCaptureText(value) {
36257
+ if (value === void 0) return void 0;
36359
36258
  const redacted = redactSensitive(value);
36360
36259
  return typeof redacted === "string" ? redacted : value;
36260
+ }
36261
+ var buildCaptureAttempt = (status, detail) => {
36262
+ const sanitizedDetail = sanitizeInspiredesignCaptureText(detail);
36263
+ return sanitizedDetail ? { status, detail: sanitizedDetail } : { status };
36264
+ };
36265
+ var detailFromCaptureError = (error, fallback) => {
36266
+ return error instanceof Error ? error.message : fallback;
36267
+ };
36268
+ var isTransportTimeoutError = (error, detail) => {
36269
+ if (error instanceof Error) {
36270
+ const code = error.code;
36271
+ if (error.name === "TimeoutError" || code === "ETIMEDOUT" || code === "ERR_HTTP_REQUEST_TIMEOUT") {
36272
+ return true;
36273
+ }
36274
+ }
36275
+ return /\btimed out after \d+ms\b/i.test(detail) || /exceeded timeout budget\./i.test(detail);
36276
+ };
36277
+ var isIgnorableNetworkIdleWaitError = (error) => {
36278
+ if (!(error instanceof Error)) {
36279
+ return false;
36280
+ }
36281
+ return /timed out|timeout/i.test(error.message);
36282
+ };
36283
+ var buildSkippedAfterTransportTimeoutAttempt = (label) => {
36284
+ return buildCaptureAttempt("skipped", `Skipped after ${label} ${SKIPPED_AFTER_TRANSPORT_TIMEOUT_SUFFIX}`);
36285
+ };
36286
+ var hasUsableCaptureText = (value) => {
36287
+ return typeof value === "string" && value.trim().length > 0;
36361
36288
  };
36362
36289
  var resolveInspiredesignCaptureCookiePolicy = (options) => {
36363
36290
  if (options.cookiePolicyOverride) return options.cookiePolicyOverride;
36364
36291
  return options.useCookies === false ? "off" : "auto";
36365
36292
  };
36366
- var verifyRequiredCaptureCookies = async (manager, sessionId, url, importState) => {
36367
- const cookies = await manager.cookieList(sessionId, [url]);
36293
+ var withCaptureDeadline = async (promise, timeoutMs, label) => {
36294
+ let clearDeadline = () => {
36295
+ };
36296
+ const timeoutPromise = new Promise((_, reject) => {
36297
+ const handle = setTimeout(() => reject(new Error(`Deep capture ${label} exceeded timeout budget.`)), timeoutMs);
36298
+ clearDeadline = () => clearTimeout(handle);
36299
+ });
36300
+ try {
36301
+ return await Promise.race([promise, timeoutPromise]);
36302
+ } finally {
36303
+ clearDeadline();
36304
+ }
36305
+ };
36306
+ var verifyRequiredCaptureCookies = async (manager, sessionId, url, importState, timeoutMs) => {
36307
+ const cookies = await withCaptureDeadline(
36308
+ manager.cookieList(sessionId, [url], void 0, timeoutMs),
36309
+ timeoutMs,
36310
+ "cookie verification"
36311
+ );
36368
36312
  if (cookies.count > 0) return;
36369
36313
  if (!importState.sourceConfigured) {
36370
36314
  throw new Error(ACTIVE_SESSION_COOKIE_REUSE_UNAVAILABLE_MESSAGE);
@@ -36372,7 +36316,7 @@ var verifyRequiredCaptureCookies = async (manager, sessionId, url, importState)
36372
36316
  const sourceDetail = importState.sourceMessage ? ` ${importState.sourceMessage}` : "";
36373
36317
  throw new Error(`Deep capture requires observable cookies from the configured provider cookie source for the requested URL.${sourceDetail}`);
36374
36318
  };
36375
- var importConfiguredCaptureCookies = async (manager, sessionId, source) => {
36319
+ var importConfiguredCaptureCookies = async (manager, sessionId, source, timeoutMs) => {
36376
36320
  if (!source || typeof manager.cookieImport !== "function") {
36377
36321
  return {
36378
36322
  sourceConfigured: Boolean(source),
@@ -36387,80 +36331,203 @@ var importConfiguredCaptureCookies = async (manager, sessionId, source) => {
36387
36331
  sourceMessage: loaded.message
36388
36332
  };
36389
36333
  }
36390
- await manager.cookieImport(sessionId, loaded.cookies, false);
36334
+ await withCaptureDeadline(
36335
+ manager.cookieImport(sessionId, loaded.cookies, false, void 0, timeoutMs),
36336
+ timeoutMs,
36337
+ "cookie import"
36338
+ );
36391
36339
  return {
36392
36340
  sourceConfigured: true,
36393
36341
  sourceAvailable: loaded.available,
36394
36342
  sourceMessage: loaded.message
36395
36343
  };
36396
36344
  };
36397
- var withCaptureDeadline = async (promise, timeoutMs, label) => {
36398
- let handle;
36345
+ var captureSnapshotArtifact = async (manager, sessionId, remainingTimeoutMs) => {
36399
36346
  try {
36400
- return await Promise.race([
36401
- promise,
36402
- new Promise((_, reject) => {
36403
- handle = setTimeout(() => reject(new Error(`Deep capture ${label} exceeded timeout budget.`)), timeoutMs);
36404
- })
36405
- ]);
36406
- } finally {
36407
- if (handle) clearTimeout(handle);
36347
+ const snapshot = await withCaptureDeadline(
36348
+ manager.snapshot(
36349
+ sessionId,
36350
+ "actionables",
36351
+ INSPIREDESIGN_CAPTURE_MAX_CHARS,
36352
+ void 0,
36353
+ void 0,
36354
+ remainingTimeoutMs()
36355
+ ),
36356
+ remainingTimeoutMs(),
36357
+ "snapshot capture"
36358
+ );
36359
+ const content = sanitizeInspiredesignCaptureText(snapshot.content) ?? "";
36360
+ if (!hasUsableCaptureText(content)) {
36361
+ return {
36362
+ attempt: buildCaptureAttempt("failed", SNAPSHOT_CAPTURE_EMPTY_MESSAGE)
36363
+ };
36364
+ }
36365
+ return {
36366
+ attempt: buildCaptureAttempt("captured"),
36367
+ snapshot: {
36368
+ content,
36369
+ refCount: snapshot.refCount,
36370
+ warnings: snapshot.warnings ?? []
36371
+ }
36372
+ };
36373
+ } catch (error) {
36374
+ const detail = detailFromCaptureError(error, "Snapshot capture failed.");
36375
+ return {
36376
+ attempt: buildCaptureAttempt("failed", detail),
36377
+ ...isTransportTimeoutError(error, detail) ? { transportTimedOut: true } : {}
36378
+ };
36408
36379
  }
36409
36380
  };
36410
- var captureInspiredesignArtifacts = async (manager, sessionId, remainingTimeoutMs) => {
36411
- const snapshotTimeoutMs = remainingTimeoutMs();
36412
- const snapshot = await withCaptureDeadline(
36413
- manager.snapshot(sessionId, "actionables", INSPIREDESIGN_CAPTURE_MAX_CHARS),
36414
- snapshotTimeoutMs,
36415
- "snapshot capture"
36416
- );
36417
- const cloneTimeoutMs = remainingTimeoutMs();
36418
- const clone2 = await withCaptureDeadline(
36419
- manager.clonePage(sessionId),
36420
- cloneTimeoutMs,
36421
- "clone capture"
36422
- );
36423
- const dom = typeof manager.clonePageHtmlWithOptions === "function" ? await withCaptureDeadline(
36424
- manager.clonePageHtmlWithOptions(sessionId),
36425
- remainingTimeoutMs(),
36426
- "DOM capture"
36427
- ).catch(() => null) : null;
36428
- return {
36429
- snapshot: {
36430
- content: sanitizeInspiredesignCaptureText(snapshot.content) ?? snapshot.content,
36431
- refCount: snapshot.refCount,
36432
- warnings: snapshot.warnings ?? []
36433
- },
36434
- ...dom?.html ? {
36381
+ var captureCloneArtifact = async (manager, sessionId, remainingTimeoutMs) => {
36382
+ try {
36383
+ const clone2 = await withCaptureDeadline(
36384
+ manager.clonePage(sessionId, void 0, remainingTimeoutMs()),
36385
+ remainingTimeoutMs(),
36386
+ "clone capture"
36387
+ );
36388
+ const componentPreview = sanitizeInspiredesignCaptureText(clone2.component) ?? "";
36389
+ const cssPreview = sanitizeInspiredesignCaptureText(clone2.css) ?? "";
36390
+ if (!hasUsableCaptureText(componentPreview) && !hasUsableCaptureText(cssPreview)) {
36391
+ return {
36392
+ attempt: buildCaptureAttempt("failed", CLONE_CAPTURE_EMPTY_MESSAGE)
36393
+ };
36394
+ }
36395
+ return {
36396
+ attempt: buildCaptureAttempt("captured"),
36397
+ clone: {
36398
+ componentPreview,
36399
+ cssPreview,
36400
+ warnings: clone2.warnings ?? []
36401
+ }
36402
+ };
36403
+ } catch (error) {
36404
+ const detail = detailFromCaptureError(error, "Clone capture failed.");
36405
+ return {
36406
+ attempt: buildCaptureAttempt("failed", detail),
36407
+ ...isTransportTimeoutError(error, detail) ? { transportTimedOut: true } : {}
36408
+ };
36409
+ }
36410
+ };
36411
+ var captureDomArtifact = async (manager, sessionId, remainingTimeoutMs) => {
36412
+ if (typeof manager.clonePageHtmlWithOptions !== "function") {
36413
+ return {
36414
+ attempt: buildCaptureAttempt("skipped", DOM_CAPTURE_HELPER_UNAVAILABLE_MESSAGE)
36415
+ };
36416
+ }
36417
+ try {
36418
+ const dom = await withCaptureDeadline(
36419
+ manager.clonePageHtmlWithOptions(sessionId, void 0, void 0, remainingTimeoutMs()),
36420
+ remainingTimeoutMs(),
36421
+ "DOM capture"
36422
+ );
36423
+ const outerHTML = sanitizeInspiredesignCaptureText(dom.html) ?? "";
36424
+ if (!hasUsableCaptureText(outerHTML)) {
36425
+ return {
36426
+ attempt: buildCaptureAttempt("failed", DOM_CAPTURE_EMPTY_MESSAGE)
36427
+ };
36428
+ }
36429
+ return {
36430
+ attempt: buildCaptureAttempt("captured"),
36435
36431
  dom: {
36436
- outerHTML: sanitizeInspiredesignCaptureText(dom.html) ?? dom.html,
36432
+ outerHTML,
36437
36433
  truncated: false
36438
36434
  }
36439
- } : {},
36440
- clone: {
36441
- componentPreview: sanitizeInspiredesignCaptureText(clone2.component) ?? clone2.component,
36442
- cssPreview: sanitizeInspiredesignCaptureText(clone2.css) ?? clone2.css,
36443
- warnings: clone2.warnings ?? []
36444
- }
36435
+ };
36436
+ } catch (error) {
36437
+ const detail = detailFromCaptureError(error, "DOM capture failed.");
36438
+ return {
36439
+ attempt: buildCaptureAttempt("failed", detail),
36440
+ ...isTransportTimeoutError(error, detail) ? { transportTimedOut: true } : {}
36441
+ };
36442
+ }
36443
+ };
36444
+ var buildCaptureEvidence = (snapshot, clone2, dom) => {
36445
+ const attempts = {
36446
+ snapshot: snapshot.attempt,
36447
+ clone: clone2.attempt,
36448
+ dom: dom.attempt
36449
+ };
36450
+ return {
36451
+ ...snapshot.snapshot ? { snapshot: snapshot.snapshot } : {},
36452
+ ...dom.dom ? { dom: dom.dom } : {},
36453
+ ...clone2.clone ? { clone: clone2.clone } : {},
36454
+ attempts
36455
+ };
36456
+ };
36457
+ var buildTransportTimeoutCaptureEvidence = (snapshot, clone2, label) => {
36458
+ const attempts = {
36459
+ snapshot: snapshot.attempt,
36460
+ clone: clone2?.attempt ?? buildSkippedAfterTransportTimeoutAttempt(label),
36461
+ dom: buildSkippedAfterTransportTimeoutAttempt(label)
36462
+ };
36463
+ return {
36464
+ ...snapshot.snapshot ? { snapshot: snapshot.snapshot } : {},
36465
+ ...clone2?.clone ? { clone: clone2.clone } : {},
36466
+ attempts
36445
36467
  };
36446
36468
  };
36469
+ var captureInspiredesignArtifacts = async (manager, sessionId, remainingTimeoutMs) => {
36470
+ const snapshot = await captureSnapshotArtifact(manager, sessionId, remainingTimeoutMs);
36471
+ if (snapshot.transportTimedOut) {
36472
+ return buildTransportTimeoutCaptureEvidence(snapshot, void 0, "snapshot capture");
36473
+ }
36474
+ const clone2 = await captureCloneArtifact(manager, sessionId, remainingTimeoutMs);
36475
+ if (clone2.transportTimedOut) {
36476
+ return buildTransportTimeoutCaptureEvidence(snapshot, clone2, "clone capture");
36477
+ }
36478
+ const dom = await captureDomArtifact(manager, sessionId, remainingTimeoutMs);
36479
+ return buildCaptureEvidence(snapshot, clone2, dom);
36480
+ };
36447
36481
  async function captureInspiredesignReferenceFromManager(manager, url, options = {}) {
36448
36482
  const cookiePolicy = resolveInspiredesignCaptureCookiePolicy(options);
36449
36483
  const captureTimeoutMs = clampInspiredesignCaptureTimeout(options.timeoutMs);
36450
36484
  const remainingTimeoutMs = createRemainingCaptureTimeout(captureTimeoutMs);
36451
- const session = await manager.launch({
36452
- headless: true,
36453
- startUrl: "about:blank",
36454
- persistProfile: false
36455
- });
36485
+ const launchTimeoutMs = remainingTimeoutMs();
36486
+ const session = await withCaptureDeadline(
36487
+ manager.launch({
36488
+ headless: true,
36489
+ startUrl: "about:blank",
36490
+ persistProfile: false,
36491
+ noExtension: true
36492
+ }, launchTimeoutMs),
36493
+ launchTimeoutMs,
36494
+ "session launch"
36495
+ );
36456
36496
  try {
36457
- const importState = cookiePolicy === "off" ? { sourceConfigured: false, sourceAvailable: false } : await importConfiguredCaptureCookies(manager, session.sessionId, options.cookieSource);
36497
+ const importState = cookiePolicy === "off" ? { sourceConfigured: false, sourceAvailable: false } : await importConfiguredCaptureCookies(
36498
+ manager,
36499
+ session.sessionId,
36500
+ options.cookieSource,
36501
+ remainingTimeoutMs()
36502
+ );
36458
36503
  if (cookiePolicy === "required") {
36459
- await verifyRequiredCaptureCookies(manager, session.sessionId, url, importState);
36504
+ await verifyRequiredCaptureCookies(
36505
+ manager,
36506
+ session.sessionId,
36507
+ url,
36508
+ importState,
36509
+ remainingTimeoutMs()
36510
+ );
36460
36511
  }
36461
36512
  manager.setSessionChallengeAutomationMode?.(session.sessionId, options.challengeAutomationMode);
36462
- await manager.goto(session.sessionId, url, "load", remainingTimeoutMs());
36463
- await manager.waitForLoad(session.sessionId, "networkidle", remainingTimeoutMs()).catch(() => void 0);
36513
+ const gotoTimeoutMs = remainingTimeoutMs();
36514
+ await withCaptureDeadline(
36515
+ manager.goto(session.sessionId, url, "load", gotoTimeoutMs),
36516
+ gotoTimeoutMs,
36517
+ "navigation"
36518
+ );
36519
+ const waitTimeoutMs = remainingTimeoutMs();
36520
+ try {
36521
+ await withCaptureDeadline(
36522
+ manager.waitForLoad(session.sessionId, "networkidle", waitTimeoutMs),
36523
+ waitTimeoutMs,
36524
+ "network idle wait"
36525
+ );
36526
+ } catch (error) {
36527
+ if (!isIgnorableNetworkIdleWaitError(error)) {
36528
+ throw error;
36529
+ }
36530
+ }
36464
36531
  return await captureInspiredesignArtifacts(manager, session.sessionId, remainingTimeoutMs);
36465
36532
  } finally {
36466
36533
  await manager.disconnect(session.sessionId, true).catch(() => void 0);
@@ -37029,7 +37096,7 @@ var waitForBinding = async (clientId, timeoutMs) => {
37029
37096
  if (!getQueueEntry(clientId)) {
37030
37097
  break;
37031
37098
  }
37032
- await new Promise((resolve8) => setTimeout(resolve8, 250));
37099
+ await new Promise((resolve9) => setTimeout(resolve9, 250));
37033
37100
  }
37034
37101
  dequeueClient(clientId);
37035
37102
  throw new Error("RELAY_WAIT_TIMEOUT: Timed out waiting for relay binding.");
@@ -37695,6 +37762,22 @@ async function handleDaemonCommand(core, request) {
37695
37762
  requireString3(params2.sessionId, "sessionId"),
37696
37763
  optionalString6(params2.targetId)
37697
37764
  );
37765
+ case "export.clonePageHtml":
37766
+ await authorizeSessionCommand(core, params2, request.name, bindingId);
37767
+ if (typeof core.manager.clonePageHtmlWithOptions !== "function") {
37768
+ throw new Error("clonePageHtmlWithOptions unavailable in this execution lane.");
37769
+ }
37770
+ {
37771
+ const maxNodes = optionalPositiveInteger2(params2.maxNodes, "maxNodes");
37772
+ return core.manager.clonePageHtmlWithOptions(
37773
+ requireString3(params2.sessionId, "sessionId"),
37774
+ optionalString6(params2.targetId),
37775
+ {
37776
+ ...typeof maxNodes === "number" ? { maxNodes } : {},
37777
+ ...typeof params2.inlineStyles === "boolean" ? { inlineStyles: params2.inlineStyles } : {}
37778
+ }
37779
+ );
37780
+ }
37698
37781
  case "export.cloneComponent":
37699
37782
  await authorizeSessionCommand(core, params2, request.name, bindingId);
37700
37783
  return core.manager.cloneComponent(
@@ -37984,8 +38067,8 @@ async function handleDaemonCommand(core, request) {
37984
38067
  await core.manager.goto(session.sessionId, url, "load", captureTimeoutMs);
37985
38068
  const screenshot = await Promise.race([
37986
38069
  core.manager.screenshot(session.sessionId),
37987
- new Promise((resolve8) => {
37988
- setTimeout(() => resolve8(null), captureTimeoutMs);
38070
+ new Promise((resolve9) => {
38071
+ setTimeout(() => resolve9(null), captureTimeoutMs);
37989
38072
  })
37990
38073
  ]);
37991
38074
  if (!screenshot || typeof screenshot.base64 !== "string" || screenshot.base64.length === 0) return null;
@@ -38623,6 +38706,15 @@ function requireFiniteNumber(value, label) {
38623
38706
  }
38624
38707
  throw new Error(`Invalid ${label}`);
38625
38708
  }
38709
+ function optionalPositiveInteger2(value, label) {
38710
+ if (typeof value === "undefined") {
38711
+ return void 0;
38712
+ }
38713
+ if (typeof value === "number" && Number.isInteger(value) && value > 0) {
38714
+ return value;
38715
+ }
38716
+ throw new Error(`Invalid ${label}`);
38717
+ }
38626
38718
  function requirePointerPoint(value, label) {
38627
38719
  const point = requireRecord2(value, label);
38628
38720
  return {
@@ -38769,7 +38861,7 @@ async function waitForRelayHandshake(relay, observedPort, timeoutMs) {
38769
38861
  if (observedStatus?.extensionHandshakeComplete) {
38770
38862
  return true;
38771
38863
  }
38772
- await new Promise((resolve8) => setTimeout(resolve8, delay3));
38864
+ await new Promise((resolve9) => setTimeout(resolve9, delay3));
38773
38865
  delay3 = Math.min(delay3 * 2, WAIT_MAX_DELAY_MS);
38774
38866
  }
38775
38867
  return false;
@@ -38964,24 +39056,39 @@ function clearDaemonMetadata() {
38964
39056
  } catch {
38965
39057
  }
38966
39058
  }
38967
- function resolveCurrentDaemonEntrypointPath() {
38968
- const rawEntry = process.argv[1];
39059
+ function resolveCurrentDaemonEntrypointPath(options = {}) {
39060
+ const rawEntry = options.argv1 ?? process.argv[1];
38969
39061
  if (typeof rawEntry === "string" && rawEntry.trim().length > 0) {
38970
39062
  return resolve7(rawEntry);
38971
39063
  }
38972
- return resolve7(__filename);
39064
+ const moduleUrl = options.moduleUrl ?? import.meta.url;
39065
+ const cliEntrypoint = resolve7(fileURLToPath2(new URL("./index.js", moduleUrl)));
39066
+ const entryExists = options.entryExists ?? existsSync6;
39067
+ if (entryExists(cliEntrypoint)) {
39068
+ return cliEntrypoint;
39069
+ }
39070
+ return resolve7(fileURLToPath2(moduleUrl));
38973
39071
  }
38974
- function hashEntrypointContents(entryPath) {
39072
+ function hashFileContents(entryPath) {
38975
39073
  try {
38976
39074
  return createHash6("sha256").update(readFileSync5(entryPath)).digest("hex");
38977
39075
  } catch {
38978
39076
  return "missing";
38979
39077
  }
38980
39078
  }
38981
- function getCurrentDaemonFingerprint() {
38982
- const entryPath = resolveCurrentDaemonEntrypointPath();
38983
- const entryHash = hashEntrypointContents(entryPath);
38984
- return createHash6("sha256").update([DAEMON_FINGERPRINT_VERSION, process.execPath, entryPath, entryHash].join("\n")).digest("hex");
39079
+ function getCurrentDaemonFingerprint(options = {}) {
39080
+ const entryPath = resolveCurrentDaemonEntrypointPath(options);
39081
+ const modulePath = resolve7(fileURLToPath2(options.moduleUrl ?? import.meta.url));
39082
+ const fingerprintParts = [
39083
+ DAEMON_FINGERPRINT_VERSION,
39084
+ process.execPath,
39085
+ entryPath,
39086
+ hashFileContents(entryPath)
39087
+ ];
39088
+ if (modulePath !== entryPath) {
39089
+ fingerprintParts.push(modulePath, hashFileContents(modulePath));
39090
+ }
39091
+ return createHash6("sha256").update(fingerprintParts.join("\n")).digest("hex");
38985
39092
  }
38986
39093
  function isCurrentDaemonFingerprint(fingerprint) {
38987
39094
  return typeof fingerprint === "string" && fingerprint === getCurrentDaemonFingerprint();
@@ -39098,9 +39205,9 @@ async function startDaemon(options = {}) {
39098
39205
  }
39099
39206
  sendJson(response, 404, { error: "Not found" });
39100
39207
  });
39101
- await new Promise((resolve8, reject) => {
39208
+ await new Promise((resolve9, reject) => {
39102
39209
  server.once("error", reject);
39103
- server.listen(port, "127.0.0.1", () => resolve8());
39210
+ server.listen(port, "127.0.0.1", () => resolve9());
39104
39211
  });
39105
39212
  const state = {
39106
39213
  port,
@@ -39158,8 +39265,8 @@ async function startDaemon(options = {}) {
39158
39265
  process.off("uncaughtException", uncaughtExceptionHandler);
39159
39266
  process.off("unhandledRejection", unhandledRejectionHandler);
39160
39267
  core.cleanup();
39161
- await new Promise((resolve8) => {
39162
- server.close(() => resolve8());
39268
+ await new Promise((resolve9) => {
39269
+ server.close(() => resolve9());
39163
39270
  });
39164
39271
  };
39165
39272
  const sigintHandler = () => {
@@ -39177,7 +39284,7 @@ async function startDaemon(options = {}) {
39177
39284
  return { state, stop };
39178
39285
  }
39179
39286
  function readJson2(request) {
39180
- return new Promise((resolve8, reject) => {
39287
+ return new Promise((resolve9, reject) => {
39181
39288
  let data = "";
39182
39289
  request.setEncoding("utf8");
39183
39290
  request.on("data", (chunk) => {
@@ -39190,7 +39297,7 @@ function readJson2(request) {
39190
39297
  reject(new Error("Invalid JSON body"));
39191
39298
  return;
39192
39299
  }
39193
- resolve8(parsed);
39300
+ resolve9(parsed);
39194
39301
  } catch (error) {
39195
39302
  reject(error);
39196
39303
  }
@@ -39246,7 +39353,7 @@ var sleep2 = async (delayMs) => {
39246
39353
  if (!(Number.isFinite(delayMs) && delayMs > 0)) {
39247
39354
  return;
39248
39355
  }
39249
- await new Promise((resolve8) => setTimeout(resolve8, delayMs));
39356
+ await new Promise((resolve9) => setTimeout(resolve9, delayMs));
39250
39357
  };
39251
39358
  var resolveRetryAttempts = (retryAttempts) => {
39252
39359
  return typeof retryAttempts === "number" && Number.isFinite(retryAttempts) && retryAttempts > 1 ? Math.floor(retryAttempts) : 1;
@@ -39326,8 +39433,9 @@ function persistDaemonStatusMetadata(base, status, config) {
39326
39433
  // src/cli/daemon-client.ts
39327
39434
  import { spawn as spawn2 } from "child_process";
39328
39435
  import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
39329
- import { join as join17 } from "path";
39436
+ import { join as join17, resolve as resolve8 } from "path";
39330
39437
  import { randomUUID as randomUUID23 } from "crypto";
39438
+ import { fileURLToPath as fileURLToPath3 } from "url";
39331
39439
  var CLIENT_ID_FILE = "client.json";
39332
39440
  var DEFAULT_RENEW_AFTER_MS = 2e4;
39333
39441
  var MIN_RENEW_AFTER_MS = 5e3;
@@ -39338,7 +39446,13 @@ var DAEMON_STATUS_RETRY_OPTIONS = {
39338
39446
  retryAttempts: 5,
39339
39447
  retryDelayMs: 250
39340
39448
  };
39449
+ var DAEMON_CONFIG_PREFER_OPTIONS = {
39450
+ timeoutMs: 500,
39451
+ retryAttempts: 3,
39452
+ retryDelayMs: 250
39453
+ };
39341
39454
  var DAEMON_RESTART_STATUS_TIMEOUT_MS = 5e3;
39455
+ var DAEMON_RECOVERY_READY_TIMEOUT_MS = 5e3;
39342
39456
  var DAEMON_RESTART_READY_TIMEOUT_MS = 15e3;
39343
39457
  var DAEMON_RESTART_POLL_DELAY_MS = 250;
39344
39458
  var cachedClientState;
@@ -39429,7 +39543,7 @@ var isLeaseInvalidError = (error) => {
39429
39543
  const message = error instanceof Error ? error.message : String(error ?? "");
39430
39544
  return message.startsWith("RELAY_LEASE_INVALID");
39431
39545
  };
39432
- var isTransportTimeoutError = (error) => {
39546
+ var isTransportTimeoutError2 = (error) => {
39433
39547
  const message = error instanceof Error ? error.message : String(error ?? "");
39434
39548
  return message.startsWith("Request timed out after ");
39435
39549
  };
@@ -39588,22 +39702,29 @@ var DaemonClient = class {
39588
39702
  }
39589
39703
  }
39590
39704
  async callRaw(name, params2, timeoutMs) {
39591
- const connection = await resolveDaemonConnection();
39705
+ const budget = createTimeoutBudget(timeoutMs);
39706
+ const connection = await resolveDaemonConnection(budget);
39592
39707
  let timedResponse;
39593
39708
  try {
39594
- timedResponse = await openDaemonCommand(connection.port, connection.token, name, params2, timeoutMs);
39709
+ timedResponse = await openDaemonCommand(
39710
+ connection.port,
39711
+ connection.token,
39712
+ name,
39713
+ params2,
39714
+ readRemainingBudgetMs(budget)
39715
+ );
39595
39716
  } catch (error) {
39596
- if (isTransportTimeoutError(error)) {
39717
+ if (isTransportTimeoutError2(error)) {
39597
39718
  throw error;
39598
39719
  }
39599
- timedResponse = await retryWithRefreshedConnection(name, params2, timeoutMs);
39720
+ timedResponse = await retryWithRefreshedConnection(name, params2, budget);
39600
39721
  }
39601
39722
  try {
39602
39723
  if (!timedResponse.response.ok) {
39603
39724
  const message = await readDaemonErrorMessage(timedResponse);
39604
39725
  if (message.includes("Unauthorized") || timedResponse.response.status === 401) {
39605
39726
  timedResponse.dispose();
39606
- timedResponse = await retryWithRefreshedConnection(name, params2, timeoutMs);
39727
+ timedResponse = await retryWithRefreshedConnection(name, params2, budget);
39607
39728
  if (!timedResponse.response.ok) {
39608
39729
  throw new CliError(await readDaemonErrorMessage(timedResponse), EXIT_EXECUTION);
39609
39730
  }
@@ -39628,6 +39749,37 @@ var DaemonClient = class {
39628
39749
  var asPositiveNumber = (value) => {
39629
39750
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
39630
39751
  };
39752
+ var createTransportTimeoutError = (timeoutMs) => {
39753
+ return new Error(`Request timed out after ${timeoutMs}ms`);
39754
+ };
39755
+ var createTimeoutBudget = (timeoutMs) => {
39756
+ const resolved = asPositiveNumber(timeoutMs);
39757
+ return resolved === void 0 ? null : { timeoutMs: resolved, deadlineMs: Date.now() + resolved };
39758
+ };
39759
+ var readRemainingBudgetMs = (budget) => {
39760
+ if (!budget) {
39761
+ return void 0;
39762
+ }
39763
+ const remainingMs = budget.deadlineMs - Date.now();
39764
+ if (remainingMs <= 0) {
39765
+ throw createTransportTimeoutError(budget.timeoutMs);
39766
+ }
39767
+ return remainingMs;
39768
+ };
39769
+ var capTimeoutToBudget = (timeoutMs, budget) => {
39770
+ const remainingMs = readRemainingBudgetMs(budget);
39771
+ return remainingMs === void 0 ? timeoutMs : Math.max(1, Math.min(timeoutMs, remainingMs));
39772
+ };
39773
+ var resolveReadyDeadlineMs = (readyTimeoutMs, budget) => {
39774
+ const localDeadlineMs = Date.now() + readyTimeoutMs;
39775
+ return budget ? Math.min(localDeadlineMs, budget.deadlineMs) : localDeadlineMs;
39776
+ };
39777
+ var hasBudgetTimedOut = (budget, deadlineMs) => {
39778
+ if (!budget) {
39779
+ return false;
39780
+ }
39781
+ return deadlineMs >= budget.deadlineMs && Date.now() >= budget.deadlineMs;
39782
+ };
39631
39783
  var deriveTransportTimeoutMs = (params2, explicitTimeoutMs) => {
39632
39784
  const explicit = asPositiveNumber(explicitTimeoutMs);
39633
39785
  if (explicit !== void 0) {
@@ -39649,11 +39801,95 @@ var cliClient = new DaemonClient({ autoRenew: false });
39649
39801
  async function callDaemon(command, params2, options) {
39650
39802
  return cliClient.call(command, params2 ?? {}, options);
39651
39803
  }
39804
+ var TYPESCRIPT_ENTRY_RE = /\.[cm]?ts$/i;
39805
+ var RESTART_LOADER_ARG_FLAGS = /* @__PURE__ */ new Set(["--experimental-loader", "--import", "--loader", "--require", "-r"]);
39806
+ var RESTART_TYPESCRIPT_CONTEXT_ARG_FLAGS = /* @__PURE__ */ new Set(["--experimental-strip-types", "--experimental-transform-types"]);
39807
+ var RESTART_DEBUG_ARG_FLAGS = /* @__PURE__ */ new Set(["--inspect", "--inspect-brk", "--inspect-port", "--debug", "--debug-brk"]);
39808
+ var isInlineRestartArg = (arg, flags) => {
39809
+ for (const flag of flags) {
39810
+ if (arg.startsWith(`${flag}=`)) {
39811
+ return true;
39812
+ }
39813
+ }
39814
+ return false;
39815
+ };
39816
+ var isRestartLoaderArg = (arg) => {
39817
+ return RESTART_LOADER_ARG_FLAGS.has(arg) || isInlineRestartArg(arg, RESTART_LOADER_ARG_FLAGS);
39818
+ };
39819
+ var isRestartTypeScriptContextArg = (arg) => {
39820
+ return RESTART_TYPESCRIPT_CONTEXT_ARG_FLAGS.has(arg) || isInlineRestartArg(arg, RESTART_TYPESCRIPT_CONTEXT_ARG_FLAGS);
39821
+ };
39822
+ var isRestartDebugArg = (arg) => {
39823
+ return RESTART_DEBUG_ARG_FLAGS.has(arg) || isInlineRestartArg(arg, RESTART_DEBUG_ARG_FLAGS);
39824
+ };
39825
+ var resolveRestartSplitArgValue = (arg, value) => {
39826
+ if (arg.includes("=")) return null;
39827
+ if (typeof value !== "string") return null;
39828
+ return value.startsWith("-") ? null : value;
39829
+ };
39830
+ var resolveRestartExecArgv = (entryPath, execArgv) => {
39831
+ const preserved = [];
39832
+ let hasLoaderContext = false;
39833
+ for (let index = 0; index < execArgv.length; index += 1) {
39834
+ const arg = execArgv[index];
39835
+ if (!arg) {
39836
+ continue;
39837
+ }
39838
+ if (isRestartDebugArg(arg)) {
39839
+ const next = resolveRestartSplitArgValue(arg, execArgv[index + 1]);
39840
+ if (RESTART_DEBUG_ARG_FLAGS.has(arg) && next) {
39841
+ index += 1;
39842
+ }
39843
+ continue;
39844
+ }
39845
+ preserved.push(arg);
39846
+ if (isRestartLoaderArg(arg) || isRestartTypeScriptContextArg(arg)) {
39847
+ hasLoaderContext = true;
39848
+ }
39849
+ const value = resolveRestartSplitArgValue(arg, execArgv[index + 1]);
39850
+ if (!value) continue;
39851
+ preserved.push(value);
39852
+ index += 1;
39853
+ }
39854
+ return TYPESCRIPT_ENTRY_RE.test(entryPath) && !hasLoaderContext ? [] : preserved;
39855
+ };
39856
+ var fetchCurrentDaemonStatus = async (connection, options, budget = null) => {
39857
+ const attempts = typeof options.retryAttempts === "number" && Number.isFinite(options.retryAttempts) && options.retryAttempts > 1 ? Math.floor(options.retryAttempts) : 1;
39858
+ const retryDelayMs = typeof options.retryDelayMs === "number" && Number.isFinite(options.retryDelayMs) && options.retryDelayMs > 0 ? options.retryDelayMs : 0;
39859
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
39860
+ const status = await fetchDaemonStatus(connection.port, connection.token, {
39861
+ timeoutMs: capTimeoutToBudget(options.timeoutMs ?? DAEMON_RESTART_STATUS_TIMEOUT_MS, budget)
39862
+ });
39863
+ if (status?.ok && isCurrentDaemonFingerprint(status.fingerprint)) {
39864
+ return status;
39865
+ }
39866
+ if (attempt < attempts) {
39867
+ await sleep3(Math.min(retryDelayMs, readRemainingBudgetMs(budget) ?? retryDelayMs));
39868
+ }
39869
+ }
39870
+ return null;
39871
+ };
39872
+ var fetchAnyDaemonStatus = async (connection, options, budget = null) => {
39873
+ const attempts = typeof options.retryAttempts === "number" && Number.isFinite(options.retryAttempts) && options.retryAttempts > 1 ? Math.floor(options.retryAttempts) : 1;
39874
+ const retryDelayMs = typeof options.retryDelayMs === "number" && Number.isFinite(options.retryDelayMs) && options.retryDelayMs > 0 ? options.retryDelayMs : 0;
39875
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
39876
+ const status = await fetchDaemonStatus(connection.port, connection.token, {
39877
+ timeoutMs: capTimeoutToBudget(options.timeoutMs ?? DAEMON_RESTART_STATUS_TIMEOUT_MS, budget)
39878
+ });
39879
+ if (status?.ok) {
39880
+ return status;
39881
+ }
39882
+ if (attempt < attempts) {
39883
+ await sleep3(Math.min(retryDelayMs, readRemainingBudgetMs(budget) ?? retryDelayMs));
39884
+ }
39885
+ }
39886
+ return null;
39887
+ };
39652
39888
  var sleep3 = async (delayMs) => {
39653
39889
  if (!(Number.isFinite(delayMs) && delayMs > 0)) {
39654
39890
  return;
39655
39891
  }
39656
- await new Promise((resolve8) => setTimeout(resolve8, delayMs));
39892
+ await new Promise((resolve9) => setTimeout(resolve9, delayMs));
39657
39893
  };
39658
39894
  var getConfiguredDaemonConnection = () => {
39659
39895
  const config = loadGlobalConfig();
@@ -39674,18 +39910,78 @@ var persistResolvedDaemonStatus = (connection, status) => {
39674
39910
  fingerprint: status.fingerprint
39675
39911
  }, status, config);
39676
39912
  };
39677
- var stopDaemonConnection = async (connection) => {
39913
+ var persistCurrentConfiguredConnection = async (configuredConnection, status, staleMetadata) => {
39914
+ if (staleMetadata && !sameDaemonConnection(staleMetadata.connection, configuredConnection)) {
39915
+ void stopDaemonConnection(staleMetadata.connection).catch(() => void 0);
39916
+ }
39917
+ persistResolvedDaemonStatus(configuredConnection, status);
39918
+ return configuredConnection;
39919
+ };
39920
+ var resolveConfiguredPreferenceOptions = (budget) => {
39921
+ if (!budget) {
39922
+ return DAEMON_CONFIG_PREFER_OPTIONS;
39923
+ }
39924
+ const remainingMs = readRemainingBudgetMs(budget);
39925
+ if (remainingMs === void 0 || remainingMs <= 1) {
39926
+ return null;
39927
+ }
39928
+ const timeoutMs = Math.min(DAEMON_CONFIG_PREFER_OPTIONS.timeoutMs ?? remainingMs, remainingMs);
39929
+ const retryDelayMs = Math.max(0, DAEMON_CONFIG_PREFER_OPTIONS.retryDelayMs ?? 0);
39930
+ const maxAttempts = Math.max(1, DAEMON_CONFIG_PREFER_OPTIONS.retryAttempts ?? 1);
39931
+ let retryAttempts = 1;
39932
+ while (retryAttempts < maxAttempts) {
39933
+ const nextAttempts = retryAttempts + 1;
39934
+ const nextWorstCaseMs = nextAttempts * timeoutMs + (nextAttempts - 1) * retryDelayMs;
39935
+ if (nextWorstCaseMs > remainingMs) {
39936
+ break;
39937
+ }
39938
+ retryAttempts = nextAttempts;
39939
+ }
39940
+ return {
39941
+ timeoutMs,
39942
+ retryAttempts,
39943
+ retryDelayMs: retryAttempts > 1 ? retryDelayMs : 0
39944
+ };
39945
+ };
39946
+ var stopDaemonConnection = async (connection, budget = null) => {
39947
+ const stopTimeoutMs = capTimeoutToBudget(DAEMON_RESTART_STATUS_TIMEOUT_MS, budget);
39678
39948
  try {
39679
39949
  await fetchWithTimeout(`http://127.0.0.1:${connection.port}/stop`, {
39680
39950
  method: "POST",
39681
39951
  headers: { Authorization: `Bearer ${connection.token}` }
39682
- }, DAEMON_RESTART_STATUS_TIMEOUT_MS);
39952
+ }, stopTimeoutMs);
39683
39953
  } catch {
39684
39954
  }
39685
39955
  };
39956
+ function resolveDaemonRestartCommand(options = {}) {
39957
+ const execPath = options.execPath ?? process.execPath;
39958
+ const execArgv = options.execArgv ?? process.execArgv;
39959
+ const moduleUrl = options.moduleUrl ?? import.meta.url;
39960
+ const argv1 = options.argv1 ?? process.argv[1];
39961
+ const entryPath = resolveCurrentDaemonEntrypointPath({
39962
+ argv1,
39963
+ moduleUrl,
39964
+ entryExists: options.entryExists ?? existsSync7
39965
+ });
39966
+ if (!(typeof argv1 === "string" && argv1.trim().length > 0)) {
39967
+ const modulePath = resolve8(fileURLToPath3(moduleUrl));
39968
+ if (entryPath === modulePath) {
39969
+ throw createDisconnectedError("Daemon restart requires a stable CLI entrypoint. Start with `opendevbrowser serve`.");
39970
+ }
39971
+ }
39972
+ const restartExecArgv = resolveRestartExecArgv(entryPath, execArgv);
39973
+ if (TYPESCRIPT_ENTRY_RE.test(entryPath) && restartExecArgv.length === 0) {
39974
+ throw createDisconnectedError("Daemon restart requires the original loader context. Start with `opendevbrowser serve`.");
39975
+ }
39976
+ return {
39977
+ command: execPath,
39978
+ args: [...restartExecArgv, entryPath]
39979
+ };
39980
+ }
39686
39981
  var restartDaemonConnection = async (connection) => {
39687
- const child = spawn2(process.execPath, [
39688
- resolveCurrentDaemonEntrypointPath(),
39982
+ const restart = resolveDaemonRestartCommand();
39983
+ const child = spawn2(restart.command, [
39984
+ ...restart.args,
39689
39985
  "serve",
39690
39986
  "--port",
39691
39987
  String(connection.port),
@@ -39699,11 +39995,18 @@ var restartDaemonConnection = async (connection) => {
39699
39995
  });
39700
39996
  child.unref();
39701
39997
  };
39702
- var waitForCurrentDaemonStatus = async (connection) => {
39703
- const deadline = Date.now() + DAEMON_RESTART_READY_TIMEOUT_MS;
39998
+ var waitForCurrentDaemonStatus = async (connection, readyTimeoutMs = DAEMON_RESTART_READY_TIMEOUT_MS, budget = null) => {
39999
+ const deadline = resolveReadyDeadlineMs(readyTimeoutMs, budget);
39704
40000
  while (true) {
40001
+ const remainingMs = deadline - Date.now();
40002
+ if (remainingMs <= 0) {
40003
+ if (hasBudgetTimedOut(budget, deadline)) {
40004
+ throw createTransportTimeoutError(budget.timeoutMs);
40005
+ }
40006
+ return null;
40007
+ }
39705
40008
  const status = await fetchDaemonStatus(connection.port, connection.token, {
39706
- timeoutMs: DAEMON_RESTART_STATUS_TIMEOUT_MS
40009
+ timeoutMs: Math.min(DAEMON_RESTART_STATUS_TIMEOUT_MS, remainingMs)
39707
40010
  });
39708
40011
  if (status?.ok && isCurrentDaemonFingerprint(status.fingerprint)) {
39709
40012
  return status;
@@ -39711,15 +40014,36 @@ var waitForCurrentDaemonStatus = async (connection) => {
39711
40014
  if (Date.now() >= deadline) {
39712
40015
  return null;
39713
40016
  }
39714
- await sleep3(DAEMON_RESTART_POLL_DELAY_MS);
40017
+ await sleep3(Math.min(DAEMON_RESTART_POLL_DELAY_MS, Math.max(0, deadline - Date.now())));
39715
40018
  }
39716
40019
  };
39717
- var resolveMetadataConnection = async (metadataConnection, configuredConnection) => {
39718
- const status = await fetchDaemonStatus(
39719
- metadataConnection.port,
39720
- metadataConnection.token,
39721
- DAEMON_STATUS_RETRY_OPTIONS
39722
- );
40020
+ var waitForDaemonShutdown = async (connection, readyTimeoutMs = DAEMON_RECOVERY_READY_TIMEOUT_MS, budget = null) => {
40021
+ const deadline = resolveReadyDeadlineMs(readyTimeoutMs, budget);
40022
+ while (true) {
40023
+ const remainingMs = deadline - Date.now();
40024
+ if (remainingMs <= 0) {
40025
+ if (hasBudgetTimedOut(budget, deadline)) {
40026
+ throw createTransportTimeoutError(budget.timeoutMs);
40027
+ }
40028
+ return null;
40029
+ }
40030
+ const status = await fetchDaemonStatus(connection.port, connection.token, {
40031
+ timeoutMs: Math.min(DAEMON_RESTART_STATUS_TIMEOUT_MS, remainingMs)
40032
+ });
40033
+ if (!status?.ok) {
40034
+ return "stopped";
40035
+ }
40036
+ if (isCurrentDaemonFingerprint(status.fingerprint)) {
40037
+ return status;
40038
+ }
40039
+ if (Date.now() >= deadline) {
40040
+ return null;
40041
+ }
40042
+ await sleep3(Math.min(DAEMON_RESTART_POLL_DELAY_MS, Math.max(0, deadline - Date.now())));
40043
+ }
40044
+ };
40045
+ var resolveMetadataConnection = async (metadataConnection, configuredConnection, budget = null) => {
40046
+ const status = await fetchAnyDaemonStatus(metadataConnection, DAEMON_STATUS_RETRY_OPTIONS, budget);
39723
40047
  if (!status?.ok) {
39724
40048
  return null;
39725
40049
  }
@@ -39732,26 +40056,35 @@ var resolveMetadataConnection = async (metadataConnection, configuredConnection)
39732
40056
  }
39733
40057
  return { connection: metadataConnection, status };
39734
40058
  };
39735
- var resolveFreshDaemonConnection = async () => {
40059
+ var resolveFreshDaemonConnection = async (budget = null) => {
39736
40060
  const configuredConnection = getConfiguredDaemonConnection();
39737
40061
  if (!configuredConnection) {
39738
40062
  throw createDisconnectedError("Daemon not running. Start with `opendevbrowser serve`.");
39739
40063
  }
39740
- const configuredStatus = await fetchDaemonStatus(
39741
- configuredConnection.port,
39742
- configuredConnection.token,
39743
- DAEMON_STATUS_RETRY_OPTIONS
39744
- );
39745
- if (configuredStatus?.ok && isCurrentDaemonFingerprint(configuredStatus.fingerprint)) {
39746
- persistResolvedDaemonStatus(configuredConnection, configuredStatus);
39747
- return configuredConnection;
39748
- }
40064
+ const configuredStatus = await fetchAnyDaemonStatus(configuredConnection, DAEMON_STATUS_RETRY_OPTIONS, budget);
40065
+ let currentConfiguredStatus = configuredStatus?.ok && isCurrentDaemonFingerprint(configuredStatus.fingerprint) ? configuredStatus : null;
39749
40066
  const metadata = readDaemonMetadata();
39750
40067
  const metadataConnection = metadata ? { port: metadata.port, token: metadata.token } : null;
39751
- const staleMetadata = metadataConnection ? await resolveMetadataConnection(metadataConnection, configuredConnection) : null;
40068
+ const staleMetadata = metadataConnection ? await resolveMetadataConnection(metadataConnection, configuredConnection, budget) : null;
40069
+ if (currentConfiguredStatus?.ok) {
40070
+ return await persistCurrentConfiguredConnection(configuredConnection, currentConfiguredStatus, staleMetadata);
40071
+ }
39752
40072
  if (staleMetadata?.status.ok && isCurrentDaemonFingerprint(staleMetadata.status.fingerprint)) {
40073
+ if (configuredStatus?.ok) {
40074
+ void stopDaemonConnection(configuredConnection, budget).catch(() => void 0);
40075
+ }
39753
40076
  return staleMetadata.connection;
39754
40077
  }
40078
+ if (!configuredStatus?.ok && staleMetadata) {
40079
+ currentConfiguredStatus = await waitForCurrentDaemonStatus(
40080
+ configuredConnection,
40081
+ DAEMON_RECOVERY_READY_TIMEOUT_MS,
40082
+ budget
40083
+ );
40084
+ if (currentConfiguredStatus?.ok) {
40085
+ return await persistCurrentConfiguredConnection(configuredConnection, currentConfiguredStatus, staleMetadata);
40086
+ }
40087
+ }
39755
40088
  const staleConnections = [];
39756
40089
  if (configuredStatus?.ok) {
39757
40090
  staleConnections.push(configuredConnection);
@@ -39760,29 +40093,65 @@ var resolveFreshDaemonConnection = async () => {
39760
40093
  staleConnections.push(staleMetadata.connection);
39761
40094
  }
39762
40095
  if (staleConnections.length === 0) {
40096
+ const recoveringStatus = await waitForCurrentDaemonStatus(
40097
+ configuredConnection,
40098
+ DAEMON_RECOVERY_READY_TIMEOUT_MS,
40099
+ budget
40100
+ );
40101
+ if (recoveringStatus?.ok) {
40102
+ persistResolvedDaemonStatus(configuredConnection, recoveringStatus);
40103
+ return configuredConnection;
40104
+ }
39763
40105
  throw createDisconnectedError("Daemon not running. Start with `opendevbrowser serve`.");
39764
40106
  }
39765
40107
  for (const staleConnection of staleConnections) {
39766
- await stopDaemonConnection(staleConnection);
40108
+ await stopDaemonConnection(staleConnection, budget);
40109
+ }
40110
+ if (configuredStatus?.ok) {
40111
+ const shutdownOutcome = await waitForDaemonShutdown(configuredConnection, DAEMON_RECOVERY_READY_TIMEOUT_MS, budget);
40112
+ if (!shutdownOutcome) {
40113
+ throw createDisconnectedError("Daemon restart could not reclaim the configured port after fingerprint mismatch. Start with `opendevbrowser serve`.");
40114
+ }
40115
+ if (shutdownOutcome !== "stopped") {
40116
+ persistResolvedDaemonStatus(configuredConnection, shutdownOutcome);
40117
+ return configuredConnection;
40118
+ }
39767
40119
  }
39768
40120
  await restartDaemonConnection(configuredConnection);
39769
- const refreshedStatus = await waitForCurrentDaemonStatus(configuredConnection);
40121
+ const refreshedStatus = await waitForCurrentDaemonStatus(configuredConnection, DAEMON_RESTART_READY_TIMEOUT_MS, budget);
39770
40122
  if (!refreshedStatus?.ok) {
39771
40123
  throw createDisconnectedError("Daemon restart failed after fingerprint mismatch. Start with `opendevbrowser serve`.");
39772
40124
  }
39773
40125
  persistResolvedDaemonStatus(configuredConnection, refreshedStatus);
39774
40126
  return configuredConnection;
39775
40127
  };
39776
- var resolveDaemonConnection = async () => {
40128
+ var resolveDaemonConnection = async (budget = null) => {
39777
40129
  const metadata = readDaemonMetadata();
39778
40130
  if (metadata && isCurrentDaemonFingerprint(metadata.fingerprint)) {
39779
- return { port: metadata.port, token: metadata.token };
40131
+ const metadataConnection = { port: metadata.port, token: metadata.token };
40132
+ const configuredConnection = getConfiguredDaemonConnection();
40133
+ if (!configuredConnection || sameDaemonConnection(metadataConnection, configuredConnection)) {
40134
+ return metadataConnection;
40135
+ }
40136
+ const configuredOptions = resolveConfiguredPreferenceOptions(budget);
40137
+ if (!configuredOptions) {
40138
+ return metadataConnection;
40139
+ }
40140
+ const configuredStatus = await fetchCurrentDaemonStatus(configuredConnection, configuredOptions, budget);
40141
+ if (configuredStatus?.ok) {
40142
+ return await persistCurrentConfiguredConnection(
40143
+ configuredConnection,
40144
+ configuredStatus,
40145
+ { connection: metadataConnection }
40146
+ );
40147
+ }
40148
+ return metadataConnection;
39780
40149
  }
39781
- return await resolveFreshDaemonConnection();
40150
+ return await resolveFreshDaemonConnection(budget);
39782
40151
  };
39783
- var retryWithRefreshedConnection = async (name, params2, timeoutMs) => {
39784
- const connection = await resolveFreshDaemonConnection();
39785
- return await openDaemonCommand(connection.port, connection.token, name, params2, timeoutMs);
40152
+ var retryWithRefreshedConnection = async (name, params2, budget) => {
40153
+ const connection = await resolveFreshDaemonConnection(budget);
40154
+ return await openDaemonCommand(connection.port, connection.token, name, params2, readRemainingBudgetMs(budget));
39786
40155
  };
39787
40156
  var openDaemonCommand = async (port, token, name, params2, timeoutMs) => {
39788
40157
  return await fetchWithTimeoutContext(`http://127.0.0.1:${port}/command`, {
@@ -39967,6 +40336,15 @@ var buildAnnotateResult = async (payload) => {
39967
40336
  };
39968
40337
  };
39969
40338
 
40339
+ // src/cli/transport-timeouts.ts
40340
+ var DEFAULT_CLICK_TRANSPORT_TIMEOUT_MS = 6e4;
40341
+ var DEFAULT_DIALOG_TRANSPORT_TIMEOUT_MS = 3e4;
40342
+ var DEFAULT_TARGET_CREATION_TRANSPORT_TIMEOUT_MS = 3e4;
40343
+ var DEFAULT_SNAPSHOT_TRANSPORT_TIMEOUT_MS = 3e4;
40344
+ var DEFAULT_REVIEW_TRANSPORT_TIMEOUT_MS = 3e4;
40345
+ var DEFAULT_SCREENSHOT_TRANSPORT_TIMEOUT_MS = 3e4;
40346
+ var DEFAULT_WORKFLOW_TRANSPORT_TIMEOUT_MS = 12e4;
40347
+
39970
40348
  // src/public-surface/generated-manifest.ts
39971
40349
  var PUBLIC_SURFACE_MANIFEST = {
39972
40350
  "schemaVersion": "2026-04-04",
@@ -40547,10 +40925,10 @@ var PUBLIC_SURFACE_MANIFEST = {
40547
40925
  "--cookie-policy"
40548
40926
  ],
40549
40927
  "examples": [
40550
- 'npx opendevbrowser inspiredesign run --brief "Extract a reusable dashboard design contract from live references" --url https://linear.app --capture-mode deep --include-prototype-guidance --output-dir /tmp/inspiredesign --output-format json'
40928
+ 'npx opendevbrowser inspiredesign run --brief "Extract a reusable dashboard design contract from live references" --url https://linear.app --include-prototype-guidance --output-dir /tmp/inspiredesign --output-format json'
40551
40929
  ],
40552
40930
  "notes": [
40553
- "--capture-mode defaults to off; opt into deep only when live DOM or layout evidence is required.",
40931
+ "Any inspiredesign --url forces deep capture for DOM/layout evidence; without URLs, --capture-mode defaults to off.",
40554
40932
  "Repeat --url for multiple references. There is no --urls alias."
40555
40933
  ],
40556
40934
  "groupId": "provider_workflows",
@@ -42489,7 +42867,7 @@ var PUBLIC_SURFACE_MANIFEST = {
42489
42867
  "name": "opendevbrowser_inspiredesign_run",
42490
42868
  "description": "Run the inspiredesign workflow directly.",
42491
42869
  "cliEquivalent": "inspiredesign",
42492
- "example": 'npx opendevbrowser inspiredesign run --brief "Extract a reusable dashboard design contract from live references" --url https://linear.app --capture-mode deep --include-prototype-guidance --output-dir /tmp/inspiredesign --output-format json'
42870
+ "example": 'npx opendevbrowser inspiredesign run --brief "Extract a reusable dashboard design contract from live references" --url https://linear.app --include-prototype-guidance --output-dir /tmp/inspiredesign --output-format json'
42493
42871
  },
42494
42872
  {
42495
42873
  "name": "opendevbrowser_canvas",
@@ -42957,6 +43335,13 @@ export {
42957
43335
  callDaemon,
42958
43336
  onboarding_metadata_default,
42959
43337
  buildAnnotateResult,
43338
+ DEFAULT_CLICK_TRANSPORT_TIMEOUT_MS,
43339
+ DEFAULT_DIALOG_TRANSPORT_TIMEOUT_MS,
43340
+ DEFAULT_TARGET_CREATION_TRANSPORT_TIMEOUT_MS,
43341
+ DEFAULT_SNAPSHOT_TRANSPORT_TIMEOUT_MS,
43342
+ DEFAULT_REVIEW_TRANSPORT_TIMEOUT_MS,
43343
+ DEFAULT_SCREENSHOT_TRANSPORT_TIMEOUT_MS,
43344
+ DEFAULT_WORKFLOW_TRANSPORT_TIMEOUT_MS,
42960
43345
  VALID_FLAGS,
42961
43346
  VALID_EQUALS_FLAGS,
42962
43347
  CLI_COMMANDS,
@@ -42965,4 +43350,4 @@ export {
42965
43350
  TOOL_SURFACE_ENTRIES
42966
43351
  };
42967
43352
  /* v8 ignore next -- @preserve */
42968
- //# sourceMappingURL=chunk-5I6TZRVS.js.map
43353
+ //# sourceMappingURL=chunk-7U63PZ4W.js.map