@agent-native/core 0.155.0 → 0.157.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +3 -1
  2. package/corpus/templates/assets/app/i18n-data.ts +21 -1
  3. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +17 -13
  4. package/corpus/templates/clips/app/components/player/share-dialog.tsx +102 -59
  5. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +15 -1
  6. package/corpus/templates/clips/app/routes/share.$shareId.tsx +16 -2
  7. package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +98 -29
  8. package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +45 -91
  9. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +94 -2
  10. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +17 -29
  11. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
  12. package/corpus/templates/slides/app/context/DeckContext.tsx +42 -2
  13. package/corpus/templates/slides/app/global.css +7 -40
  14. package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
  15. package/corpus/templates/slides/app/pages/DeckEditor.tsx +130 -45
  16. package/dist/agent/index.d.ts +1 -1
  17. package/dist/agent/production-agent.d.ts +30 -0
  18. package/dist/agent/production-agent.js +100 -8
  19. package/dist/agent/types.d.ts +9 -0
  20. package/dist/client/AgentPanel.js +12 -9
  21. package/dist/client/AssistantChat.d.ts +15 -1
  22. package/dist/client/AssistantChat.js +110 -43
  23. package/dist/client/MultiTabAssistantChat.js +44 -27
  24. package/dist/client/chat/markdown-renderer.js +4 -2
  25. package/dist/client/chat/message-components.d.ts +2 -2
  26. package/dist/client/chat/message-components.js +69 -35
  27. package/dist/client/chat/run-recovery.d.ts +4 -1
  28. package/dist/client/chat/run-recovery.js +62 -30
  29. package/dist/client/chat/tool-call-display.d.ts +12 -3
  30. package/dist/client/chat/tool-call-display.js +79 -40
  31. package/dist/client/chat/widgets/DataChartRenderer.js +3 -1
  32. package/dist/client/chat/widgets/DataChartWidget.js +8 -2
  33. package/dist/client/chat/widgets/DataInsightsWidget.js +3 -1
  34. package/dist/client/chat/widgets/DataTableWidget.js +23 -9
  35. package/dist/client/chat/widgets/builtin-tool-renderers.js +3 -1
  36. package/dist/client/components/ui/message-scroller.d.ts +1 -1
  37. package/dist/client/components/ui/message-scroller.js +7 -3
  38. package/dist/client/composer/runtime-adapters.js +3 -2
  39. package/dist/client/context-xray/ContextMeter.js +5 -1
  40. package/dist/client/context-xray/ContextXRayPanel.js +5 -5
  41. package/dist/client/error-format.d.ts +4 -0
  42. package/dist/client/error-format.js +93 -5
  43. package/dist/client/i18n.js +83 -17
  44. package/dist/client/observability/ThumbsFeedback.js +10 -8
  45. package/dist/client/sharing/ShareButton.js +160 -54
  46. package/dist/coding-tools/run-code.js +2 -1
  47. package/dist/coding-tools/sandbox/background.d.ts +1 -0
  48. package/dist/coding-tools/sandbox/background.js +8 -1
  49. package/dist/coding-tools/sandbox/executions-store.d.ts +2 -0
  50. package/dist/coding-tools/sandbox/executions-store.js +41 -3
  51. package/dist/collab/routes.d.ts +1 -1
  52. package/dist/index.d.ts +1 -1
  53. package/dist/localization/core-messages/ar-SA.d.ts +3 -0
  54. package/dist/localization/core-messages/ar-SA.js +541 -0
  55. package/dist/localization/core-messages/de-DE.d.ts +3 -0
  56. package/dist/localization/core-messages/de-DE.js +513 -0
  57. package/dist/localization/core-messages/en-US.d.ts +513 -0
  58. package/dist/localization/core-messages/en-US.js +513 -0
  59. package/dist/localization/core-messages/es-ES.d.ts +3 -0
  60. package/dist/localization/core-messages/es-ES.js +520 -0
  61. package/dist/localization/core-messages/fr-FR.d.ts +3 -0
  62. package/dist/localization/core-messages/fr-FR.js +520 -0
  63. package/dist/localization/core-messages/hi-IN.d.ts +3 -0
  64. package/dist/localization/core-messages/hi-IN.js +513 -0
  65. package/dist/localization/core-messages/ja-JP.d.ts +3 -0
  66. package/dist/localization/core-messages/ja-JP.js +506 -0
  67. package/dist/localization/core-messages/ko-KR.d.ts +3 -0
  68. package/dist/localization/core-messages/ko-KR.js +506 -0
  69. package/dist/localization/core-messages/pt-BR.d.ts +3 -0
  70. package/dist/localization/core-messages/pt-BR.js +520 -0
  71. package/dist/localization/core-messages/zh-CN.d.ts +3 -0
  72. package/dist/localization/core-messages/zh-CN.js +506 -0
  73. package/dist/localization/core-messages/zh-TW.d.ts +3 -0
  74. package/dist/localization/core-messages/zh-TW.js +506 -0
  75. package/dist/localization/core-messages.d.ts +524 -0
  76. package/dist/localization/core-messages.js +124 -0
  77. package/dist/localization/default-messages.d.ts +2 -0
  78. package/dist/localization/default-messages.js +2 -0
  79. package/dist/notifications/routes.d.ts +1 -1
  80. package/dist/observability/routes.d.ts +5 -5
  81. package/dist/resources/handlers.d.ts +1 -1
  82. package/dist/secrets/routes.d.ts +9 -9
  83. package/dist/server/agent-chat/plugin-options.d.ts +7 -2
  84. package/dist/server/agent-chat-plugin.d.ts +10 -0
  85. package/dist/server/agent-chat-plugin.js +144 -41
  86. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  87. package/dist/server/agent-run-context.d.ts +7 -1
  88. package/dist/server/agent-run-context.js +9 -2
  89. package/dist/server/agent-teams-run-queue.d.ts +3 -0
  90. package/dist/server/agent-teams.js +38 -9
  91. package/dist/server/index.d.ts +1 -1
  92. package/dist/server/request-context.d.ts +7 -0
  93. package/dist/server/request-context.js +15 -0
  94. package/docs/content/agent-surfaces.mdx +30 -0
  95. package/package.json +2 -2
