@superblocksteam/gateway 2.0.0-SNAPSHOT.2161f9a02a4eb5d8

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 (239) hide show
  1. package/LICENSE.txt +87 -0
  2. package/README.md +284 -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 +3417 -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 +112 -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 +23 -0
  79. package/dist/playwright/ensure-chromium.js +59 -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 +133 -0
  94. package/dist/sabs/app-state.js +347 -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 +749 -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 +386 -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 +512 -0
  119. package/dist/sabs/turn-collector.js.map +1 -0
  120. package/dist/sabs/websocket-session-peer.d.ts +533 -0
  121. package/dist/sabs/websocket-session-peer.js +3241 -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 +400 -0
  127. package/dist/server/client.js +649 -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 +51 -0
  151. package/dist/transports/mcp/admin-tools.js +211 -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/decision-card-html.d.ts +26 -0
  160. package/dist/transports/mcp/decision-card-html.js +876 -0
  161. package/dist/transports/mcp/decision-card-html.js.map +1 -0
  162. package/dist/transports/mcp/decision-elicitation.d.ts +116 -0
  163. package/dist/transports/mcp/decision-elicitation.js +292 -0
  164. package/dist/transports/mcp/decision-elicitation.js.map +1 -0
  165. package/dist/transports/mcp/dispatch-probe.d.ts +24 -0
  166. package/dist/transports/mcp/dispatch-probe.js +48 -0
  167. package/dist/transports/mcp/dispatch-probe.js.map +1 -0
  168. package/dist/transports/mcp/format-tool-content.d.ts +20 -0
  169. package/dist/transports/mcp/format-tool-content.js +89 -0
  170. package/dist/transports/mcp/format-tool-content.js.map +1 -0
  171. package/dist/transports/mcp/instructions/index.d.ts +23 -0
  172. package/dist/transports/mcp/instructions/index.js +81 -0
  173. package/dist/transports/mcp/instructions/index.js.map +1 -0
  174. package/dist/transports/mcp/instructions/result.d.ts +18 -0
  175. package/dist/transports/mcp/instructions/result.js +58 -0
  176. package/dist/transports/mcp/instructions/result.js.map +1 -0
  177. package/dist/transports/mcp/instructions/tools/ask-user.d.ts +2 -0
  178. package/dist/transports/mcp/instructions/tools/ask-user.js +17 -0
  179. package/dist/transports/mcp/instructions/tools/ask-user.js.map +1 -0
  180. package/dist/transports/mcp/instructions/tools/check-app-progress.d.ts +3 -0
  181. package/dist/transports/mcp/instructions/tools/check-app-progress.js +72 -0
  182. package/dist/transports/mcp/instructions/tools/check-app-progress.js.map +1 -0
  183. package/dist/transports/mcp/instructions/tools/check-publish-progress.d.ts +2 -0
  184. package/dist/transports/mcp/instructions/tools/check-publish-progress.js +14 -0
  185. package/dist/transports/mcp/instructions/tools/check-publish-progress.js.map +1 -0
  186. package/dist/transports/mcp/instructions/tools/copy.d.ts +8 -0
  187. package/dist/transports/mcp/instructions/tools/copy.js +19 -0
  188. package/dist/transports/mcp/instructions/tools/copy.js.map +1 -0
  189. package/dist/transports/mcp/instructions/tools/create-integration.d.ts +3 -0
  190. package/dist/transports/mcp/instructions/tools/create-integration.js +32 -0
  191. package/dist/transports/mcp/instructions/tools/create-integration.js.map +1 -0
  192. package/dist/transports/mcp/instructions/tools/edit-app.d.ts +2 -0
  193. package/dist/transports/mcp/instructions/tools/edit-app.js +14 -0
  194. package/dist/transports/mcp/instructions/tools/edit-app.js.map +1 -0
  195. package/dist/transports/mcp/instructions/tools/get-app.d.ts +3 -0
  196. package/dist/transports/mcp/instructions/tools/get-app.js +47 -0
  197. package/dist/transports/mcp/instructions/tools/get-app.js.map +1 -0
  198. package/dist/transports/mcp/instructions/tools/get-integration-metadata.d.ts +2 -0
  199. package/dist/transports/mcp/instructions/tools/get-integration-metadata.js +13 -0
  200. package/dist/transports/mcp/instructions/tools/get-integration-metadata.js.map +1 -0
  201. package/dist/transports/mcp/instructions/tools/index.d.ts +7 -0
  202. package/dist/transports/mcp/instructions/tools/index.js +26 -0
  203. package/dist/transports/mcp/instructions/tools/index.js.map +1 -0
  204. package/dist/transports/mcp/instructions/tools/preview-app.d.ts +3 -0
  205. package/dist/transports/mcp/instructions/tools/preview-app.js +14 -0
  206. package/dist/transports/mcp/instructions/tools/preview-app.js.map +1 -0
  207. package/dist/transports/mcp/instructions/tools/publish-app.d.ts +2 -0
  208. package/dist/transports/mcp/instructions/tools/publish-app.js +11 -0
  209. package/dist/transports/mcp/instructions/tools/publish-app.js.map +1 -0
  210. package/dist/transports/mcp/instructions/tools/start-app.d.ts +2 -0
  211. package/dist/transports/mcp/instructions/tools/start-app.js +18 -0
  212. package/dist/transports/mcp/instructions/tools/start-app.js.map +1 -0
  213. package/dist/transports/mcp/instructions/tools/upload-artifact.d.ts +2 -0
  214. package/dist/transports/mcp/instructions/tools/upload-artifact.js +13 -0
  215. package/dist/transports/mcp/instructions/tools/upload-artifact.js.map +1 -0
  216. package/dist/transports/mcp/mcp-app-brand-css.d.ts +1 -0
  217. package/dist/transports/mcp/mcp-app-brand-css.js +180 -0
  218. package/dist/transports/mcp/mcp-app-brand-css.js.map +1 -0
  219. package/dist/transports/mcp/mount.d.ts +21 -0
  220. package/dist/transports/mcp/mount.js +968 -0
  221. package/dist/transports/mcp/mount.js.map +1 -0
  222. package/dist/transports/mcp/native-browser-presence.d.ts +45 -0
  223. package/dist/transports/mcp/native-browser-presence.js +158 -0
  224. package/dist/transports/mcp/native-browser-presence.js.map +1 -0
  225. package/dist/transports/mcp/plan-approval.d.ts +38 -0
  226. package/dist/transports/mcp/plan-approval.js +175 -0
  227. package/dist/transports/mcp/plan-approval.js.map +1 -0
  228. package/dist/transports/mcp/progress-notifier.d.ts +39 -0
  229. package/dist/transports/mcp/progress-notifier.js +52 -0
  230. package/dist/transports/mcp/progress-notifier.js.map +1 -0
  231. package/dist/transports/mcp/session-directory.d.ts +7 -0
  232. package/dist/transports/mcp/session-directory.js +18 -0
  233. package/dist/transports/mcp/session-directory.js.map +1 -0
  234. package/dist/transports/mcp/tool-names.d.ts +2 -0
  235. package/dist/transports/mcp/tool-names.js +2 -0
  236. package/dist/transports/mcp/tool-names.js.map +1 -0
  237. package/package.json +78 -0
  238. package/skills/superblocks-build/SKILL.md +59 -0
  239. package/skills/superblocks-import/SKILL.md +87 -0
