@agent-native/core 0.124.3 → 0.124.4

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 (254) hide show
  1. package/README.md +1 -1
  2. package/corpus/README.md +2 -2
  3. package/corpus/core/CHANGELOG.md +10 -0
  4. package/corpus/core/docs/content/cloneable-saas.mdx +9 -9
  5. package/corpus/core/docs/content/creating-templates.mdx +2 -2
  6. package/corpus/core/docs/content/deployment.mdx +23 -0
  7. package/corpus/core/docs/content/faq.mdx +4 -4
  8. package/corpus/core/docs/content/key-concepts.mdx +1 -1
  9. package/corpus/core/docs/content/multi-app-workspace.mdx +1 -1
  10. package/corpus/core/docs/content/syncing-template-changes.mdx +1 -1
  11. package/corpus/core/docs/content/template-analytics-developers.mdx +2 -2
  12. package/corpus/core/docs/content/template-analytics.mdx +2 -2
  13. package/corpus/core/docs/content/template-assets-developers.mdx +3 -3
  14. package/corpus/core/docs/content/template-assets.mdx +2 -2
  15. package/corpus/core/docs/content/template-brain-developers.mdx +2 -2
  16. package/corpus/core/docs/content/template-brain.mdx +1 -1
  17. package/corpus/core/docs/content/template-calendar-developers.mdx +1 -1
  18. package/corpus/core/docs/content/template-calendar.mdx +1 -1
  19. package/corpus/core/docs/content/template-chat.mdx +1 -1
  20. package/corpus/core/docs/content/template-clips-developers.mdx +4 -4
  21. package/corpus/core/docs/content/template-clips.mdx +2 -2
  22. package/corpus/core/docs/content/template-content-developers.mdx +2 -2
  23. package/corpus/core/docs/content/template-content.mdx +1 -1
  24. package/corpus/core/docs/content/template-design-brand-and-figma.mdx +1 -1
  25. package/corpus/core/docs/content/template-design-developers.mdx +2 -2
  26. package/corpus/core/docs/content/template-design.mdx +2 -2
  27. package/corpus/core/docs/content/template-dispatch-developers.mdx +5 -5
  28. package/corpus/core/docs/content/template-forms-developers.mdx +1 -1
  29. package/corpus/core/docs/content/template-forms.mdx +1 -1
  30. package/corpus/core/docs/content/template-mail-developers.mdx +2 -2
  31. package/corpus/core/docs/content/template-mail.mdx +2 -2
  32. package/corpus/core/docs/content/template-plan-developers.mdx +3 -3
  33. package/corpus/core/docs/content/template-plan.mdx +3 -3
  34. package/corpus/core/docs/content/template-slides-developers.mdx +4 -4
  35. package/corpus/core/docs/content/template-slides.mdx +1 -1
  36. package/corpus/core/docs/content/what-is-agent-native.mdx +5 -5
  37. package/corpus/core/package.json +1 -1
  38. package/corpus/core/src/a2a/auth-policy.ts +1 -1
  39. package/corpus/core/src/agent/production-agent.ts +14 -1
  40. package/corpus/core/src/agent/run-manager.ts +6 -13
  41. package/corpus/core/src/cli/index.ts +11 -1
  42. package/corpus/core/src/client/route-chunk-recovery.ts +18 -7
  43. package/corpus/core/src/db/client.ts +7 -6
  44. package/corpus/core/src/db/migrations.ts +2 -1
  45. package/corpus/core/src/deploy/build.ts +290 -4
  46. package/corpus/core/src/deploy/nitro-preset.ts +50 -0
  47. package/corpus/core/src/integrations/pending-tasks-retry-job.ts +2 -1
  48. package/corpus/core/src/scripts/call-agent.ts +4 -2
  49. package/corpus/core/src/server/agent-discovery.ts +1 -0
  50. package/corpus/core/src/server/agent-run-context.ts +13 -3
  51. package/corpus/core/src/server/request-context.ts +2 -0
  52. package/corpus/core/src/shared/cloudflare-globals.d.ts +2 -1
  53. package/corpus/core/src/shared/runtime.ts +2 -0
  54. package/corpus/core/src/templates/default/.agents/skills/secrets/SKILL.md +29 -0
  55. package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +6 -6
  56. package/corpus/core/src/templates/default/app/i18n/de-DE.ts +6 -6
  57. package/corpus/core/src/templates/default/app/i18n/en-US.ts +6 -6
  58. package/corpus/core/src/templates/default/app/i18n/es-ES.ts +6 -6
  59. package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +6 -6
  60. package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +6 -6
  61. package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +6 -6
  62. package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +6 -6
  63. package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +6 -6
  64. package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +6 -6
  65. package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +6 -6
  66. package/corpus/core/src/templates/headless/.agents/skills/secrets/SKILL.md +29 -0
  67. package/corpus/core/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +29 -0
  68. package/corpus/core/src/vite/client.ts +20 -1
  69. package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +9 -2
  70. package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +3 -0
  71. package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +1 -1
  72. package/corpus/templates/analytics/app/global.css +10 -9
  73. package/corpus/templates/analytics/app/hooks/use-chart-tooltip-portal.ts +59 -18
  74. package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +14 -2
  75. package/corpus/templates/analytics/app/i18n-data.ts +102 -0
  76. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +232 -2
  77. package/corpus/templates/analytics/changelog/2026-07-27-chart-tooltips-stay-beside-the-cursor-when-they-extend-beyon.md +6 -0
  78. package/corpus/templates/analytics/changelog/2026-07-27-chat-no-longer-claims-a-data-source-is-disconnected-when-it-.md +6 -0
  79. package/corpus/templates/analytics/changelog/2026-07-27-dashboard-changes-can-be-undone-with-cmd-z-and-actions-menu.md +6 -0
  80. package/corpus/templates/analytics/changelog/2026-07-27-dashboard-redo-with-cmd-shift-z-and-actions-menu.md +6 -0
  81. package/corpus/templates/analytics/changelog/2026-07-27-dashboard-skeletons-are-subtler-and-smoother.md +6 -0
  82. package/corpus/templates/analytics/server/lib/dashboards-store.ts +61 -20
  83. package/corpus/templates/analytics/server/lib/real-data-actions.ts +1 -0
  84. package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -3
  85. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +7 -32
  86. package/corpus/templates/calendar/changelog/2026-07-27-calendar-s-sidebar-now-uses-a-cleaner-layout-with-fewer-util.md +6 -0
  87. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +14 -6
  88. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +32 -37
  89. package/corpus/templates/content/changelog/2026-07-27-content-sidebar-page-lists-now-load-with-quiet-skeletons-and.md +6 -0
  90. package/corpus/templates/design/app/components/layout/Sidebar.tsx +16 -18
  91. package/corpus/templates/design/changelog/2026-07-27-collapsed-sidebar-keeps-the-agent-native-logo.md +6 -0
  92. package/corpus/templates/dispatch/AGENTS.md +7 -2
  93. package/corpus/templates/dispatch/actions/view-screen.ts +3 -2
  94. package/corpus/templates/dispatch/changelog/2026-07-17-curated-template-remixes.md +1 -1
  95. package/corpus/templates/dispatch/changelog/2026-07-27-creating-an-app-from-a-curated-template-now-uses-clearer-mor.md +6 -0
  96. package/corpus/templates/dispatch/changelog/2026-07-27-thread-debug-accepts-request-run-ids.md +6 -0
  97. package/corpus/templates/slides/actions/create-design-system.ts +10 -2
  98. package/corpus/templates/slides/actions/import-file.ts +173 -1
  99. package/corpus/templates/slides/actions/list-slide-comments.ts +16 -1
  100. package/corpus/templates/slides/actions/update-design-system.ts +13 -2
  101. package/corpus/templates/slides/app/components/editor/AssetLibraryPanel.tsx +35 -12
  102. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +36 -0
  103. package/corpus/templates/slides/app/i18n/en-US.ts +3 -0
  104. package/corpus/templates/slides/app/lib/dynamic-import.ts +63 -0
  105. package/corpus/templates/slides/app/lib/export-pdf-client.ts +3 -2
  106. package/corpus/templates/slides/app/lib/export-pptx-client.ts +5 -2
  107. package/corpus/templates/slides/app/pages/DesignSystems.tsx +9 -1
  108. package/corpus/templates/slides/server/db/schema.ts +11 -0
  109. package/corpus/templates/slides/server/handlers/assets.ts +64 -19
  110. package/corpus/templates/slides/server/handlers/import/html-converter.ts +38 -0
  111. package/corpus/templates/slides/server/plugins/db.ts +20 -0
  112. package/corpus/templates/slides/shared/design-system-validation.ts +62 -0
  113. package/dist/a2a/auth-policy.js +1 -1
  114. package/dist/a2a/auth-policy.js.map +1 -1
  115. package/dist/agent/production-agent.d.ts +1 -0
  116. package/dist/agent/production-agent.d.ts.map +1 -1
  117. package/dist/agent/production-agent.js +12 -1
  118. package/dist/agent/production-agent.js.map +1 -1
  119. package/dist/agent/run-manager.d.ts +2 -0
  120. package/dist/agent/run-manager.d.ts.map +1 -1
  121. package/dist/agent/run-manager.js +4 -10
  122. package/dist/agent/run-manager.js.map +1 -1
  123. package/dist/cli/index.js +8 -1
  124. package/dist/cli/index.js.map +1 -1
  125. package/dist/client/route-chunk-recovery.d.ts.map +1 -1
  126. package/dist/client/route-chunk-recovery.js +16 -7
  127. package/dist/client/route-chunk-recovery.js.map +1 -1
  128. package/dist/collab/awareness.d.ts +2 -2
  129. package/dist/collab/awareness.d.ts.map +1 -1
  130. package/dist/collab/routes.d.ts +1 -1
  131. package/dist/collab/struct-routes.d.ts +1 -1
  132. package/dist/db/client.d.ts.map +1 -1
  133. package/dist/db/client.js +4 -2
  134. package/dist/db/client.js.map +1 -1
  135. package/dist/db/migrations.d.ts.map +1 -1
  136. package/dist/db/migrations.js +2 -1
  137. package/dist/db/migrations.js.map +1 -1
  138. package/dist/deploy/build.d.ts +25 -0
  139. package/dist/deploy/build.d.ts.map +1 -1
  140. package/dist/deploy/build.js +227 -4
  141. package/dist/deploy/build.js.map +1 -1
  142. package/dist/deploy/nitro-preset.d.ts +8 -0
  143. package/dist/deploy/nitro-preset.d.ts.map +1 -0
  144. package/dist/deploy/nitro-preset.js +36 -0
  145. package/dist/deploy/nitro-preset.js.map +1 -0
  146. package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
  147. package/dist/integrations/pending-tasks-retry-job.js +2 -1
  148. package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
  149. package/dist/notifications/routes.d.ts +3 -3
  150. package/dist/observability/routes.d.ts +3 -3
  151. package/dist/progress/routes.d.ts +1 -1
  152. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  153. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  154. package/dist/scripts/call-agent.d.ts.map +1 -1
  155. package/dist/scripts/call-agent.js +4 -2
  156. package/dist/scripts/call-agent.js.map +1 -1
  157. package/dist/secrets/routes.d.ts +3 -3
  158. package/dist/server/agent-discovery.d.ts.map +1 -1
  159. package/dist/server/agent-discovery.js +1 -0
  160. package/dist/server/agent-discovery.js.map +1 -1
  161. package/dist/server/agent-run-context.d.ts.map +1 -1
  162. package/dist/server/agent-run-context.js +10 -3
  163. package/dist/server/agent-run-context.js.map +1 -1
  164. package/dist/server/request-context.d.ts +2 -0
  165. package/dist/server/request-context.d.ts.map +1 -1
  166. package/dist/server/request-context.js.map +1 -1
  167. package/dist/server/transcribe-voice.d.ts +1 -1
  168. package/dist/shared/runtime.d.ts.map +1 -1
  169. package/dist/shared/runtime.js +2 -0
  170. package/dist/shared/runtime.js.map +1 -1
  171. package/dist/templates/default/.agents/skills/secrets/SKILL.md +29 -0
  172. package/dist/templates/default/app/i18n/ar-SA.ts +6 -6
  173. package/dist/templates/default/app/i18n/de-DE.ts +6 -6
  174. package/dist/templates/default/app/i18n/en-US.ts +6 -6
  175. package/dist/templates/default/app/i18n/es-ES.ts +6 -6
  176. package/dist/templates/default/app/i18n/fr-FR.ts +6 -6
  177. package/dist/templates/default/app/i18n/hi-IN.ts +6 -6
  178. package/dist/templates/default/app/i18n/ja-JP.ts +6 -6
  179. package/dist/templates/default/app/i18n/ko-KR.ts +6 -6
  180. package/dist/templates/default/app/i18n/pt-BR.ts +6 -6
  181. package/dist/templates/default/app/i18n/zh-CN.ts +6 -6
  182. package/dist/templates/default/app/i18n/zh-TW.ts +6 -6
  183. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +29 -0
  184. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +29 -0
  185. package/dist/vite/client.d.ts +1 -1
  186. package/dist/vite/client.d.ts.map +1 -1
  187. package/dist/vite/client.js +16 -0
  188. package/dist/vite/client.js.map +1 -1
  189. package/docs/content/cloneable-saas.mdx +9 -9
  190. package/docs/content/creating-templates.mdx +2 -2
  191. package/docs/content/deployment.mdx +23 -0
  192. package/docs/content/faq.mdx +4 -4
  193. package/docs/content/key-concepts.mdx +1 -1
  194. package/docs/content/multi-app-workspace.mdx +1 -1
  195. package/docs/content/syncing-template-changes.mdx +1 -1
  196. package/docs/content/template-analytics-developers.mdx +2 -2
  197. package/docs/content/template-analytics.mdx +2 -2
  198. package/docs/content/template-assets-developers.mdx +3 -3
  199. package/docs/content/template-assets.mdx +2 -2
  200. package/docs/content/template-brain-developers.mdx +2 -2
  201. package/docs/content/template-brain.mdx +1 -1
  202. package/docs/content/template-calendar-developers.mdx +1 -1
  203. package/docs/content/template-calendar.mdx +1 -1
  204. package/docs/content/template-chat.mdx +1 -1
  205. package/docs/content/template-clips-developers.mdx +4 -4
  206. package/docs/content/template-clips.mdx +2 -2
  207. package/docs/content/template-content-developers.mdx +2 -2
  208. package/docs/content/template-content.mdx +1 -1
  209. package/docs/content/template-design-brand-and-figma.mdx +1 -1
  210. package/docs/content/template-design-developers.mdx +2 -2
  211. package/docs/content/template-design.mdx +2 -2
  212. package/docs/content/template-dispatch-developers.mdx +5 -5
  213. package/docs/content/template-forms-developers.mdx +1 -1
  214. package/docs/content/template-forms.mdx +1 -1
  215. package/docs/content/template-mail-developers.mdx +2 -2
  216. package/docs/content/template-mail.mdx +2 -2
  217. package/docs/content/template-plan-developers.mdx +3 -3
  218. package/docs/content/template-plan.mdx +3 -3
  219. package/docs/content/template-slides-developers.mdx +4 -4
  220. package/docs/content/template-slides.mdx +1 -1
  221. package/docs/content/what-is-agent-native.mdx +5 -5
  222. package/package.json +1 -1
  223. package/src/a2a/auth-policy.ts +1 -1
  224. package/src/agent/production-agent.ts +14 -1
  225. package/src/agent/run-manager.ts +6 -13
  226. package/src/cli/index.ts +11 -1
  227. package/src/client/route-chunk-recovery.ts +18 -7
  228. package/src/db/client.ts +7 -6
  229. package/src/db/migrations.ts +2 -1
  230. package/src/deploy/build.ts +290 -4
  231. package/src/deploy/nitro-preset.ts +50 -0
  232. package/src/integrations/pending-tasks-retry-job.ts +2 -1
  233. package/src/scripts/call-agent.ts +4 -2
  234. package/src/server/agent-discovery.ts +1 -0
  235. package/src/server/agent-run-context.ts +13 -3
  236. package/src/server/request-context.ts +2 -0
  237. package/src/shared/cloudflare-globals.d.ts +2 -1
  238. package/src/shared/runtime.ts +2 -0
  239. package/src/templates/default/.agents/skills/secrets/SKILL.md +29 -0
  240. package/src/templates/default/app/i18n/ar-SA.ts +6 -6
  241. package/src/templates/default/app/i18n/de-DE.ts +6 -6
  242. package/src/templates/default/app/i18n/en-US.ts +6 -6
  243. package/src/templates/default/app/i18n/es-ES.ts +6 -6
  244. package/src/templates/default/app/i18n/fr-FR.ts +6 -6
  245. package/src/templates/default/app/i18n/hi-IN.ts +6 -6
  246. package/src/templates/default/app/i18n/ja-JP.ts +6 -6
  247. package/src/templates/default/app/i18n/ko-KR.ts +6 -6
  248. package/src/templates/default/app/i18n/pt-BR.ts +6 -6
  249. package/src/templates/default/app/i18n/zh-CN.ts +6 -6
  250. package/src/templates/default/app/i18n/zh-TW.ts +6 -6
  251. package/src/templates/headless/.agents/skills/secrets/SKILL.md +29 -0
  252. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +29 -0
  253. package/src/vite/client.ts +20 -1
  254. /package/corpus/templates/slides/server/routes/api/assets/{[filename].delete.ts → [id].delete.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"agent-run-context.js","sourceRoot":"","sources":["../../src/server/agent-run-context.ts"],"names":[],"mappings":"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","sourcesContent":["import { createError, getHeader, type H3Event } from \"h3\";\n\nimport { resolveOrgIdForEmail, getOrgContext } from \"../org/context.js\";\nimport { getSession } from \"./auth.js\";\nimport {\n runWithRequestContext,\n type RequestContext,\n} from \"./request-context.js\";\n\nexport type AgentRunOwnerContext = {\n owner: string;\n anonymous: boolean;\n name?: string;\n};\n\nexport const AGENT_RUN_OWNER_CONTEXT_KEY = \"__agentNativeOwnerContext\";\n\ntype EventWithAgentRunContext = H3Event & {\n context?: Record<string, unknown>;\n};\n\ntype AnonymousOwnerResolver = (\n event: H3Event,\n) => string | null | Promise<string | null>;\n\ntype OrgIdResolver = (\n event: H3Event,\n) => string | null | undefined | Promise<string | null | undefined>;\n\nfunction eventContext(\n event: EventWithAgentRunContext,\n): Record<string, unknown> {\n event.context = event.context ?? {};\n return event.context;\n}\n\nfunction normalizeId(value: string | null | undefined): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : undefined;\n}\n\nfunction readHeaderValue(event: any, name: string): unknown {\n try {\n const value = getHeader(event, name);\n if (value !== undefined && value !== null) return value;\n } catch {\n // Unit tests and a few framework internals pass lightweight event shims.\n }\n\n const headers = event?.headers;\n if (headers && typeof headers.get === \"function\") {\n return headers.get(name) ?? headers.get(name.toLowerCase()) ?? undefined;\n }\n\n const reqHeaders = event?.node?.req?.headers ?? event?.req?.headers;\n if (reqHeaders && typeof reqHeaders === \"object\") {\n return reqHeaders[name] ?? reqHeaders[name.toLowerCase()];\n }\n\n return undefined;\n}\n\nexport function readAgentRunTimezone(event: H3Event): string | undefined {\n const raw = readHeaderValue(event, \"x-user-timezone\");\n const value = Array.isArray(raw) ? raw[0] : raw;\n return typeof value === \"string\" &&\n value.trim().length > 0 &&\n value.trim().length < 64\n ? value.trim()\n : undefined;\n}\n\nexport function seedAgentRunOwnerContext(\n event: H3Event,\n ownerContext: AgentRunOwnerContext,\n): AgentRunOwnerContext {\n eventContext(event as EventWithAgentRunContext)[AGENT_RUN_OWNER_CONTEXT_KEY] =\n ownerContext;\n return ownerContext;\n}\n\nexport async function seedBackgroundAgentRunOwnerContext(\n event: H3Event,\n runId: string,\n): Promise<AgentRunOwnerContext | null> {\n try {\n const { getRunOwnerEmail } = await import(\"../agent/run-store.js\");\n const owner = await getRunOwnerEmail(runId);\n if (!owner) return null;\n return seedAgentRunOwnerContext(event, { owner, anonymous: false });\n } catch {\n return null;\n }\n}\n\nexport async function resolveAgentRunOwnerContext(\n event: H3Event,\n options: { anonymousOwner?: AnonymousOwnerResolver } = {},\n): Promise<AgentRunOwnerContext> {\n const ctx = eventContext(event as EventWithAgentRunContext);\n const seeded = ctx[AGENT_RUN_OWNER_CONTEXT_KEY] as\n | AgentRunOwnerContext\n | undefined;\n if (seeded) return seeded;\n\n const session = await getSession(event);\n if (session?.email) {\n return seedAgentRunOwnerContext(event, {\n owner: session.email,\n anonymous: false,\n name: session.name,\n });\n }\n\n const anonymousOwner = await options.anonymousOwner?.(event);\n if (anonymousOwner) {\n return seedAgentRunOwnerContext(event, {\n owner: anonymousOwner,\n anonymous: true,\n });\n }\n\n throw createError({\n statusCode: 401,\n statusMessage: \"Unauthenticated\",\n });\n}\n\nexport async function resolveAgentRunOrgId(options: {\n event: H3Event;\n ownerContext: AgentRunOwnerContext;\n resolveOrgId?: OrgIdResolver;\n}): Promise<string | undefined> {\n let resolvedOrgId: string | undefined;\n\n if (options.resolveOrgId) {\n resolvedOrgId = normalizeId(await options.resolveOrgId(options.event));\n } else {\n try {\n const session = await getSession(options.event);\n resolvedOrgId = normalizeId(session?.orgId);\n } catch {\n // Session not available.\n }\n\n if (!resolvedOrgId) {\n try {\n const orgContext = await getOrgContext(options.event);\n resolvedOrgId = normalizeId(orgContext.orgId);\n } catch {\n // Org tables may not exist yet on first boot.\n }\n }\n }\n\n if (\n !resolvedOrgId &&\n options.ownerContext.owner &&\n !options.ownerContext.anonymous\n ) {\n try {\n resolvedOrgId = normalizeId(\n await resolveOrgIdForEmail(options.ownerContext.owner),\n );\n } catch {\n // Org tables may not exist yet on first boot.\n }\n }\n\n return resolvedOrgId;\n}\n\nexport async function resolveAgentRunRequestContext(options: {\n event: H3Event;\n ownerContext: AgentRunOwnerContext;\n resolveOrgId?: OrgIdResolver;\n isBackgroundWorker?: boolean;\n}): Promise<RequestContext> {\n const orgId = await resolveAgentRunOrgId(options);\n const timezone = readAgentRunTimezone(options.event);\n return {\n userEmail: options.ownerContext.owner,\n userName: options.ownerContext.name,\n orgId,\n timezone,\n ...(options.isBackgroundWorker\n ? { run: { isBackgroundWorker: true } }\n : {}),\n };\n}\n\nexport async function runWithAgentRunContext<T>(\n options: {\n event: H3Event;\n ownerContext: AgentRunOwnerContext;\n resolveOrgId?: OrgIdResolver;\n isBackgroundWorker?: boolean;\n },\n fn: () => T | Promise<T>,\n): Promise<T> {\n const requestContext = await resolveAgentRunRequestContext(options);\n return await runWithRequestContext(requestContext, fn);\n}\n"]}
