@superblocksteam/gateway 2.0.161 → 2.0.162-next.1
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/README.md +135 -39
- package/dist/agents/resolve-orchestrator-url.d.ts +18 -0
- package/dist/agents/resolve-orchestrator-url.js +64 -1
- package/dist/agents/resolve-orchestrator-url.js.map +1 -1
- package/dist/capabilities/lifecycle.d.ts +46 -29
- package/dist/capabilities/lifecycle.js +1731 -843
- package/dist/capabilities/lifecycle.js.map +1 -1
- package/dist/capabilities/query-integration.d.ts +14 -0
- package/dist/capabilities/query-integration.js +172 -0
- package/dist/capabilities/query-integration.js.map +1 -0
- package/dist/capabilities/source-files-archive.d.ts +11 -0
- package/dist/capabilities/source-files-archive.js +54 -0
- package/dist/capabilities/source-files-archive.js.map +1 -0
- package/dist/capabilities/types.d.ts +197 -119
- package/dist/capabilities/types.js +45 -6
- package/dist/capabilities/types.js.map +1 -1
- package/dist/capture/browser-contract.d.ts +15 -5
- package/dist/capture/browser-contract.js +13 -3
- package/dist/capture/browser-contract.js.map +1 -1
- package/dist/capture/browser-instructions.d.ts +3 -2
- package/dist/capture/browser-instructions.js +3 -2
- package/dist/capture/browser-instructions.js.map +1 -1
- package/dist/capture/mode.d.ts +8 -1
- package/dist/capture/mode.js +22 -2
- package/dist/capture/mode.js.map +1 -1
- package/dist/config.d.ts +22 -23
- package/dist/config.js +13 -12
- package/dist/config.js.map +1 -1
- package/dist/deps.d.ts +7 -7
- package/dist/index.d.ts +2 -4
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/integrations/read-only-postgres-query.d.ts +2 -0
- package/dist/integrations/read-only-postgres-query.js +164 -0
- package/dist/integrations/read-only-postgres-query.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/playwright/ensure-chromium.d.ts +5 -7
- package/dist/playwright/ensure-chromium.js +13 -13
- package/dist/playwright/ensure-chromium.js.map +1 -1
- package/dist/preview/capture-screenshot.d.ts +30 -4
- package/dist/preview/capture-screenshot.js +67 -17
- package/dist/preview/capture-screenshot.js.map +1 -1
- package/dist/preview/viewer-url.js +3 -1
- package/dist/preview/viewer-url.js.map +1 -1
- package/dist/process/fault-barrier.js +1 -1
- package/dist/process/fault-barrier.js.map +1 -1
- package/dist/sabs/agent-facing-text.d.ts +2 -0
- package/dist/sabs/agent-facing-text.js +56 -2
- package/dist/sabs/agent-facing-text.js.map +1 -1
- package/dist/sabs/app-state.d.ts +126 -0
- package/dist/sabs/app-state.js +332 -0
- package/dist/sabs/app-state.js.map +1 -0
- package/dist/sabs/awaited-decision.d.ts +49 -0
- package/dist/sabs/awaited-decision.js +129 -0
- package/dist/sabs/awaited-decision.js.map +1 -0
- package/dist/sabs/editor-client-methods.d.ts +23 -5
- package/dist/sabs/editor-client-methods.js +45 -4
- package/dist/sabs/editor-client-methods.js.map +1 -1
- package/dist/sabs/editor-socket.d.ts +85 -0
- package/dist/sabs/editor-socket.js +67 -0
- package/dist/sabs/editor-socket.js.map +1 -0
- package/dist/sabs/session-peer.d.ts +119 -82
- package/dist/sabs/session-peer.js +10 -1
- package/dist/sabs/session-peer.js.map +1 -1
- package/dist/sabs/streamed-reply.d.ts +45 -0
- package/dist/sabs/streamed-reply.js +125 -0
- package/dist/sabs/streamed-reply.js.map +1 -0
- package/dist/sabs/turn-collector.d.ts +50 -35
- package/dist/sabs/turn-collector.js +110 -176
- package/dist/sabs/turn-collector.js.map +1 -1
- package/dist/sabs/websocket-session-peer.d.ts +104 -69
- package/dist/sabs/websocket-session-peer.js +1333 -477
- package/dist/sabs/websocket-session-peer.js.map +1 -1
- package/dist/server/client.d.ts +41 -9
- package/dist/server/client.js +126 -21
- package/dist/server/client.js.map +1 -1
- package/dist/start.d.ts +1 -1
- package/dist/start.js +30 -8
- package/dist/start.js.map +1 -1
- package/dist/stores/memory.d.ts +46 -0
- package/dist/stores/memory.js +163 -0
- package/dist/stores/memory.js.map +1 -0
- package/dist/stores/types.d.ts +92 -0
- package/dist/stores/types.js +11 -0
- package/dist/stores/types.js.map +1 -0
- package/dist/telemetry/mcp-client.d.ts +6 -1
- package/dist/telemetry/mcp-client.js +100 -4
- package/dist/telemetry/mcp-client.js.map +1 -1
- package/dist/telemetry/metrics.d.ts +12 -3
- package/dist/telemetry/metrics.js +60 -14
- package/dist/telemetry/metrics.js.map +1 -1
- package/dist/telemetry/runtime.js +4 -6
- package/dist/telemetry/runtime.js.map +1 -1
- package/dist/transports/mcp/admin-tools.d.ts +8 -0
- package/dist/transports/mcp/admin-tools.js +115 -4
- package/dist/transports/mcp/admin-tools.js.map +1 -1
- package/dist/transports/mcp/app-status-html.d.ts +4 -8
- package/dist/transports/mcp/app-status-html.js +336 -128
- package/dist/transports/mcp/app-status-html.js.map +1 -1
- package/dist/transports/mcp/client-presentation.d.ts +16 -0
- package/dist/transports/mcp/client-presentation.js +13 -0
- package/dist/transports/mcp/client-presentation.js.map +1 -0
- package/dist/transports/mcp/cowork-editor-url.d.ts +6 -0
- package/dist/transports/mcp/cowork-editor-url.js +10 -0
- package/dist/transports/mcp/cowork-editor-url.js.map +1 -0
- package/dist/transports/mcp/decision-card-html.d.ts +26 -0
- package/dist/transports/mcp/decision-card-html.js +876 -0
- package/dist/transports/mcp/decision-card-html.js.map +1 -0
- package/dist/transports/mcp/decision-elicitation.d.ts +42 -0
- package/dist/transports/mcp/decision-elicitation.js +59 -0
- package/dist/transports/mcp/decision-elicitation.js.map +1 -1
- package/dist/transports/mcp/editor-document-probe.d.ts +4 -0
- package/dist/transports/mcp/editor-document-probe.js +35 -0
- package/dist/transports/mcp/editor-document-probe.js.map +1 -0
- package/dist/transports/mcp/editor-integration-setup-url.d.ts +14 -0
- package/dist/transports/mcp/editor-integration-setup-url.js +29 -0
- package/dist/transports/mcp/editor-integration-setup-url.js.map +1 -0
- package/dist/transports/mcp/format-tool-content.d.ts +13 -18
- package/dist/transports/mcp/format-tool-content.js +172 -13
- package/dist/transports/mcp/format-tool-content.js.map +1 -1
- package/dist/transports/mcp/instructions/index.d.ts +23 -0
- package/dist/transports/mcp/instructions/index.js +81 -0
- package/dist/transports/mcp/instructions/index.js.map +1 -0
- package/dist/transports/mcp/instructions/result.d.ts +18 -0
- package/dist/transports/mcp/instructions/result.js +58 -0
- package/dist/transports/mcp/instructions/result.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/ask-user.d.ts +2 -0
- package/dist/transports/mcp/instructions/tools/ask-user.js +20 -0
- package/dist/transports/mcp/instructions/tools/ask-user.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/build-app.d.ts +4 -0
- package/dist/transports/mcp/instructions/tools/build-app.js +54 -0
- package/dist/transports/mcp/instructions/tools/build-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/check-app-progress.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/check-app-progress.js +79 -0
- package/dist/transports/mcp/instructions/tools/check-app-progress.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/check-publish-progress.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/check-publish-progress.js +23 -0
- package/dist/transports/mcp/instructions/tools/check-publish-progress.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/copy.d.ts +18 -0
- package/dist/transports/mcp/instructions/tools/copy.js +49 -0
- package/dist/transports/mcp/instructions/tools/copy.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/create-integration.d.ts +4 -0
- package/dist/transports/mcp/instructions/tools/create-integration.js +41 -0
- package/dist/transports/mcp/instructions/tools/create-integration.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/edit-app.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/edit-app.js +18 -0
- package/dist/transports/mcp/instructions/tools/edit-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/get-app.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/get-app.js +49 -0
- package/dist/transports/mcp/instructions/tools/get-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/get-integration-metadata.d.ts +2 -0
- package/dist/transports/mcp/instructions/tools/get-integration-metadata.js +13 -0
- package/dist/transports/mcp/instructions/tools/get-integration-metadata.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/index.d.ts +7 -0
- package/dist/transports/mcp/instructions/tools/index.js +31 -0
- package/dist/transports/mcp/instructions/tools/index.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/publish-app.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/publish-app.js +23 -0
- package/dist/transports/mcp/instructions/tools/publish-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/start-app.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/start-app.js +22 -0
- package/dist/transports/mcp/instructions/tools/start-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/upload-artifact.d.ts +2 -0
- package/dist/transports/mcp/instructions/tools/upload-artifact.js +13 -0
- package/dist/transports/mcp/instructions/tools/upload-artifact.js.map +1 -0
- package/dist/transports/mcp/mcp-app-brand-css.d.ts +1 -0
- package/dist/transports/mcp/mcp-app-brand-css.js +180 -0
- package/dist/transports/mcp/mcp-app-brand-css.js.map +1 -0
- package/dist/transports/mcp/mount.d.ts +14 -1
- package/dist/transports/mcp/mount.js +729 -172
- package/dist/transports/mcp/mount.js.map +1 -1
- package/dist/transports/mcp/native-browser-presence.d.ts +45 -0
- package/dist/transports/mcp/native-browser-presence.js +158 -0
- package/dist/transports/mcp/native-browser-presence.js.map +1 -0
- package/dist/transports/mcp/plan-approval.d.ts +44 -0
- package/dist/transports/mcp/plan-approval.js +179 -0
- package/dist/transports/mcp/plan-approval.js.map +1 -0
- package/dist/transports/mcp/session-directory.d.ts +7 -0
- package/dist/transports/mcp/session-directory.js +18 -0
- package/dist/transports/mcp/session-directory.js.map +1 -0
- package/dist/transports/mcp/tool-names.d.ts +2 -0
- package/dist/transports/mcp/tool-names.js +2 -0
- package/dist/transports/mcp/tool-names.js.map +1 -0
- package/package.json +16 -7
- package/skills/superblocks-build/SKILL.md +59 -0
- package/skills/superblocks-import/SKILL.md +125 -0
- package/dist/capabilities/import-prompt.d.ts +0 -11
- package/dist/capabilities/import-prompt.js +0 -96
- package/dist/capabilities/import-prompt.js.map +0 -1
- package/dist/capabilities/persisted-progress.d.ts +0 -46
- package/dist/capabilities/persisted-progress.js +0 -246
- package/dist/capabilities/persisted-progress.js.map +0 -1
- package/dist/events/cursor.d.ts +0 -43
- package/dist/events/cursor.js +0 -78
- package/dist/events/cursor.js.map +0 -1
- package/dist/events/memory-event-store.d.ts +0 -34
- package/dist/events/memory-event-store.js +0 -110
- package/dist/events/memory-event-store.js.map +0 -1
- package/dist/events/merge.d.ts +0 -23
- package/dist/events/merge.js +0 -97
- package/dist/events/merge.js.map +0 -1
- package/dist/events/normalized-collector.d.ts +0 -62
- package/dist/events/normalized-collector.js +0 -156
- package/dist/events/normalized-collector.js.map +0 -1
- package/dist/events/schema.d.ts +0 -9
- package/dist/events/schema.js +0 -93
- package/dist/events/schema.js.map +0 -1
- package/dist/events/snapshot.d.ts +0 -32
- package/dist/events/snapshot.js +0 -57
- package/dist/events/snapshot.js.map +0 -1
- package/dist/events/stream-key.d.ts +0 -2
- package/dist/events/stream-key.js +0 -31
- package/dist/events/stream-key.js.map +0 -1
- package/dist/events/types.d.ts +0 -179
- package/dist/events/types.js +0 -66
- package/dist/events/types.js.map +0 -1
- package/dist/resume/memory-progress-store.d.ts +0 -39
- package/dist/resume/memory-progress-store.js +0 -82
- package/dist/resume/memory-progress-store.js.map +0 -1
- package/dist/resume/memory-recent-app-store.d.ts +0 -14
- package/dist/resume/memory-recent-app-store.js +0 -27
- package/dist/resume/memory-recent-app-store.js.map +0 -1
- package/dist/resume/memory-turn-store.d.ts +0 -18
- package/dist/resume/memory-turn-store.js +0 -73
- package/dist/resume/memory-turn-store.js.map +0 -1
- package/dist/resume/progress-key.d.ts +0 -21
- package/dist/resume/progress-key.js +0 -58
- package/dist/resume/progress-key.js.map +0 -1
- package/dist/resume/stores.d.ts +0 -14
- package/dist/resume/stores.js +0 -18
- package/dist/resume/stores.js.map +0 -1
- package/dist/resume/types.d.ts +0 -124
- package/dist/resume/types.js +0 -13
- package/dist/resume/types.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superblocksteam/gateway",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.162-next.1",
|
|
4
4
|
"description": "Gateway v0 — MCP entry for app start/edit/publish",
|
|
5
5
|
"license": "Superblocks Community Software License",
|
|
6
6
|
"bin": {
|
|
7
7
|
"superblocks-gateway": "./dist/main.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"skills"
|
|
11
12
|
],
|
|
12
13
|
"type": "module",
|
|
13
14
|
"main": "dist/index.js",
|
|
@@ -16,16 +17,23 @@
|
|
|
16
17
|
"types": "./dist/index.d.ts",
|
|
17
18
|
"import": "./dist/index.js",
|
|
18
19
|
"default": "./dist/index.js"
|
|
19
|
-
}
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json",
|
|
22
|
+
"./skills/superblocks-import/SKILL.md": "./skills/superblocks-import/SKILL.md"
|
|
20
23
|
},
|
|
21
24
|
"dependencies": {
|
|
22
25
|
"@modelcontextprotocol/ext-apps": "^1.7.5",
|
|
23
26
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
24
27
|
"@opentelemetry/api": "^1.9.1",
|
|
25
|
-
"@superblocksteam/library-shared": "2.0.
|
|
26
|
-
"@superblocksteam/mcp-server": "2.0.
|
|
27
|
-
"@superblocksteam/shared": "0.
|
|
28
|
-
"@superblocksteam/telemetry": "2.0.
|
|
28
|
+
"@superblocksteam/library-shared": "2.0.162-next.1",
|
|
29
|
+
"@superblocksteam/mcp-server": "2.0.162-next.1",
|
|
30
|
+
"@superblocksteam/shared": "0.9613.1",
|
|
31
|
+
"@superblocksteam/telemetry": "2.0.162-next.1",
|
|
32
|
+
"fflate": "^0.8.3",
|
|
33
|
+
"libpg-query": "^17.7.4",
|
|
34
|
+
"mdast-util-from-markdown": "2.0.2",
|
|
35
|
+
"mdast-util-gfm-autolink-literal": "2.0.1",
|
|
36
|
+
"micromark-extension-gfm-autolink-literal": "2.1.0",
|
|
29
37
|
"playwright": "1.56.0",
|
|
30
38
|
"ws": "8.21.0",
|
|
31
39
|
"zod": "^4.3.6"
|
|
@@ -33,6 +41,7 @@
|
|
|
33
41
|
"devDependencies": {
|
|
34
42
|
"@eslint/js": "^9.39.2",
|
|
35
43
|
"@types/express": "^4.17.21",
|
|
44
|
+
"@types/mdast": "4.0.4",
|
|
36
45
|
"@types/node": "^24",
|
|
37
46
|
"@types/ws": "^8.18.1",
|
|
38
47
|
"eslint": "^9.39.2",
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: superblocks-build
|
|
3
|
+
description: >
|
|
4
|
+
Use when the user asks to build, create, change, update, edit, or modify an
|
|
5
|
+
app, dashboard, internal tool, admin panel, form, or CRUD UI - including one
|
|
6
|
+
they might otherwise make as a local file or artifact. Most requests never
|
|
7
|
+
say which location they mean. An existing or named app is still ambiguous
|
|
8
|
+
unless this conversation already established its location. Ask where it
|
|
9
|
+
should live before creating or editing anything and before using any tool;
|
|
10
|
+
do not list apps to infer the answer.
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Where does this app get built?
|
|
14
|
+
|
|
15
|
+
Two places can build what the user just asked for:
|
|
16
|
+
|
|
17
|
+
- **Superblocks** — a real application. Org datasources, server-side APIs,
|
|
18
|
+
platform auth and permissions, a deploy story, other people can use it.
|
|
19
|
+
- **Here** — a local file or artifact in this chat. Fast and private, but it
|
|
20
|
+
reaches no company data and nobody else can run it.
|
|
21
|
+
|
|
22
|
+
Most requests name neither. Choosing silently is wrong about half the time, and
|
|
23
|
+
the user only finds out once the work already exists in the wrong place.
|
|
24
|
+
|
|
25
|
+
## Ask first
|
|
26
|
+
|
|
27
|
+
Before creating or editing anything, ask one short question naming both options,
|
|
28
|
+
then wait for the answer:
|
|
29
|
+
|
|
30
|
+
> Do you want this built in Superblocks, or as a local artifact here?
|
|
31
|
+
|
|
32
|
+
If the location is ambiguous, your first action must be the two-option question
|
|
33
|
+
above. Do not call any Superblocks tool, including `list_applications`, or
|
|
34
|
+
create or edit a local artifact until the user answers.
|
|
35
|
+
|
|
36
|
+
Ask once per request. Do not build a local version "to show them" while waiting.
|
|
37
|
+
Building it is the choice.
|
|
38
|
+
|
|
39
|
+
## Do not ask when they already answered
|
|
40
|
+
|
|
41
|
+
- Said Superblocks, or explicitly named a Superblocks app already established in
|
|
42
|
+
this conversation -> build there.
|
|
43
|
+
- Said local, artifact, file, HTML, "just show me", "quick mockup" -> build here.
|
|
44
|
+
- Answered this question for this same request -> honor it, stay silent.
|
|
45
|
+
- Not an app at all (a script, a chart, an analysis, a document, a snippet)
|
|
46
|
+
-> just do the work.
|
|
47
|
+
|
|
48
|
+
## Editing counts too
|
|
49
|
+
|
|
50
|
+
The same question applies to changing an app, dashboard, or artifact the user
|
|
51
|
+
names, including one already imported into Superblocks. When you cannot tell
|
|
52
|
+
which copy they mean, ask that instead.
|
|
53
|
+
|
|
54
|
+
## Once they pick Superblocks
|
|
55
|
+
|
|
56
|
+
- Something new -> `start_app`.
|
|
57
|
+
- Existing source to port -> use the `superblocks-import` skill.
|
|
58
|
+
- An app already in Superblocks -> `list_applications` to find it, then
|
|
59
|
+
`edit_app`.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: superblocks-import
|
|
3
|
+
description: >
|
|
4
|
+
Import, migrate, or port an existing app (React, Replit, Lovable, v0, Streamlit,
|
|
5
|
+
a zip on disk, or files in the conversation) into Superblocks. Use when the
|
|
6
|
+
user has existing source and wants it as a Superblocks application — not when
|
|
7
|
+
they are only editing an app that already exists in Superblocks.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Superblocks import (host director)
|
|
11
|
+
|
|
12
|
+
You plan and slice. **Superblocks writes** the application through Builder MCP
|
|
13
|
+
(`start_app` / `edit_app`). Do not invent Superblocks `client/` or `server/`
|
|
14
|
+
files on the laptop. Superblocks already has its own in-sandbox migration
|
|
15
|
+
skillset; your job is to ask for the right slices.
|
|
16
|
+
|
|
17
|
+
## Choose the source path
|
|
18
|
+
|
|
19
|
+
Check source files and archives for secrets and production data before uploading.
|
|
20
|
+
Keep placeholder configuration such as `.env.example`, not real credentials.
|
|
21
|
+
|
|
22
|
+
When source files are already visible in this conversation, call
|
|
23
|
+
`upload_artifact` with `files: [{ path, content }]`. Keep their original
|
|
24
|
+
relative paths; do not write or zip them first. Pass the returned `artifact` to
|
|
25
|
+
`start_app` in `artifacts` and ask Superblocks to migrate the attached source.
|
|
26
|
+
|
|
27
|
+
When the source is a readable tree on disk, inventory it locally, then
|
|
28
|
+
archive the source and assets with their original relative paths. Exclude
|
|
29
|
+
`.git`, `node_modules`, build output, secrets, and production data; inspect
|
|
30
|
+
the archive before uploading it. Call `upload_artifact` with the archive's
|
|
31
|
+
`filePath` and pass its returned `artifact` unchanged in `start_app.artifacts`.
|
|
32
|
+
Local paths and prose descriptions are not a substitute for the source artifact:
|
|
33
|
+
Superblocks cannot read the host's workspace. Ask Superblocks to read the
|
|
34
|
+
attached source and preserve its UI and behavior, not recreate it from prose.
|
|
35
|
+
|
|
36
|
+
For an existing source archive, call `upload_artifact` with
|
|
37
|
+
`filePath` (never `zipBase64`), then pass its `artifact` to `start_app` in
|
|
38
|
+
`artifacts`. Archives over 50 MB are rejected; request a smaller source export
|
|
39
|
+
without dependencies or build output rather than silently omitting source.
|
|
40
|
+
If the gateway cannot read the host path, use `files` for text within the
|
|
41
|
+
tool's limits. For binary assets, ask for an accessible export; never encode
|
|
42
|
+
them as text or silently leave them out.
|
|
43
|
+
|
|
44
|
+
Keep the returned artifact and application IDs. To resume, reuse the same
|
|
45
|
+
artifact ID with `edit_app` and the same application ID. Do not upload the
|
|
46
|
+
source again, and do not call `start_app` again.
|
|
47
|
+
|
|
48
|
+
Replit / Lovable / v0: clone or export onto this machine first. Do not ask
|
|
49
|
+
the live-edit environment to fetch those clouds.
|
|
50
|
+
|
|
51
|
+
## Slice order
|
|
52
|
+
|
|
53
|
+
1. Inventory locally (routes, env keys, ORMs, `fetch`/`axios`, tests). Keep
|
|
54
|
+
the source app running if you can. Map secrets from `.env.example` — never
|
|
55
|
+
paste production `.env` into `edit_app`.
|
|
56
|
+
2. `list_integrations`. Reuse an existing datasource (`find_apps_by_integration`)
|
|
57
|
+
before `create_integration`.
|
|
58
|
+
3. `start_app` with the user's import request, named integrations, and the
|
|
59
|
+
uploaded source in `artifacts`. Ask Superblocks to read and migrate that
|
|
60
|
+
source, preserving its UI and behavior.
|
|
61
|
+
`start_app` defaults to Plan mode. Pass `mode: "BUILD"` only if the user
|
|
62
|
+
asks for build mode explicitly (e.g. "use build mode" or "skip the plan").
|
|
63
|
+
Otherwise, follow the returned `agentInstructions` to present the first
|
|
64
|
+
plan and collect the user's decision. When `decision.plan` is returned,
|
|
65
|
+
show it in full, verbatim as Markdown in chat, not inside a form. For this
|
|
66
|
+
plan decision, use the native form only for `Approve` / `Refine` when
|
|
67
|
+
instructed, or use the instructed fallback, then wait for their answer.
|
|
68
|
+
Only if they approve, call `edit_app` with `planAction: "approve"` instead
|
|
69
|
+
of planning it again. Do not run a second “migrate everything” plan.
|
|
70
|
+
Mode is per call and never sticks: every `edit_app` below plans unless it
|
|
71
|
+
passes `mode: "BUILD"`, so send it on each slice.
|
|
72
|
+
4. One backend operation per `edit_app`, then `check_app_progress` while the
|
|
73
|
+
slice is building, handling any requested decision. For interrupted or
|
|
74
|
+
unknown turns and errors, follow returned `agentInstructions` and
|
|
75
|
+
`pendingAction`, including stop or user continuation requirements; missing
|
|
76
|
+
`recentRuns` alone is not permission to restart. Check the completed slice's
|
|
77
|
+
runtime outcome in `recentRuns` or Superblocks' report. Only for a completed
|
|
78
|
+
slice, if verification is missing or failed, send a focused `edit_app` to
|
|
79
|
+
test or fix the same API, not more polling of a finished turn. Advance only
|
|
80
|
+
when the API passed or testing was explicitly skipped with a reason
|
|
81
|
+
reported as unverified. There is no MCP SQL tool.
|
|
82
|
+
5. One UI route per `edit_app`, wired to APIs whose verification was resolved
|
|
83
|
+
above.
|
|
84
|
+
6. Auth, jobs, leftovers last.
|
|
85
|
+
7. After each slice, `get_application_structure` (and `get_app` URLs). Ground
|
|
86
|
+
the next prompt in what Superblocks actually wrote. `list_knowledge` /
|
|
87
|
+
`get_knowledge` for org playbooks.
|
|
88
|
+
|
|
89
|
+
`list_applications` if `start_app` errors: the app may already exist.
|
|
90
|
+
|
|
91
|
+
Follow `browserNavigation` by opening its exact URL when returned, and
|
|
92
|
+
`agentInstructions` for editor-only decisions. Do not open an app preview
|
|
93
|
+
before `viewStatus` is ready.
|
|
94
|
+
|
|
95
|
+
## Primitive map (not Next.js)
|
|
96
|
+
|
|
97
|
+
- Backend operations are **named APIs** in a registry, not URL routes.
|
|
98
|
+
- Each UI page is a Superblocks page using `useApi` / `useApiData` /
|
|
99
|
+
`executeApi` from the fullstack template — not Next App Router, not the
|
|
100
|
+
source app’s QueryClient.
|
|
101
|
+
- Datasources are **org integrations** (UUIDs). Credentials live there, not
|
|
102
|
+
`process.env` in generated code. Auth is platform user context; drop the
|
|
103
|
+
source login stack unless Superblocks asks otherwise.
|
|
104
|
+
|
|
105
|
+
## `edit_app` prompt shape
|
|
106
|
+
|
|
107
|
+
Ask Superblocks to implement **this slice** as fullstack (APIs vs pages vs
|
|
108
|
+
integrations). Tell it to follow its third-party migration skillset. Reuse the
|
|
109
|
+
uploaded artifact in `edit_app.artifacts` and cite its relative source paths;
|
|
110
|
+
small excerpts can clarify a change but do not replace the attached source.
|
|
111
|
+
|
|
112
|
+
For every backend slice, include this in the `edit_app` prompt:
|
|
113
|
+
|
|
114
|
+
> After implementing this API, run `testApi` with representative inputs and
|
|
115
|
+
> verify the expected result, then report the API name, passed/failed/skipped,
|
|
116
|
+
> and the concrete outcome before finishing this slice. For mutating tests,
|
|
117
|
+
> honor the tool's permission checks; if denied or the user explicitly asks
|
|
118
|
+
> to skip testing, report skipped with the reason. Do not claim untested APIs
|
|
119
|
+
> passed.
|
|
120
|
+
|
|
121
|
+
## Do not
|
|
122
|
+
|
|
123
|
+
- `browser_evaluate` JWTs; `browser_close` / Playwright `--isolated` between
|
|
124
|
+
IdP and retry.
|
|
125
|
+
- Dump `.env` or production data into prompts.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { ImportAppSource } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Archive names land in instruction-bearing prompt text. Keep a single-line
|
|
4
|
-
* basename so a crafted zip path cannot inject newlines or role-play into Clark.
|
|
5
|
-
*/
|
|
6
|
-
export declare function sanitizeArchiveDisplayName(zipFileName: string): string;
|
|
7
|
-
export declare function buildImportPrompt(input: {
|
|
8
|
-
extraPrompt?: string;
|
|
9
|
-
source: ImportAppSource;
|
|
10
|
-
zipFileName: string;
|
|
11
|
-
}): string;
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Migration prompts mirror the browser MigrationModal templates so Clark loads
|
|
3
|
-
* the same skills and inspects the attached archive the same way.
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* The browser migration flow leans on the `third-party-migration` skill, which
|
|
7
|
-
* ends by deferring verification to "the user running the app" — and is dropped
|
|
8
|
-
* entirely unless the org has `ui.third-party-import.enabled`. Neither holds
|
|
9
|
-
* here: no one is clicking through a headless migration, and the gateway hands
|
|
10
|
-
* Clark the org's integrations plus a live `testApi` on every turn. Say so in
|
|
11
|
-
* the prompt rather than hoping a skill is loaded.
|
|
12
|
-
*/
|
|
13
|
-
const API_VERIFICATION_INSTRUCTION = `Nobody is watching this migration in a browser, so you verify your own work. This turn's context lists the org's integrations — use them for the data sources you find in the project. Run every API you create or change through testApi before you report the migration finished, and say what testApi returned, failures included. Do not defer API verification to the user, and do not treat testApi as unavailable during a migration.`;
|
|
14
|
-
function withMigrationSkillInstruction(prompt) {
|
|
15
|
-
return `Please follow the migration guidelines as detailed in your skillset.
|
|
16
|
-
|
|
17
|
-
${prompt}`;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Archive names land in instruction-bearing prompt text. Keep a single-line
|
|
21
|
-
* basename so a crafted zip path cannot inject newlines or role-play into Clark.
|
|
22
|
-
*/
|
|
23
|
-
export function sanitizeArchiveDisplayName(zipFileName) {
|
|
24
|
-
const base = zipFileName.replace(/\\/g, "/").split("/").pop() ?? "archive.zip";
|
|
25
|
-
let cleaned = "";
|
|
26
|
-
for (const ch of base) {
|
|
27
|
-
const code = ch.codePointAt(0) ?? 0;
|
|
28
|
-
// Drop C0 controls and DEL so a crafted basename cannot inject newlines
|
|
29
|
-
// into instruction-bearing prompt text.
|
|
30
|
-
if (code >= 32 && code !== 127) {
|
|
31
|
-
cleaned += ch;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
cleaned = cleaned.trim();
|
|
35
|
-
return cleaned.length > 0 ? cleaned : "archive.zip";
|
|
36
|
-
}
|
|
37
|
-
function genericImportPrompt(zipFileName) {
|
|
38
|
-
return withMigrationSkillInstruction(`Import this codebase into Superblocks. The project is attached as ${zipFileName}. Inspect the structure, identify the framework and data sources, then migrate it into the current Superblocks fullstack app.`);
|
|
39
|
-
}
|
|
40
|
-
const SOURCE_PROMPTS = {
|
|
41
|
-
chatgpt: genericImportPrompt,
|
|
42
|
-
claude: genericImportPrompt,
|
|
43
|
-
"claude-design": (zipFileName) => withMigrationSkillInstruction(`Migrate this Claude Design app into Superblocks. The exported project is attached as ${zipFileName}.`),
|
|
44
|
-
lovable: (zipFileName) => withMigrationSkillInstruction(`Migrate this Lovable app into Superblocks. The exported project is attached as ${zipFileName}.`),
|
|
45
|
-
replit: (zipFileName) => withMigrationSkillInstruction(`Migrate this Replit app into Superblocks. The exported project is attached as ${zipFileName}.`),
|
|
46
|
-
streamlit: genericImportPrompt,
|
|
47
|
-
v0: (zipFileName) => withMigrationSkillInstruction(`Migrate this v0 app into Superblocks. The exported project is attached as ${zipFileName}.`),
|
|
48
|
-
zip: genericImportPrompt,
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* Builds the Clark prompt for an import turn. Optional `extraPrompt` is the
|
|
52
|
-
* caller's intent (e.g. "make it more secure"), appended after the template.
|
|
53
|
-
*/
|
|
54
|
-
function promptForSource(source, zipFileName) {
|
|
55
|
-
// Exhaustive switch with direct calls — no dynamic property lookup — so
|
|
56
|
-
// CodeQL cannot treat `source` as an unvalidated method name.
|
|
57
|
-
switch (source) {
|
|
58
|
-
case "chatgpt":
|
|
59
|
-
return SOURCE_PROMPTS.chatgpt(zipFileName);
|
|
60
|
-
case "claude":
|
|
61
|
-
return SOURCE_PROMPTS.claude(zipFileName);
|
|
62
|
-
case "claude-design":
|
|
63
|
-
return SOURCE_PROMPTS["claude-design"](zipFileName);
|
|
64
|
-
case "lovable":
|
|
65
|
-
return SOURCE_PROMPTS.lovable(zipFileName);
|
|
66
|
-
case "replit":
|
|
67
|
-
return SOURCE_PROMPTS.replit(zipFileName);
|
|
68
|
-
case "streamlit":
|
|
69
|
-
return SOURCE_PROMPTS.streamlit(zipFileName);
|
|
70
|
-
case "v0":
|
|
71
|
-
return SOURCE_PROMPTS.v0(zipFileName);
|
|
72
|
-
case "zip":
|
|
73
|
-
return SOURCE_PROMPTS.zip(zipFileName);
|
|
74
|
-
default: {
|
|
75
|
-
const _exhaustive = source;
|
|
76
|
-
throw new Error(`unsupported import source: ${String(_exhaustive)}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
export function buildImportPrompt(input) {
|
|
81
|
-
const zipFileName = sanitizeArchiveDisplayName(input.zipFileName);
|
|
82
|
-
const base = promptForSource(input.source, zipFileName);
|
|
83
|
-
const extra = input.extraPrompt?.trim();
|
|
84
|
-
// Verification goes last: a caller asking to "just get it running" should not
|
|
85
|
-
// end up with a migration that reports untested APIs.
|
|
86
|
-
const intent = extra
|
|
87
|
-
? `${base}
|
|
88
|
-
|
|
89
|
-
Additional instructions from the user:
|
|
90
|
-
${extra}`
|
|
91
|
-
: base;
|
|
92
|
-
return `${intent}
|
|
93
|
-
|
|
94
|
-
${API_VERIFICATION_INSTRUCTION}`;
|
|
95
|
-
}
|
|
96
|
-
//# sourceMappingURL=import-prompt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"import-prompt.js","sourceRoot":"","sources":["../../src/capabilities/import-prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { EventSnapshot } from "../events/types.js";
|
|
2
|
-
import type { BuildStatus, GenerationStatus } from "./types.js";
|
|
3
|
-
export type PersistedProgress = {
|
|
4
|
-
/** Superblocks' own words since this caller last read, oldest first. */
|
|
5
|
-
activity: string[];
|
|
6
|
-
/** Set when the build is stuck waiting for an interactive authorization. */
|
|
7
|
-
authRequiredReason?: string;
|
|
8
|
-
/** Present once the persisted stream shows the turn reached a terminal state. */
|
|
9
|
-
generationStatus?: GenerationStatus;
|
|
10
|
-
/** Newest assistant message, so a resumed caller can report the outcome. */
|
|
11
|
-
reply?: string;
|
|
12
|
-
status: BuildStatus;
|
|
13
|
-
};
|
|
14
|
-
/**
|
|
15
|
-
* Reads a build's state out of what was persisted, for a caller that has no
|
|
16
|
-
* live turn to ask.
|
|
17
|
-
*
|
|
18
|
-
* The two halves of a snapshot answer different questions and are used
|
|
19
|
-
* differently. Activity comes from the window after the caller's cursor,
|
|
20
|
-
* because that is what is new *to this caller*. State comes from the tail of
|
|
21
|
-
* the stream regardless of the cursor, because a caller that already consumed
|
|
22
|
-
* the terminal event still needs to be told the build finished — reading
|
|
23
|
-
* state from the after-cursor window would tell it nothing is known and send
|
|
24
|
-
* it back to poll a turn that ended.
|
|
25
|
-
*/
|
|
26
|
-
export declare function readPersistedProgress(snapshot: Pick<EventSnapshot, "events" | "tail">, liveness: StreamLiveness,
|
|
27
|
-
/**
|
|
28
|
-
* The quiet window a `completed` must outlast, which has to be the same one
|
|
29
|
-
* the live turn settled with (`config.clarkSettleMs`). Defaults to the
|
|
30
|
-
* collector's constant so a caller with no config in hand still reads the
|
|
31
|
-
* stream the way an untuned gateway wrote it.
|
|
32
|
-
*/
|
|
33
|
-
settleMs?: number): PersistedProgress;
|
|
34
|
-
/**
|
|
35
|
-
* How to judge whether what the stream last said is still true.
|
|
36
|
-
*
|
|
37
|
-
* Required rather than optional so no caller can read a status the rule was
|
|
38
|
-
* never applied to: the whole point of reading state here is that `get_app` and
|
|
39
|
-
* `check_app_progress` stop contradicting each other about one app, and an
|
|
40
|
-
* omitted rule is how they would drift apart again (ENG-5808).
|
|
41
|
-
*/
|
|
42
|
-
export type StreamLiveness = {
|
|
43
|
-
nowMs: number;
|
|
44
|
-
/** How long the work can be silent before the stream stops meaning it. */
|
|
45
|
-
staleAfterMs: number;
|
|
46
|
-
};
|
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_SETTLE_MS } from "../sabs/turn-collector.js";
|
|
2
|
-
import { buildStatusOf } from "./types.js";
|
|
3
|
-
/**
|
|
4
|
-
* Reads a build's state out of what was persisted, for a caller that has no
|
|
5
|
-
* live turn to ask.
|
|
6
|
-
*
|
|
7
|
-
* The two halves of a snapshot answer different questions and are used
|
|
8
|
-
* differently. Activity comes from the window after the caller's cursor,
|
|
9
|
-
* because that is what is new *to this caller*. State comes from the tail of
|
|
10
|
-
* the stream regardless of the cursor, because a caller that already consumed
|
|
11
|
-
* the terminal event still needs to be told the build finished — reading
|
|
12
|
-
* state from the after-cursor window would tell it nothing is known and send
|
|
13
|
-
* it back to poll a turn that ended.
|
|
14
|
-
*/
|
|
15
|
-
export function readPersistedProgress(snapshot, liveness,
|
|
16
|
-
/**
|
|
17
|
-
* The quiet window a `completed` must outlast, which has to be the same one
|
|
18
|
-
* the live turn settled with (`config.clarkSettleMs`). Defaults to the
|
|
19
|
-
* collector's constant so a caller with no config in hand still reads the
|
|
20
|
-
* stream the way an untuned gateway wrote it.
|
|
21
|
-
*/
|
|
22
|
-
settleMs = DEFAULT_SETTLE_MS) {
|
|
23
|
-
const activity = [];
|
|
24
|
-
for (const event of snapshot.events) {
|
|
25
|
-
const line = activityLine(event);
|
|
26
|
-
// The collector drops a repeated progress line for the same reason: a
|
|
27
|
-
// build that says "Installing dependencies" twice in a row has not told
|
|
28
|
-
// the reader anything the second time.
|
|
29
|
-
if (line && line !== activity[activity.length - 1]) {
|
|
30
|
-
activity.push(line);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
let authRequiredReason;
|
|
34
|
-
let generationStatus;
|
|
35
|
-
let reply;
|
|
36
|
-
let status = snapshot.tail.length > 0 ? "building" : "unknown";
|
|
37
|
-
// When the turn last reported it was done, and when its session went away.
|
|
38
|
-
// Whether the first of those had settled before the second decides which of
|
|
39
|
-
// them is the outcome.
|
|
40
|
-
let completedAtMs;
|
|
41
|
-
let teardownAtMs;
|
|
42
|
-
for (const event of snapshot.tail) {
|
|
43
|
-
if (event.payload.kind === "auth_required") {
|
|
44
|
-
authRequiredReason = event.payload.reason ?? "auth_required";
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
if (event.payload.kind === "chat_message" &&
|
|
48
|
-
event.payload.role === "assistant") {
|
|
49
|
-
reply = event.payload.text;
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (event.payload.kind === "session") {
|
|
53
|
-
// SABS tearing the live edit down settles a turn that never settled
|
|
54
|
-
// itself: the dev server exits silently when it loses its lock, so no
|
|
55
|
-
// terminal generation_state is coming and a caller reading from the
|
|
56
|
-
// stream would otherwise be told "building" forever.
|
|
57
|
-
//
|
|
58
|
-
// Not every teardown is that, though. Every healthy build ends with its
|
|
59
|
-
// session going away too, and reading that as a dead live edit would
|
|
60
|
-
// report each finished app as a failure. Which one this is comes down to
|
|
61
|
-
// whether the turn had really finished first - see `teardownEndsTurn`.
|
|
62
|
-
if (event.payload.status !== "terminated") {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
teardownAtMs = event.occurredAtMs;
|
|
66
|
-
if (!teardownEndsTurn(generationStatus, completedAtMs, teardownAtMs, settleMs)) {
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
generationStatus = "live_edit_terminated";
|
|
70
|
-
status = buildStatusOf(generationStatus);
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
if (event.payload.kind !== "generation_state") {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
// Later states supersede earlier ones: a build that went back to
|
|
77
|
-
// generating after an idle blip is generating.
|
|
78
|
-
//
|
|
79
|
-
// A torn-down live edit is the exception. The dev server cannot report
|
|
80
|
-
// progress after SABS has killed it, so a non-terminal state stamped
|
|
81
|
-
// later than the teardown is skew between two producers merged by
|
|
82
|
-
// `occurredAtMs`, not news that the turn revived. Letting it through
|
|
83
|
-
// would put the caller back to polling the dead session this status
|
|
84
|
-
// exists to name. Only another terminal state outranks the teardown.
|
|
85
|
-
const state = terminalStatus(event.payload.state);
|
|
86
|
-
if (!state && generationStatus === "live_edit_terminated") {
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
// A `completed` the teardown already cut short does not come back to life
|
|
90
|
-
// by being listed second. The two producers stamp their own clocks, so the
|
|
91
|
-
// tail can carry the pair either way round; the same pair of facts has to
|
|
92
|
-
// reach the same outcome both times.
|
|
93
|
-
if (state === "completed" &&
|
|
94
|
-
generationStatus === "live_edit_terminated" &&
|
|
95
|
-
teardownAtMs !== undefined &&
|
|
96
|
-
!outlastedSettleWindow(event.occurredAtMs, teardownAtMs, settleMs)) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
completedAtMs = state === "completed" ? event.occurredAtMs : undefined;
|
|
100
|
-
generationStatus = state;
|
|
101
|
-
status = state ? buildStatusOf(state) : "building";
|
|
102
|
-
}
|
|
103
|
-
// Applied after the tail, not before it: the loop above assigns `building` for
|
|
104
|
-
// every non-terminal generation state it sees, so a rule that only set the
|
|
105
|
-
// initial value would be overwritten by the very events it exists to judge.
|
|
106
|
-
//
|
|
107
|
-
// Only a non-terminal reading expires. How a turn ended is a fact - a
|
|
108
|
-
// completed turn stays completed and a torn-down live edit stays torn down -
|
|
109
|
-
// and an old terminal state is the answer a caller needs, not a stale one.
|
|
110
|
-
if (!generationStatus && !reportsLiveWork(snapshot.tail, liveness)) {
|
|
111
|
-
status = "unknown";
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
activity,
|
|
115
|
-
...(authRequiredReason ? { authRequiredReason } : {}),
|
|
116
|
-
...(generationStatus ? { generationStatus } : {}),
|
|
117
|
-
...(reply ? { reply } : {}),
|
|
118
|
-
status,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Whether a `completed` had closed its quiet window before the teardown
|
|
123
|
-
* landed.
|
|
124
|
-
*
|
|
125
|
-
* `completed` is provisional until it settles: the gateway checkpoints Clark's
|
|
126
|
-
* files only once the window closes, and that checkpoint runs over the socket
|
|
127
|
-
* to the dev server. A teardown inside the window therefore means no
|
|
128
|
-
* checkpoint could have landed - the same conclusion the live path draws from
|
|
129
|
-
* the same pair of facts, so a caller holding the turn and a caller reading
|
|
130
|
-
* the stream cannot answer differently. The gateway holds the socket for a
|
|
131
|
-
* release grace that outlasts this window, so a healthy build's teardown is
|
|
132
|
-
* never mistaken for one.
|
|
133
|
-
*
|
|
134
|
-
* Distance, not order: the two producers stamp their own clocks.
|
|
135
|
-
*/
|
|
136
|
-
function outlastedSettleWindow(completedAtMs, teardownAtMs, settleMs) {
|
|
137
|
-
return Math.abs(teardownAtMs - completedAtMs) >= settleMs;
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Whether a teardown is this turn's outcome rather than the tail of one that
|
|
141
|
-
* had already finished.
|
|
142
|
-
*
|
|
143
|
-
* Nothing terminal read yet means the dev server never reported an end and
|
|
144
|
-
* never will. `cancelled` and `needs_decision` settle the moment they arrive,
|
|
145
|
-
* so a later teardown leaves them standing. Only `completed` has a window it
|
|
146
|
-
* can be cut short inside.
|
|
147
|
-
*/
|
|
148
|
-
function teardownEndsTurn(generationStatus, completedAtMs, teardownAtMs, settleMs) {
|
|
149
|
-
if (!generationStatus) {
|
|
150
|
-
return true;
|
|
151
|
-
}
|
|
152
|
-
if (generationStatus !== "completed" || completedAtMs === undefined) {
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
return !outlastedSettleWindow(completedAtMs, teardownAtMs, settleMs);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* How a persisted generation state reads as a finished turn, or undefined
|
|
159
|
-
* while the build is still going.
|
|
160
|
-
*
|
|
161
|
-
* `idle` counts as finished for the same reason the live collector treats it
|
|
162
|
-
* that way: it is what Superblocks reports when it has stopped working and is
|
|
163
|
-
* not waiting for anything.
|
|
164
|
-
*/
|
|
165
|
-
function terminalStatus(state) {
|
|
166
|
-
switch (state) {
|
|
167
|
-
case "awaiting_user_input":
|
|
168
|
-
return "needs_decision";
|
|
169
|
-
case "cancelled":
|
|
170
|
-
return "cancelled";
|
|
171
|
-
case "completed":
|
|
172
|
-
case "idle":
|
|
173
|
-
return "completed";
|
|
174
|
-
default:
|
|
175
|
-
return undefined;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Whether the tail is evidence of a build that is still going, short of any
|
|
180
|
-
* terminal state.
|
|
181
|
-
*
|
|
182
|
-
* Two things disqualify it. The caller's own prompt coming back is not a report
|
|
183
|
-
* of work - which events a producer emits is settled in another package and, for
|
|
184
|
-
* SABS, another repository, so this asks to be shown the work rather than
|
|
185
|
-
* trusting that a user message is never left in a stream on its own. And the
|
|
186
|
-
* tail is bounded, so a turn's terminal event can age out of it and leave a
|
|
187
|
-
* finished build looking like a running one forever; work that has been silent
|
|
188
|
-
* for longer than a turn can last has ended, whatever the stream still holds.
|
|
189
|
-
*
|
|
190
|
-
* Both halves read the same events on purpose. Judging the age by anything the
|
|
191
|
-
* stream carried, the prompt included, let a new prompt hold the clock open over
|
|
192
|
-
* work that had stopped talking a whole turn budget earlier.
|
|
193
|
-
*
|
|
194
|
-
* TODO(ENG-5896): `occurredAtMs` is stamped by the producer, so the age below is
|
|
195
|
-
* arithmetic across two machines' clocks. A stamp from the future is read as
|
|
196
|
-
* fresh here rather than stale, which covers a producer running ahead; a
|
|
197
|
-
* producer running far enough behind still reads as silent. Closing that needs a
|
|
198
|
-
* gateway-side receive timestamp at ingress.
|
|
199
|
-
*/
|
|
200
|
-
function reportsLiveWork(tail, liveness) {
|
|
201
|
-
let newestAtMs;
|
|
202
|
-
for (const event of tail) {
|
|
203
|
-
if (reportsWork(event)) {
|
|
204
|
-
newestAtMs = Math.max(newestAtMs ?? 0, event.occurredAtMs);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
if (newestAtMs === undefined) {
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
const ageMs = liveness.nowMs - newestAtMs;
|
|
211
|
-
if (ageMs < 0) {
|
|
212
|
-
// Not silence: the producer's clock is ahead of ours. Calling that stale
|
|
213
|
-
// would be reading a clock difference as the end of a build.
|
|
214
|
-
console.warn("gateway persisted stream is stamped in the future", {
|
|
215
|
-
newestAtMs,
|
|
216
|
-
nowMs: liveness.nowMs,
|
|
217
|
-
skewMs: -ageMs,
|
|
218
|
-
});
|
|
219
|
-
return true;
|
|
220
|
-
}
|
|
221
|
-
return ageMs <= liveness.staleAfterMs;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Whether an event says something about the work, as opposed to being the
|
|
225
|
-
* caller's own prompt coming back. Anything Superblocks or SABS reports counts -
|
|
226
|
-
* a generation state, a progress line, a reply, an auth prompt, the session
|
|
227
|
-
* itself - so this excludes only the one event a caller produces.
|
|
228
|
-
*/
|
|
229
|
-
function reportsWork(event) {
|
|
230
|
-
return !(event.payload.kind === "chat_message" && event.payload.role === "user");
|
|
231
|
-
}
|
|
232
|
-
function activityLine(event) {
|
|
233
|
-
switch (event.payload.kind) {
|
|
234
|
-
case "chat_message":
|
|
235
|
-
// A user message is the prompt coming back; relaying it would have the
|
|
236
|
-
// caller read its own words out as if they were news.
|
|
237
|
-
return event.payload.role === "assistant"
|
|
238
|
-
? event.payload.text
|
|
239
|
-
: undefined;
|
|
240
|
-
case "progress":
|
|
241
|
-
return event.payload.label;
|
|
242
|
-
default:
|
|
243
|
-
return undefined;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
//# sourceMappingURL=persisted-progress.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"persisted-progress.js","sourceRoot":"","sources":["../../src/capabilities/persisted-progress.ts"],"names":[],"mappings":"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"}
|