@agent-native/core 0.12.40 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/agent/run-manager.d.ts +5 -1
  2. package/dist/agent/run-manager.d.ts.map +1 -1
  3. package/dist/agent/run-manager.js +48 -2
  4. package/dist/agent/run-manager.js.map +1 -1
  5. package/dist/agent/run-store.d.ts +8 -0
  6. package/dist/agent/run-store.d.ts.map +1 -1
  7. package/dist/agent/run-store.js +36 -5
  8. package/dist/agent/run-store.js.map +1 -1
  9. package/dist/cli/templates-meta.js +10 -10
  10. package/dist/cli/templates-meta.js.map +1 -1
  11. package/dist/client/AssistantChat.d.ts.map +1 -1
  12. package/dist/client/AssistantChat.js +42 -3
  13. package/dist/client/AssistantChat.js.map +1 -1
  14. package/dist/client/ConnectBuilderCard.js +1 -1
  15. package/dist/client/ConnectBuilderCard.js.map +1 -1
  16. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  17. package/dist/client/MultiTabAssistantChat.js +27 -16
  18. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  19. package/dist/client/RunStuckBanner.d.ts +35 -0
  20. package/dist/client/RunStuckBanner.d.ts.map +1 -0
  21. package/dist/client/RunStuckBanner.js +66 -0
  22. package/dist/client/RunStuckBanner.js.map +1 -0
  23. package/dist/client/components/AgentPresenceChip.d.ts +1 -1
  24. package/dist/client/components/AgentPresenceChip.js +1 -1
  25. package/dist/client/components/AgentPresenceChip.js.map +1 -1
  26. package/dist/client/components/CodeRequiredDialog.js +5 -5
  27. package/dist/client/components/CodeRequiredDialog.js.map +1 -1
  28. package/dist/client/components/PresenceBar.js +1 -1
  29. package/dist/client/components/PresenceBar.js.map +1 -1
  30. package/dist/client/composer/ComposerPlusMenu.d.ts +3 -3
  31. package/dist/client/composer/ComposerPlusMenu.js +3 -3
  32. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  33. package/dist/client/composer/TiptapComposer.js +1 -1
  34. package/dist/client/composer/TiptapComposer.js.map +1 -1
  35. package/dist/client/composer/VoiceButton.js +3 -3
  36. package/dist/client/composer/VoiceButton.js.map +1 -1
  37. package/dist/client/extensions/ExtensionsSidebarSection.js +1 -1
  38. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  39. package/dist/client/index.d.ts +2 -0
  40. package/dist/client/index.d.ts.map +1 -1
  41. package/dist/client/index.js +2 -0
  42. package/dist/client/index.js.map +1 -1
  43. package/dist/client/onboarding/OnboardingPanel.js +1 -1
  44. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  45. package/dist/client/resources/ResourcesPanel.js +2 -2
  46. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  47. package/dist/client/settings/SecretsSection.js +3 -3
  48. package/dist/client/settings/SecretsSection.js.map +1 -1
  49. package/dist/client/use-chat-threads.d.ts +7 -0
  50. package/dist/client/use-chat-threads.d.ts.map +1 -1
  51. package/dist/client/use-chat-threads.js +91 -43
  52. package/dist/client/use-chat-threads.js.map +1 -1
  53. package/dist/client/use-run-stuck-detection.d.ts +47 -0
  54. package/dist/client/use-run-stuck-detection.d.ts.map +1 -0
  55. package/dist/client/use-run-stuck-detection.js +102 -0
  56. package/dist/client/use-run-stuck-detection.js.map +1 -0
  57. package/dist/collab/agent-identity.js +1 -1
  58. package/dist/collab/agent-identity.js.map +1 -1
  59. package/dist/collab/client.js +1 -1
  60. package/dist/collab/client.js.map +1 -1
  61. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  62. package/dist/server/agent-chat-plugin.js +2 -0
  63. package/dist/server/agent-chat-plugin.js.map +1 -1
  64. package/dist/server/google-auth-plugin.d.ts.map +1 -1
  65. package/dist/server/google-auth-plugin.js +28 -2
  66. package/dist/server/google-auth-plugin.js.map +1 -1
  67. package/dist/server/oauth-public-origin.d.ts +2 -0
  68. package/dist/server/oauth-public-origin.d.ts.map +1 -0
  69. package/dist/server/oauth-public-origin.js +28 -0
  70. package/dist/server/oauth-public-origin.js.map +1 -0
  71. package/dist/server/onboarding-html.d.ts.map +1 -1
  72. package/dist/server/onboarding-html.js +24 -0
  73. package/dist/server/onboarding-html.js.map +1 -1
  74. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"google-auth-plugin.d.ts","sourceRoot":"","sources":["../../src/server/google-auth-plugin.ts"],"names":[],"mappings":"AAEA,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9D,MAAM,WAAW,uBAAuB;IACtC,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AA4OD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,CAAC,EAAE,uBAAuB,GAChC,cAAc,CAUhB"}
