@agent-native/core 0.35.0 → 0.35.3

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 (104) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/context-xray-local.d.ts +2 -2
  3. package/dist/cli/context-xray-local.d.ts.map +1 -1
  4. package/dist/cli/context-xray-local.js +1449 -53
  5. package/dist/cli/context-xray-local.js.map +1 -1
  6. package/dist/cli/create.d.ts.map +1 -1
  7. package/dist/cli/create.js +1 -0
  8. package/dist/cli/create.js.map +1 -1
  9. package/dist/cli/skills.d.ts.map +1 -1
  10. package/dist/cli/skills.js +226 -78
  11. package/dist/cli/skills.js.map +1 -1
  12. package/dist/cli/templates-meta.d.ts.map +1 -1
  13. package/dist/cli/templates-meta.js +8 -4
  14. package/dist/cli/templates-meta.js.map +1 -1
  15. package/dist/client/AgentPanel.d.ts.map +1 -1
  16. package/dist/client/AgentPanel.js +5 -11
  17. package/dist/client/AgentPanel.js.map +1 -1
  18. package/dist/client/AssistantChat.d.ts +6 -0
  19. package/dist/client/AssistantChat.d.ts.map +1 -1
  20. package/dist/client/AssistantChat.js +33 -5
  21. package/dist/client/AssistantChat.js.map +1 -1
  22. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  23. package/dist/client/MultiTabAssistantChat.js +63 -3
  24. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  25. package/dist/client/agent-chat.d.ts +39 -3
  26. package/dist/client/agent-chat.d.ts.map +1 -1
  27. package/dist/client/agent-chat.js +168 -33
  28. package/dist/client/agent-chat.js.map +1 -1
  29. package/dist/client/application-state.d.ts +13 -0
  30. package/dist/client/application-state.d.ts.map +1 -0
  31. package/dist/client/application-state.js +99 -0
  32. package/dist/client/application-state.js.map +1 -0
  33. package/dist/client/frame-protocol.d.ts +11 -3
  34. package/dist/client/frame-protocol.d.ts.map +1 -1
  35. package/dist/client/frame-protocol.js.map +1 -1
  36. package/dist/client/index.d.ts +4 -2
  37. package/dist/client/index.d.ts.map +1 -1
  38. package/dist/client/index.js +4 -2
  39. package/dist/client/index.js.map +1 -1
  40. package/dist/client/progress/RunsTray.d.ts +1 -0
  41. package/dist/client/progress/RunsTray.d.ts.map +1 -1
  42. package/dist/client/progress/RunsTray.js +50 -16
  43. package/dist/client/progress/RunsTray.js.map +1 -1
  44. package/dist/client/use-action.d.ts +12 -0
  45. package/dist/client/use-action.d.ts.map +1 -1
  46. package/dist/client/use-action.js +14 -2
  47. package/dist/client/use-action.js.map +1 -1
  48. package/dist/client/use-agent-chat-context.d.ts +15 -0
  49. package/dist/client/use-agent-chat-context.d.ts.map +1 -0
  50. package/dist/client/use-agent-chat-context.js +32 -0
  51. package/dist/client/use-agent-chat-context.js.map +1 -0
  52. package/dist/deploy/build.d.ts.map +1 -1
  53. package/dist/deploy/build.js +1 -2
  54. package/dist/deploy/build.js.map +1 -1
  55. package/dist/index.browser.d.ts +1 -1
  56. package/dist/index.browser.d.ts.map +1 -1
  57. package/dist/index.browser.js +1 -1
  58. package/dist/index.browser.js.map +1 -1
  59. package/dist/index.d.ts +1 -1
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +1 -1
  62. package/dist/index.js.map +1 -1
  63. package/dist/mcp/server.d.ts +4 -2
  64. package/dist/mcp/server.d.ts.map +1 -1
  65. package/dist/mcp/server.js +33 -4
  66. package/dist/mcp/server.js.map +1 -1
  67. package/dist/provider-api/index.d.ts.map +1 -1
  68. package/dist/provider-api/index.js +14 -6
  69. package/dist/provider-api/index.js.map +1 -1
  70. package/dist/server/agent-teams.d.ts +4 -1
  71. package/dist/server/agent-teams.d.ts.map +1 -1
  72. package/dist/server/agent-teams.js +104 -28
  73. package/dist/server/agent-teams.js.map +1 -1
  74. package/dist/server/auth.d.ts.map +1 -1
  75. package/dist/server/auth.js +21 -11
  76. package/dist/server/auth.js.map +1 -1
  77. package/dist/server/request-context.d.ts +3 -4
  78. package/dist/server/request-context.d.ts.map +1 -1
  79. package/dist/server/request-context.js.map +1 -1
  80. package/dist/server/self-dispatch.d.ts.map +1 -1
  81. package/dist/server/self-dispatch.js +17 -1
  82. package/dist/server/self-dispatch.js.map +1 -1
  83. package/dist/server/ssr-handler.d.ts.map +1 -1
  84. package/dist/server/ssr-handler.js +9 -18
  85. package/dist/server/ssr-handler.js.map +1 -1
  86. package/dist/templates/default/AGENTS.md +1 -1
  87. package/dist/templates/default/DEVELOPING.md +7 -13
  88. package/dist/templates/default/package.json +3 -3
  89. package/dist/templates/workspace-core/AGENTS.md +6 -4
  90. package/dist/templates/workspace-root/AGENTS.md +6 -4
  91. package/docs/content/actions.md +5 -7
  92. package/docs/content/client.md +49 -44
  93. package/docs/content/context-awareness.md +20 -33
  94. package/docs/content/creating-templates.md +2 -2
  95. package/docs/content/key-concepts.md +3 -3
  96. package/docs/content/sharing.md +1 -1
  97. package/docs/content/template-mail.md +1 -1
  98. package/docs/content/voice-input.md +1 -1
  99. package/package.json +11 -7
  100. package/src/templates/default/AGENTS.md +1 -1
  101. package/src/templates/default/DEVELOPING.md +7 -13
  102. package/src/templates/default/package.json +3 -3
  103. package/src/templates/workspace-core/AGENTS.md +6 -4
  104. package/src/templates/workspace-root/AGENTS.md +6 -4