@@ -0,0 +1,533 @@
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
+ libraryBrowserContext(applicationId: string, requestedBranch?: string): import("@superblocksteam/library-shared/types").BrowserContext | undefined;
222
+ holdLiveEdit(input: HoldLiveEditInput): Promise<void>;
223
+ release(applicationId: string): void;
224
+ closeAll(): void;
225
+ /**
226
+ * Sends the prompt and waits for Clark's whole turn.
227
+ *
228
+ * Kept for callers with nowhere to poll from — the HTTP capability routes
229
+ * answer a single request — and implemented on the same engine as
230
+ * {@link startPrompt} so there is one turn lifecycle, not two.
231
+ */
232
+ forwardPrompt(input: PromptInput): Promise<ForwardPromptResult>;
233
+ private claimPromptLane;
234
+ startPrompt(input: PromptInput): Promise<StartPromptResult>;
235
+ /**
236
+ * Sends the prompt on a session already holding a subscribed turn, and hands
237
+ * the turn to {@link runTurn} once the session confirms it took it on.
238
+ */
239
+ private sendPrompt;
240
+ private latestTurn;
241
+ private observeEditorEvent;
242
+ private forgetObservedTurn;
243
+ private finishObservedTurn;
244
+ private settleObservedTurn;
245
+ private armObservedTurnRelease;
246
+ private armObservedPostTurnRelease;
247
+ awaitTurn(input: {
248
+ applicationId: string;
249
+ branch?: string;
250
+ organizationId?: string;
251
+ signal?: AbortSignal;
252
+ userId?: string;
253
+ floorMs?: number;
254
+ waitMs: number;
255
+ }): Promise<TurnUpdate>;
256
+ /**
257
+ * Follows the turn to its end on the held session: terminal state, then the
258
+ * checkpoint that commits Clark's draft. Never throws — a caller polling for
259
+ * news has to be told what happened, and the only place left to report a
260
+ * failure is the turn record itself.
261
+ */
262
+ private runTurn;
263
+ private pushWaitMs;
264
+ /**
265
+ * Checks that the session took this prompt on as a turn belonging to this
266
+ * peer, and gives up on it now if it did not.
267
+ *
268
+ * A dev server that predates the gateway role accepts the socket, echoes the
269
+ * role it was offered, and then treats the connection as a library socket: the
270
+ * prompt is acknowledged and Clark's pushes go to the browser binding
271
+ * instead. The turn would spend its whole budget looking detached, and a
272
+ * rollout with one stale sandbox in it would look like Clark hanging. Only a
273
+ * server that bound the turn can name it back, so the missing handle is the
274
+ * mismatch, reported where it is still cheap to act on.
275
+ */
276
+ private assertHeadlessTurnBound;
277
+ /**
278
+ * The field the session reads to decide which turn a call belongs to. Sent on
279
+ * the calls that make up a turn's lifetime, so a turn keeps reporting into
280
+ * this caller across a reattach and no other session can be handed it.
281
+ */
282
+ private turnCorrelator;
283
+ /**
284
+ * Moves a turn onto a fresh socket while the one it is on is still open,
285
+ * because Clark has stopped pushing to it. A turn that was running unseen
286
+ * becomes visible again from where it got to.
287
+ *
288
+ * The socket it came in on is still the better of the two whenever the
289
+ * replacement fails to take the turn over: the sandbox is demonstrably alive,
290
+ * and it is still pushing this turn somewhere. A caller mid-turn has nothing
291
+ * to gain from an exception here, so there is no failure to report but the
292
+ * log line.
293
+ */
294
+ private reattach;
295
+ /**
296
+ * Whether this turn gets another go at its live edit, booking it if so.
297
+ *
298
+ * The allowance is for a live edit that cannot hold a socket, and a turn that
299
+ * has heard from Clark since its last reconnect is not that: it is getting
300
+ * somewhere, so its allowance starts over. Without that, a long build behind
301
+ * a proxy that reaps every few minutes runs out of goes and is failed for the
302
+ * very reason this path exists to survive.
303
+ */
304
+ private takeReconnectAllowance;
305
+ /**
306
+ * Opens a replacement connection and asks the live edit to hand `turn` over
307
+ * to it.
308
+ *
309
+ * Everything that belongs to the session rather than to the socket is carried
310
+ * across first: the credential the claim itself is made with is one of those
311
+ * things, and so is the orchestrator a mid-turn tool call needs. The turn's
312
+ * listener goes on the replacement before the claim, so a push that arrives
313
+ * while it is in flight is not dropped.
314
+ *
315
+ * The turn is claimed before the old socket is let go. The session releases a
316
+ * turn when the connection holding it closes, so closing first leaves the
317
+ * claim nothing to take over; claiming first makes the old socket's close a
318
+ * no-op scoped to a peer that is no longer the owner.
319
+ *
320
+ * Nothing has moved when this fails: the listener is back where it was and
321
+ * the replacement is closed, which leaves the caller free to decide what a
322
+ * socket it could not replace means.
323
+ */
324
+ private takeOverTurn;
325
+ private attemptTakeOver;
326
+ /**
327
+ * Carries onto a replacement socket everything that belongs to the session
328
+ * rather than to the connection: who the turn runs as, what it is allowed to
329
+ * do, and which orchestrator its tool calls go to. A replacement missing any
330
+ * of it is connected but cannot act for the caller.
331
+ */
332
+ private carryOver;
333
+ /**
334
+ * Makes one authenticated read on a freshly opened socket.
335
+ *
336
+ * The dev server trusts a peer's identity per connection and does not carry
337
+ * it over from the peer this one replaced, so it withholds the pushes it
338
+ * scopes to a caller — Clark's step-by-step task status — until the new
339
+ * connection has proven who it is. Reading the chat is the cheapest way to
340
+ * prove it, and it costs a turn nothing when the read fails.
341
+ *
342
+ * Naming `turnId` is what makes this call a reattach rather than just an
343
+ * authenticated read: the session only moves a turn onto a connection that
344
+ * can say which turn it is taking over.
345
+ *
346
+ * Answers whether it worked, because a caller mid-reattach has to decide
347
+ * between two sockets on it.
348
+ */
349
+ private proveIdentity;
350
+ private reconnect;
351
+ private setHeld;
352
+ private recordEditorStructure;
353
+ private publishEditorStructure;
354
+ private currentViewStatus;
355
+ /** Lines this caller has not been handed yet. */
356
+ private drain;
357
+ private wake;
358
+ /** Adds a line to what the next poll on this turn is handed. */
359
+ private note;
360
+ /**
361
+ * Records the outcome of a turn from outside runTurn, and ends the collector
362
+ * waits so runTurn cannot overwrite it with a later timeout of its own. The
363
+ * first outcome written wins: it is the one callers have already been shown.
364
+ */
365
+ private settleTurn;
366
+ /**
367
+ * Mirrors the browser editor's auto-accept: wait for the dev server to flush
368
+ * Clark's files, then commit the draft. Failing to checkpoint costs the caller
369
+ * a committed app, not the generation itself, so this never throws.
370
+ */
371
+ private checkpoint;
372
+ private ensureHeld;
373
+ private connect;
374
+ private assertReadOnlyHoldCurrent;
375
+ /**
376
+ * The liveness beat for one held socket.
377
+ *
378
+ * Everything about pacing, deadlines and when to believe a silence lives in
379
+ * {@link SocketHeartbeat}; what belongs here is only what is specific to this
380
+ * peer - which call to make, what counts as unanswered on this client, and
381
+ * who to tell.
382
+ */
383
+ private buildHeartbeat;
384
+ private confirmBeatLostSession;
385
+ private armIdle;
386
+ /**
387
+ * Ends a turn whose live edit is gone.
388
+ *
389
+ * The dev server exits on its own when its lock is lost, and it says nothing
390
+ * on the way out. A turn left waiting on that socket burns its entire budget
391
+ * — ten minutes — before the caller is told anything.
392
+ *
393
+ * Reached only once the live edit being gone is established, which a close on
394
+ * its own never does: either it named its own end in the application range,
395
+ * or {@link recoverTurn} could not get back to it for the whole reconnect
396
+ * grace. `live_edit_terminated` is a claim about the sandbox, so it is worth
397
+ * only as much as the evidence behind it. The close code and heartbeat
398
+ * account go in the reply, since they are the only account of the cause that
399
+ * reaches the caller.
400
+ */
401
+ private abandonTurnOnDisconnect;
402
+ /**
403
+ * Ends a turn SABS has just said has no live edit left to run on.
404
+ *
405
+ * A socket close is the other trigger for this same outcome, and it is the
406
+ * slower one: the dev server exits silently when it loses its lock, so the
407
+ * close can be minutes late or never arrive at all. This event is the control
408
+ * plane stating the session is gone, which is the same fact without waiting
409
+ * for a connection to notice it.
410
+ *
411
+ * Only for a turn that has not settled itself, though. Every healthy build
412
+ * ends with its session torn down too, and reading that as a dead live edit
413
+ * would report each finished app as a failure. A collector that already
414
+ * settled on a terminal state keeps it; the teardown is the outcome only for
415
+ * a turn still waiting for one. The disconnect path needs no such guard - an
416
+ * unsolicited close mid-turn is abnormal in its own right, where a teardown
417
+ * is what the end of every turn looks like.
418
+ *
419
+ * Settled, not merely reached: a terminal state is provisional until the
420
+ * quiet window closes, because a build that resumes after a false
421
+ * completed/idle clears it. A teardown inside that window therefore still
422
+ * ends the turn - which is the honest answer, since the checkpoint that
423
+ * would follow runs over the socket to the dev server that just died and
424
+ * could not have landed either way.
425
+ */
426
+ private abandonTurnOnSessionTerminated;
427
+ /**
428
+ * Ends a turn whose socket has stopped answering.
429
+ *
430
+ * Three gates answer different questions. `SocketHeartbeat`
431
+ * declares the beat lost after consecutive genuine misses, having already
432
+ * excused a run of unanswered beats and every silence that inbound traffic
433
+ * explained - the right threshold for a diagnostic, and too eager for this: a
434
+ * sandbox that misses two beats and answers the next was recovering, and its
435
+ * turn has to survive that. So the loss also has to outlast
436
+ * {@link DEFAULT_BEAT_LOST_GRACE_MS}, and any beat that succeeds clears it.
437
+ * Finally, an independent HTTP request must fail to confirm that this same
438
+ * application's dev server is healthy.
439
+ *
440
+ * What is left is a request channel that has been silent for minutes on a
441
+ * socket that never closed, with a turn waiting on it - which without this
442
+ * waits out the whole turn budget.
443
+ *
444
+ * This is the only trigger that reaches a half-open socket. An unsolicited
445
+ * close is the ordinary one and never arrives for a connection that stays up
446
+ * with nothing behind it, and the SABS `session: terminated` event cannot
447
+ * reach a gateway with no inbound route - which is every gateway run on a
448
+ * laptop, where a loopback public URL leaves SABS no way to post at all.
449
+ *
450
+ * The socket is deliberately left in place. Whether a connection proven
451
+ * wedged should also be torn down rather than handed to the next prompt is a
452
+ * separate question from whether this turn should keep waiting on it.
453
+ */
454
+ private abandonTurnOnBeatLost;
455
+ /**
456
+ * Records a dead live edit as the turn's outcome and ends every wait on it.
457
+ * `evidence` is appended to the reply because it is the only account of the
458
+ * cause that reaches the caller.
459
+ */
460
+ private settleAsLiveEditTerminated;
461
+ /**
462
+ * Decides what a close the gateway did not ask for actually means, by going
463
+ * back for the live edit rather than inferring from the close.
464
+ *
465
+ * The reattach machinery exists for exactly this: a turn whose socket went
466
+ * away is one the gateway can move onto a replacement. Abandoning here is
467
+ * what used to make that unreachable, and it charged a recoverable blip the
468
+ * whole turn - the caller is told to send the prompt again, and the work
469
+ * already done in it is discarded.
470
+ *
471
+ * Each of the three outcomes is a different thing to tell the caller:
472
+ *
473
+ * - taken over: nothing to tell. The turn carries on where it got to.
474
+ * - unreachable for the whole grace: the termination the close only hinted
475
+ * at, now with the evidence to say so.
476
+ * - reached but refused the turn: the sandbox is alive and building where
477
+ * this gateway cannot watch it, which is `detached`. Calling that a death
478
+ * would send the caller to retry a build that is still running.
479
+ *
480
+ * A reconnect that fails while SABS is still relaying the turn settles
481
+ * nothing: the socket is one of two ways this turn reports, and the events
482
+ * still arriving are the better account of whether the build is alive.
483
+ *
484
+ * Never throws: nothing awaits this, and every outcome it can reach belongs
485
+ * on the turn rather than on the socket handler that started it.
486
+ */
487
+ private recoverTurn;
488
+ /**
489
+ * Ends a prior turn for `applicationId` before a newer prompt claims the map
490
+ * slot. Callers polling the old turn see `cancelled`; its runTurn exits via
491
+ * AbortSignal and must not keep listening or arming release on the held
492
+ * session.
493
+ */
494
+ private supersedeTurn;
495
+ private cancelTurn;
496
+ private discardUnstartedTurn;
497
+ private armPostTurnRelease;
498
+ private armKeepalive;
499
+ /**
500
+ * Clears the turn timers only. The beat is stopped separately on purpose: it
501
+ * belongs to the socket and outlives these, which the post-turn grace period
502
+ * resets.
503
+ */
504
+ private clearIdleTimer;
505
+ private clearTimers;
506
+ private drop;
507
+ private editorContextFor;
508
+ /**
509
+ * Context the sandbox needs before it will let Clark drive a browser.
510
+ *
511
+ * Absent when headless testing is off or the session is missing something
512
+ * the app shell cannot boot without — Clark then runs the turn with its
513
+ * ordinary tools rather than failing it.
514
+ */
515
+ private browserContextFor;
516
+ /**
517
+ * Library iframe bootstrap from a held session. Used for Gateway's own
518
+ * live-canvas screenshot even when Clark's in-sandbox Playwright is off.
519
+ */
520
+ private buildHeldBrowserContext;
521
+ /**
522
+ * Resolves a real org profile key once per held session. Sending the legacy
523
+ * placeholder `default` makes the orchestrator fail every integration query
524
+ * with "Invalid profile specified" / HTTP 500.
525
+ */
526
+ private resolveHeldProfileKey;
527
+ /**
528
+ * Discovers the orchestrator / agent base URL the way the browser does:
529
+ * Server `/users/me` agents filtered by org agentType, Active status, and
530
+ * profile tags. Operators never set this URL.
531
+ */
532
+ private resolveHeldOrchestrator;
533
+ }