@superblocksteam/gateway 2.0.0-SNAPSHOT.1d4c72c0ab174c21

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 (248) hide show
  1. package/LICENSE.txt +87 -0
  2. package/README.md +291 -0
  3. package/dist/agents/resolve-orchestrator-url.d.ts +22 -0
  4. package/dist/agents/resolve-orchestrator-url.js +38 -0
  5. package/dist/agents/resolve-orchestrator-url.js.map +1 -0
  6. package/dist/capabilities/integration-metadata.d.ts +28 -0
  7. package/dist/capabilities/integration-metadata.js +174 -0
  8. package/dist/capabilities/integration-metadata.js.map +1 -0
  9. package/dist/capabilities/lifecycle.d.ts +93 -0
  10. package/dist/capabilities/lifecycle.js +3450 -0
  11. package/dist/capabilities/lifecycle.js.map +1 -0
  12. package/dist/capabilities/query-integration.d.ts +14 -0
  13. package/dist/capabilities/query-integration.js +172 -0
  14. package/dist/capabilities/query-integration.js.map +1 -0
  15. package/dist/capabilities/source-files-archive.d.ts +11 -0
  16. package/dist/capabilities/source-files-archive.js +54 -0
  17. package/dist/capabilities/source-files-archive.js.map +1 -0
  18. package/dist/capabilities/types.d.ts +542 -0
  19. package/dist/capabilities/types.js +86 -0
  20. package/dist/capabilities/types.js.map +1 -0
  21. package/dist/capture/browser-contract.d.ts +46 -0
  22. package/dist/capture/browser-contract.js +34 -0
  23. package/dist/capture/browser-contract.js.map +1 -0
  24. package/dist/capture/browser-instructions.d.ts +10 -0
  25. package/dist/capture/browser-instructions.js +18 -0
  26. package/dist/capture/browser-instructions.js.map +1 -0
  27. package/dist/capture/capture-library-probe.d.ts +55 -0
  28. package/dist/capture/capture-library-probe.js +177 -0
  29. package/dist/capture/capture-library-probe.js.map +1 -0
  30. package/dist/capture/capture-library.d.ts +52 -0
  31. package/dist/capture/capture-library.js +249 -0
  32. package/dist/capture/capture-library.js.map +1 -0
  33. package/dist/capture/classify-library-paint.d.ts +21 -0
  34. package/dist/capture/classify-library-paint.js +13 -0
  35. package/dist/capture/classify-library-paint.js.map +1 -0
  36. package/dist/capture/host-mcp-scan.d.ts +16 -0
  37. package/dist/capture/host-mcp-scan.js +64 -0
  38. package/dist/capture/host-mcp-scan.js.map +1 -0
  39. package/dist/capture/library-parent-script.d.ts +35 -0
  40. package/dist/capture/library-parent-script.js +82 -0
  41. package/dist/capture/library-parent-script.js.map +1 -0
  42. package/dist/capture/mode.d.ts +29 -0
  43. package/dist/capture/mode.js +65 -0
  44. package/dist/capture/mode.js.map +1 -0
  45. package/dist/config.d.ts +148 -0
  46. package/dist/config.js +111 -0
  47. package/dist/config.js.map +1 -0
  48. package/dist/debug.d.ts +2 -0
  49. package/dist/debug.js +9 -0
  50. package/dist/debug.js.map +1 -0
  51. package/dist/deps.d.ts +38 -0
  52. package/dist/deps.js +2 -0
  53. package/dist/deps.js.map +1 -0
  54. package/dist/health/readiness.d.ts +99 -0
  55. package/dist/health/readiness.js +202 -0
  56. package/dist/health/readiness.js.map +1 -0
  57. package/dist/index.d.ts +8 -0
  58. package/dist/index.js +8 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/integrations/filters.d.ts +8 -0
  61. package/dist/integrations/filters.js +40 -0
  62. package/dist/integrations/filters.js.map +1 -0
  63. package/dist/integrations/map.d.ts +27 -0
  64. package/dist/integrations/map.js +43 -0
  65. package/dist/integrations/map.js.map +1 -0
  66. package/dist/integrations/profile-key.d.ts +19 -0
  67. package/dist/integrations/profile-key.js +35 -0
  68. package/dist/integrations/profile-key.js.map +1 -0
  69. package/dist/integrations/read-only-postgres-query.d.ts +2 -0
  70. package/dist/integrations/read-only-postgres-query.js +164 -0
  71. package/dist/integrations/read-only-postgres-query.js.map +1 -0
  72. package/dist/main.d.ts +2 -0
  73. package/dist/main.js +5 -0
  74. package/dist/main.js.map +1 -0
  75. package/dist/orchestrator/client.d.ts +62 -0
  76. package/dist/orchestrator/client.js +160 -0
  77. package/dist/orchestrator/client.js.map +1 -0
  78. package/dist/playwright/ensure-chromium.d.ts +24 -0
  79. package/dist/playwright/ensure-chromium.js +60 -0
  80. package/dist/playwright/ensure-chromium.js.map +1 -0
  81. package/dist/preview/capture-screenshot.d.ts +67 -0
  82. package/dist/preview/capture-screenshot.js +179 -0
  83. package/dist/preview/capture-screenshot.js.map +1 -0
  84. package/dist/preview/viewer-url.d.ts +82 -0
  85. package/dist/preview/viewer-url.js +130 -0
  86. package/dist/preview/viewer-url.js.map +1 -0
  87. package/dist/process/fault-barrier.d.ts +55 -0
  88. package/dist/process/fault-barrier.js +113 -0
  89. package/dist/process/fault-barrier.js.map +1 -0
  90. package/dist/sabs/agent-facing-text.d.ts +35 -0
  91. package/dist/sabs/agent-facing-text.js +165 -0
  92. package/dist/sabs/agent-facing-text.js.map +1 -0
  93. package/dist/sabs/app-state.d.ts +126 -0
  94. package/dist/sabs/app-state.js +332 -0
  95. package/dist/sabs/app-state.js.map +1 -0
  96. package/dist/sabs/awaited-decision.d.ts +47 -0
  97. package/dist/sabs/awaited-decision.js +124 -0
  98. package/dist/sabs/awaited-decision.js.map +1 -0
  99. package/dist/sabs/browser-context.d.ts +53 -0
  100. package/dist/sabs/browser-context.js +92 -0
  101. package/dist/sabs/browser-context.js.map +1 -0
  102. package/dist/sabs/editor-client-methods.d.ts +164 -0
  103. package/dist/sabs/editor-client-methods.js +750 -0
  104. package/dist/sabs/editor-client-methods.js.map +1 -0
  105. package/dist/sabs/editor-socket.d.ts +84 -0
  106. package/dist/sabs/editor-socket.js +64 -0
  107. package/dist/sabs/editor-socket.js.map +1 -0
  108. package/dist/sabs/recent-tool-runs.d.ts +14 -0
  109. package/dist/sabs/recent-tool-runs.js +61 -0
  110. package/dist/sabs/recent-tool-runs.js.map +1 -0
  111. package/dist/sabs/session-peer.d.ts +392 -0
  112. package/dist/sabs/session-peer.js +11 -0
  113. package/dist/sabs/session-peer.js.map +1 -0
  114. package/dist/sabs/streamed-reply.d.ts +42 -0
  115. package/dist/sabs/streamed-reply.js +110 -0
  116. package/dist/sabs/streamed-reply.js.map +1 -0
  117. package/dist/sabs/turn-collector.d.ts +169 -0
  118. package/dist/sabs/turn-collector.js +506 -0
  119. package/dist/sabs/turn-collector.js.map +1 -0
  120. package/dist/sabs/websocket-session-peer.d.ts +540 -0
  121. package/dist/sabs/websocket-session-peer.js +3289 -0
  122. package/dist/sabs/websocket-session-peer.js.map +1 -0
  123. package/dist/security/constant-time.d.ts +9 -0
  124. package/dist/security/constant-time.js +13 -0
  125. package/dist/security/constant-time.js.map +1 -0
  126. package/dist/server/client.d.ts +405 -0
  127. package/dist/server/client.js +684 -0
  128. package/dist/server/client.js.map +1 -0
  129. package/dist/server/identity-reads.d.ts +76 -0
  130. package/dist/server/identity-reads.js +209 -0
  131. package/dist/server/identity-reads.js.map +1 -0
  132. package/dist/start.d.ts +24 -0
  133. package/dist/start.js +81 -0
  134. package/dist/start.js.map +1 -0
  135. package/dist/stores/memory.d.ts +42 -0
  136. package/dist/stores/memory.js +121 -0
  137. package/dist/stores/memory.js.map +1 -0
  138. package/dist/stores/types.d.ts +74 -0
  139. package/dist/stores/types.js +11 -0
  140. package/dist/stores/types.js.map +1 -0
  141. package/dist/telemetry/mcp-client.d.ts +22 -0
  142. package/dist/telemetry/mcp-client.js +140 -0
  143. package/dist/telemetry/mcp-client.js.map +1 -0
  144. package/dist/telemetry/metrics.d.ts +41 -0
  145. package/dist/telemetry/metrics.js +103 -0
  146. package/dist/telemetry/metrics.js.map +1 -0
  147. package/dist/telemetry/runtime.d.ts +9 -0
  148. package/dist/telemetry/runtime.js +118 -0
  149. package/dist/telemetry/runtime.js.map +1 -0
  150. package/dist/transports/mcp/admin-tools.d.ts +56 -0
  151. package/dist/transports/mcp/admin-tools.js +252 -0
  152. package/dist/transports/mcp/admin-tools.js.map +1 -0
  153. package/dist/transports/mcp/app-status-html.d.ts +11 -0
  154. package/dist/transports/mcp/app-status-html.js +899 -0
  155. package/dist/transports/mcp/app-status-html.js.map +1 -0
  156. package/dist/transports/mcp/client-presentation.d.ts +16 -0
  157. package/dist/transports/mcp/client-presentation.js +13 -0
  158. package/dist/transports/mcp/client-presentation.js.map +1 -0
  159. package/dist/transports/mcp/cowork-editor-url.d.ts +6 -0
  160. package/dist/transports/mcp/cowork-editor-url.js +10 -0
  161. package/dist/transports/mcp/cowork-editor-url.js.map +1 -0
  162. package/dist/transports/mcp/decision-card-html.d.ts +26 -0
  163. package/dist/transports/mcp/decision-card-html.js +876 -0
  164. package/dist/transports/mcp/decision-card-html.js.map +1 -0
  165. package/dist/transports/mcp/decision-elicitation.d.ts +116 -0
  166. package/dist/transports/mcp/decision-elicitation.js +292 -0
  167. package/dist/transports/mcp/decision-elicitation.js.map +1 -0
  168. package/dist/transports/mcp/dispatch-probe.d.ts +24 -0
  169. package/dist/transports/mcp/dispatch-probe.js +48 -0
  170. package/dist/transports/mcp/dispatch-probe.js.map +1 -0
  171. package/dist/transports/mcp/editor-document-probe.d.ts +4 -0
  172. package/dist/transports/mcp/editor-document-probe.js +35 -0
  173. package/dist/transports/mcp/editor-document-probe.js.map +1 -0
  174. package/dist/transports/mcp/editor-integration-setup-url.d.ts +8 -0
  175. package/dist/transports/mcp/editor-integration-setup-url.js +23 -0
  176. package/dist/transports/mcp/editor-integration-setup-url.js.map +1 -0
  177. package/dist/transports/mcp/format-tool-content.d.ts +20 -0
  178. package/dist/transports/mcp/format-tool-content.js +89 -0
  179. package/dist/transports/mcp/format-tool-content.js.map +1 -0
  180. package/dist/transports/mcp/instructions/index.d.ts +23 -0
  181. package/dist/transports/mcp/instructions/index.js +81 -0
  182. package/dist/transports/mcp/instructions/index.js.map +1 -0
  183. package/dist/transports/mcp/instructions/result.d.ts +18 -0
  184. package/dist/transports/mcp/instructions/result.js +58 -0
  185. package/dist/transports/mcp/instructions/result.js.map +1 -0
  186. package/dist/transports/mcp/instructions/tools/ask-user.d.ts +2 -0
  187. package/dist/transports/mcp/instructions/tools/ask-user.js +17 -0
  188. package/dist/transports/mcp/instructions/tools/ask-user.js.map +1 -0
  189. package/dist/transports/mcp/instructions/tools/check-app-progress.d.ts +3 -0
  190. package/dist/transports/mcp/instructions/tools/check-app-progress.js +75 -0
  191. package/dist/transports/mcp/instructions/tools/check-app-progress.js.map +1 -0
  192. package/dist/transports/mcp/instructions/tools/check-publish-progress.d.ts +3 -0
  193. package/dist/transports/mcp/instructions/tools/check-publish-progress.js +23 -0
  194. package/dist/transports/mcp/instructions/tools/check-publish-progress.js.map +1 -0
  195. package/dist/transports/mcp/instructions/tools/copy.d.ts +14 -0
  196. package/dist/transports/mcp/instructions/tools/copy.js +35 -0
  197. package/dist/transports/mcp/instructions/tools/copy.js.map +1 -0
  198. package/dist/transports/mcp/instructions/tools/create-integration.d.ts +4 -0
  199. package/dist/transports/mcp/instructions/tools/create-integration.js +41 -0
  200. package/dist/transports/mcp/instructions/tools/create-integration.js.map +1 -0
  201. package/dist/transports/mcp/instructions/tools/edit-app.d.ts +2 -0
  202. package/dist/transports/mcp/instructions/tools/edit-app.js +18 -0
  203. package/dist/transports/mcp/instructions/tools/edit-app.js.map +1 -0
  204. package/dist/transports/mcp/instructions/tools/get-app.d.ts +3 -0
  205. package/dist/transports/mcp/instructions/tools/get-app.js +47 -0
  206. package/dist/transports/mcp/instructions/tools/get-app.js.map +1 -0
  207. package/dist/transports/mcp/instructions/tools/get-integration-metadata.d.ts +2 -0
  208. package/dist/transports/mcp/instructions/tools/get-integration-metadata.js +13 -0
  209. package/dist/transports/mcp/instructions/tools/get-integration-metadata.js.map +1 -0
  210. package/dist/transports/mcp/instructions/tools/index.d.ts +7 -0
  211. package/dist/transports/mcp/instructions/tools/index.js +26 -0
  212. package/dist/transports/mcp/instructions/tools/index.js.map +1 -0
  213. package/dist/transports/mcp/instructions/tools/preview-app.d.ts +3 -0
  214. package/dist/transports/mcp/instructions/tools/preview-app.js +14 -0
  215. package/dist/transports/mcp/instructions/tools/preview-app.js.map +1 -0
  216. package/dist/transports/mcp/instructions/tools/publish-app.d.ts +3 -0
  217. package/dist/transports/mcp/instructions/tools/publish-app.js +23 -0
  218. package/dist/transports/mcp/instructions/tools/publish-app.js.map +1 -0
  219. package/dist/transports/mcp/instructions/tools/start-app.d.ts +2 -0
  220. package/dist/transports/mcp/instructions/tools/start-app.js +22 -0
  221. package/dist/transports/mcp/instructions/tools/start-app.js.map +1 -0
  222. package/dist/transports/mcp/instructions/tools/upload-artifact.d.ts +2 -0
  223. package/dist/transports/mcp/instructions/tools/upload-artifact.js +13 -0
  224. package/dist/transports/mcp/instructions/tools/upload-artifact.js.map +1 -0
  225. package/dist/transports/mcp/mcp-app-brand-css.d.ts +1 -0
  226. package/dist/transports/mcp/mcp-app-brand-css.js +180 -0
  227. package/dist/transports/mcp/mcp-app-brand-css.js.map +1 -0
  228. package/dist/transports/mcp/mount.d.ts +22 -0
  229. package/dist/transports/mcp/mount.js +1040 -0
  230. package/dist/transports/mcp/mount.js.map +1 -0
  231. package/dist/transports/mcp/native-browser-presence.d.ts +45 -0
  232. package/dist/transports/mcp/native-browser-presence.js +158 -0
  233. package/dist/transports/mcp/native-browser-presence.js.map +1 -0
  234. package/dist/transports/mcp/plan-approval.d.ts +38 -0
  235. package/dist/transports/mcp/plan-approval.js +175 -0
  236. package/dist/transports/mcp/plan-approval.js.map +1 -0
  237. package/dist/transports/mcp/progress-notifier.d.ts +39 -0
  238. package/dist/transports/mcp/progress-notifier.js +52 -0
  239. package/dist/transports/mcp/progress-notifier.js.map +1 -0
  240. package/dist/transports/mcp/session-directory.d.ts +7 -0
  241. package/dist/transports/mcp/session-directory.js +18 -0
  242. package/dist/transports/mcp/session-directory.js.map +1 -0
  243. package/dist/transports/mcp/tool-names.d.ts +2 -0
  244. package/dist/transports/mcp/tool-names.js +2 -0
  245. package/dist/transports/mcp/tool-names.js.map +1 -0
  246. package/package.json +78 -0
  247. package/skills/superblocks-build/SKILL.md +59 -0
  248. package/skills/superblocks-import/SKILL.md +88 -0