1
+ {"version":3,"file":"agent-run-context.js","sourceRoot":"","sources":["../../src/server/agent-run-context.ts"],"names":[],"mappings":"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","sourcesContent":["import { createError, getHeader, type H3Event } from \"h3\";\n\nimport { resolveOrgIdForEmail, getOrgContext } from \"../org/context.js\";\nimport { getSession } from \"./auth.js\";\nimport {\n runWithRequestContext,\n type RequestContext,\n} from \"./request-context.js\";\n\nexport type AgentRunOwnerContext = {\n owner: string;\n anonymous: boolean;\n name?: string;\n};\n\nexport const AGENT_RUN_OWNER_CONTEXT_KEY = \"__agentNativeOwnerContext\";\n\ntype EventWithAgentRunContext = H3Event & {\n context?: Record<string, unknown>;\n};\n\ntype AnonymousOwnerResolver = (\n event: H3Event,\n) => string | null | Promise<string | null>;\n\ntype OrgIdResolver = (\n event: H3Event,\n) => string | null | undefined | Promise<string | null | undefined>;\n\nfunction eventContext(\n event: EventWithAgentRunContext,\n): Record<string, unknown> {\n event.context = event.context ?? {};\n return event.context;\n}\n\nfunction requestWaitUntil(\n event: H3Event,\n): ((promise: Promise<unknown>) => void) | undefined {\n const waitUntil = event.req?.waitUntil;\n return typeof waitUntil === \"function\" ? waitUntil : undefined;\n}\n\nfunction normalizeId(value: string | null | undefined): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : undefined;\n}\n\nfunction readHeaderValue(event: any, name: string): unknown {\n try {\n const value = getHeader(event, name);\n if (value !== undefined && value !== null) return value;\n } catch {\n // Unit tests and a few framework internals pass lightweight event shims.\n }\n\n const headers = event?.headers;\n if (headers && typeof headers.get === \"function\") {\n return headers.get(name) ?? headers.get(name.toLowerCase()) ?? undefined;\n }\n\n const reqHeaders = event?.node?.req?.headers ?? event?.req?.headers;\n if (reqHeaders && typeof reqHeaders === \"object\") {\n return reqHeaders[name] ?? reqHeaders[name.toLowerCase()];\n }\n\n return undefined;\n}\n\nexport function readAgentRunTimezone(event: H3Event): string | undefined {\n const raw = readHeaderValue(event, \"x-user-timezone\");\n const value = Array.isArray(raw) ? raw[0] : raw;\n return typeof value === \"string\" &&\n value.trim().length > 0 &&\n value.trim().length < 64\n ? value.trim()\n : undefined;\n}\n\nexport function seedAgentRunOwnerContext(\n event: H3Event,\n ownerContext: AgentRunOwnerContext,\n): AgentRunOwnerContext {\n eventContext(event as EventWithAgentRunContext)[AGENT_RUN_OWNER_CONTEXT_KEY] =\n ownerContext;\n return ownerContext;\n}\n\nexport async function seedBackgroundAgentRunOwnerContext(\n event: H3Event,\n runId: string,\n): Promise<AgentRunOwnerContext | null> {\n try {\n const { getRunOwnerEmail } = await import(\"../agent/run-store.js\");\n const owner = await getRunOwnerEmail(runId);\n if (!owner) return null;\n return seedAgentRunOwnerContext(event, { owner, anonymous: false });\n } catch {\n return null;\n }\n}\n\nexport async function resolveAgentRunOwnerContext(\n event: H3Event,\n options: { anonymousOwner?: AnonymousOwnerResolver } = {},\n): Promise<AgentRunOwnerContext> {\n const ctx = eventContext(event as EventWithAgentRunContext);\n const seeded = ctx[AGENT_RUN_OWNER_CONTEXT_KEY] as\n | AgentRunOwnerContext\n | undefined;\n if (seeded) return seeded;\n\n const session = await getSession(event);\n if (session?.email) {\n return seedAgentRunOwnerContext(event, {\n owner: session.email,\n anonymous: false,\n name: session.name,\n });\n }\n\n const anonymousOwner = await options.anonymousOwner?.(event);\n if (anonymousOwner) {\n return seedAgentRunOwnerContext(event, {\n owner: anonymousOwner,\n anonymous: true,\n });\n }\n\n throw createError({\n statusCode: 401,\n statusMessage: \"Unauthenticated\",\n });\n}\n\nexport async function resolveAgentRunOrgId(options: {\n event: H3Event;\n ownerContext: AgentRunOwnerContext;\n resolveOrgId?: OrgIdResolver;\n}): Promise<string | undefined> {\n let resolvedOrgId: string | undefined;\n\n if (options.resolveOrgId) {\n resolvedOrgId = normalizeId(await options.resolveOrgId(options.event));\n } else {\n try {\n const session = await getSession(options.event);\n resolvedOrgId = normalizeId(session?.orgId);\n } catch {\n // Session not available.\n }\n\n if (!resolvedOrgId) {\n try {\n const orgContext = await getOrgContext(options.event);\n resolvedOrgId = normalizeId(orgContext.orgId);\n } catch {\n // Org tables may not exist yet on first boot.\n }\n }\n }\n\n if (\n !resolvedOrgId &&\n options.ownerContext.owner &&\n !options.ownerContext.anonymous\n ) {\n try {\n resolvedOrgId = normalizeId(\n await resolveOrgIdForEmail(options.ownerContext.owner),\n );\n } catch {\n // Org tables may not exist yet on first boot.\n }\n }\n\n return resolvedOrgId;\n}\n\nexport async function resolveAgentRunRequestContext(options: {\n event: H3Event;\n ownerContext: AgentRunOwnerContext;\n resolveOrgId?: OrgIdResolver;\n isBackgroundWorker?: boolean;\n}): Promise<RequestContext> {\n const orgId = await resolveAgentRunOrgId(options);\n const timezone = readAgentRunTimezone(options.event);\n const waitUntil = requestWaitUntil(options.event);\n const run = {\n ...(options.isBackgroundWorker ? { isBackgroundWorker: true } : {}),\n ...(waitUntil ? { waitUntil } : {}),\n };\n return {\n userEmail: options.ownerContext.owner,\n userName: options.ownerContext.name,\n orgId,\n timezone,\n ...(Object.keys(run).length > 0 ? { run } : {}),\n };\n}\n\nexport async function runWithAgentRunContext<T>(\n options: {\n event: H3Event;\n ownerContext: AgentRunOwnerContext;\n resolveOrgId?: OrgIdResolver;\n isBackgroundWorker?: boolean;\n },\n fn: () => T | Promise<T>,\n): Promise<T> {\n const requestContext = await resolveAgentRunRequestContext(options);\n return await runWithRequestContext(requestContext, fn);\n}\n"]}
@@ -27,6 +27,8 @@
27
27
  * the live per-request value via `getRequestRunContext()`.