1
+ {"version":3,"file":"google-auth-plugin.d.ts","sourceRoot":"","sources":["../../src/server/google-auth-plugin.ts"],"names":[],"mappings":"AAGA,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9D,MAAM,WAAW,uBAAuB;IACtC,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAqQD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,CAAC,EAAE,uBAAuB,GAChC,cAAc,CAUhB"}
@@ -1,5 +1,8 @@
1
1
  import { createAuthPlugin } from "./auth-plugin.js";
2
- const GOOGLE_LOGIN_HTML = `<!DOCTYPE html>
2
+ import { getPublicOAuthOrigin } from "./oauth-public-origin.js";
3
+ function getGoogleLoginHtml() {
4
+ const publicOAuthOrigin = getPublicOAuthOrigin();
5
+ return `<!DOCTYPE html>
3
6
  <html lang="en">
4
7
  <head>
5
8
  <meta charset="UTF-8">
@@ -78,6 +81,20 @@ const GOOGLE_LOGIN_HTML = `<!DOCTYPE html>
78
81
  function __anPath(path) {
79
82
  return __anBasePath() + path;
80
83
  }
84
+ var __AN_PUBLIC_OAUTH_ORIGIN = ${JSON.stringify(publicOAuthOrigin)};
85
+ function __anConfiguredOAuthOrigin() {
86
+ if (!__AN_PUBLIC_OAUTH_ORIGIN) return '';
87
+ try {
88
+ var origin = new URL(__AN_PUBLIC_OAUTH_ORIGIN).origin;
89
+ return origin && origin !== window.location.origin ? origin : '';
90
+ } catch(e) {
91
+ return '';
92
+ }
93
+ }
94
+ function __anAuthPath(path) {
95
+ var origin = __anIsBuilderPreview() ? __anConfiguredOAuthOrigin() : '';
96
+ return origin ? origin + path : __anPath(path);
97
+ }
81
98
  function __anIsBuilderPreview() {
82
99
  try {
83
100
  var params = new URLSearchParams(window.location.search);
@@ -213,6 +230,14 @@ const GOOGLE_LOGIN_HTML = `<!DOCTYPE html>
213
230
  __anStartBuilderOAuth(ret, btn, err);
214
231
  return;
215
232
  }
