@superblocksteam/gateway 2.0.177-next.0 → 2.0.178-next.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 (221) hide show
  1. package/README.md +52 -19
  2. package/dist/agents/hosted-boundary.d.ts +36 -0
  3. package/dist/agents/hosted-boundary.d.ts.map +1 -0
  4. package/dist/agents/hosted-boundary.js +66 -0
  5. package/dist/agents/hosted-boundary.js.map +1 -0
  6. package/dist/agents/resolve-orchestrator-url.d.ts +8 -0
  7. package/dist/agents/resolve-orchestrator-url.d.ts.map +1 -1
  8. package/dist/agents/resolve-orchestrator-url.js +5 -0
  9. package/dist/agents/resolve-orchestrator-url.js.map +1 -1
  10. package/dist/capabilities/integration-metadata.d.ts.map +1 -1
  11. package/dist/capabilities/integration-metadata.js +12 -1
  12. package/dist/capabilities/integration-metadata.js.map +1 -1
  13. package/dist/capabilities/lifecycle.d.ts +1 -6
  14. package/dist/capabilities/lifecycle.d.ts.map +1 -1
  15. package/dist/capabilities/lifecycle.js +339 -21
  16. package/dist/capabilities/lifecycle.js.map +1 -1
  17. package/dist/capabilities/live-state-attaches.d.ts +28 -0
  18. package/dist/capabilities/live-state-attaches.d.ts.map +1 -1
  19. package/dist/capabilities/live-state-attaches.js +33 -0
  20. package/dist/capabilities/live-state-attaches.js.map +1 -1
  21. package/dist/capabilities/query-integration.d.ts.map +1 -1
  22. package/dist/capabilities/query-integration.js +12 -1
  23. package/dist/capabilities/query-integration.js.map +1 -1
  24. package/dist/capabilities/tool-permission-reply.d.ts.map +1 -1
  25. package/dist/capabilities/tool-permission-reply.js.map +1 -1
  26. package/dist/capabilities/types.d.ts +3 -4
  27. package/dist/capabilities/types.d.ts.map +1 -1
  28. package/dist/capabilities/types.js.map +1 -1
  29. package/dist/capture/browser-contract.d.ts +1 -18
  30. package/dist/capture/browser-contract.d.ts.map +1 -1
  31. package/dist/capture/browser-contract.js +1 -13
  32. package/dist/capture/browser-contract.js.map +1 -1
  33. package/dist/capture/browser-instructions.d.ts +3 -3
  34. package/dist/capture/browser-instructions.d.ts.map +1 -1
  35. package/dist/capture/browser-instructions.js +4 -5
  36. package/dist/capture/browser-instructions.js.map +1 -1
  37. package/dist/capture/capture-library-probe.d.ts +0 -1
  38. package/dist/capture/capture-library-probe.d.ts.map +1 -1
  39. package/dist/capture/capture-library-probe.js +1 -1
  40. package/dist/capture/capture-library-probe.js.map +1 -1
  41. package/dist/capture/capture-library.d.ts +2 -1
  42. package/dist/capture/capture-library.d.ts.map +1 -1
  43. package/dist/capture/classify-library-paint.d.ts +2 -1
  44. package/dist/capture/classify-library-paint.d.ts.map +1 -1
  45. package/dist/capture/library-parent-script.d.ts +3 -2
  46. package/dist/capture/library-parent-script.d.ts.map +1 -1
  47. package/dist/capture/mode.d.ts +2 -3
  48. package/dist/capture/mode.d.ts.map +1 -1
  49. package/dist/capture/mode.js +2 -3
  50. package/dist/capture/mode.js.map +1 -1
  51. package/dist/config.d.ts +21 -1
  52. package/dist/config.d.ts.map +1 -1
  53. package/dist/config.js +3 -0
  54. package/dist/config.js.map +1 -1
  55. package/dist/debug.js.map +1 -1
  56. package/dist/deps.d.ts +3 -3
  57. package/dist/health/readiness.d.ts +2 -1
  58. package/dist/health/readiness.d.ts.map +1 -1
  59. package/dist/http/main.d.ts +3 -0
  60. package/dist/http/main.d.ts.map +1 -0
  61. package/dist/http/main.js +11 -0
  62. package/dist/http/main.js.map +1 -0
  63. package/dist/http/serve.d.ts +26 -0
  64. package/dist/http/serve.d.ts.map +1 -0
  65. package/dist/http/serve.js +298 -0
  66. package/dist/http/serve.js.map +1 -0
  67. package/dist/integrations/filters.d.ts.map +1 -1
  68. package/dist/integrations/filters.js +1 -16
  69. package/dist/integrations/filters.js.map +1 -1
  70. package/dist/integrations/map.d.ts +0 -5
  71. package/dist/integrations/map.d.ts.map +1 -1
  72. package/dist/integrations/map.js +1 -1
  73. package/dist/integrations/map.js.map +1 -1
  74. package/dist/internal-ingress.d.ts +47 -0
  75. package/dist/internal-ingress.d.ts.map +1 -0
  76. package/dist/internal-ingress.js +90 -0
  77. package/dist/internal-ingress.js.map +1 -0
  78. package/dist/orchestrator/client.d.ts +11 -5
  79. package/dist/orchestrator/client.d.ts.map +1 -1
  80. package/dist/orchestrator/client.js +14 -3
  81. package/dist/orchestrator/client.js.map +1 -1
  82. package/dist/playwright/ensure-chromium.js.map +1 -1
  83. package/dist/preview/capture-screenshot.d.ts +2 -2
  84. package/dist/preview/capture-screenshot.d.ts.map +1 -1
  85. package/dist/preview/capture-screenshot.js +2 -2
  86. package/dist/preview/capture-screenshot.js.map +1 -1
  87. package/dist/process/fault-barrier.d.ts +4 -3
  88. package/dist/process/fault-barrier.d.ts.map +1 -1
  89. package/dist/sabs/app-state.d.ts +2 -13
  90. package/dist/sabs/app-state.d.ts.map +1 -1
  91. package/dist/sabs/app-state.js +7 -2
  92. package/dist/sabs/app-state.js.map +1 -1
  93. package/dist/sabs/awaited-decision.d.ts.map +1 -1
  94. package/dist/sabs/browser-context.d.ts +4 -1
  95. package/dist/sabs/browser-context.d.ts.map +1 -1
  96. package/dist/sabs/browser-context.js +1 -0
  97. package/dist/sabs/browser-context.js.map +1 -1
  98. package/dist/sabs/editor-client-methods.d.ts.map +1 -1
  99. package/dist/sabs/editor-client-methods.js +1 -1
  100. package/dist/sabs/editor-client-methods.js.map +1 -1
  101. package/dist/sabs/editor-socket.d.ts.map +1 -1
  102. package/dist/sabs/editor-socket.js.map +1 -1
  103. package/dist/sabs/session-peer.d.ts +13 -1
  104. package/dist/sabs/session-peer.d.ts.map +1 -1
  105. package/dist/sabs/session-peer.js.map +1 -1
  106. package/dist/sabs/streamed-reply.d.ts.map +1 -1
  107. package/dist/sabs/streamed-reply.js.map +1 -1
  108. package/dist/sabs/turn-collector.d.ts.map +1 -1
  109. package/dist/sabs/turn-collector.js.map +1 -1
  110. package/dist/sabs/websocket-session-peer.d.ts +17 -1
  111. package/dist/sabs/websocket-session-peer.d.ts.map +1 -1
  112. package/dist/sabs/websocket-session-peer.js +89 -15
  113. package/dist/sabs/websocket-session-peer.js.map +1 -1
  114. package/dist/server/client.d.ts +48 -0
  115. package/dist/server/client.d.ts.map +1 -1
  116. package/dist/server/client.js +91 -173
  117. package/dist/server/client.js.map +1 -1
  118. package/dist/server/identity-reads.d.ts +5 -3
  119. package/dist/server/identity-reads.d.ts.map +1 -1
  120. package/dist/server/identity-reads.js +31 -4
  121. package/dist/server/identity-reads.js.map +1 -1
  122. package/dist/start.d.ts +5 -1
  123. package/dist/start.d.ts.map +1 -1
  124. package/dist/start.js +23 -9
  125. package/dist/start.js.map +1 -1
  126. package/dist/stores/memory.d.ts.map +1 -1
  127. package/dist/stores/types.d.ts +2 -1
  128. package/dist/stores/types.d.ts.map +1 -1
  129. package/dist/telemetry/mcp-client.d.ts +2 -1
  130. package/dist/telemetry/mcp-client.d.ts.map +1 -1
  131. package/dist/telemetry/mcp-client.js.map +1 -1
  132. package/dist/telemetry/mcp-usage.d.ts +22 -0
  133. package/dist/telemetry/mcp-usage.d.ts.map +1 -0
  134. package/dist/telemetry/mcp-usage.js +102 -0
  135. package/dist/telemetry/mcp-usage.js.map +1 -0
  136. package/dist/telemetry/metrics.d.ts +9 -0
  137. package/dist/telemetry/metrics.d.ts.map +1 -1
  138. package/dist/telemetry/metrics.js +21 -0
  139. package/dist/telemetry/metrics.js.map +1 -1
  140. package/dist/telemetry/runtime.d.ts +2 -1
  141. package/dist/telemetry/runtime.d.ts.map +1 -1
  142. package/dist/telemetry/runtime.js +18 -5
  143. package/dist/telemetry/runtime.js.map +1 -1
  144. package/dist/transports/mcp/admin-tools.d.ts +3 -7
  145. package/dist/transports/mcp/admin-tools.d.ts.map +1 -1
  146. package/dist/transports/mcp/admin-tools.js +9 -82
  147. package/dist/transports/mcp/admin-tools.js.map +1 -1
  148. package/dist/transports/mcp/app-status-html.d.ts +2 -2
  149. package/dist/transports/mcp/app-status-html.d.ts.map +1 -1
  150. package/dist/transports/mcp/app-status-html.js +1 -27
  151. package/dist/transports/mcp/app-status-html.js.map +1 -1
  152. package/dist/transports/mcp/client-presentation.d.ts +10 -13
  153. package/dist/transports/mcp/client-presentation.d.ts.map +1 -1
  154. package/dist/transports/mcp/client-presentation.js +2 -14
  155. package/dist/transports/mcp/client-presentation.js.map +1 -1
  156. package/dist/transports/mcp/decision-elicitation.js +23 -1
  157. package/dist/transports/mcp/decision-elicitation.js.map +1 -1
  158. package/dist/transports/mcp/dispatch-probe.js.map +1 -1
  159. package/dist/transports/mcp/editor-document-probe.js.map +1 -1
  160. package/dist/transports/mcp/editor-integration-setup-url.d.ts +0 -1
  161. package/dist/transports/mcp/editor-integration-setup-url.d.ts.map +1 -1
  162. package/dist/transports/mcp/editor-integration-setup-url.js +0 -3
  163. package/dist/transports/mcp/editor-integration-setup-url.js.map +1 -1
  164. package/dist/transports/mcp/format-tool-content.js +1 -1
  165. package/dist/transports/mcp/format-tool-content.js.map +1 -1
  166. package/dist/transports/mcp/instructions/tools/build-app.d.ts +2 -3
  167. package/dist/transports/mcp/instructions/tools/build-app.d.ts.map +1 -1
  168. package/dist/transports/mcp/instructions/tools/build-app.js +5 -11
  169. package/dist/transports/mcp/instructions/tools/build-app.js.map +1 -1
  170. package/dist/transports/mcp/instructions/tools/check-app-progress.d.ts.map +1 -1
  171. package/dist/transports/mcp/instructions/tools/check-app-progress.js +1 -25
  172. package/dist/transports/mcp/instructions/tools/check-app-progress.js.map +1 -1
  173. package/dist/transports/mcp/instructions/tools/check-publish-progress.d.ts +1 -2
  174. package/dist/transports/mcp/instructions/tools/check-publish-progress.d.ts.map +1 -1
  175. package/dist/transports/mcp/instructions/tools/check-publish-progress.js +2 -11
  176. package/dist/transports/mcp/instructions/tools/check-publish-progress.js.map +1 -1
  177. package/dist/transports/mcp/instructions/tools/copy.d.ts +1 -8
  178. package/dist/transports/mcp/instructions/tools/copy.d.ts.map +1 -1
  179. package/dist/transports/mcp/instructions/tools/copy.js +4 -28
  180. package/dist/transports/mcp/instructions/tools/copy.js.map +1 -1
  181. package/dist/transports/mcp/instructions/tools/create-integration.d.ts +1 -2
  182. package/dist/transports/mcp/instructions/tools/create-integration.d.ts.map +1 -1
  183. package/dist/transports/mcp/instructions/tools/create-integration.js +4 -8
  184. package/dist/transports/mcp/instructions/tools/create-integration.js.map +1 -1
  185. package/dist/transports/mcp/instructions/tools/edit-app.js +2 -2
  186. package/dist/transports/mcp/instructions/tools/edit-app.js.map +1 -1
  187. package/dist/transports/mcp/instructions/tools/get-app.d.ts.map +1 -1
  188. package/dist/transports/mcp/instructions/tools/get-app.js +1 -23
  189. package/dist/transports/mcp/instructions/tools/get-app.js.map +1 -1
  190. package/dist/transports/mcp/instructions/tools/index.d.ts.map +1 -1
  191. package/dist/transports/mcp/instructions/tools/index.js +0 -4
  192. package/dist/transports/mcp/instructions/tools/index.js.map +1 -1
  193. package/dist/transports/mcp/instructions/tools/publish-app.d.ts +1 -2
  194. package/dist/transports/mcp/instructions/tools/publish-app.d.ts.map +1 -1
  195. package/dist/transports/mcp/instructions/tools/publish-app.js +1 -10
  196. package/dist/transports/mcp/instructions/tools/publish-app.js.map +1 -1
  197. package/dist/transports/mcp/instructions/tools/start-app.d.ts +1 -2
  198. package/dist/transports/mcp/instructions/tools/start-app.d.ts.map +1 -1
  199. package/dist/transports/mcp/instructions/tools/start-app.js +3 -3
  200. package/dist/transports/mcp/instructions/tools/start-app.js.map +1 -1
  201. package/dist/transports/mcp/mount.d.ts +8 -15
  202. package/dist/transports/mcp/mount.d.ts.map +1 -1
  203. package/dist/transports/mcp/mount.js +233 -206
  204. package/dist/transports/mcp/mount.js.map +1 -1
  205. package/dist/transports/mcp/plan-approval.d.ts.map +1 -1
  206. package/dist/transports/mcp/plan-approval.js.map +1 -1
  207. package/dist/transports/mcp/tool-permissions.d.ts +30 -0
  208. package/dist/transports/mcp/tool-permissions.d.ts.map +1 -0
  209. package/dist/transports/mcp/tool-permissions.js +39 -0
  210. package/dist/transports/mcp/tool-permissions.js.map +1 -0
  211. package/package.json +28 -22
  212. package/skills/superblocks-import/SKILL.md +5 -3
  213. package/dist/capture/cowork-editor-url.d.ts +0 -7
  214. package/dist/capture/cowork-editor-url.d.ts.map +0 -1
  215. package/dist/capture/cowork-editor-url.js +0 -12
  216. package/dist/capture/cowork-editor-url.js.map +0 -1
  217. package/dist/transports/mcp/native-browser-presence.d.ts +0 -46
  218. package/dist/transports/mcp/native-browser-presence.d.ts.map +0 -1
  219. package/dist/transports/mcp/native-browser-presence.js +0 -158
  220. package/dist/transports/mcp/native-browser-presence.js.map +0 -1
  221. package/skills/superblocks-build/SKILL.md +0 -59