@@ -50,10 +50,9 @@ export interface RequestContext {
50
50
  orgId?: string;
51
51
  timezone?: string;
52
52
  /**
53
- * Set when SSR code reads authenticated request context. The SSR cache layer
54
- * uses this as a last-resort leak guard: public shell/data should not read
55
- * user/org state during render, but older templates still do. Routes that
56
- * need CDN caching should move those reads behind client-side actions/API.
53
+ * Set when code reads authenticated request context. Public SSR shell/data
54
+ * should not depend on this value; user/org-specific reads belong behind
55
+ * client-side actions/API after hydration.
57
56
  */
58
57
  authContextAccessed?: boolean;
59
58
  /**
@@ -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 */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\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 /** 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}\n\nexport interface RequestContext {\n userEmail?: string;\n userName?: string;\n orgId?: string;\n timezone?: string;\n /**\n * Set when SSR code reads authenticated request context. The SSR cache layer\n * uses this as a last-resort leak guard: public shell/data should not read\n * user/org state during render, but older templates still do. Routes that\n * need CDN caching should move those reads behind client-side actions/API.\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 };\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;\ntype RequestContextObserver = (ctx: RequestContext) => void;\ntype GlobalWithRequestContext = typeof globalThis & {\n [GLOBAL_KEY]?: AsyncLocalStorage<RequestContext>;\n [OBSERVERS_KEY]?: RequestContextObserver[];\n};\nconst globalRef = globalThis as GlobalWithRequestContext;\nif (!globalRef[GLOBAL_KEY]) {\n globalRef[GLOBAL_KEY] = new AsyncLocalStorage<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 * 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`.\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 return process.env.AGENT_USER_EMAIL;\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 process.env.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 process.env.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 process.env.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 */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\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 /** 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}\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 };\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;\ntype RequestContextObserver = (ctx: RequestContext) => void;\ntype GlobalWithRequestContext = typeof globalThis & {\n [GLOBAL_KEY]?: AsyncLocalStorage<RequestContext>;\n [OBSERVERS_KEY]?: RequestContextObserver[];\n};\nconst globalRef = globalThis as GlobalWithRequestContext;\nif (!globalRef[GLOBAL_KEY]) {\n globalRef[GLOBAL_KEY] = new AsyncLocalStorage<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 * 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`.\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 return process.env.AGENT_USER_EMAIL;\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 process.env.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 process.env.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 process.env.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 +1 @@
1
- {"version":3,"file":"self-dispatch.d.ts","sourceRoot":"","sources":["../../src/server/self-dispatch.ts"],"names":[],"mappings":"AA0BA;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAgB9C;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,CAAC,EAAE,GAAG,GAAG,MAAM,CAoB9D;AAED,MAAM,WAAW,2BAA2B;IAC1C,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAgCf"}
1
+ {"version":3,"file":"self-dispatch.d.ts","sourceRoot":"","sources":["../../src/server/self-dispatch.ts"],"names":[],"mappings":"AA0BA;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAgB9C;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,CAAC,EAAE,GAAG,GAAG,MAAM,CAoB9D;AAED,MAAM,WAAW,2BAA2B;IAC1C,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAkBD;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAqCf"}
@@ -71,6 +71,17 @@ export function resolveSelfDispatchBaseUrl(event) {
71
71
  const host = readHeader(event, "host") || `localhost:${process.env.PORT || 3000}`;
72
72
  return withConfiguredAppBasePath(`${proto}://${host}`);
73
73
  }
74
+ async function dispatchResponseError(path, res) {
75
+ let body = "";
76
+ try {
77
+ body = (await res.text()).trim();
78
+ }
79
+ catch {
80
+ body = "";
81
+ }
82
+ const detail = body ? `: ${body.slice(0, 300)}` : "";
83
+ return new Error(`Self-dispatch to ${path} returned HTTP ${res.status} ${res.statusText}${detail}`);
84
+ }
74
85
  /**
75
86
  * Fire a fresh, HMAC-signed POST to a processor route on this same deployment.
76
87
  * Fire-and-forget: the dispatch is NOT awaited to completion (the processed run
@@ -101,7 +112,12 @@ export async function fireInternalDispatch(options) {
101
112
  method: "POST",
102
113
  headers,
103
114
  body: JSON.stringify({ taskId: options.taskId, ...(options.body ?? {}) }),
104
- }).catch((err) => {
115
+ }).then(async (res) => {
116
+ if (!res.ok) {
117
+ throw await dispatchResponseError(options.path, res);
118
+ }
119
+ });
120
+ dispatchPromise.catch((err) => {
105
121
  console.error(`[self-dispatch] dispatch to ${options.path} failed:`, err);
106
122
  });
107
123
  const settleMs = options.settleMs ?? DEFAULT_DISPATCH_SETTLE_MS;
@@ -1 +1 @@
1
- {"version":3,"file":"self-dispatch.js","sourceRoot":"","sources":["../../src/server/self-dispatch.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared self-dispatch helper for the framework's serverless background-work\n * pattern: enqueue a unit of work to SQL, then fire a fresh HTTP POST back to\n * this same deployment so the work runs in its own function invocation (with\n * its own full timeout budget) instead of riding on the request that created\n * it.\n *\n * This is the single mechanism that makes background work portable across every\n * host Nitro deploys to:\n * - Netlify Lambda / Vercel Functions / AWS Lambda — the dispatched request\n * hits a fresh function with its own budget; no `waitUntil` needed.\n * - Cloudflare Workers — same (and `waitUntil` still works as a belt-and-\n * suspenders fallback where the in-process path is used).\n * - Self-hosted / long-lived Node — the dispatch comes back as another\n * request to the same process; each handler still runs to completion.\n *\n * Originally inlined in both `a2a/handlers.ts` (`resolveSelfBaseUrl` +\n * `fireProcessTaskDispatch`) and `integrations/webhook-handler.ts`\n * (`resolveBaseUrl` + the dispatch in `enqueueAndDispatch`). Extracted here so\n * A2A, integration webhooks, and Agent Teams sub-agents share one tested\n * implementation.\n */\nimport { withConfiguredAppBasePath } from \"./app-base-path.js\";\nimport { isLocalDatabase } from \"../db/client.js\";\nimport { signInternalToken } from \"../integrations/internal-token.js\";\n\n/**\n * On serverless, returning from the dispatching handler before the outbound\n * TCP handshake starts can freeze the function with the dispatch request stuck\n * in the queue. Racing the fetch against a short timer gives the request a\n * chance to leave the box at the cost of a little added latency on the\n * dispatching call. Mirrors the 250ms used by the A2A/webhook paths.\n */\nexport const DEFAULT_DISPATCH_SETTLE_MS = 250;\n\nfunction readHeader(event: any, name: string): string | undefined {\n try {\n const headers = event?.node?.req?.headers ?? event?.headers;\n if (!headers) return undefined;\n if (typeof headers.get === \"function\") {\n return headers.get(name) ?? undefined;\n }\n const map = headers as Record<string, string | undefined>;\n return map[name] ?? map[String(name).toLowerCase()];\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolve the base URL to fire a self-dispatch request at. Prefers explicit env\n * vars (most reliable on serverless, where inbound host headers can be the\n * platform's internal hostname), falling back to the inbound request headers\n * and finally localhost in dev.\n *\n * Throws in production / shared deployments when no env var is set — a silent\n * fallback to a bad host there would drop background work invisibly.\n */\nexport function resolveSelfDispatchBaseUrl(event?: any): string {\n const fromEnv =\n process.env.APP_URL ||\n process.env.URL ||\n process.env.DEPLOY_URL ||\n process.env.BETTER_AUTH_URL;\n if (fromEnv) return withConfiguredAppBasePath(String(fromEnv));\n\n if (process.env.NODE_ENV === \"production\" || !isLocalDatabase()) {\n throw new Error(\n \"Self-dispatch requires APP_URL, URL, DEPLOY_URL, or BETTER_AUTH_URL in \" +\n \"production/shared deployments so background work can reach this \" +\n \"deployment's own URL.\",\n );\n }\n\n const proto = readHeader(event, \"x-forwarded-proto\") || \"http\";\n const host =\n readHeader(event, \"host\") || `localhost:${process.env.PORT || 3000}`;\n return withConfiguredAppBasePath(`${proto}://${host}`);\n}\n\nexport interface FireInternalDispatchOptions {\n /** Base URL of this deployment. Defaults to `resolveSelfDispatchBaseUrl(event)`. */\n baseUrl?: string;\n /** Request event used to derive the base URL when `baseUrl` is omitted. */\n event?: any;\n /** Framework route path to POST to (e.g. \"/_agent-native/agent-teams/_process-run\"). */\n path: string;\n /** Task/run id the processor will claim. Used to sign the HMAC token and as the default body. */\n taskId: string;\n /** Extra fields merged into the JSON body alongside `{ taskId }`. */\n body?: Record<string, unknown>;\n /** Max ms to wait for the outbound request to leave the box. Default 250ms. */\n settleMs?: number;\n}\n\n/**\n * Fire a fresh, HMAC-signed POST to a processor route on this same deployment.\n * Fire-and-forget: the dispatch is NOT awaited to completion (the processed run\n * may take minutes); it is only raced against a short settle timer so the\n * request reliably leaves a serverless box before it freezes.\n *\n * When `A2A_SECRET` is unset (local dev), the request is sent unsigned — the\n * processor accepts unsigned dispatches in dev and relies on the SQL atomic\n * claim for double-processing protection, mirroring the A2A/webhook flow.\n */\nexport async function fireInternalDispatch(\n options: FireInternalDispatchOptions,\n): Promise<void> {\n const baseUrl = options.baseUrl ?? resolveSelfDispatchBaseUrl(options.event);\n const url = `${baseUrl}${options.path}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n try {\n headers[\"Authorization\"] = `Bearer ${signInternalToken(options.taskId)}`;\n } catch (err) {\n // Distinguish the documented \"no A2A_SECRET in dev\" path from a real\n // signing failure, so a malformed secret doesn't fail invisibly.\n if (err instanceof Error && !/A2A_SECRET/i.test(err.message)) {\n console.error(\n `[self-dispatch] signInternalToken failed unexpectedly for ${options.taskId}:`,\n err,\n );\n }\n }\n\n const dispatchPromise = fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ taskId: options.taskId, ...(options.body ?? {}) }),\n }).catch((err) => {\n console.error(`[self-dispatch] dispatch to ${options.path} failed:`, err);\n });\n\n const settleMs = options.settleMs ?? DEFAULT_DISPATCH_SETTLE_MS;\n await Promise.race([\n dispatchPromise,\n new Promise<void>((resolve) => setTimeout(resolve, settleMs)),\n ]);\n}\n"]}
1
+ {"version":3,"file":"self-dispatch.js","sourceRoot":"","sources":["../../src/server/self-dispatch.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared self-dispatch helper for the framework's serverless background-work\n * pattern: enqueue a unit of work to SQL, then fire a fresh HTTP POST back to\n * this same deployment so the work runs in its own function invocation (with\n * its own full timeout budget) instead of riding on the request that created\n * it.\n *\n * This is the single mechanism that makes background work portable across every\n * host Nitro deploys to:\n * - Netlify Lambda / Vercel Functions / AWS Lambda — the dispatched request\n * hits a fresh function with its own budget; no `waitUntil` needed.\n * - Cloudflare Workers — same (and `waitUntil` still works as a belt-and-\n * suspenders fallback where the in-process path is used).\n * - Self-hosted / long-lived Node — the dispatch comes back as another\n * request to the same process; each handler still runs to completion.\n *\n * Originally inlined in both `a2a/handlers.ts` (`resolveSelfBaseUrl` +\n * `fireProcessTaskDispatch`) and `integrations/webhook-handler.ts`\n * (`resolveBaseUrl` + the dispatch in `enqueueAndDispatch`). Extracted here so\n * A2A, integration webhooks, and Agent Teams sub-agents share one tested\n * implementation.\n */\nimport { withConfiguredAppBasePath } from \"./app-base-path.js\";\nimport { isLocalDatabase } from \"../db/client.js\";\nimport { signInternalToken } from \"../integrations/internal-token.js\";\n\n/**\n * On serverless, returning from the dispatching handler before the outbound\n * TCP handshake starts can freeze the function with the dispatch request stuck\n * in the queue. Racing the fetch against a short timer gives the request a\n * chance to leave the box at the cost of a little added latency on the\n * dispatching call. Mirrors the 250ms used by the A2A/webhook paths.\n */\nexport const DEFAULT_DISPATCH_SETTLE_MS = 250;\n\nfunction readHeader(event: any, name: string): string | undefined {\n try {\n const headers = event?.node?.req?.headers ?? event?.headers;\n if (!headers) return undefined;\n if (typeof headers.get === \"function\") {\n return headers.get(name) ?? undefined;\n }\n const map = headers as Record<string, string | undefined>;\n return map[name] ?? map[String(name).toLowerCase()];\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolve the base URL to fire a self-dispatch request at. Prefers explicit env\n * vars (most reliable on serverless, where inbound host headers can be the\n * platform's internal hostname), falling back to the inbound request headers\n * and finally localhost in dev.\n *\n * Throws in production / shared deployments when no env var is set — a silent\n * fallback to a bad host there would drop background work invisibly.\n */\nexport function resolveSelfDispatchBaseUrl(event?: any): string {\n const fromEnv =\n process.env.APP_URL ||\n process.env.URL ||\n process.env.DEPLOY_URL ||\n process.env.BETTER_AUTH_URL;\n if (fromEnv) return withConfiguredAppBasePath(String(fromEnv));\n\n if (process.env.NODE_ENV === \"production\" || !isLocalDatabase()) {\n throw new Error(\n \"Self-dispatch requires APP_URL, URL, DEPLOY_URL, or BETTER_AUTH_URL in \" +\n \"production/shared deployments so background work can reach this \" +\n \"deployment's own URL.\",\n );\n }\n\n const proto = readHeader(event, \"x-forwarded-proto\") || \"http\";\n const host =\n readHeader(event, \"host\") || `localhost:${process.env.PORT || 3000}`;\n return withConfiguredAppBasePath(`${proto}://${host}`);\n}\n\nexport interface FireInternalDispatchOptions {\n /** Base URL of this deployment. Defaults to `resolveSelfDispatchBaseUrl(event)`. */\n baseUrl?: string;\n /** Request event used to derive the base URL when `baseUrl` is omitted. */\n event?: any;\n /** Framework route path to POST to (e.g. \"/_agent-native/agent-teams/_process-run\"). */\n path: string;\n /** Task/run id the processor will claim. Used to sign the HMAC token and as the default body. */\n taskId: string;\n /** Extra fields merged into the JSON body alongside `{ taskId }`. */\n body?: Record<string, unknown>;\n /** Max ms to wait for the outbound request to leave the box. Default 250ms. */\n settleMs?: number;\n}\n\nasync function dispatchResponseError(\n path: string,\n res: Response,\n): Promise<Error> {\n let body = \"\";\n try {\n body = (await res.text()).trim();\n } catch {\n body = \"\";\n }\n const detail = body ? `: ${body.slice(0, 300)}` : \"\";\n return new Error(\n `Self-dispatch to ${path} returned HTTP ${res.status} ${res.statusText}${detail}`,\n );\n}\n\n/**\n * Fire a fresh, HMAC-signed POST to a processor route on this same deployment.\n * Fire-and-forget: the dispatch is NOT awaited to completion (the processed run\n * may take minutes); it is only raced against a short settle timer so the\n * request reliably leaves a serverless box before it freezes.\n *\n * When `A2A_SECRET` is unset (local dev), the request is sent unsigned — the\n * processor accepts unsigned dispatches in dev and relies on the SQL atomic\n * claim for double-processing protection, mirroring the A2A/webhook flow.\n */\nexport async function fireInternalDispatch(\n options: FireInternalDispatchOptions,\n): Promise<void> {\n const baseUrl = options.baseUrl ?? resolveSelfDispatchBaseUrl(options.event);\n const url = `${baseUrl}${options.path}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n try {\n headers[\"Authorization\"] = `Bearer ${signInternalToken(options.taskId)}`;\n } catch (err) {\n // Distinguish the documented \"no A2A_SECRET in dev\" path from a real\n // signing failure, so a malformed secret doesn't fail invisibly.\n if (err instanceof Error && !/A2A_SECRET/i.test(err.message)) {\n console.error(\n `[self-dispatch] signInternalToken failed unexpectedly for ${options.taskId}:`,\n err,\n );\n }\n }\n\n const dispatchPromise = fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ taskId: options.taskId, ...(options.body ?? {}) }),\n }).then(async (res) => {\n if (!res.ok) {\n throw await dispatchResponseError(options.path, res);\n }\n });\n dispatchPromise.catch((err) => {\n console.error(`[self-dispatch] dispatch to ${options.path} failed:`, err);\n });\n\n const settleMs = options.settleMs ?? DEFAULT_DISPATCH_SETTLE_MS;\n await Promise.race([\n dispatchPromise,\n new Promise<void>((resolve) => setTimeout(resolve, settleMs)),\n ]);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-handler.d.ts","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"AA4CA,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;AAyWpC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,2FAyE5E"}
1
+ {"version":3,"file":"ssr-handler.d.ts","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"AAwCA,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;AAiVpC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,2FAuE5E"}
@@ -19,7 +19,7 @@ import { createRequestHandler } from "react-router";
19
19
  import { defineEventHandler } from "h3";
20
20
  import { getSentryClientConfigScript } from "./sentry-config.js";
21
21
  import { BETTER_AUTH_COOKIE_PREFIX, COOKIE_NAME, getSession } from "./auth.js";
22
- import { hasAuthContextAccess, runWithRequestContext, } from "./request-context.js";
22
+ import { runWithRequestContext } from "./request-context.js";
23
23
  import { requestHasEmbedAuthMarker } from "./embed-session.js";
24
24
  import { EMBED_SESSION_COOKIE, EMBED_TOKEN_QUERY_PARAM, } from "../shared/embed-auth.js";
25
25
  import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, } from "../shared/social-meta.js";
@@ -190,17 +190,9 @@ function isAuthenticatedCookieName(name) {
190
190
  bareName === `${BETTER_AUTH_COOKIE_PREFIX}.session_data` ||
191
191
  BETTER_AUTH_SESSION_COOKIE_RE.test(bareName));
192
192
  }
193
- function shouldUseDefaultSsrCacheHeader(headers, status, pathname, authContextAccessed) {
193
+ function shouldUseDefaultSsrCacheHeader(headers, status, pathname) {
194
194
  if (status < 200 || status >= 400)
195
195
  return false;
196
- if (authContextAccessed) {
197
- // Do not bypass cache just because a browser carries an auth-looking
198
- // cookie: public docs/pages can receive stale workspace cookies and should
199
- // still warm the CDN. But if SSR code actually reads user/org context,
200
- // that route is rendering private data and must not be public-cached.
201
- // Move those reads to client-side actions/API to regain CDN caching.
202
- return false;
203
- }
204
196
  const contentType = headers.get("content-type")?.toLowerCase() ?? "";
205
197
  if (contentType.includes("text/html")) {
206
198
  // SSR HTML is public app shell in this framework; any per-user state is
@@ -219,15 +211,14 @@ function shouldUseDefaultSsrCacheHeader(headers, status, pathname, authContextAc
219
211
  // routes. Keep `.data` on the same short-fresh/long-SWR policy as HTML so
220
212
  // route data fetches warm the CDN instead of hammering origin.
221
213
  // Do not re-add a blanket cookie/auth-signal bypass here: logged-in browsers
222
- // still need CDN-cached public route data. The auth-context leak guard above
223
- // is the narrow protection for old SSR loaders that still read user/org data.
214
+ // still need CDN-cached public route data.
224
215
  // Also do not preserve route-level private/no-store for React Router .data:
225
216
  // if a route needs per-user data, it belongs behind a client-side action/API
226
217
  // call rather than in the shared SSR payload.
227
218
  return true;
228
219
  }
229
- function applyDefaultSsrCacheHeader(headers, status, pathname, authContextAccessed) {
230
- if (!shouldUseDefaultSsrCacheHeader(headers, status, pathname, authContextAccessed)) {
220
+ function applyDefaultSsrCacheHeader(headers, status, pathname) {
221
+ if (!shouldUseDefaultSsrCacheHeader(headers, status, pathname)) {
231
222
  return;
232
223
  }
233
224
  // Netlify Functions/proxies are not cached by default, and production docs
@@ -272,10 +263,10 @@ function isFrameworkOrAssetPath(pathname) {
272
263
  pathname === "/favicon.png" ||
273
264
  (/\.\w+$/.test(pathname) && !pathname.endsWith(".data")));
274
265
  }
275
- async function rewriteMountedResponse(response, basePath, pathname, requestUrl, requestContext) {
266
+ async function rewriteMountedResponse(response, basePath, pathname, requestUrl) {
276
267
  const sentryClientConfigScript = getSentryClientConfigScript();
277
268
  const headers = new Headers(response.headers);
278
- applyDefaultSsrCacheHeader(headers, response.status, pathname, hasAuthContextAccess(requestContext));
269
+ applyDefaultSsrCacheHeader(headers, response.status, pathname);
279
270
  applyDefaultSpeculationRulesHeader(headers, response.status, basePath);
280
271
  const location = headers.get("location");
281
272
  if (location?.startsWith("/") && !location.startsWith("//")) {
@@ -342,9 +333,9 @@ export function createH3SSRHandler(getBuild) {
342
333
  status: response.status,
343
334
  statusText: response.statusText,
344
335
  headers: response.headers,
345
- }), basePath, p, request.url, ctx);
336
+ }), basePath, p, request.url);
346
337
  }
347
- return await rewriteMountedResponse(await runWithRequestContext(ctx, () => handler(request)), basePath, p, request.url, ctx);
338
+ return await rewriteMountedResponse(await runWithRequestContext(ctx, () => handler(request)), basePath, p, request.url);
348
339
  }
349
340
  catch (err) {
350
341
  // Log the full stack server-side, but never leak it to the client.
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-handler.js","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared SSR catch-all handler for React Router framework mode.\n *\n * Templates wire this up via:\n *\n * // server/routes/[...page].get.ts\n * import { createH3SSRHandler } from \"@agent-native/core/server/ssr-handler\";\n * export default createH3SSRHandler(\n * () => import(\"virtual:react-router/server-build\"),\n * );\n *\n * The `getBuild` callback MUST live in the template's own source so Vite's\n * @react-router/dev plugin can resolve the `virtual:` module. Pulling the\n * import into core (e.g. via a re-export) puts it in node_modules where\n * Vite's SSR externalizer leaves it untouched and Node's ESM loader rejects\n * the unknown scheme — silently 302'ing every request to \"/\".\n */\nimport { createRequestHandler } from \"react-router\";\nimport { defineEventHandler, type H3Event } from \"h3\";\nimport { getSentryClientConfigScript } from \"./sentry-config.js\";\nimport { BETTER_AUTH_COOKIE_PREFIX, COOKIE_NAME, getSession } from \"./auth.js\";\nimport {\n hasAuthContextAccess,\n runWithRequestContext,\n type RequestContext,\n} from \"./request-context.js\";\nimport { requestHasEmbedAuthMarker } from \"./embed-session.js\";\nimport {\n EMBED_SESSION_COOKIE,\n EMBED_TOKEN_QUERY_PARAM,\n} from \"../shared/embed-auth.js\";\nimport {\n AGENT_NATIVE_SOCIAL_IMAGE_ALT,\n AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,\n AGENT_NATIVE_SOCIAL_IMAGE_PATH,\n AGENT_NATIVE_SOCIAL_IMAGE_TYPE,\n AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,\n} from \"../shared/social-meta.js\";\nimport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_PATH,\n DEFAULT_SSR_CACHE_CONTROL,\n} from \"../shared/cache-control.js\";\n\nexport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_HEADER,\n DEFAULT_SSR_CACHE_CONTROL,\n} from \"../shared/cache-control.js\";\nconst ANONYMOUS_SESSION_COOKIE_NAMES = new Set([\"an_docs_session\"]);\nconst BETTER_AUTH_SESSION_COOKIE_RE = /\\.session_(?:token|data)$/;\n\n/**\n * Read the active org for a request without forcing every template to bundle\n * the org module. Mirrors what `core-routes-plugin` does for action handlers.\n */\nasync function readOrgIdForEvent(event: H3Event): Promise<string | undefined> {\n try {\n const { getOrgContext } = await import(\"../org/context.js\");\n const ctx = await getOrgContext(event);\n return ctx?.orgId ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeAppBasePath(value: string | undefined): string {\n if (!value || value === \"/\") return \"\";\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n return `/${trimmed.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")}`;\n}\n\nfunction getAppBasePath(): string {\n const metaEnv = (\n import.meta as unknown as {\n env?: Record<string, string | undefined>;\n }\n ).env;\n return normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH ||\n process.env.APP_BASE_PATH ||\n metaEnv?.VITE_APP_BASE_PATH ||\n metaEnv?.APP_BASE_PATH ||\n metaEnv?.BASE_URL,\n );\n}\n\nfunction stripAppBasePath(pathname: string): string {\n const basePath = getAppBasePath();\n return stripBasePath(pathname, basePath);\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string {\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction requestWithPathname(\n request: Request,\n pathname: string,\n basePath: string,\n): Request {\n const url = new URL(request.url);\n let changed = false;\n if (basePath && pathname === \"/__manifest\") {\n const paths = url.searchParams.get(\"paths\");\n if (paths) {\n const strippedPaths = paths\n .split(\",\")\n .map((path) => stripBasePath(path, basePath))\n .join(\",\");\n if (strippedPaths !== paths) {\n url.searchParams.set(\"paths\", strippedPaths);\n changed = true;\n }\n }\n }\n if (url.pathname !== pathname) {\n url.pathname = pathname;\n changed = true;\n }\n if (!changed) return request;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(url, init);\n}\n\nfunction prefixMountedPath(path: string, basePath: string): string {\n if (!basePath || !path.startsWith(\"/\") || path.startsWith(\"//\")) return path;\n if (path === basePath || path.startsWith(`${basePath}/`)) return path;\n return `${basePath}${path}`;\n}\n\nfunction prefixMountedHtml(html: string, basePath: string): string {\n if (!basePath) return html;\n return html\n .replace(\n /\\b(href|src|action|formaction|poster)=([\"'])(\\/(?!\\/)[^\"']*)\\2/g,\n (_match, attr: string, quote: string, path: string) =>\n `${attr}=${quote}${prefixMountedPath(path, basePath)}${quote}`,\n )\n .replace(/url\\(([\"']?)(\\/(?!\\/)[^)'\" ]+)\\1\\)/g, (_match, quote, path) => {\n const q = quote || \"\";\n return `url(${q}${prefixMountedPath(path, basePath)}${q})`;\n });\n}\n\nfunction injectHeadScript(html: string, script: string | null): string {\n if (!script) return html;\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);\n}\n\nconst OG_IMAGE_META_RE = /<meta\\b(?=[^>]*\\bproperty=([\"'])og:image\\1)[^>]*>/i;\nconst TWITTER_CARD_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:card\\1)[^>]*>/i;\nconst TWITTER_IMAGE_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:image\\1)[^>]*>/i;\n\nfunction defaultSocialImageUrl(requestUrl: string, basePath: string): string {\n return new URL(\n prefixMountedPath(AGENT_NATIVE_SOCIAL_IMAGE_PATH, basePath),\n requestUrl,\n ).toString();\n}\n\nfunction injectDefaultSocialImageMeta(html: string, imageUrl: string): string {\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n\n const hasAnySocialImage =\n OG_IMAGE_META_RE.test(html) || TWITTER_IMAGE_META_RE.test(html);\n const tags: string[] = [];\n\n if (!hasAnySocialImage) {\n tags.push(`<meta property=\"og:image\" content=\"${imageUrl}\">`);\n tags.push(`<meta property=\"og:image:secure_url\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta property=\"og:image:type\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_TYPE}\">`,\n );\n tags.push(\n `<meta property=\"og:image:width\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_WIDTH}\">`,\n );\n tags.push(\n `<meta property=\"og:image:height\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT}\">`,\n );\n tags.push(\n `<meta property=\"og:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n if (!TWITTER_CARD_META_RE.test(html)) {\n tags.push(`<meta name=\"twitter:card\" content=\"summary_large_image\">`);\n }\n if (!hasAnySocialImage) {\n tags.push(`<meta name=\"twitter:image\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta name=\"twitter:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n\n if (tags.length === 0) return html;\n return html.slice(0, headCloseIdx) + tags.join(\"\") + html.slice(headCloseIdx);\n}\n\nfunction requestHasAuthSignal(event: H3Event): boolean {\n const headers = event.req.headers;\n return Boolean(\n headers.get(\"authorization\") ||\n requestHasAuthenticatedCookie(headers.get(\"cookie\")) ||\n event.url.searchParams.has(EMBED_TOKEN_QUERY_PARAM) ||\n event.url.searchParams.has(\"_session\") ||\n requestHasEmbedAuthMarker(event),\n );\n}\n\nfunction requestHasAuthenticatedCookie(cookieHeader: string | null): boolean {\n if (!cookieHeader) return false;\n return cookieHeader\n .split(\";\")\n .map((cookie) => cookie.trim().split(\"=\", 1)[0]?.trim())\n .filter((name): name is string => Boolean(name))\n .some(isAuthenticatedCookieName);\n}\n\nfunction isAuthenticatedCookieName(name: string): boolean {\n if (ANONYMOUS_SESSION_COOKIE_NAMES.has(name)) return false;\n const bareName = name.replace(/^__(?:Secure|Host)-/, \"\");\n return (\n bareName === COOKIE_NAME ||\n bareName === EMBED_SESSION_COOKIE ||\n bareName === \"an_session\" ||\n bareName === \"an_session_workspace\" ||\n bareName.startsWith(\"an_session_\") ||\n bareName === `${BETTER_AUTH_COOKIE_PREFIX}.session_token` ||\n bareName === `${BETTER_AUTH_COOKIE_PREFIX}.session_data` ||\n BETTER_AUTH_SESSION_COOKIE_RE.test(bareName)\n );\n}\n\nfunction shouldUseDefaultSsrCacheHeader(\n headers: Headers,\n status: number,\n pathname: string,\n authContextAccessed: boolean,\n): boolean {\n if (status < 200 || status >= 400) return false;\n if (authContextAccessed) {\n // Do not bypass cache just because a browser carries an auth-looking\n // cookie: public docs/pages can receive stale workspace cookies and should\n // still warm the CDN. But if SSR code actually reads user/org context,\n // that route is rendering private data and must not be public-cached.\n // Move those reads to client-side actions/API to regain CDN caching.\n return false;\n }\n\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (contentType.includes(\"text/html\")) {\n // SSR HTML is public app shell in this framework; any per-user state is\n // fetched after hydration. Always enforce the framework SWR default here;\n // route-level no-cache/private headers on SSR HTML recreate the same\n // origin stampede this cache policy is meant to prevent.\n return true;\n }\n\n if (!pathname.endsWith(\".data\")) return false;\n if (!contentType.includes(\"text/x-script\")) return false;\n\n // React Router gives loader `.data` responses `cache-control: no-cache` by\n // default. In Agent-Native, SSR output is intentionally public app shell:\n // user/org-specific reads happen after hydration through actions and API\n // routes. Keep `.data` on the same short-fresh/long-SWR policy as HTML so\n // route data fetches warm the CDN instead of hammering origin.\n // Do not re-add a blanket cookie/auth-signal bypass here: logged-in browsers\n // still need CDN-cached public route data. The auth-context leak guard above\n // is the narrow protection for old SSR loaders that still read user/org data.\n // Also do not preserve route-level private/no-store for React Router .data:\n // if a route needs per-user data, it belongs behind a client-side action/API\n // call rather than in the shared SSR payload.\n return true;\n}\n\nfunction applyDefaultSsrCacheHeader(\n headers: Headers,\n status: number,\n pathname: string,\n authContextAccessed: boolean,\n) {\n if (\n !shouldUseDefaultSsrCacheHeader(\n headers,\n status,\n pathname,\n authContextAccessed,\n )\n ) {\n return;\n }\n // Netlify Functions/proxies are not cached by default, and production docs\n // requests often carry stale auth/doc cookies. Keep all three cache headers:\n // Cache-Control for browsers, CDN-Cache-Control for generic CDNs, and\n // Netlify-CDN-Cache-Control (with durable) so Netlify's shared cache actually\n // serves SSR HTML/.data instead of forwarding every request to origin.\n for (const [name, value] of Object.entries(DEFAULT_SSR_CACHE_HEADERS)) {\n headers.set(name, value);\n }\n}\n\nfunction applyDefaultSpeculationRulesHeader(\n headers: Headers,\n status: number,\n basePath: string,\n) {\n if (status < 200 || status >= 400) return;\n if (headers.has(\"speculation-rules\")) return;\n\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (!contentType.includes(\"text/html\")) return;\n\n // Cloudflare Speed Brain injects its own Speculation-Rules header when the\n // origin omits one. Those browser prefetches carry `Sec-Purpose: prefetch`,\n // and Cloudflare refuses cache-ineligible dynamic pages with a 503 before\n // the request can reach Netlify/origin. We publish an explicit no-op ruleset\n // by default so Cloudflare does not inject its edge prefetch rules. Preserve\n // an app-provided Speculation-Rules header above if a template deliberately\n // owns this behavior.\n const rulesPath = prefixMountedPath(DEFAULT_SPECULATION_RULES_PATH, basePath);\n headers.set(\"speculation-rules\", `\"${rulesPath}\"`);\n}\n\nfunction isFrameworkOrAssetPath(pathname: string): boolean {\n return (\n pathname.startsWith(\"/.well-known/\") ||\n pathname.startsWith(\"/_agent_native/\") ||\n pathname.startsWith(\"/_agent-native/\") ||\n pathname.startsWith(\"/api/\") ||\n pathname.startsWith(\"/@vite/\") ||\n pathname.startsWith(\"/@id/\") ||\n pathname.startsWith(\"/@fs/\") ||\n pathname === \"/@react-refresh\" ||\n pathname === \"/__vite_ping\" ||\n pathname === \"/__open-in-editor\" ||\n pathname === \"/favicon.ico\" ||\n pathname === \"/favicon.png\" ||\n (/\\.\\w+$/.test(pathname) && !pathname.endsWith(\".data\"))\n );\n}\n\nasync function rewriteMountedResponse(\n response: Response,\n basePath: string,\n pathname: string,\n requestUrl: string,\n requestContext?: RequestContext,\n): Promise<Response> {\n const sentryClientConfigScript = getSentryClientConfigScript();\n const headers = new Headers(response.headers);\n applyDefaultSsrCacheHeader(\n headers,\n response.status,\n pathname,\n hasAuthContextAccess(requestContext),\n );\n applyDefaultSpeculationRulesHeader(headers, response.status, basePath);\n\n const location = headers.get(\"location\");\n if (location?.startsWith(\"/\") && !location.startsWith(\"//\")) {\n headers.set(\"location\", prefixMountedPath(location, basePath));\n }\n\n const contentType = headers.get(\"content-type\") ?? \"\";\n if (!contentType.toLowerCase().includes(\"text/html\") || !response.body) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n const html = await response.text();\n headers.delete(\"content-length\");\n return new Response(\n injectHeadScript(\n injectDefaultSocialImageMeta(\n prefixMountedHtml(html, basePath),\n defaultSocialImageUrl(requestUrl, basePath),\n ),\n sentryClientConfigScript,\n ),\n {\n status: response.status,\n statusText: response.statusText,\n headers,\n },\n );\n}\n\n/**\n * Create an h3 catch-all that hands page routes to React Router and\n * returns 404 for framework / asset paths that React Router doesn't own.\n */\nexport function createH3SSRHandler(getBuild: () => Promise<unknown> | unknown) {\n const handler = createRequestHandler(getBuild as any);\n return defineEventHandler(async (event) => {\n const basePath = getAppBasePath();\n const p = stripAppBasePath(event.url.pathname);\n if (isFrameworkOrAssetPath(p)) {\n return new Response(null, { status: 404 });\n }\n try {\n const request = requestWithPathname(event.req as Request, p, basePath);\n // Pin the active session onto the async request context so React Router\n // loaders that call `getRequestUserEmail()` / `accessFilter()` see the\n // signed-in user. Without this, SSR loaders fall through to the\n // unauthenticated branch even when the user is logged in — which broke\n // shared-deck \"Presentation link\" access for non-public decks.\n let session: Awaited<ReturnType<typeof getSession>> | null = null;\n const hasAuthSignal = requestHasAuthSignal(event);\n if (hasAuthSignal) {\n try {\n session = await getSession(event);\n } catch {\n // Auth lookup failures must not break SSR; treat as unauthenticated.\n }\n }\n const orgId = session?.email ? await readOrgIdForEvent(event) : undefined;\n const ctx = {\n userEmail: session?.email ?? undefined,\n orgId,\n };\n if (request.method === \"HEAD\") {\n const getRequest = new Request(request.url, {\n method: \"GET\",\n headers: request.headers,\n signal: request.signal,\n });\n const response = await runWithRequestContext(ctx, () =>\n handler(getRequest),\n );\n return await rewriteMountedResponse(\n new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n }),\n basePath,\n p,\n request.url,\n ctx,\n );\n }\n return await rewriteMountedResponse(\n await runWithRequestContext(ctx, () => handler(request)),\n basePath,\n p,\n request.url,\n ctx,\n );\n } catch (err) {\n // Log the full stack server-side, but never leak it to the client.\n // Stack traces expose file paths, library versions, and code structure\n // that aid reconnaissance attacks. In dev we surface the message text\n // so devtools shows something useful; in prod we return a bare 500.\n console.error(\"[ssr-handler] SSR error:\", err);\n const isProd = process.env.NODE_ENV === \"production\";\n const body = isProd\n ? \"Internal Server Error\"\n : `Internal Server Error: ${(err as Error)?.message ?? err}`;\n return new Response(body, {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n });\n}\n"]}
1
+ {"version":3,"file":"ssr-handler.js","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared SSR catch-all handler for React Router framework mode.\n *\n * Templates wire this up via:\n *\n * // server/routes/[...page].get.ts\n * import { createH3SSRHandler } from \"@agent-native/core/server/ssr-handler\";\n * export default createH3SSRHandler(\n * () => import(\"virtual:react-router/server-build\"),\n * );\n *\n * The `getBuild` callback MUST live in the template's own source so Vite's\n * @react-router/dev plugin can resolve the `virtual:` module. Pulling the\n * import into core (e.g. via a re-export) puts it in node_modules where\n * Vite's SSR externalizer leaves it untouched and Node's ESM loader rejects\n * the unknown scheme — silently 302'ing every request to \"/\".\n */\nimport { createRequestHandler } from \"react-router\";\nimport { defineEventHandler, type H3Event } from \"h3\";\nimport { getSentryClientConfigScript } from \"./sentry-config.js\";\nimport { BETTER_AUTH_COOKIE_PREFIX, COOKIE_NAME, getSession } from \"./auth.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\nimport { requestHasEmbedAuthMarker } from \"./embed-session.js\";\nimport {\n EMBED_SESSION_COOKIE,\n EMBED_TOKEN_QUERY_PARAM,\n} from \"../shared/embed-auth.js\";\nimport {\n AGENT_NATIVE_SOCIAL_IMAGE_ALT,\n AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,\n AGENT_NATIVE_SOCIAL_IMAGE_PATH,\n AGENT_NATIVE_SOCIAL_IMAGE_TYPE,\n AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,\n} from \"../shared/social-meta.js\";\nimport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_PATH,\n DEFAULT_SSR_CACHE_CONTROL,\n} from \"../shared/cache-control.js\";\n\nexport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_HEADER,\n DEFAULT_SSR_CACHE_CONTROL,\n} from \"../shared/cache-control.js\";\nconst ANONYMOUS_SESSION_COOKIE_NAMES = new Set([\"an_docs_session\"]);\nconst BETTER_AUTH_SESSION_COOKIE_RE = /\\.session_(?:token|data)$/;\n\n/**\n * Read the active org for a request without forcing every template to bundle\n * the org module. Mirrors what `core-routes-plugin` does for action handlers.\n */\nasync function readOrgIdForEvent(event: H3Event): Promise<string | undefined> {\n try {\n const { getOrgContext } = await import(\"../org/context.js\");\n const ctx = await getOrgContext(event);\n return ctx?.orgId ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeAppBasePath(value: string | undefined): string {\n if (!value || value === \"/\") return \"\";\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n return `/${trimmed.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")}`;\n}\n\nfunction getAppBasePath(): string {\n const metaEnv = (\n import.meta as unknown as {\n env?: Record<string, string | undefined>;\n }\n ).env;\n return normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH ||\n process.env.APP_BASE_PATH ||\n metaEnv?.VITE_APP_BASE_PATH ||\n metaEnv?.APP_BASE_PATH ||\n metaEnv?.BASE_URL,\n );\n}\n\nfunction stripAppBasePath(pathname: string): string {\n const basePath = getAppBasePath();\n return stripBasePath(pathname, basePath);\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string {\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction requestWithPathname(\n request: Request,\n pathname: string,\n basePath: string,\n): Request {\n const url = new URL(request.url);\n let changed = false;\n if (basePath && pathname === \"/__manifest\") {\n const paths = url.searchParams.get(\"paths\");\n if (paths) {\n const strippedPaths = paths\n .split(\",\")\n .map((path) => stripBasePath(path, basePath))\n .join(\",\");\n if (strippedPaths !== paths) {\n url.searchParams.set(\"paths\", strippedPaths);\n changed = true;\n }\n }\n }\n if (url.pathname !== pathname) {\n url.pathname = pathname;\n changed = true;\n }\n if (!changed) return request;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(url, init);\n}\n\nfunction prefixMountedPath(path: string, basePath: string): string {\n if (!basePath || !path.startsWith(\"/\") || path.startsWith(\"//\")) return path;\n if (path === basePath || path.startsWith(`${basePath}/`)) return path;\n return `${basePath}${path}`;\n}\n\nfunction prefixMountedHtml(html: string, basePath: string): string {\n if (!basePath) return html;\n return html\n .replace(\n /\\b(href|src|action|formaction|poster)=([\"'])(\\/(?!\\/)[^\"']*)\\2/g,\n (_match, attr: string, quote: string, path: string) =>\n `${attr}=${quote}${prefixMountedPath(path, basePath)}${quote}`,\n )\n .replace(/url\\(([\"']?)(\\/(?!\\/)[^)'\" ]+)\\1\\)/g, (_match, quote, path) => {\n const q = quote || \"\";\n return `url(${q}${prefixMountedPath(path, basePath)}${q})`;\n });\n}\n\nfunction injectHeadScript(html: string, script: string | null): string {\n if (!script) return html;\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);\n}\n\nconst OG_IMAGE_META_RE = /<meta\\b(?=[^>]*\\bproperty=([\"'])og:image\\1)[^>]*>/i;\nconst TWITTER_CARD_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:card\\1)[^>]*>/i;\nconst TWITTER_IMAGE_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:image\\1)[^>]*>/i;\n\nfunction defaultSocialImageUrl(requestUrl: string, basePath: string): string {\n return new URL(\n prefixMountedPath(AGENT_NATIVE_SOCIAL_IMAGE_PATH, basePath),\n requestUrl,\n ).toString();\n}\n\nfunction injectDefaultSocialImageMeta(html: string, imageUrl: string): string {\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n\n const hasAnySocialImage =\n OG_IMAGE_META_RE.test(html) || TWITTER_IMAGE_META_RE.test(html);\n const tags: string[] = [];\n\n if (!hasAnySocialImage) {\n tags.push(`<meta property=\"og:image\" content=\"${imageUrl}\">`);\n tags.push(`<meta property=\"og:image:secure_url\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta property=\"og:image:type\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_TYPE}\">`,\n );\n tags.push(\n `<meta property=\"og:image:width\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_WIDTH}\">`,\n );\n tags.push(\n `<meta property=\"og:image:height\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT}\">`,\n );\n tags.push(\n `<meta property=\"og:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n if (!TWITTER_CARD_META_RE.test(html)) {\n tags.push(`<meta name=\"twitter:card\" content=\"summary_large_image\">`);\n }\n if (!hasAnySocialImage) {\n tags.push(`<meta name=\"twitter:image\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta name=\"twitter:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n\n if (tags.length === 0) return html;\n return html.slice(0, headCloseIdx) + tags.join(\"\") + html.slice(headCloseIdx);\n}\n\nfunction requestHasAuthSignal(event: H3Event): boolean {\n const headers = event.req.headers;\n return Boolean(\n headers.get(\"authorization\") ||\n requestHasAuthenticatedCookie(headers.get(\"cookie\")) ||\n event.url.searchParams.has(EMBED_TOKEN_QUERY_PARAM) ||\n event.url.searchParams.has(\"_session\") ||\n requestHasEmbedAuthMarker(event),\n );\n}\n\nfunction requestHasAuthenticatedCookie(cookieHeader: string | null): boolean {\n if (!cookieHeader) return false;\n return cookieHeader\n .split(\";\")\n .map((cookie) => cookie.trim().split(\"=\", 1)[0]?.trim())\n .filter((name): name is string => Boolean(name))\n .some(isAuthenticatedCookieName);\n}\n\nfunction isAuthenticatedCookieName(name: string): boolean {\n if (ANONYMOUS_SESSION_COOKIE_NAMES.has(name)) return false;\n const bareName = name.replace(/^__(?:Secure|Host)-/, \"\");\n return (\n bareName === COOKIE_NAME ||\n bareName === EMBED_SESSION_COOKIE ||\n bareName === \"an_session\" ||\n bareName === \"an_session_workspace\" ||\n bareName.startsWith(\"an_session_\") ||\n bareName === `${BETTER_AUTH_COOKIE_PREFIX}.session_token` ||\n bareName === `${BETTER_AUTH_COOKIE_PREFIX}.session_data` ||\n BETTER_AUTH_SESSION_COOKIE_RE.test(bareName)\n );\n}\n\nfunction shouldUseDefaultSsrCacheHeader(\n headers: Headers,\n status: number,\n pathname: string,\n): boolean {\n if (status < 200 || status >= 400) return false;\n\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (contentType.includes(\"text/html\")) {\n // SSR HTML is public app shell in this framework; any per-user state is\n // fetched after hydration. Always enforce the framework SWR default here;\n // route-level no-cache/private headers on SSR HTML recreate the same\n // origin stampede this cache policy is meant to prevent.\n return true;\n }\n\n if (!pathname.endsWith(\".data\")) return false;\n if (!contentType.includes(\"text/x-script\")) return false;\n\n // React Router gives loader `.data` responses `cache-control: no-cache` by\n // default. In Agent-Native, SSR output is intentionally public app shell:\n // user/org-specific reads happen after hydration through actions and API\n // routes. Keep `.data` on the same short-fresh/long-SWR policy as HTML so\n // route data fetches warm the CDN instead of hammering origin.\n // Do not re-add a blanket cookie/auth-signal bypass here: logged-in browsers\n // still need CDN-cached public route data.\n // Also do not preserve route-level private/no-store for React Router .data:\n // if a route needs per-user data, it belongs behind a client-side action/API\n // call rather than in the shared SSR payload.\n return true;\n}\n\nfunction applyDefaultSsrCacheHeader(\n headers: Headers,\n status: number,\n pathname: string,\n) {\n if (!shouldUseDefaultSsrCacheHeader(headers, status, pathname)) {\n return;\n }\n // Netlify Functions/proxies are not cached by default, and production docs\n // requests often carry stale auth/doc cookies. Keep all three cache headers:\n // Cache-Control for browsers, CDN-Cache-Control for generic CDNs, and\n // Netlify-CDN-Cache-Control (with durable) so Netlify's shared cache actually\n // serves SSR HTML/.data instead of forwarding every request to origin.\n for (const [name, value] of Object.entries(DEFAULT_SSR_CACHE_HEADERS)) {\n headers.set(name, value);\n }\n}\n\nfunction applyDefaultSpeculationRulesHeader(\n headers: Headers,\n status: number,\n basePath: string,\n) {\n if (status < 200 || status >= 400) return;\n if (headers.has(\"speculation-rules\")) return;\n\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (!contentType.includes(\"text/html\")) return;\n\n // Cloudflare Speed Brain injects its own Speculation-Rules header when the\n // origin omits one. Those browser prefetches carry `Sec-Purpose: prefetch`,\n // and Cloudflare refuses cache-ineligible dynamic pages with a 503 before\n // the request can reach Netlify/origin. We publish an explicit no-op ruleset\n // by default so Cloudflare does not inject its edge prefetch rules. Preserve\n // an app-provided Speculation-Rules header above if a template deliberately\n // owns this behavior.\n const rulesPath = prefixMountedPath(DEFAULT_SPECULATION_RULES_PATH, basePath);\n headers.set(\"speculation-rules\", `\"${rulesPath}\"`);\n}\n\nfunction isFrameworkOrAssetPath(pathname: string): boolean {\n return (\n pathname.startsWith(\"/.well-known/\") ||\n pathname.startsWith(\"/_agent_native/\") ||\n pathname.startsWith(\"/_agent-native/\") ||\n pathname.startsWith(\"/api/\") ||\n pathname.startsWith(\"/@vite/\") ||\n pathname.startsWith(\"/@id/\") ||\n pathname.startsWith(\"/@fs/\") ||\n pathname === \"/@react-refresh\" ||\n pathname === \"/__vite_ping\" ||\n pathname === \"/__open-in-editor\" ||\n pathname === \"/favicon.ico\" ||\n pathname === \"/favicon.png\" ||\n (/\\.\\w+$/.test(pathname) && !pathname.endsWith(\".data\"))\n );\n}\n\nasync function rewriteMountedResponse(\n response: Response,\n basePath: string,\n pathname: string,\n requestUrl: string,\n): Promise<Response> {\n const sentryClientConfigScript = getSentryClientConfigScript();\n const headers = new Headers(response.headers);\n applyDefaultSsrCacheHeader(headers, response.status, pathname);\n applyDefaultSpeculationRulesHeader(headers, response.status, basePath);\n\n const location = headers.get(\"location\");\n if (location?.startsWith(\"/\") && !location.startsWith(\"//\")) {\n headers.set(\"location\", prefixMountedPath(location, basePath));\n }\n\n const contentType = headers.get(\"content-type\") ?? \"\";\n if (!contentType.toLowerCase().includes(\"text/html\") || !response.body) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n const html = await response.text();\n headers.delete(\"content-length\");\n return new Response(\n injectHeadScript(\n injectDefaultSocialImageMeta(\n prefixMountedHtml(html, basePath),\n defaultSocialImageUrl(requestUrl, basePath),\n ),\n sentryClientConfigScript,\n ),\n {\n status: response.status,\n statusText: response.statusText,\n headers,\n },\n );\n}\n\n/**\n * Create an h3 catch-all that hands page routes to React Router and\n * returns 404 for framework / asset paths that React Router doesn't own.\n */\nexport function createH3SSRHandler(getBuild: () => Promise<unknown> | unknown) {\n const handler = createRequestHandler(getBuild as any);\n return defineEventHandler(async (event) => {\n const basePath = getAppBasePath();\n const p = stripAppBasePath(event.url.pathname);\n if (isFrameworkOrAssetPath(p)) {\n return new Response(null, { status: 404 });\n }\n try {\n const request = requestWithPathname(event.req as Request, p, basePath);\n // Pin the active session onto the async request context so React Router\n // loaders that call `getRequestUserEmail()` / `accessFilter()` see the\n // signed-in user. Without this, SSR loaders fall through to the\n // unauthenticated branch even when the user is logged in — which broke\n // shared-deck \"Presentation link\" access for non-public decks.\n let session: Awaited<ReturnType<typeof getSession>> | null = null;\n const hasAuthSignal = requestHasAuthSignal(event);\n if (hasAuthSignal) {\n try {\n session = await getSession(event);\n } catch {\n // Auth lookup failures must not break SSR; treat as unauthenticated.\n }\n }\n const orgId = session?.email ? await readOrgIdForEvent(event) : undefined;\n const ctx = {\n userEmail: session?.email ?? undefined,\n orgId,\n };\n if (request.method === \"HEAD\") {\n const getRequest = new Request(request.url, {\n method: \"GET\",\n headers: request.headers,\n signal: request.signal,\n });\n const response = await runWithRequestContext(ctx, () =>\n handler(getRequest),\n );\n return await rewriteMountedResponse(\n new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n }),\n basePath,\n p,\n request.url,\n );\n }\n return await rewriteMountedResponse(\n await runWithRequestContext(ctx, () => handler(request)),\n basePath,\n p,\n request.url,\n );\n } catch (err) {\n // Log the full stack server-side, but never leak it to the client.\n // Stack traces expose file paths, library versions, and code structure\n // that aid reconnaissance attacks. In dev we surface the message text\n // so devtools shows something useful; in prod we return a bare 500.\n console.error(\"[ssr-handler] SSR error:\", err);\n const isProd = process.env.NODE_ENV === \"production\";\n const body = isProd\n ? \"Internal Server Error\"\n : `Internal Server Error: ${(err as Error)?.message ?? err}`;\n return new Response(body, {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n });\n}\n"]}
@@ -7,7 +7,7 @@ This is an **@agent-native/core** application -- the AI agent and UI share state
7
7
  ### Core Principles
