@agent-native/core 0.15.7 → 0.15.10

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 (28) hide show
  1. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  2. package/dist/agent/engine/builder-engine.js +19 -1
  3. package/dist/agent/engine/builder-engine.js.map +1 -1
  4. package/dist/client/settings/SettingsPanel.js.map +1 -1
  5. package/dist/client/settings/useBuilderStatus.d.ts +10 -1
  6. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  7. package/dist/client/settings/useBuilderStatus.js +39 -3
  8. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  9. package/dist/client/settings/useBuilderStatus.spec.js +76 -0
  10. package/dist/client/settings/useBuilderStatus.spec.js.map +1 -1
  11. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  12. package/dist/server/agent-chat-plugin.js +5 -2
  13. package/dist/server/agent-chat-plugin.js.map +1 -1
  14. package/dist/server/builder-browser.d.ts +52 -15
  15. package/dist/server/builder-browser.d.ts.map +1 -1
  16. package/dist/server/builder-browser.js +126 -15
  17. package/dist/server/builder-browser.js.map +1 -1
  18. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  19. package/dist/server/core-routes-plugin.js +105 -19
  20. package/dist/server/core-routes-plugin.js.map +1 -1
  21. package/dist/server/credential-provider.d.ts +25 -4
  22. package/dist/server/credential-provider.d.ts.map +1 -1
  23. package/dist/server/credential-provider.js +112 -15
  24. package/dist/server/credential-provider.js.map +1 -1
  25. package/dist/server/google-realtime-session.d.ts.map +1 -1
  26. package/dist/server/google-realtime-session.js +1 -1
  27. package/dist/server/google-realtime-session.js.map +1 -1
  28. package/package.json +1 -1
@@ -7,7 +7,7 @@ export interface BuilderStatus {
7
7
  * and take precedence for that request.
8
8
  */
9
9
  envManaged?: boolean;
10
- credentialSource?: "user" | "org" | "env";
10
+ credentialSource?: "user" | "org" | "workspace" | "env";
11
11
  connectUrl: string;
12
12
  cliAuthUrl?: string;
13
13
  appHost: string;
@@ -28,6 +28,15 @@ export interface BuilderStatus {
28
28
  message: string;
29
29
  at: number;
30
30
  };
31
+ /**
32
+ * Set when the currently effective Builder credential was rejected by
33
+ * Builder's API. Unlike connectError, this describes the old credential pair
34
+ * and should not abort a new reconnect attempt while the popup is open.
35
+ */
36
+ authError?: {
37
+ message: string;
38
+ at: number;
39
+ };
31
40
  }
