@agent-native/core 0.11.3 → 0.12.0

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 (87) hide show
  1. package/dist/agent/index.d.ts +1 -1
  2. package/dist/agent/index.d.ts.map +1 -1
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/agent/production-agent.d.ts +29 -0
  5. package/dist/agent/production-agent.d.ts.map +1 -1
  6. package/dist/agent/production-agent.js +57 -2
  7. package/dist/agent/production-agent.js.map +1 -1
  8. package/dist/client/AgentPanel.d.ts.map +1 -1
  9. package/dist/client/AgentPanel.js +10 -6
  10. package/dist/client/AgentPanel.js.map +1 -1
  11. package/dist/client/AssistantChat.d.ts.map +1 -1
  12. package/dist/client/AssistantChat.js +29 -9
  13. package/dist/client/AssistantChat.js.map +1 -1
  14. package/dist/client/ConnectBuilderCard.d.ts +3 -3
  15. package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
  16. package/dist/client/ConnectBuilderCard.js +5 -6
  17. package/dist/client/ConnectBuilderCard.js.map +1 -1
  18. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  19. package/dist/client/MultiTabAssistantChat.js +8 -6
  20. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  21. package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
  22. package/dist/client/NewWorkspaceAppFlow.js +2 -0
  23. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  24. package/dist/client/composer/ComposerPlusMenu.js +2 -2
  25. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  26. package/dist/client/composer/TiptapComposer.js +2 -2
  27. package/dist/client/composer/TiptapComposer.js.map +1 -1
  28. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  29. package/dist/client/extensions/ExtensionsListPage.js +36 -4
  30. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  31. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  32. package/dist/client/extensions/ExtensionsSidebarSection.js +67 -47
  33. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  34. package/dist/client/resources/McpServerDetail.d.ts.map +1 -1
  35. package/dist/client/resources/McpServerDetail.js +3 -1
  36. package/dist/client/resources/McpServerDetail.js.map +1 -1
  37. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  38. package/dist/client/resources/ResourcesPanel.js +2 -2
  39. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  40. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  41. package/dist/client/settings/SettingsPanel.js +2 -1
  42. package/dist/client/settings/SettingsPanel.js.map +1 -1
  43. package/dist/client/settings/useBuilderStatus.d.ts +5 -3
  44. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  45. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  46. package/dist/extensions/actions.d.ts.map +1 -1
  47. package/dist/extensions/actions.js +173 -2
  48. package/dist/extensions/actions.js.map +1 -1
  49. package/dist/extensions/html-shell.d.ts.map +1 -1
  50. package/dist/extensions/html-shell.js +47 -1
  51. package/dist/extensions/html-shell.js.map +1 -1
  52. package/dist/extensions/routes.js +1 -1
  53. package/dist/extensions/routes.js.map +1 -1
  54. package/dist/extensions/schema.d.ts +87 -0
  55. package/dist/extensions/schema.d.ts.map +1 -1
  56. package/dist/extensions/schema.js +22 -0
  57. package/dist/extensions/schema.js.map +1 -1
  58. package/dist/extensions/store.d.ts +7 -1
  59. package/dist/extensions/store.d.ts.map +1 -1
  60. package/dist/extensions/store.js +54 -11
  61. package/dist/extensions/store.js.map +1 -1
  62. package/dist/server/agent-chat-plugin.d.ts +6 -0
  63. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  64. package/dist/server/agent-chat-plugin.js +13 -5
  65. package/dist/server/agent-chat-plugin.js.map +1 -1
  66. package/dist/server/builder-browser.d.ts +2 -0
  67. package/dist/server/builder-browser.d.ts.map +1 -1
  68. package/dist/server/builder-browser.js +24 -0
  69. package/dist/server/builder-browser.js.map +1 -1
  70. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  71. package/dist/server/core-routes-plugin.js +46 -29
  72. package/dist/server/core-routes-plugin.js.map +1 -1
  73. package/dist/server/index.d.ts +3 -3
  74. package/dist/server/index.d.ts.map +1 -1
  75. package/dist/server/index.js +2 -2
  76. package/dist/server/index.js.map +1 -1
  77. package/dist/server/request-context.d.ts +11 -0
  78. package/dist/server/request-context.d.ts.map +1 -1
  79. package/dist/server/request-context.js.map +1 -1
  80. package/dist/templates/workspace-core/AGENTS.md +19 -3
  81. package/dist/templates/workspace-root/AGENTS.md +20 -0
  82. package/dist/templates/workspace-root/README.md +6 -0
  83. package/docs/content/extensions.md +12 -11
  84. package/package.json +1 -1
  85. package/src/templates/workspace-core/AGENTS.md +19 -3
  86. package/src/templates/workspace-root/AGENTS.md +20 -0
  87. package/src/templates/workspace-root/README.md +6 -0