233
+ if (__anIsBuilderPreview()) {
234
+ var params = new URLSearchParams();
235
+ if (ret) params.set('return', ret);
236
+ params.set('redirect', '1');
237
+ __anSetOAuthDebug('Opening Google sign-in redirect');
238
+ __anOpenOAuthUrl(__anAuthPath('/_agent-native/google/auth-url') + '?' + params.toString());
239
+ return;
240
+ }
216
241
  try {
217
242
  var res = await fetch(__anPath('/_agent-native/google/auth-url') + '?return=' + encodeURIComponent(ret));
218
243
  var data = await res.json();
@@ -232,6 +257,7 @@ const GOOGLE_LOGIN_HTML = `<!DOCTYPE html>
232
257
  </script>
233
258
  </body>
234
259
  </html>`;
260
+ }
235
261
  /**
236
262
  * Create an auth plugin that uses Google OAuth for authentication.
237
263
  *
@@ -258,7 +284,7 @@ export function createGoogleAuthPlugin(options) {
258
284
  "/_agent-native/auth/ba",
259
285
  ...(options?.publicPaths ?? []),
260
286
  ],
261
- loginHtml: GOOGLE_LOGIN_HTML,
287
+ loginHtml: getGoogleLoginHtml(),
262
288
  });
263
289
  }
264
290
  //# sourceMappingURL=google-auth-plugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"google-auth-plugin.js","sourceRoot":"","sources":["../../src/server/google-auth-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AASpD,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwOlB,CAAC;AAET;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAiC;IAEjC,OAAO,gBAAgB,CAAC;QACtB,WAAW,EAAE;YACX,gCAAgC;YAChC,gCAAgC;YAChC,wBAAwB;YACxB,GAAG,CAAC,OAAO,EAAE,WAAW,IAAI,EAAE,CAAC;SAChC;QACD,SAAS,EAAE,iBAAiB;KAC7B,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { createAuthPlugin } from \"./auth-plugin.js\";\n\ntype NitroPluginDef = (nitroApp: any) => void | Promise<void>;\n\nexport interface GoogleAuthPluginOptions {\n /** Additional paths accessible without authentication */\n publicPaths?: string[];\n}\n\nconst GOOGLE_LOGIN_HTML = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n<title>Sign in</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n width: 100%;\n max-width: 360px;\n padding: 2rem;\n background: #141414;\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 12px;\n text-align: center;\n }\n h1 { font-size: 1.125rem; font-weight: 600; margin-bottom: 0.5rem; color: #fff; }\n .subtitle { font-size: 0.8125rem; color: #888; margin-bottom: 1.5rem; }\n button {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.625rem;\n padding: 0.625rem;\n background: #fff;\n color: #000;\n border: none;\n border-radius: 8px;\n font-size: 0.9375rem;\n font-weight: 500;\n cursor: pointer;\n }\n button:hover { opacity: 0.85; }\n button:disabled { opacity: 0.5; cursor: wait; }\n .error { margin-top: 0.75rem; font-size: 0.8125rem; color: #f87171; display: none; }\n .error.show { display: block; }\n .debug {\n display: none;\n margin-top: 0.625rem;\n font-size: 0.6875rem;\n line-height: 1.45;\n color: #777;\n word-break: break-word;\n }\n .debug.show { display: block; }\n svg { width: 18px; height: 18px; }\n</style>\n</head>\n<body>\n<div class=\"card\">\n <h1>Sign in</h1>\n <p class=\"subtitle\">Continue with your Google account</p>\n <button id=\"btn\" onclick=\"signIn()\">\n <svg viewBox=\"0 0 24 24\"><path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\"/><path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"/><path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"/><path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"/></svg>\n Sign in with Google\n </button>\n <p class=\"error\" id=\"err\"></p>\n <p class=\"debug\" id=\"debug\"></p>\n</div>\n<script>\n function __anBasePath() {\n var marker = '/_agent-native';\n var idx = window.location.pathname.indexOf(marker);\n return idx > 0 ? window.location.pathname.slice(0, idx) : '';\n }\n function __anPath(path) {\n return __anBasePath() + path;\n }\n function __anIsBuilderPreview() {\n try {\n var params = new URLSearchParams(window.location.search);\n if (params.has('builder.preview') || params.has('builder.frameEditing') || params.has('__builder_editing__')) return true;\n } catch(e) {}\n try {\n var ref = document.referrer || '';\n return ref.indexOf('builder.io') !== -1 || ref.indexOf('builder.my') !== -1 || ref.indexOf('builderio.xyz') !== -1;\n } catch(e) {\n return false;\n }\n }\n function __anIsBuilderDesktop() {\n try {\n var ua = navigator.userAgent || '';\n return ua.indexOf('Electron') !== -1 && ua.indexOf('AgentNativeDesktop') === -1;\n } catch(e) {\n return false;\n }\n }\n var __anOAuthPollTimer = null;\n var __anOAuthPollCount = 0;\n function __anNewOAuthFlowId() {\n try {\n if (window.crypto && typeof window.crypto.randomUUID === 'function') {\n return window.crypto.randomUUID();\n }\n } catch(e) {}\n return 'builder-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2);\n }\n function __anFlowDebugId(flowId) {\n return flowId ? String(flowId).slice(-10) : '';\n }\n function __anSetOAuthDebug(message, flowId) {\n var text = message + (flowId ? ' (flow ' + __anFlowDebugId(flowId) + ')' : '');\n try {\n console.info('[agent-native][google-oauth]', { message: message, flow: __anFlowDebugId(flowId) || undefined });\n } catch(e) {}\n var debug = document.getElementById('debug');\n if (debug) {\n debug.textContent = text;\n debug.classList.add('show');\n }\n }\n function __anShowOAuthError(err, btn, message) {\n if (__anOAuthPollTimer) {\n clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = null;\n }\n err.textContent = message;\n err.classList.add('show');\n btn.disabled = false;\n }\n function __anWaitForOAuthExchange(flowId, ret, btn, err) {\n var started = Date.now();\n var timeoutMs = 5 * 60 * 1000;\n __anOAuthPollCount = 0;\n async function check() {\n __anOAuthPollCount++;\n try {\n var res = await fetch(__anPath('/_agent-native/auth/desktop-exchange') + '?flow_id=' + encodeURIComponent(flowId), { credentials: 'include' });\n var data = await res.json().catch(function() { return {}; });\n if (data && (data.email || data.token)) {\n if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = null;\n __anSetOAuthDebug('OAuth exchange redeemed; returning to the app', flowId);\n window.location.href = ret || '/';\n return;\n }\n if (data && data.error) {\n __anSetOAuthDebug('OAuth exchange returned an error: ' + (data.message || data.error), flowId);\n __anShowOAuthError(err, btn, data.message || data.error);\n return;\n }\n if (data && data.pending && (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0)) {\n __anSetOAuthDebug('Waiting for the Google callback; polling attempt ' + __anOAuthPollCount, flowId);\n }\n } catch(e) {\n if (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0) {\n __anSetOAuthDebug('Could not reach the OAuth exchange endpoint: ' + (e && e.message ? e.message : 'network error'), flowId);\n }\n }\n if (Date.now() - started > timeoutMs) {\n __anShowOAuthError(err, btn, 'Google sign-in did not finish. Flow ' + __anFlowDebugId(flowId) + ' never redeemed; check server logs for [agent-native][google-oauth].');\n }\n }\n if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = setInterval(check, 1000);\n setTimeout(check, 500);\n }\n function __anStartBuilderOAuth(ret, btn, err) {\n var flowId = __anNewOAuthFlowId();\n var params = new URLSearchParams();\n if (ret) params.set('return', ret);\n params.set('desktop', '1');\n params.set('flow_id', flowId);\n params.set('redirect', '1');\n var url = __anPath('/_agent-native/google/auth-url') + '?' + params.toString();\n try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}\n __anSetOAuthDebug('Opening Google sign-in popup', flowId);\n try {\n var popup = window.open('', '_blank', 'width=640,height=760');\n if (!popup) {\n __anShowOAuthError(err, btn, 'Google popup was blocked. Allow popups for this site and try again (flow ' + __anFlowDebugId(flowId) + ').');\n return;\n }\n try { popup.opener = null; } catch(e) {}\n try {\n popup.location.href = url;\n } catch(e) {\n try { popup.close(); } catch(closeErr) {}\n __anShowOAuthError(err, btn, 'Could not navigate Google popup for flow ' + __anFlowDebugId(flowId) + ': ' + (e && e.message ? e.message : 'unknown error'));\n return;\n }\n __anSetOAuthDebug('Google popup opened; waiting for callback', flowId);\n } catch(e) {\n __anShowOAuthError(err, btn, 'Could not open Google popup for flow ' + __anFlowDebugId(flowId) + ': ' + (e && e.message ? e.message : 'unknown error'));\n return;\n }\n __anWaitForOAuthExchange(flowId, ret, btn, err);\n }\n function __anOpenOAuthUrl(url) {\n try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}\n window.location.href = url;\n }\n async function signIn() {\n var btn = document.getElementById('btn');\n var err = document.getElementById('err');\n var ret = window.location.pathname + window.location.search;\n btn.disabled = true;\n err.classList.remove('show');\n if (__anIsBuilderPreview() && !__anIsBuilderDesktop()) {\n __anStartBuilderOAuth(ret, btn, err);\n return;\n }\n try {\n var res = await fetch(__anPath('/_agent-native/google/auth-url') + '?return=' + encodeURIComponent(ret));\n var data = await res.json();\n if (data.url) {\n __anOpenOAuthUrl(data.url);\n } else {\n err.textContent = data.message || 'Google OAuth is not configured. Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.';\n err.classList.add('show');\n btn.disabled = false;\n }\n } catch (e) {\n err.textContent = 'Failed to connect. Please try again.';\n err.classList.add('show');\n btn.disabled = false;\n }\n }\n</script>\n</body>\n</html>`;\n\n/**\n * Create an auth plugin that uses Google OAuth for authentication.\n *\n * When a user visits the app unauthenticated, they see a \"Sign in with Google\"\n * page. The Google OAuth callback (handled by the template) creates a session\n * tied to the user's Google email. `getSession()` then returns `{ email }` for\n * all subsequent requests.\n *\n * Better Auth handles Google OAuth internally when GOOGLE_CLIENT_ID and\n * GOOGLE_CLIENT_SECRET are set. The template's callback route at\n * /_agent-native/google/callback handles mobile deep linking.\n *\n * Usage in a template's `server/plugins/auth.ts`:\n * ```ts\n * import { createGoogleAuthPlugin } from \"@agent-native/core/server\";\n * export default createGoogleAuthPlugin();\n * ```\n */\nexport function createGoogleAuthPlugin(\n options?: GoogleAuthPluginOptions,\n): NitroPluginDef {\n return createAuthPlugin({\n publicPaths: [\n \"/_agent-native/google/callback\",\n \"/_agent-native/google/auth-url\",\n \"/_agent-native/auth/ba\",\n ...(options?.publicPaths ?? []),\n ],\n loginHtml: GOOGLE_LOGIN_HTML,\n });\n}\n"]}