28
28
  */
29
29
  export interface RequestRunContext {
30
+ /** Request-scoped serverless continuation hook, when the runtime provides one. */
31
+ waitUntil?: (promise: Promise<unknown>) => void;
30
32
  /** Origin of the current request (used by the builder-browser tool). */
31
33
  requestOrigin?: string;
32
34
  /** Stable browser tab id for tab-scoped app-state reads/writes. */
@@ -1 +1 @@
1
- {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"request-context.js","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Per-request context using AsyncLocalStorage.\n *\n * Replaces the unsafe pattern of mutating `process.env.AGENT_USER_EMAIL` /\n * `process.env.AGENT_ORG_ID` on every request. On Node.js (Netlify, self-hosted)\n * concurrent requests would overwrite each other's env vars. AsyncLocalStorage\n * gives each async call-chain its own isolated context.\n *\n * Supported on all deployment targets:\n * - Node.js (native)\n * - Cloudflare Workers (via nodejs_compat flag)\n * - Deno Deploy (via node:async_hooks compat)\n *\n * For CLI scripts that run outside a request context, the getters fall back to\n * process.env so existing `AGENT_USER_EMAIL=x pnpm action foo` invocations\n * continue to work.\n */\n\ntype AsyncLocalStorageLike<T> = {\n getStore(): T | undefined;\n run<R>(store: T, callback: () => R): R;\n};\n\ntype AsyncLocalStorageCtor = new <T>() => AsyncLocalStorageLike<T>;\n\nclass StackAsyncLocalStorage<T> implements AsyncLocalStorageLike<T> {\n private readonly stack: T[] = [];\n\n getStore(): T | undefined {\n return this.stack.at(-1);\n }\n\n run<R>(store: T, callback: () => R): R {\n this.stack.push(store);\n try {\n const result = callback();\n const maybePromise = result as unknown as\n | { finally?: (callback: () => void) => unknown }\n | undefined;\n if (maybePromise && typeof maybePromise.finally === \"function\") {\n return maybePromise.finally(() => {\n this.stack.pop();\n }) as R;\n }\n this.stack.pop();\n return result;\n } catch (error) {\n this.stack.pop();\n throw error;\n }\n }\n}\n\nfunction getAsyncLocalStorageCtor(): AsyncLocalStorageCtor | undefined {\n if (\n typeof window !== \"undefined\" ||\n typeof process === \"undefined\" ||\n !process.versions?.node ||\n typeof process.getBuiltinModule !== \"function\"\n ) {\n return undefined;\n }\n return process.getBuiltinModule(\"node:async_hooks\")?.AsyncLocalStorage as\n | AsyncLocalStorageCtor\n | undefined;\n}\n\nconst AsyncLocalStorageCtor = getAsyncLocalStorageCtor();\n\nfunction processEnv(name: string): string | undefined {\n if (typeof process === \"undefined\") return undefined;\n return process.env?.[name];\n}\n\n/**\n * Per-request agent-run state. Lives on `RequestContext.run` so the\n * agent-chat plugin can populate fields as the run progresses (owner,\n * resolved API key, system prompt, engine, model, threadId) without\n * mutating module-scope `let` bindings — those leak across concurrent\n * requests on a single Node.js process.\n *\n * Mutated in-place by `prepareRun`, `onEngineResolved`, `onRunStart` so\n * tool factory closures (automation, fetch, team, builder-browser) read\n * the live per-request value via `getRequestRunContext()`.\n */\nexport interface RequestRunContext {\n /** Origin of the current request (used by the builder-browser tool). */\n requestOrigin?: string;\n /** Stable browser tab id for tab-scoped app-state reads/writes. */\n browserTabId?: string;\n /** Resource scope for the current chat thread, e.g. the active deck. */\n chatScope?: {\n type: string;\n id: string;\n label?: string;\n } | null;\n /** Resolved owner email (set by prepareRun). */\n owner?: string;\n /** Owner's active Anthropic API key (set by prepareRun). */\n userApiKey?: string;\n /** Thread ID for the current run (set by onRunStart). */\n threadId?: string;\n /** System prompt actually sent to the model for this run. */\n systemPrompt?: string;\n /** Engine instance for this run (set by onEngineResolved). */\n engine?: import(\"../agent/engine/types.js\").AgentEngine;\n /** Model name for this run (set by onEngineResolved). */\n model?: string;\n /**\n * True when this run is executing inside the durable background-function\n * worker (the `_process-run` self-dispatch), not the synchronous foreground\n * request. Template `extraContext` / system-prompt builders can read this to\n * skip heavy, hang-prone enrichment (large data-dictionary DB reads, etc.)\n * in the worker so it reliably claims its run within the setup budget.\n */\n isBackgroundWorker?: boolean;\n /** Tool calls made so far in the current agent loop. */\n toolCalls?: Array<{ name: string; input: unknown }>;\n /** Tool results returned so far in the current agent loop. */\n toolResults?: Array<{ name: string; content: string; isError: boolean }>;\n /** Per-run fingerprints for large extension bodies already sent to the LLM. */\n extensionContentReads?: Record<string, string>;\n /** Per-run fingerprints for repeated tool-search calls already sent to the LLM. */\n toolSearchReads?: Record<\n string,\n { totalTools: number; resultNames: string[] }\n >;\n}\n\nexport interface RequestContext {\n userEmail?: string;\n userName?: string;\n orgId?: string;\n timezone?: string;\n /**\n * Set when code reads authenticated request context. Public SSR shell/data\n * should not depend on this value; user/org-specific reads belong behind\n * client-side actions/API after hydration.\n */\n authContextAccessed?: boolean;\n /**\n * Origin of the inbound request (e.g. `http://127.0.0.1:8100`). Set by the\n * MCP mount from the request headers so actions that build externally\n * fetchable URLs (e.g. design `export-coding-handoff`'s signed raw-code URL)\n * resolve the real local-workspace origin instead of a prod/localhost\n * fallback. Optional — absent on paths that don't populate it.\n */\n requestOrigin?: string;\n /**\n * True when this request is being processed by an integration-platform\n * webhook (Slack, Telegram, etc.) where the function timeout is the\n * binding constraint. Code that calls slow remote APIs can use this to apply\n * tighter budgets on this path while leaving normal agent-chat callers\n * (5+ min budget) unaffected.\n */\n isIntegrationCaller?: boolean;\n /**\n * Metadata for the currently-processing integration task. This lets tools\n * that start long-running remote work persist a continuation that can update\n * the originating platform thread after the current function budget ends.\n */\n integration?: {\n taskId: string;\n attempts?: number;\n incoming: import(\"../integrations/types.js\").IncomingMessage;\n placeholderRef?: string;\n /** Opaque provider-native progress surface for a durable continuation. */\n progressRef?: import(\"../integrations/types.js\").PlatformRunProgressRef;\n installationId?: string;\n scopeId?: string;\n principalType?: \"user\" | \"service\";\n lineage?: {\n runId?: string;\n parentTaskId?: string;\n source?: {\n kind: string;\n platform?: string;\n id: string;\n url?: string;\n };\n network?: {\n protocol: \"a2a\" | \"mcp\" | \"provider-api\";\n id: string;\n peer?: string;\n };\n };\n };\n /**\n * Mutable per-request agent-run state. Populated by the agent-chat plugin\n * during a run; tool closures dereference it on each invocation.\n */\n run?: RequestRunContext;\n}\n\nconst GLOBAL_KEY = \"__agentNativeRequestContextAls\" as const;\nconst OBSERVERS_KEY = \"__agentNativeRequestContextObservers\" as const;\nconst BOUNDARY_KEY = \"__agentNativeRequestBoundaryInstalled\" as const;\ntype RequestContextObserver = (ctx: RequestContext) => void;\ntype GlobalWithRequestContext = typeof globalThis & {\n [GLOBAL_KEY]?: AsyncLocalStorageLike<RequestContext>;\n [OBSERVERS_KEY]?: RequestContextObserver[];\n [BOUNDARY_KEY]?: boolean;\n};\nconst globalRef = globalThis as GlobalWithRequestContext;\nif (!globalRef[GLOBAL_KEY]) {\n globalRef[GLOBAL_KEY] = AsyncLocalStorageCtor\n ? new AsyncLocalStorageCtor<RequestContext>()\n : new StackAsyncLocalStorage<RequestContext>();\n}\nif (!globalRef[OBSERVERS_KEY]) {\n globalRef[OBSERVERS_KEY] = [];\n}\nconst als = globalRef[GLOBAL_KEY]!;\nconst observers = globalRef[OBSERVERS_KEY]!;\n\n/**\n * Register a callback fired every time `runWithRequestContext` enters a new\n * scope. The hook runs INSIDE the AsyncLocalStorage scope, so observability\n * helpers that read the current isolation scope (e.g. Sentry) attach to the\n * right per-request context.\n *\n * Returned function unregisters the observer. Observers must never throw —\n * any error is swallowed so a misbehaving observer can't break the request\n * path.\n */\nexport function addRequestContextObserver(\n observer: RequestContextObserver,\n): () => void {\n observers.push(observer);\n return () => {\n const i = observers.indexOf(observer);\n if (i !== -1) observers.splice(i, 1);\n };\n}\n\n/**\n * Run a callback within a per-request context. The context is available to all\n * async operations spawned from `fn` via `getRequestUserEmail()` / `getRequestOrgId()`.\n *\n * Any registered `addRequestContextObserver` callbacks fire inside the new\n * scope before `fn` runs, so observability code can pin user/org info onto\n * isolation-scoped backends (Sentry, OpenTelemetry, etc.).\n */\nexport function runWithRequestContext<T>(\n ctx: RequestContext,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n return als.run(ctx, () => {\n if (observers.length > 0) {\n for (const obs of observers) {\n try {\n obs(ctx);\n } catch {\n // Observers must never break the request path.\n }\n }\n }\n return fn();\n });\n}\n\n/**\n * Return the active request context, if this call chain is running under one.\n *\n * This is intentionally distinct from `getRequestUserEmail()`: callers that\n * have an active context with no authenticated user must not fall through to\n * process-wide CLI fallbacks such as `AGENT_USER_EMAIL` or \"latest session\".\n */\nexport function getRequestContext(): RequestContext | undefined {\n const store = als.getStore();\n markAuthContextAccess(store);\n return store;\n}\n\n/**\n * True when AsyncLocalStorage has an active context for this call chain.\n * Useful for helpers that support both HTTP requests and standalone CLI runs.\n */\nexport function hasRequestContext(): boolean {\n return als.getStore() !== undefined;\n}\n\n/**\n * Record that the framework's request-boundary middleware is installed in this\n * process, so every inbound HTTP request runs inside a `RequestContext`.\n *\n * Once that is true, a request-scoped identity read that finds no store can no\n * longer be an HTTP caller — which is what makes the ambient-identity warning\n * in `getRequestUserEmail()` specific enough to be worth emitting.\n */\nexport function markRequestBoundaryInstalled(): void {\n globalRef[BOUNDARY_KEY] = true;\n}\n\nexport function hasRequestBoundary(): boolean {\n return globalRef[BOUNDARY_KEY] === true;\n}\n\n/**\n * The ambient, process-wide identity configured for this deployment\n * (`AGENT_USER_EMAIL`). Legitimate callers are the ones with no request behind\n * them at all: CLI invocations, cron/scheduled jobs, seed and QA scripts.\n *\n * TRAP: this is not the caller's identity, and a request handler that reads it\n * authorizes whoever the deploy env names rather than whoever signed in — it\n * fails open toward more privilege. Request handlers read\n * `getRequestUserEmail()` and fail closed when it returns undefined.\n */\nexport function getAmbientUserEmail(): string | undefined {\n return processEnv(\"AGENT_USER_EMAIL\");\n}\n\n/** Ambient process-wide org (`AGENT_ORG_ID`). Same trap as `getAmbientUserEmail()`. */\nexport function getAmbientOrgId(): string | undefined {\n return processEnv(\"AGENT_ORG_ID\");\n}\n\nconst warnedAmbientIdentities = new Set<string>();\n\nfunction warnAmbientIdentitySatisfiedRead(email: string): void {\n if (!hasRequestBoundary()) return;\n if (warnedAmbientIdentities.has(email)) return;\n warnedAmbientIdentities.add(email);\n console.warn(\n `[agent-native] getRequestUserEmail() found no request context and answered with the ambient ` +\n `AGENT_USER_EMAIL identity (${email}). This process serves HTTP requests, so a request-scoped ` +\n `read reaching the ambient identity is a bug: it authorizes the deploy env, not the signed-in ` +\n `user. Wrap the caller in runWithRequestContext({ userEmail }), or call getAmbientUserEmail() ` +\n `explicitly if the process identity really is what you mean.`,\n );\n}\n\n/**\n * Get the current request's user email.\n *\n * - If a request context exists (HTTP/A2A path), returns its `userEmail` —\n * even when that value is `undefined`. The env fallback MUST NOT fire here:\n * a stale process-wide `AGENT_USER_EMAIL` from a CLI run or previous bug\n * would leak into an unauthenticated A2A/API call (e.g. unsigned or API-key\n * modes where `runWithRequestContext({ userEmail: undefined })` is used).\n * - Only when there is NO request context (CLI scripts) do we fall back to\n * `process.env.AGENT_USER_EMAIL`. In a process that serves HTTP requests the\n * framework installs a request boundary so that case cannot be a request;\n * if it happens anyway we warn loudly rather than answer silently.\n */\nexport function getRequestUserEmail(): string | undefined {\n const store = als.getStore();\n if (store !== undefined) {\n if (store.userEmail) markAuthContextAccess(store);\n return store.userEmail;\n }\n const ambient = processEnv(\"AGENT_USER_EMAIL\");\n if (ambient) warnAmbientIdentitySatisfiedRead(ambient);\n return ambient;\n}\n\n/**\n * Get the current request's display name, when the auth provider supplied one.\n *\n * The same request-context fallback rules as `getRequestUserEmail()` apply:\n * HTTP/A2A calls only read AsyncLocalStorage, while CLI scripts may opt in via\n * `AGENT_USER_NAME`.\n */\nexport function getRequestUserName(): string | undefined {\n const store = als.getStore();\n if (store !== undefined) {\n if (store.userName) markAuthContextAccess(store);\n return store.userName;\n }\n return processEnv(\"AGENT_USER_NAME\");\n}\n\n/**\n * Get the current request's org ID.\n *\n * Same store-aware semantics as `getRequestUserEmail()` — env fallback is\n * CLI-only, so a request that explicitly has no org doesn't inherit a stale\n * `process.env.AGENT_ORG_ID` from a prior request on the same Lambda instance.\n */\nexport function getRequestOrgId(): string | undefined {\n const store = als.getStore();\n if (store !== undefined) {\n if (store.orgId) markAuthContextAccess(store);\n return store.orgId;\n }\n return processEnv(\"AGENT_ORG_ID\");\n}\n\nfunction markAuthContextAccess(ctx: RequestContext | undefined) {\n if (!ctx) return;\n if (ctx.userEmail || ctx.userName || ctx.orgId) {\n ctx.authContextAccessed = true;\n }\n}\n\nexport function hasAuthContextAccess(ctx: RequestContext | undefined): boolean {\n return Boolean(ctx?.authContextAccessed);\n}\n\n/**\n * Get the current request's IANA timezone (e.g. \"America/Los_Angeles\").\n * The UI sends this via the `x-user-timezone` header on every action call, and\n * the agent chat plugin propagates it into the request context so that\n * agent-initiated tool calls also see the user's timezone. Falls back to\n * `process.env.AGENT_USER_TIMEZONE` only for CLI scripts (no request context).\n */\nexport function getRequestTimezone(): string | undefined {\n const store = als.getStore();\n if (store !== undefined) return store.timezone;\n return processEnv(\"AGENT_USER_TIMEZONE\");\n}\n\n/**\n * Returns true when this request is on an integration-platform path (Slack,\n * Telegram, etc.) — i.e. we're inside the integration plugin's processor\n * function and the platform's deliver-by deadline plus the host's function\n * timeout are the binding budget. Non-integration callers (CLI, normal\n * agent chat) should treat this as `false`.\n */\nexport function isIntegrationCallerRequest(): boolean {\n return als.getStore()?.isIntegrationCaller === true;\n}\n\nexport function getIntegrationRequestContext():\n | NonNullable<RequestContext[\"integration\"]>\n | undefined {\n return als.getStore()?.integration;\n}\n\n/**\n * Convenience: returns `{ userEmail, orgId }` from the active request context,\n * suitable for passing to `resolveCredential(key, ctx)`. Returns `null` when\n * no user is associated with the call (e.g. an unauthenticated public route).\n *\n * For framework actions auto-mounted at `/_agent-native/actions/...` this is\n * always populated because action-routes wraps every invocation in\n * `runWithRequestContext`. For hand-written `/api/*` routes the calling code\n * is responsible for setting up the context (see `runWithRequestContext`).\n */\nexport function getCredentialContext(): {\n userEmail: string;\n orgId: string | null;\n} | null {\n const userEmail = getRequestUserEmail();\n if (!userEmail) return null;\n return { userEmail, orgId: getRequestOrgId() ?? null };\n}\n\n/**\n * Get the active request's mutable agent-run state. Returns `undefined` when\n * called outside an agent run (e.g. before `prepareRun` or in a non-agent\n * code path). Callers must tolerate the field absence; use the helper\n * `requireRequestRunContext()` if missing context is a programming error.\n */\nexport function getRequestRunContext(): RequestRunContext | undefined {\n const store = als.getStore();\n if (!store) return undefined;\n return store.run;\n}\n\n/**\n * Ensure a `RequestRunContext` exists on the active request store and\n * return it. Used by the agent-chat handler to attach run state once it\n * starts processing a chat request. Returns `undefined` if there is no\n * active request store (caller should not be invoking this outside ALS).\n */\nexport function ensureRequestRunContext(): RequestRunContext | undefined {\n const store = als.getStore();\n if (!store) return undefined;\n if (!store.run) store.run = {};\n return store.run;\n}\n"]}
1
+ {"version":3,"file":"request-context.js","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Per-request context using AsyncLocalStorage.\n *\n * Replaces the unsafe pattern of mutating `process.env.AGENT_USER_EMAIL` /\n * `process.env.AGENT_ORG_ID` on every request. On Node.js (Netlify, self-hosted)\n * concurrent requests would overwrite each other's env vars. AsyncLocalStorage\n * gives each async call-chain its own isolated context.\n *\n * Supported on all deployment targets:\n * - Node.js (native)\n * - Cloudflare Workers (via nodejs_compat flag)\n * - Deno Deploy (via node:async_hooks compat)\n *\n * For CLI scripts that run outside a request context, the getters fall back to\n * process.env so existing `AGENT_USER_EMAIL=x pnpm action foo` invocations\n * continue to work.\n */\n\ntype AsyncLocalStorageLike<T> = {\n getStore(): T | undefined;\n run<R>(store: T, callback: () => R): R;\n};\n\ntype AsyncLocalStorageCtor = new <T>() => AsyncLocalStorageLike<T>;\n\nclass StackAsyncLocalStorage<T> implements AsyncLocalStorageLike<T> {\n private readonly stack: T[] = [];\n\n getStore(): T | undefined {\n return this.stack.at(-1);\n }\n\n run<R>(store: T, callback: () => R): R {\n this.stack.push(store);\n try {\n const result = callback();\n const maybePromise = result as unknown as\n | { finally?: (callback: () => void) => unknown }\n | undefined;\n if (maybePromise && typeof maybePromise.finally === \"function\") {\n return maybePromise.finally(() => {\n this.stack.pop();\n }) as R;\n }\n this.stack.pop();\n return result;\n } catch (error) {\n this.stack.pop();\n throw error;\n }\n }\n}\n\nfunction getAsyncLocalStorageCtor(): AsyncLocalStorageCtor | undefined {\n if (\n typeof window !== \"undefined\" ||\n typeof process === \"undefined\" ||\n !process.versions?.node ||\n typeof process.getBuiltinModule !== \"function\"\n ) {\n return undefined;\n }\n return process.getBuiltinModule(\"node:async_hooks\")?.AsyncLocalStorage as\n | AsyncLocalStorageCtor\n | undefined;\n}\n\nconst AsyncLocalStorageCtor = getAsyncLocalStorageCtor();\n\nfunction processEnv(name: string): string | undefined {\n if (typeof process === \"undefined\") return undefined;\n return process.env?.[name];\n}\n\n/**\n * Per-request agent-run state. Lives on `RequestContext.run` so the\n * agent-chat plugin can populate fields as the run progresses (owner,\n * resolved API key, system prompt, engine, model, threadId) without\n * mutating module-scope `let` bindings — those leak across concurrent\n * requests on a single Node.js process.\n *\n * Mutated in-place by `prepareRun`, `onEngineResolved`, `onRunStart` so\n * tool factory closures (automation, fetch, team, builder-browser) read\n * the live per-request value via `getRequestRunContext()`.\n */\nexport interface RequestRunContext {\n /** Request-scoped serverless continuation hook, when the runtime provides one. */\n waitUntil?: (promise: Promise<unknown>) => void;\n /** Origin of the current request (used by the builder-browser tool). */\n requestOrigin?: string;\n /** Stable browser tab id for tab-scoped app-state reads/writes. */\n browserTabId?: string;\n /** Resource scope for the current chat thread, e.g. the active deck. */\n chatScope?: {\n type: string;\n id: string;\n label?: string;\n } | null;\n /** Resolved owner email (set by prepareRun). */\n owner?: string;\n /** Owner's active Anthropic API key (set by prepareRun). */\n userApiKey?: string;\n /** Thread ID for the current run (set by onRunStart). */\n threadId?: string;\n /** System prompt actually sent to the model for this run. */\n systemPrompt?: string;\n /** Engine instance for this run (set by onEngineResolved). */\n engine?: import(\"../agent/engine/types.js\").AgentEngine;\n /** Model name for this run (set by onEngineResolved). */\n model?: string;\n /**\n * True when this run is executing inside the durable background-function\n * worker (the `_process-run` self-dispatch), not the synchronous foreground\n * request. Template `extraContext` / system-prompt builders can read this to\n * skip heavy, hang-prone enrichment (large data-dictionary DB reads, etc.)\n * in the worker so it reliably claims its run within the setup budget.\n */\n isBackgroundWorker?: boolean;\n /** Tool calls made so far in the current agent loop. */\n toolCalls?: Array<{ name: string; input: unknown }>;\n /** Tool results returned so far in the current agent loop. */\n toolResults?: Array<{ name: string; content: string; isError: boolean }>;\n /** Per-run fingerprints for large extension bodies already sent to the LLM. */\n extensionContentReads?: Record<string, string>;\n /** Per-run fingerprints for repeated tool-search calls already sent to the LLM. */\n toolSearchReads?: Record<\n string,\n { totalTools: number; resultNames: string[] }\n >;\n}\n\nexport interface RequestContext {\n userEmail?: string;\n userName?: string;\n orgId?: string;\n timezone?: string;\n /**\n * Set when code reads authenticated request context. Public SSR shell/data\n * should not depend on this value; user/org-specific reads belong behind\n * client-side actions/API after hydration.\n */\n authContextAccessed?: boolean;\n /**\n * Origin of the inbound request (e.g. `http://127.0.0.1:8100`). Set by the\n * MCP mount from the request headers so actions that build externally\n * fetchable URLs (e.g. design `export-coding-handoff`'s signed raw-code URL)\n * resolve the real local-workspace origin instead of a prod/localhost\n * fallback. Optional — absent on paths that don't populate it.\n */\n requestOrigin?: string;\n /**\n * True when this request is being processed by an integration-platform\n * webhook (Slack, Telegram, etc.) where the function timeout is the\n * binding constraint. Code that calls slow remote APIs can use this to apply\n * tighter budgets on this path while leaving normal agent-chat callers\n * (5+ min budget) unaffected.\n */\n isIntegrationCaller?: boolean;\n /**\n * Metadata for the currently-processing integration task. This lets tools\n * that start long-running remote work persist a continuation that can update\n * the originating platform thread after the current function budget ends.\n */\n integration?: {\n taskId: string;\n attempts?: number;\n incoming: import(\"../integrations/types.js\").IncomingMessage;\n placeholderRef?: string;\n /** Opaque provider-native progress surface for a durable continuation. */\n progressRef?: import(\"../integrations/types.js\").PlatformRunProgressRef;\n installationId?: string;\n scopeId?: string;\n principalType?: \"user\" | \"service\";\n lineage?: {\n runId?: string;\n parentTaskId?: string;\n source?: {\n kind: string;\n platform?: string;\n id: string;\n url?: string;\n };\n network?: {\n protocol: \"a2a\" | \"mcp\" | \"provider-api\";\n id: string;\n peer?: string;\n };\n };\n };\n /**\n * Mutable per-request agent-run state. Populated by the agent-chat plugin\n * during a run; tool closures dereference it on each invocation.\n */\n run?: RequestRunContext;\n}\n\nconst GLOBAL_KEY = \"__agentNativeRequestContextAls\" as const;\nconst OBSERVERS_KEY = \"__agentNativeRequestContextObservers\" as const;\nconst BOUNDARY_KEY = \"__agentNativeRequestBoundaryInstalled\" as const;\ntype RequestContextObserver = (ctx: RequestContext) => void;\ntype GlobalWithRequestContext = typeof globalThis & {\n [GLOBAL_KEY]?: AsyncLocalStorageLike<RequestContext>;\n [OBSERVERS_KEY]?: RequestContextObserver[];\n [BOUNDARY_KEY]?: boolean;\n};\nconst globalRef = globalThis as GlobalWithRequestContext;\nif (!globalRef[GLOBAL_KEY]) {\n globalRef[GLOBAL_KEY] = AsyncLocalStorageCtor\n ? new AsyncLocalStorageCtor<RequestContext>()\n : new StackAsyncLocalStorage<RequestContext>();\n}\nif (!globalRef[OBSERVERS_KEY]) {\n globalRef[OBSERVERS_KEY] = [];\n}\nconst als = globalRef[GLOBAL_KEY]!;\nconst observers = globalRef[OBSERVERS_KEY]!;\n\n/**\n * Register a callback fired every time `runWithRequestContext` enters a new\n * scope. The hook runs INSIDE the AsyncLocalStorage scope, so observability\n * helpers that read the current isolation scope (e.g. Sentry) attach to the\n * right per-request context.\n *\n * Returned function unregisters the observer. Observers must never throw —\n * any error is swallowed so a misbehaving observer can't break the request\n * path.\n */\nexport function addRequestContextObserver(\n observer: RequestContextObserver,\n): () => void {\n observers.push(observer);\n return () => {\n const i = observers.indexOf(observer);\n if (i !== -1) observers.splice(i, 1);\n };\n}\n\n/**\n * Run a callback within a per-request context. The context is available to all\n * async operations spawned from `fn` via `getRequestUserEmail()` / `getRequestOrgId()`.\n *\n * Any registered `addRequestContextObserver` callbacks fire inside the new\n * scope before `fn` runs, so observability code can pin user/org info onto\n * isolation-scoped backends (Sentry, OpenTelemetry, etc.).\n */\nexport function runWithRequestContext<T>(\n ctx: RequestContext,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n return als.run(ctx, () => {\n if (observers.length > 0) {\n for (const obs of observers) {\n try {\n obs(ctx);\n } catch {\n // Observers must never break the request path.\n }\n }\n }\n return fn();\n });\n}\n\n/**\n * Return the active request context, if this call chain is running under one.\n *\n * This is intentionally distinct from `getRequestUserEmail()`: callers that\n * have an active context with no authenticated user must not fall through to\n * process-wide CLI fallbacks such as `AGENT_USER_EMAIL` or \"latest session\".\n */\nexport function getRequestContext(): RequestContext | undefined {\n const store = als.getStore();\n markAuthContextAccess(store);\n return store;\n}\n\n/**\n * True when AsyncLocalStorage has an active context for this call chain.\n * Useful for helpers that support both HTTP requests and standalone CLI runs.\n */\nexport function hasRequestContext(): boolean {\n return als.getStore() !== undefined;\n}\n\n/**\n * Record that the framework's request-boundary middleware is installed in this\n * process, so every inbound HTTP request runs inside a `RequestContext`.\n *\n * Once that is true, a request-scoped identity read that finds no store can no\n * longer be an HTTP caller — which is what makes the ambient-identity warning\n * in `getRequestUserEmail()` specific enough to be worth emitting.\n */\nexport function markRequestBoundaryInstalled(): void {\n globalRef[BOUNDARY_KEY] = true;\n}\n\nexport function hasRequestBoundary(): boolean {\n return globalRef[BOUNDARY_KEY] === true;\n}\n\n/**\n * The ambient, process-wide identity configured for this deployment\n * (`AGENT_USER_EMAIL`). Legitimate callers are the ones with no request behind\n * them at all: CLI invocations, cron/scheduled jobs, seed and QA scripts.\n *\n * TRAP: this is not the caller's identity, and a request handler that reads it\n * authorizes whoever the deploy env names rather than whoever signed in — it\n * fails open toward more privilege. Request handlers read\n * `getRequestUserEmail()` and fail closed when it returns undefined.\n */\nexport function getAmbientUserEmail(): string | undefined {\n return processEnv(\"AGENT_USER_EMAIL\");\n}\n\n/** Ambient process-wide org (`AGENT_ORG_ID`). Same trap as `getAmbientUserEmail()`. */\nexport function getAmbientOrgId(): string | undefined {\n return processEnv(\"AGENT_ORG_ID\");\n}\n\nconst warnedAmbientIdentities = new Set<string>();\n\nfunction warnAmbientIdentitySatisfiedRead(email: string): void {\n if (!hasRequestBoundary()) return;\n if (warnedAmbientIdentities.has(email)) return;\n warnedAmbientIdentities.add(email);\n console.warn(\n `[agent-native] getRequestUserEmail() found no request context and answered with the ambient ` +\n `AGENT_USER_EMAIL identity (${email}). This process serves HTTP requests, so a request-scoped ` +\n `read reaching the ambient identity is a bug: it authorizes the deploy env, not the signed-in ` +\n `user. Wrap the caller in runWithRequestContext({ userEmail }), or call getAmbientUserEmail() ` +\n `explicitly if the process identity really is what you mean.`,\n );\n}\n\n/**\n * Get the current request's user email.\n *\n * - If a request context exists (HTTP/A2A path), returns its `userEmail` —\n * even when that value is `undefined`. The env fallback MUST NOT fire here:\n * a stale process-wide `AGENT_USER_EMAIL` from a CLI run or previous bug\n * would leak into an unauthenticated A2A/API call (e.g. unsigned or API-key\n * modes where `runWithRequestContext({ userEmail: undefined })` is used).\n * - Only when there is NO request context (CLI scripts) do we fall back to\n * `process.env.AGENT_USER_EMAIL`. In a process that serves HTTP requests the\n * framework installs a request boundary so that case cannot be a request;\n * if it happens anyway we warn loudly rather than answer silently.\n */\nexport function getRequestUserEmail(): string | undefined {\n const store = als.getStore();\n if (store !== undefined) {\n if (store.userEmail) markAuthContextAccess(store);\n return store.userEmail;\n }\n const ambient = processEnv(\"AGENT_USER_EMAIL\");\n if (ambient) warnAmbientIdentitySatisfiedRead(ambient);\n return ambient;\n}\n\n/**\n * Get the current request's display name, when the auth provider supplied one.\n *\n * The same request-context fallback rules as `getRequestUserEmail()` apply:\n * HTTP/A2A calls only read AsyncLocalStorage, while CLI scripts may opt in via\n * `AGENT_USER_NAME`.\n */\nexport function getRequestUserName(): string | undefined {\n const store = als.getStore();\n if (store !== undefined) {\n if (store.userName) markAuthContextAccess(store);\n return store.userName;\n }\n return processEnv(\"AGENT_USER_NAME\");\n}\n\n/**\n * Get the current request's org ID.\n *\n * Same store-aware semantics as `getRequestUserEmail()` — env fallback is\n * CLI-only, so a request that explicitly has no org doesn't inherit a stale\n * `process.env.AGENT_ORG_ID` from a prior request on the same Lambda instance.\n */\nexport function getRequestOrgId(): string | undefined {\n const store = als.getStore();\n if (store !== undefined) {\n if (store.orgId) markAuthContextAccess(store);\n return store.orgId;\n }\n return processEnv(\"AGENT_ORG_ID\");\n}\n\nfunction markAuthContextAccess(ctx: RequestContext | undefined) {\n if (!ctx) return;\n if (ctx.userEmail || ctx.userName || ctx.orgId) {\n ctx.authContextAccessed = true;\n }\n}\n\nexport function hasAuthContextAccess(ctx: RequestContext | undefined): boolean {\n return Boolean(ctx?.authContextAccessed);\n}\n\n/**\n * Get the current request's IANA timezone (e.g. \"America/Los_Angeles\").\n * The UI sends this via the `x-user-timezone` header on every action call, and\n * the agent chat plugin propagates it into the request context so that\n * agent-initiated tool calls also see the user's timezone. Falls back to\n * `process.env.AGENT_USER_TIMEZONE` only for CLI scripts (no request context).\n */\nexport function getRequestTimezone(): string | undefined {\n const store = als.getStore();\n if (store !== undefined) return store.timezone;\n return processEnv(\"AGENT_USER_TIMEZONE\");\n}\n\n/**\n * Returns true when this request is on an integration-platform path (Slack,\n * Telegram, etc.) — i.e. we're inside the integration plugin's processor\n * function and the platform's deliver-by deadline plus the host's function\n * timeout are the binding budget. Non-integration callers (CLI, normal\n * agent chat) should treat this as `false`.\n */\nexport function isIntegrationCallerRequest(): boolean {\n return als.getStore()?.isIntegrationCaller === true;\n}\n\nexport function getIntegrationRequestContext():\n | NonNullable<RequestContext[\"integration\"]>\n | undefined {\n return als.getStore()?.integration;\n}\n\n/**\n * Convenience: returns `{ userEmail, orgId }` from the active request context,\n * suitable for passing to `resolveCredential(key, ctx)`. Returns `null` when\n * no user is associated with the call (e.g. an unauthenticated public route).\n *\n * For framework actions auto-mounted at `/_agent-native/actions/...` this is\n * always populated because action-routes wraps every invocation in\n * `runWithRequestContext`. For hand-written `/api/*` routes the calling code\n * is responsible for setting up the context (see `runWithRequestContext`).\n */\nexport function getCredentialContext(): {\n userEmail: string;\n orgId: string | null;\n} | null {\n const userEmail = getRequestUserEmail();\n if (!userEmail) return null;\n return { userEmail, orgId: getRequestOrgId() ?? null };\n}\n\n/**\n * Get the active request's mutable agent-run state. Returns `undefined` when\n * called outside an agent run (e.g. before `prepareRun` or in a non-agent\n * code path). Callers must tolerate the field absence; use the helper\n * `requireRequestRunContext()` if missing context is a programming error.\n */\nexport function getRequestRunContext(): RequestRunContext | undefined {\n const store = als.getStore();\n if (!store) return undefined;\n return store.run;\n}\n\n/**\n * Ensure a `RequestRunContext` exists on the active request store and\n * return it. Used by the agent-chat handler to attach run state once it\n * starts processing a chat request. Returns `undefined` if there is no\n * active request store (caller should not be invoking this outside ALS).\n */\nexport function ensureRequestRunContext(): RequestRunContext | undefined {\n const store = als.getStore();\n if (!store) return undefined;\n if (!store.run) store.run = {};\n return store.run;\n}\n"]}
@@ -20,7 +20,7 @@ export declare function createTranscribeVoiceHandler(): import("h3").EventHandle
20
20
  error: string;