@@ -11,6 +11,8 @@ export interface BuilderStatus {
11
11
  connectUrl: string;
12
12
  appHost: string;
13
13
  apiHost: string;
14
+ branchProjectIdConfigured?: boolean;
15
+ branchProjectId?: string;
14
16
  publicKeyConfigured: boolean;
15
17
  privateKeyConfigured: boolean;
16
18
  userId?: string;
@@ -52,9 +54,9 @@ export interface BuilderConnectFlow {
52
54
  */
53
55
  envManaged: boolean;
54
56
  /**
55
- * True when ENABLE_BUILDER (or a BUILDER_BRANCH_PROJECT_ID) is set on the
56
- * deploy, gating Builder cloud branch creation. When false, the card
57
- * surfaces a "coming soon" waitlist CTA instead of a Send button.
57
+ * True when the server has a Builder branch project configured for this
58
+ * request. When false, the card surfaces a waitlist CTA instead of a Send
59
+ * button.
58
60
  */
59
61
  builderEnabled: boolean;
60
62
  orgName: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"useBuilderStatus.d.ts","sourceRoot":"","sources":["../../../src/client/settings/useBuilderStatus.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,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,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;AAcD,wBAAgB,qBAAqB,CACnC,IAAI,GAAE,yBAA8B,GACnC,kBAAkB,CAuOpB"}
1
+ {"version":3,"file":"useBuilderStatus.d.ts","sourceRoot":"","sources":["../../../src/client/settings/useBuilderStatus.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,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,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;AAcD,wBAAgB,qBAAqB,CACnC,IAAI,GAAE,yBAA8B,GACnC,kBAAkB,CAuOpB"}
@@ -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\";\n\nexport interface BuilderStatus {\n configured: boolean;\n builderEnabled: boolean;\n /**\n * True when `BUILDER_PRIVATE_KEY` is set at the deploy level. Every user\n * of this deploy shares the operator's Builder identity and per-user\n * connect/disconnect is disabled. UIs must hide connect prompts and\n * disconnect buttons when this is true.\n */\n envManaged?: boolean;\n connectUrl: string;\n appHost: string;\n apiHost: 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 /** 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. UIs should treat\n * Builder as connected for everyone in this mode and hide all connect /\n * disconnect controls — `start()` will be a no-op.\n */\n envManaged: boolean;\n /**\n * True when ENABLE_BUILDER (or a BUILDER_BRANCH_PROJECT_ID) is set on the\n * deploy, gating Builder cloud branch creation. When false, the card\n * surfaces a \"coming soon\" waitlist CTA instead of a Send 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;\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\nexport function useBuilderConnectFlow(\n opts: BuilderConnectFlowOptions = {},\n): BuilderConnectFlow {\n const { popupUrl, onConnected } = 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 silently\n // fails the same-origin check on the popup side. Track freshness so\n // start() can fall back to the bare /builder/connect path when stale.\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 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 setStatusConnectUrl(s.connectUrl ?? null);\n statusConnectUrlAtRef.current = s.connectUrl ? 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 // In env-managed mode, per-user OAuth is disabled — `/builder/connect`\n // returns 409. Skip the popup and just refresh state so the UI flips\n // to its \"connected via deployment\" rendering.\n if (envManaged) return;\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 // The signed _an_connect token in statusConnectUrl has a 10-minute TTL.\n // If the panel has been open longer than that the token is dead and the\n // popup will silently 403; drop the cached URL and let the bare /connect\n // route do the same-origin Sec-Fetch-Site check instead.\n const STATUS_CONNECT_URL_TTL_MS = 9 * 60 * 1000;\n const cachedAt = statusConnectUrlAtRef.current;\n const cachedFresh =\n typeof cachedAt === \"number\" &&\n Date.now() - cachedAt < STATUS_CONNECT_URL_TTL_MS;\n const url =\n (cachedFresh ? statusConnectUrl : null) ??\n popupUrl ??\n new URL(agentNativePath(\"/_agent-native/builder/connect\"), origin).href;\n try {\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n } catch {\n // Fall through — polling still detects completion if the user\n // opens the URL themselves.\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 setStatusConnectUrl(s.connectUrl ?? null);\n statusConnectUrlAtRef.current = s.connectUrl ? 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 setError(\n \"Didn't hear back from Builder in 5 minutes. Allow popups and try again.\",\n );\n }\n }, POLL_INTERVAL_MS);\n }, [envManaged, fetchStatus, popupUrl, statusConnectUrl, stopPoll]);\n\n // Popup-side fast path: the error 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\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-error\") return;\n if (typeof data.message !== \"string\" || !data.message) return;\n handleError(data.message);\n };\n } catch {\n // BroadcastChannel not available (rare) \\u2014 fall through to postMessage.\n }\n\n const handler = (e: MessageEvent) => {\n if (e.origin !== window.location.origin) return;\n const data = e.data as { type?: string; message?: string } | undefined;\n if (data?.type !== \"builder-connect-error\") return;\n if (typeof data.message !== \"string\" || !data.message) return;\n handleError(data.message);\n };\n window.addEventListener(\"message\", handler);\n\n return () => {\n channel?.close();\n window.removeEventListener(\"message\", handler);\n };\n }, [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":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport { getCallbackOrigin } from \"../frame.js\";\n\nexport interface BuilderStatus {\n configured: boolean;\n builderEnabled: boolean;\n /**\n * True when `BUILDER_PRIVATE_KEY` is set at the deploy level. Every user\n * of this deploy shares the operator's Builder identity and per-user\n * connect/disconnect is disabled. UIs must hide connect prompts and\n * disconnect buttons when this is true.\n */\n envManaged?: boolean;\n connectUrl: 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 /** 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. UIs should treat\n * Builder as connected for everyone in this mode and hide all connect /\n * disconnect controls — `start()` will be a no-op.\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;\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\nexport function useBuilderConnectFlow(\n opts: BuilderConnectFlowOptions = {},\n): BuilderConnectFlow {\n const { popupUrl, onConnected } = 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 silently\n // fails the same-origin check on the popup side. Track freshness so\n // start() can fall back to the bare /builder/connect path when stale.\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 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 setStatusConnectUrl(s.connectUrl ?? null);\n statusConnectUrlAtRef.current = s.connectUrl ? 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 // In env-managed mode, per-user OAuth is disabled — `/builder/connect`\n // returns 409. Skip the popup and just refresh state so the UI flips\n // to its \"connected via deployment\" rendering.\n if (envManaged) return;\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 // The signed _an_connect token in statusConnectUrl has a 10-minute TTL.\n // If the panel has been open longer than that the token is dead and the\n // popup will silently 403; drop the cached URL and let the bare /connect\n // route do the same-origin Sec-Fetch-Site check instead.\n const STATUS_CONNECT_URL_TTL_MS = 9 * 60 * 1000;\n const cachedAt = statusConnectUrlAtRef.current;\n const cachedFresh =\n typeof cachedAt === \"number\" &&\n Date.now() - cachedAt < STATUS_CONNECT_URL_TTL_MS;\n const url =\n (cachedFresh ? statusConnectUrl : null) ??\n popupUrl ??\n new URL(agentNativePath(\"/_agent-native/builder/connect\"), origin).href;\n try {\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n } catch {\n // Fall through — polling still detects completion if the user\n // opens the URL themselves.\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 setStatusConnectUrl(s.connectUrl ?? null);\n statusConnectUrlAtRef.current = s.connectUrl ? 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 setError(\n \"Didn't hear back from Builder in 5 minutes. Allow popups and try again.\",\n );\n }\n }, POLL_INTERVAL_MS);\n }, [envManaged, fetchStatus, popupUrl, statusConnectUrl, stopPoll]);\n\n // Popup-side fast path: the error 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\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-error\") return;\n if (typeof data.message !== \"string\" || !data.message) return;\n handleError(data.message);\n };\n } catch {\n // BroadcastChannel not available (rare) \\u2014 fall through to postMessage.\n }\n\n const handler = (e: MessageEvent) => {\n if (e.origin !== window.location.origin) return;\n const data = e.data as { type?: string; message?: string } | undefined;\n if (data?.type !== \"builder-connect-error\") return;\n if (typeof data.message !== \"string\" || !data.message) return;\n handleError(data.message);\n };\n window.addEventListener(\"message\", handler);\n\n return () => {\n channel?.close();\n window.removeEventListener(\"message\", handler);\n };\n }, [stopPoll]);\n\n return {\n configured,\n envManaged,\n builderEnabled,\n orgName,\n connecting,\n error,\n hasFetchedStatus,\n start,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/extensions/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAkBhE,wBAAgB,4BAA4B,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAiS1E"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/extensions/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAyBhE,wBAAgB,4BAA4B,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAob1E"}
@@ -1,11 +1,62 @@
1
1
  import { writeAppState } from "../application-state/script-helpers.js";
2
- import { createExtension, getExtension, updateExtension, updateExtensionContent, } from "./store.js";
2
+ import { createExtension, deleteExtension, getHiddenExtensionIdsForCurrentUser, getExtension, hideExtension, listExtensions, unhideExtension, updateExtension, updateExtensionContent, } from "./store.js";
3
+ import { resolveAccess } from "../sharing/access.js";
3
4
  import { addExtensionSlotTarget, installExtensionSlot, uninstallExtensionSlot, listExtensionsForSlot, listSlotsForExtension, } from "./slots/store.js";
4
5
  export function createExtensionActionEntries() {
5
6
  return {
7
+ "list-extensions": {
8
+ tool: {
9
+ description: "List extensions visible in the current user's Extensions list/sidebar. Use this before updating, hiding, or deleting existing extensions; do not query the legacy tools table directly for extension management.",
10
+ parameters: {
11
+ type: "object",
12
+ properties: {
13
+ search: {
14
+ type: "string",
15
+ description: "Optional case-insensitive filter matched against id, name, description, and owner email. Example: Connect Zoom.",
16
+ },
17
+ includeHidden: {
18
+ type: "boolean",
19
+ description: "Include extensions the current user has hidden from their list. Defaults to false.",
20
+ },
21
+ includeContent: {
22
+ type: "boolean",
23
+ description: "Include full Alpine.js content. Defaults to false to keep results concise.",
24
+ },
25
+ limit: {
26
+ type: "number",
27
+ description: "Maximum results to return. Defaults to 100.",
28
+ },
29
+ },
30
+ },
31
+ },
32
+ run: async (args) => {
33
+ const includeHidden = coerceBoolean(args?.includeHidden);
34
+ const includeContent = coerceBoolean(args?.includeContent);
35
+ const search = String(args?.search ?? "")
36
+ .trim()
37
+ .toLowerCase();
38
+ const limit = coerceLimit(args?.limit);
39
+ const hiddenIds = await getHiddenExtensionIdsForCurrentUser();
40
+ let rows = await listExtensions({ includeHidden });
41
+ if (search) {
42
+ rows = rows.filter((row) => [row.id, row.name, row.description, row.ownerEmail]
43
+ .join("\n")
44
+ .toLowerCase()
45
+ .includes(search));
46
+ }
47
+ rows = rows.slice(0, limit);
48
+ const extensions = await Promise.all(rows.map((row) => summarizeExtension(row, hiddenIds, includeContent)));
49
+ return {
50
+ ok: true,
51
+ count: extensions.length,
52
+ extensions,
53
+ };
54
+ },
55
+ readOnly: true,
56
+ },
6
57
  "create-extension": {
7
58
  tool: {
8
- description: "Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction()/appFetch() for app data; parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables.",
59
+ description: "Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. Call this action exactly once per requested extension. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction(name, params) for app data and actions, including read actions mounted as GET; do not call template /api/* routes from appFetch because the extension bridge only allows framework /_agent-native/* paths. Parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables.",
9
60
  parameters: {
10
61
  type: "object",
11
62
  properties: {
@@ -137,6 +188,89 @@ export function createExtensionActionEntries() {
137
188
  return { ok: true, extension: result };
138
189
  },
139
190
  },
191
+ "delete-extension": {
192
+ tool: {
193
+ description: "Permanently delete an extension everywhere it is shared. Requires owner/admin access. If the user only wants a shared extension removed from their own sidebar/list, use hide-extension instead.",
194
+ parameters: {
195
+ type: "object",
196
+ properties: {
197
+ id: {
198
+ type: "string",
199
+ description: "Extension id to permanently delete. Use list-extensions first if you only know the display name.",
200
+ },
201
+ },
202
+ required: ["id"],
203
+ },
204
+ },
205
+ run: async (args) => {
206
+ const id = String(args?.id ?? "").trim();
207
+ if (!id)
208
+ return "Error: id is required.";
209
+ const extension = await getExtension(id);
210
+ if (!extension)
211
+ return `Error: extension not found: ${id}`;
212
+ try {
213
+ const ok = await deleteExtension(id);
214
+ if (!ok)
215
+ return `Error: extension not found: ${id}`;
216
+ return { ok: true, deleted: summarizeDeletedExtension(extension) };
217
+ }
218
+ catch (err) {
219
+ return {
220
+ ok: false,
221
+ error: err?.message ?? String(err),
222
+ next: "If the user wants this gone only from their own view, call hide-extension with the same id.",
223
+ };
224
+ }
225
+ },
226
+ },
227
+ "hide-extension": {
228
+ tool: {
229
+ description: "Hide an accessible extension from the current user's Extensions list/sidebar without deleting it for anyone else. Use this when the user says to remove a shared extension from their view, or when delete-extension reports that the current user is not owner/admin.",
230
+ parameters: {
231
+ type: "object",
232
+ properties: {
233
+ id: {
234
+ type: "string",
235
+ description: "Extension id to hide for the current user. Use list-extensions first if you only know the display name.",
236
+ },
237
+ },
238
+ required: ["id"],
239
+ },
240
+ },
241
+ run: async (args) => {
242
+ const id = String(args?.id ?? "").trim();
243
+ if (!id)
244
+ return "Error: id is required.";
245
+ const extension = await getExtension(id);
246
+ if (!extension)
247
+ return `Error: extension not found: ${id}`;
248
+ await hideExtension(id);
249
+ return { ok: true, hidden: summarizeDeletedExtension(extension) };
250
+ },
251
+ },
252
+ "unhide-extension": {
253
+ tool: {
254
+ description: "Restore an extension the current user previously hid so it appears in their Extensions list/sidebar again. Use list-extensions with includeHidden=true to find hidden ids.",
255
+ parameters: {
256
+ type: "object",
257
+ properties: {
258
+ id: {
259
+ type: "string",
260
+ description: "Extension id to restore for the current user.",
261
+ },
262
+ },
263
+ required: ["id"],
264
+ },
265
+ },
266
+ run: async (args) => {
267
+ const id = String(args?.id ?? "").trim();
268
+ if (!id)
269
+ return "Error: id is required.";
270
+ await unhideExtension(id);
271
+ return { ok: true, id };
272
+ },
273
+ },
140
274
  "add-extension-slot-target": {
141
275
  tool: {
142
276
  description: 'Declare that an extension can render in a UI extension-point slot of an app (e.g. "mail.contact-sidebar.bottom"). Apps drop ExtensionSlot components in their UI; this action registers an extension as installable into one of those slots. Slot IDs follow the convention <app>.<area>.<position>. Caller must have editor access to the extension.',
@@ -273,6 +407,43 @@ export function createExtensionActionEntries() {
273
407
  },
274
408
  };
275
409
  }
410
+ async function summarizeExtension(row, hiddenIds, includeContent) {
411
+ const access = await resolveAccess("extension", row.id).catch(() => null);
412
+ return {
413
+ id: row.id,
414
+ name: row.name,
415
+ description: row.description,
416
+ icon: row.icon,
417
+ ownerEmail: row.ownerEmail,
418
+ visibility: row.visibility,
419
+ role: access?.role ?? null,
420
+ canEdit: access
421
+ ? ["owner", "admin", "editor"].includes(access.role)
422
+ : false,
423
+ canDelete: access ? ["owner", "admin"].includes(access.role) : false,
424
+ hidden: hiddenIds.has(row.id),
425
+ createdAt: row.createdAt,
426
+ updatedAt: row.updatedAt,
427
+ ...(includeContent ? { content: row.content } : {}),
428
+ };
429
+ }
430
+ function summarizeDeletedExtension(row) {
431
+ return {
432
+ id: row.id,
433
+ name: row.name,
434
+ ownerEmail: row.ownerEmail,
435
+ visibility: row.visibility,
436
+ };
437
+ }
438
+ function coerceBoolean(value) {
439
+ return value === true || value === "true";
440
+ }
441
+ function coerceLimit(value) {
442
+ const limit = Number(value ?? 100);
443
+ if (!Number.isFinite(limit))
444
+ return 100;
445
+ return Math.min(Math.max(1, Math.floor(limit)), 500);
446
+ }
276
447
  function parsePatches(value) {
277
448
  if (value === undefined)
278
449
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/extensions/actions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EACL,eAAe,EACf,YAAY,EACZ,eAAe,EACf,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAI1B,MAAM,UAAU,4BAA4B;IAC1C,OAAO;QACL,kBAAkB,EAAE;YAClB,IAAI,EAAE;gBACJ,WAAW,EACT,+cAA+c;gBACjd,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,IAAI,EAAE;4BACJ,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,qHAAqH;yBACxH;wBACD,WAAW,EAAE;4BACX,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,kDAAkD;yBAChE;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,kUAAkU;yBACrU;wBACD,IAAI,EAAE;4BACJ,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,oCAAoC;yBAClD;qBACF;oBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;iBAC9B;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACnD,IAAI,CAAC,IAAI;oBAAE,OAAO,0BAA0B,CAAC;gBAC7C,IAAI,CAAC,OAAO;oBAAE,OAAO,6BAA6B,CAAC;gBAEnD,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC;oBACtC,IAAI;oBACJ,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;oBACnD,OAAO;oBACP,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;iBACjD,CAAC,CAAC;gBAEH,kEAAkE;gBAClE,8DAA8D;gBAC9D,oEAAoE;gBACpE,IAAI,CAAC;oBACH,MAAM,aAAa,CAAC,UAAU,EAAE;wBAC9B,IAAI,EAAE,YAAY;wBAClB,WAAW,EAAE,SAAS,CAAC,EAAE;wBACzB,IAAI,EAAE,eAAe,SAAS,CAAC,EAAE,EAAE;qBACpC,CAAC,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACP,6DAA6D;gBAC/D,CAAC;gBAED,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,SAAS;oBACT,IAAI,EAAE,oHAAoH;iBAC3H,CAAC;YACJ,CAAC;SACF;QAED,kBAAkB,EAAE;YAClB,IAAI,EAAE;gBACJ,WAAW,EACT,iJAAiJ;gBACnJ,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE;4BACF,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,yBAAyB;yBACvC;wBACD,IAAI,EAAE;4BACJ,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,4BAA4B;yBAC1C;wBACD,WAAW,EAAE;4BACX,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,2BAA2B;yBACzC;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,wDAAwD;yBAC3D;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,qGAAqG;yBACxG;wBACD,IAAI,EAAE;4BACJ,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,oCAAoC;yBAClD;wBACD,UAAU,EAAE;4BACV,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,8BAA8B;4BAC3C,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC;yBACnC;qBACF;oBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE;oBAAE,OAAO,wBAAwB,CAAC;gBAEzC,IAAI,MAAM,GAAG,IAAI,CAAC;gBAClB,IAAI,IAAI,EAAE,OAAO,KAAK,SAAS,IAAI,IAAI,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC/D,MAAM,OAAO,GAAG,YAAY,CAAE,IAAY,CAAC,OAAO,CAAC,CAAC;oBACpD,IAAI,IAAI,EAAE,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;wBAC5C,OAAO,mEAAmE,CAAC;oBAC7E,CAAC;oBACD,MAAM,GAAG,MAAM,sBAAsB,CAAC,EAAE,EAAE;wBACxC,OAAO,EACL,IAAI,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;wBAChE,OAAO;qBACR,CAAC,CAAC;gBACL,CAAC;gBAED,MAAM,IAAI,GAA2B,EAAE,CAAC;gBACxC,IAAI,IAAI,EAAE,IAAI,KAAK,SAAS;oBAAE,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;gBACnE,IAAI,IAAI,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;oBACpC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;gBACrD,CAAC;gBACD,IAAI,IAAI,EAAE,IAAI,KAAK,SAAS;oBAAE,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5D,IAAI,IAAI,EAAE,UAAU,KAAK,SAAS,EAAE,CAAC;oBACnC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC5C,CAAC;gBACD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACjC,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,IAAW,CAAC,CAAC;gBAClD,CAAC;gBAED,IAAI,CAAC,MAAM;oBAAE,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;gBAC7C,IAAI,CAAC,MAAM;oBAAE,OAAO,+BAA+B,EAAE,EAAE,CAAC;gBACxD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;YACzC,CAAC;SACF;QAED,2BAA2B,EAAE;YAC3B,IAAI,EAAE;gBACJ,WAAW,EACT,uVAAuV;gBACzV,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;wBAC7D,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,uDAAuD;yBAC1D;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,yEAAyE;yBAC5E;qBACF;oBACD,QAAQ,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC;iBACpC;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,CAAC,WAAW;oBAAE,OAAO,iCAAiC,CAAC;gBAC3D,IAAI,CAAC,MAAM;oBAAE,OAAO,4BAA4B,CAAC;gBACjD,MAAM,GAAG,GAAG,MAAM,sBAAsB,CACtC,WAAW,EACX,MAAM,EACN,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAC/C,CAAC;gBACF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;YACjC,CAAC;SACF;QAED,mBAAmB,EAAE;YACnB,IAAI,EAAE;gBACJ,WAAW,EACT,4UAA4U;gBAC9U,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,WAAW,EAAE;4BACX,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,0BAA0B;yBACxC;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,uDAAuD;yBAC1D;wBACD,QAAQ,EAAE;4BACR,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,+EAA+E;yBAClF;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,qEAAqE;yBACxE;qBACF;oBACD,QAAQ,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC;iBACpC;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,CAAC,WAAW;oBAAE,OAAO,iCAAiC,CAAC;gBAC3D,IAAI,CAAC,MAAM;oBAAE,OAAO,4BAA4B,CAAC;gBACjD,MAAM,QAAQ,GACZ,IAAI,EAAE,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;oBACpD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;oBACvB,CAAC,CAAC,SAAS,CAAC;gBAChB,MAAM,GAAG,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE;oBAC1D,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAkB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;oBACpE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;iBACvD,CAAC,CAAC;gBACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YACpC,CAAC;SACF;QAED,qBAAqB,EAAE;YACrB,IAAI,EAAE;gBACJ,WAAW,EACT,8GAA8G;gBAChH,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;wBAC7D,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE;qBAC5D;oBACD,QAAQ,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC;iBACpC;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,CAAC,WAAW;oBAAE,OAAO,iCAAiC,CAAC;gBAC3D,IAAI,CAAC,MAAM;oBAAE,OAAO,4BAA4B,CAAC;gBACjD,MAAM,sBAAsB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;gBAClD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YACtB,CAAC;SACF;QAED,0BAA0B,EAAE;YAC1B,IAAI,EAAE;gBACJ,WAAW,EACT,uKAAuK;gBACzK,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE;qBAC5D;oBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;iBACrB;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,CAAC,MAAM;oBAAE,OAAO,4BAA4B,CAAC;gBACjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7D,CAAC;YACD,QAAQ,EAAE,IAAI;SACf;QAED,sBAAsB,EAAE;YACtB,IAAI,EAAE;gBACJ,WAAW,EACT,iIAAiI;gBACnI,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;qBAC9D;oBACD,QAAQ,EAAE,CAAC,aAAa,CAAC;iBAC1B;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,IAAI,CAAC,WAAW;oBAAE,OAAO,iCAAiC,CAAC;gBAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7D,CAAC;YACD,QAAQ,EAAE,IAAI;SACf;KACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACrE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7C,IACE,MAAM,CAAC,IAAI,CACT,CAAC,KAAK,EAAE,EAAE,CACR,CAAC,KAAK;QACN,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CACpC,EACD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type { ActionEntry } from \"../agent/production-agent.js\";\nimport { writeAppState } from \"../application-state/script-helpers.js\";\nimport {\n createExtension,\n getExtension,\n updateExtension,\n updateExtensionContent,\n} from \"./store.js\";\nimport {\n addExtensionSlotTarget,\n installExtensionSlot,\n uninstallExtensionSlot,\n listExtensionsForSlot,\n listSlotsForExtension,\n} from \"./slots/store.js\";\n\ntype ExtensionPatch = { find: string; replace: string };\n\nexport function createExtensionActionEntries(): Record<string, ActionEntry> {\n return {\n \"create-extension\": {\n tool: {\n description:\n \"Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction()/appFetch() for app data; parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables.\",\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n 'Short display name for the extension. Do not include \"app\" — e.g. name a todo app \"Todos\", a weather app \"Weather\".',\n },\n description: {\n type: \"string\",\n description: \"One-sentence summary of what the extension does.\",\n },\n content: {\n type: \"string\",\n description:\n \"Self-contained Alpine.js HTML body snippet. The iframe canvas already has modest default padding, so avoid duplicate outer padding unless the design needs it. Use semantic Tailwind colors (bg-background, text-foreground, bg-primary, etc.) for native theming. Do not include a full app build, React code, or source files.\",\n },\n icon: {\n type: \"string\",\n description: \"Optional icon name or short label.\",\n },\n },\n required: [\"name\", \"content\"],\n },\n },\n run: async (args) => {\n const name = String(args?.name ?? \"\").trim();\n const content = String(args?.content ?? \"\").trim();\n if (!name) return \"Error: name is required.\";\n if (!content) return \"Error: content is required.\";\n\n const extension = await createExtension({\n name,\n description: String(args?.description ?? \"\").trim(),\n content,\n icon: args?.icon ? String(args.icon) : undefined,\n });\n\n // Auto-navigate so the user lands on the new extension instead of\n // having to read the JSON response and click a link. Writes a\n // one-shot `navigate` app-state command the UI consumes and clears.\n try {\n await writeAppState(\"navigate\", {\n view: \"extensions\",\n extensionId: extension.id,\n path: `/extensions/${extension.id}`,\n });\n } catch {\n // Non-fatal — agent can still mention the path in its reply.\n }\n\n return {\n ok: true,\n extension,\n next: `Created. The user is being navigated to the new extension automatically — no further navigation tool calls needed.`,\n };\n },\n },\n\n \"update-extension\": {\n tool: {\n description:\n \"Update an existing sandboxed Alpine.js mini-app extension. Prefer patches for surgical edits; use full content replacement only when necessary.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Extension id to update.\",\n },\n name: {\n type: \"string\",\n description: \"Optional new display name.\",\n },\n description: {\n type: \"string\",\n description: \"Optional new description.\",\n },\n content: {\n type: \"string\",\n description:\n \"Optional full replacement Alpine.js HTML body snippet.\",\n },\n patches: {\n type: \"string\",\n description:\n 'Optional JSON array of { \"find\": \"...\", \"replace\": \"...\" } patches to apply to the current content.',\n },\n icon: {\n type: \"string\",\n description: \"Optional icon name or short label.\",\n },\n visibility: {\n type: \"string\",\n description: \"Optional sharing visibility.\",\n enum: [\"private\", \"org\", \"public\"],\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n\n let result = null;\n if (args?.content !== undefined || args?.patches !== undefined) {\n const patches = parsePatches((args as any).patches);\n if (args?.patches !== undefined && !patches) {\n return \"Error: patches must be a JSON array of { find, replace } objects.\";\n }\n result = await updateExtensionContent(id, {\n content:\n args?.content !== undefined ? String(args.content) : undefined,\n patches,\n });\n }\n\n const meta: Record<string, string> = {};\n if (args?.name !== undefined) meta.name = String(args.name).trim();\n if (args?.description !== undefined) {\n meta.description = String(args.description).trim();\n }\n if (args?.icon !== undefined) meta.icon = String(args.icon);\n if (args?.visibility !== undefined) {\n meta.visibility = String(args.visibility);\n }\n if (Object.keys(meta).length > 0) {\n result = await updateExtension(id, meta as any);\n }\n\n if (!result) result = await getExtension(id);\n if (!result) return `Error: extension not found: ${id}`;\n return { ok: true, extension: result };\n },\n },\n\n \"add-extension-slot-target\": {\n tool: {\n description:\n 'Declare that an extension can render in a UI extension-point slot of an app (e.g. \"mail.contact-sidebar.bottom\"). Apps drop ExtensionSlot components in their UI; this action registers an extension as installable into one of those slots. Slot IDs follow the convention <app>.<area>.<position>. Caller must have editor access to the extension.',\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n slotId: {\n type: \"string\",\n description:\n 'Slot identifier — e.g. \"mail.contact-sidebar.bottom\".',\n },\n config: {\n type: \"string\",\n description:\n \"Optional JSON string with slot-specific config (defaults, hints, etc.).\",\n },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n const row = await addExtensionSlotTarget(\n extensionId,\n slotId,\n args?.config ? String(args.config) : undefined,\n );\n return { ok: true, slot: row };\n },\n },\n\n \"install-extension\": {\n tool: {\n description:\n \"Install an extension as a widget in an extension-point slot for the current user. The extension must already declare the slot via add-extension-slot-target. Per-user installation — only affects the calling user's view. Use after creating an extension that targets a slot, or when the user asks to add an existing widget to a slot.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: {\n type: \"string\",\n description: \"Extension id to install.\",\n },\n slotId: {\n type: \"string\",\n description:\n 'Slot identifier — e.g. \"mail.contact-sidebar.bottom\".',\n },\n position: {\n type: \"number\",\n description:\n \"Optional integer position within the slot (lower = earlier). Defaults to end.\",\n },\n config: {\n type: \"string\",\n description:\n \"Optional JSON string with per-install config (overrides, settings).\",\n },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n const position =\n args?.position !== undefined && args.position !== null\n ? Number(args.position)\n : undefined;\n const row = await installExtensionSlot(extensionId, slotId, {\n position: Number.isFinite(position as number) ? position : undefined,\n config: args?.config ? String(args.config) : undefined,\n });\n return { ok: true, install: row };\n },\n },\n\n \"uninstall-extension\": {\n tool: {\n description:\n \"Remove an extension from an extension-point slot for the current user. Does not delete the extension itself.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n slotId: { type: \"string\", description: \"Slot identifier.\" },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n await uninstallExtensionSlot(extensionId, slotId);\n return { ok: true };\n },\n },\n\n \"list-extensions-for-slot\": {\n tool: {\n description:\n \"List extensions the current user has access to that declare a given extension-point slot. Use to discover what's available to install into a slot the user mentioned.\",\n parameters: {\n type: \"object\",\n properties: {\n slotId: { type: \"string\", description: \"Slot identifier.\" },\n },\n required: [\"slotId\"],\n },\n },\n run: async (args) => {\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!slotId) return \"Error: slotId is required.\";\n return { extensions: await listExtensionsForSlot(slotId) };\n },\n readOnly: true,\n },\n\n \"list-extension-slots\": {\n tool: {\n description:\n \"List the extension-point slots a specific extension declares it can render in. Caller must have viewer access to the extension.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n },\n required: [\"extensionId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n return { slots: await listSlotsForExtension(extensionId) };\n },\n readOnly: true,\n },\n };\n}\n\nfunction parsePatches(value: unknown): ExtensionPatch[] | undefined {\n if (value === undefined) return undefined;\n const parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n if (!Array.isArray(parsed)) return undefined;\n if (\n parsed.some(\n (patch) =>\n !patch ||\n typeof patch.find !== \"string\" ||\n typeof patch.replace !== \"string\",\n )\n ) {\n return undefined;\n }\n return parsed;\n}\n"]}
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/extensions/actions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ActionEntry } from \"../agent/production-agent.js\";\nimport { writeAppState } from \"../application-state/script-helpers.js\";\nimport {\n createExtension,\n deleteExtension,\n getHiddenExtensionIdsForCurrentUser,\n getExtension,\n hideExtension,\n listExtensions,\n unhideExtension,\n updateExtension,\n updateExtensionContent,\n type ExtensionRow,\n} from \"./store.js\";\nimport { resolveAccess } from \"../sharing/access.js\";\nimport {\n addExtensionSlotTarget,\n installExtensionSlot,\n uninstallExtensionSlot,\n listExtensionsForSlot,\n listSlotsForExtension,\n} from \"./slots/store.js\";\n\ntype ExtensionPatch = { find: string; replace: string };\n\nexport function createExtensionActionEntries(): Record<string, ActionEntry> {\n return {\n \"list-extensions\": {\n tool: {\n description:\n \"List extensions visible in the current user's Extensions list/sidebar. Use this before updating, hiding, or deleting existing extensions; do not query the legacy tools table directly for extension management.\",\n parameters: {\n type: \"object\",\n properties: {\n search: {\n type: \"string\",\n description:\n \"Optional case-insensitive filter matched against id, name, description, and owner email. Example: Connect Zoom.\",\n },\n includeHidden: {\n type: \"boolean\",\n description:\n \"Include extensions the current user has hidden from their list. Defaults to false.\",\n },\n includeContent: {\n type: \"boolean\",\n description:\n \"Include full Alpine.js content. Defaults to false to keep results concise.\",\n },\n limit: {\n type: \"number\",\n description: \"Maximum results to return. Defaults to 100.\",\n },\n },\n },\n },\n run: async (args) => {\n const includeHidden = coerceBoolean(args?.includeHidden);\n const includeContent = coerceBoolean(args?.includeContent);\n const search = String(args?.search ?? \"\")\n .trim()\n .toLowerCase();\n const limit = coerceLimit(args?.limit);\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n\n let rows = await listExtensions({ includeHidden });\n if (search) {\n rows = rows.filter((row) =>\n [row.id, row.name, row.description, row.ownerEmail]\n .join(\"\\n\")\n .toLowerCase()\n .includes(search),\n );\n }\n\n rows = rows.slice(0, limit);\n const extensions = await Promise.all(\n rows.map((row) => summarizeExtension(row, hiddenIds, includeContent)),\n );\n return {\n ok: true,\n count: extensions.length,\n extensions,\n };\n },\n readOnly: true,\n },\n\n \"create-extension\": {\n tool: {\n description:\n \"Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. Call this action exactly once per requested extension. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction(name, params) for app data and actions, including read actions mounted as GET; do not call template /api/* routes from appFetch because the extension bridge only allows framework /_agent-native/* paths. Parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables.\",\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n 'Short display name for the extension. Do not include \"app\" — e.g. name a todo app \"Todos\", a weather app \"Weather\".',\n },\n description: {\n type: \"string\",\n description: \"One-sentence summary of what the extension does.\",\n },\n content: {\n type: \"string\",\n description:\n \"Self-contained Alpine.js HTML body snippet. The iframe canvas already has modest default padding, so avoid duplicate outer padding unless the design needs it. Use semantic Tailwind colors (bg-background, text-foreground, bg-primary, etc.) for native theming. Do not include a full app build, React code, or source files.\",\n },\n icon: {\n type: \"string\",\n description: \"Optional icon name or short label.\",\n },\n },\n required: [\"name\", \"content\"],\n },\n },\n run: async (args) => {\n const name = String(args?.name ?? \"\").trim();\n const content = String(args?.content ?? \"\").trim();\n if (!name) return \"Error: name is required.\";\n if (!content) return \"Error: content is required.\";\n\n const extension = await createExtension({\n name,\n description: String(args?.description ?? \"\").trim(),\n content,\n icon: args?.icon ? String(args.icon) : undefined,\n });\n\n // Auto-navigate so the user lands on the new extension instead of\n // having to read the JSON response and click a link. Writes a\n // one-shot `navigate` app-state command the UI consumes and clears.\n try {\n await writeAppState(\"navigate\", {\n view: \"extensions\",\n extensionId: extension.id,\n path: `/extensions/${extension.id}`,\n });\n } catch {\n // Non-fatal — agent can still mention the path in its reply.\n }\n\n return {\n ok: true,\n extension,\n next: `Created. The user is being navigated to the new extension automatically — no further navigation tool calls needed.`,\n };\n },\n },\n\n \"update-extension\": {\n tool: {\n description:\n \"Update an existing sandboxed Alpine.js mini-app extension. Prefer patches for surgical edits; use full content replacement only when necessary.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Extension id to update.\",\n },\n name: {\n type: \"string\",\n description: \"Optional new display name.\",\n },\n description: {\n type: \"string\",\n description: \"Optional new description.\",\n },\n content: {\n type: \"string\",\n description:\n \"Optional full replacement Alpine.js HTML body snippet.\",\n },\n patches: {\n type: \"string\",\n description:\n 'Optional JSON array of { \"find\": \"...\", \"replace\": \"...\" } patches to apply to the current content.',\n },\n icon: {\n type: \"string\",\n description: \"Optional icon name or short label.\",\n },\n visibility: {\n type: \"string\",\n description: \"Optional sharing visibility.\",\n enum: [\"private\", \"org\", \"public\"],\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n\n let result = null;\n if (args?.content !== undefined || args?.patches !== undefined) {\n const patches = parsePatches((args as any).patches);\n if (args?.patches !== undefined && !patches) {\n return \"Error: patches must be a JSON array of { find, replace } objects.\";\n }\n result = await updateExtensionContent(id, {\n content:\n args?.content !== undefined ? String(args.content) : undefined,\n patches,\n });\n }\n\n const meta: Record<string, string> = {};\n if (args?.name !== undefined) meta.name = String(args.name).trim();\n if (args?.description !== undefined) {\n meta.description = String(args.description).trim();\n }\n if (args?.icon !== undefined) meta.icon = String(args.icon);\n if (args?.visibility !== undefined) {\n meta.visibility = String(args.visibility);\n }\n if (Object.keys(meta).length > 0) {\n result = await updateExtension(id, meta as any);\n }\n\n if (!result) result = await getExtension(id);\n if (!result) return `Error: extension not found: ${id}`;\n return { ok: true, extension: result };\n },\n },\n\n \"delete-extension\": {\n tool: {\n description:\n \"Permanently delete an extension everywhere it is shared. Requires owner/admin access. If the user only wants a shared extension removed from their own sidebar/list, use hide-extension instead.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to permanently delete. Use list-extensions first if you only know the display name.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const extension = await getExtension(id);\n if (!extension) return `Error: extension not found: ${id}`;\n\n try {\n const ok = await deleteExtension(id);\n if (!ok) return `Error: extension not found: ${id}`;\n return { ok: true, deleted: summarizeDeletedExtension(extension) };\n } catch (err: any) {\n return {\n ok: false,\n error: err?.message ?? String(err),\n next: \"If the user wants this gone only from their own view, call hide-extension with the same id.\",\n };\n }\n },\n },\n\n \"hide-extension\": {\n tool: {\n description:\n \"Hide an accessible extension from the current user's Extensions list/sidebar without deleting it for anyone else. Use this when the user says to remove a shared extension from their view, or when delete-extension reports that the current user is not owner/admin.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to hide for the current user. Use list-extensions first if you only know the display name.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const extension = await getExtension(id);\n if (!extension) return `Error: extension not found: ${id}`;\n\n await hideExtension(id);\n return { ok: true, hidden: summarizeDeletedExtension(extension) };\n },\n },\n\n \"unhide-extension\": {\n tool: {\n description:\n \"Restore an extension the current user previously hid so it appears in their Extensions list/sidebar again. Use list-extensions with includeHidden=true to find hidden ids.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Extension id to restore for the current user.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n await unhideExtension(id);\n return { ok: true, id };\n },\n },\n\n \"add-extension-slot-target\": {\n tool: {\n description:\n 'Declare that an extension can render in a UI extension-point slot of an app (e.g. \"mail.contact-sidebar.bottom\"). Apps drop ExtensionSlot components in their UI; this action registers an extension as installable into one of those slots. Slot IDs follow the convention <app>.<area>.<position>. Caller must have editor access to the extension.',\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n slotId: {\n type: \"string\",\n description:\n 'Slot identifier — e.g. \"mail.contact-sidebar.bottom\".',\n },\n config: {\n type: \"string\",\n description:\n \"Optional JSON string with slot-specific config (defaults, hints, etc.).\",\n },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n const row = await addExtensionSlotTarget(\n extensionId,\n slotId,\n args?.config ? String(args.config) : undefined,\n );\n return { ok: true, slot: row };\n },\n },\n\n \"install-extension\": {\n tool: {\n description:\n \"Install an extension as a widget in an extension-point slot for the current user. The extension must already declare the slot via add-extension-slot-target. Per-user installation — only affects the calling user's view. Use after creating an extension that targets a slot, or when the user asks to add an existing widget to a slot.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: {\n type: \"string\",\n description: \"Extension id to install.\",\n },\n slotId: {\n type: \"string\",\n description:\n 'Slot identifier — e.g. \"mail.contact-sidebar.bottom\".',\n },\n position: {\n type: \"number\",\n description:\n \"Optional integer position within the slot (lower = earlier). Defaults to end.\",\n },\n config: {\n type: \"string\",\n description:\n \"Optional JSON string with per-install config (overrides, settings).\",\n },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n const position =\n args?.position !== undefined && args.position !== null\n ? Number(args.position)\n : undefined;\n const row = await installExtensionSlot(extensionId, slotId, {\n position: Number.isFinite(position as number) ? position : undefined,\n config: args?.config ? String(args.config) : undefined,\n });\n return { ok: true, install: row };\n },\n },\n\n \"uninstall-extension\": {\n tool: {\n description:\n \"Remove an extension from an extension-point slot for the current user. Does not delete the extension itself.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n slotId: { type: \"string\", description: \"Slot identifier.\" },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n await uninstallExtensionSlot(extensionId, slotId);\n return { ok: true };\n },\n },\n\n \"list-extensions-for-slot\": {\n tool: {\n description:\n \"List extensions the current user has access to that declare a given extension-point slot. Use to discover what's available to install into a slot the user mentioned.\",\n parameters: {\n type: \"object\",\n properties: {\n slotId: { type: \"string\", description: \"Slot identifier.\" },\n },\n required: [\"slotId\"],\n },\n },\n run: async (args) => {\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!slotId) return \"Error: slotId is required.\";\n return { extensions: await listExtensionsForSlot(slotId) };\n },\n readOnly: true,\n },\n\n \"list-extension-slots\": {\n tool: {\n description:\n \"List the extension-point slots a specific extension declares it can render in. Caller must have viewer access to the extension.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n },\n required: [\"extensionId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n return { slots: await listSlotsForExtension(extensionId) };\n },\n readOnly: true,\n },\n };\n}\n\nasync function summarizeExtension(\n row: ExtensionRow,\n hiddenIds: Set<string>,\n includeContent: boolean,\n) {\n const access = await resolveAccess(\"extension\", row.id).catch(() => null);\n return {\n id: row.id,\n name: row.name,\n description: row.description,\n icon: row.icon,\n ownerEmail: row.ownerEmail,\n visibility: row.visibility,\n role: access?.role ?? null,\n canEdit: access\n ? [\"owner\", \"admin\", \"editor\"].includes(access.role)\n : false,\n canDelete: access ? [\"owner\", \"admin\"].includes(access.role) : false,\n hidden: hiddenIds.has(row.id),\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n ...(includeContent ? { content: row.content } : {}),\n };\n}\n\nfunction summarizeDeletedExtension(row: ExtensionRow) {\n return {\n id: row.id,\n name: row.name,\n ownerEmail: row.ownerEmail,\n visibility: row.visibility,\n };\n}\n\nfunction coerceBoolean(value: unknown): boolean {\n return value === true || value === \"true\";\n}\n\nfunction coerceLimit(value: unknown): number {\n const limit = Number(value ?? 100);\n if (!Number.isFinite(limit)) return 100;\n return Math.min(Math.max(1, Math.floor(limit)), 500);\n}\n\nfunction parsePatches(value: unknown): ExtensionPatch[] | undefined {\n if (value === undefined) return undefined;\n const parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n if (!Array.isArray(parsed)) return undefined;\n if (\n parsed.some(\n (patch) =>\n !patch ||\n typeof patch.find !== \"string\" ||\n typeof patch.replace !== \"string\",\n )\n ) {\n return undefined;\n }\n return parsed;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"html-shell.d.ts","sourceRoot":"","sources":["../../src/extensions/html-shell.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,8YAC4W,CAAC;AAE9Y,eAAO,MAAM,yBAAyB,QAGrC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,MAAM,WAAW,sBAAsB;IACrC,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;;;;OASG;IACH,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAC/C;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM,CA4gBR"}
1
+ {"version":3,"file":"html-shell.d.ts","sourceRoot":"","sources":["../../src/extensions/html-shell.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,8YAC4W,CAAC;AAE9Y,eAAO,MAAM,yBAAyB,QAGrC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,MAAM,WAAW,sBAAsB;IACrC,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;;;;OASG;IACH,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAC/C;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM,CA0jBR"}
@@ -242,13 +242,59 @@ export function buildExtensionHtml(content, themeVars, isDark, extensionId, bind
242
242
  });
243
243
  }
244
244
 
245
+ function _appendActionQuery(path, params) {
246
+ var search = new URLSearchParams();
247
+ params = params || {};
248
+ Object.keys(params).forEach(function(key) {
249
+ var value = params[key];
250
+ if (value === undefined || value === null) return;
251
+ if (Array.isArray(value)) {
252
+ value.forEach(function(item) {
253
+ if (item !== undefined && item !== null) {
254
+ search.append(key, String(item));
255
+ }
256
+ });
257
+ return;
258
+ }
259
+ search.set(key, String(value));
260
+ });
261
+ var qs = search.toString();
262
+ return qs ? path + '?' + qs : path;
263
+ }
264
+
265
+ function _methodHintFromActionResponse(res) {
266
+ if (!res || res.status !== 405) return null;
267
+ var body = res.body || {};
268
+ var message = typeof body === 'string' ? body : body.error;
269
+ if (!message) return null;
270
+ var match = String(message).match(/Use (GET|POST|PUT|PATCH|DELETE|HEAD)\\.?/i);
271
+ return match ? match[1].toUpperCase() : null;
272
+ }
273
+
245
274
  async function appAction(name, params) {
246
275
  params = params || {};
247
- var res = await hostRequest('/_agent-native/actions/' + encodeURIComponent(name), {
276
+ var path = '/_agent-native/actions/' + encodeURIComponent(name);
277
+ var res = await hostRequest(path, {
248
278
  method: 'POST',
249
279
  headers: { 'Content-Type': 'application/json' },
250
280
  body: JSON.stringify(params),
251
281
  });
282
+
283
+ var retryMethod = _methodHintFromActionResponse(res);
284
+ if (!res.ok && retryMethod && retryMethod !== 'POST') {
285
+ var retryPath = path;
286
+ var retryOptions = {
287
+ method: retryMethod,
288
+ headers: { 'Content-Type': 'application/json' },
289
+ };
290
+ if (retryMethod === 'GET' || retryMethod === 'HEAD') {
291
+ retryPath = _appendActionQuery(path, params);
292
+ } else {
293
+ retryOptions.body = JSON.stringify(params);
294
+ }
295
+ res = await hostRequest(retryPath, retryOptions);
296
+ }
297
+
252
298
  if (!res.ok) {
253
299
  var err = res.body || { error: res.statusText };
254
300
  throw new Error(err.error || 'Action failed: ' + res.status);