@@ -0,0 +1,540 @@
1
+ import type { LLMProviderConfig } from "@superblocksteam/library-shared/types";
2
+ import type { RecentToolRun } from "../capabilities/types.js";
3
+ import { type OrchestratorClient } from "../orchestrator/client.js";
4
+ import type { SuperblocksServerClient } from "../server/client.js";
5
+ import { AppState } from "./app-state.js";
6
+ import { type ForwardPromptResult, type HoldLiveEditInput, type PromptInput, type RecoveryAction, type RetryAction, type SessionPeer, type StartPromptResult, type TurnDecision, type TurnState, type TurnUpdate } from "./session-peer.js";
7
+ /**
8
+ * Consecutive upgrade rejections from one host before asking where the live
9
+ * edit went. More than one, so an ingress route that briefly answers for a pod
10
+ * that is not up yet is waited out rather than read as a move.
11
+ *
12
+ * Exported so a test can say "kept trying past the point where it asked"
13
+ * without restating the number.
14
+ */
15
+ export declare const HOST_REJECTIONS_BEFORE_RERESOLVE = 2;
16
+ /**
17
+ * How many times one connect may ask where the session went.
18
+ *
19
+ * Bounded because each ask is a Superblocks API round trip, and spaced by a
20
+ * fresh rejection streak so the asks land across the connect window rather
21
+ * than all at the start of it - SABS needs time to notice the pod is gone
22
+ * before it can answer with anywhere different.
23
+ */
24
+ export declare const MAX_RERESOLVES_PER_OPEN = 3;
25
+ /**
26
+ * Grace period between a turn settling and the gateway socket being dropped.
27
+ *
28
+ * Long enough for the checkpoint and any trailing pushes to land, short enough
29
+ * that the sandbox is not held open by a peer with nothing left to do.
30
+ *
31
+ * Must outlast {@link DEFAULT_SETTLE_MS}. The teardown this release leads to is
32
+ * read as a dead live edit by any turn whose `completed` had not settled yet,
33
+ * so releasing inside the settle window would report healthy builds as
34
+ * failures. `releases the socket only after a completed has had its settle
35
+ * window` holds this.
36
+ */
37
+ export declare const DEFAULT_RELEASE_AFTER_TURN_MS = 30000;
38
+ export type WebSocketSessionPeerOptions = {
39
+ /** Shared with the capability layer; created here when omitted. */
40
+ appState?: AppState;
41
+ /**
42
+ * How long a lost liveness beat must stay lost before the turn on that socket
43
+ * is given up on. See {@link DEFAULT_BEAT_LOST_GRACE_MS}.
44
+ */
45
+ beatLostGraceMs?: number;
46
+ connectAttemptTimeoutMs?: number;
47
+ coreModel?: LLMProviderConfig["coreModel"];
48
+ /**
49
+ * How long a turn that died before Superblocks saw it stays worth reporting.
50
+ * See {@link AppState}; injectable so its bounds are testable without waiting
51
+ * them out.
52
+ */
53
+ failedStartTtlMs?: number;
54
+ /** Maximum age of acknowledged work before it is treated as abandoned. */
55
+ pendingStartTtlMs?: number;
56
+ /**
57
+ * Distinct apps holding a dead start at once. See {@link AppState}.
58
+ */
59
+ maxFailedStarts?: number;
60
+ /** Consecutive genuine misses before the beat is declared lost. */
61
+ heartbeatMaxMisses?: number;
62
+ /**
63
+ * Consecutive unanswered beats to tolerate before neither proof of life nor
64
+ * grace may excuse another.
65
+ */
66
+ heartbeatMaxUnanswered?: number;
67
+ /** How often the held socket proves the gateway is still alive. */
68
+ heartbeatMs?: number;
69
+ /** How long a single liveness beat waits before it counts as missed. */
70
+ heartbeatTimeoutMs?: number;
71
+ idleMs?: number;
72
+ keepaliveMs?: number;
73
+ /**
74
+ * Optional test override for the orchestrator HTTP client. Production
75
+ * discovers the agent URL from Server `/users/me` agents per session.
76
+ */
77
+ orchestrator?: OrchestratorClient;
78
+ /**
79
+ * Optional test override for the agent base URL handed to the sandbox
80
+ * browser as `agentUrls`. Production discovers this from Server agents.
81
+ */
82
+ orchestratorUrl?: string;
83
+ /**
84
+ * Integration profile key used when asking the orchestrator for metadata or
85
+ * executing APIs. Defaults to `default`.
86
+ */
87
+ profileKey?: string;
88
+ provider?: LLMProviderConfig["provider"];
89
+ pushWaitMs?: number;
90
+ readyWaitMs?: number;
91
+ /** Grace period between a turn settling and the gateway socket being dropped. */
92
+ releaseAfterTurnMs?: number;
93
+ reattachWaitMs?: number;
94
+ /** How many times one turn goes back for a live edit that keeps dropping it. */
95
+ reconnectAttempts?: number;
96
+ /** How long a turn keeps trying to get back onto its live edit. */
97
+ reconnectGraceMs?: number;
98
+ /**
99
+ * Superblocks API client used to list integrations for Clark mid-build.
100
+ */
101
+ server?: SuperblocksServerClient;
102
+ settleMs?: number;
103
+ /**
104
+ * Opt-in: lets Clark run browser tests during a headless turn. Requires
105
+ * `orchestratorUrl` and `uiBaseUrl`. Off by default so Gateway turns do
106
+ * not launch Chromium inside the live-edit pod.
107
+ */
108
+ testingEnabled?: boolean;
109
+ timeoutMs?: number;
110
+ turnTimeoutMs?: number;
111
+ /** Origin the sandbox app shell should report as its parent window. */
112
+ uiBaseUrl?: string;
113
+ };
114
+ export declare function buildSessionUrl(input: {
115
+ applicationId: string;
116
+ liveEditUrl: string;
117
+ peerId: string;
118
+ userId?: string;
119
+ }): URL;
120
+ export declare class WebSocketSessionPeer implements SessionPeer {
121
+ private readonly options;
122
+ private readonly held;
123
+ private readonly promptStarts;
124
+ /**
125
+ * Every server -> editor method the dev server has called on this peer.
126
+ * Diagnostic only: it answers "did that push ever arrive" without guessing
127
+ * from what the collector chose to keep.
128
+ */
129
+ private readonly inboundMethods;
130
+ /**
131
+ * In-flight opens, so overlapping prompts for one app share a socket instead
132
+ * of each opening their own and orphaning all but the last.
133
+ */
134
+ private readonly connecting;
135
+ /**
136
+ * Turns keyed by application. An entry outlives the call that started it and
137
+ * is kept after finishing so a late poll still learns the outcome; the next
138
+ * prompt for the same app replaces it.
139
+ */
140
+ private readonly turns;
141
+ /** Browser-owned turns observed over an authenticated held session. */
142
+ private readonly observedTurns;
143
+ private readonly editorStructureByScope;
144
+ /** Facts about an application that outlive any one turn. */
145
+ private readonly appState;
146
+ constructor(options?: WebSocketSessionPeerOptions);
147
+ /** The per-application facts this peer writes, for the capability layer. */
148
+ state(): AppState;
149
+ recordPendingStart(input: {
150
+ applicationId: string;
151
+ branch?: string;
152
+ idempotencyKey?: string;
153
+ organizationId: string;
154
+ retryAction?: RetryAction;
155
+ userId: string;
156
+ }): number;
157
+ clearPendingStart(input: {
158
+ applicationId: string;
159
+ branch?: string;
160
+ idempotencyKey?: string;
161
+ organizationId: string;
162
+ pendingStartToken?: number;
163
+ userId: string;
164
+ }): void;
165
+ private waitForPendingTurn;
166
+ /**
167
+ * Plan waiting on human approve/refine for this application, if any.
168
+ */
169
+ pendingPlan(applicationId: string, requestedBranch?: string): {
170
+ branch?: string;
171
+ messageId?: string;
172
+ plan: string;
173
+ title?: string;
174
+ } | undefined;
175
+ /**
176
+ * Full needs_decision payload waiting on a human for this application.
177
+ */
178
+ pendingDecision(applicationId: string, requestedBranch?: string): {
179
+ branch?: string;
180
+ decision: TurnDecision;
181
+ recentRuns?: RecentToolRun[];
182
+ reply: string;
183
+ } | undefined;
184
+ /**
185
+ * Remember a turn that never reached Superblocks. See
186
+ * {@link SessionPeer.recordFailedStart}.
187
+ */
188
+ recordFailedStart(input: {
189
+ applicationId: string;
190
+ branch?: string;
191
+ decision?: TurnDecision;
192
+ generationStatus?: "detached" | "live_edit_terminated" | "needs_decision";
193
+ idempotencyKey?: string;
194
+ organizationId: string;
195
+ pendingStartRequired?: boolean;
196
+ pendingStartToken?: number;
197
+ reason: string;
198
+ recoveryAction?: RecoveryAction;
199
+ revision?: number;
200
+ retryAction?: RetryAction;
201
+ retryable?: false;
202
+ userId: string;
203
+ }): void;
204
+ /**
205
+ * Where this application's turn stands for this caller, read without draining
206
+ * the activity an {@link WebSocketSessionPeer.awaitTurn} poll is owed.
207
+ *
208
+ * A running turn is current. Once it finishes, the newer of that turn and an
209
+ * unscoped failed start wins; explicit branch reads filter before comparing.
210
+ * Revisions preserve that ordering even when both events share a clock tick.
211
+ */
212
+ turnState(input: {
213
+ applicationId: string;
214
+ branch?: string;
215
+ organizationId: string;
216
+ userId: string;
217
+ }): TurnState | undefined;
218
+ clearPendingPlan(applicationId: string): void;
219
+ clearPendingDecision(applicationId: string): void;
220
+ isHeld(applicationId: string): boolean;
221
+ heldContext(applicationId: string): {
222
+ branch?: string;
223
+ } | undefined;
224
+ libraryBrowserContext(applicationId: string, requestedBranch?: string): import("@superblocksteam/library-shared/types").BrowserContext | undefined;
225
+ holdLiveEdit(input: HoldLiveEditInput): Promise<void>;
226
+ release(applicationId: string): void;
227
+ closeAll(): void;
228
+ /**
229
+ * Sends the prompt and waits for Clark's whole turn.
230
+ *
231
+ * Kept for callers with nowhere to poll from — the HTTP capability routes
232
+ * answer a single request — and implemented on the same engine as
233
+ * {@link startPrompt} so there is one turn lifecycle, not two.
234
+ */
235
+ forwardPrompt(input: PromptInput): Promise<ForwardPromptResult>;
236
+ private claimPromptLane;
237
+ startPrompt(input: PromptInput): Promise<StartPromptResult>;
238
+ /**
239
+ * Sends the prompt on a session already holding a subscribed turn, and hands
240
+ * the turn to {@link runTurn} once the session confirms it took it on.
241
+ */
242
+ private sendPrompt;
243
+ private latestTurn;
244
+ private observeEditorEvent;
245
+ private forgetObservedTurn;
246
+ private finishObservedTurn;
247
+ private settleObservedTurn;
248
+ private armObservedTurnRelease;
249
+ private armObservedPostTurnRelease;
250
+ awaitTurn(input: {
251
+ applicationId: string;
252
+ branch?: string;
253
+ organizationId?: string;
254
+ signal?: AbortSignal;
255
+ userId?: string;
256
+ floorMs?: number;
257
+ waitMs: number;
258
+ }): Promise<TurnUpdate>;
259
+ /**
260
+ * Follows the turn to its end on the held session: terminal state, then the
261
+ * checkpoint that commits Clark's draft. Never throws — a caller polling for
262
+ * news has to be told what happened, and the only place left to report a
263
+ * failure is the turn record itself.
264
+ */
265
+ private runTurn;
266
+ private pushWaitMs;
267
+ /**
268
+ * Checks that the session took this prompt on as a turn belonging to this
269
+ * peer, and gives up on it now if it did not.
270
+ *
271
+ * A dev server that predates the gateway role accepts the socket, echoes the
272
+ * role it was offered, and then treats the connection as a library socket: the
273
+ * prompt is acknowledged and Clark's pushes go to the browser binding
274
+ * instead. The turn would spend its whole budget looking detached, and a
275
+ * rollout with one stale sandbox in it would look like Clark hanging. Only a
276
+ * server that bound the turn can name it back, so the missing handle is the
277
+ * mismatch, reported where it is still cheap to act on.
278
+ */
279
+ private assertHeadlessTurnBound;
280
+ /**
281
+ * The field the session reads to decide which turn a call belongs to. Sent on
282
+ * the calls that make up a turn's lifetime, so a turn keeps reporting into
283
+ * this caller across a reattach and no other session can be handed it.
284
+ */
285
+ private turnCorrelator;
286
+ /**
287
+ * Moves a turn onto a fresh socket while the one it is on is still open,
288
+ * because Clark has stopped pushing to it. A turn that was running unseen
289
+ * becomes visible again from where it got to.
290
+ *
291
+ * The socket it came in on is still the better of the two whenever the
292
+ * replacement fails to take the turn over: the sandbox is demonstrably alive,
293
+ * and it is still pushing this turn somewhere. A caller mid-turn has nothing
294
+ * to gain from an exception here, so there is no failure to report but the
295
+ * log line.
296
+ */
297
+ private reattach;
298
+ /**
299
+ * Whether this turn gets another go at its live edit, booking it if so.
300
+ *
301
+ * The allowance is for a live edit that cannot hold a socket, and a turn that
302
+ * has heard from Clark since its last reconnect is not that: it is getting
303
+ * somewhere, so its allowance starts over. Without that, a long build behind
304
+ * a proxy that reaps every few minutes runs out of goes and is failed for the
305
+ * very reason this path exists to survive.
306
+ */
307
+ private takeReconnectAllowance;
308
+ /**
309
+ * Opens a replacement connection and asks the live edit to hand `turn` over
310
+ * to it.
311
+ *
312
+ * Everything that belongs to the session rather than to the socket is carried
313
+ * across first: the credential the claim itself is made with is one of those
314
+ * things, and so is the orchestrator a mid-turn tool call needs. The turn's
315
+ * listener goes on the replacement before the claim, so a push that arrives
316
+ * while it is in flight is not dropped.
317
+ *
318
+ * The turn is claimed before the old socket is let go. The session releases a
319
+ * turn when the connection holding it closes, so closing first leaves the
320
+ * claim nothing to take over; claiming first makes the old socket's close a
321
+ * no-op scoped to a peer that is no longer the owner.
322
+ *
323
+ * Nothing has moved when this fails: the listener is back where it was and
324
+ * the replacement is closed, which leaves the caller free to decide what a
325
+ * socket it could not replace means.
326
+ */
327
+ private takeOverTurn;
328
+ private attemptTakeOver;
329
+ /**
330
+ * Carries onto a replacement socket everything that belongs to the session
331
+ * rather than to the connection: who the turn runs as, what it is allowed to
332
+ * do, and which orchestrator its tool calls go to. A replacement missing any
333
+ * of it is connected but cannot act for the caller.
334
+ */
335
+ private carryOver;
336
+ /**
337
+ * Makes one authenticated read on a freshly opened socket.
338
+ *
339
+ * The dev server trusts a peer's identity per connection and does not carry
340
+ * it over from the peer this one replaced, so it withholds the pushes it
341
+ * scopes to a caller — Clark's step-by-step task status — until the new
342
+ * connection has proven who it is. Reading the chat is the cheapest way to
343
+ * prove it, and it costs a turn nothing when the read fails.
344
+ *
345
+ * Naming `turnId` is what makes this call a reattach rather than just an
346
+ * authenticated read: the session only moves a turn onto a connection that
347
+ * can say which turn it is taking over.
348
+ *
349
+ * Answers whether it worked, because a caller mid-reattach has to decide
350
+ * between two sockets on it.
351
+ */
352
+ private proveIdentity;
353
+ private reconnect;
354
+ private setHeld;
355
+ private recordEditorStructure;
356
+ private publishEditorStructure;
357
+ private currentViewStatus;
358
+ /** Lines this caller has not been handed yet. */
359
+ private drain;
360
+ private wake;
361
+ /** Adds a line to what the next poll on this turn is handed. */
362
+ private note;
363
+ /**
364
+ * Records the outcome of a turn from outside runTurn, and ends the collector
365
+ * waits so runTurn cannot overwrite it with a later timeout of its own. The
366
+ * first outcome written wins: it is the one callers have already been shown.
367
+ */
368
+ private settleTurn;
369
+ /**
370
+ * Mirrors the browser editor's auto-accept: wait for the dev server to flush
371
+ * Clark's files, then commit the draft. Failing to checkpoint costs the caller
372
+ * a committed app, not the generation itself, so this never throws.
373
+ */
374
+ private checkpoint;
375
+ private ensureHeld;
376
+ private connect;
377
+ private assertReadOnlyHoldCurrent;
378
+ /**
379
+ * The liveness beat for one held socket.
380
+ *
381
+ * Everything about pacing, deadlines and when to believe a silence lives in
382
+ * {@link SocketHeartbeat}; what belongs here is only what is specific to this
383
+ * peer - which call to make, what counts as unanswered on this client, and
384
+ * who to tell.
385
+ */
386
+ private buildHeartbeat;
387
+ private livenessTurnSnapshot;
388
+ private sameLivenessTurnSnapshot;
389
+ private confirmBeatLostSession;
390
+ private armIdle;
391
+ /**
392
+ * Ends a turn whose live edit is gone.
393
+ *
394
+ * The dev server exits on its own when its lock is lost, and it says nothing
395
+ * on the way out. A turn left waiting on that socket burns its entire budget
396
+ * — ten minutes — before the caller is told anything.
397
+ *
398
+ * Reached only once the live edit being gone is established, which a close on
399
+ * its own never does: either it named its own end in the application range,
400
+ * or {@link recoverTurn} could not get back to it for the whole reconnect
401
+ * grace. `live_edit_terminated` is a claim about the sandbox, so it is worth
402
+ * only as much as the evidence behind it. The close code and heartbeat
403
+ * account go in the reply, since they are the only account of the cause that
404
+ * reaches the caller.
405
+ */
406
+ private abandonTurnOnDisconnect;
407
+ /**
408
+ * Ends a turn SABS has just said has no live edit left to run on.
409
+ *
410
+ * A socket close is the other trigger for this same outcome, and it is the
411
+ * slower one: the dev server exits silently when it loses its lock, so the
412
+ * close can be minutes late or never arrive at all. This event is the control
413
+ * plane stating the session is gone, which is the same fact without waiting
414
+ * for a connection to notice it.
415
+ *
416
+ * Only for a turn that has not settled itself, though. Every healthy build
417
+ * ends with its session torn down too, and reading that as a dead live edit
418
+ * would report each finished app as a failure. A collector that already
419
+ * settled on a terminal state keeps it; the teardown is the outcome only for
420
+ * a turn still waiting for one. The disconnect path needs no such guard - an
421
+ * unsolicited close mid-turn is abnormal in its own right, where a teardown
422
+ * is what the end of every turn looks like.
423
+ *
424
+ * Settled, not merely reached: a terminal state is provisional until the
425
+ * quiet window closes, because a build that resumes after a false
426
+ * completed/idle clears it. A teardown inside that window therefore still
427
+ * ends the turn - which is the honest answer, since the checkpoint that
428
+ * would follow runs over the socket to the dev server that just died and
429
+ * could not have landed either way.
430
+ */
431
+ private abandonTurnOnSessionTerminated;
432
+ /**
433
+ * Ends a turn whose socket has stopped answering.
434
+ *
435
+ * Three gates answer different questions. `SocketHeartbeat`
436
+ * declares the beat lost after consecutive genuine misses, having already
437
+ * excused a run of unanswered beats and every silence that inbound traffic
438
+ * explained - the right threshold for a diagnostic, and too eager for this: a
439
+ * sandbox that misses two beats and answers the next was recovering, and its
440
+ * turn has to survive that. So the loss also has to outlast
441
+ * {@link DEFAULT_BEAT_LOST_GRACE_MS}, and any beat that succeeds clears it.
442
+ * Finally, the exact live edit must either be terminal in the control plane,
443
+ * or its direct HTTP health check must fail again after another grace
444
+ * window. One timeout, 5xx, or inconclusive control-plane result is still
445
+ * recoverable.
446
+ *
447
+ * What is left is a request channel that has been silent for minutes on a
448
+ * socket that never closed, with a turn waiting on it - which without this
449
+ * waits out the whole turn budget.
450
+ *
451
+ * This is the only trigger that reaches a half-open socket. An unsolicited
452
+ * close is the ordinary one and never arrives for a connection that stays up
453
+ * with nothing behind it, and the SABS `session: terminated` event cannot
454
+ * reach a gateway with no inbound route - which is every gateway run on a
455
+ * laptop, where a loopback public URL leaves SABS no way to post at all.
456
+ *
457
+ * The socket is deliberately left in place. Whether a connection proven
458
+ * wedged should also be torn down rather than handed to the next prompt is a
459
+ * separate question from whether this turn should keep waiting on it.
460
+ */
461
+ private abandonTurnOnBeatLost;
462
+ /**
463
+ * Records a dead live edit as the turn's outcome and ends every wait on it.
464
+ * `evidence` is appended to the reply because it is the only account of the
465
+ * cause that reaches the caller.
466
+ */
467
+ private settleAsLiveEditTerminated;
468
+ /**
469
+ * Decides what a close the gateway did not ask for actually means, by going
470
+ * back for the live edit rather than inferring from the close.
471
+ *
472
+ * The reattach machinery exists for exactly this: a turn whose socket went
473
+ * away is one the gateway can move onto a replacement. Abandoning here is
474
+ * what used to make that unreachable, and it charged a recoverable blip the
475
+ * whole turn - the caller is told to send the prompt again, and the work
476
+ * already done in it is discarded.
477
+ *
478
+ * Each of the three outcomes is a different thing to tell the caller:
479
+ *
480
+ * - taken over: nothing to tell. The turn carries on where it got to.
481
+ * - unreachable for the whole grace: the termination the close only hinted
482
+ * at, now with the evidence to say so.
483
+ * - reached but refused the turn: the sandbox is alive and building where
484
+ * this gateway cannot watch it, which is `detached`. Calling that a death
485
+ * would send the caller to retry a build that is still running.
486
+ *
487
+ * A reconnect that fails while SABS is still relaying the turn settles
488
+ * nothing: the socket is one of two ways this turn reports, and the events
489
+ * still arriving are the better account of whether the build is alive.
490
+ *
491
+ * Never throws: nothing awaits this, and every outcome it can reach belongs
492
+ * on the turn rather than on the socket handler that started it.
493
+ */
494
+ private recoverTurn;
495
+ /**
496
+ * Ends a prior turn for `applicationId` before a newer prompt claims the map
497
+ * slot. Callers polling the old turn see `cancelled`; its runTurn exits via
498
+ * AbortSignal and must not keep listening or arming release on the held
499
+ * session.
500
+ */
501
+ private supersedeTurn;
502
+ private cancelTurn;
503
+ private discardUnstartedTurn;
504
+ private armPostTurnRelease;
505
+ private armKeepalive;
506
+ /**
507
+ * Clears the turn timers only. The beat is stopped separately on purpose: it
508
+ * belongs to the socket and outlives these, which the post-turn grace period
509
+ * resets.
510
+ */
511
+ private clearIdleTimer;
512
+ private clearTimers;
513
+ private drop;
514
+ private editorContextFor;
515
+ /**
516
+ * Context the sandbox needs before it will let Clark drive a browser.
517
+ *
518
+ * Absent when headless testing is off or the session is missing something
519
+ * the app shell cannot boot without — Clark then runs the turn with its
520
+ * ordinary tools rather than failing it.
521
+ */
522
+ private browserContextFor;
523
+ /**
524
+ * Library iframe bootstrap from a held session. Used for Gateway's own
525
+ * live-canvas screenshot even when Clark's in-sandbox Playwright is off.
526
+ */
527
+ private buildHeldBrowserContext;
528
+ /**
529
+ * Resolves a real org profile key once per held session. Sending the legacy
530
+ * placeholder `default` makes the orchestrator fail every integration query
531
+ * with "Invalid profile specified" / HTTP 500.
532
+ */
533
+ private resolveHeldProfileKey;
534
+ /**
535
+ * Discovers the orchestrator / agent base URL the way the browser does:
536
+ * Server `/users/me` agents filtered by org agentType, Active status, and
537
+ * profile tags. Operators never set this URL.
538
+ */
539
+ private resolveHeldOrchestrator;
540
+ }