21
21
  text?: undefined;
22
22
  } | {
23
- text: string;
24
23
  error?: undefined;
24
+ text: string;
25
25
  }>>;
26
26
  //# sourceMappingURL=transcribe-voice.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/shared/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,kFAAkF;AAClF,wBAAgB,aAAa,IAAI,OAAO,CAOvC;AAED,qDAAqD;AACrD,wBAAgB,mBAAmB,IAAI,OAAO,CAM7C;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,IAAI,OAAO,CAEvC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/shared/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,kFAAkF;AAClF,wBAAgB,aAAa,IAAI,OAAO,CAQvC;AAED,qDAAqD;AACrD,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,IAAI,OAAO,CAEvC"}
@@ -10,11 +10,13 @@ export function isNodeRuntime() {
10
10
  return (typeof process !== "undefined" &&
11
11
  typeof process.versions?.node === "string" &&
12
12
  !("__cf_env" in globalThis) &&
13
+ !("__env__" in globalThis) &&
13
14
  !("Deno" in globalThis));
14
15
  }
15
16
  /** True when running in Cloudflare Workers/Pages. */
16
17
  export function isCloudflareRuntime() {
17
18
  return ("__cf_env" in globalThis ||
19
+ "__env__" in globalThis ||
18
20
  (typeof navigator !== "undefined" &&
19
21
  navigator.userAgent === "Cloudflare-Workers"));
20
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/shared/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,kFAAkF;AAClF,MAAM,UAAU,aAAa;IAC3B,OAAO,CACL,OAAO,OAAO,KAAK,WAAW;QAC9B,OAAO,OAAO,CAAC,QAAQ,EAAE,IAAI,KAAK,QAAQ;QAC1C,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC;QAC3B,CAAC,CAAC,MAAM,IAAI,UAAU,CAAC,CACxB,CAAC;AACJ,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,mBAAmB;IACjC,OAAO,CACL,UAAU,IAAI,UAAU;QACxB,CAAC,OAAO,SAAS,KAAK,WAAW;YAC/B,SAAS,CAAC,SAAS,KAAK,oBAAoB,CAAC,CAChD,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,aAAa;IAC3B,OAAO,CAAC,aAAa,EAAE,CAAC;AAC1B,CAAC","sourcesContent":["/**\n * Runtime detection utilities.\n *\n * Detect whether the code is running in Node.js, Cloudflare Workers,\n * Deno, or another edge runtime. Used to gracefully skip Node-only\n * features (filesystem, PTY, file watching) on edge runtimes.\n */\n\n/** True when running in a full Node.js environment (not CF Workers, not Deno). */\nexport function isNodeRuntime(): boolean {\n return (\n typeof process !== \"undefined\" &&\n typeof process.versions?.node === \"string\" &&\n !(\"__cf_env\" in globalThis) &&\n !(\"Deno\" in globalThis)\n );\n}\n\n/** True when running in Cloudflare Workers/Pages. */\nexport function isCloudflareRuntime(): boolean {\n return (\n \"__cf_env\" in globalThis ||\n (typeof navigator !== \"undefined\" &&\n navigator.userAgent === \"Cloudflare-Workers\")\n );\n}\n\n/** True when running in any edge/serverless runtime (not full Node.js). */\nexport function isEdgeRuntime(): boolean {\n return !isNodeRuntime();\n}\n"]}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/shared/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,kFAAkF;AAClF,MAAM,UAAU,aAAa;IAC3B,OAAO,CACL,OAAO,OAAO,KAAK,WAAW;QAC9B,OAAO,OAAO,CAAC,QAAQ,EAAE,IAAI,KAAK,QAAQ;QAC1C,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC;QAC3B,CAAC,CAAC,SAAS,IAAI,UAAU,CAAC;QAC1B,CAAC,CAAC,MAAM,IAAI,UAAU,CAAC,CACxB,CAAC;AACJ,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,mBAAmB;IACjC,OAAO,CACL,UAAU,IAAI,UAAU;QACxB,SAAS,IAAI,UAAU;QACvB,CAAC,OAAO,SAAS,KAAK,WAAW;YAC/B,SAAS,CAAC,SAAS,KAAK,oBAAoB,CAAC,CAChD,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,aAAa;IAC3B,OAAO,CAAC,aAAa,EAAE,CAAC;AAC1B,CAAC","sourcesContent":["/**\n * Runtime detection utilities.\n *\n * Detect whether the code is running in Node.js, Cloudflare Workers,\n * Deno, or another edge runtime. Used to gracefully skip Node-only\n * features (filesystem, PTY, file watching) on edge runtimes.\n */\n\n/** True when running in a full Node.js environment (not CF Workers, not Deno). */\nexport function isNodeRuntime(): boolean {\n return (\n typeof process !== \"undefined\" &&\n typeof process.versions?.node === \"string\" &&\n !(\"__cf_env\" in globalThis) &&\n !(\"__env__\" in globalThis) &&\n !(\"Deno\" in globalThis)\n );\n}\n\n/** True when running in Cloudflare Workers/Pages. */\nexport function isCloudflareRuntime(): boolean {\n return (\n \"__cf_env\" in globalThis ||\n \"__env__\" in globalThis ||\n (typeof navigator !== \"undefined\" &&\n navigator.userAgent === \"Cloudflare-Workers\")\n );\n}\n\n/** True when running in any edge/serverless runtime (not full Node.js). */\nexport function isEdgeRuntime(): boolean {\n return !isNodeRuntime();\n}\n"]}
@@ -151,6 +151,35 @@ Rules:
151
151
  - **Scope matches the registration.** `scope: "user"` → pass the user email.
152
152
  `scope: "workspace"` → pass the active `orgId` from
153
153
  `getOrgContext(event).orgId`.
154
+ - **One resolver per key, and every runtime path goes through it.** Before
155
+ reading a credential, grep the app for the key name. If a resolver already
156
+ exists (`resolveXConfig`, a connector, a client factory), call it — do not
157
+ read `process.env` for that key a second time somewhere else.
158
+ - **Identity comes from the caller, not the module.** A shared helper under
159
+ `server/lib/` takes the email as a parameter; only an entrypoint (action,
160
+ route, cron) decides whose identity it is. A library that resolves its own
161
+ identity from `process.env.AGENT_USER_EMAIL` authorizes the deployment rather
162
+ than the caller.
163
+
164
+ The failure this prevents is not a leak — it is a split brain. When the config
165
+ check reads the vault and the feature reads `process.env`, the settings UI and
166
+ onboarding checklist report the integration as **configured** while every actual
167
+ call fails with "env var is required". The credential is right there in the
168
+ vault, so the error names the wrong cause and sends everyone hunting for a sync
169
+ or redeploy problem that does not exist. This has now shipped four times in one
170
+ app (BigQuery, Jira, Pylon, Academy).
171
+
172
+ Before finishing any change that touches a credential, run the guard from the
173
+ app directory — it finds this whether the app lives in `templates/` or in a
174
+ workspace repo:
175
+
176
+ ```bash
177
+ npx agent-native doctor --only no-env-credentials
178
+ ```
179
+
180
+ Findings in files that already call `resolveCredential` are usually the
181
+ sanctioned `resolveCredential(key, ctx) ?? process.env.KEY` fallback. The bugs
182
+ are the files with **no** resolver at all.
154
183
 
155
184
  ## HTTP routes
156
185
 
@@ -92,19 +92,19 @@ const messages = {
92
92
  curatedTemplates: "قوالب منسقة",
93
93
  curatedTemplatesDescription:
94
94
  "ابدأ من شكل تطبيق تمت مراجعته، ثم اجعله خاصًا بك.",
95
- remix: "إعادة المزج",
96
- remixTemplate: "إعادة مزج {{name}}",
95
+ remix: "إنشاء من قالب",
96
+ remixTemplate: "إنشاء تطبيق {{name}}",
97
97
  remixAppIdLabel: "معرّف التطبيق الجديد",
98
- remixStarted: "بدأت إعادة مزج {{name}}",
98
+ remixStarted: "بدأ إنشاء {{name}}",
99
99
  viewLiveApp: "عرض التطبيق المباشر",
100
100
  alreadyInWorkspace: "موجود بالفعل في مساحة العمل",
101
101
  remixAppIdDescription:
102
102
  "اختر معرّفًا آمنًا لعنوان URL لتطبيق مساحة العمل الجديد.",
103
103
  integrationSetup: "إعداد التكامل",
104
104
  source: "المصدر",
105
- remixing: "جارٍ إعادة المزج…",
106
- remixSuccess: "بدأت إعادة مزج القالب.",
107
- remixError: "تعذرت إعادة مزج هذا القالب",
105
+ remixing: "جارٍ إنشاء التطبيق…",
106
+ remixSuccess: "بدأ إنشاء التطبيق من القالب.",
107
+ remixError: "تعذر إنشاء تطبيق من هذا القالب",
108
108
  appIdRequired: "معرّف التطبيق مطلوب.",
109
109
  hide: "إخفاء",
110
110
  show: "Show",
@@ -91,19 +91,19 @@ const messages = {
91
91
  curatedTemplates: "Kuratierte Vorlagen",
92
92
  curatedTemplatesDescription:
93
93
  "Starte mit einer geprüften App-Struktur und passe sie an.",
94
- remix: "Remix",
95
- remixTemplate: "{{name}} remixen",
94
+ remix: "Aus Vorlage erstellen",
95
+ remixTemplate: "{{name}}-App erstellen",
96
96
  remixAppIdLabel: "Neue App-ID",
97
- remixStarted: "Remix für {{name}} gestartet",
97
+ remixStarted: "Erstellung von {{name}} gestartet",
98
98
  viewLiveApp: "Live-App öffnen",
99
99
  alreadyInWorkspace: "Bereits im Workspace",
100
100
  remixAppIdDescription:
101
101
  "Wähle eine URL-sichere ID für die neue Workspace-App.",
102
102
  integrationSetup: "Integration einrichten",
103
103
  source: "Quelle",
104
- remixing: "Remix wird erstellt…",
105
- remixSuccess: "Template-Remix gestartet.",
106
- remixError: "Dieses Template konnte nicht geremixt werden",
104
+ remixing: "App wird erstellt…",
105
+ remixSuccess: "Erstellung der App aus der Vorlage gestartet.",
106
+ remixError: "App konnte nicht aus dieser Vorlage erstellt werden",
107
107
  appIdRequired: "App-ID ist erforderlich.",
108
108
  hide: "Ausblenden",
109
109
  show: "Show",
@@ -89,19 +89,19 @@ const messages = {
89
89
  curatedTemplates: "Curated templates",
90
90
  curatedTemplatesDescription:
91
91
  "Start from a reviewed app shape, then make it your own.",
92
- remix: "Remix",
93
- remixTemplate: "Remix {{name}}",
92
+ remix: "Create from template",
93
+ remixTemplate: "Create {{name}} app",
94
94
  remixAppIdLabel: "New app id",
95
- remixStarted: "Started {{name}} remix",
95
+ remixStarted: "Started creating {{name}}",
96
96
  viewLiveApp: "View live app",
97
97
  alreadyInWorkspace: "Already in workspace",
98
98
  remixAppIdDescription:
99
99
  "Choose the URL-safe id for the new workspace app.",
100
100
  integrationSetup: "Integration setup",
101
101
  source: "Source",
102
- remixing: "Remixing…",
103
- remixSuccess: "Template remix started.",
104
- remixError: "Could not remix this template",
102
+ remixing: "Creating app…",
103
+ remixSuccess: "Template app creation started.",
104
+ remixError: "Could not create an app from this template",
105
105
  appIdRequired: "App ID is required.",
106
106
  hide: "Hide",
107
107
  show: "Show",
@@ -91,19 +91,19 @@ const messages = {
91
91
  curatedTemplates: "Plantillas seleccionadas",
92
92
  curatedTemplatesDescription:
93
93
  "Empieza con una estructura de aplicación revisada y hazla tuya.",
94
- remix: "Reutilizar",
95
- remixTemplate: "Reutilizar {{name}}",
94
+ remix: "Crear desde plantilla",
95
+ remixTemplate: "Crear app de {{name}}",
96
96
  remixAppIdLabel: "Nuevo ID de aplicación",
97
- remixStarted: "Se inició la reutilización de {{name}}",
97
+ remixStarted: "Se inició la creación de {{name}}",
98
98
  viewLiveApp: "Ver aplicación en vivo",
99
99
  alreadyInWorkspace: "Ya está en el espacio de trabajo",
100
100
  remixAppIdDescription:
101
101
  "Elige un ID seguro para URL para la nueva aplicación.",
102
102
  integrationSetup: "Configuración de integración",
103
103
  source: "Origen",
104
- remixing: "Reutilizando…",
105
- remixSuccess: "Se inició la reutilización de la plantilla.",
106
- remixError: "No se pudo reutilizar esta plantilla",
104
+ remixing: "Creando app…",
105
+ remixSuccess: "Se inició la creación de la app desde la plantilla.",
106
+ remixError: "No se pudo crear una app desde esta plantilla",
107
107
  appIdRequired: "El ID de aplicación es obligatorio.",
108
108
  hide: "Ocultar",
109
109
  show: "Show",
@@ -93,19 +93,19 @@ const messages = {
93
93
  curatedTemplates: "Modèles sélectionnés",
94
94
  curatedTemplatesDescription:
95
95
  "Partez d’une structure d’application vérifiée et personnalisez-la.",
96
- remix: "Remixer",
97
- remixTemplate: "Remixer {{name}}",
96
+ remix: "Créer à partir du modèle",
97
+ remixTemplate: "Créer l’app {{name}}",
98
98
  remixAppIdLabel: "Nouvel identifiant d’application",
99
- remixStarted: "Remix de {{name}} lancé",
99
+ remixStarted: "Création de {{name}} démarrée",
100
100
  viewLiveApp: "Voir l’application en direct",
101
101
  alreadyInWorkspace: "Déjà dans l’espace de travail",
102
102
  remixAppIdDescription:
103
103
  "Choisissez un identifiant compatible avec l’URL pour la nouvelle application.",
104
104
  integrationSetup: "Configuration de l’intégration",
105
105
  source: "Source",
106
- remixing: "Remix en cours…",
107
- remixSuccess: "Le remix du modèle a démarré.",
108
- remixError: "Impossible de remixer ce modèle",
106
+ remixing: "Création de l’app…",
107
+ remixSuccess: "Création de l’app à partir du modèle démarrée.",
108
+ remixError: "Impossible de créer une app à partir de ce modèle",
109
109
  appIdRequired: "L’identifiant de l’application est requis.",
110
110
  hide: "Masquer",
111
111
  show: "Show",
@@ -87,18 +87,18 @@ const messages = {
87
87
  curatedTemplates: "चयनित टेम्पलेट",
88
88
  curatedTemplatesDescription:
89
89
  "समीक्षित ऐप संरचना से शुरू करें और इसे अपने अनुसार बनाएं।",
90
- remix: "रीमिक्स",
91
- remixTemplate: "{{name}} रीमिक्स करें",
90
+ remix: "टेम्पलेट से बनाएं",
91
+ remixTemplate: "{{name}} ऐप बनाएं",
92
92
  remixAppIdLabel: "नया ऐप आईडी",
93
- remixStarted: "{{name}} रीमिक्स शुरू हुआ",
93
+ remixStarted: "{{name}} बनाना शुरू किया",
94
94
  viewLiveApp: "लाइव ऐप देखें",
95
95
  alreadyInWorkspace: "वर्कस्पेस में पहले से मौजूद",
96
96
  remixAppIdDescription: "नए वर्कस्पेस ऐप के लिए URL-सुरक्षित आईडी चुनें।",
97
97
  integrationSetup: "इंटीग्रेशन सेटअप",
98
98
  source: "स्रोत",
99
- remixing: "रीमिक्स हो रहा है…",
100
- remixSuccess: "टेम्पलेट रीमिक्स शुरू हुआ।",
101
- remixError: "यह टेम्पलेट रीमिक्स नहीं हो सका",
99
+ remixing: "ऐप बनाया जा रहा है…",
100
+ remixSuccess: "टेम्पलेट से ऐप बनाना शुरू किया गया।",
101
+ remixError: "इस टेम्पलेट से ऐप नहीं बना सके",
102
102
  appIdRequired: "ऐप आईडी आवश्यक है।",
103
103
  hide: "छिपाएं",
104
104
  show: "Show",
@@ -89,19 +89,19 @@ const messages = {
89
89
  curatedTemplates: "厳選テンプレート",
90
90
  curatedTemplatesDescription:
91
91
  "レビュー済みのアプリ構成をベースに、自分用にカスタマイズできます。",
92
- remix: "リミックス",
93
- remixTemplate: "{{name}} をリミックス",
92
+ remix: "テンプレートから作成",
93
+ remixTemplate: "{{name}} アプリを作成",
94
94
  remixAppIdLabel: "新しいアプリ ID",
95
- remixStarted: "{{name}} のリミックスを開始しました",
95
+ remixStarted: "{{name}} の作成を開始しました",
96
96
  viewLiveApp: "ライブアプリを見る",
97
97
  alreadyInWorkspace: "ワークスペースに追加済み",
98
98
  remixAppIdDescription:
99
99
  "新しいワークスペースアプリの URL セーフな ID を選択してください。",
100
100
  integrationSetup: "連携の設定",
101
101
  source: "提供元",
102
- remixing: "リミックス中…",
103
- remixSuccess: "テンプレートのリミックスを開始しました。",
104
- remixError: "このテンプレートをリミックスできませんでした",
102
+ remixing: "アプリを作成中…",
103
+ remixSuccess: "テンプレートからのアプリ作成を開始しました。",
104
+ remixError: "このテンプレートからアプリを作成できませんでした",
105
105
  appIdRequired: "アプリ ID は必須です。",
106
106
  hide: "非表示",
107
107
  show: "Show",
@@ -88,18 +88,18 @@ const messages = {
88
88
  curatedTemplates: "엄선된 템플릿",
89
89
  curatedTemplatesDescription:
90
90
  "검토된 앱 구조에서 시작해 나만의 앱으로 만들어 보세요.",
91
- remix: "리믹스",
92
- remixTemplate: "{{name}} 리믹스",
91
+ remix: "템플릿에서 만들기",
92
+ remixTemplate: "{{name}} 앱 만들기",
93
93
  remixAppIdLabel: "새 앱 ID",
94
- remixStarted: "{{name}} 리믹스를 시작했습니다",
94
+ remixStarted: "{{name}} 생성을 시작했습니다",
95
95
  viewLiveApp: "라이브 앱 보기",
96
96
  alreadyInWorkspace: "워크스페이스에 이미 있음",
97
97
  remixAppIdDescription: "새 워크스페이스 앱의 URL 안전 ID를 선택하세요.",
98
98
  integrationSetup: "연동 설정",
99
99
  source: "소스",
100
- remixing: "리믹스 중…",
101
- remixSuccess: "템플릿 리믹스를 시작했습니다.",
102
- remixError: "이 템플릿을 리믹스할 수 없습니다",
100
+ remixing: " 만드는 중…",
101
+ remixSuccess: "템플릿에서 만들기를 시작했습니다.",
102
+ remixError: "이 템플릿에서 앱을 만들 수 없습니다",
103
103
  appIdRequired: "앱 ID가 필요합니다.",
104
104
  hide: "숨기기",
105
105
  show: "Show",
@@ -92,19 +92,19 @@ const messages = {
92
92
  curatedTemplates: "Modelos selecionados",
93
93
  curatedTemplatesDescription:
94
94
  "Comece com uma estrutura de app revisada e personalize-a.",
95
- remix: "Remixar",
96
- remixTemplate: "Remixar {{name}}",
95
+ remix: "Criar a partir do modelo",
96
+ remixTemplate: "Criar app {{name}}",
97
97
  remixAppIdLabel: "Novo ID do app",
98
- remixStarted: "Remix de {{name}} iniciado",
98
+ remixStarted: "Criação de {{name}} iniciada",
99
99
  viewLiveApp: "Ver app ao vivo",
100
100
  alreadyInWorkspace: "Já está no workspace",
101
101
  remixAppIdDescription:
102
102
  "Escolha um ID seguro para URL para o novo app do workspace.",
103
103
  integrationSetup: "Configuração da integração",
104
104
  source: "Origem",
105
- remixing: "Remixando…",
106
- remixSuccess: "Remix do modelo iniciado.",
107
- remixError: "Não foi possível remixar este modelo",
105
+ remixing: "Criando app…",
106
+ remixSuccess: "Criação do app a partir do modelo iniciada.",
107
+ remixError: "Não foi possível criar um app a partir deste modelo",
108
108
  appIdRequired: "O ID do app é obrigatório.",
109
109
  hide: "Ocultar",
110
110
  show: "Show",
@@ -85,18 +85,18 @@ const messages = {
85
85
  curatedTemplates: "精选模板",
86
86
  curatedTemplatesDescription:
87
87
  "从经过审核的应用结构开始,然后打造属于你的应用。",
88
- remix: "再创作",
89
- remixTemplate: "再创作 {{name}}",
88
+ remix: "从模板创建",
89
+ remixTemplate: "创建 {{name}} 应用",
90
90
  remixAppIdLabel: "新应用 ID",
91
- remixStarted: "已开始再创作 {{name}}",
91
+ remixStarted: "已开始创建 {{name}}",
92
92
  viewLiveApp: "查看在线应用",
93
93
  alreadyInWorkspace: "已在工作区中",
94
94
  remixAppIdDescription: "为新的工作区应用选择一个 URL 安全的 ID。",
95
95
  integrationSetup: "集成设置",
96
96
  source: "来源",
97
- remixing: "正在再创作…",
98
- remixSuccess: "已开始再创作模板。",
99
- remixError: "无法再创作此模板",
97
+ remixing: "正在创建应用…",
98
+ remixSuccess: "已开始从模板创建应用。",
99
+ remixError: "无法从此模板创建应用",
100
100
  appIdRequired: "应用 ID 是必填项。",
101
101
  hide: "隐藏",
102
102
  show: "Show",
@@ -85,18 +85,18 @@ const messages = {
85
85
  curatedTemplates: "精選範本",
86
86
  curatedTemplatesDescription:
87
87
  "從經過審核的應用程式結構開始,打造屬於你的應用程式。",
88
- remix: "重新混搭",
89
- remixTemplate: "重新混搭 {{name}}",
88
+ remix: "從範本建立",
89
+ remixTemplate: "建立 {{name}} 應用程式",
90
90
  remixAppIdLabel: "新應用程式 ID",
91
- remixStarted: "已開始重新混搭 {{name}}",
91
+ remixStarted: "已開始建立 {{name}}",
92
92
  viewLiveApp: "查看線上應用程式",
93
93
  alreadyInWorkspace: "已在工作區中",
94
94
  remixAppIdDescription: "為新的工作區應用程式選擇 URL 安全的 ID。",
95
95
  integrationSetup: "整合設定",
96
96
  source: "來源",
97
- remixing: "正在重新混搭…",
98
- remixSuccess: "已開始重新混搭範本。",
99
- remixError: "無法重新混搭此範本",
97
+ remixing: "正在建立應用程式…",
98
+ remixSuccess: "已開始從範本建立應用程式。",
99
+ remixError: "無法從此範本建立應用程式",
100
100
  appIdRequired: "應用程式 ID 為必填項目。",
101
101
  hide: "隱藏",
102
102
  show: "Show",
@@ -151,6 +151,35 @@ Rules:
151
151
  - **Scope matches the registration.** `scope: "user"` → pass the user email.
152
152
  `scope: "workspace"` → pass the active `orgId` from
153
153
  `getOrgContext(event).orgId`.
154
+ - **One resolver per key, and every runtime path goes through it.** Before
155
+ reading a credential, grep the app for the key name. If a resolver already
156
+ exists (`resolveXConfig`, a connector, a client factory), call it — do not
157
+ read `process.env` for that key a second time somewhere else.
158
+ - **Identity comes from the caller, not the module.** A shared helper under
159
+ `server/lib/` takes the email as a parameter; only an entrypoint (action,
160
+ route, cron) decides whose identity it is. A library that resolves its own
161
+ identity from `process.env.AGENT_USER_EMAIL` authorizes the deployment rather
162
+ than the caller.
163
+
164
+ The failure this prevents is not a leak — it is a split brain. When the config
165
+ check reads the vault and the feature reads `process.env`, the settings UI and
166
+ onboarding checklist report the integration as **configured** while every actual
167
+ call fails with "env var is required". The credential is right there in the
168
+ vault, so the error names the wrong cause and sends everyone hunting for a sync
169
+ or redeploy problem that does not exist. This has now shipped four times in one
170
+ app (BigQuery, Jira, Pylon, Academy).
171
+
172
+ Before finishing any change that touches a credential, run the guard from the
173
+ app directory — it finds this whether the app lives in `templates/` or in a
174
+ workspace repo:
175
+
176
+ ```bash
177
+ npx agent-native doctor --only no-env-credentials
178
+ ```
179
+
180
+ Findings in files that already call `resolveCredential` are usually the
181
+ sanctioned `resolveCredential(key, ctx) ?? process.env.KEY` fallback. The bugs
182
+ are the files with **no** resolver at all.
154
183
 
155
184
  ## HTTP routes
156
185