32
41
  /**
33
42
  * Fetches Builder connection status from /_agent-native/builder/status.
@@ -1 +1 @@
1
- {"version":3,"file":"useBuilderStatus.d.ts","sourceRoot":"","sources":["../../../src/client/settings/useBuilderStatus.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,YAAY,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB;;;;EA4C/B;AAkBD,MAAM,WAAW,yBAAyB;IACxC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;;;;OAOG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAC1B,oFAAoF;IACpF,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAwHD,MAAM,WAAW,8BAA8B;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,GAAG,EACH,MAA0B,EAC1B,QAAgC,GACjC,GAAE,8BAAmC,GAAG,MAAM,GAAG,IAAI,CAkCrD;AAED,wBAAgB,qBAAqB,CACnC,IAAI,GAAE,yBAA8B,GACnC,kBAAkB,CAyWpB"}
1
+ {"version":3,"file":"useBuilderStatus.d.ts","sourceRoot":"","sources":["../../../src/client/settings/useBuilderStatus.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,WAAW,GAAG,KAAK,CAAC;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,YAAY,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C;;;;OAIG;IACH,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB;;;;EA4C/B;AAkBD,MAAM,WAAW,yBAAyB;IACxC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;;;;OAOG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAC1B,oFAAoF;IACpF,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAmID,MAAM,WAAW,8BAA8B;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,GAAG,EACH,MAA0B,EAC1B,QAAgC,GACjC,GAAE,8BAAmC,GAAG,MAAM,GAAG,IAAI,CAkCrD;AAED,wBAAgB,qBAAqB,CACnC,IAAI,GAAE,yBAA8B,GACnC,kBAAkB,CAmYpB"}
@@ -86,6 +86,13 @@ function isFreshSignedConnectUrl(url, fetchedAt) {
86
86
  typeof fetchedAt === "number" &&
87
87
  Date.now() - fetchedAt < STATUS_CONNECT_URL_TTL_MS);
88
88
  }
89
+ function isCurrentConnectError(error, startedAt) {
90
+ if (!error?.message)
91
+ return false;
92
+ if (!startedAt)
93
+ return true;
94
+ return typeof error.at !== "number" || error.at >= startedAt - 1000;
95
+ }
89
96
  function showBuilderConnectPopupPlaceholder(opened) {
90
97
  try {
91
98
  opened.opener = null;
@@ -151,7 +158,9 @@ function isTrustedBuilderConnectMessageOrigin(origin) {
151
158
  hostname === "builderio.dev" ||
152
159
  hostname.endsWith(".builderio.dev") ||
153
160
  hostname === "builder.codes" ||
154
- hostname.endsWith(".builder.codes"));
161
+ hostname.endsWith(".builder.codes") ||
162
+ hostname === "agent-native.com" ||
163
+ hostname.endsWith(".agent-native.com"));
155
164
  }
156
165
  catch {
157
166
  return false;
@@ -210,6 +219,7 @@ export function useBuilderConnectFlow(opts = {}) {
210
219
  // gesture path (browser/editor embeds).
211
220
  const statusConnectUrlAtRef = useRef(null);
212
221
  const pollRef = useRef(null);
222
+ const connectStartedAtRef = useRef(null);
213
223
  const mountedRef = useRef(true);
214
224
  const notifiedConnectedRef = useRef(false);
215
225
  // Keep onConnected in a ref so start() doesn't need to re-create when the
@@ -260,6 +270,9 @@ export function useBuilderConnectFlow(opts = {}) {
260
270
  statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;
261
271
  const org = s.orgName ?? null;
262
272
  setOrgName(org);
273
+ if (s.configured) {
274
+ connectStartedAtRef.current = null;
275
+ }
263
276
  if (s.configured && !notifiedConnectedRef.current) {
264
277
  notifiedConnectedRef.current = true;
265
278
  notifyAgentEngineConfiguredChanged("builder-status");
@@ -273,6 +286,19 @@ export function useBuilderConnectFlow(opts = {}) {
273
286
  else if (!s.configured) {
274
287
  notifiedConnectedRef.current = false;
275
288
  }
289
+ // Surface persisted auth-failure messages on idle refreshes, but don't
290
+ // let an old rejected credential abort a new reconnect popup while the
291
+ // user is still choosing a Builder space.
292
+ const activeConnectStartedAt = connectStartedAtRef.current;
293
+ if (isCurrentConnectError(s.connectError, activeConnectStartedAt)) {
294
+ setError(s.connectError.message);
295
+ }
296
+ else if (!activeConnectStartedAt && s.authError?.message) {
297
+ setError(s.authError.message);
298
+ }
299
+ else if (s.configured) {
300
+ setError(null);
301
+ }
276
302
  };
277
303
  refresh();
278
304
  const onVisible = () => {
@@ -293,6 +319,8 @@ export function useBuilderConnectFlow(opts = {}) {
293
319
  }, [fetchStatus, stopPoll]);
294
320
  const start = useCallback(() => {
295
321
  stopPoll();
322
+ const started = Date.now();
323
+ connectStartedAtRef.current = started;
296
324
  setConnecting(true);
297
325
  setError(null);
298
326
  // Open SYNCHRONOUSLY inside the caller's click handler — any await
@@ -331,6 +359,7 @@ export function useBuilderConnectFlow(opts = {}) {
331
359
  features: "width=600,height=700",
332
360
  });
333
361
  if (!opened) {
362
+ connectStartedAtRef.current = null;
334
363
  setConnecting(false);
335
364
  setError("Couldn't open Builder. Allow popups and try again.");
336
365
  return;
@@ -343,6 +372,7 @@ export function useBuilderConnectFlow(opts = {}) {
343
372
  features: "width=600,height=700",
344
373
  });
345
374
  if (!opened) {
375
+ connectStartedAtRef.current = null;
346
376
  setConnecting(false);
347
377
  setError("Couldn't open Builder. Allow popups and try again.");
348
378
  return;
@@ -384,18 +414,19 @@ export function useBuilderConnectFlow(opts = {}) {
384
414
  // Ignore close failures.
385
415
  }
386
416
  stopPoll();
417
+ connectStartedAtRef.current = null;
387
418
  setConnecting(false);
388
419
  setError("Couldn't start Builder connect. Refresh this page and try again.");
389
420
  return;
390
421
  }
391
422
  if (!navigateBuilderConnectPopup(opened, freshUrl)) {
392
423
  stopPoll();
424
+ connectStartedAtRef.current = null;
393
425
  setConnecting(false);
394
426
  setError("Couldn't navigate the Builder popup. Allow popups and try again.");
395
427
  }
396
428
  })();
397
429
  }
398
- const started = Date.now();
399
430
  pollRef.current = setInterval(async () => {
400
431
  const s = await fetchStatus();
401
432
  if (!mountedRef.current) {
@@ -413,6 +444,7 @@ export function useBuilderConnectFlow(opts = {}) {
413
444
  const org = s.orgName ?? null;
414
445
  setOrgName(org);
415
446
  setConnecting(false);
447
+ connectStartedAtRef.current = null;
416
448
  notifiedConnectedRef.current = true;
417
449
  notifyAgentEngineConfiguredChanged("builder-connect");
418
450
  try {
@@ -423,15 +455,17 @@ export function useBuilderConnectFlow(opts = {}) {
423
455
  // to connected. Swallow so we don't re-arm the flow.
424
456
  }
425
457
  }
426
- else if (s?.connectError?.message) {
458
+ else if (isCurrentConnectError(s?.connectError, started)) {
427
459
  // OAuth callback ran but writeBuilderCredentials threw — surface the
428
460
  // real error instead of letting the user wait 5 minutes for timeout.
429
461
  stopPoll();
462
+ connectStartedAtRef.current = null;
430
463
  setConnecting(false);
431
464
  setError(`Couldn't save Builder credentials: ${s.connectError.message}. Try again or contact support.`);
432
465
  }
433
466
  else if (Date.now() - started > POLL_TIMEOUT_MS) {
434
467
  stopPoll();
468
+ connectStartedAtRef.current = null;
435
469
  setConnecting(false);
436
470
  trackEvent("builder connect failed", {
437
471
  feature: "builder",
@@ -455,6 +489,7 @@ export function useBuilderConnectFlow(opts = {}) {
455
489
  let channel = null;
456
490
  const handleError = (message) => {
457
491
  stopPoll();
492
+ connectStartedAtRef.current = null;
458
493
  setConnecting(false);
459
494
  setError(`Couldn't save Builder credentials: ${message}.`);
460
495
  };
@@ -473,6 +508,7 @@ export function useBuilderConnectFlow(opts = {}) {
473
508
  const org = s.orgName ?? null;
474
509
  setOrgName(org);
475
510
  setConnecting(false);
511
+ connectStartedAtRef.current = null;
476
512
  notifiedConnectedRef.current = true;
477
513
  notifyAgentEngineConfiguredChanged("builder-connect-message");
478
514
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"useBuilderStatus.js","sourceRoot":"","sources":["../../../src/client/settings/useBuilderStatus.ts"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport { getCallbackOrigin } from \"../frame.js\";\nimport { trackEvent } from \"../analytics.js\";\n\nexport interface BuilderStatus {\n configured: boolean;\n builderEnabled: boolean;\n /**\n * True when `BUILDER_PRIVATE_KEY` is set at the deploy level. This is a\n * fallback credential; per-user/org Builder connections are still allowed\n * and take precedence for that request.\n */\n envManaged?: boolean;\n credentialSource?: \"user\" | \"org\" | \"env\";\n connectUrl: string;\n cliAuthUrl?: string;\n appHost: string;\n apiHost: string;\n branchProjectIdConfigured?: boolean;\n branchProjectId?: string;\n publicKeyConfigured: boolean;\n privateKeyConfigured: boolean;\n userId?: string;\n orgName?: string;\n orgKind?: string;\n /**\n * Set when the OAuth callback ran but failed to persist credentials.\n * Surfaced as a one-shot row by the server so the connect-flow polling\n * can stop with a clear message instead of timing out at 5min.\n */\n connectError?: { message: string; at: number };\n}\n\n/**\n * Fetches Builder connection status from /_agent-native/builder/status.\n * Re-fetches on window focus to detect post-redirect state changes.\n */\nexport function useBuilderStatus() {\n const [status, setStatus] = useState<BuilderStatus | null>(null);\n const [loading, setLoading] = useState(true);\n\n const fetchStatus = useCallback(async () => {\n try {\n const res = await fetch(agentNativePath(\"/_agent-native/builder/status\"));\n if (!res.ok) {\n setStatus(null);\n return;\n }\n setStatus(await res.json());\n } catch {\n setStatus(null);\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n fetchStatus();\n\n function onFocus() {\n fetchStatus();\n }\n function onVisibility() {\n if (document.visibilityState === \"visible\") fetchStatus();\n }\n window.addEventListener(\"focus\", onFocus);\n document.addEventListener(\"visibilitychange\", onVisibility);\n // Engine connect/disconnect actions (e.g. the Builder disconnect button)\n // dispatch this event so dependent cards refresh without a full reload.\n window.addEventListener(\"agent-engine:configured-changed\", fetchStatus);\n return () => {\n window.removeEventListener(\"focus\", onFocus);\n document.removeEventListener(\"visibilitychange\", onVisibility);\n window.removeEventListener(\n \"agent-engine:configured-changed\",\n fetchStatus,\n );\n };\n }, [fetchStatus]);\n\n return { status, loading, refetch: fetchStatus };\n}\n\n// ─── useBuilderConnectFlow ──────────────────────────────────────────────────\n//\n// Shared state machine for the \"open Builder CLI-auth popup + poll\n// /builder/status until credentials land\" interaction. Replaces three\n// near-duplicate inline implementations: `BuilderCliAuthMethod` in\n// OnboardingPanel, `ConnectBuilderCard`, and `BuilderConnectCta` in\n// AssistantChat. Each consumer supplies its own popup URL / completion\n// behavior; the hook owns the polling + timeout + focus refresh.\n//\n// `popupUrl` is what we pass to `window.open`. The default\n// `/_agent-native/builder/connect` is a server-side 302 to the real\n// cli-auth URL — using it keeps the click handler synchronous so popup\n// blockers don't downgrade the open to same-tab navigation. Pass an\n// explicit `popupUrl` (e.g. the already-computed cli-auth URL) if your\n// caller already has it in hand.\n\nexport interface BuilderConnectFlowOptions {\n /** URL to synchronously open on start(). Defaults to the 302 shortcut. */\n popupUrl?: string;\n /** Low-cardinality label for the UI surface that opened Builder connect. */\n trackingSource?: string;\n /** Invoked after the status poll first sees `configured: true`. */\n onConnected?: (state: { orgName: string | null }) => void | Promise<void>;\n}\n\nexport interface BuilderConnectFlow {\n configured: boolean;\n /**\n * True when the deploy has BUILDER_PRIVATE_KEY set as a fallback. Connect\n * is still available so users can override the fallback with their own\n * Builder account.\n */\n envManaged: boolean;\n /**\n * True when the server has a Builder branch project configured for this\n * request. When false, the card surfaces a waitlist CTA instead of a Send\n * button.\n */\n builderEnabled: boolean;\n orgName: string | null;\n connecting: boolean;\n error: string | null;\n /**\n * True once the first `/builder/status` fetch has completed (successfully\n * or not). Consumers that accept an `initialConfigured` prop (e.g. agent\n * tool-call results rendered with server-side state) should treat\n * `configured`/`orgName` as authoritative only once this flips true —\n * otherwise the hook's starting `false` defaults would cause a flash\n * back to \"Connect Builder\" on first paint.\n */\n hasFetchedStatus: boolean;\n /** Open the popup and begin polling. Must be called from a user-gesture handler. */\n start: () => void;\n}\n\nconst POLL_INTERVAL_MS = 2000;\nconst POLL_TIMEOUT_MS = 5 * 60 * 1000;\nconst BUILDER_CONNECT_PARAM = \"_an_connect\";\nconst BUILDER_STATE_PARAM = \"_an_state\";\nconst STATUS_CONNECT_URL_TTL_MS = 9 * 60 * 1000;\n\nfunction isAgentNativeDesktop() {\n if (typeof navigator === \"undefined\") return false;\n return /AgentNativeDesktop/i.test(navigator.userAgent || \"\");\n}\n\nfunction hasSignedConnectToken(url: string | null | undefined): boolean {\n if (!url || typeof window === \"undefined\") return false;\n try {\n return new URL(url, window.location.origin).searchParams.has(\n BUILDER_CONNECT_PARAM,\n );\n } catch {\n return false;\n }\n}\n\nfunction hasSignedCallbackState(url: string | null | undefined): boolean {\n if (!url || typeof window === \"undefined\") return false;\n try {\n const parsed = new URL(url, window.location.origin);\n const redirectUrl = parsed.searchParams.get(\"redirect_url\");\n if (!redirectUrl) return false;\n return new URL(redirectUrl).searchParams.has(BUILDER_STATE_PARAM);\n } catch {\n return false;\n }\n}\n\nfunction isFreshSignedConnectUrl(\n url: string | null,\n fetchedAt: number | null,\n): url is string {\n return (\n (hasSignedConnectToken(url) || hasSignedCallbackState(url)) &&\n typeof fetchedAt === \"number\" &&\n Date.now() - fetchedAt < STATUS_CONNECT_URL_TTL_MS\n );\n}\n\nfunction showBuilderConnectPopupPlaceholder(opened: Window) {\n try {\n opened.opener = null;\n } catch {\n // Best effort only. We still hold the WindowProxy so the parent can\n // navigate the blank popup after refreshing the signed connect URL.\n }\n try {\n opened.document.title = \"Opening Builder.io\";\n opened.document.body.style.margin = \"0\";\n opened.document.body.style.background = \"#111\";\n opened.document.body.style.color = \"#ddd\";\n opened.document.body.style.fontFamily =\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif';\n opened.document.body.style.display = \"flex\";\n opened.document.body.style.alignItems = \"center\";\n opened.document.body.style.justifyContent = \"center\";\n opened.document.body.style.height = \"100vh\";\n opened.document.body.textContent = \"Opening Builder.io...\";\n } catch {\n // Popup may already be cross-origin or browser may block document writes.\n }\n}\n\nfunction navigateBuilderConnectPopup(opened: Window, url: string): boolean {\n try {\n opened.location.href = url;\n return true;\n } catch {\n try {\n opened.close();\n } catch {\n // Ignore close failures.\n }\n return false;\n }\n}\n\nfunction notifyAgentEngineConfiguredChanged(source: string) {\n if (typeof window === \"undefined\") return;\n window.dispatchEvent(\n new CustomEvent(\"agent-engine:configured-changed\", {\n detail: { source },\n }),\n );\n}\n\nfunction isTrustedBuilderConnectMessageOrigin(origin: string): boolean {\n if (typeof window !== \"undefined\" && origin === window.location.origin) {\n return true;\n }\n try {\n const hostname = new URL(origin).hostname.toLowerCase();\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"builder.io\" ||\n hostname.endsWith(\".builder.io\") ||\n hostname === \"builder.my\" ||\n hostname.endsWith(\".builder.my\") ||\n hostname === \"builderio.xyz\" ||\n hostname.endsWith(\".builderio.xyz\") ||\n hostname === \"builderio.dev\" ||\n hostname.endsWith(\".builderio.dev\") ||\n hostname === \"builder.codes\" ||\n hostname.endsWith(\".builder.codes\")\n );\n } catch {\n return false;\n }\n}\n\nexport interface OpenBuilderConnectPopupOptions {\n url?: string;\n source?: string;\n features?: string;\n}\n\nexport function openBuilderConnectPopup({\n url,\n source = \"builder_connect\",\n features = \"noopener,noreferrer\",\n}: OpenBuilderConnectPopupOptions = {}): Window | null {\n if (typeof window === \"undefined\") return null;\n const origin = getCallbackOrigin() || window.location.origin;\n const href =\n url ??\n new URL(agentNativePath(\"/_agent-native/builder/connect\"), origin).href;\n const connectUrlKind = url ? \"provided\" : \"default\";\n trackEvent(\"builder connect clicked\", {\n feature: \"builder\",\n stage: \"client\",\n source,\n connect_url_kind: connectUrlKind,\n });\n try {\n const opened = window.open(href, \"_blank\", features);\n if (!opened && !/AgentNativeDesktop/i.test(navigator.userAgent || \"\")) {\n trackEvent(\"builder connect popup blocked\", {\n feature: \"builder\",\n stage: \"client\",\n source,\n connect_url_kind: connectUrlKind,\n });\n }\n return opened;\n } catch {\n trackEvent(\"builder connect failed\", {\n feature: \"builder\",\n stage: \"client\",\n reason: \"popup_open_exception\",\n source,\n connect_url_kind: connectUrlKind,\n });\n return null;\n }\n}\n\nexport function useBuilderConnectFlow(\n opts: BuilderConnectFlowOptions = {},\n): BuilderConnectFlow {\n const {\n popupUrl,\n trackingSource = \"builder_connect_flow\",\n onConnected,\n } = opts;\n const [configured, setConfigured] = useState(false);\n const [envManaged, setEnvManaged] = useState(false);\n const [builderEnabled, setBuilderEnabled] = useState(false);\n const [orgName, setOrgName] = useState<string | null>(null);\n const [connecting, setConnecting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [hasFetchedStatus, setHasFetchedStatus] = useState(false);\n const [statusConnectUrl, setStatusConnectUrl] = useState<string | null>(null);\n // When statusConnectUrl was last fetched. The server signs the embedded\n // _an_connect token with a 10-minute TTL; using an older URL fails the\n // cross-origin popup gate. Track freshness so start() can either use a\n // still-good direct URL (desktop) or refresh a new one inside the popup\n // gesture path (browser/editor embeds).\n const statusConnectUrlAtRef = useRef<number | null>(null);\n const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const mountedRef = useRef(true);\n const notifiedConnectedRef = useRef(false);\n // Keep onConnected in a ref so start() doesn't need to re-create when the\n // caller passes an inline arrow function.\n const onConnectedRef = useRef(onConnected);\n onConnectedRef.current = onConnected;\n\n const stopPoll = useCallback(() => {\n if (pollRef.current) {\n clearInterval(pollRef.current);\n pollRef.current = null;\n }\n }, []);\n\n const fetchStatus = useCallback(async () => {\n const origin = getCallbackOrigin() || window.location.origin;\n try {\n const r = await fetch(\n new URL(agentNativePath(\"/_agent-native/builder/status\"), origin).href,\n );\n if (!r.ok) return null;\n return (await r.json()) as {\n configured: boolean;\n envManaged?: boolean;\n builderEnabled?: boolean;\n orgName?: string | null;\n connectUrl?: string;\n cliAuthUrl?: string;\n credentialSource?: \"user\" | \"org\" | \"env\";\n connectError?: { message: string; at: number };\n };\n } catch {\n return null;\n }\n }, []);\n\n // Initial fetch + focus/visibility refresh so if the user completed the\n // flow in another tab (or a downgraded same-tab nav) we notice it. Also\n // listen for `agent-engine:configured-changed` so a Disconnect click in\n // Settings propagates to any connect-CTA cards rendered elsewhere in\n // the app without waiting for the next focus event.\n useEffect(() => {\n mountedRef.current = true;\n let cancelled = false;\n const refresh = async () => {\n const s = await fetchStatus();\n if (cancelled || !mountedRef.current) return;\n // Flip `hasFetchedStatus` even when the fetch failed — the caller's\n // \"use initial props until the hook has an answer\" pattern wants to\n // stop waiting after we've tried, regardless of network outcome.\n setHasFetchedStatus(true);\n if (!s) return;\n setConfigured(!!s.configured);\n setEnvManaged(!!s.envManaged);\n setBuilderEnabled(!!s.builderEnabled);\n const nextConnectUrl = s.cliAuthUrl ?? s.connectUrl ?? null;\n setStatusConnectUrl(nextConnectUrl);\n statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;\n const org = s.orgName ?? null;\n setOrgName(org);\n if (s.configured && !notifiedConnectedRef.current) {\n notifiedConnectedRef.current = true;\n notifyAgentEngineConfiguredChanged(\"builder-status\");\n try {\n await onConnectedRef.current?.({ orgName: org });\n } catch {\n // The caller's callback is a UI convenience; status is already set.\n }\n } else if (!s.configured) {\n notifiedConnectedRef.current = false;\n }\n };\n refresh();\n const onVisible = () => {\n if (document.visibilityState === \"visible\") refresh();\n };\n window.addEventListener(\"focus\", refresh);\n document.addEventListener(\"visibilitychange\", onVisible);\n window.addEventListener(\"agent-engine:configured-changed\", refresh);\n return () => {\n cancelled = true;\n mountedRef.current = false;\n window.removeEventListener(\"focus\", refresh);\n document.removeEventListener(\"visibilitychange\", onVisible);\n window.removeEventListener(\"agent-engine:configured-changed\", refresh);\n stopPoll();\n };\n }, [fetchStatus, stopPoll]);\n\n const start = useCallback(() => {\n stopPoll();\n setConnecting(true);\n setError(null);\n\n // Open SYNCHRONOUSLY inside the caller's click handler — any await\n // before window.open lets the user-gesture token expire, which causes\n // popup blockers to block entirely or fall back to same-tab navigation.\n const origin = getCallbackOrigin() || window.location.origin;\n const cachedFreshUrl = isFreshSignedConnectUrl(\n statusConnectUrl,\n statusConnectUrlAtRef.current,\n )\n ? statusConnectUrl\n : null;\n // popupUrl prop (e.g. from a chat ConnectBuilderCard) may be a signed\n // URL that was minted minutes-to-days ago — we don't have a mint\n // timestamp for it, so we can't be sure it's still within the signed\n // TTL. Use it as a *direct* popup URL only for desktop (where the\n // about:blank refresh-in-popup path doesn't exist); on web, fall\n // through to the refresh-in-popup branch so a stale prop URL doesn't\n // open an expired popup.\n const signedPropUrl = hasSignedConnectToken(popupUrl) ? popupUrl : null;\n const signedCliPropUrl = hasSignedCallbackState(popupUrl) ? popupUrl : null;\n const fallbackUrl = new URL(\n agentNativePath(\"/_agent-native/builder/connect\"),\n origin,\n ).href;\n const hasDirectSignedUrl = Boolean(cachedFreshUrl);\n const directUrl =\n cachedFreshUrl ?? signedCliPropUrl ?? signedPropUrl ?? fallbackUrl;\n\n if (isAgentNativeDesktop()) {\n const opened = openBuilderConnectPopup({\n url: directUrl,\n source: trackingSource,\n });\n if (!opened) {\n // Agent Native Desktop handles the popup in Electron and reports\n // null to the embedded webview, so null is not a blocker here.\n }\n } else if (hasDirectSignedUrl) {\n const opened = openBuilderConnectPopup({\n url: directUrl,\n source: trackingSource,\n features: \"width=600,height=700\",\n });\n if (!opened) {\n setConnecting(false);\n setError(\"Couldn't open Builder. Allow popups and try again.\");\n return;\n }\n } else {\n const opened = openBuilderConnectPopup({\n url: \"about:blank\",\n source: trackingSource,\n features: \"width=600,height=700\",\n });\n if (!opened) {\n setConnecting(false);\n setError(\"Couldn't open Builder. Allow popups and try again.\");\n return;\n }\n showBuilderConnectPopupPlaceholder(opened);\n void (async () => {\n const s = await fetchStatus();\n if (!mountedRef.current) {\n try {\n opened.close();\n } catch {\n // Ignore close failures.\n }\n return;\n }\n if (s) {\n setHasFetchedStatus(true);\n setConfigured(!!s.configured);\n setEnvManaged(!!s.envManaged);\n setBuilderEnabled(!!s.builderEnabled);\n const nextConnectUrl = s.cliAuthUrl ?? s.connectUrl ?? null;\n setStatusConnectUrl(nextConnectUrl);\n statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;\n setOrgName(s.orgName ?? null);\n }\n\n const freshUrl =\n (s?.cliAuthUrl && hasSignedCallbackState(s.cliAuthUrl)\n ? s.cliAuthUrl\n : null) ??\n (s?.connectUrl && hasSignedConnectToken(s.connectUrl)\n ? s.connectUrl\n : null) ??\n cachedFreshUrl;\n if (!freshUrl) {\n try {\n opened.close();\n } catch {\n // Ignore close failures.\n }\n stopPoll();\n setConnecting(false);\n setError(\n \"Couldn't start Builder connect. Refresh this page and try again.\",\n );\n return;\n }\n if (!navigateBuilderConnectPopup(opened, freshUrl)) {\n stopPoll();\n setConnecting(false);\n setError(\n \"Couldn't navigate the Builder popup. Allow popups and try again.\",\n );\n }\n })();\n }\n\n const started = Date.now();\n pollRef.current = setInterval(async () => {\n const s = await fetchStatus();\n if (!mountedRef.current) {\n stopPoll();\n return;\n }\n if (s?.configured) {\n stopPoll();\n setConfigured(true);\n setEnvManaged(!!s.envManaged);\n setBuilderEnabled(!!s.builderEnabled);\n const nextConnectUrl = s.cliAuthUrl ?? s.connectUrl ?? null;\n setStatusConnectUrl(nextConnectUrl);\n statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;\n const org = s.orgName ?? null;\n setOrgName(org);\n setConnecting(false);\n notifiedConnectedRef.current = true;\n notifyAgentEngineConfiguredChanged(\"builder-connect\");\n try {\n await onConnectedRef.current?.({ orgName: org });\n } catch {\n // Consumer's callback failed; we've already flipped the UI state\n // to connected. Swallow so we don't re-arm the flow.\n }\n } else if (s?.connectError?.message) {\n // OAuth callback ran but writeBuilderCredentials threw — surface the\n // real error instead of letting the user wait 5 minutes for timeout.\n stopPoll();\n setConnecting(false);\n setError(\n `Couldn't save Builder credentials: ${s.connectError.message}. Try again or contact support.`,\n );\n } else if (Date.now() - started > POLL_TIMEOUT_MS) {\n stopPoll();\n setConnecting(false);\n trackEvent(\"builder connect failed\", {\n feature: \"builder\",\n stage: \"client\",\n reason: \"timeout\",\n source: trackingSource,\n });\n setError(\n \"Didn't hear back from Builder in 5 minutes. Allow popups and try again.\",\n );\n }\n }, POLL_INTERVAL_MS);\n }, [fetchStatus, popupUrl, statusConnectUrl, stopPoll, trackingSource]);\n\n // Popup-side fast path: the callback page broadcasts a message so we stop\n // polling immediately rather than waiting for the next 2s tick.\n //\n // We listen on BroadcastChannel (same-origin, works with noopener popups)\n // AND on window.message (legacy path for environments without BC or for\n // popups that still have opener access). Both paths are safe to have open\n // simultaneously \\u2014 the first one to fire wins and the error is deduplicated\n // by the stopPoll() call which is idempotent.\n useEffect(() => {\n let channel: BroadcastChannel | null = null;\n const handleError = (message: string) => {\n stopPoll();\n setConnecting(false);\n setError(`Couldn't save Builder credentials: ${message}.`);\n };\n const handleSuccess = async () => {\n const s = await fetchStatus();\n if (!mountedRef.current || !s?.configured) return;\n stopPoll();\n setHasFetchedStatus(true);\n setConfigured(true);\n setEnvManaged(!!s.envManaged);\n setBuilderEnabled(!!s.builderEnabled);\n const nextConnectUrl = s.cliAuthUrl ?? s.connectUrl ?? null;\n setStatusConnectUrl(nextConnectUrl);\n statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;\n const org = s.orgName ?? null;\n setOrgName(org);\n setConnecting(false);\n notifiedConnectedRef.current = true;\n notifyAgentEngineConfiguredChanged(\"builder-connect-message\");\n try {\n await onConnectedRef.current?.({ orgName: org });\n } catch {\n // The caller's callback is a UI convenience; status is already set.\n }\n };\n\n try {\n channel = new BroadcastChannel(`builder-connect:${window.location.host}`);\n channel.onmessage = (e: MessageEvent) => {\n const data = e.data as { type?: string; message?: string } | undefined;\n if (data?.type === \"builder-connect-success\") {\n void handleSuccess();\n return;\n }\n if (data?.type === \"builder-connect-error\") {\n if (typeof data.message !== \"string\" || !data.message) return;\n handleError(data.message);\n }\n };\n } catch {\n // BroadcastChannel not available (rare) \\u2014 fall through to postMessage.\n }\n\n const handler = (e: MessageEvent) => {\n if (!isTrustedBuilderConnectMessageOrigin(e.origin)) return;\n const data = e.data as { type?: string; message?: string } | undefined;\n if (data?.type === \"builder-connect-success\") {\n void handleSuccess();\n return;\n }\n if (data?.type === \"builder-connect-error\") {\n if (typeof data.message !== \"string\" || !data.message) return;\n handleError(data.message);\n }\n };\n window.addEventListener(\"message\", handler);\n\n return () => {\n channel?.close();\n window.removeEventListener(\"message\", handler);\n };\n }, [fetchStatus, stopPoll]);\n\n return {\n configured,\n envManaged,\n builderEnabled,\n orgName,\n connecting,\n error,\n hasFetchedStatus,\n start,\n };\n}\n"]}
1
+ {"version":3,"file":"useBuilderStatus.js","sourceRoot":"","sources":["../../../src/client/settings/useBuilderStatus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAqC7C;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAuB,IAAI,CAAC,CAAC;IACjE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE7C,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACzC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,+BAA+B,CAAC,CAAC,CAAC;YAC1E,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,SAAS,CAAC,IAAI,CAAC,CAAC;gBAChB,OAAO;YACT,CAAC;YACD,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,EAAE,CAAC;QAEd,SAAS,OAAO;YACd,WAAW,EAAE,CAAC;QAChB,CAAC;QACD,SAAS,YAAY;YACnB,IAAI,QAAQ,CAAC,eAAe,KAAK,SAAS;gBAAE,WAAW,EAAE,CAAC;QAC5D,CAAC;QACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;QAC5D,yEAAyE;QACzE,wEAAwE;QACxE,MAAM,CAAC,gBAAgB,CAAC,iCAAiC,EAAE,WAAW,CAAC,CAAC;QACxE,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;YAC/D,MAAM,CAAC,mBAAmB,CACxB,iCAAiC,EACjC,WAAW,CACZ,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;AACnD,CAAC;AAyDD,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACtC,MAAM,qBAAqB,GAAG,aAAa,CAAC;AAC5C,MAAM,mBAAmB,GAAG,WAAW,CAAC;AACxC,MAAM,yBAAyB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhD,SAAS,oBAAoB;IAC3B,IAAI,OAAO,SAAS,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,qBAAqB,CAAC,GAA8B;IAC3D,IAAI,CAAC,GAAG,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,GAAG,CAC1D,qBAAqB,CACtB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,GAA8B;IAC5D,IAAI,CAAC,GAAG,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC5D,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QAC/B,OAAO,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACpE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAC9B,GAAkB,EAClB,SAAwB;IAExB,OAAO,CACL,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,sBAAsB,CAAC,GAAG,CAAC,CAAC;QAC3D,OAAO,SAAS,KAAK,QAAQ;QAC7B,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,yBAAyB,CACnD,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC5B,KAAkD,EAClD,SAAwB;IAExB,IAAI,CAAC,KAAK,EAAE,OAAO;QAAE,OAAO,KAAK,CAAC;IAClC,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,KAAK,CAAC,EAAE,IAAI,SAAS,GAAG,IAAI,CAAC;AACtE,CAAC;AAED,SAAS,kCAAkC,CAAC,MAAc;IACxD,IAAI,CAAC;QACH,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,oEAAoE;IACtE,CAAC;IACD,IAAI,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,KAAK,GAAG,oBAAoB,CAAC;QAC7C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC;QAC/C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC;QAC1C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU;YACnC,2DAA2D,CAAC;QAC9D,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QAC5C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;QACjD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC;QACrD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;QAC5C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,GAAG,uBAAuB,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;IAC5E,CAAC;AACH,CAAC;AAED,SAAS,2BAA2B,CAAC,MAAc,EAAE,GAAW;IAC9D,IAAI,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,kCAAkC,CAAC,MAAc;IACxD,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO;IAC1C,MAAM,CAAC,aAAa,CAClB,IAAI,WAAW,CAAC,iCAAiC,EAAE;QACjD,MAAM,EAAE,EAAE,MAAM,EAAE;KACnB,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAS,oCAAoC,CAAC,MAAc;IAC1D,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QACxD,OAAO,CACL,QAAQ,KAAK,WAAW;YACxB,QAAQ,KAAK,WAAW;YACxB,QAAQ,KAAK,KAAK;YAClB,QAAQ,KAAK,YAAY;YACzB,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC;YAChC,QAAQ,KAAK,YAAY;YACzB,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC;YAChC,QAAQ,KAAK,eAAe;YAC5B,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YACnC,QAAQ,KAAK,eAAe;YAC5B,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YACnC,QAAQ,KAAK,eAAe;YAC5B,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YACnC,QAAQ,KAAK,kBAAkB;YAC/B,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CACvC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAQD,MAAM,UAAU,uBAAuB,CAAC,EACtC,GAAG,EACH,MAAM,GAAG,iBAAiB,EAC1B,QAAQ,GAAG,qBAAqB,MACE,EAAE;IACpC,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,MAAM,GAAG,iBAAiB,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IAC7D,MAAM,IAAI,GACR,GAAG;QACH,IAAI,GAAG,CAAC,eAAe,CAAC,gCAAgC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC;IAC1E,MAAM,cAAc,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACpD,UAAU,CAAC,yBAAyB,EAAE;QACpC,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,QAAQ;QACf,MAAM;QACN,gBAAgB,EAAE,cAAc;KACjC,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,CAAC;YACtE,UAAU,CAAC,+BAA+B,EAAE;gBAC1C,OAAO,EAAE,SAAS;gBAClB,KAAK,EAAE,QAAQ;gBACf,MAAM;gBACN,gBAAgB,EAAE,cAAc;aACjC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,CAAC,wBAAwB,EAAE;YACnC,OAAO,EAAE,SAAS;YAClB,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,sBAAsB;YAC9B,MAAM;YACN,gBAAgB,EAAE,cAAc;SACjC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAAkC,EAAE;IAEpC,MAAM,EACJ,QAAQ,EACR,cAAc,GAAG,sBAAsB,EACvC,WAAW,GACZ,GAAG,IAAI,CAAC;IACT,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC5D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChE,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC9E,wEAAwE;IACxE,uEAAuE;IACvE,uEAAuE;IACvE,wEAAwE;IACxE,wCAAwC;IACxC,MAAM,qBAAqB,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,MAAM,CAAwC,IAAI,CAAC,CAAC;IACpE,MAAM,mBAAmB,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,oBAAoB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3C,0EAA0E;IAC1E,0CAA0C;IAC1C,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3C,cAAc,CAAC,OAAO,GAAG,WAAW,CAAC;IAErC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;QAChC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC/B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QACzB,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACzC,MAAM,MAAM,GAAG,iBAAiB,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC7D,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,KAAK,CACnB,IAAI,GAAG,CAAC,eAAe,CAAC,+BAA+B,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CACvE,CAAC;YACF,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YACvB,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAUrB,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,wEAAwE;IACxE,wEAAwE;IACxE,wEAAwE;IACxE,qEAAqE;IACrE,oDAAoD;IACpD,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC1B,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;YACzB,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,IAAI,SAAS,IAAI,CAAC,UAAU,CAAC,OAAO;gBAAE,OAAO;YAC7C,oEAAoE;YACpE,oEAAoE;YACpE,iEAAiE;YACjE,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAC1B,IAAI,CAAC,CAAC;gBAAE,OAAO;YACf,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAC9B,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAC9B,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;YACtC,MAAM,cAAc,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC;YAC5D,mBAAmB,CAAC,cAAc,CAAC,CAAC;YACpC,qBAAqB,CAAC,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YACnE,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC;YAC9B,UAAU,CAAC,GAAG,CAAC,CAAC;YAChB,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;gBACjB,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;YACrC,CAAC;YACD,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,CAAC;gBAClD,oBAAoB,CAAC,OAAO,GAAG,IAAI,CAAC;gBACpC,kCAAkC,CAAC,gBAAgB,CAAC,CAAC;gBACrD,IAAI,CAAC;oBACH,MAAM,cAAc,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;gBACnD,CAAC;gBAAC,MAAM,CAAC;oBACP,oEAAoE;gBACtE,CAAC;YACH,CAAC;iBAAM,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;gBACzB,oBAAoB,CAAC,OAAO,GAAG,KAAK,CAAC;YACvC,CAAC;YACD,uEAAuE;YACvE,uEAAuE;YACvE,0CAA0C;YAC1C,MAAM,sBAAsB,GAAG,mBAAmB,CAAC,OAAO,CAAC;YAC3D,IAAI,qBAAqB,CAAC,CAAC,CAAC,YAAY,EAAE,sBAAsB,CAAC,EAAE,CAAC;gBAClE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;iBAAM,IAAI,CAAC,sBAAsB,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC;gBAC3D,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;iBAAM,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;gBACxB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;QACF,OAAO,EAAE,CAAC;QACV,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,IAAI,QAAQ,CAAC,eAAe,KAAK,SAAS;gBAAE,OAAO,EAAE,CAAC;QACxD,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;QACzD,MAAM,CAAC,gBAAgB,CAAC,iCAAiC,EAAE,OAAO,CAAC,CAAC;QACpE,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;YACjB,UAAU,CAAC,OAAO,GAAG,KAAK,CAAC;YAC3B,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;YAC5D,MAAM,CAAC,mBAAmB,CAAC,iCAAiC,EAAE,OAAO,CAAC,CAAC;YACvE,QAAQ,EAAE,CAAC;QACb,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE5B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,QAAQ,EAAE,CAAC;QACX,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,mBAAmB,CAAC,OAAO,GAAG,OAAO,CAAC;QACtC,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,mEAAmE;QACnE,sEAAsE;QACtE,wEAAwE;QACxE,MAAM,MAAM,GAAG,iBAAiB,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC7D,MAAM,cAAc,GAAG,uBAAuB,CAC5C,gBAAgB,EAChB,qBAAqB,CAAC,OAAO,CAC9B;YACC,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,IAAI,CAAC;QACT,sEAAsE;QACtE,iEAAiE;QACjE,qEAAqE;QACrE,kEAAkE;QAClE,iEAAiE;QACjE,qEAAqE;QACrE,yBAAyB;QACzB,MAAM,aAAa,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;QACxE,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5E,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,eAAe,CAAC,gCAAgC,CAAC,EACjD,MAAM,CACP,CAAC,IAAI,CAAC;QACP,MAAM,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;QACnD,MAAM,SAAS,GACb,cAAc,IAAI,gBAAgB,IAAI,aAAa,IAAI,WAAW,CAAC;QAErE,IAAI,oBAAoB,EAAE,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,uBAAuB,CAAC;gBACrC,GAAG,EAAE,SAAS;gBACd,MAAM,EAAE,cAAc;aACvB,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,iEAAiE;gBACjE,+DAA+D;YACjE,CAAC;QACH,CAAC;aAAM,IAAI,kBAAkB,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,uBAAuB,CAAC;gBACrC,GAAG,EAAE,SAAS;gBACd,MAAM,EAAE,cAAc;gBACtB,QAAQ,EAAE,sBAAsB;aACjC,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;gBACnC,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,QAAQ,CAAC,oDAAoD,CAAC,CAAC;gBAC/D,OAAO;YACT,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,uBAAuB,CAAC;gBACrC,GAAG,EAAE,aAAa;gBAClB,MAAM,EAAE,cAAc;gBACtB,QAAQ,EAAE,sBAAsB;aACjC,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;gBACnC,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,QAAQ,CAAC,oDAAoD,CAAC,CAAC;gBAC/D,OAAO;YACT,CAAC;YACD,kCAAkC,CAAC,MAAM,CAAC,CAAC;YAC3C,KAAK,CAAC,KAAK,IAAI,EAAE;gBACf,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC;gBAC9B,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;oBACxB,IAAI,CAAC;wBACH,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,CAAC;oBAAC,MAAM,CAAC;wBACP,yBAAyB;oBAC3B,CAAC;oBACD,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,EAAE,CAAC;oBACN,mBAAmB,CAAC,IAAI,CAAC,CAAC;oBAC1B,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;oBAC9B,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;oBAC9B,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;oBACtC,MAAM,cAAc,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC;oBAC5D,mBAAmB,CAAC,cAAc,CAAC,CAAC;oBACpC,qBAAqB,CAAC,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;oBACnE,UAAU,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;gBAChC,CAAC;gBAED,MAAM,QAAQ,GACZ,CAAC,CAAC,EAAE,UAAU,IAAI,sBAAsB,CAAC,CAAC,CAAC,UAAU,CAAC;oBACpD,CAAC,CAAC,CAAC,CAAC,UAAU;oBACd,CAAC,CAAC,IAAI,CAAC;oBACT,CAAC,CAAC,EAAE,UAAU,IAAI,qBAAqB,CAAC,CAAC,CAAC,UAAU,CAAC;wBACnD,CAAC,CAAC,CAAC,CAAC,UAAU;wBACd,CAAC,CAAC,IAAI,CAAC;oBACT,cAAc,CAAC;gBACjB,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,IAAI,CAAC;wBACH,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,CAAC;oBAAC,MAAM,CAAC;wBACP,yBAAyB;oBAC3B,CAAC;oBACD,QAAQ,EAAE,CAAC;oBACX,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;oBACnC,aAAa,CAAC,KAAK,CAAC,CAAC;oBACrB,QAAQ,CACN,kEAAkE,CACnE,CAAC;oBACF,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,2BAA2B,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;oBACnD,QAAQ,EAAE,CAAC;oBACX,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;oBACnC,aAAa,CAAC,KAAK,CAAC,CAAC;oBACrB,QAAQ,CACN,kEAAkE,CACnE,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;QAED,OAAO,CAAC,OAAO,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YACvC,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;gBACxB,QAAQ,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YACD,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;gBAClB,QAAQ,EAAE,CAAC;gBACX,aAAa,CAAC,IAAI,CAAC,CAAC;gBACpB,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;gBAC9B,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;gBACtC,MAAM,cAAc,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC;gBAC5D,mBAAmB,CAAC,cAAc,CAAC,CAAC;gBACpC,qBAAqB,CAAC,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBACnE,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC;gBAC9B,UAAU,CAAC,GAAG,CAAC,CAAC;gBAChB,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;gBACnC,oBAAoB,CAAC,OAAO,GAAG,IAAI,CAAC;gBACpC,kCAAkC,CAAC,iBAAiB,CAAC,CAAC;gBACtD,IAAI,CAAC;oBACH,MAAM,cAAc,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;gBACnD,CAAC;gBAAC,MAAM,CAAC;oBACP,iEAAiE;oBACjE,qDAAqD;gBACvD,CAAC;YACH,CAAC;iBAAM,IAAI,qBAAqB,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC3D,qEAAqE;gBACrE,qEAAqE;gBACrE,QAAQ,EAAE,CAAC;gBACX,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;gBACnC,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,QAAQ,CACN,sCAAsC,CAAC,CAAC,YAAY,CAAC,OAAO,iCAAiC,CAC9F,CAAC;YACJ,CAAC;iBAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,eAAe,EAAE,CAAC;gBAClD,QAAQ,EAAE,CAAC;gBACX,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;gBACnC,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,UAAU,CAAC,wBAAwB,EAAE;oBACnC,OAAO,EAAE,SAAS;oBAClB,KAAK,EAAE,QAAQ;oBACf,MAAM,EAAE,SAAS;oBACjB,MAAM,EAAE,cAAc;iBACvB,CAAC,CAAC;gBACH,QAAQ,CACN,yEAAyE,CAC1E,CAAC;YACJ,CAAC;QACH,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACvB,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC;IAExE,0EAA0E;IAC1E,gEAAgE;IAChE,EAAE;IACF,0EAA0E;IAC1E,wEAAwE;IACxE,0EAA0E;IAC1E,iFAAiF;IACjF,8CAA8C;IAC9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,GAA4B,IAAI,CAAC;QAC5C,MAAM,WAAW,GAAG,CAAC,OAAe,EAAE,EAAE;YACtC,QAAQ,EAAE,CAAC;YACX,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;YACnC,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,QAAQ,CAAC,sCAAsC,OAAO,GAAG,CAAC,CAAC;QAC7D,CAAC,CAAC;QACF,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;YAC/B,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,UAAU;gBAAE,OAAO;YAClD,QAAQ,EAAE,CAAC;YACX,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAC1B,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAC9B,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;YACtC,MAAM,cAAc,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC;YAC5D,mBAAmB,CAAC,cAAc,CAAC,CAAC;YACpC,qBAAqB,CAAC,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YACnE,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC;YAC9B,UAAU,CAAC,GAAG,CAAC,CAAC;YAChB,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;YACnC,oBAAoB,CAAC,OAAO,GAAG,IAAI,CAAC;YACpC,kCAAkC,CAAC,yBAAyB,CAAC,CAAC;YAC9D,IAAI,CAAC;gBACH,MAAM,cAAc,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;YACnD,CAAC;YAAC,MAAM,CAAC;gBACP,oEAAoE;YACtE,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,gBAAgB,CAAC,mBAAmB,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1E,OAAO,CAAC,SAAS,GAAG,CAAC,CAAe,EAAE,EAAE;gBACtC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAuD,CAAC;gBACvE,IAAI,IAAI,EAAE,IAAI,KAAK,yBAAyB,EAAE,CAAC;oBAC7C,KAAK,aAAa,EAAE,CAAC;oBACrB,OAAO;gBACT,CAAC;gBACD,IAAI,IAAI,EAAE,IAAI,KAAK,uBAAuB,EAAE,CAAC;oBAC3C,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO;wBAAE,OAAO;oBAC9D,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,4EAA4E;QAC9E,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,CAAe,EAAE,EAAE;YAClC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC,MAAM,CAAC;gBAAE,OAAO;YAC5D,MAAM,IAAI,GAAG,CAAC,CAAC,IAAuD,CAAC;YACvE,IAAI,IAAI,EAAE,IAAI,KAAK,yBAAyB,EAAE,CAAC;gBAC7C,KAAK,aAAa,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,IAAI,IAAI,EAAE,IAAI,KAAK,uBAAuB,EAAE,CAAC;gBAC3C,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO;oBAAE,OAAO;gBAC9D,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAE5C,OAAO,GAAG,EAAE;YACV,OAAO,EAAE,KAAK,EAAE,CAAC;YACjB,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE5B,OAAO;QACL,UAAU;QACV,UAAU;QACV,cAAc;QACd,OAAO;QACP,UAAU;QACV,KAAK;QACL,gBAAgB;QAChB,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport { getCallbackOrigin } from \"../frame.js\";\nimport { trackEvent } from \"../analytics.js\";\n\nexport interface BuilderStatus {\n configured: boolean;\n builderEnabled: boolean;\n /**\n * True when `BUILDER_PRIVATE_KEY` is set at the deploy level. This is a\n * fallback credential; per-user/org Builder connections are still allowed\n * and take precedence for that request.\n */\n envManaged?: boolean;\n credentialSource?: \"user\" | \"org\" | \"workspace\" | \"env\";\n connectUrl: string;\n cliAuthUrl?: string;\n appHost: string;\n apiHost: string;\n branchProjectIdConfigured?: boolean;\n branchProjectId?: string;\n publicKeyConfigured: boolean;\n privateKeyConfigured: boolean;\n userId?: string;\n orgName?: string;\n orgKind?: string;\n /**\n * Set when the OAuth callback ran but failed to persist credentials.\n * Surfaced as a one-shot row by the server so the connect-flow polling\n * can stop with a clear message instead of timing out at 5min.\n */\n connectError?: { message: string; at: number };\n /**\n * Set when the currently effective Builder credential was rejected by\n * Builder's API. Unlike connectError, this describes the old credential pair\n * and should not abort a new reconnect attempt while the popup is open.\n */\n authError?: { message: string; at: number };\n}\n\n/**\n * Fetches Builder connection status from /_agent-native/builder/status.\n * Re-fetches on window focus to detect post-redirect state changes.\n */\nexport function useBuilderStatus() {\n const [status, setStatus] = useState<BuilderStatus | null>(null);\n const [loading, setLoading] = useState(true);\n\n const fetchStatus = useCallback(async () => {\n try {\n const res = await fetch(agentNativePath(\"/_agent-native/builder/status\"));\n if (!res.ok) {\n setStatus(null);\n return;\n }\n setStatus(await res.json());\n } catch {\n setStatus(null);\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n fetchStatus();\n\n function onFocus() {\n fetchStatus();\n }\n function onVisibility() {\n if (document.visibilityState === \"visible\") fetchStatus();\n }\n window.addEventListener(\"focus\", onFocus);\n document.addEventListener(\"visibilitychange\", onVisibility);\n // Engine connect/disconnect actions (e.g. the Builder disconnect button)\n // dispatch this event so dependent cards refresh without a full reload.\n window.addEventListener(\"agent-engine:configured-changed\", fetchStatus);\n return () => {\n window.removeEventListener(\"focus\", onFocus);\n document.removeEventListener(\"visibilitychange\", onVisibility);\n window.removeEventListener(\n \"agent-engine:configured-changed\",\n fetchStatus,\n );\n };\n }, [fetchStatus]);\n\n return { status, loading, refetch: fetchStatus };\n}\n\n// ─── useBuilderConnectFlow ──────────────────────────────────────────────────\n//\n// Shared state machine for the \"open Builder CLI-auth popup + poll\n// /builder/status until credentials land\" interaction. Replaces three\n// near-duplicate inline implementations: `BuilderCliAuthMethod` in\n// OnboardingPanel, `ConnectBuilderCard`, and `BuilderConnectCta` in\n// AssistantChat. Each consumer supplies its own popup URL / completion\n// behavior; the hook owns the polling + timeout + focus refresh.\n//\n// `popupUrl` is what we pass to `window.open`. The default\n// `/_agent-native/builder/connect` is a server-side 302 to the real\n// cli-auth URL — using it keeps the click handler synchronous so popup\n// blockers don't downgrade the open to same-tab navigation. Pass an\n// explicit `popupUrl` (e.g. the already-computed cli-auth URL) if your\n// caller already has it in hand.\n\nexport interface BuilderConnectFlowOptions {\n /** URL to synchronously open on start(). Defaults to the 302 shortcut. */\n popupUrl?: string;\n /** Low-cardinality label for the UI surface that opened Builder connect. */\n trackingSource?: string;\n /** Invoked after the status poll first sees `configured: true`. */\n onConnected?: (state: { orgName: string | null }) => void | Promise<void>;\n}\n\nexport interface BuilderConnectFlow {\n configured: boolean;\n /**\n * True when the deploy has BUILDER_PRIVATE_KEY set as a fallback. Connect\n * is still available so users can override the fallback with their own\n * Builder account.\n */\n envManaged: boolean;\n /**\n * True when the server has a Builder branch project configured for this\n * request. When false, the card surfaces a waitlist CTA instead of a Send\n * button.\n */\n builderEnabled: boolean;\n orgName: string | null;\n connecting: boolean;\n error: string | null;\n /**\n * True once the first `/builder/status` fetch has completed (successfully\n * or not). Consumers that accept an `initialConfigured` prop (e.g. agent\n * tool-call results rendered with server-side state) should treat\n * `configured`/`orgName` as authoritative only once this flips true —\n * otherwise the hook's starting `false` defaults would cause a flash\n * back to \"Connect Builder\" on first paint.\n */\n hasFetchedStatus: boolean;\n /** Open the popup and begin polling. Must be called from a user-gesture handler. */\n start: () => void;\n}\n\nconst POLL_INTERVAL_MS = 2000;\nconst POLL_TIMEOUT_MS = 5 * 60 * 1000;\nconst BUILDER_CONNECT_PARAM = \"_an_connect\";\nconst BUILDER_STATE_PARAM = \"_an_state\";\nconst STATUS_CONNECT_URL_TTL_MS = 9 * 60 * 1000;\n\nfunction isAgentNativeDesktop() {\n if (typeof navigator === \"undefined\") return false;\n return /AgentNativeDesktop/i.test(navigator.userAgent || \"\");\n}\n\nfunction hasSignedConnectToken(url: string | null | undefined): boolean {\n if (!url || typeof window === \"undefined\") return false;\n try {\n return new URL(url, window.location.origin).searchParams.has(\n BUILDER_CONNECT_PARAM,\n );\n } catch {\n return false;\n }\n}\n\nfunction hasSignedCallbackState(url: string | null | undefined): boolean {\n if (!url || typeof window === \"undefined\") return false;\n try {\n const parsed = new URL(url, window.location.origin);\n const redirectUrl = parsed.searchParams.get(\"redirect_url\");\n if (!redirectUrl) return false;\n return new URL(redirectUrl).searchParams.has(BUILDER_STATE_PARAM);\n } catch {\n return false;\n }\n}\n\nfunction isFreshSignedConnectUrl(\n url: string | null,\n fetchedAt: number | null,\n): url is string {\n return (\n (hasSignedConnectToken(url) || hasSignedCallbackState(url)) &&\n typeof fetchedAt === \"number\" &&\n Date.now() - fetchedAt < STATUS_CONNECT_URL_TTL_MS\n );\n}\n\nfunction isCurrentConnectError(\n error: { message: string; at: number } | undefined,\n startedAt: number | null,\n): error is { message: string; at: number } {\n if (!error?.message) return false;\n if (!startedAt) return true;\n return typeof error.at !== \"number\" || error.at >= startedAt - 1000;\n}\n\nfunction showBuilderConnectPopupPlaceholder(opened: Window) {\n try {\n opened.opener = null;\n } catch {\n // Best effort only. We still hold the WindowProxy so the parent can\n // navigate the blank popup after refreshing the signed connect URL.\n }\n try {\n opened.document.title = \"Opening Builder.io\";\n opened.document.body.style.margin = \"0\";\n opened.document.body.style.background = \"#111\";\n opened.document.body.style.color = \"#ddd\";\n opened.document.body.style.fontFamily =\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif';\n opened.document.body.style.display = \"flex\";\n opened.document.body.style.alignItems = \"center\";\n opened.document.body.style.justifyContent = \"center\";\n opened.document.body.style.height = \"100vh\";\n opened.document.body.textContent = \"Opening Builder.io...\";\n } catch {\n // Popup may already be cross-origin or browser may block document writes.\n }\n}\n\nfunction navigateBuilderConnectPopup(opened: Window, url: string): boolean {\n try {\n opened.location.href = url;\n return true;\n } catch {\n try {\n opened.close();\n } catch {\n // Ignore close failures.\n }\n return false;\n }\n}\n\nfunction notifyAgentEngineConfiguredChanged(source: string) {\n if (typeof window === \"undefined\") return;\n window.dispatchEvent(\n new CustomEvent(\"agent-engine:configured-changed\", {\n detail: { source },\n }),\n );\n}\n\nfunction isTrustedBuilderConnectMessageOrigin(origin: string): boolean {\n if (typeof window !== \"undefined\" && origin === window.location.origin) {\n return true;\n }\n try {\n const hostname = new URL(origin).hostname.toLowerCase();\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"builder.io\" ||\n hostname.endsWith(\".builder.io\") ||\n hostname === \"builder.my\" ||\n hostname.endsWith(\".builder.my\") ||\n hostname === \"builderio.xyz\" ||\n hostname.endsWith(\".builderio.xyz\") ||\n hostname === \"builderio.dev\" ||\n hostname.endsWith(\".builderio.dev\") ||\n hostname === \"builder.codes\" ||\n hostname.endsWith(\".builder.codes\") ||\n hostname === \"agent-native.com\" ||\n hostname.endsWith(\".agent-native.com\")\n );\n } catch {\n return false;\n }\n}\n\nexport interface OpenBuilderConnectPopupOptions {\n url?: string;\n source?: string;\n features?: string;\n}\n\nexport function openBuilderConnectPopup({\n url,\n source = \"builder_connect\",\n features = \"noopener,noreferrer\",\n}: OpenBuilderConnectPopupOptions = {}): Window | null {\n if (typeof window === \"undefined\") return null;\n const origin = getCallbackOrigin() || window.location.origin;\n const href =\n url ??\n new URL(agentNativePath(\"/_agent-native/builder/connect\"), origin).href;\n const connectUrlKind = url ? \"provided\" : \"default\";\n trackEvent(\"builder connect clicked\", {\n feature: \"builder\",\n stage: \"client\",\n source,\n connect_url_kind: connectUrlKind,\n });\n try {\n const opened = window.open(href, \"_blank\", features);\n if (!opened && !/AgentNativeDesktop/i.test(navigator.userAgent || \"\")) {\n trackEvent(\"builder connect popup blocked\", {\n feature: \"builder\",\n stage: \"client\",\n source,\n connect_url_kind: connectUrlKind,\n });\n }\n return opened;\n } catch {\n trackEvent(\"builder connect failed\", {\n feature: \"builder\",\n stage: \"client\",\n reason: \"popup_open_exception\",\n source,\n connect_url_kind: connectUrlKind,\n });\n return null;\n }\n}\n\nexport function useBuilderConnectFlow(\n opts: BuilderConnectFlowOptions = {},\n): BuilderConnectFlow {\n const {\n popupUrl,\n trackingSource = \"builder_connect_flow\",\n onConnected,\n } = opts;\n const [configured, setConfigured] = useState(false);\n const [envManaged, setEnvManaged] = useState(false);\n const [builderEnabled, setBuilderEnabled] = useState(false);\n const [orgName, setOrgName] = useState<string | null>(null);\n const [connecting, setConnecting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [hasFetchedStatus, setHasFetchedStatus] = useState(false);\n const [statusConnectUrl, setStatusConnectUrl] = useState<string | null>(null);\n // When statusConnectUrl was last fetched. The server signs the embedded\n // _an_connect token with a 10-minute TTL; using an older URL fails the\n // cross-origin popup gate. Track freshness so start() can either use a\n // still-good direct URL (desktop) or refresh a new one inside the popup\n // gesture path (browser/editor embeds).\n const statusConnectUrlAtRef = useRef<number | null>(null);\n const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const connectStartedAtRef = useRef<number | null>(null);\n const mountedRef = useRef(true);\n const notifiedConnectedRef = useRef(false);\n // Keep onConnected in a ref so start() doesn't need to re-create when the\n // caller passes an inline arrow function.\n const onConnectedRef = useRef(onConnected);\n onConnectedRef.current = onConnected;\n\n const stopPoll = useCallback(() => {\n if (pollRef.current) {\n clearInterval(pollRef.current);\n pollRef.current = null;\n }\n }, []);\n\n const fetchStatus = useCallback(async () => {\n const origin = getCallbackOrigin() || window.location.origin;\n try {\n const r = await fetch(\n new URL(agentNativePath(\"/_agent-native/builder/status\"), origin).href,\n );\n if (!r.ok) return null;\n return (await r.json()) as {\n configured: boolean;\n envManaged?: boolean;\n builderEnabled?: boolean;\n orgName?: string | null;\n connectUrl?: string;\n cliAuthUrl?: string;\n credentialSource?: \"user\" | \"org\" | \"workspace\" | \"env\";\n connectError?: { message: string; at: number };\n authError?: { message: string; at: number };\n };\n } catch {\n return null;\n }\n }, []);\n\n // Initial fetch + focus/visibility refresh so if the user completed the\n // flow in another tab (or a downgraded same-tab nav) we notice it. Also\n // listen for `agent-engine:configured-changed` so a Disconnect click in\n // Settings propagates to any connect-CTA cards rendered elsewhere in\n // the app without waiting for the next focus event.\n useEffect(() => {\n mountedRef.current = true;\n let cancelled = false;\n const refresh = async () => {\n const s = await fetchStatus();\n if (cancelled || !mountedRef.current) return;\n // Flip `hasFetchedStatus` even when the fetch failed — the caller's\n // \"use initial props until the hook has an answer\" pattern wants to\n // stop waiting after we've tried, regardless of network outcome.\n setHasFetchedStatus(true);\n if (!s) return;\n setConfigured(!!s.configured);\n setEnvManaged(!!s.envManaged);\n setBuilderEnabled(!!s.builderEnabled);\n const nextConnectUrl = s.cliAuthUrl ?? s.connectUrl ?? null;\n setStatusConnectUrl(nextConnectUrl);\n statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;\n const org = s.orgName ?? null;\n setOrgName(org);\n if (s.configured) {\n connectStartedAtRef.current = null;\n }\n if (s.configured && !notifiedConnectedRef.current) {\n notifiedConnectedRef.current = true;\n notifyAgentEngineConfiguredChanged(\"builder-status\");\n try {\n await onConnectedRef.current?.({ orgName: org });\n } catch {\n // The caller's callback is a UI convenience; status is already set.\n }\n } else if (!s.configured) {\n notifiedConnectedRef.current = false;\n }\n // Surface persisted auth-failure messages on idle refreshes, but don't\n // let an old rejected credential abort a new reconnect popup while the\n // user is still choosing a Builder space.\n const activeConnectStartedAt = connectStartedAtRef.current;\n if (isCurrentConnectError(s.connectError, activeConnectStartedAt)) {\n setError(s.connectError.message);\n } else if (!activeConnectStartedAt && s.authError?.message) {\n setError(s.authError.message);\n } else if (s.configured) {\n setError(null);\n }\n };\n refresh();\n const onVisible = () => {\n if (document.visibilityState === \"visible\") refresh();\n };\n window.addEventListener(\"focus\", refresh);\n document.addEventListener(\"visibilitychange\", onVisible);\n window.addEventListener(\"agent-engine:configured-changed\", refresh);\n return () => {\n cancelled = true;\n mountedRef.current = false;\n window.removeEventListener(\"focus\", refresh);\n document.removeEventListener(\"visibilitychange\", onVisible);\n window.removeEventListener(\"agent-engine:configured-changed\", refresh);\n stopPoll();\n };\n }, [fetchStatus, stopPoll]);\n\n const start = useCallback(() => {\n stopPoll();\n const started = Date.now();\n connectStartedAtRef.current = started;\n setConnecting(true);\n setError(null);\n\n // Open SYNCHRONOUSLY inside the caller's click handler — any await\n // before window.open lets the user-gesture token expire, which causes\n // popup blockers to block entirely or fall back to same-tab navigation.\n const origin = getCallbackOrigin() || window.location.origin;\n const cachedFreshUrl = isFreshSignedConnectUrl(\n statusConnectUrl,\n statusConnectUrlAtRef.current,\n )\n ? statusConnectUrl\n : null;\n // popupUrl prop (e.g. from a chat ConnectBuilderCard) may be a signed\n // URL that was minted minutes-to-days ago — we don't have a mint\n // timestamp for it, so we can't be sure it's still within the signed\n // TTL. Use it as a *direct* popup URL only for desktop (where the\n // about:blank refresh-in-popup path doesn't exist); on web, fall\n // through to the refresh-in-popup branch so a stale prop URL doesn't\n // open an expired popup.\n const signedPropUrl = hasSignedConnectToken(popupUrl) ? popupUrl : null;\n const signedCliPropUrl = hasSignedCallbackState(popupUrl) ? popupUrl : null;\n const fallbackUrl = new URL(\n agentNativePath(\"/_agent-native/builder/connect\"),\n origin,\n ).href;\n const hasDirectSignedUrl = Boolean(cachedFreshUrl);\n const directUrl =\n cachedFreshUrl ?? signedCliPropUrl ?? signedPropUrl ?? fallbackUrl;\n\n if (isAgentNativeDesktop()) {\n const opened = openBuilderConnectPopup({\n url: directUrl,\n source: trackingSource,\n });\n if (!opened) {\n // Agent Native Desktop handles the popup in Electron and reports\n // null to the embedded webview, so null is not a blocker here.\n }\n } else if (hasDirectSignedUrl) {\n const opened = openBuilderConnectPopup({\n url: directUrl,\n source: trackingSource,\n features: \"width=600,height=700\",\n });\n if (!opened) {\n connectStartedAtRef.current = null;\n setConnecting(false);\n setError(\"Couldn't open Builder. Allow popups and try again.\");\n return;\n }\n } else {\n const opened = openBuilderConnectPopup({\n url: \"about:blank\",\n source: trackingSource,\n features: \"width=600,height=700\",\n });\n if (!opened) {\n connectStartedAtRef.current = null;\n setConnecting(false);\n setError(\"Couldn't open Builder. Allow popups and try again.\");\n return;\n }\n showBuilderConnectPopupPlaceholder(opened);\n void (async () => {\n const s = await fetchStatus();\n if (!mountedRef.current) {\n try {\n opened.close();\n } catch {\n // Ignore close failures.\n }\n return;\n }\n if (s) {\n setHasFetchedStatus(true);\n setConfigured(!!s.configured);\n setEnvManaged(!!s.envManaged);\n setBuilderEnabled(!!s.builderEnabled);\n const nextConnectUrl = s.cliAuthUrl ?? s.connectUrl ?? null;\n setStatusConnectUrl(nextConnectUrl);\n statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;\n setOrgName(s.orgName ?? null);\n }\n\n const freshUrl =\n (s?.cliAuthUrl && hasSignedCallbackState(s.cliAuthUrl)\n ? s.cliAuthUrl\n : null) ??\n (s?.connectUrl && hasSignedConnectToken(s.connectUrl)\n ? s.connectUrl\n : null) ??\n cachedFreshUrl;\n if (!freshUrl) {\n try {\n opened.close();\n } catch {\n // Ignore close failures.\n }\n stopPoll();\n connectStartedAtRef.current = null;\n setConnecting(false);\n setError(\n \"Couldn't start Builder connect. Refresh this page and try again.\",\n );\n return;\n }\n if (!navigateBuilderConnectPopup(opened, freshUrl)) {\n stopPoll();\n connectStartedAtRef.current = null;\n setConnecting(false);\n setError(\n \"Couldn't navigate the Builder popup. Allow popups and try again.\",\n );\n }\n })();\n }\n\n pollRef.current = setInterval(async () => {\n const s = await fetchStatus();\n if (!mountedRef.current) {\n stopPoll();\n return;\n }\n if (s?.configured) {\n stopPoll();\n setConfigured(true);\n setEnvManaged(!!s.envManaged);\n setBuilderEnabled(!!s.builderEnabled);\n const nextConnectUrl = s.cliAuthUrl ?? s.connectUrl ?? null;\n setStatusConnectUrl(nextConnectUrl);\n statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;\n const org = s.orgName ?? null;\n setOrgName(org);\n setConnecting(false);\n connectStartedAtRef.current = null;\n notifiedConnectedRef.current = true;\n notifyAgentEngineConfiguredChanged(\"builder-connect\");\n try {\n await onConnectedRef.current?.({ orgName: org });\n } catch {\n // Consumer's callback failed; we've already flipped the UI state\n // to connected. Swallow so we don't re-arm the flow.\n }\n } else if (isCurrentConnectError(s?.connectError, started)) {\n // OAuth callback ran but writeBuilderCredentials threw — surface the\n // real error instead of letting the user wait 5 minutes for timeout.\n stopPoll();\n connectStartedAtRef.current = null;\n setConnecting(false);\n setError(\n `Couldn't save Builder credentials: ${s.connectError.message}. Try again or contact support.`,\n );\n } else if (Date.now() - started > POLL_TIMEOUT_MS) {\n stopPoll();\n connectStartedAtRef.current = null;\n setConnecting(false);\n trackEvent(\"builder connect failed\", {\n feature: \"builder\",\n stage: \"client\",\n reason: \"timeout\",\n source: trackingSource,\n });\n setError(\n \"Didn't hear back from Builder in 5 minutes. Allow popups and try again.\",\n );\n }\n }, POLL_INTERVAL_MS);\n }, [fetchStatus, popupUrl, statusConnectUrl, stopPoll, trackingSource]);\n\n // Popup-side fast path: the callback page broadcasts a message so we stop\n // polling immediately rather than waiting for the next 2s tick.\n //\n // We listen on BroadcastChannel (same-origin, works with noopener popups)\n // AND on window.message (legacy path for environments without BC or for\n // popups that still have opener access). Both paths are safe to have open\n // simultaneously \\u2014 the first one to fire wins and the error is deduplicated\n // by the stopPoll() call which is idempotent.\n useEffect(() => {\n let channel: BroadcastChannel | null = null;\n const handleError = (message: string) => {\n stopPoll();\n connectStartedAtRef.current = null;\n setConnecting(false);\n setError(`Couldn't save Builder credentials: ${message}.`);\n };\n const handleSuccess = async () => {\n const s = await fetchStatus();\n if (!mountedRef.current || !s?.configured) return;\n stopPoll();\n setHasFetchedStatus(true);\n setConfigured(true);\n setEnvManaged(!!s.envManaged);\n setBuilderEnabled(!!s.builderEnabled);\n const nextConnectUrl = s.cliAuthUrl ?? s.connectUrl ?? null;\n setStatusConnectUrl(nextConnectUrl);\n statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;\n const org = s.orgName ?? null;\n setOrgName(org);\n setConnecting(false);\n connectStartedAtRef.current = null;\n notifiedConnectedRef.current = true;\n notifyAgentEngineConfiguredChanged(\"builder-connect-message\");\n try {\n await onConnectedRef.current?.({ orgName: org });\n } catch {\n // The caller's callback is a UI convenience; status is already set.\n }\n };\n\n try {\n channel = new BroadcastChannel(`builder-connect:${window.location.host}`);\n channel.onmessage = (e: MessageEvent) => {\n const data = e.data as { type?: string; message?: string } | undefined;\n if (data?.type === \"builder-connect-success\") {\n void handleSuccess();\n return;\n }\n if (data?.type === \"builder-connect-error\") {\n if (typeof data.message !== \"string\" || !data.message) return;\n handleError(data.message);\n }\n };\n } catch {\n // BroadcastChannel not available (rare) \\u2014 fall through to postMessage.\n }\n\n const handler = (e: MessageEvent) => {\n if (!isTrustedBuilderConnectMessageOrigin(e.origin)) return;\n const data = e.data as { type?: string; message?: string } | undefined;\n if (data?.type === \"builder-connect-success\") {\n void handleSuccess();\n return;\n }\n if (data?.type === \"builder-connect-error\") {\n if (typeof data.message !== \"string\" || !data.message) return;\n handleError(data.message);\n }\n };\n window.addEventListener(\"message\", handler);\n\n return () => {\n channel?.close();\n window.removeEventListener(\"message\", handler);\n };\n }, [fetchStatus, stopPoll]);\n\n return {\n configured,\n envManaged,\n builderEnabled,\n orgName,\n connecting,\n error,\n hasFetchedStatus,\n start,\n };\n}\n"]}
@@ -60,6 +60,7 @@ describe("useBuilderConnectFlow", () => {
60
60
  afterEach(() => {
61
61
  act(() => root.unmount());
62
62
  container.remove();
63
+ vi.useRealTimers();
63
64
  vi.unstubAllGlobals();
64
65
  });
65
66
  it("opens the signed Builder cli-auth URL directly", async () => {
@@ -166,5 +167,80 @@ describe("useBuilderConnectFlow", () => {
166
167
  expect(window.location.href).toBe("http://localhost:3000/settings");
167
168
  expect(container.textContent).not.toContain("Popup blocked");
168
169
  });
170
+ it("does not abort a reconnect popup because the old credential was rejected", async () => {
171
+ vi.useFakeTimers();
172
+ vi.setSystemTime(new Date("2026-05-14T12:00:00.000Z"));
173
+ setUserAgent("Mozilla/5.0 Chrome/140.0");
174
+ const popup = createPopupStub();
175
+ openSpy.mockReturnValue(popup);
176
+ const signedConnectUrl = "http://localhost:3000/_agent-native/builder/connect?_an_connect=signed";
177
+ vi.mocked(fetch).mockResolvedValue(jsonResponse({
178
+ configured: false,
179
+ envManaged: true,
180
+ builderEnabled: true,
181
+ orgName: null,
182
+ connectUrl: signedConnectUrl,
183
+ appHost: "https://builder.io",
184
+ apiHost: "https://api.builder.io",
185
+ publicKeyConfigured: false,
186
+ privateKeyConfigured: false,
187
+ authError: {
188
+ message: "Private key does not match spaceId",
189
+ at: Date.now() - 60_000,
190
+ },
191
+ }));
192
+ await act(async () => {
193
+ root.render(_jsx(BuilderConnectProbe, {}));
194
+ await Promise.resolve();
195
+ });
196
+ expect(container.textContent).toContain("Private key does not match spaceId");
197
+ await act(async () => {
198
+ container.querySelector("button")?.click();
199
+ });
200
+ expect(openSpy).toHaveBeenCalledWith(signedConnectUrl, "_blank", "width=600,height=700");
201
+ expect(container.textContent).toContain("not-configured connecting");
202
+ expect(container.textContent).not.toContain("Private key does not match spaceId");
203
+ await act(async () => {
204
+ await vi.advanceTimersByTimeAsync(2000);
205
+ });
206
+ expect(container.textContent).toContain("not-configured connecting");
207
+ expect(container.textContent).not.toContain("Private key does not match spaceId");
208
+ });
209
+ it("ignores stale connect callback errors after starting a fresh reconnect", async () => {
210
+ vi.useFakeTimers();
211
+ vi.setSystemTime(new Date("2026-05-14T12:00:00.000Z"));
212
+ setUserAgent("Mozilla/5.0 Chrome/140.0");
213
+ const popup = createPopupStub();
214
+ openSpy.mockReturnValue(popup);
215
+ const signedConnectUrl = "http://localhost:3000/_agent-native/builder/connect?_an_connect=signed";
216
+ vi.mocked(fetch).mockResolvedValue(jsonResponse({
217
+ configured: false,
218
+ envManaged: false,
219
+ builderEnabled: true,
220
+ orgName: null,
221
+ connectUrl: signedConnectUrl,
222
+ appHost: "https://builder.io",
223
+ apiHost: "https://api.builder.io",
224
+ publicKeyConfigured: false,
225
+ privateKeyConfigured: false,
226
+ connectError: {
227
+ message: "No active connect flow found",
228
+ at: Date.now() - 60_000,
229
+ },
230
+ }));
231
+ await act(async () => {
232
+ root.render(_jsx(BuilderConnectProbe, {}));
233
+ await Promise.resolve();
234
+ });
235
+ expect(container.textContent).toContain("No active connect flow found");
236
+ await act(async () => {
237
+ container.querySelector("button")?.click();
238
+ });
239
+ await act(async () => {
240
+ await vi.advanceTimersByTimeAsync(2000);
241
+ });
242
+ expect(container.textContent).toContain("not-configured connecting");
243
+ expect(container.textContent).not.toContain("No active connect flow found");
244
+ });
169
245
  });
170
246
  //# sourceMappingURL=useBuilderStatus.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useBuilderStatus.spec.js","sourceRoot":"","sources":["../../../src/client/settings/useBuilderStatus.spec.tsx"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment happy-dom\nimport React, { act } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { useBuilderConnectFlow } from \"./useBuilderStatus.js\";\n\nfunction jsonResponse(data: unknown): Response {\n return new Response(JSON.stringify(data), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nfunction setUserAgent(userAgent: string) {\n Object.defineProperty(window.navigator, \"userAgent\", {\n value: userAgent,\n configurable: true,\n });\n}\n\nfunction BuilderConnectProbe({ popupUrl }: { popupUrl?: string }) {\n const flow = useBuilderConnectFlow({ popupUrl });\n return (\n <div>\n <button type=\"button\" onClick={flow.start}>\n Connect\n </button>\n <output data-testid=\"status\">\n {flow.configured ? \"configured\" : \"not-configured\"}{\" \"}\n {flow.connecting ? \"connecting\" : \"idle\"}\n </output>\n <output>{flow.error ?? \"\"}</output>\n </div>\n );\n}\n\nfunction createPopupStub() {\n const doc = document.implementation.createHTMLDocument(\"popup\");\n return {\n closed: false,\n close: vi.fn(),\n document: doc,\n location: { href: \"\" },\n opener: window,\n } as unknown as Window;\n}\n\nconst signedCliAuthUrl =\n \"https://builder.io/cli-auth?response_type=code&host=agent-native-browser&client_id=Agent%20Native%20Browser&redirect_url=https%3A%2F%2Fagent-workspace.builder.io%2Fdispatch%2F_agent-native%2Fbuilder%2Fcallback%3F_an_state%3Dsigned&preview_url=https%3A%2F%2Fagent-workspace.builder.io%2Fdispatch&framework=agent-native\";\nconst staleCliAuthUrl = signedCliAuthUrl.replace(\n \"_an_state%3Dsigned\",\n \"_an_state%3Dstale\",\n);\nconst refreshedCliAuthUrl = signedCliAuthUrl.replace(\n \"_an_state%3Dsigned\",\n \"_an_state%3Drefreshed\",\n);\n\ndescribe(\"useBuilderConnectFlow\", () => {\n let container: HTMLDivElement;\n let root: Root;\n let openSpy: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n vi.stubGlobal(\"IS_REACT_ACT_ENVIRONMENT\", true);\n window.history.replaceState({}, \"\", \"http://localhost:3000/settings\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async () =>\n jsonResponse({\n configured: false,\n envManaged: false,\n builderEnabled: true,\n orgName: null,\n cliAuthUrl: signedCliAuthUrl,\n connectUrl:\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\",\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: false,\n privateKeyConfigured: false,\n }),\n ),\n );\n openSpy = vi.fn(() => null);\n vi.stubGlobal(\"open\", openSpy);\n container = document.createElement(\"div\");\n document.body.appendChild(container);\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => root.unmount());\n container.remove();\n vi.unstubAllGlobals();\n });\n\n it(\"opens the signed Builder cli-auth URL directly\", async () => {\n setUserAgent(\"Mozilla/5.0 Chrome/140.0\");\n const popup = createPopupStub();\n openSpy.mockReturnValue(popup);\n\n await act(async () => {\n root.render(<BuilderConnectProbe />);\n await Promise.resolve();\n await Promise.resolve();\n });\n\n await act(async () => {\n container.querySelector(\"button\")?.click();\n });\n\n expect(openSpy).toHaveBeenCalledWith(\n signedCliAuthUrl,\n \"_blank\",\n \"width=600,height=700\",\n );\n expect(popup.location.href).toBe(\"\");\n expect(container.textContent).not.toContain(\"Popup blocked\");\n });\n\n it(\"refreshes an un-timestamped signed prop URL before navigating web popups\", async () => {\n setUserAgent(\"Mozilla/5.0 Chrome/140.0\");\n const popup = createPopupStub();\n openSpy.mockReturnValue(popup);\n\n let resolveInitialFetch!: (response: Response) => void;\n const initialFetch = new Promise<Response>((resolve) => {\n resolveInitialFetch = resolve;\n });\n vi.mocked(fetch)\n .mockReturnValueOnce(initialFetch)\n .mockResolvedValue(\n jsonResponse({\n configured: false,\n envManaged: false,\n builderEnabled: true,\n orgName: null,\n cliAuthUrl: refreshedCliAuthUrl,\n connectUrl:\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\",\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: false,\n privateKeyConfigured: false,\n }),\n );\n\n await act(async () => {\n root.render(<BuilderConnectProbe popupUrl={staleCliAuthUrl} />);\n });\n\n await act(async () => {\n container.querySelector(\"button\")?.click();\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(openSpy).toHaveBeenCalledWith(\n \"about:blank\",\n \"_blank\",\n \"width=600,height=700\",\n );\n expect(popup.location.href).toBe(refreshedCliAuthUrl);\n\n resolveInitialFetch(jsonResponse({ configured: false }));\n });\n\n it(\"refreshes status when a Builder preview callback posts success\", async () => {\n setUserAgent(\"Mozilla/5.0 Chrome/140.0\");\n vi.mocked(fetch)\n .mockResolvedValueOnce(\n jsonResponse({\n configured: false,\n envManaged: false,\n builderEnabled: true,\n orgName: null,\n cliAuthUrl: signedCliAuthUrl,\n connectUrl:\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\",\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: false,\n privateKeyConfigured: false,\n }),\n )\n .mockResolvedValueOnce(\n jsonResponse({\n configured: true,\n envManaged: false,\n builderEnabled: true,\n orgName: \"Builder space\",\n cliAuthUrl: signedCliAuthUrl,\n connectUrl:\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\",\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: true,\n privateKeyConfigured: true,\n }),\n );\n\n await act(async () => {\n root.render(<BuilderConnectProbe />);\n await Promise.resolve();\n });\n\n expect(container.textContent).toContain(\"not-configured\");\n\n await act(async () => {\n window.dispatchEvent(\n new MessageEvent(\"message\", {\n origin:\n \"https://940ebc5a83164aa6a37dde445e494f3a-fluid-crack-ctnhvsyb.builderio.xyz\",\n data: { type: \"builder-connect-success\" },\n }),\n );\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(container.textContent).toContain(\"configured\");\n });\n\n it(\"does not replace the desktop webview when Electron reports a handled popup as null\", async () => {\n setUserAgent(\"Mozilla/5.0 Electron/41.2.2 AgentNativeDesktop/0.1.7\");\n\n await act(async () => {\n root.render(<BuilderConnectProbe />);\n });\n\n await act(async () => {\n container.querySelector(\"button\")?.click();\n });\n\n expect(openSpy).toHaveBeenCalledWith(\n signedCliAuthUrl,\n \"_blank\",\n \"noopener,noreferrer\",\n );\n expect(window.location.href).toBe(\"http://localhost:3000/settings\");\n expect(container.textContent).not.toContain(\"Popup blocked\");\n });\n});\n"]}
1
+ {"version":3,"file":"useBuilderStatus.spec.js","sourceRoot":"","sources":["../../../src/client/settings/useBuilderStatus.spec.tsx"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment happy-dom\nimport React, { act } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { useBuilderConnectFlow } from \"./useBuilderStatus.js\";\n\nfunction jsonResponse(data: unknown): Response {\n return new Response(JSON.stringify(data), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nfunction setUserAgent(userAgent: string) {\n Object.defineProperty(window.navigator, \"userAgent\", {\n value: userAgent,\n configurable: true,\n });\n}\n\nfunction BuilderConnectProbe({ popupUrl }: { popupUrl?: string }) {\n const flow = useBuilderConnectFlow({ popupUrl });\n return (\n <div>\n <button type=\"button\" onClick={flow.start}>\n Connect\n </button>\n <output data-testid=\"status\">\n {flow.configured ? \"configured\" : \"not-configured\"}{\" \"}\n {flow.connecting ? \"connecting\" : \"idle\"}\n </output>\n <output>{flow.error ?? \"\"}</output>\n </div>\n );\n}\n\nfunction createPopupStub() {\n const doc = document.implementation.createHTMLDocument(\"popup\");\n return {\n closed: false,\n close: vi.fn(),\n document: doc,\n location: { href: \"\" },\n opener: window,\n } as unknown as Window;\n}\n\nconst signedCliAuthUrl =\n \"https://builder.io/cli-auth?response_type=code&host=agent-native-browser&client_id=Agent%20Native%20Browser&redirect_url=https%3A%2F%2Fagent-workspace.builder.io%2Fdispatch%2F_agent-native%2Fbuilder%2Fcallback%3F_an_state%3Dsigned&preview_url=https%3A%2F%2Fagent-workspace.builder.io%2Fdispatch&framework=agent-native\";\nconst staleCliAuthUrl = signedCliAuthUrl.replace(\n \"_an_state%3Dsigned\",\n \"_an_state%3Dstale\",\n);\nconst refreshedCliAuthUrl = signedCliAuthUrl.replace(\n \"_an_state%3Dsigned\",\n \"_an_state%3Drefreshed\",\n);\n\ndescribe(\"useBuilderConnectFlow\", () => {\n let container: HTMLDivElement;\n let root: Root;\n let openSpy: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n vi.stubGlobal(\"IS_REACT_ACT_ENVIRONMENT\", true);\n window.history.replaceState({}, \"\", \"http://localhost:3000/settings\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async () =>\n jsonResponse({\n configured: false,\n envManaged: false,\n builderEnabled: true,\n orgName: null,\n cliAuthUrl: signedCliAuthUrl,\n connectUrl:\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\",\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: false,\n privateKeyConfigured: false,\n }),\n ),\n );\n openSpy = vi.fn(() => null);\n vi.stubGlobal(\"open\", openSpy);\n container = document.createElement(\"div\");\n document.body.appendChild(container);\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => root.unmount());\n container.remove();\n vi.useRealTimers();\n vi.unstubAllGlobals();\n });\n\n it(\"opens the signed Builder cli-auth URL directly\", async () => {\n setUserAgent(\"Mozilla/5.0 Chrome/140.0\");\n const popup = createPopupStub();\n openSpy.mockReturnValue(popup);\n\n await act(async () => {\n root.render(<BuilderConnectProbe />);\n await Promise.resolve();\n await Promise.resolve();\n });\n\n await act(async () => {\n container.querySelector(\"button\")?.click();\n });\n\n expect(openSpy).toHaveBeenCalledWith(\n signedCliAuthUrl,\n \"_blank\",\n \"width=600,height=700\",\n );\n expect(popup.location.href).toBe(\"\");\n expect(container.textContent).not.toContain(\"Popup blocked\");\n });\n\n it(\"refreshes an un-timestamped signed prop URL before navigating web popups\", async () => {\n setUserAgent(\"Mozilla/5.0 Chrome/140.0\");\n const popup = createPopupStub();\n openSpy.mockReturnValue(popup);\n\n let resolveInitialFetch!: (response: Response) => void;\n const initialFetch = new Promise<Response>((resolve) => {\n resolveInitialFetch = resolve;\n });\n vi.mocked(fetch)\n .mockReturnValueOnce(initialFetch)\n .mockResolvedValue(\n jsonResponse({\n configured: false,\n envManaged: false,\n builderEnabled: true,\n orgName: null,\n cliAuthUrl: refreshedCliAuthUrl,\n connectUrl:\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\",\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: false,\n privateKeyConfigured: false,\n }),\n );\n\n await act(async () => {\n root.render(<BuilderConnectProbe popupUrl={staleCliAuthUrl} />);\n });\n\n await act(async () => {\n container.querySelector(\"button\")?.click();\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(openSpy).toHaveBeenCalledWith(\n \"about:blank\",\n \"_blank\",\n \"width=600,height=700\",\n );\n expect(popup.location.href).toBe(refreshedCliAuthUrl);\n\n resolveInitialFetch(jsonResponse({ configured: false }));\n });\n\n it(\"refreshes status when a Builder preview callback posts success\", async () => {\n setUserAgent(\"Mozilla/5.0 Chrome/140.0\");\n vi.mocked(fetch)\n .mockResolvedValueOnce(\n jsonResponse({\n configured: false,\n envManaged: false,\n builderEnabled: true,\n orgName: null,\n cliAuthUrl: signedCliAuthUrl,\n connectUrl:\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\",\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: false,\n privateKeyConfigured: false,\n }),\n )\n .mockResolvedValueOnce(\n jsonResponse({\n configured: true,\n envManaged: false,\n builderEnabled: true,\n orgName: \"Builder space\",\n cliAuthUrl: signedCliAuthUrl,\n connectUrl:\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\",\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: true,\n privateKeyConfigured: true,\n }),\n );\n\n await act(async () => {\n root.render(<BuilderConnectProbe />);\n await Promise.resolve();\n });\n\n expect(container.textContent).toContain(\"not-configured\");\n\n await act(async () => {\n window.dispatchEvent(\n new MessageEvent(\"message\", {\n origin:\n \"https://940ebc5a83164aa6a37dde445e494f3a-fluid-crack-ctnhvsyb.builderio.xyz\",\n data: { type: \"builder-connect-success\" },\n }),\n );\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(container.textContent).toContain(\"configured\");\n });\n\n it(\"does not replace the desktop webview when Electron reports a handled popup as null\", async () => {\n setUserAgent(\"Mozilla/5.0 Electron/41.2.2 AgentNativeDesktop/0.1.7\");\n\n await act(async () => {\n root.render(<BuilderConnectProbe />);\n });\n\n await act(async () => {\n container.querySelector(\"button\")?.click();\n });\n\n expect(openSpy).toHaveBeenCalledWith(\n signedCliAuthUrl,\n \"_blank\",\n \"noopener,noreferrer\",\n );\n expect(window.location.href).toBe(\"http://localhost:3000/settings\");\n expect(container.textContent).not.toContain(\"Popup blocked\");\n });\n\n it(\"does not abort a reconnect popup because the old credential was rejected\", async () => {\n vi.useFakeTimers();\n vi.setSystemTime(new Date(\"2026-05-14T12:00:00.000Z\"));\n setUserAgent(\"Mozilla/5.0 Chrome/140.0\");\n const popup = createPopupStub();\n openSpy.mockReturnValue(popup);\n const signedConnectUrl =\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\";\n vi.mocked(fetch).mockResolvedValue(\n jsonResponse({\n configured: false,\n envManaged: true,\n builderEnabled: true,\n orgName: null,\n connectUrl: signedConnectUrl,\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: false,\n privateKeyConfigured: false,\n authError: {\n message: \"Private key does not match spaceId\",\n at: Date.now() - 60_000,\n },\n }),\n );\n\n await act(async () => {\n root.render(<BuilderConnectProbe />);\n await Promise.resolve();\n });\n\n expect(container.textContent).toContain(\n \"Private key does not match spaceId\",\n );\n\n await act(async () => {\n container.querySelector(\"button\")?.click();\n });\n\n expect(openSpy).toHaveBeenCalledWith(\n signedConnectUrl,\n \"_blank\",\n \"width=600,height=700\",\n );\n expect(container.textContent).toContain(\"not-configured connecting\");\n expect(container.textContent).not.toContain(\n \"Private key does not match spaceId\",\n );\n\n await act(async () => {\n await vi.advanceTimersByTimeAsync(2000);\n });\n\n expect(container.textContent).toContain(\"not-configured connecting\");\n expect(container.textContent).not.toContain(\n \"Private key does not match spaceId\",\n );\n });\n\n it(\"ignores stale connect callback errors after starting a fresh reconnect\", async () => {\n vi.useFakeTimers();\n vi.setSystemTime(new Date(\"2026-05-14T12:00:00.000Z\"));\n setUserAgent(\"Mozilla/5.0 Chrome/140.0\");\n const popup = createPopupStub();\n openSpy.mockReturnValue(popup);\n const signedConnectUrl =\n \"http://localhost:3000/_agent-native/builder/connect?_an_connect=signed\";\n vi.mocked(fetch).mockResolvedValue(\n jsonResponse({\n configured: false,\n envManaged: false,\n builderEnabled: true,\n orgName: null,\n connectUrl: signedConnectUrl,\n appHost: \"https://builder.io\",\n apiHost: \"https://api.builder.io\",\n publicKeyConfigured: false,\n privateKeyConfigured: false,\n connectError: {\n message: \"No active connect flow found\",\n at: Date.now() - 60_000,\n },\n }),\n );\n\n await act(async () => {\n root.render(<BuilderConnectProbe />);\n await Promise.resolve();\n });\n\n expect(container.textContent).toContain(\"No active connect flow found\");\n\n await act(async () => {\n container.querySelector(\"button\")?.click();\n });\n\n await act(async () => {\n await vi.advanceTimersByTimeAsync(2000);\n });\n\n expect(container.textContent).toContain(\"not-configured connecting\");\n expect(container.textContent).not.toContain(\"No active connect flow found\");\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-chat-plugin.d.ts","sourceRoot":"","sources":["../../src/server/agent-chat-plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-chat-plugin.d.ts","sourceRoot":"","sources":["../../src/server/agent-chat-plugin.ts"],"names":[],"mappings":"AAaA,OAAO,EASL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAStC,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAElB,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,gBAAgB,EAUjB,MAAM,wBAAwB,CAAC;AA0DhC,OAAO,EAGL,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EAC1B,MAAM,6BAA6B,CAAC;AAsErC,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,WAAW,EAAE,SAAS,oBAAoB,EAAE,EAC5C,OAAO,GAAE,0BAA0B,GAAG;IAAE,KAAK,CAAC,EAAE,GAAG,CAAA;CAAO,GACzD;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAO7C;AA+oCD,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACrC,+DAA+D;IAC/D,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,CAAC,MACG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9C,wCAAwC;IACxC,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,CAAC,MACG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9C,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;sDAGkD;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EACH,OAAO,0BAA0B,EAAE,WAAW,GAC9C,MAAM,GACN;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IACtD,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,gBAAgB,CAAC,EACb,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAC/B,CAAC,MACG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAClD,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtE;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxE;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;;;;;OAcG;IACH,YAAY,CAAC,EAAE,CACb,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,MAAM,KACV,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5C;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,8BAA8B,EAAE,2BAA2B,CAAC;IACxF;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE;QACzB,KAAK,EAAE,GAAG,CAAC;QACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,mBAAmB,EAAE,CAAC;QACnC,UAAU,EAAE,kBAAkB,EAAE,CAAC;QACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;KACtB,KACG,IAAI,GACJ;QACE,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;KACrC,GACD,OAAO,CAAC,IAAI,GAAG;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;KACrC,CAAC,CAAC;IACP;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAo3BD,wBAAgB,qBAAqB,CACnC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,cAAc,CA86FhB;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,cAAwC,CAAC;AAa9E,yEAAyE;AACzE,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,IAAI,CAE7D"}
@@ -795,9 +795,12 @@ function createBuilderBrowserTool(deps) {
795
795
  },
796
796
  },
797
797
  run: async (args) => {
798
- const { resolveBuilderCredentials } = await import("./credential-provider.js");
798
+ const { getBuilderCredentialAuthFailure, resolveBuilderCredentials } = await import("./credential-provider.js");
799
799
  const creds = await resolveBuilderCredentials();
800
- const configured = !!(creds.privateKey && creds.publicKey);
800
+ const authFailure = await getBuilderCredentialAuthFailure(creds);
801
+ const configured = !!(creds.privateKey &&
802
+ creds.publicKey &&
803
+ !authFailure);
801
804
  const branchProjectId = await resolveBuilderBranchProjectId();
802
805
  const prompt = typeof args?.prompt === "string" ? args.prompt : "";
803
806
  const origin = deps.getOrigin();