@@ -1,11 +1,13 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { WebSocket } from "ws";
3
3
  import { AiMode as SharedAiMode, llmConfigFromFlags, } from "@superblocksteam/library-shared/types";
4
- import { createISocketClient, ISocket, SocketHeartbeat, } from "@superblocksteam/shared";
4
+ import { createISocketClient, DEFAULT_NON_GIT_BRANCH, ISocket, SocketHeartbeat, } from "@superblocksteam/shared";
5
+ import { HostedOrchestratorRefusedError, refusingOrchestratorClient, } from "../agents/hosted-boundary.js";
5
6
  import { canonicalizeOrchestratorBaseUrl, orchestratorUrlDependsOnProfile, pickOrchestratorBaseUrl, } from "../agents/resolve-orchestrator-url.js";
6
7
  import { gatewayDebug } from "../debug.js";
7
8
  import { resolveAppEditorProfileKey, } from "../integrations/profile-key.js";
8
9
  import { resolveProfileForApplication } from "../integrations/resolve-profile.js";
10
+ import { internalIngress } from "../internal-ingress.js";
9
11
  import { HttpOrchestratorClient, } from "../orchestrator/client.js";
10
12
  import { recordCheckpointOutcome, recordIntegrationProfileResolution, } from "../telemetry/metrics.js";