@@ -12,7 +12,7 @@ import { AGENT_CHAT_BACKGROUND_RUN_FIELD, AGENT_CHAT_PROCESS_RUN_PATH, backgroun
12
12
  import { resolveEngine, createAnthropicEngine, getStoredModelForEngine, normalizeModelForEngine, resolveDelegatedRunModel, getAgentEngineEntry, isAgentEnginePackageInstalled, isStoredEngineUsableForRequest, listAgentEngines, registerBuiltinEngines, } from "../agent/engine/index.js";
13
13
  import { SYSTEM_PROMPT_CACHE_SPLIT } from "../agent/engine/prompt-cache.js";
14
14
  import { PROVIDER_TO_ENV } from "../agent/engine/provider-env-vars.js";
15
- import { createProductionAgentHandler, actionsToEngineTools, executeAgentToolCall, toolCallCacheKey, getActiveRunForThreadAsync, abortRunDurably, abortTurnDurably, subscribeToRun, } from "../agent/production-agent.js";
15
+ import { createProductionAgentHandler, actionsToEngineTools, executeAgentToolCall, filterActionsByAllowedNames, readPersistedActionSurface, toolCallCacheKey, getActiveRunForThreadAsync, abortRunDurably, abortTurnDurably, subscribeToRun, } from "../agent/production-agent.js";
16
16
  import { callerHasRunAccess, callerHasThreadAccess, } from "../agent/run-ownership.js";
17
17
  import { markTurnAborted, readBackgroundRunClaim } from "../agent/run-store.js";
18
18
  import { buildCurrentTimeUserContext, buildRuntimeContextPrompt, } from "../agent/runtime-context.js";
@@ -208,6 +208,46 @@ export async function resolveA2ARecoverableArtifactSecret(orgId = getRequestOrgI
208
208
  export function buildLeanRunPolicyPrompt(codeEditingSurfaceRestriction, prodCodeExecPromptNote) {
209
209
  return codeEditingSurfaceRestriction + prodCodeExecPromptNote;
210
210
  }
211
+ export function filterPromptActionsToSurface(actions, allowedActionNames) {
212
+ if (!allowedActionNames)
213
+ return actions;
214
+ return filterActionsByAllowedNames(actions, allowedActionNames.filter((name) => actions[name]));
215
+ }
216
+ /** Keep late-bound sandbox and data-program bridges on the current request's
217
+ * authorized registry instead of the plugin's process-wide action catalog. */
218
+ export function filterRuntimeActionsToSurface(actions) {
219
+ return filterPromptActionsToSurface(actions, getRequestRunContext()?.allowedActionNames);
220
+ }
221
+ /** Remove framework guidance for tools that the request surface does not
222
+ * expose. The default framework prompt is line-oriented, so dropping the
223
+ * affected instruction keeps unrelated behavioral guidance intact without
224
+ * teaching the model names it cannot call. */
225
+ export function filterFrameworkPromptToSurface(prompt, actions, allowedActionNames) {
226
+ if (!allowedActionNames)
227
+ return prompt;
228
+ const allowedNames = new Set(allowedActionNames);
229
+ const deniedPatterns = Object.keys(actions)
230
+ .filter((name) => !allowedNames.has(name))
231
+ .sort((a, b) => b.length - a.length)
232
+ .map((name) => {
233
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
234
+ return new RegExp(`(^|[^a-z0-9-])${escaped}(?=$|[^a-z0-9-])`);
235
+ });
236
+ if (deniedPatterns.length === 0)
237
+ return prompt;
238
+ return prompt
239
+ .split("\n")
240
+ .filter((line) => !deniedPatterns.some((pattern) => pattern.test(line)))
241
+ .join("\n")
242
+ .replace(/\n{3,}/g, "\n\n")
243
+ .trimEnd();
244
+ }
245
+ export function resolveProductionCodeExecutionForActionSurface(mode, hasRequestScopedSurface) {
246
+ // A trusted shell can reach action routes outside the native registry, so it
247
+ // cannot uphold a hard per-request allowlist. Keep sandboxed run-code, whose
248
+ // bridge is filtered against the current request, as the safe equivalent.
249
+ return hasRequestScopedSurface && mode === "trusted" ? "sandboxed" : mode;
250
+ }
211
251
  /**
212
252
  * In-memory rate-limit tracker for `/generate-title`. Keyed by user email,
213
253
  * value is recent invocation timestamps within the rolling window. Stale
@@ -892,6 +932,11 @@ export function createAgentChatPlugin(options) {
892
932
  : rawEnvCodeExec === "off"
893
933
  ? "off"
894
934
  : (options?.codeExecution?.production ?? "off");
935
+ const effectiveProdCodeExec = resolveProductionCodeExecutionForActionSurface(resolvedProdCodeExec, Boolean(options?.resolveActionSurface));
936
+ if (resolvedProdCodeExec === "trusted" &&
937
+ effectiveProdCodeExec !== "trusted") {
938
+ console.warn("[agent-native] Request-scoped action surfaces disable trusted shell tools; using sandboxed code execution instead.");
939
+ }
895
940
  // Forward-declaration for the production code-execution bridge supplier.
896
941
  // Must come before the code entries are created so their closures can capture it.
897
942
  let prodRunCodeToolActions = {};
@@ -902,11 +947,11 @@ export function createAgentChatPlugin(options) {
902
947
  const runCodeTool = await loadRunCodeToolEntries(
903
948
  // Supplier is evaluated at invocation time so runtime additions to
904
949
  // prodActions (e.g. MCP sync) are visible to the bridge.
905
- () => prodRunCodeToolActions, { bridgeTools: options?.codeExecution?.bridgeTools });
950
+ () => filterRuntimeActionsToSurface(prodRunCodeToolActions), { bridgeTools: options?.codeExecution?.bridgeTools });
906
951
  const leanRunCodeTool = await loadRunCodeToolEntries(
907
952
  // Lean prompt mode intentionally exposes a much smaller action
908
953
  // surface; keep sandbox appAction() calls scoped to that same surface.
909
- () => leanRunCodeToolActions, { bridgeTools: options?.codeExecution?.bridgeTools });
954
+ () => filterRuntimeActionsToSurface(leanRunCodeToolActions), { bridgeTools: options?.codeExecution?.bridgeTools });
910
955
  // Full coding tool registry (bash/read/edit/write) for "trusted" prod.
911
956
  // In dev mode this is handled separately via devHandler below.
912
957
  const prodCodingTools = {};
@@ -935,7 +980,7 @@ export function createAgentChatPlugin(options) {
935
980
  // use a late-binding supplier so devRunCodeTool can reference the
936
981
  // devActions registry once it is built below (see devHandler block).
937
982
  const devRunCodeTool = canToggle
938
- ? await loadRunCodeToolEntries(() => devRunCodeToolActions, {
983
+ ? await loadRunCodeToolEntries(() => filterRuntimeActionsToSurface(devRunCodeToolActions), {
939
984
  bridgeTools: options?.codeExecution?.bridgeTools,
940
985
  })
941
986
  : {};
@@ -946,7 +991,7 @@ export function createAgentChatPlugin(options) {
946
991
  ...templateScripts,
947
992
  ...(canToggle
948
993
  ? devRunCodeTool
949
- : resolvedProdCodeExec !== "off"
994
+ : effectiveProdCodeExec !== "off"
950
995
  ? runCodeTool
951
996
  : {}),
952
997
  };
@@ -1684,6 +1729,36 @@ export function createAgentChatPlugin(options) {
1684
1729
  : "";
1685
1730
  const prodActionsPrompt = generateActionsPrompt(templateScripts, "tool", lazyContext ? effectiveInitialToolNames : undefined) + corpusToolsPrompt;
1686
1731
  const devActionsPrompt = generateActionsPrompt({ ...discoveredActions, ...templateScripts }, "cli") + corpusToolsPrompt;
1732
+ const filterPromptActionsForRequest = (actions) => {
1733
+ return filterPromptActionsToSurface(actions, getRequestRunContext()?.allowedActionNames);
1734
+ };
1735
+ const resolveRequestActionsPrompt = (mode) => {
1736
+ const allowedNames = getRequestRunContext()?.allowedActionNames;
1737
+ if (!allowedNames) {
1738
+ return mode === "tool" ? prodActionsPrompt : devActionsPrompt;
1739
+ }
1740
+ const promptActions = filterPromptActionsForRequest(mode === "tool"
1741
+ ? templateScripts
1742
+ : { ...discoveredActions, ...templateScripts });
1743
+ const promptCorpus = filterPromptActionsForRequest(corpusPromptRegistry);
1744
+ return (generateActionsPrompt(promptActions, mode) +
1745
+ (loadCorpusToolsInitially
1746
+ ? generateCorpusToolsPrompt(promptCorpus)
1747
+ : ""));
1748
+ };
1749
+ const leanActionsPrompt = prodActionsPrompt +
1750
+ (a2aAgentDelegationEnabled
1751
+ ? generateActionsPrompt(callAgentScript, "tool")
1752
+ : "");
1753
+ const resolveRequestLeanActionsPrompt = () => {
1754
+ const allowedNames = getRequestRunContext()?.allowedActionNames;
1755
+ if (!allowedNames)
1756
+ return leanActionsPrompt;
1757
+ return generateActionsPrompt(filterPromptActionsForRequest({
1758
+ ...templateScripts,
1759
+ ...(a2aAgentDelegationEnabled ? callAgentScript : {}),
1760
+ }), "tool");
1761
+ };
1687
1762
  // Build system prompts — dynamic functions that pre-load resources per-request.
1688
1763
  // Production gets PROD_FRAMEWORK_PROMPT, dev gets DEV_FRAMEWORK_PROMPT.
1689
1764
  // Custom systemPrompt from options overrides the framework default entirely.
@@ -1695,10 +1770,19 @@ export function createAgentChatPlugin(options) {
1695
1770
  // `nativeActionsInDev` or `leanPrompt`), the dev prompt's "invoke
1696
1771
  // template actions via bash" guidance is wrong — use the prod prompt
1697
1772
  // + tool-format action list instead, same as production.
1698
- const devNative = options?.nativeActionsInDev === true || leanPrompt;
1699
- const devPrompt = devNative
1700
- ? prodPrompt
1701
- : (options?.devSystemPrompt
1773
+ const devNative = options?.nativeActionsInDev === true ||
1774
+ leanPrompt ||
1775
+ Boolean(options?.resolveActionSurface);
1776
+ // Keep legacy names for the composition below
1777
+ const basePrompt = prodPrompt;
1778
+ const getFrameworkPromptActions = () => Object.fromEntries(Object.entries(prodActions).filter(([name]) => !templateScripts[name] && !mcpActionEntries[name]));
1779
+ const resolveRequestBasePrompt = () => (options?.systemPrompt ??
1780
+ filterFrameworkPromptToSurface(lazyContext ? PROD_FRAMEWORK_PROMPT_COMPACT : PROD_FRAMEWORK_PROMPT, getFrameworkPromptActions(), getRequestRunContext()?.allowedActionNames)) + resolveRequestActionsPrompt("tool");
1781
+ const resolveRequestLeanPrompt = () => (options?.systemPrompt ?? "") + resolveRequestLeanActionsPrompt();
1782
+ const resolveRequestDevPrompt = () => {
1783
+ if (devNative)
1784
+ return resolveRequestBasePrompt();
1785
+ const frameworkPrompt = options?.devSystemPrompt
1702
1786
  ? options.devSystemPrompt +
1703
1787
  (options?.systemPrompt ??
1704
1788
  (lazyContext
@@ -1706,9 +1790,9 @@ export function createAgentChatPlugin(options) {
1706
1790
  : PROD_FRAMEWORK_PROMPT))
1707
1791
  : lazyContext
1708
1792
  ? DEV_FRAMEWORK_PROMPT_COMPACT
1709
- : DEV_FRAMEWORK_PROMPT) + devActionsPrompt;
1710
- // Keep legacy names for the composition below
1711
- const basePrompt = prodPrompt;
1793
+ : DEV_FRAMEWORK_PROMPT;
1794
+ return frameworkPrompt + resolveRequestActionsPrompt("cli");
1795
+ };
1712
1796
  if (mcpOptions.enabled) {
1713
1797
  // Mount MCP remote server — same action registry as A2A + agent chat
1714
1798
  const { mountMCP } = await import("../mcp/server.js");
@@ -2245,7 +2329,7 @@ export function createAgentChatPlugin(options) {
2245
2329
  const teamTools = createTeamTools({
2246
2330
  getOwner: () => requireCurrentRunOwner("spawn or manage sub-agents"),
2247
2331
  getSystemPrompt: () => getRequestRunContext()?.systemPrompt ?? basePrompt,
2248
- getActions: buildSubAgentActions,
2332
+ getActions: () => filterRuntimeActionsToSurface(buildSubAgentActions()),
2249
2333
  getEngine: () => {
2250
2334
  const runCtx = getRequestRunContext();
2251
2335
  // Sub-agents must inherit the parent run's resolved key so
@@ -2343,9 +2427,11 @@ export function createAgentChatPlugin(options) {
2343
2427
  ...mcpActionEntries,
2344
2428
  // Sandboxed run-code for hosted production when enabled, and for the
2345
2429
  // app-rendered production-style handler in local dev.
2346
- ...(canToggle || resolvedProdCodeExec !== "off" ? runCodeTool : {}),
2430
+ ...(canToggle || effectiveProdCodeExec !== "off" ? runCodeTool : {}),
2347
2431
  // Full coding tools in production when mode is "trusted".
2348
- ...(!canToggle ? prodCodingTools : {}),
2432
+ ...(!canToggle && effectiveProdCodeExec === "trusted"
2433
+ ? prodCodingTools
2434
+ : {}),
2349
2435
  });
2350
2436
  mountRealtimeVoiceRoutes(nitroApp, prodActions, {
2351
2437
  resolveOrgId: options?.resolveOrgId,
@@ -2393,7 +2479,9 @@ export function createAgentChatPlugin(options) {
2393
2479
  // Otherwise templates with a minimal prompt can advertise sandboxed
2394
2480
  // execution in the system prompt while the actual tool registry omits
2395
2481
  // it.
2396
- ...(canToggle || resolvedProdCodeExec !== "off" ? leanRunCodeTool : {}),
2482
+ ...(canToggle || effectiveProdCodeExec !== "off"
2483
+ ? leanRunCodeTool
2484
+ : {}),
2397
2485
  });
2398
2486
  leanRunCodeToolActions = leanActions;
2399
2487
  // Keep the prod action dict's MCP entries in sync when the manager's
@@ -2410,14 +2498,18 @@ export function createAgentChatPlugin(options) {
2410
2498
  // Lean mode: use only the template's systemPrompt + actions list.
2411
2499
  // Skip resource loading and schema block — those add DB round-trips
2412
2500
  // and tokens that minimal/voice apps don't need.
2413
- const leanActionsPrompt = prodActionsPrompt +
2414
- (a2aAgentDelegationEnabled
2415
- ? generateActionsPrompt(callAgentScript, "tool")
2416
- : "");
2417
- const leanBasePrompt = (options?.systemPrompt ?? "") + leanActionsPrompt;
2418
2501
  const anonymousReadOnlyPrompt = (options?.systemPrompt ?? PROD_FRAMEWORK_PROMPT_COMPACT) +
2419
2502
  generateActionsPrompt(filterReadOnlyActions(templateScripts), "tool", lazyContext ? effectiveInitialToolNames : undefined) +
2420
2503
  "\n\nYou are answering from a public shared page. Treat the visible resource as read-only: do not create, edit, delete, comment on, share, or otherwise mutate app data. If the user asks for a change, describe what you would change or suggest signing in to edit.";
2504
+ const resolveAnonymousReadOnlyPrompt = () => {
2505
+ if (!getRequestRunContext()?.allowedActionNames) {
2506
+ return anonymousReadOnlyPrompt;
2507
+ }
2508
+ return ((options?.systemPrompt ??
2509
+ filterFrameworkPromptToSurface(PROD_FRAMEWORK_PROMPT_COMPACT, getFrameworkPromptActions(), getRequestRunContext()?.allowedActionNames)) +
2510
+ generateActionsPrompt(filterPromptActionsForRequest(filterReadOnlyActions(templateScripts)), "tool") +
2511
+ "\n\nYou are answering from a public shared page. Treat the visible resource as read-only: do not create, edit, delete, comment on, share, or otherwise mutate app data. If the user asks for a change, describe what you would change or suggest signing in to edit.");
2512
+ };
2421
2513
  // Per-request preamble shared by both prod and dev handlers. Resolves
2422
2514
  // owner + user API key onto the AsyncLocalStorage run context so
2423
2515
  // downstream tool closures (automation, fetch, team) read the
@@ -2585,8 +2677,8 @@ When the user asks to add a feature, edit a component, fix a bug in the app itse
2585
2677
  Non-code requests are still fine on this surface: read data, navigate the UI, summarize, search, create/update extensions (sandboxed Alpine.js mini-apps stored in SQL), and call template actions. The restriction is specifically about direct edits to the host app's own source files.
2586
2678
  </app-rendered-chat-no-direct-code-edits>`;
2587
2679
  // System-prompt note appended when production code execution is enabled.
2588
- const prodCodeExecPromptNote = !canToggle && resolvedProdCodeExec !== "off"
2589
- ? resolvedProdCodeExec === "trusted"
2680
+ const prodCodeExecPromptNote = !canToggle && effectiveProdCodeExec !== "off"
2681
+ ? effectiveProdCodeExec === "trusted"
2590
2682
  ? "\n\n<code-execution-mode>Full shell access is enabled (trusted mode). You have bash, read, edit, write, and run-code tools available. Use bash for file discovery, running tests and builds, and project CLIs. Use run-code for sandboxed JavaScript data processing: provider/API pagination, joins, classification, aggregation, and large-response reduction. Use tool-orchestration for short bounded fan-out or reduction over read-only tools. Use `pnpm action <name>` in bash to invoke registered app actions from the shell.</code-execution-mode>"
2591
2683
  : "\n\n<code-execution-mode>Sandboxed code execution is enabled. Use tool-orchestration for short bounded fan-out, joins, and reduction over read-only tools. Use run-code when you need its broader provider/web helpers, workspace staging, or durable background execution. In either tool, authenticated calls go through the provided host globals and results should be reduced before printing.</code-execution-mode>"
2592
2684
  : "";
@@ -2594,6 +2686,10 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2594
2686
  actions: leanPrompt ? leanActions : prodActions,
2595
2687
  systemPrompt: async (event) => {
2596
2688
  const { owner, extra } = await prepareRun(event);
2689
+ const requestActionsPrompt = resolveRequestActionsPrompt("tool");
2690
+ const requestLeanActionsPrompt = resolveRequestLeanActionsPrompt();
2691
+ const requestBasePrompt = resolveRequestBasePrompt();
2692
+ const requestLeanPrompt = resolveRequestLeanPrompt();
2597
2693
  const runtimeContext = runtimeContextForEvent(event);
2598
2694
  const codeEditingSurfaceRestriction = shouldBlockInProductCodeEditing(event)
2599
2695
  ? APP_RENDERED_CHAT_NO_DIRECT_CODE_PROMPT
@@ -2612,8 +2708,8 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2612
2708
  const leanRunPolicyPrompt = buildLeanRunPolicyPrompt(codeEditingSurfaceRestriction, prodCodeExecPromptNote);
2613
2709
  const resources = await loadResourcesForPrompt(owner, true, options?.appId, undefined, { disabledFrameworkGroups });
2614
2710
  await emitContextXraySystemSections(event, {
2615
- frameworkPrompt: leanBasePrompt.slice(0, Math.max(0, leanBasePrompt.length - leanActionsPrompt.length)),
2616
- actionsPrompt: leanActionsPrompt,
2711
+ frameworkPrompt: requestLeanPrompt.slice(0, Math.max(0, requestLeanPrompt.length - requestLeanActionsPrompt.length)),
2712
+ actionsPrompt: requestLeanActionsPrompt,
2617
2713
  additionalFramework: leanRunPolicyPrompt,
2618
2714
  resources,
2619
2715
  extra,
@@ -2621,7 +2717,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2621
2717
  runtimeContext,
2622
2718
  });
2623
2719
  return setSystemPromptOnContext(buildLeanSystemPrompt({
2624
- basePrompt: leanBasePrompt,
2720
+ basePrompt: requestLeanPrompt,
2625
2721
  additionalFramework: leanRunPolicyPrompt,
2626
2722
  cacheSplit: SYSTEM_PROMPT_CACHE_SPLIT,
2627
2723
  resources,
@@ -2637,8 +2733,8 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2637
2733
  ? ""
2638
2734
  : await buildSchemaBlock(owner, databaseToolsMode);
2639
2735
  await emitContextXraySystemSections(event, {
2640
- frameworkPrompt: basePrompt.slice(0, Math.max(0, basePrompt.length - prodActionsPrompt.length)),
2641
- actionsPrompt: prodActionsPrompt,
2736
+ frameworkPrompt: requestBasePrompt.slice(0, Math.max(0, requestBasePrompt.length - requestActionsPrompt.length)),
2737
+ actionsPrompt: requestActionsPrompt,
2642
2738
  resources,
2643
2739
  schemaBlock,
2644
2740
  extra,
@@ -2646,7 +2742,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2646
2742
  runtimeContext,
2647
2743
  additionalFramework: codeEditingSurfaceRestriction + prodCodeExecPromptNote,
2648
2744
  });
2649
- return setSystemPromptOnContext(basePrompt +
2745
+ return setSystemPromptOnContext(requestBasePrompt +
2650
2746
  SYSTEM_PROMPT_CACHE_SPLIT +
2651
2747
  resources +
2652
2748
  schemaBlock +
@@ -2708,6 +2804,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2708
2804
  message,
2709
2805
  };
2710
2806
  },
2807
+ resolveActionSurface: options?.resolveActionSurface,
2711
2808
  skipFilesContext,
2712
2809
  initialToolNames: effectiveInitialToolNames,
2713
2810
  ...(options?.toolLimits ? { toolLimits: options.toolLimits } : {}),
@@ -2741,12 +2838,13 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2741
2838
  actions: anonymousReadOnlyActions,
2742
2839
  systemPrompt: async (event) => {
2743
2840
  const { extra } = await prepareRun(event);
2841
+ const requestAnonymousPrompt = resolveAnonymousReadOnlyPrompt();
2744
2842
  await emitContextXraySystemSections(event, {
2745
- frameworkPrompt: anonymousReadOnlyPrompt,
2843
+ frameworkPrompt: requestAnonymousPrompt,
2746
2844
  extra,
2747
2845
  runtimeContext: runtimeContextForEvent(event),
2748
2846
  });
2749
- return setSystemPromptOnContext(anonymousReadOnlyPrompt +
2847
+ return setSystemPromptOnContext(requestAnonymousPrompt +
2750
2848
  extra +
2751
2849
  runtimeContextForEvent(event));
2752
2850
  },
@@ -2756,6 +2854,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2756
2854
  ...resolveInteractiveAgentRunOptions(options),
2757
2855
  finalResponseGuard: options?.finalResponseGuard,
2758
2856
  prepareRequest: options?.prepareRequest,
2857
+ resolveActionSurface: options?.resolveActionSurface,
2759
2858
  skipFilesContext: true,
2760
2859
  initialToolNames: effectiveInitialToolNames,
2761
2860
  onEngineResolved: (engine, model) => {
@@ -2847,6 +2946,10 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2847
2946
  actions: devActions,
2848
2947
  systemPrompt: async (event) => {
2849
2948
  const { owner, extra } = await prepareRun(event);
2949
+ const requestActionsPrompt = resolveRequestActionsPrompt(devNative ? "tool" : "cli");
2950
+ const requestLeanActionsPrompt = resolveRequestLeanActionsPrompt();
2951
+ const requestLeanPrompt = resolveRequestLeanPrompt();
2952
+ const requestDevPrompt = resolveRequestDevPrompt();
2850
2953
  const runtimeContext = runtimeContextForEvent(event);
2851
2954
  const modelOverlay = resolveModelOverlay();
2852
2955
  // Stable-first ordering: runtimeContext (day-granular) is
@@ -2856,15 +2959,15 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2856
2959
  if (leanPrompt) {
2857
2960
  const resources = await loadResourcesForPrompt(owner, true, options?.appId, undefined, { disabledFrameworkGroups });
2858
2961
  await emitContextXraySystemSections(event, {
2859
- frameworkPrompt: leanBasePrompt.slice(0, Math.max(0, leanBasePrompt.length - leanActionsPrompt.length)),
2860
- actionsPrompt: leanActionsPrompt,
2962
+ frameworkPrompt: requestLeanPrompt.slice(0, Math.max(0, requestLeanPrompt.length - requestLeanActionsPrompt.length)),
2963
+ actionsPrompt: requestLeanActionsPrompt,
2861
2964
  resources,
2862
2965
  extra,
2863
2966
  modelOverlay,
2864
2967
  runtimeContext,
2865
2968
  });
2866
2969
  return setSystemPromptOnContext(buildLeanSystemPrompt({
2867
- basePrompt: leanBasePrompt,
2970
+ basePrompt: requestLeanPrompt,
2868
2971
  resources,
2869
2972
  extra,
2870
2973
  modelOverlay,
@@ -2876,17 +2979,15 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2876
2979
  ? ""
2877
2980
  : await buildSchemaBlock(owner, databaseToolsMode);
2878
2981
  await emitContextXraySystemSections(event, {
2879
- frameworkPrompt: devNative
2880
- ? basePrompt.slice(0, Math.max(0, basePrompt.length - prodActionsPrompt.length))
2881
- : devPrompt.slice(0, Math.max(0, devPrompt.length - devActionsPrompt.length)),
2882
- actionsPrompt: devNative ? prodActionsPrompt : devActionsPrompt,
2982
+ frameworkPrompt: requestDevPrompt.slice(0, Math.max(0, requestDevPrompt.length - requestActionsPrompt.length)),
2983
+ actionsPrompt: requestActionsPrompt,
2883
2984
  resources,
2884
2985
  schemaBlock,
2885
2986
  extra,
2886
2987
  modelOverlay,
2887
2988
  runtimeContext,
2888
2989
  });
2889
- return setSystemPromptOnContext(devPrompt +
2990
+ return setSystemPromptOnContext(requestDevPrompt +
2890
2991
  resources +
2891
2992
  schemaBlock +
2892
2993
  extra +
@@ -2913,6 +3014,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2913
3014
  }
2914
3015
  return options?.prepareRequest?.(details);
2915
3016
  },
3017
+ resolveActionSurface: options?.resolveActionSurface,
2916
3018
  skipFilesContext,
2917
3019
  initialToolNames: effectiveInitialToolNames,
2918
3020
  ...(options?.toolLimits ? { toolLimits: options.toolLimits } : {}),
@@ -3085,7 +3187,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
3085
3187
  // just told, and filtering to the full set would only add a
3086
3188
  // tool-search schema with nothing new for it to find.
3087
3189
  return {
3088
- baseSystemPrompt: basePrompt,
3190
+ baseSystemPrompt: filterFrameworkPromptToSurface(basePrompt, prodActions, payload.allowedActionNames),
3089
3191
  actions: buildSubAgentActions(),
3090
3192
  engine,
3091
3193
  model,
@@ -4793,7 +4895,8 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
4793
4895
  // helper expands that owner into the same user/org AsyncLocalStorage
4794
4896
  // context the foreground request uses, so credential and data scoping
4795
4897
  // stay aligned.
4796
- await seedBackgroundAgentRunOwnerContext(event, prepared.runId);
4898
+ const persistedSurface = readPersistedActionSurface(workerBody, "__resolvedActionSurface");
4899
+ await seedBackgroundAgentRunOwnerContext(event, prepared.runId, persistedSurface?.orgId);
4797
4900
  return await invokeAgentChatHandler(event);
4798
4901
  }
4799
4902
  catch (err) {
@@ -27,10 +27,10 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
27
27
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
28
28
  error: any;
29
29
  } | {
30
+ error?: undefined;
30
31
  ok: boolean;
31
32
  key: string;
32
33
  baseUrlKey?: string;
33
34
  scope: AgentEngineApiKeyScope;
34
- error?: undefined;
35
35
  }>>;
36
36
  export {};
@@ -4,6 +4,12 @@ export type AgentRunOwnerContext = {
4
4
  owner: string;
5
5
  anonymous: boolean;
6
6
  name?: string;
7
+ /**
8
+ * Trusted org binding for a cookieless durable worker. Presence matters:
9
+ * `null` means the authenticated foreground request had no org and must not
10
+ * fall back to another membership during worker re-entry.
11
+ */
12
+ orgId?: string | null;
7
13
  };
8
14
  export declare const AGENT_RUN_OWNER_CONTEXT_KEY = "__agentNativeOwnerContext";
9
15
  type AnonymousOwnerResolver = (event: H3Event) => string | null | Promise<string | null>;
@@ -20,7 +26,7 @@ export declare function readAgentRunTimezone(event: H3Event): string | undefined
20
26
  */
21
27
  export declare function readBrowserSessionIdHeader(event: H3Event): string | undefined;
22
28
  export declare function seedAgentRunOwnerContext(event: H3Event, ownerContext: AgentRunOwnerContext): AgentRunOwnerContext;
23
- export declare function seedBackgroundAgentRunOwnerContext(event: H3Event, runId: string): Promise<AgentRunOwnerContext | null>;
29
+ export declare function seedBackgroundAgentRunOwnerContext(event: H3Event, runId: string, orgId?: string | null): Promise<AgentRunOwnerContext | null>;
24
30
  export declare function resolveAgentRunOwnerContext(event: H3Event, options?: {
25
31
  anonymousOwner?: AnonymousOwnerResolver;
26
32
  }): Promise<AgentRunOwnerContext>;
@@ -67,13 +67,17 @@ export function seedAgentRunOwnerContext(event, ownerContext) {
67
67
  ownerContext;
68
68
  return ownerContext;
69
69
  }
70
- export async function seedBackgroundAgentRunOwnerContext(event, runId) {
70
+ export async function seedBackgroundAgentRunOwnerContext(event, runId, orgId) {
71
71
  try {
72
72
  const { getRunOwnerEmail } = await import("../agent/run-store.js");
73
73
  const owner = await getRunOwnerEmail(runId);
74
74
  if (!owner)
75
75
  return null;
76
- return seedAgentRunOwnerContext(event, { owner, anonymous: false });
76
+ return seedAgentRunOwnerContext(event, {
77
+ owner,
78
+ anonymous: false,
79
+ ...(orgId !== undefined ? { orgId } : {}),
80
+ });
77
81
  }
78
82
  catch {
79
83
  return null;
@@ -105,6 +109,9 @@ export async function resolveAgentRunOwnerContext(event, options = {}) {
105
109
  });
106
110
  }
107
111
  export async function resolveAgentRunOrgId(options) {
112
+ if (Object.prototype.hasOwnProperty.call(options.ownerContext, "orgId")) {
113
+ return normalizeId(options.ownerContext.orgId);
114
+ }
108
115
  let resolvedOrgId;
109
116
  if (options.resolveOrgId) {
110
117
  resolvedOrgId = normalizeId(await options.resolveOrgId(options.event));
@@ -31,6 +31,9 @@ export interface AgentTeamRunPayload {
31
31
  parentRunId?: string;
32
32
  /** Display name for the sub-agent tab. */
33
33
  name?: string;
34
+ /** Exact action registry captured when the parent spawned this task. Older
35
+ * queue rows omit it and retain their original unscoped behavior. */
36
+ allowedActionNames?: string[];
34
37
  /** Logical-turn id, stable across continuation chunks so durable assistant
35
38
  * messages fold into one. */
36
39
  turnId: string;
@@ -17,7 +17,7 @@
17
17
  import { AsyncLocalStorage } from "node:async_hooks";
18
18
  import { applyAgentTextEventToBuffer } from "../a2a/response-text.js";
19
19
  import { resolveMainChatMaxOutputTokens } from "../agent/engine/output-tokens.js";
20
- import { actionsToEngineTools, filterInitialEngineTools, resolveAgentRequestReasoningEffort, } from "../agent/production-agent.js";
20
+ import { actionsToEngineTools, filterActionsByAllowedNames, filterInitialEngineTools, readPersistedAllowedActionNames, resolveAgentRequestReasoningEffort, } from "../agent/production-agent.js";
21
21
  import { runAgentLoop, appendAgentLoopContinuation, } from "../agent/production-agent.js";
22
22
  import { abortRun, getActiveRunForThreadAsync, getRun, startRun, subscribeToRun, } from "../agent/run-manager.js";
23
23
  import { getRunEventsSince } from "../agent/run-store.js";
@@ -31,7 +31,7 @@ import { describeDbError } from "../db/client.js";
31
31
  import { resolveOrgIdForEmail } from "../org/context.js";
32
32
  import { completeRun as completeProgressRun, startRun as startProgressRun, updateRunProgress, } from "../progress/registry.js";
33
33
  import { enqueueAgentTeamRun, claimAgentTeamRun, touchAgentTeamRun, bumpAgentTeamContinuation, completeAgentTeamRun, getAgentTeamRunDispatchState, listActiveAgentTeamTaskIdsForOwner, MAX_AGENT_TEAM_CONTINUATIONS, MAX_AGENT_TEAM_NO_PROGRESS_CONTINUATIONS, RUN_DISPATCH_STUCK_AFTER_MS, RUN_PROCESSING_STUCK_AFTER_MS, } from "./agent-teams-run-queue.js";
34
- import { getRequestUserEmail, runWithRequestContext, } from "./request-context.js";
34
+ import { getRequestOrgId, getRequestRunContext, getRequestUserEmail, hasRequestContext, runWithRequestContext, } from "./request-context.js";
35
35
  import { fireInternalDispatch } from "./self-dispatch.js";
36
36
  /**
37
37
  * Ambient delegation depth for the agent whose run is currently executing.
@@ -972,12 +972,17 @@ export async function spawnTask(opts) {
972
972
  // (integrations/webhook-handler.ts). Execution happens in `processAgentTeamRun`,
973
973
  // invoked by the `/_agent-native/agent-teams/_process-run` route mounted
974
974
  // inside the agent-chat plugin (where the action/prompt/engine closures live).
975
- let orgId = null;
976
- try {
977
- orgId = (await resolveOrgIdForEmail(opts.ownerEmail)) ?? null;
975
+ let orgId;
976
+ if (hasRequestContext()) {
977
+ orgId = getRequestOrgId() ?? null;
978
978
  }
979
- catch {
980
- orgId = null;
979
+ else {
980
+ try {
981
+ orgId = await resolveOrgIdForEmail(opts.ownerEmail);
982
+ }
983
+ catch {
984
+ orgId = null;
985
+ }
981
986
  }
982
987
  const payload = {
983
988
  description: opts.description,
@@ -986,6 +991,9 @@ export async function spawnTask(opts) {
986
991
  ...(opts.parentThreadId ? { parentThreadId: opts.parentThreadId } : {}),
987
992
  ...(opts.parentRunId ? { parentRunId: opts.parentRunId } : {}),
988
993
  ...(opts.name ? { name: opts.name } : {}),
994
+ ...(getRequestRunContext()?.allowedActionNames !== undefined
995
+ ? { allowedActionNames: Object.keys(opts.actions) }
996
+ : {}),
989
997
  // Stable across continuation chunks so the durable assistant message folds.
990
998
  turnId: runId,
991
999
  };
@@ -1171,9 +1179,19 @@ export async function processAgentTeamRun(opts) {
1171
1179
  const claimed = await claimAgentTeamRun(opts.taskId);
1172
1180
  if (!claimed)
1173
1181
  return { ok: true, skipped: "already-claimed-or-missing" };
1182
+ const persistedAllowedActionNames = readPersistedAllowedActionNames(claimed.payload);
1183
+ const payload = persistedAllowedActionNames === undefined
1184
+ ? claimed.payload
1185
+ : {
1186
+ ...claimed.payload,
1187
+ allowedActionNames: persistedAllowedActionNames,
1188
+ };
1174
1189
  return await runWithRequestContext({
1175
1190
  userEmail: claimed.ownerEmail ?? undefined,
1176
1191
  orgId: claimed.orgId ?? undefined,
1192
+ run: persistedAllowedActionNames === undefined
1193
+ ? undefined
1194
+ : { allowedActionNames: persistedAllowedActionNames },
1177
1195
  }, async () => {
1178
1196
  const task = await loadTask(opts.taskId);
1179
1197
  if (!task) {
@@ -1184,13 +1202,18 @@ export async function processAgentTeamRun(opts) {
1184
1202
  await completeAgentTeamRun(opts.taskId, task.status === "completed" ? "done" : "failed");
1185
1203
  return { ok: true, skipped: "task-terminal" };
1186
1204
  }
1187
- const payload = claimed.payload;
1188
1205
  const ownerEmail = claimed.ownerEmail ?? getRequestUserEmail() ?? "";
1189
1206
  const orgId = claimed.orgId;
1190
1207
  const turnId = payload.turnId || taskRunId(opts.taskId);
1191
1208
  let config;
1192
1209
  try {
1193
1210
  config = await opts.resolveConfig({ payload, ownerEmail, orgId });
1211
+ if (persistedAllowedActionNames !== undefined) {
1212
+ config = {
1213
+ ...config,
1214
+ actions: filterActionsByAllowedNames(config.actions, persistedAllowedActionNames),
1215
+ };
1216
+ }
1194
1217
  }
1195
1218
  catch (err) {
1196
1219
  const message = err instanceof Error
@@ -1304,7 +1327,13 @@ export async function processAgentTeamRun(opts) {
1304
1327
  task.currentStep = "";
1305
1328
  }
1306
1329
  };
1307
- await runWithRequestContext({ userEmail: ownerEmail || undefined, orgId: orgId ?? undefined },
1330
+ await runWithRequestContext({
1331
+ userEmail: ownerEmail || undefined,
1332
+ orgId: orgId ?? undefined,
1333
+ run: persistedAllowedActionNames === undefined
1334
+ ? undefined
1335
+ : { allowedActionNames: persistedAllowedActionNames },
1336
+ },
1308
1337
  // Record THIS sub-agent's own delegation depth as the ambient
1309
1338
  // depth for the duration of its agent loop. If a tool call from
1310
1339
  // within the loop reaches `spawnTask` (even with the team tool not
@@ -13,7 +13,7 @@ export { requireEnvKey, type MissingKeyResponse } from "./missing-key.js";
13
13
  export { assertCurrentRequestUserIsOrgAdmin, currentRequestUserIsOrgAdmin, } from "./org-admin.js";
14
14
  export { verifyCaptcha, type CaptchaVerifyResult } from "./captcha.js";
15
15
  export { getLocaleInitScript, parseAcceptLanguage, resolveLocaleFromRequest, type LocaleInitScriptOptions, type ResolveLocaleFromRequestOptions, type ResolvedRequestLocale, } from "../localization/server.js";
16
- export { createProductionAgentHandler, type ActionEntry, type ScriptEntry, type ProductionAgentOptions, type ActionTool, type ScriptTool, type AgentMessage, type AgentChatRequest, type AgentChatEvent, type AgentChatAttachment, type AgentChatReference, type MentionProvider, type MentionProviderItem, type AgentLoopFinalResponseGuard, type AgentLoopFinalResponseGuardContext, type AgentLoopFinalResponseGuardResult, type AgentLoopToolCallSummary, type AgentLoopToolResultSummary, } from "../agent/index.js";
16
+ export { createProductionAgentHandler, type ActionEntry, type ScriptEntry, type ProductionAgentOptions, type AgentActionSurface, type AgentActionSurfaceDetails, type ActionTool, type ScriptTool, type AgentMessage, type AgentChatRequest, type AgentChatEvent, type AgentChatAttachment, type AgentChatReference, type MentionProvider, type MentionProviderItem, type AgentLoopFinalResponseGuard, type AgentLoopFinalResponseGuardContext, type AgentLoopFinalResponseGuardResult, type AgentLoopToolCallSummary, type AgentLoopToolResultSummary, } from "../agent/index.js";
17
17
  export { actionsToEngineTools, executeAgentToolCall, getOwnerActiveApiKey, getOwnerApiKeyForEngine, resolveOwnerEngineApiKey, runAgentLoop, type AgentToolCallExecutionResult, type ExecuteAgentToolCallOptions, type ResolvedOwnerApiKey, } from "../agent/production-agent.js";
18
18
  export { mountRealtimeVoiceRoutes, realtimeVoiceSafetyIdentifier, REALTIME_VOICE_MAX_SDP_BYTES, REALTIME_VOICE_MAX_TOOL_BODY_BYTES, REALTIME_VOICE_MAX_TOOL_OUTPUT_CHARS, REALTIME_VOICE_SESSION_PATH, REALTIME_VOICE_TOOL_PATH, type MountRealtimeVoiceRoutesOptions, type RealtimeVoiceRequestContext, type RealtimeVoiceToolExecutionRequest, type RealtimeVoiceToolExecutionResult, } from "./realtime-voice.js";
19
19
  export { getStoredModelForEngine, resolveEngine, } from "../agent/engine/index.js";
@@ -59,6 +59,8 @@ export interface RequestRunContext {
59
59
  engine?: import("../agent/engine/types.js").AgentEngine;
60
60
  /** Model name for this run (set by onEngineResolved). */
61
61
  model?: string;
62
+ /** Request-authorized action names exposed to this agent run. */
63
+ allowedActionNames?: readonly string[];
62
64
  /**
63
65
  * True when this run is executing inside the durable background-function
64
66
  * worker (the `_process-run` self-dispatch), not the synchronous foreground
@@ -175,6 +177,11 @@ export interface RequestContext {
175
177
  run?: RequestRunContext;
176
178
  }
177
179
  type RequestContextObserver = (ctx: RequestContext) => void;
180
+ /**
181
+ * Authorization state must never use the shared-stack compatibility fallback:
182
+ * overlapping async requests are only isolated by native AsyncLocalStorage.
183
+ */
184
+ export declare function assertRequestActionSurfaceIsolation(): void;
178
185
  /**
179
186
  * Register a callback fired every time `runWithRequestContext` enters a new
180
187
  * scope. The hook runs INSIDE the AsyncLocalStorage scope, so observability