8
8
 
9
9
  1. **Shared SQL database** -- All app state lives in SQL. Local SQLite at `data/app.db` is the zero-setup dev fallback; deployed apps need a persistent `DATABASE_URL` so data survives container/serverless restarts. Turso is optional, not required: Neon, Supabase, Turso/libSQL, plain Postgres, durable SQLite, D1 bindings, and Builder.io-managed environments are all valid when supported by the deploy. Core stores: `application_state`, `settings`, `oauth_tokens`, `sessions`, `resources`.
10
- 2. **All AI through agent chat** -- No inline LLM calls. UI delegates to the AI via `sendToAgentChat()` / `agentChat.submit()`. When UI selections should add hidden context for the user's next prompt without submitting, use `setContextToAgentChat()` with a stable `key`.
10
+ 2. **All AI through agent chat** -- No inline LLM calls. UI delegates to the AI via `sendToAgentChat()` / `agentChat.submit()`. Use `sendToAgentChat({ message, context, submit })` for simple UI handoffs and prefill/review flows. Only use the agent-chat context state helpers (`useAgentChatContext`, `setAgentChatContextItem`, `listAgentChatContext`, `removeAgentChatContextItem`, `clearAgentChatContext`) when the UI needs two-way sync with staged context chips.
11
11
  3. **Actions for app operations** -- `pnpm action <name>` dispatches to callable action files in `actions/`; `defineAction` also auto-exposes those operations at `/_agent-native/actions/:name` for the UI. Do not create custom REST routes that re-export actions.
