@superblocksteam/gateway 2.0.155-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.
- package/LICENSE.txt +87 -0
- package/README.md +170 -0
- package/dist/agents/resolve-orchestrator-url.d.ts +22 -0
- package/dist/agents/resolve-orchestrator-url.js +38 -0
- package/dist/agents/resolve-orchestrator-url.js.map +1 -0
- package/dist/capabilities/import-prompt.d.ts +11 -0
- package/dist/capabilities/import-prompt.js +96 -0
- package/dist/capabilities/import-prompt.js.map +1 -0
- package/dist/capabilities/lifecycle.d.ts +73 -0
- package/dist/capabilities/lifecycle.js +2531 -0
- package/dist/capabilities/lifecycle.js.map +1 -0
- package/dist/capabilities/persisted-progress.d.ts +46 -0
- package/dist/capabilities/persisted-progress.js +246 -0
- package/dist/capabilities/persisted-progress.js.map +1 -0
- package/dist/capabilities/types.d.ts +446 -0
- package/dist/capabilities/types.js +47 -0
- package/dist/capabilities/types.js.map +1 -0
- package/dist/capture/browser-contract.d.ts +36 -0
- package/dist/capture/browser-contract.js +24 -0
- package/dist/capture/browser-contract.js.map +1 -0
- package/dist/capture/browser-instructions.d.ts +9 -0
- package/dist/capture/browser-instructions.js +17 -0
- package/dist/capture/browser-instructions.js.map +1 -0
- package/dist/capture/capture-library-probe.d.ts +55 -0
- package/dist/capture/capture-library-probe.js +177 -0
- package/dist/capture/capture-library-probe.js.map +1 -0
- package/dist/capture/capture-library.d.ts +52 -0
- package/dist/capture/capture-library.js +249 -0
- package/dist/capture/capture-library.js.map +1 -0
- package/dist/capture/classify-library-paint.d.ts +21 -0
- package/dist/capture/classify-library-paint.js +13 -0
- package/dist/capture/classify-library-paint.js.map +1 -0
- package/dist/capture/host-mcp-scan.d.ts +16 -0
- package/dist/capture/host-mcp-scan.js +64 -0
- package/dist/capture/host-mcp-scan.js.map +1 -0
- package/dist/capture/library-parent-script.d.ts +34 -0
- package/dist/capture/library-parent-script.js +82 -0
- package/dist/capture/library-parent-script.js.map +1 -0
- package/dist/capture/mode.d.ts +22 -0
- package/dist/capture/mode.js +45 -0
- package/dist/capture/mode.js.map +1 -0
- package/dist/config.d.ts +141 -0
- package/dist/config.js +109 -0
- package/dist/config.js.map +1 -0
- package/dist/debug.d.ts +2 -0
- package/dist/debug.js +9 -0
- package/dist/debug.js.map +1 -0
- package/dist/deps.d.ts +36 -0
- package/dist/deps.js +2 -0
- package/dist/deps.js.map +1 -0
- package/dist/events/cursor.d.ts +43 -0
- package/dist/events/cursor.js +78 -0
- package/dist/events/cursor.js.map +1 -0
- package/dist/events/memory-event-store.d.ts +34 -0
- package/dist/events/memory-event-store.js +110 -0
- package/dist/events/memory-event-store.js.map +1 -0
- package/dist/events/merge.d.ts +23 -0
- package/dist/events/merge.js +97 -0
- package/dist/events/merge.js.map +1 -0
- package/dist/events/normalized-collector.d.ts +62 -0
- package/dist/events/normalized-collector.js +156 -0
- package/dist/events/normalized-collector.js.map +1 -0
- package/dist/events/schema.d.ts +9 -0
- package/dist/events/schema.js +93 -0
- package/dist/events/schema.js.map +1 -0
- package/dist/events/snapshot.d.ts +32 -0
- package/dist/events/snapshot.js +57 -0
- package/dist/events/snapshot.js.map +1 -0
- package/dist/events/stream-key.d.ts +2 -0
- package/dist/events/stream-key.js +31 -0
- package/dist/events/stream-key.js.map +1 -0
- package/dist/events/types.d.ts +179 -0
- package/dist/events/types.js +66 -0
- package/dist/events/types.js.map +1 -0
- package/dist/health/readiness.d.ts +99 -0
- package/dist/health/readiness.js +202 -0
- package/dist/health/readiness.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/filters.d.ts +8 -0
- package/dist/integrations/filters.js +40 -0
- package/dist/integrations/filters.js.map +1 -0
- package/dist/integrations/map.d.ts +26 -0
- package/dist/integrations/map.js +43 -0
- package/dist/integrations/map.js.map +1 -0
- package/dist/integrations/profile-key.d.ts +19 -0
- package/dist/integrations/profile-key.js +35 -0
- package/dist/integrations/profile-key.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +5 -0
- package/dist/main.js.map +1 -0
- package/dist/orchestrator/client.d.ts +62 -0
- package/dist/orchestrator/client.js +160 -0
- package/dist/orchestrator/client.js.map +1 -0
- package/dist/playwright/ensure-chromium.d.ts +26 -0
- package/dist/playwright/ensure-chromium.js +60 -0
- package/dist/playwright/ensure-chromium.js.map +1 -0
- package/dist/preview/capture-screenshot.d.ts +52 -0
- package/dist/preview/capture-screenshot.js +158 -0
- package/dist/preview/capture-screenshot.js.map +1 -0
- package/dist/preview/viewer-url.d.ts +82 -0
- package/dist/preview/viewer-url.js +128 -0
- package/dist/preview/viewer-url.js.map +1 -0
- package/dist/process/fault-barrier.d.ts +55 -0
- package/dist/process/fault-barrier.js +113 -0
- package/dist/process/fault-barrier.js.map +1 -0
- package/dist/resume/memory-progress-store.d.ts +39 -0
- package/dist/resume/memory-progress-store.js +82 -0
- package/dist/resume/memory-progress-store.js.map +1 -0
- package/dist/resume/memory-recent-app-store.d.ts +14 -0
- package/dist/resume/memory-recent-app-store.js +27 -0
- package/dist/resume/memory-recent-app-store.js.map +1 -0
- package/dist/resume/memory-turn-store.d.ts +18 -0
- package/dist/resume/memory-turn-store.js +73 -0
- package/dist/resume/memory-turn-store.js.map +1 -0
- package/dist/resume/progress-key.d.ts +21 -0
- package/dist/resume/progress-key.js +58 -0
- package/dist/resume/progress-key.js.map +1 -0
- package/dist/resume/stores.d.ts +14 -0
- package/dist/resume/stores.js +18 -0
- package/dist/resume/stores.js.map +1 -0
- package/dist/resume/types.d.ts +124 -0
- package/dist/resume/types.js +13 -0
- package/dist/resume/types.js.map +1 -0
- package/dist/sabs/agent-facing-text.d.ts +33 -0
- package/dist/sabs/agent-facing-text.js +125 -0
- package/dist/sabs/agent-facing-text.js.map +1 -0
- package/dist/sabs/browser-context.d.ts +53 -0
- package/dist/sabs/browser-context.js +91 -0
- package/dist/sabs/browser-context.js.map +1 -0
- package/dist/sabs/editor-client-methods.d.ts +147 -0
- package/dist/sabs/editor-client-methods.js +715 -0
- package/dist/sabs/editor-client-methods.js.map +1 -0
- package/dist/sabs/recent-tool-runs.d.ts +14 -0
- package/dist/sabs/recent-tool-runs.js +61 -0
- package/dist/sabs/recent-tool-runs.js.map +1 -0
- package/dist/sabs/session-peer.d.ts +351 -0
- package/dist/sabs/session-peer.js +2 -0
- package/dist/sabs/session-peer.js.map +1 -0
- package/dist/sabs/turn-collector.d.ts +152 -0
- package/dist/sabs/turn-collector.js +573 -0
- package/dist/sabs/turn-collector.js.map +1 -0
- package/dist/sabs/websocket-session-peer.d.ts +514 -0
- package/dist/sabs/websocket-session-peer.js +2487 -0
- package/dist/sabs/websocket-session-peer.js.map +1 -0
- package/dist/security/constant-time.d.ts +9 -0
- package/dist/security/constant-time.js +13 -0
- package/dist/security/constant-time.js.map +1 -0
- package/dist/server/client.d.ts +371 -0
- package/dist/server/client.js +572 -0
- package/dist/server/client.js.map +1 -0
- package/dist/server/identity-reads.d.ts +76 -0
- package/dist/server/identity-reads.js +209 -0
- package/dist/server/identity-reads.js.map +1 -0
- package/dist/start.d.ts +14 -0
- package/dist/start.js +75 -0
- package/dist/start.js.map +1 -0
- package/dist/telemetry/metrics.d.ts +32 -0
- package/dist/telemetry/metrics.js +57 -0
- package/dist/telemetry/metrics.js.map +1 -0
- package/dist/transports/mcp/admin-tools.d.ts +47 -0
- package/dist/transports/mcp/admin-tools.js +164 -0
- package/dist/transports/mcp/admin-tools.js.map +1 -0
- package/dist/transports/mcp/app-status-html.d.ts +15 -0
- package/dist/transports/mcp/app-status-html.js +563 -0
- package/dist/transports/mcp/app-status-html.js.map +1 -0
- package/dist/transports/mcp/decision-elicitation.d.ts +74 -0
- package/dist/transports/mcp/decision-elicitation.js +233 -0
- package/dist/transports/mcp/decision-elicitation.js.map +1 -0
- package/dist/transports/mcp/dispatch-probe.d.ts +24 -0
- package/dist/transports/mcp/dispatch-probe.js +48 -0
- package/dist/transports/mcp/dispatch-probe.js.map +1 -0
- package/dist/transports/mcp/format-tool-content.d.ts +25 -0
- package/dist/transports/mcp/format-tool-content.js +48 -0
- package/dist/transports/mcp/format-tool-content.js.map +1 -0
- package/dist/transports/mcp/mount.d.ts +9 -0
- package/dist/transports/mcp/mount.js +469 -0
- package/dist/transports/mcp/mount.js.map +1 -0
- package/dist/transports/mcp/progress-notifier.d.ts +39 -0
- package/dist/transports/mcp/progress-notifier.js +52 -0
- package/dist/transports/mcp/progress-notifier.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page source that makes a top-level pitcherURL visit look like the Code Mode
|
|
3
|
+
* iframe: mock `window.parent`, answer `sb-ready` / bootstrap / API auth in
|
|
4
|
+
* page JS so the host driver never sees the scoped JWT.
|
|
5
|
+
*
|
|
6
|
+
* Source text rather than a function handed to `addInitScript` because
|
|
7
|
+
* Playwright serializes functions and can drag bundler helpers (`__name`)
|
|
8
|
+
* into the page. Same rule as `buildEmbedHandshakeScript`.
|
|
9
|
+
*/
|
|
10
|
+
export function buildLibraryParentScript(payload) {
|
|
11
|
+
return `(function () {
|
|
12
|
+
if (window.parent !== window) return;
|
|
13
|
+
var payload = ${JSON.stringify(payload)};
|
|
14
|
+
var init = payload.initData;
|
|
15
|
+
var bootstrap = payload.bootstrapData;
|
|
16
|
+
window.__sbGatewayCaptureEvents = [];
|
|
17
|
+
function record(message) {
|
|
18
|
+
if (message && typeof message.type === "string") {
|
|
19
|
+
window.__sbGatewayCaptureEvents.push({ type: message.type });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function send(message) {
|
|
23
|
+
window.postMessage(message, window.location.origin);
|
|
24
|
+
}
|
|
25
|
+
var mockParent = {
|
|
26
|
+
postMessage: function (message) {
|
|
27
|
+
record(message);
|
|
28
|
+
if (message && message.type === "sb-ready" && init) {
|
|
29
|
+
send({
|
|
30
|
+
payload: {
|
|
31
|
+
appId: init.appId,
|
|
32
|
+
devServerAuthorization: init.devServerAuthorization,
|
|
33
|
+
peerId: init.peerId,
|
|
34
|
+
userId: init.userId,
|
|
35
|
+
windowOriginUrl: init.windowOriginUrl,
|
|
36
|
+
},
|
|
37
|
+
startTime: Date.now(),
|
|
38
|
+
type: "sb-init",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (message && message.type === "sb-editor-request-bootstrap" && bootstrap) {
|
|
42
|
+
send({
|
|
43
|
+
payload: bootstrap,
|
|
44
|
+
startTime: Date.now(),
|
|
45
|
+
type: "sb-bootstrap-response",
|
|
46
|
+
});
|
|
47
|
+
if (bootstrap.profiles) {
|
|
48
|
+
send({
|
|
49
|
+
payload: { global: { profiles: bootstrap.profiles } },
|
|
50
|
+
startTime: Date.now(),
|
|
51
|
+
type: "sb-global-sync",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (message && message.type === "authenticate-api-request") {
|
|
56
|
+
var callbackId = message.payload && message.payload.callbackId;
|
|
57
|
+
if (callbackId) {
|
|
58
|
+
send({
|
|
59
|
+
callbackId: callbackId,
|
|
60
|
+
payload: {
|
|
61
|
+
tokens: {
|
|
62
|
+
accessToken: bootstrap.accessToken,
|
|
63
|
+
token: bootstrap.token,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
type: "resolve-promise",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
document: document,
|
|
72
|
+
location: window.location,
|
|
73
|
+
window: window,
|
|
74
|
+
};
|
|
75
|
+
Object.defineProperty(window, "parent", {
|
|
76
|
+
configurable: true,
|
|
77
|
+
value: mockParent,
|
|
78
|
+
writable: false,
|
|
79
|
+
});
|
|
80
|
+
})();`;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=library-parent-script.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library-parent-script.js","sourceRoot":"","sources":["../../src/capture/library-parent-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA6BH,MAAM,UAAU,wBAAwB,CACtC,OAA6B;IAE7B,OAAO;;oBAEW,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAmErC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How this Gateway can (or cannot) capture a live canvas or complete IdP.
|
|
3
|
+
*
|
|
4
|
+
* `host_mcp_configured` is a setup-time scan of the MCP client config. That
|
|
5
|
+
* file can lie: the listed server may fail to start or miss PATH. Tool results
|
|
6
|
+
* therefore keep hostBrowserTools as "unknown" rather than claiming this turn
|
|
7
|
+
* has Playwright.
|
|
8
|
+
*/
|
|
9
|
+
export declare const CAPTURE_MODES: readonly ["gateway_chromium", "host_mcp_configured", "urls_only"];
|
|
10
|
+
export type CaptureMode = (typeof CAPTURE_MODES)[number];
|
|
11
|
+
export declare function resolveCaptureMode(input: {
|
|
12
|
+
gatewayChromium: boolean;
|
|
13
|
+
hostMcpConfigured: boolean;
|
|
14
|
+
}): CaptureMode;
|
|
15
|
+
/**
|
|
16
|
+
* Human + machine summary for `gateway setup` stderr. Info goes to stderr so
|
|
17
|
+
* a redirected stdout report stays clean.
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatCaptureModeSummary(input: {
|
|
20
|
+
isolated: boolean;
|
|
21
|
+
mode: CaptureMode;
|
|
22
|
+
}): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How this Gateway can (or cannot) capture a live canvas or complete IdP.
|
|
3
|
+
*
|
|
4
|
+
* `host_mcp_configured` is a setup-time scan of the MCP client config. That
|
|
5
|
+
* file can lie: the listed server may fail to start or miss PATH. Tool results
|
|
6
|
+
* therefore keep hostBrowserTools as "unknown" rather than claiming this turn
|
|
7
|
+
* has Playwright.
|
|
8
|
+
*/
|
|
9
|
+
export const CAPTURE_MODES = [
|
|
10
|
+
"gateway_chromium",
|
|
11
|
+
"host_mcp_configured",
|
|
12
|
+
"urls_only",
|
|
13
|
+
];
|
|
14
|
+
export function resolveCaptureMode(input) {
|
|
15
|
+
if (input.hostMcpConfigured) {
|
|
16
|
+
return "host_mcp_configured";
|
|
17
|
+
}
|
|
18
|
+
if (input.gatewayChromium) {
|
|
19
|
+
return "gateway_chromium";
|
|
20
|
+
}
|
|
21
|
+
return "urls_only";
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Human + machine summary for `gateway setup` stderr. Info goes to stderr so
|
|
25
|
+
* a redirected stdout report stays clean.
|
|
26
|
+
*/
|
|
27
|
+
export function formatCaptureModeSummary(input) {
|
|
28
|
+
const lines = [`capture.mode: ${input.mode}`];
|
|
29
|
+
switch (input.mode) {
|
|
30
|
+
case "host_mcp_configured":
|
|
31
|
+
lines.push("A host browser MCP is listed in this client config. Config on disk can lie if that server fails to start or misses PATH.");
|
|
32
|
+
break;
|
|
33
|
+
case "gateway_chromium":
|
|
34
|
+
lines.push("Gateway Playwright Chromium is present for preview screenshots. No host browser MCP was found. Config on disk can lie if a listed server fails to start. IdP step-up still returns needs_browser_driver until a host browser MCP (@playwright/mcp) is configured. Gateway Chromium cannot complete IdP.");
|
|
35
|
+
break;
|
|
36
|
+
case "urls_only":
|
|
37
|
+
lines.push("URLs only: no host browser MCP and no Gateway Chromium. Config on disk can lie if a listed server fails to start. Live-canvas capture will return needs_browser_driver; superblocks gateway setup --with-screenshots may help live-canvas capture and does not clear IdP. Add @playwright/mcp for IdP step-up.");
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
if (input.isolated) {
|
|
41
|
+
lines.push("Warning: a scanned browser MCP includes --isolated. IdP cookies will not survive browser_close.");
|
|
42
|
+
}
|
|
43
|
+
return lines.join("\n");
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mode.js","sourceRoot":"","sources":["../../src/capture/mode.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,kBAAkB;IAClB,qBAAqB;IACrB,WAAW;CACH,CAAC;AAIX,MAAM,UAAU,kBAAkB,CAAC,KAGlC;IACC,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC5B,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;QAC1B,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAGxC;IACC,MAAM,KAAK,GAAG,CAAC,iBAAiB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,qBAAqB;YACxB,KAAK,CAAC,IAAI,CACR,0HAA0H,CAC3H,CAAC;YACF,MAAM;QACR,KAAK,kBAAkB;YACrB,KAAK,CAAC,IAAI,CACR,ySAAyS,CAC1S,CAAC;YACF,MAAM;QACR,KAAK,WAAW;YACd,KAAK,CAAC,IAAI,CACR,gTAAgT,CACjT,CAAC;YACF,MAAM;IACV,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CACR,iGAAiG,CAClG,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
export type GatewayConfig = {
|
|
2
|
+
deploymentEnvironmentName: string;
|
|
3
|
+
/** Cloud-Prem laptop agent: single-user process on a corp machine. */
|
|
4
|
+
localAgentMode: boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Cloud-Prem Admin laptop agent: register Admin tools (integrations, apps,
|
|
7
|
+
* users, deploy_application, ...) only, and skip the Builder surface
|
|
8
|
+
* (start_app, edit_app, ...) that needs Playwright Chromium for preview
|
|
9
|
+
* screenshots and a live-edit session it never opens on this machine.
|
|
10
|
+
*/
|
|
11
|
+
adminToolsOnly: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Where `import_app` looks for an archive it was handed the name of.
|
|
14
|
+
*
|
|
15
|
+
* A file attached to a chat lives in the model's own sandbox, so the path the
|
|
16
|
+
* model can quote is unreadable here even though the user downloaded the file
|
|
17
|
+
* to this machine. Only the file name is taken from that path, and only these
|
|
18
|
+
* directories are searched, so a caller cannot walk the filesystem with it.
|
|
19
|
+
*/
|
|
20
|
+
importSearchDirs: string[];
|
|
21
|
+
/**
|
|
22
|
+
* How long the held socket's liveness beat must stay lost before the turn
|
|
23
|
+
* running on it is given up on. Exposed because this is the one knob that can
|
|
24
|
+
* end a turn the sandbox might still have finished: raising it far past the
|
|
25
|
+
* turn budget disables the behavior without a deploy.
|
|
26
|
+
*/
|
|
27
|
+
beatLostGraceMs: number;
|
|
28
|
+
/**
|
|
29
|
+
* How long to hold an editor websocket after the last prompt before
|
|
30
|
+
* releasing it. Headless MCP needs the socket kept open so the sandbox
|
|
31
|
+
* startup watchdog does not tear the session down.
|
|
32
|
+
*/
|
|
33
|
+
heldSessionIdleMs: number;
|
|
34
|
+
/**
|
|
35
|
+
* Grace period between a Clark turn settling and the held editor socket
|
|
36
|
+
* being dropped. Keeping it short leaves the user's own editor tab as the
|
|
37
|
+
* sandbox's only editor peer, which is the peer Clark's API calls run on.
|
|
38
|
+
*/
|
|
39
|
+
heldSessionReleaseAfterTurnMs: number;
|
|
40
|
+
/**
|
|
41
|
+
* How long `start_app` / `edit_app` wait for Clark's generation turn after
|
|
42
|
+
* the prompt is acknowledged.
|
|
43
|
+
*/
|
|
44
|
+
clarkTurnTimeoutMs: number;
|
|
45
|
+
/**
|
|
46
|
+
* Quiet window after Clark emits completed/idle before treating the job as
|
|
47
|
+
* done, so an acknowledgment that resumes generating is coalesced.
|
|
48
|
+
*/
|
|
49
|
+
clarkSettleMs: number;
|
|
50
|
+
/**
|
|
51
|
+
* After Clark's job settles, how long to wait for the dev server to flush
|
|
52
|
+
* Clark's files before giving up on checkpointing them.
|
|
53
|
+
*/
|
|
54
|
+
clarkReadyWaitMs: number;
|
|
55
|
+
/**
|
|
56
|
+
* Opt-in: hands Clark a browser context so its Playwright test tools are
|
|
57
|
+
* registered on headless turns. Off by default because that launches
|
|
58
|
+
* Chromium inside the live-edit pod (3Gi), which OOMKills generation.
|
|
59
|
+
* Gateway preview screenshots use laptop Chromium and ignore this flag.
|
|
60
|
+
* Set GATEWAY_CLARK_TESTING_ENABLED=true only when the sandbox has
|
|
61
|
+
* Chromium headroom and you want Clark to drive browser_* tools.
|
|
62
|
+
*/
|
|
63
|
+
clarkTestingEnabled: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* How long a single `check_app_progress` call waits for new Clark activity
|
|
66
|
+
* before answering with what it has. Sized to stay inside a client's tool
|
|
67
|
+
* timeout so the caller can poll again rather than lose the turn.
|
|
68
|
+
*/
|
|
69
|
+
clarkProgressWaitMs: number;
|
|
70
|
+
/**
|
|
71
|
+
* How long to wait between `check_app_progress` polls once a plan is
|
|
72
|
+
* approved and the app is being built. Longer than
|
|
73
|
+
* {@link GatewayConfig.clarkProgressWaitMs} so a multi-minute build does not
|
|
74
|
+
* burn through a host's tool-call budget; the plan phase still uses the
|
|
75
|
+
* shorter progress wait so a decision surfaces quickly.
|
|
76
|
+
*/
|
|
77
|
+
clarkBuildPollAfterMs: number;
|
|
78
|
+
/**
|
|
79
|
+
* How long a build may run without saying anything before a poll warns that
|
|
80
|
+
* it has gone quiet. Nonterminal and well under
|
|
81
|
+
* {@link GatewayConfig.clarkTurnTimeoutMs}, so the caller hears about the
|
|
82
|
+
* silence long before the turn is given up on.
|
|
83
|
+
*/
|
|
84
|
+
clarkStallHintAfterMs: number;
|
|
85
|
+
/**
|
|
86
|
+
* Ceiling on any single host-facing call, whatever it is waiting for.
|
|
87
|
+
*
|
|
88
|
+
* Hosts abandon a tool call after their own timeout, and a host that
|
|
89
|
+
* advertises progress notifications is under no obligation to act on them —
|
|
90
|
+
* so a call cannot be allowed to run past this on the strength of having
|
|
91
|
+
* sent progress. Anything still unfinished here returns pacing and a cursor
|
|
92
|
+
* instead of holding the request open.
|
|
93
|
+
*/
|
|
94
|
+
hostCallCeilingMs: number;
|
|
95
|
+
/**
|
|
96
|
+
* How long `publish_app` polls a queued deploy before giving up.
|
|
97
|
+
*/
|
|
98
|
+
publishWaitTimeoutMs: number;
|
|
99
|
+
/**
|
|
100
|
+
* Interval between deploy-status polls while waiting for a queued publish.
|
|
101
|
+
*/
|
|
102
|
+
publishPollIntervalMs: number;
|
|
103
|
+
/**
|
|
104
|
+
* Preferred integration profile key. When unset or `default`, Gateway
|
|
105
|
+
* picks a real org profile (staging → dev → production → first).
|
|
106
|
+
*/
|
|
107
|
+
profileKey: string;
|
|
108
|
+
serverUrl: string;
|
|
109
|
+
turnTtlMs: number;
|
|
110
|
+
uiBaseUrl: string;
|
|
111
|
+
/**
|
|
112
|
+
* Base URL of the deployed-app shell / CDN used for JWT preview links.
|
|
113
|
+
* Local default is the csb-mock CDN. May include `__SB_APP_ID`.
|
|
114
|
+
*/
|
|
115
|
+
deployedShellBaseUrl: string | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Optional https front door for the deployed shell (viewer/CDN tunnel).
|
|
118
|
+
* When set, Claude Desktop can openLink preview URLs. Stdio Gateway does
|
|
119
|
+
* not bind HTTP, so this is never a gateway origin.
|
|
120
|
+
*/
|
|
121
|
+
publicViewerBaseUrl: string | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* When true, always attempt a headless screenshot even if previewUrl is
|
|
124
|
+
* already https (demo / debugging).
|
|
125
|
+
*/
|
|
126
|
+
forcePreviewScreenshot: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Setup-time scan: a host browser MCP (@playwright/mcp, chrome-devtools,
|
|
129
|
+
* puppeteer, agent-browser) was listed in the client config. Config on disk
|
|
130
|
+
* can lie; tool results keep hostBrowserTools as "unknown".
|
|
131
|
+
*/
|
|
132
|
+
captureHostMcp: boolean;
|
|
133
|
+
/** Scanned host browser MCP args included --isolated (IdP cookies die). */
|
|
134
|
+
captureHostIsolated: boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Test override for whether Playwright Chromium is on disk. Unset in
|
|
137
|
+
* production: capabilities probe without installing.
|
|
138
|
+
*/
|
|
139
|
+
gatewayChromiumPresent?: boolean;
|
|
140
|
+
};
|
|
141
|
+
export declare function loadConfig(env?: NodeJS.ProcessEnv): GatewayConfig;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { DEFAULT_TURN_TTL_MS } from "./resume/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Reads an env var, treating blank as absent.
|
|
6
|
+
*
|
|
7
|
+
* Every optional var the Tilt profile passes is written as
|
|
8
|
+
* `os.getenv(name, '')`, and `FOO= cmd` sets an empty string too. Without this,
|
|
9
|
+
* `??` happily accepts `""` and it reaches config as a real value — a zero
|
|
10
|
+
* turn TTL, an empty UI URL that then fails URL construction.
|
|
11
|
+
*/
|
|
12
|
+
function readEnv(env, name) {
|
|
13
|
+
return env[name]?.trim() || undefined;
|
|
14
|
+
}
|
|
15
|
+
function required(env, name, fallback) {
|
|
16
|
+
const value = readEnv(env, name) ?? fallback;
|
|
17
|
+
if (!value) {
|
|
18
|
+
throw new Error(`Missing required env var: ${name}`);
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
function explicitEnvironmentName(env) {
|
|
23
|
+
return (readEnv(env, "DEPLOYMENT_ENVIRONMENT_NAME") ?? readEnv(env, "NODE_ENV"));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Where a file the user just got hold of actually sits: the browser's download
|
|
27
|
+
* folder, the desktop, or a temp directory, which is where Claude's own
|
|
28
|
+
* downloads land. `/tmp` and `/private/tmp` cover the macOS `/tmp` symlink both
|
|
29
|
+
* ways; `/private/var/folders` covers Claude's realpath'd temp dirs without
|
|
30
|
+
* opening the rest of `/private`. Anything outside these is refused, so an
|
|
31
|
+
* operator who needs more sets the env var.
|
|
32
|
+
*/
|
|
33
|
+
function resolveImportSearchDirs(env) {
|
|
34
|
+
const configured = readEnv(env, "GATEWAY_IMPORT_SEARCH_DIRS");
|
|
35
|
+
if (configured) {
|
|
36
|
+
return configured
|
|
37
|
+
.split(",")
|
|
38
|
+
.map((dir) => dir.trim())
|
|
39
|
+
.filter(Boolean);
|
|
40
|
+
}
|
|
41
|
+
const home = homedir();
|
|
42
|
+
return [
|
|
43
|
+
path.join(home, "Downloads"),
|
|
44
|
+
path.join(home, "Desktop"),
|
|
45
|
+
"/tmp",
|
|
46
|
+
"/private/tmp",
|
|
47
|
+
"/private/var/folders",
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
function isTruthyFlag(value) {
|
|
51
|
+
if (!value) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const normalized = value.toLowerCase();
|
|
55
|
+
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
56
|
+
}
|
|
57
|
+
export function loadConfig(env = process.env) {
|
|
58
|
+
const explicitEnvironment = explicitEnvironmentName(env);
|
|
59
|
+
const localAgentMode = isTruthyFlag(readEnv(env, "GATEWAY_LOCAL_AGENT"));
|
|
60
|
+
const adminToolsOnly = isTruthyFlag(readEnv(env, "GATEWAY_ADMIN_TOOLS_ONLY"));
|
|
61
|
+
// Never default the label to "local". A deployment that forgot to set the
|
|
62
|
+
// variable is not local, and anything reading the label would otherwise
|
|
63
|
+
// relax itself on the strength of a default.
|
|
64
|
+
const deploymentEnvironmentName = explicitEnvironment ?? "unknown";
|
|
65
|
+
// One origin standing in for both the server and the UI, for environments
|
|
66
|
+
// that serve them together - an ee deployment, a shared dev box. The local
|
|
67
|
+
// stack splits them across ports and sets each explicitly, and those still
|
|
68
|
+
// win: this is only the fallback beneath them.
|
|
69
|
+
const baseUrl = readEnv(env, "GATEWAY_BASE_URL");
|
|
70
|
+
return {
|
|
71
|
+
deploymentEnvironmentName,
|
|
72
|
+
localAgentMode,
|
|
73
|
+
adminToolsOnly,
|
|
74
|
+
importSearchDirs: resolveImportSearchDirs(env),
|
|
75
|
+
beatLostGraceMs: Number(readEnv(env, "GATEWAY_BEAT_LOST_GRACE_MS") ?? String(60_000)),
|
|
76
|
+
heldSessionIdleMs: Number(readEnv(env, "GATEWAY_HELD_SESSION_IDLE_MS") ?? String(30 * 60 * 1000)),
|
|
77
|
+
heldSessionReleaseAfterTurnMs: Number(readEnv(env, "GATEWAY_HELD_SESSION_RELEASE_AFTER_TURN_MS") ??
|
|
78
|
+
String(30_000)),
|
|
79
|
+
clarkTurnTimeoutMs: Number(readEnv(env, "GATEWAY_CLARK_TURN_TIMEOUT_MS") ?? String(10 * 60 * 1000)),
|
|
80
|
+
clarkSettleMs: Number(readEnv(env, "GATEWAY_CLARK_SETTLE_MS") ?? String(12_000)),
|
|
81
|
+
clarkReadyWaitMs: Number(readEnv(env, "GATEWAY_CLARK_READY_WAIT_MS") ?? String(30_000)),
|
|
82
|
+
clarkTestingEnabled: readEnv(env, "GATEWAY_CLARK_TESTING_ENABLED") === "true" ||
|
|
83
|
+
readEnv(env, "GATEWAY_CLARK_TESTING_ENABLED") === "1",
|
|
84
|
+
// Ceiling on one progress poll, not a floor: a poll returns the moment
|
|
85
|
+
// Clark says anything. Keep this around 10s so the plan phase stays
|
|
86
|
+
// responsive; the post-approve build cadence is clarkBuildPollAfterMs.
|
|
87
|
+
clarkProgressWaitMs: Number(readEnv(env, "GATEWAY_CLARK_PROGRESS_WAIT_MS") ?? String(10_000)),
|
|
88
|
+
// Suggested gap between polls once a plan is approved. ~30s keeps a
|
|
89
|
+
// 2-4 minute build inside Claude Desktop's tool-call budget.
|
|
90
|
+
clarkBuildPollAfterMs: Number(readEnv(env, "GATEWAY_CLARK_BUILD_POLL_AFTER_MS") ?? String(30_000)),
|
|
91
|
+
clarkStallHintAfterMs: Number(readEnv(env, "GATEWAY_CLARK_STALL_HINT_AFTER_MS") ?? String(120_000)),
|
|
92
|
+
// Under the 60s most MCP hosts allow a tool call, with room for the
|
|
93
|
+
// response to be written and read.
|
|
94
|
+
hostCallCeilingMs: Number(readEnv(env, "GATEWAY_HOST_CALL_CEILING_MS") ?? String(50_000)),
|
|
95
|
+
publishWaitTimeoutMs: Number(readEnv(env, "GATEWAY_PUBLISH_WAIT_TIMEOUT_MS") ?? String(2 * 60 * 1000)),
|
|
96
|
+
publishPollIntervalMs: Number(readEnv(env, "GATEWAY_PUBLISH_POLL_INTERVAL_MS") ?? "2000"),
|
|
97
|
+
profileKey: required(env, "GATEWAY_PROFILE_KEY", "default"),
|
|
98
|
+
serverUrl: required(env, "SUPERBLOCKS_SERVER_URL", readEnv(env, "GATEWAY_SERVER_URL") ?? baseUrl ?? "http://localhost:8080"),
|
|
99
|
+
turnTtlMs: Number(readEnv(env, "GATEWAY_TURN_TTL_MS") ?? DEFAULT_TURN_TTL_MS),
|
|
100
|
+
uiBaseUrl: required(env, "GATEWAY_UI_BASE_URL", baseUrl ?? "http://localhost:3000"),
|
|
101
|
+
deployedShellBaseUrl: readEnv(env, "GATEWAY_DEPLOYED_SHELL_BASE_URL"),
|
|
102
|
+
publicViewerBaseUrl: readEnv(env, "GATEWAY_PUBLIC_VIEWER_BASE_URL"),
|
|
103
|
+
forcePreviewScreenshot: readEnv(env, "GATEWAY_FORCE_PREVIEW_SCREENSHOT") === "true" ||
|
|
104
|
+
readEnv(env, "GATEWAY_FORCE_PREVIEW_SCREENSHOT") === "1",
|
|
105
|
+
captureHostMcp: isTruthyFlag(readEnv(env, "GATEWAY_CAPTURE_HOST_MCP")),
|
|
106
|
+
captureHostIsolated: isTruthyFlag(readEnv(env, "GATEWAY_CAPTURE_HOST_ISOLATED")),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/debug.d.ts
ADDED
package/dist/debug.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { debuglog } from "node:util";
|
|
2
|
+
export const gatewayDebug = debuglog("gateway");
|
|
3
|
+
export function gatewayDebugStack(message, attributes = {}) {
|
|
4
|
+
if (!gatewayDebug.enabled) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
gatewayDebug(message, { ...attributes, stack: new Error().stack });
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=debug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEhD,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,aAAsC,EAAE;IAExC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO;IACT,CAAC;IACD,YAAY,CAAC,OAAO,EAAE,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,IAAI,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;AACrE,CAAC"}
|
package/dist/deps.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { GatewayConfig } from "./config.js";
|
|
2
|
+
import type { EventStore } from "./events/types.js";
|
|
3
|
+
import type { ProgressStore, RecentAppStore, TurnStore } from "./resume/types.js";
|
|
4
|
+
import type { SessionPeer } from "./sabs/session-peer.js";
|
|
5
|
+
import type { SuperblocksServerClient } from "./server/client.js";
|
|
6
|
+
/**
|
|
7
|
+
* Runtime collaborators for one Gateway process. Stdio MCP is the only
|
|
8
|
+
* production transport; tests build the same bag and connect an in-memory
|
|
9
|
+
* client.
|
|
10
|
+
*/
|
|
11
|
+
export type AppDeps = {
|
|
12
|
+
config: GatewayConfig;
|
|
13
|
+
/**
|
|
14
|
+
* Personal API key of the already-logged-in Superblocks CLI user.
|
|
15
|
+
* Gateway tools call the control plane as this identity.
|
|
16
|
+
*/
|
|
17
|
+
cliApiKey: string;
|
|
18
|
+
/**
|
|
19
|
+
* Superblocks user already resolved for this CLI session. When present,
|
|
20
|
+
* capabilities skip `/users/me` (ENG-5806). When absent, the first tool
|
|
21
|
+
* call resolves it through the guarded identity read.
|
|
22
|
+
*/
|
|
23
|
+
cliIdentity?: {
|
|
24
|
+
email?: string;
|
|
25
|
+
organizationId: string;
|
|
26
|
+
userId: string;
|
|
27
|
+
};
|
|
28
|
+
/** Durable, bounded history of what happened in each live-edit session. */
|
|
29
|
+
events: EventStore;
|
|
30
|
+
/** Each caller's place in a build's event stream, kept between calls. */
|
|
31
|
+
progressCursors: ProgressStore;
|
|
32
|
+
recentApps: RecentAppStore;
|
|
33
|
+
server: SuperblocksServerClient;
|
|
34
|
+
sessionPeer: SessionPeer;
|
|
35
|
+
turns: TurnStore;
|
|
36
|
+
};
|
package/dist/deps.js
ADDED
package/dist/deps.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deps.js","sourceRoot":"","sources":["../src/deps.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type EventProducer, type LiveEditEvent } from "./types.js";
|
|
2
|
+
export declare const EVENT_CURSOR_VERSION = 1;
|
|
3
|
+
/**
|
|
4
|
+
* How far one caller has read a live edit's history.
|
|
5
|
+
*
|
|
6
|
+
* There is deliberately no single number here. SABS and the dev server mint
|
|
7
|
+
* their own sequence counters and cannot see each other's, so a global
|
|
8
|
+
* position would either have to be invented by the gateway — making it a
|
|
9
|
+
* third counter that two producers can race — or would have to pretend one
|
|
10
|
+
* producer's 7 is comparable with the other's. Naming each producer's own
|
|
11
|
+
* position is the smallest contract that stays true to how the events are
|
|
12
|
+
* produced, and it degrades gracefully: a producer this cursor has never
|
|
13
|
+
* heard from simply reads from the start of its stream.
|
|
14
|
+
*
|
|
15
|
+
* Keys are the wire producer names (lowercase snake_case) and the field name
|
|
16
|
+
* is lowerCamelCase, so the cursor survives a round trip through a tool
|
|
17
|
+
* result unchanged.
|
|
18
|
+
*/
|
|
19
|
+
export type EventCursor = {
|
|
20
|
+
streams: Partial<Record<EventProducer, number>>;
|
|
21
|
+
version: typeof EVENT_CURSOR_VERSION;
|
|
22
|
+
};
|
|
23
|
+
export declare const EMPTY_EVENT_CURSOR: EventCursor;
|
|
24
|
+
/** Last sequence this cursor consumed from a producer; 0 when never read. */
|
|
25
|
+
export declare function cursorPosition(cursor: EventCursor | undefined, producer: EventProducer): number;
|
|
26
|
+
/**
|
|
27
|
+
* Moves a cursor past the given events.
|
|
28
|
+
*
|
|
29
|
+
* Only ever forwards. Events arrive out of order between producers, and a
|
|
30
|
+
* re-read of an older event must not rewind a caller that has already gone
|
|
31
|
+
* further — that is the loop where a caller replays the same events forever.
|
|
32
|
+
*/
|
|
33
|
+
export declare function advanceEventCursor(cursor: EventCursor | undefined, events: readonly LiveEditEvent[]): EventCursor;
|
|
34
|
+
/**
|
|
35
|
+
* Reads a cursor a caller handed back.
|
|
36
|
+
*
|
|
37
|
+
* Anything unrecognized reads as "no cursor" rather than as an error: a caller
|
|
38
|
+
* resuming with a cursor from an older contract should re-read the retained
|
|
39
|
+
* history, not be refused. Positions are clamped to safe non-negative
|
|
40
|
+
* integers, so a hand-edited cursor cannot skip a stream to infinity or wind
|
|
41
|
+
* one backwards into a replay loop.
|
|
42
|
+
*/
|
|
43
|
+
export declare function parseEventCursor(raw: unknown): EventCursor | undefined;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { EVENT_PRODUCERS, } from "./types.js";
|
|
2
|
+
export const EVENT_CURSOR_VERSION = 1;
|
|
3
|
+
export const EMPTY_EVENT_CURSOR = {
|
|
4
|
+
streams: {},
|
|
5
|
+
version: EVENT_CURSOR_VERSION,
|
|
6
|
+
};
|
|
7
|
+
/** Last sequence this cursor consumed from a producer; 0 when never read. */
|
|
8
|
+
export function cursorPosition(cursor, producer) {
|
|
9
|
+
return cursor?.streams[producer] ?? 0;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Moves a cursor past the given events.
|
|
13
|
+
*
|
|
14
|
+
* Only ever forwards. Events arrive out of order between producers, and a
|
|
15
|
+
* re-read of an older event must not rewind a caller that has already gone
|
|
16
|
+
* further — that is the loop where a caller replays the same events forever.
|
|
17
|
+
*/
|
|
18
|
+
export function advanceEventCursor(cursor, events) {
|
|
19
|
+
const streams = {
|
|
20
|
+
...(cursor?.streams ?? {}),
|
|
21
|
+
};
|
|
22
|
+
for (const event of events) {
|
|
23
|
+
const seen = streams[event.producer] ?? 0;
|
|
24
|
+
if (event.sequence > seen) {
|
|
25
|
+
streams[event.producer] = event.sequence;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return { streams: sortStreams(streams), version: EVENT_CURSOR_VERSION };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Producer keys in a fixed order, so two cursors holding the same positions
|
|
32
|
+
* serialize to the same bytes. A cursor travels through JSON in a tool result
|
|
33
|
+
* and back again; an unstable key order would make two equal cursors compare
|
|
34
|
+
* unequal wherever they are compared as text.
|
|
35
|
+
*/
|
|
36
|
+
function sortStreams(streams) {
|
|
37
|
+
const sorted = {};
|
|
38
|
+
for (const producer of [...EVENT_PRODUCERS].sort()) {
|
|
39
|
+
const position = streams[producer];
|
|
40
|
+
if (position !== undefined) {
|
|
41
|
+
sorted[producer] = position;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return sorted;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Reads a cursor a caller handed back.
|
|
48
|
+
*
|
|
49
|
+
* Anything unrecognized reads as "no cursor" rather than as an error: a caller
|
|
50
|
+
* resuming with a cursor from an older contract should re-read the retained
|
|
51
|
+
* history, not be refused. Positions are clamped to safe non-negative
|
|
52
|
+
* integers, so a hand-edited cursor cannot skip a stream to infinity or wind
|
|
53
|
+
* one backwards into a replay loop.
|
|
54
|
+
*/
|
|
55
|
+
export function parseEventCursor(raw) {
|
|
56
|
+
if (typeof raw !== "object" || raw === null) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const candidate = raw;
|
|
60
|
+
if (candidate.version !== EVENT_CURSOR_VERSION) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
if (typeof candidate.streams !== "object" || candidate.streams === null) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const source = candidate.streams;
|
|
67
|
+
const streams = {};
|
|
68
|
+
for (const producer of EVENT_PRODUCERS) {
|
|
69
|
+
const position = source[producer];
|
|
70
|
+
if (typeof position === "number" &&
|
|
71
|
+
Number.isSafeInteger(position) &&
|
|
72
|
+
position >= 0) {
|
|
73
|
+
streams[producer] = position;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { streams: sortStreams(streams), version: EVENT_CURSOR_VERSION };
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/events/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,GAGhB,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAuBtC,MAAM,CAAC,MAAM,kBAAkB,GAAgB;IAC7C,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,oBAAoB;CAC9B,CAAC;AAEF,6EAA6E;AAC7E,MAAM,UAAU,cAAc,CAC5B,MAA+B,EAC/B,QAAuB;IAEvB,OAAO,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAA+B,EAC/B,MAAgC;IAEhC,MAAM,OAAO,GAA2C;QACtD,GAAG,CAAC,MAAM,EAAE,OAAO,IAAI,EAAE,CAAC;KAC3B,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,KAAK,CAAC,QAAQ,GAAG,IAAI,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAClB,OAA+C;IAE/C,MAAM,MAAM,GAA2C,EAAE,CAAC;IAC1D,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,SAAS,GAAG,GAA+C,CAAC;IAClE,IAAI,SAAS,CAAC,OAAO,KAAK,oBAAoB,EAAE,CAAC;QAC/C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,SAAS,CAAC,OAAO,KAAK,QAAQ,IAAI,SAAS,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QACxE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAkC,CAAC;IAC5D,MAAM,OAAO,GAA2C,EAAE,CAAC;IAC3D,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClC,IACE,OAAO,QAAQ,KAAK,QAAQ;YAC5B,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC;YAC9B,QAAQ,IAAI,CAAC,EACb,CAAC;YACD,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { EventCursor } from "./cursor.js";
|
|
2
|
+
import { type AppendOutcome, type EventProducer, type EventScope, type EventSnapshot, type EventStore, type LiveEditEvent } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Local-only fallback for a laptop stack with no Redis, matching the same
|
|
5
|
+
* fallback the turn store makes. It is not a second source of truth: a
|
|
6
|
+
* multi-replica deployment would need an external store, because two
|
|
7
|
+
* processes with private maps cannot agree on what was already delivered.
|
|
8
|
+
*
|
|
9
|
+
* A shared test suite runs both implementations against the same behaviour, so
|
|
10
|
+
* "works locally, breaks on Redis" shows up here rather than in production.
|
|
11
|
+
*/
|
|
12
|
+
export declare class MemoryEventStore implements EventStore {
|
|
13
|
+
private readonly streams;
|
|
14
|
+
append(event: LiveEditEvent): Promise<AppendOutcome>;
|
|
15
|
+
list(input: EventScope & {
|
|
16
|
+
afterSequence?: number;
|
|
17
|
+
limit?: number;
|
|
18
|
+
producer?: EventProducer;
|
|
19
|
+
}): Promise<LiveEditEvent[]>;
|
|
20
|
+
snapshot(input: EventScope & {
|
|
21
|
+
cursor?: EventCursor;
|
|
22
|
+
limit?: number;
|
|
23
|
+
}): Promise<EventSnapshot>;
|
|
24
|
+
/** One producer's retained stream in sequence order, as Redis reads it. */
|
|
25
|
+
private ordered;
|
|
26
|
+
private streamFor;
|
|
27
|
+
/**
|
|
28
|
+
* Drops the lowest-sequence events past the bound, which takes their
|
|
29
|
+
* de-duplication records with them: keeping every id forever would make the
|
|
30
|
+
* bound on events pointless.
|
|
31
|
+
*/
|
|
32
|
+
private trim;
|
|
33
|
+
private evictExpired;
|
|
34
|
+
}
|