1
+ {"version":3,"file":"google-auth-plugin.js","sourceRoot":"","sources":["../../src/server/google-auth-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAShE,SAAS,kBAAkB;IACzB,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAC;IACjD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mCA+E0B,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA+K5D,CAAC;AACT,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAiC;IAEjC,OAAO,gBAAgB,CAAC;QACtB,WAAW,EAAE;YACX,gCAAgC;YAChC,gCAAgC;YAChC,wBAAwB;YACxB,GAAG,CAAC,OAAO,EAAE,WAAW,IAAI,EAAE,CAAC;SAChC;QACD,SAAS,EAAE,kBAAkB,EAAE;KAChC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { createAuthPlugin } from \"./auth-plugin.js\";\nimport { getPublicOAuthOrigin } from \"./oauth-public-origin.js\";\n\ntype NitroPluginDef = (nitroApp: any) => void | Promise<void>;\n\nexport interface GoogleAuthPluginOptions {\n /** Additional paths accessible without authentication */\n publicPaths?: string[];\n}\n\nfunction getGoogleLoginHtml(): string {\n const publicOAuthOrigin = getPublicOAuthOrigin();\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n<title>Sign in</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n width: 100%;\n max-width: 360px;\n padding: 2rem;\n background: #141414;\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 12px;\n text-align: center;\n }\n h1 { font-size: 1.125rem; font-weight: 600; margin-bottom: 0.5rem; color: #fff; }\n .subtitle { font-size: 0.8125rem; color: #888; margin-bottom: 1.5rem; }\n button {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.625rem;\n padding: 0.625rem;\n background: #fff;\n color: #000;\n border: none;\n border-radius: 8px;\n font-size: 0.9375rem;\n font-weight: 500;\n cursor: pointer;\n }\n button:hover { opacity: 0.85; }\n button:disabled { opacity: 0.5; cursor: wait; }\n .error { margin-top: 0.75rem; font-size: 0.8125rem; color: #f87171; display: none; }\n .error.show { display: block; }\n .debug {\n display: none;\n margin-top: 0.625rem;\n font-size: 0.6875rem;\n line-height: 1.45;\n color: #777;\n word-break: break-word;\n }\n .debug.show { display: block; }\n svg { width: 18px; height: 18px; }\n</style>\n</head>\n<body>\n<div class=\"card\">\n <h1>Sign in</h1>\n <p class=\"subtitle\">Continue with your Google account</p>\n <button id=\"btn\" onclick=\"signIn()\">\n <svg viewBox=\"0 0 24 24\"><path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\"/><path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"/><path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"/><path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"/></svg>\n Sign in with Google\n </button>\n <p class=\"error\" id=\"err\"></p>\n <p class=\"debug\" id=\"debug\"></p>\n</div>\n<script>\n function __anBasePath() {\n var marker = '/_agent-native';\n var idx = window.location.pathname.indexOf(marker);\n return idx > 0 ? window.location.pathname.slice(0, idx) : '';\n }\n function __anPath(path) {\n return __anBasePath() + path;\n }\n var __AN_PUBLIC_OAUTH_ORIGIN = ${JSON.stringify(publicOAuthOrigin)};\n function __anConfiguredOAuthOrigin() {\n if (!__AN_PUBLIC_OAUTH_ORIGIN) return '';\n try {\n var origin = new URL(__AN_PUBLIC_OAUTH_ORIGIN).origin;\n return origin && origin !== window.location.origin ? origin : '';\n } catch(e) {\n return '';\n }\n }\n function __anAuthPath(path) {\n var origin = __anIsBuilderPreview() ? __anConfiguredOAuthOrigin() : '';\n return origin ? origin + path : __anPath(path);\n }\n function __anIsBuilderPreview() {\n try {\n var params = new URLSearchParams(window.location.search);\n if (params.has('builder.preview') || params.has('builder.frameEditing') || params.has('__builder_editing__')) return true;\n } catch(e) {}\n try {\n var ref = document.referrer || '';\n return ref.indexOf('builder.io') !== -1 || ref.indexOf('builder.my') !== -1 || ref.indexOf('builderio.xyz') !== -1;\n } catch(e) {\n return false;\n }\n }\n function __anIsBuilderDesktop() {\n try {\n var ua = navigator.userAgent || '';\n return ua.indexOf('Electron') !== -1 && ua.indexOf('AgentNativeDesktop') === -1;\n } catch(e) {\n return false;\n }\n }\n var __anOAuthPollTimer = null;\n var __anOAuthPollCount = 0;\n function __anNewOAuthFlowId() {\n try {\n if (window.crypto && typeof window.crypto.randomUUID === 'function') {\n return window.crypto.randomUUID();\n }\n } catch(e) {}\n return 'builder-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2);\n }\n function __anFlowDebugId(flowId) {\n return flowId ? String(flowId).slice(-10) : '';\n }\n function __anSetOAuthDebug(message, flowId) {\n var text = message + (flowId ? ' (flow ' + __anFlowDebugId(flowId) + ')' : '');\n try {\n console.info('[agent-native][google-oauth]', { message: message, flow: __anFlowDebugId(flowId) || undefined });\n } catch(e) {}\n var debug = document.getElementById('debug');\n if (debug) {\n debug.textContent = text;\n debug.classList.add('show');\n }\n }\n function __anShowOAuthError(err, btn, message) {\n if (__anOAuthPollTimer) {\n clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = null;\n }\n err.textContent = message;\n err.classList.add('show');\n btn.disabled = false;\n }\n function __anWaitForOAuthExchange(flowId, ret, btn, err) {\n var started = Date.now();\n var timeoutMs = 5 * 60 * 1000;\n __anOAuthPollCount = 0;\n async function check() {\n __anOAuthPollCount++;\n try {\n var res = await fetch(__anPath('/_agent-native/auth/desktop-exchange') + '?flow_id=' + encodeURIComponent(flowId), { credentials: 'include' });\n var data = await res.json().catch(function() { return {}; });\n if (data && (data.email || data.token)) {\n if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = null;\n __anSetOAuthDebug('OAuth exchange redeemed; returning to the app', flowId);\n window.location.href = ret || '/';\n return;\n }\n if (data && data.error) {\n __anSetOAuthDebug('OAuth exchange returned an error: ' + (data.message || data.error), flowId);\n __anShowOAuthError(err, btn, data.message || data.error);\n return;\n }\n if (data && data.pending && (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0)) {\n __anSetOAuthDebug('Waiting for the Google callback; polling attempt ' + __anOAuthPollCount, flowId);\n }\n } catch(e) {\n if (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0) {\n __anSetOAuthDebug('Could not reach the OAuth exchange endpoint: ' + (e && e.message ? e.message : 'network error'), flowId);\n }\n }\n if (Date.now() - started > timeoutMs) {\n __anShowOAuthError(err, btn, 'Google sign-in did not finish. Flow ' + __anFlowDebugId(flowId) + ' never redeemed; check server logs for [agent-native][google-oauth].');\n }\n }\n if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);\n __anOAuthPollTimer = setInterval(check, 1000);\n setTimeout(check, 500);\n }\n function __anStartBuilderOAuth(ret, btn, err) {\n var flowId = __anNewOAuthFlowId();\n var params = new URLSearchParams();\n if (ret) params.set('return', ret);\n params.set('desktop', '1');\n params.set('flow_id', flowId);\n params.set('redirect', '1');\n var url = __anPath('/_agent-native/google/auth-url') + '?' + params.toString();\n try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}\n __anSetOAuthDebug('Opening Google sign-in popup', flowId);\n try {\n var popup = window.open('', '_blank', 'width=640,height=760');\n if (!popup) {\n __anShowOAuthError(err, btn, 'Google popup was blocked. Allow popups for this site and try again (flow ' + __anFlowDebugId(flowId) + ').');\n return;\n }\n try { popup.opener = null; } catch(e) {}\n try {\n popup.location.href = url;\n } catch(e) {\n try { popup.close(); } catch(closeErr) {}\n __anShowOAuthError(err, btn, 'Could not navigate Google popup for flow ' + __anFlowDebugId(flowId) + ': ' + (e && e.message ? e.message : 'unknown error'));\n return;\n }\n __anSetOAuthDebug('Google popup opened; waiting for callback', flowId);\n } catch(e) {\n __anShowOAuthError(err, btn, 'Could not open Google popup for flow ' + __anFlowDebugId(flowId) + ': ' + (e && e.message ? e.message : 'unknown error'));\n return;\n }\n __anWaitForOAuthExchange(flowId, ret, btn, err);\n }\n function __anOpenOAuthUrl(url) {\n try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}\n window.location.href = url;\n }\n async function signIn() {\n var btn = document.getElementById('btn');\n var err = document.getElementById('err');\n var ret = window.location.pathname + window.location.search;\n btn.disabled = true;\n err.classList.remove('show');\n if (__anIsBuilderPreview() && !__anIsBuilderDesktop()) {\n __anStartBuilderOAuth(ret, btn, err);\n return;\n }\n if (__anIsBuilderPreview()) {\n var params = new URLSearchParams();\n if (ret) params.set('return', ret);\n params.set('redirect', '1');\n __anSetOAuthDebug('Opening Google sign-in redirect');\n __anOpenOAuthUrl(__anAuthPath('/_agent-native/google/auth-url') + '?' + params.toString());\n return;\n }\n try {\n var res = await fetch(__anPath('/_agent-native/google/auth-url') + '?return=' + encodeURIComponent(ret));\n var data = await res.json();\n if (data.url) {\n __anOpenOAuthUrl(data.url);\n } else {\n err.textContent = data.message || 'Google OAuth is not configured. Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.';\n err.classList.add('show');\n btn.disabled = false;\n }\n } catch (e) {\n err.textContent = 'Failed to connect. Please try again.';\n err.classList.add('show');\n btn.disabled = false;\n }\n }\n</script>\n</body>\n</html>`;\n}\n\n/**\n * Create an auth plugin that uses Google OAuth for authentication.\n *\n * When a user visits the app unauthenticated, they see a \"Sign in with Google\"\n * page. The Google OAuth callback (handled by the template) creates a session\n * tied to the user's Google email. `getSession()` then returns `{ email }` for\n * all subsequent requests.\n *\n * Better Auth handles Google OAuth internally when GOOGLE_CLIENT_ID and\n * GOOGLE_CLIENT_SECRET are set. The template's callback route at\n * /_agent-native/google/callback handles mobile deep linking.\n *\n * Usage in a template's `server/plugins/auth.ts`:\n * ```ts\n * import { createGoogleAuthPlugin } from \"@agent-native/core/server\";\n * export default createGoogleAuthPlugin();\n * ```\n */\nexport function createGoogleAuthPlugin(\n options?: GoogleAuthPluginOptions,\n): NitroPluginDef {\n return createAuthPlugin({\n publicPaths: [\n \"/_agent-native/google/callback\",\n \"/_agent-native/google/auth-url\",\n \"/_agent-native/auth/ba\",\n ...(options?.publicPaths ?? []),\n ],\n loginHtml: getGoogleLoginHtml(),\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function getPublicOAuthOrigin(): string;
2
+ //# sourceMappingURL=oauth-public-origin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-public-origin.d.ts","sourceRoot":"","sources":["../../src/server/oauth-public-origin.ts"],"names":[],"mappings":"AASA,wBAAgB,oBAAoB,IAAI,MAAM,CAe7C"}
@@ -0,0 +1,28 @@
1
+ function normalizeOrigin(raw) {
2
+ if (!raw)
3
+ return "";
4
+ try {
5
+ return new URL(raw).origin;
6
+ }
7
+ catch {
8
+ return "";
9
+ }
10
+ }
11
+ export function getPublicOAuthOrigin() {
12
+ for (const raw of [
13
+ process.env.WORKSPACE_OAUTH_ORIGIN,
14
+ process.env.VITE_WORKSPACE_OAUTH_ORIGIN,
15
+ process.env.APP_URL,
16
+ process.env.VITE_APP_URL,
17
+ process.env.BETTER_AUTH_URL,
18
+ process.env.VITE_BETTER_AUTH_URL,
19
+ process.env.WORKSPACE_GATEWAY_URL,
20
+ process.env.VITE_WORKSPACE_GATEWAY_URL,
21
+ ]) {
22
+ const origin = normalizeOrigin(raw);
23
+ if (origin)
24
+ return origin;
25
+ }
26
+ return "";
27
+ }
28
+ //# sourceMappingURL=oauth-public-origin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-public-origin.js","sourceRoot":"","sources":["../../src/server/oauth-public-origin.ts"],"names":[],"mappings":"AAAA,SAAS,eAAe,CAAC,GAAuB;IAC9C,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,KAAK,MAAM,GAAG,IAAI;QAChB,OAAO,CAAC,GAAG,CAAC,sBAAsB;QAClC,OAAO,CAAC,GAAG,CAAC,2BAA2B;QACvC,OAAO,CAAC,GAAG,CAAC,OAAO;QACnB,OAAO,CAAC,GAAG,CAAC,YAAY;QACxB,OAAO,CAAC,GAAG,CAAC,eAAe;QAC3B,OAAO,CAAC,GAAG,CAAC,oBAAoB;QAChC,OAAO,CAAC,GAAG,CAAC,qBAAqB;QACjC,OAAO,CAAC,GAAG,CAAC,0BAA0B;KACvC,EAAE,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC","sourcesContent":["function normalizeOrigin(raw: string | undefined): string {\n if (!raw) return \"\";\n try {\n return new URL(raw).origin;\n } catch {\n return \"\";\n }\n}\n\nexport function getPublicOAuthOrigin(): string {\n for (const raw of [\n process.env.WORKSPACE_OAUTH_ORIGIN,\n process.env.VITE_WORKSPACE_OAUTH_ORIGIN,\n process.env.APP_URL,\n process.env.VITE_APP_URL,\n process.env.BETTER_AUTH_URL,\n process.env.VITE_BETTER_AUTH_URL,\n process.env.WORKSPACE_GATEWAY_URL,\n process.env.VITE_WORKSPACE_GATEWAY_URL,\n ]) {\n const origin = normalizeOrigin(raw);\n if (origin) return origin;\n }\n return \"\";\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding-html.d.ts","sourceRoot":"","sources":["../../src/server/onboarding-html.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkCH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF;;;;OAIG;IACH,kBAAkB,CAAC,EAAE;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,qBAA0B,GAAG,MAAM,CAs+C1E;AAED,kDAAkD;AAClD,eAAO,MAAM,eAAe,QAAsB,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAwG7C"}
1
+ {"version":3,"file":"onboarding-html.d.ts","sourceRoot":"","sources":["../../src/server/onboarding-html.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAoCH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF;;;;OAIG;IACH,kBAAkB,CAAC,EAAE;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,qBAA0B,GAAG,MAAM,CA6/C1E;AAED,kDAAkD;AAClD,eAAO,MAAM,eAAe,QAAsB,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAwG7C"}
@@ -6,6 +6,7 @@
6
6
  *
7
7
  * After first account exists, this page acts as a normal login page.
8
8
  */
9
+ import { getPublicOAuthOrigin } from "./oauth-public-origin.js";
9
10
  function hasGoogleOAuth() {
10
11
  return !!(process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET);
11
12
  }
@@ -43,6 +44,7 @@ export function getOnboardingHtml(opts = {}) {
43
44
  const showGoogle = hasGoogleOAuth();
44
45
  const googleOnly = !!opts.googleOnly;
45
46
  const appBasePath = normalizeAppBasePath(process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH);
47
+ const publicOAuthOrigin = getPublicOAuthOrigin();
46
48
  const marketing = opts.marketing;
47
49
  const hasMarketing = !!marketing;
48
50
  const runLocalCommand = marketing?.runLocalCommand?.trim();
@@ -832,6 +834,20 @@ ${googleOnly
832
834
  function __anPath(path) {
833
835
  return __anBasePath() + path;
834
836
  }
837
+ var __AN_PUBLIC_OAUTH_ORIGIN = ${JSON.stringify(publicOAuthOrigin)};
838
+ function __anConfiguredOAuthOrigin() {
839
+ if (!__AN_PUBLIC_OAUTH_ORIGIN) return '';
840
+ try {
841
+ var origin = new URL(__AN_PUBLIC_OAUTH_ORIGIN).origin;
842
+ return origin && origin !== window.location.origin ? origin : '';
843
+ } catch(e) {
844
+ return '';
845
+ }
846
+ }
847
+ function __anAuthPath(path) {
848
+ var origin = __anIsBuilderPreview() ? __anConfiguredOAuthOrigin() : '';
849
+ return origin ? origin + path : __anPath(path);
850
+ }
835
851
  function __anGetReturnPath() {
836
852
  try {
837
853
  var inner = new URLSearchParams(window.location.search).get('return');
@@ -1439,6 +1455,14 @@ ${showGoogle
1439
1455
  __anStartBuilderOAuth(ret, btn, err);
1440
1456
  return;
1441
1457
  }
1458
+ if (__anIsBuilderPreview()) {
1459
+ var params = new URLSearchParams();
1460
+ if (ret) params.set('return', ret);
1461
+ params.set('redirect', '1');
1462
+ __anSetOAuthDebug('Opening Google sign-in redirect');
1463
+ __anOpenOAuthUrl(__anAuthPath('/_agent-native/google/auth-url') + '?' + params.toString());
1464
+ return;
1465
+ }
1442
1466
  try {
1443
1467
  var authUrl = __anPath('/_agent-native/google/auth-url') + '?return=' + encodeURIComponent(ret);
1444
1468
  var res = await fetch(authUrl);