12
12
  4. **Live sync keeps the UI current** -- Database writes stream over `/_agent-native/events` first, with `/_agent-native/poll` as the fallback. **When you (the agent) write data, the UI must reflect the change without a manual refresh.** This is non-negotiable. Use `useActionQuery` / `useActionMutation` for action-backed data (preferred). If you use raw `useQuery`, fold `useChangeVersions([<source>, "action"])` into the key for targeted refreshes. See the `real-time-sync` and `adding-a-feature` skills.
13
13
  5. **Agent can update code** -- The agent can modify this app's source code directly.
@@ -81,7 +81,7 @@ export default defineNitroPlugin(async (nitroApp) => {
81
81
  | `readResource`, `writeResource` | Read/write resources (from `@agent-native/core/resources`) |
82
82
  | `defineEventHandler`, `readBody`, `getQuery` | H3 route handler utilities (re-exported) |
83
83
  | `sendToAgentChat` | Send or prefill messages in the agent chat from UI (client-side) |
84
- | `setContextToAgentChat` | Stage keyed context chips for the next agent chat prompt from UI |
84
+ | Agent chat context state helpers | Optional advanced helpers for two-way sync with staged context chips |
85
85
  | `agentChat` | Send messages to agent from scripts (server-side) |
86
86
 
87
87
  ## Adding a Script
@@ -102,18 +102,12 @@ sendToAgentChat({
102
102
  });
103
103
  ```
104
104
 
105
- To add hidden context without submitting or filling the prompt text, stage
106
- keyed context nuggets. Multiple nuggets stack; using the same `key` replaces the
107
- previous nugget.
108
-
109
- ```ts
110
- import { setContextToAgentChat } from "@agent-native/core";
111
- setContextToAgentChat({
112
- key: "selected-record",
113
- title: "Selected Record",
114
- context: JSON.stringify(record, null, 2),
115
- });
116
- ```
105
+ For most UI handoffs, pass hidden context directly with `sendToAgentChat()`. Use
106
+ `submit: false` when the user should review the draft first. Use
107
+ `useAgentChatContext`, `setAgentChatContextItem`, `listAgentChatContext`,
108
+ `removeAgentChatContextItem`, and `clearAgentChatContext` only for advanced UI
109
+ that needs to read, mirror, stage, remove, or clear staged context chips as local
110
+ interface state.
117
111
 
118
112
  **From scripts:**
119
113
 
@@ -21,8 +21,8 @@
21
21
  "zod": "^4.4.3"
22
22
  },
23
23
  "devDependencies": {
24
- "@react-router/dev": "^7.13.1",
25
- "@react-router/fs-routes": "^7.13.1",
24
+ "@react-router/dev": "^7.16.0",
25
+ "@react-router/fs-routes": "^7.16.0",
26
26
  "@tailwindcss/vite": "^4.1.18",
27
27
  "@tanstack/react-query": "^5.99.2",
28
28
  "@types/node": "^24.2.1",
@@ -34,7 +34,7 @@
34
34
  "prettier": "^3.6.2",
35
35
  "react": "^19.2.5",
36
36
  "react-dom": "^19.2.5",
37
- "react-router": "^7.13.1",
37
+ "react-router": "^7.16.0",
38
38
  "sonner": "^2.0.7",
39
39
  "tailwind-merge": "^3.5.0",
40
40
  "tailwindcss": "^4.1.18",
@@ -14,10 +14,12 @@ agent should know.
14
14
  - All AI/LLM behavior goes through the app's agent chat. UI and server code
15
15
  must not call model providers, AI SDK `generateText()` / `streamText()`, or
16
16
  other inline LLM APIs directly. Use `sendToAgentChat()` for local app-agent
17
- work. When selected UI data should become hidden context for the user's next
18
- prompt without submitting anything, use `setContextToAgentChat()` with a
19
- stable `key`. Read `.agents/skills/delegate-to-agent/SKILL.md` before
20
- building agent-driven UI or "AI" features.
17
+ work, including hidden `context` and `submit: false` prefill/review flows.
18
+ Only use `useAgentChatContext`, `setAgentChatContextItem`,
19
+ `listAgentChatContext`, `removeAgentChatContextItem`, and
20
+ `clearAgentChatContext` when UI needs two-way sync with staged context chips.
21
+ Read `.agents/skills/delegate-to-agent/SKILL.md` before building agent-driven
22
+ UI or "AI" features.
21
23
  - Put shared code in `packages/shared` only when multiple apps need it.
22
24
  - Keep app-specific screens, actions, state, and skills inside `apps/<app>`.
23
25
  - Store shared runtime configuration in the workspace root `.env`; use
@@ -11,10 +11,12 @@ coding agents can discover the same workspace-wide guidance from the root.
11
11
  - All AI/LLM behavior goes through the app's agent chat. UI and server code
12
12
  must not call model providers, AI SDK `generateText()` / `streamText()`, or
13
13
  other inline LLM APIs directly. Use `sendToAgentChat()` for local app-agent
14
- work. When selected UI data should become hidden context for the user's next
15
- prompt without submitting anything, use `setContextToAgentChat()` with a
16
- stable `key`. Read `packages/shared/.agents/skills/delegate-to-agent/SKILL.md`
17
- before building agent-driven UI or "AI" features.
14
+ work, including hidden `context` and `submit: false` prefill/review flows.
15
+ Only use `useAgentChatContext`, `setAgentChatContextItem`,
16
+ `listAgentChatContext`, `removeAgentChatContextItem`, and
17
+ `clearAgentChatContext` when UI needs two-way sync with staged context chips.
18
+ Read `packages/shared/.agents/skills/delegate-to-agent/SKILL.md` before
19
+ building agent-driven UI or "AI" features.
18
20
 
19
21
  ## Workspace Resources
20
22
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: "Actions"
3
- description: "defineAction — the single definition that becomes an agent tool, a typesafe frontend mutation, an HTTP endpoint, an MCP tool, and a CLI command."
3
+ description: "defineAction — the single definition that becomes an agent tool, typed frontend hooks, framework transport, an MCP tool, and a CLI command."
4
4
  ---
5
5
 
6
6
  # Actions
@@ -8,8 +8,9 @@ description: "defineAction — the single definition that becomes an agent tool,
8
8
  Actions are the single source of truth for anything your app does. Define an action once with `defineAction()`, drop it in `actions/`, and it's immediately available as:
9
9
 
10
10
  - **An agent tool** — the agent sees it with a zod-derived JSON Schema and can call it in chat.
11
- - **A typesafe React mutation** — `useActionMutation("name")` on the frontend, types inferred from the schema.
12
- - **An HTTP endpoint** — `POST /_agent-native/actions/<name>` (auto-mounted by the framework).
11
+ - **Typesafe React hooks** — `useActionQuery("name")` and `useActionMutation("name")` on the frontend, types inferred from the schema.
12
+ - **Imperative client calls** — `callAction("name", params)` when a hook does not fit.
13
+ - **Framework transport** — auto-mounted by the framework behind those hooks and available to external HTTP clients.
13
14
  - **An MCP tool** — exposed to Claude, ChatGPT custom MCP apps, Claude Desktop/Code, Cursor, Codex, and any other MCP client.
14
15
  - **An A2A tool** — called by other agent-native apps over A2A.
15
16
  - **A CLI command** — `pnpm action <name>` for scripting and dev loops.
@@ -199,10 +200,7 @@ export default defineAction({
199
200
  const screen: Record<string, unknown> = { navigation };
200
201
 
201
202
  if (navigation?.view === "inbox") {
202
- const res = await fetch(
203
- `${process.env.APP_URL}/api/emails?label=${navigation.label}`,
204
- );
205
- screen.emailList = await res.json();
203
+ screen.emailList = await listEmailsForLabel(navigation.label);
206
204
  }
207
205
 
208
206
  return screen;