11
13
  import { sanitizeAgentFacingText } from "./agent-facing-text.js";
@@ -17,6 +19,18 @@ import { appendRecentToolRun, buildRecentToolRun } from "./recent-tool-runs.js";
17
19
  import { PromptNotSentError, } from "./session-peer.js";
18
20
  import { DEFAULT_SETTLE_MS, TurnCollector } from "./turn-collector.js";
19
21
  const RELEASE_TURN_LOCK_METHOD = "editor.releaseTurnLock";
22
+ /**
23
+ * The branch an edit-mode SDK API run fetches its code from. The server only
24
+ * lets the session's edit token read code on a named branch, so this always
25
+ * names one: the branch the server opened the live edit on, sent as the server
26
+ * named it, else the branch that was picked. The server's branch wins because
27
+ * connect can open a different branch than the one picked (for example main,
28
+ * when another user holds the picked branch), and the runs must test the code
29
+ * being edited.
30
+ */
31
+ function sdkApiRunBranch(held) {
32
+ return held.liveEditBranch || held.branchName || DEFAULT_NON_GIT_BRANCH;
33
+ }
20
34
  function editorStructureScopeKey(applicationId, branch) {
21
35
  return `${applicationId}\u0000${branch?.trim() ?? ""}`;
22
36
  }
@@ -590,7 +604,9 @@ function decisionFields(decision) {
590
604
  return decision ? { decision } : {};
591
605
  }
592
606
  async function attempt(url, timeoutMs, onSocketError) {
593
- const socket = new WebSocket(url, GATEWAY_PROTOCOL);
607
+ const socket = new WebSocket(url, GATEWAY_PROTOCOL, {
608
+ createConnection: internalIngress.createConnection(url),
609
+ });
594
610
  return await new Promise((resolve, reject) => {
595
611
  const timer = setTimeout(() => {
596
612
  socket.terminate();
@@ -777,7 +793,7 @@ export class WebSocketSessionPeer {
777
793
  editorStructureByScope = new Map();
778
794
  /** Facts about an application that outlive any one turn. */
779
795
  appState;
780
- constructor(options = {}) {
796
+ constructor(options) {
781
797
  this.options = options;
782
798
  this.appState =
783
799
  options.appState ??
@@ -959,6 +975,10 @@ export class WebSocketSessionPeer {
959
975
  : {}),
960
976
  };
961
977
  }
978
+ anyTurnRunning() {
979
+ return (this.appState.hasPendingStart() ||
980
+ [...this.turns.values()].some((turn) => !turn.finished));
981
+ }
962
982
  clearPendingPlan(applicationId) {
963
983
  this.appState.clearPending(applicationId);
964
984
  }
@@ -1009,6 +1029,7 @@ export class WebSocketSessionPeer {
1009
1029
  held.organizationId = input.organizationId;
1010
1030
  }
1011
1031
  held.sessionToken = input.sessionToken;
1032
+ held.liveEditBranch = input.liveEditBranch;
1012
1033
  try {
1013
1034
  await this.synchronizeChatState(held, input.sessionToken);
1014
1035
  await this.resolveHeldProfileKey(held);
@@ -1257,6 +1278,7 @@ export class WebSocketSessionPeer {
1257
1278
  held.organizationId = input.organizationId;
1258
1279
  }
1259
1280
  held.sessionToken = input.sessionToken;
1281
+ held.liveEditBranch = input.liveEditBranch;
1260
1282
  await beforePromptDeadline(this.resolveHeldProfileKey(held), deadline, input.signal);
1261
1283
  await beforePromptDeadline(this.resolveHeldOrchestrator(held), deadline, input.signal);
1262
1284
  }
@@ -1452,6 +1474,7 @@ export class WebSocketSessionPeer {
1452
1474
  mode: input.mode === "BUILD" ? SharedAiMode.BUILD : SharedAiMode.PLAN,
1453
1475
  }),
1454
1476
  prompt: input.prompt,
1477
+ mcpClientName: input.mcpClientName,
1455
1478
  promptContext: {
1456
1479
  attachments: input.attachments ?? [],
1457
1480
  entities: [],
@@ -2452,6 +2475,7 @@ export class WebSocketSessionPeer {
2452
2475
  carryOver(fresh, previous) {
2453
2476
  fresh.apiKey = previous.apiKey;
2454
2477
  fresh.branchName = previous.branchName;
2478
+ fresh.liveEditBranch = previous.liveEditBranch;
2455
2479
  fresh.isFactsEnabled = previous.isFactsEnabled;
2456
2480
  fresh.llmConfig = previous.llmConfig;
2457
2481
  fresh.orchestrator = previous.orchestrator;
@@ -2619,7 +2643,20 @@ export class WebSocketSessionPeer {
2619
2643
  ? normalizeCheckpointWarning(result?.warning)
2620
2644
  : undefined;
2621
2645
  const captureCheckpointScreenshot = this.options.captureCheckpointScreenshot;
2622
- if (commitId && captureCheckpointScreenshot) {
2646
+ const previewBlocked = commitId !== undefined &&
2647
+ captureCheckpointScreenshot !== undefined &&
2648
+ this.hostedPreviewBlocked(input.held);
2649
+ if (previewBlocked) {
2650
+ // The preview picks the org's agents itself, so loading it here would
2651
+ // run the app's on-load APIs against the customer's agent from our
2652
+ // control plane.
2653
+ console.warn("gateway checkpoint screenshot skipped", {
2654
+ applicationId: input.held.applicationId,
2655
+ commitId,
2656
+ reason: "hosted_customer_agent",
2657
+ });
2658
+ }
2659
+ if (commitId && captureCheckpointScreenshot && !previewBlocked) {
2623
2660
  const screenshotTask = (async () => {
2624
2661
  const budgetMs = this.options.checkpointScreenshotTimeoutMs ??
2625
2662
  DEFAULT_CHECKPOINT_SCREENSHOT_TIMEOUT_MS;
@@ -3666,7 +3703,7 @@ export class WebSocketSessionPeer {
3666
3703
  return {
3667
3704
  apiKey: held.apiKey,
3668
3705
  applicationId: held.applicationId,
3669
- branchName: held.branchName,
3706
+ branchName: sdkApiRunBranch(held),
3670
3707
  organizationId: held.organizationId,
3671
3708
  orchestrator: held.orchestrator,
3672
3709
  profileKey: held.profileKey,
@@ -3696,6 +3733,16 @@ export class WebSocketSessionPeer {
3696
3733
  }
3697
3734
  return this.buildHeldBrowserContext(held);
3698
3735
  }
3736
+ /**
3737
+ * Whether the hosted Platform MCP must keep this session's app out of any
3738
+ * browser it runs. A hosted session has an agent URL only when the org's
3739
+ * agent is one Superblocks runs, so a session without one (refused, or not
3740
+ * discovered) fails closed. The CLI runs on the person's own machine and is
3741
+ * never blocked here.
3742
+ */
3743
+ hostedPreviewBlocked(held) {
3744
+ return this.options.hosted && !held.orchestratorUrl;
3745
+ }
3699
3746
  /**
3700
3747
  * Library iframe bootstrap from a held session. Used for Gateway's own
3701
3748
  * live-canvas screenshot even when Clark's in-sandbox Playwright is off.
@@ -3719,12 +3766,18 @@ export class WebSocketSessionPeer {
3719
3766
  });
3720
3767
  return undefined;
3721
3768
  }
3722
- const apiKey = this.options.getAccessToken
3723
- ? await this.options.getAccessToken()
3724
- : held.apiKey;
3769
+ // Hosted, both of these are the /mcp tools token, which the server refuses
3770
+ // when the orchestrator forwards it. Leaving the key out makes the preview
3771
+ // send the session token instead, which may read this app's code.
3772
+ const apiKey = this.options.hosted
3773
+ ? undefined
3774
+ : this.options.getAccessToken
3775
+ ? await this.options.getAccessToken()
3776
+ : held.apiKey;
3725
3777
  return buildBrowserContext({
3726
3778
  ...(apiKey ? { apiKey } : {}),
3727
3779
  applicationId: held.applicationId,
3780
+ branchName: sdkApiRunBranch(held),
3728
3781
  liveEditUrl: held.liveEdit.url,
3729
3782
  orchestratorUrl: held.orchestratorUrl,
3730
3783
  organizationId: held.organizationId,
@@ -3896,14 +3949,35 @@ export class WebSocketSessionPeer {
3896
3949
  });
3897
3950
  return;
3898
3951
  }
3899
- const orchestratorUrl = pickOrchestratorBaseUrl({
3900
- agentType: inventory.agentType,
3901
- agents: inventory.agents,
3902
- controlPlaneUrl: inventory.controlPlaneUrl,
3903
- profileKey,
3904
- });
3952
+ let orchestratorUrl;
3953
+ try {
3954
+ orchestratorUrl = pickOrchestratorBaseUrl({
3955
+ agentType: inventory.agentType,
3956
+ agents: inventory.agents,
3957
+ controlPlaneUrl: inventory.controlPlaneUrl,
3958
+ hosted: this.options.hosted,
3959
+ profileKey,
3960
+ });
3961
+ }
3962
+ catch (error) {
3963
+ if (!(error instanceof HostedOrchestratorRefusedError)) {
3964
+ throw error;
3965
+ }
3966
+ // The turn still runs, so Clark can build and hear why its API runs
3967
+ // fail. No agent URL is kept, so none reaches the sandbox browser.
3968
+ held.orchestrator = refusingOrchestratorClient(error);
3969
+ delete held.orchestratorUrl;
3970
+ held.orchestratorAgentType = inventory.agentType;
3971
+ delete held.orchestratorStale;
3972
+ console.warn("gateway refused orchestrator for hosted session", {
3973
+ applicationId: held.applicationId,
3974
+ organizationId: held.organizationId,
3975
+ reason: error.reason,
3976
+ });
3977
+ return;
3978
+ }
3905
3979
  held.orchestratorUrl = orchestratorUrl;
3906
- held.orchestrator = new HttpOrchestratorClient(orchestratorUrl, undefined, this.options.getAccessToken);
3980
+ held.orchestrator = new HttpOrchestratorClient(orchestratorUrl, this.options.hosted, undefined, this.options.getAccessToken);
3907
3981
  held.orchestratorAgentType = inventory.agentType;
3908
3982
  delete held.orchestratorStale;
3909
3983
  console.error("gateway resolved orchestrator url", {