@sapiom/harness 0.4.1 → 0.5.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/core/adapters/adapter.d.ts +0 -9
  3. package/dist/core/adapters/adapter.d.ts.map +1 -1
  4. package/dist/core/adapters/claude-code-info.d.ts.map +1 -1
  5. package/dist/core/adapters/claude-code-info.js +0 -2
  6. package/dist/core/adapters/claude-code-info.js.map +1 -1
  7. package/dist/core/adapters/codex-info.d.ts.map +1 -1
  8. package/dist/core/adapters/codex-info.js +0 -2
  9. package/dist/core/adapters/codex-info.js.map +1 -1
  10. package/dist/core/adapters/conductor.d.ts.map +1 -1
  11. package/dist/core/adapters/conductor.js +0 -2
  12. package/dist/core/adapters/conductor.js.map +1 -1
  13. package/dist/core/adapters/opencode.d.ts.map +1 -1
  14. package/dist/core/adapters/opencode.js +0 -2
  15. package/dist/core/adapters/opencode.js.map +1 -1
  16. package/dist/core/adapters/pi.d.ts.map +1 -1
  17. package/dist/core/adapters/pi.js +0 -2
  18. package/dist/core/adapters/pi.js.map +1 -1
  19. package/dist/core/bracketed-paste.d.ts +55 -0
  20. package/dist/core/bracketed-paste.d.ts.map +1 -0
  21. package/dist/core/bracketed-paste.js +97 -0
  22. package/dist/core/bracketed-paste.js.map +1 -0
  23. package/dist/core/canvas-body.d.ts +9 -0
  24. package/dist/core/canvas-body.d.ts.map +1 -1
  25. package/dist/core/canvas-body.js +30 -12
  26. package/dist/core/canvas-body.js.map +1 -1
  27. package/dist/core/canvas-run-state.d.ts +19 -1
  28. package/dist/core/canvas-run-state.d.ts.map +1 -1
  29. package/dist/core/canvas-run-state.js +43 -1
  30. package/dist/core/canvas-run-state.js.map +1 -1
  31. package/dist/core/canvas-template.d.ts.map +1 -1
  32. package/dist/core/canvas-template.js +40 -10
  33. package/dist/core/canvas-template.js.map +1 -1
  34. package/dist/core/example-seed.d.ts.map +1 -1
  35. package/dist/core/example-seed.js +18 -29
  36. package/dist/core/example-seed.js.map +1 -1
  37. package/dist/core/session-manager.d.ts.map +1 -1
  38. package/dist/core/session-manager.js +23 -2
  39. package/dist/core/session-manager.js.map +1 -1
  40. package/dist/server/rest.d.ts.map +1 -1
  41. package/dist/server/rest.js +1 -114
  42. package/dist/server/rest.js.map +1 -1
  43. package/dist/shared/types.d.ts +4 -51
  44. package/dist/shared/types.d.ts.map +1 -1
  45. package/dist/shared/types.js +5 -28
  46. package/dist/shared/types.js.map +1 -1
  47. package/dist/web/assets/index-BuH6LNdL.js +463 -0
  48. package/dist/web/assets/index-Dmj2SA0s.css +32 -0
  49. package/dist/web/canvas/sess-boot/index.html +4 -10
  50. package/dist/web/index.html +2 -2
  51. package/package.json +3 -3
  52. package/dist/web/assets/index-BaADppjR.css +0 -32
  53. package/dist/web/assets/index-Bof-vfeB.js +0 -463
package/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # @sapiom/harness
2
2
 
3
+ ## 0.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 7612e30: Submit injected prompts as a bracketed paste, so a click that sends a prompt to the CLI chat lands as one prompt and actually sends. Multi-line prompts (the canvas chat prepends step context to every question) no longer submit at their first newline, and the trailing Enter is a keypress rather than a race against the coding agent's paste heuristic — which is why the same click sometimes needed a manual Enter. Sessions whose harness never enables bracketed paste keep the previous raw write.
8
+
9
+ ## 0.5.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 5aa3e01: Give the account menu's "Overview" its own page — a proper introduction to Agent Studio
14
+
15
+ "Overview" used to be an alias for the composer home. It now opens a standalone
16
+ Overview destination (`OverviewPanel`) that introduces the app: the
17
+ build-with-your-coding-agent → shape-on-the-Canvas → run-on-Sapiom loop, a
18
+ "How it works" trio, and a grid of what's in the window (embedded coding agent,
19
+ Agents rail, Canvas, Templates, deploy, production run, Sapiom capabilities,
20
+ zero config mutation). It renders as a full-width destination like Templates
21
+ (`.app.is-browsing` hides the panes) with its own top bar, a Build-an-agent CTA
22
+ into the composer, and a Start-from-a-template shortcut.
23
+
24
+ The page follows the Studio brand: neutral chrome throughout, with the scarce
25
+ green (`--brand`) spent only on the three "how it works" glyphs. First run warms
26
+ the eyebrow to a welcome and, when signed out, hints at connecting a Sapiom
27
+ account. "Create new" (the composer) is unchanged and remains the primary
28
+ creative action.
29
+
30
+ ### Patch Changes
31
+
32
+ - 19b8bbb: Install a new agent's dependencies on scaffold, and turn the Canvas's "Could not resolve …" render error into an actionable "run npm install" hint
33
+
34
+ The Canvas step-graph extraction (`check` / `loadDefinition`) esbuild-bundles a project's `index.ts` resolving its imports — `@sapiom/agent`, `zod`, … — from the project's own `node_modules`. A newly-scaffolded (or freshly-cloned) agent whose deps were never installed therefore failed its very first, unprompted Canvas render with a raw esbuild wall (`Could not resolve "@sapiom/agent" … Could not resolve "zod"`), which the failure panel relayed verbatim.
35
+
36
+ Two fixes:
37
+
38
+ - `scaffold()` gains an opt-in `installDependencies` flag (returned as `dependenciesInstalled`), and the `sapiom_dev_agents_scaffold` MCP tool — the Studio's create path — now passes it, so a new agent opens with a working Canvas. Best-effort and non-fatal: a missing/offline npm still yields a successful scaffold. The `installProjectDependencies` helper (previously demo-only inside the harness's example seed) now lives in `@sapiom/agent-core` and is shared by both.
39
+ - `check` and `loadDefinition` now route bundle failures through `describeBundleFailure`, which detects the "no `node_modules` + unresolved import" case and returns `Dependencies are not installed. Run \`npm install\` in <dir>, then try again.` (preserving the raw esbuild detail). Every other bundle failure's message is unchanged.
40
+
41
+ - 03d23c8: Hold a new session's first prompt until Claude Code is signed in
42
+
43
+ Starting a session from the composer (or a template/clone) created the session and then fired the initial prompt immediately, retrying only on a 409 for ~9s. But a Claude Code session only becomes injectable once its `SessionStart` hook fires — which doesn't happen until the user is past Claude's own login/onboarding. A first-time, not-yet-signed-in user therefore blew past the 9s window and the prompt was silently dropped.
44
+
45
+ The prompt is now held per session and sent the moment the session reports ready (i.e. Claude is signed in and interactive). If the session is still not ready after a short grace, a hint points the user at the terminal login ("Sign in to Claude in the terminal — your prompt sends automatically once you're signed in"), so first-run intent is preserved instead of lost.
46
+
47
+ - Updated dependencies [19b8bbb]
48
+ - @sapiom/agent-core@0.10.5
49
+ - @sapiom/mcp@0.12.4
50
+
3
51
  ## 0.4.1
4
52
 
5
53
  ### Patch Changes
@@ -45,15 +45,6 @@ export interface HarnessAdapterBase {
45
45
  * supported harnesses.
46
46
  */
47
47
  experimental?: boolean;
48
- /**
49
- * Whether this harness can consume an image the composer attaches. The
50
- * harness relays an image by writing it to disk (see HARNESS_UPLOADS_DIR)
51
- * and injecting its path into the agent's prompt, so this is true exactly
52
- * for harnesses whose CLI reads image files referenced by path. The upload
53
- * endpoint rejects attaches to a harness where this is false, and the SPA
54
- * hides the attach affordance for it.
55
- */
56
- imageInput: boolean;
57
48
  }
58
49
  /**
59
50
  * An adapter the harness spawns inside a pty session.
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,OAAO,GACP,IAAI,GACJ,UAAU,GACV,WAAW,CAAC;AAEhB;oCACoC;AACpC,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,UAAU,CAAC;AAEzD,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,EAAE,EAAE,gBAAgB,CAAC;IACrB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,IAAI,EAAE,kBAAkB,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,IAAI,MAAM,CAAC;IAC3B;;;OAGG;IACH,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;OAOG;IACH,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,0BAA0B,GAAG,0BAA0B,CAAC"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,OAAO,GACP,IAAI,GACJ,UAAU,GACV,WAAW,CAAC;AAEhB;oCACoC;AACpC,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,UAAU,CAAC;AAEzD,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,EAAE,EAAE,gBAAgB,CAAC;IACrB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,IAAI,EAAE,kBAAkB,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,IAAI,MAAM,CAAC;IAC3B;;;OAGG;IACH,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,0BAA0B,GAAG,0BAA0B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code-info.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/claude-code-info.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAkB/D,eAAO,MAAM,qBAAqB,EAAE,0BAYnC,CAAC"}
1
+ {"version":3,"file":"claude-code-info.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/claude-code-info.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAkB/D,eAAO,MAAM,qBAAqB,EAAE,0BAUnC,CAAC"}
@@ -17,8 +17,6 @@ export const claudeCodeAdapterInfo = {
17
17
  id: "claude-code",
18
18
  label: "Claude Code",
19
19
  mode: "embedded",
20
- // Claude Code reads images referenced by path in a prompt.
21
- imageInput: true,
22
20
  installMcpPrompt() {
23
21
  return INSTALL_MCP_PROMPT;
24
22
  },
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code-info.js","sourceRoot":"","sources":["../../../src/core/adapters/claude-code-info.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,kBAAkB,GAAG;IACzB,+CAA+C;IAC/C,EAAE;IACF,oDAAoD;IACpD,EAAE;IACF,oDAAoD;IACpD,EAAE;IACF,yEAAyE;IACzE,uEAAuE;IACvE,yEAAyE;IACzE,0EAA0E;IAC1E,0EAA0E;IAC1E,uDAAuD;CACxD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,qBAAqB,GAA+B;IAC/D,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,aAAa;IACpB,IAAI,EAAE,UAAU;IAChB,2DAA2D;IAC3D,UAAU,EAAE,IAAI;IAChB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,eAAe;QACb,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"claude-code-info.js","sourceRoot":"","sources":["../../../src/core/adapters/claude-code-info.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,kBAAkB,GAAG;IACzB,+CAA+C;IAC/C,EAAE;IACF,oDAAoD;IACpD,EAAE;IACF,oDAAoD;IACpD,EAAE;IACF,yEAAyE;IACzE,uEAAuE;IACvE,yEAAyE;IACzE,0EAA0E;IAC1E,0EAA0E;IAC1E,uDAAuD;CACxD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,qBAAqB,GAA+B;IAC/D,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,aAAa;IACpB,IAAI,EAAE,UAAU;IAChB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,eAAe;QACb,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"codex-info.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/codex-info.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAuB/D,eAAO,MAAM,gBAAgB,EAAE,0BAY9B,CAAC"}
1
+ {"version":3,"file":"codex-info.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/codex-info.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAuB/D,eAAO,MAAM,gBAAgB,EAAE,0BAU9B,CAAC"}
@@ -22,8 +22,6 @@ export const codexAdapterInfo = {
22
22
  id: "codex",
23
23
  label: "Codex CLI",
24
24
  mode: "embedded",
25
- // Codex reads images referenced by path in a prompt.
26
- imageInput: true,
27
25
  installMcpPrompt() {
28
26
  return INSTALL_MCP_PROMPT;
29
27
  },
@@ -1 +1 @@
1
- {"version":3,"file":"codex-info.js","sourceRoot":"","sources":["../../../src/core/adapters/codex-info.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,kBAAkB,GAAG;IACzB,iDAAiD;IACjD,EAAE;IACF,0EAA0E;IAC1E,aAAa;IACb,EAAE;IACF,mDAAmD;IACnD,EAAE;IACF,yDAAyD;IACzD,EAAE;IACF,6BAA6B;IAC7B,oBAAoB;IACpB,iCAAiC;IACjC,EAAE;IACF,yEAAyE;IACzE,kCAAkC;IAClC,yEAAyE;IACzE,gBAAgB;CACjB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,gBAAgB,GAA+B;IAC1D,EAAE,EAAE,OAAO;IACX,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,UAAU;IAChB,qDAAqD;IACrD,UAAU,EAAE,IAAI;IAChB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,eAAe;QACb,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"codex-info.js","sourceRoot":"","sources":["../../../src/core/adapters/codex-info.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,kBAAkB,GAAG;IACzB,iDAAiD;IACjD,EAAE;IACF,0EAA0E;IAC1E,aAAa;IACb,EAAE;IACF,mDAAmD;IACnD,EAAE;IACF,yDAAyD;IACzD,EAAE;IACF,6BAA6B;IAC7B,oBAAoB;IACpB,iCAAiC;IACjC,EAAE;IACF,yEAAyE;IACzE,kCAAkC;IAClC,yEAAyE;IACzE,gBAAgB;CACjB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,gBAAgB,GAA+B;IAC1D,EAAE,EAAE,OAAO;IACX,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,UAAU;IAChB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,eAAe;QACb,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"conductor.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/conductor.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAoB/D;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,OAAO,GAAE,MAAqB,GAC7B,MAAM,EAAE,CAMV;AAED,eAAO,MAAM,oBAAoB,EAAE,0BAkBlC,CAAC"}
1
+ {"version":3,"file":"conductor.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/conductor.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAoB/D;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,OAAO,GAAE,MAAqB,GAC7B,MAAM,EAAE,CAMV;AAED,eAAO,MAAM,oBAAoB,EAAE,0BAgBlC,CAAC"}
@@ -40,8 +40,6 @@ export const conductorAdapterInfo = {
40
40
  id: "conductor",
41
41
  label: "Conductor",
42
42
  mode: "external",
43
- // External companion app — no pty to relay an image into.
44
- imageInput: false,
45
43
  installMcpPrompt() {
46
44
  return INSTALL_MCP_PROMPT;
47
45
  },
@@ -1 +1 @@
1
- {"version":3,"file":"conductor.js","sourceRoot":"","sources":["../../../src/core/adapters/conductor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,MAAM,kBAAkB,GAAG;IACzB,6CAA6C;IAC7C,EAAE;IACF,0EAA0E;IAC1E,yEAAyE;IACzE,KAAK;IACL,EAAE;IACF,mCAAmC;IACnC,EAAE;IACF,oEAAoE;IACpE,EAAE;IACF,oEAAoE;IACpE,0EAA0E;IAC1E,+DAA+D;IAC/D,gEAAgE;IAChE,iEAAiE;CAClE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAA4B,OAAO,CAAC,QAAQ,EAC5C,UAAkB,EAAE,CAAC,OAAO,EAAE;IAE9B,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO;QACL,6BAA6B;QAC7B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,eAAe,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAA+B;IAC9D,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,UAAU;IAChB,0DAA0D;IAC1D,UAAU,EAAE,KAAK;IACjB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,KAAK,CAAC,eAAe;QACnB,OAAO,sBAAsB,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;YACjD,IAAI,CAAC;gBACH,OAAO,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"conductor.js","sourceRoot":"","sources":["../../../src/core/adapters/conductor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,MAAM,kBAAkB,GAAG;IACzB,6CAA6C;IAC7C,EAAE;IACF,0EAA0E;IAC1E,yEAAyE;IACzE,KAAK;IACL,EAAE;IACF,mCAAmC;IACnC,EAAE;IACF,oEAAoE;IACpE,EAAE;IACF,oEAAoE;IACpE,0EAA0E;IAC1E,+DAA+D;IAC/D,gEAAgE;IAChE,iEAAiE;CAClE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAA4B,OAAO,CAAC,QAAQ,EAC5C,UAAkB,EAAE,CAAC,OAAO,EAAE;IAE9B,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO;QACL,6BAA6B;QAC7B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,eAAe,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAA+B;IAC9D,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,UAAU;IAChB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,KAAK,CAAC,eAAe;QACnB,OAAO,sBAAsB,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;YACjD,IAAI,CAAC;gBACH,OAAO,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/opencode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAyB/D,eAAO,MAAM,mBAAmB,EAAE,0BAajC,CAAC"}
1
+ {"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/opencode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAyB/D,eAAO,MAAM,mBAAmB,EAAE,0BAWjC,CAAC"}
@@ -25,8 +25,6 @@ export const opencodeAdapterInfo = {
25
25
  label: "opencode",
26
26
  mode: "embedded",
27
27
  experimental: true,
28
- // Scaffold adapter — image relay not yet exercised, so not offered.
29
- imageInput: false,
30
28
  installMcpPrompt() {
31
29
  return INSTALL_MCP_PROMPT;
32
30
  },
@@ -1 +1 @@
1
- {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/core/adapters/opencode.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,kBAAkB,GAAG;IACzB,4CAA4C;IAC5C,EAAE;IACF,wEAAwE;IACxE,+CAA+C;IAC/C,EAAE;IACF,MAAM;IACN,eAAe;IACf,wBAAwB;IACxB,2BAA2B;IAC3B,mDAAmD;IACnD,0BAA0B;IAC1B,UAAU;IACV,QAAQ;IACR,MAAM;IACN,EAAE;IACF,yEAAyE;IACzE,kCAAkC;IAClC,sEAAsE;IACtE,sBAAsB;CACvB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,mBAAmB,GAA+B;IAC7D,EAAE,EAAE,UAAU;IACd,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,YAAY,EAAE,IAAI;IAClB,oEAAoE;IACpE,UAAU,EAAE,KAAK;IACjB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,eAAe;QACb,OAAO,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/core/adapters/opencode.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,kBAAkB,GAAG;IACzB,4CAA4C;IAC5C,EAAE;IACF,wEAAwE;IACxE,+CAA+C;IAC/C,EAAE;IACF,MAAM;IACN,eAAe;IACf,wBAAwB;IACxB,2BAA2B;IAC3B,mDAAmD;IACnD,0BAA0B;IAC1B,UAAU;IACV,QAAQ;IACR,MAAM;IACN,EAAE;IACF,yEAAyE;IACzE,kCAAkC;IAClC,sEAAsE;IACtE,sBAAsB;CACvB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,mBAAmB,GAA+B;IAC7D,EAAE,EAAE,UAAU;IACd,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,YAAY,EAAE,IAAI;IAClB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,eAAe;QACb,OAAO,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"pi.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/pi.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAc/D,eAAO,MAAM,aAAa,EAAE,0BAa3B,CAAC"}
1
+ {"version":3,"file":"pi.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/pi.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAc/D,eAAO,MAAM,aAAa,EAAE,0BAW3B,CAAC"}
@@ -14,8 +14,6 @@ export const piAdapterInfo = {
14
14
  label: "pi",
15
15
  mode: "embedded",
16
16
  experimental: true,
17
- // Scaffold adapter — image relay not yet exercised, so not offered.
18
- imageInput: false,
19
17
  installMcpPrompt() {
20
18
  return INSTALL_MCP_PROMPT;
21
19
  },
@@ -1 +1 @@
1
- {"version":3,"file":"pi.js","sourceRoot":"","sources":["../../../src/core/adapters/pi.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,kBAAkB,GAAG;IACzB,sCAAsC;IACtC,EAAE;IACF,yEAAyE;IACzE,2EAA2E;IAC3E,oEAAoE;IACpE,qEAAqE;IACrE,oEAAoE;IACpE,yDAAyD;CAC1D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,aAAa,GAA+B;IACvD,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,UAAU;IAChB,YAAY,EAAE,IAAI;IAClB,oEAAoE;IACpE,UAAU,EAAE,KAAK;IACjB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,eAAe;QACb,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"pi.js","sourceRoot":"","sources":["../../../src/core/adapters/pi.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,kBAAkB,GAAG;IACzB,sCAAsC;IACtC,EAAE;IACF,yEAAyE;IACzE,2EAA2E;IAC3E,oEAAoE;IACpE,qEAAqE;IACrE,oEAAoE;IACpE,yDAAyD;CAC1D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,aAAa,GAA+B;IACvD,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,UAAU;IAChB,YAAY,EAAE,IAAI;IAClB,gBAAgB;QACd,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,eAAe;QACb,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;CACF,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Bracketed paste (DEC private mode 2004) for programmatic prompt injection.
3
+ *
4
+ * `submitInput()` writes a prompt into a coding agent's pty and then a `\r` to
5
+ * send it. Both halves are ambiguous to a TUI unless the paste is bracketed:
6
+ *
7
+ * - A prompt with newlines in it (the canvas chat prepends a multi-line step
8
+ * context to every question) is a stream of `\n`s to the app. Ink — Claude
9
+ * Code's input layer — maps a bare `\n` to Return exactly like `\r`, so a
10
+ * raw write submits at the FIRST newline and the rest of the prompt lands
11
+ * as further half-prompts.
12
+ * - The trailing `\r` is only a "submit" keypress if the app has already
13
+ * stopped treating the write as pasted content. Its paste heuristic is a
14
+ * timing/size guess, so the same click can submit or sit in the composer
15
+ * depending on how busy the agent was — the reported inconsistency.
16
+ *
17
+ * With mode 2004 on, the app is told where pasted content starts and ends, so
18
+ * newlines inside stay literal and the following `\r` is unambiguously a
19
+ * keypress. The mode is only usable when the app turned it on, so
20
+ * {@link trackBracketedPaste} reads that fact off the pty's own output rather
21
+ * than assuming it: an app that never enables 2004 keeps the previous raw
22
+ * behaviour instead of being fed escape sequences it would render as text.
23
+ *
24
+ * Pure — no I/O, no pty — so the parsing is unit-testable on strings.
25
+ */
26
+ /** Start of pasted content (`ESC [ 200 ~`). */
27
+ export declare const PASTE_START = "\u001B[200~";
28
+ /** End of pasted content (`ESC [ 201 ~`). */
29
+ export declare const PASTE_END = "\u001B[201~";
30
+ /** Incremental scan state — see {@link trackBracketedPaste}. */
31
+ export interface BracketedPasteState {
32
+ /** Whether the app currently has mode 2004 on. */
33
+ enabled: boolean;
34
+ /** Trailing bytes of the last chunk that may be an unfinished sequence. */
35
+ carry: string;
36
+ }
37
+ export declare const initialBracketedPasteState: BracketedPasteState;
38
+ /**
39
+ * Fold one chunk of pty output into the running bracketed-paste mode state.
40
+ * The LAST 2004 set/reset in the chunk wins, matching how the terminal itself
41
+ * would apply them in order.
42
+ */
43
+ export declare function trackBracketedPaste(state: BracketedPasteState, chunk: string): BracketedPasteState;
44
+ /**
45
+ * Wrap `text` as bracketed pasted content.
46
+ *
47
+ * Any `ESC [ 201 ~` inside the text would end the paste early and hand the
48
+ * remainder to the app as keystrokes, so it is dropped — to a FIXPOINT, since
49
+ * removing one terminator can let the bytes on either side re-form another
50
+ * (`"\x1b[20" + ESC[201~ + "1~"` collapses to a fresh `ESC[201~`). `\r` is then
51
+ * normalized to `\n`, because a carriage return inside a paste is what the app
52
+ * reads as Return, which is precisely the premature submit this exists to prevent.
53
+ */
54
+ export declare function wrapPaste(text: string): string;
55
+ //# sourceMappingURL=bracketed-paste.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bracketed-paste.d.ts","sourceRoot":"","sources":["../../src/core/bracketed-paste.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,+CAA+C;AAC/C,eAAO,MAAM,WAAW,gBAAc,CAAC;AACvC,6CAA6C;AAC7C,eAAO,MAAM,SAAS,gBAAc,CAAC;AAkBrC,gEAAgE;AAChE,MAAM,WAAW,mBAAmB;IAClC,kDAAkD;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,0BAA0B,EAAE,mBAAmD,CAAC;AAsB7F;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,mBAAmB,EAC1B,KAAK,EAAE,MAAM,GACZ,mBAAmB,CAOrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK9C"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Bracketed paste (DEC private mode 2004) for programmatic prompt injection.
3
+ *
4
+ * `submitInput()` writes a prompt into a coding agent's pty and then a `\r` to
5
+ * send it. Both halves are ambiguous to a TUI unless the paste is bracketed:
6
+ *
7
+ * - A prompt with newlines in it (the canvas chat prepends a multi-line step
8
+ * context to every question) is a stream of `\n`s to the app. Ink — Claude
9
+ * Code's input layer — maps a bare `\n` to Return exactly like `\r`, so a
10
+ * raw write submits at the FIRST newline and the rest of the prompt lands
11
+ * as further half-prompts.
12
+ * - The trailing `\r` is only a "submit" keypress if the app has already
13
+ * stopped treating the write as pasted content. Its paste heuristic is a
14
+ * timing/size guess, so the same click can submit or sit in the composer
15
+ * depending on how busy the agent was — the reported inconsistency.
16
+ *
17
+ * With mode 2004 on, the app is told where pasted content starts and ends, so
18
+ * newlines inside stay literal and the following `\r` is unambiguously a
19
+ * keypress. The mode is only usable when the app turned it on, so
20
+ * {@link trackBracketedPaste} reads that fact off the pty's own output rather
21
+ * than assuming it: an app that never enables 2004 keeps the previous raw
22
+ * behaviour instead of being fed escape sequences it would render as text.
23
+ *
24
+ * Pure — no I/O, no pty — so the parsing is unit-testable on strings.
25
+ */
26
+ /** Start of pasted content (`ESC [ 200 ~`). */
27
+ export const PASTE_START = "\x1b[200~";
28
+ /** End of pasted content (`ESC [ 201 ~`). */
29
+ export const PASTE_END = "\x1b[201~";
30
+ /**
31
+ * A DEC private mode set/reset: `ESC [ ? <params> h|l`, where params is a
32
+ * `;`-separated list (apps commonly batch, e.g. `ESC[?1049;2004h`).
33
+ */
34
+ // eslint-disable-next-line no-control-regex
35
+ const PRIVATE_MODE_RE = /\x1b\[\?([0-9;]*)([hl])/g;
36
+ /**
37
+ * Longest partial private-mode sequence worth carrying between chunks: an
38
+ * `ESC [ ? <params>` with no terminator yet. A pty chunk can split an escape
39
+ * sequence at any byte, so such a tail is re-scanned with the next chunk
40
+ * instead of being dropped. Sized to hold a realistically long *batched* set —
41
+ * a terminal enables several modes at once, e.g. `ESC[?1049;1000;1002;…;2004h`.
42
+ */
43
+ const MAX_CARRY = 64;
44
+ export const initialBracketedPasteState = { enabled: false, carry: "" };
45
+ /**
46
+ * The tail of `chunk` that could still grow into a private-mode set/reset on
47
+ * the next chunk. Anchored on the last ESC — not on the full `ESC[?` — so a
48
+ * boundary that falls *inside* the introducer (`ESC` | `[?…`, or `ESC[` | `?…`)
49
+ * still carries, instead of dropping the mode change (and, for a RESET split
50
+ * that way, leaving 2004 wrongly stuck on and pasting escape bytes at an app
51
+ * that has turned bracketed paste off).
52
+ */
53
+ function pendingCarry(chunk) {
54
+ const esc = chunk.lastIndexOf("\x1b");
55
+ if (esc === -1)
56
+ return "";
57
+ const tail = chunk.slice(esc);
58
+ // Keep it only while it is still a viable prefix of `ESC [ ? <params>` with no
59
+ // terminator yet: a final h/l, a second byte other than "[", or a post-"["
60
+ // byte other than "?" all mean it can never become a private-mode sequence.
61
+ // eslint-disable-next-line no-control-regex
62
+ if (!/^\x1b(\[(\?[0-9;]*)?)?$/.test(tail))
63
+ return "";
64
+ return tail.length > MAX_CARRY ? "" : tail;
65
+ }
66
+ /**
67
+ * Fold one chunk of pty output into the running bracketed-paste mode state.
68
+ * The LAST 2004 set/reset in the chunk wins, matching how the terminal itself
69
+ * would apply them in order.
70
+ */
71
+ export function trackBracketedPaste(state, chunk) {
72
+ const scanned = state.carry + chunk;
73
+ let enabled = state.enabled;
74
+ for (const match of scanned.matchAll(PRIVATE_MODE_RE)) {
75
+ if (match[1]?.split(";").includes("2004"))
76
+ enabled = match[2] === "h";
77
+ }
78
+ return { enabled, carry: pendingCarry(scanned) };
79
+ }
80
+ /**
81
+ * Wrap `text` as bracketed pasted content.
82
+ *
83
+ * Any `ESC [ 201 ~` inside the text would end the paste early and hand the
84
+ * remainder to the app as keystrokes, so it is dropped — to a FIXPOINT, since
85
+ * removing one terminator can let the bytes on either side re-form another
86
+ * (`"\x1b[20" + ESC[201~ + "1~"` collapses to a fresh `ESC[201~`). `\r` is then
87
+ * normalized to `\n`, because a carriage return inside a paste is what the app
88
+ * reads as Return, which is precisely the premature submit this exists to prevent.
89
+ */
90
+ export function wrapPaste(text) {
91
+ let body = text;
92
+ while (body.includes(PASTE_END))
93
+ body = body.split(PASTE_END).join("");
94
+ body = body.replace(/\r\n?/g, "\n");
95
+ return PASTE_START + body + PASTE_END;
96
+ }
97
+ //# sourceMappingURL=bracketed-paste.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bracketed-paste.js","sourceRoot":"","sources":["../../src/core/bracketed-paste.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,+CAA+C;AAC/C,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AACvC,6CAA6C;AAC7C,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;AAErC;;;GAGG;AACH,4CAA4C;AAC5C,MAAM,eAAe,GAAG,0BAA0B,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,SAAS,GAAG,EAAE,CAAC;AAUrB,MAAM,CAAC,MAAM,0BAA0B,GAAwB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AAE7F;;;;;;;GAOG;AACH,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,+EAA+E;IAC/E,2EAA2E;IAC3E,4EAA4E;IAC5E,4CAA4C;IAC5C,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACrD,OAAO,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA0B,EAC1B,KAAa;IAEb,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IACpC,IAAI,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACtD,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;IACxE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;AACnD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpC,OAAO,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;AACxC,CAAC"}
@@ -27,6 +27,15 @@ export interface WorkflowPanelMeta {
27
27
  * Returns "" when nothing is worth keying, so the panel omits the footer.
28
28
  */
29
29
  export declare function buildLegendHtml(nodeKinds: Set<CanvasNodeKind>, edgeKinds: Set<CanvasEdgeKind>): string;
30
+ /**
31
+ * The same key as `buildLegendHtml`, as data rather than markup: the app's
32
+ * overview panel renders it beside the graph instead of the board floating it
33
+ * over itself.
34
+ */
35
+ export declare function buildLegendItems(nodeKinds: Set<CanvasNodeKind>, edgeKinds: Set<CanvasEdgeKind>): Array<{
36
+ kind: string;
37
+ label: string;
38
+ }>;
30
39
  /** One workflow's full panel: title/badges + summary header and the SVG
31
40
  * diagram, with the deterministic enrichment merged in (summary line and
32
41
  * node/edge annotations), plus the embedded step-graph payload the Steps tab
@@ -1 +1 @@
1
- {"version":3,"file":"canvas-body.d.ts","sourceRoot":"","sources":["../../src/core/canvas-body.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAO/D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAoBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,GAAG,MAAM,CAYtG;AA6ED;;;aAGa;AACb,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,iBAAiB,EACvB,UAAU,CAAC,EAAE,gBAAgB,GAAG,IAAI,GACnC,MAAM,CA2BR;AAED;;qCAEqC;AACrC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAczE;AAED;;;;;;+DAM+D;AAC/D,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAY7D;AAED;;gFAEgF;AAChF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,MAAM,CAEtE"}
1
+ {"version":3,"file":"canvas-body.d.ts","sourceRoot":"","sources":["../../src/core/canvas-body.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAO/D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAoBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,GAAG,MAAM,CAYtG;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAC9B,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,GAC7B,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CASxC;AAsFD;;;aAGa;AACb,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,iBAAiB,EACvB,UAAU,CAAC,EAAE,gBAAgB,GAAG,IAAI,GACnC,MAAM,CAyBR;AAED;;qCAEqC;AACrC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAczE;AAED;;;;;;+DAM+D;AAC/D,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAY7D;AAED;;gFAEgF;AAChF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,MAAM,CAEtE"}
@@ -32,6 +32,21 @@ export function buildLegendHtml(nodeKinds, edgeKinds) {
32
32
  return "";
33
33
  return `<footer class="canvas-legend">${items.join("")}</footer>`;
34
34
  }
35
+ /**
36
+ * The same key as `buildLegendHtml`, as data rather than markup: the app's
37
+ * overview panel renders it beside the graph instead of the board floating it
38
+ * over itself.
39
+ */
40
+ export function buildLegendItems(nodeKinds, edgeKinds) {
41
+ const items = NODE_KIND_ORDER.filter((k) => nodeKinds.has(k)).map((k) => ({
42
+ kind: k,
43
+ label: NODE_KIND_LABEL[k],
44
+ }));
45
+ if (edgeKinds.has("cross")) {
46
+ items.push({ kind: "cross", label: "cross-agent signal/handoff" });
47
+ }
48
+ return items;
49
+ }
35
50
  /**
36
51
  * Serializes the graph (enrichment merged) into the JSON payload the app's
37
52
  * Steps tab / inspector consumes, embedded as a `<script id="sapiom-graph">`
@@ -78,10 +93,12 @@ function buildGraphPayload(graph, enrichment) {
78
93
  }
79
94
  /** The workflow-level overview the Canvas tab's bottom panel shows: a
80
95
  * deterministic stats line ("N steps · M exits · <entry> entry"), the shape
81
- * summary as the description, and the graph's validation notes. Embedded as a
82
- * JSON data block (read by bootCanvasOverview), the same pattern as the step
83
- * graph everything here is derived from the graph, no LLM. */
84
- function buildOverviewPayload(graph, enrichment) {
96
+ * summary as the description, the graph's validation notes, and the chrome
97
+ * the board used to float over itself — the status badges and the node-kind
98
+ * key. Embedded as a JSON data block (read by bootCanvasOverview), the same
99
+ * pattern as the step graph — everything here is derived from the graph, no
100
+ * LLM. */
101
+ function buildOverviewPayload(graph, badges, legend, enrichment) {
85
102
  const exits = graph.nodes.filter((n) => n.kind === "terminal-success" || n.kind === "terminal-warn").length;
86
103
  const steps = graph.nodes.filter((n) => n.kind !== "terminal-success" &&
87
104
  n.kind !== "terminal-warn" &&
@@ -98,6 +115,8 @@ function buildOverviewPayload(graph, enrichment) {
98
115
  description: graph.description ?? "",
99
116
  stats: parts.join(" · "),
100
117
  notes: enrichment?.notes ?? [],
118
+ badges,
119
+ legend,
101
120
  };
102
121
  // JSON in a <script> block: neutralize any "</script>"/"<" in derived text.
103
122
  return JSON.stringify(overview).replace(/</g, "\\u003c");
@@ -107,23 +126,22 @@ function buildOverviewPayload(graph, enrichment) {
107
126
  * node/edge annotations), plus the embedded step-graph payload the Steps tab
108
127
  * reads. */
109
128
  export function buildWorkflowPanelHtml(graph, meta, enrichment) {
110
- const badges = (meta.badges ?? [])
111
- .map((b) => `<span class="canvas-badge">${esc(b)}</span>`)
112
- .join("");
113
- const warningBadge = graph.warnings.length > 0
114
- ? `<span class="canvas-badge">${graph.warnings.length} warning${graph.warnings.length === 1 ? "" : "s"}</span>`
115
- : "";
129
+ const badgeLabels = [...(meta.badges ?? [])];
130
+ if (graph.warnings.length > 0) {
131
+ badgeLabels.push(`${graph.warnings.length} warning${graph.warnings.length === 1 ? "" : "s"}`);
132
+ }
133
+ const badges = badgeLabels.map((b) => `<span class="canvas-badge">${esc(b)}</span>`).join("");
116
134
  const summary = enrichment?.summary ? `\n <p class="canvas-subtitle">${esc(enrichment.summary)}</p>` : "";
117
135
  const used = usedKinds(graph);
118
136
  const legend = buildLegendHtml(used.nodeKinds, used.edgeKinds);
119
137
  const legendHtml = legend ? `\n ${legend}` : "";
120
138
  const graphData = buildGraphPayload(graph, enrichment);
121
- const overviewData = buildOverviewPayload(graph, enrichment);
139
+ const overviewData = buildOverviewPayload(graph, badgeLabels, buildLegendItems(used.nodeKinds, used.edgeKinds), enrichment);
122
140
  return `<section class="canvas-panel">
123
141
  <header class="canvas-header">
124
142
  <div class="canvas-title-row">
125
143
  <h1 class="canvas-title">${esc(meta.title)}</h1>
126
- ${badges}${warningBadge}
144
+ ${badges}
127
145
  </div>${summary}
128
146
  </header>
129
147
  <div class="canvas-diagram-panel">
@@ -1 +1 @@
1
- {"version":3,"file":"canvas-body.js","sourceRoot":"","sources":["../../src/core/canvas-body.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canvas-body.js","sourceRoot":"","sources":["../../src/core/canvas-body.ts"],"names":[],"mappings":"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"}
@@ -96,6 +96,23 @@ export declare function bootCanvasRunState(): void;
96
96
  * Stringified into the iframe template by `canvas-template.ts`.
97
97
  */
98
98
  export declare function bootCanvasNodeClicks(): void;
99
+ /**
100
+ * Keeps the board's selected node lit while the parent's bottom inspector
101
+ * shows that step.
102
+ *
103
+ * Without this the served board answers a pick (see `bootCanvasNodeClicks`)
104
+ * and then looks untouched: the inspector swaps its content with nothing on
105
+ * the graph to say WHICH card it is describing — change blindness on every
106
+ * pick. The parent posts `{ type: "sapiom-canvas:select", id }` (null clears)
107
+ * with the graph node id, which the SVG carries as `data-step-id`; older
108
+ * documents that only carry a label fall back to `data-step-name`.
109
+ *
110
+ * Selection is orthogonal to run state: `is-selected` only rings the node, so
111
+ * a running/passed/failed card keeps its own lighting while selected.
112
+ *
113
+ * Stringified into the iframe template by `canvas-template.ts`.
114
+ */
115
+ export declare function bootCanvasSelection(): void;
99
116
  /**
100
117
  * Wires the view (pan/zoom) channel and announces the graph's natural size.
101
118
  *
@@ -128,7 +145,8 @@ export declare function bootCanvasView(): void;
128
145
  */
129
146
  export declare function bootCanvasGraph(): void;
130
147
  /**
131
- * Posts the workflow-level overview (`{ description, stats, notes }`) so the
148
+ * Posts the workflow-level overview (`{ description, stats, notes, badges,
149
+ * legend }`) so the
132
150
  * Canvas tab's bottom panel can show it — the deterministic equivalent of the
133
151
  * demo doc's overview. Embedded by `canvas-body.ts` as a `<script
134
152
  * type="application/json" id="sapiom-overview">` data block (read as text, same
@@ -1 +1 @@
1
- {"version":3,"file":"canvas-run-state.d.ts","sourceRoot":"","sources":["../../src/core/canvas-run-state.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAExE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,QAAQ,EACb,GAAG,EAAE;IACH,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GACA,IAAI,CAwDN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAMzC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAqC3C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAkDrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAkBtC;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAwBzC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAuBtC"}
1
+ {"version":3,"file":"canvas-run-state.d.ts","sourceRoot":"","sources":["../../src/core/canvas-run-state.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAExE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,QAAQ,EACb,GAAG,EAAE;IACH,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GACA,IAAI,CAwDN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAMzC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAqC3C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAmB1C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAkDrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAkBtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CA4BzC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAuBtC"}
@@ -196,6 +196,43 @@ export function bootCanvasNodeClicks() {
196
196
  }
197
197
  });
198
198
  }
199
+ /**
200
+ * Keeps the board's selected node lit while the parent's bottom inspector
201
+ * shows that step.
202
+ *
203
+ * Without this the served board answers a pick (see `bootCanvasNodeClicks`)
204
+ * and then looks untouched: the inspector swaps its content with nothing on
205
+ * the graph to say WHICH card it is describing — change blindness on every
206
+ * pick. The parent posts `{ type: "sapiom-canvas:select", id }` (null clears)
207
+ * with the graph node id, which the SVG carries as `data-step-id`; older
208
+ * documents that only carry a label fall back to `data-step-name`.
209
+ *
210
+ * Selection is orthogonal to run state: `is-selected` only rings the node, so
211
+ * a running/passed/failed card keeps its own lighting while selected.
212
+ *
213
+ * Stringified into the iframe template by `canvas-template.ts`.
214
+ */
215
+ export function bootCanvasSelection() {
216
+ window.addEventListener("message", function (e) {
217
+ const d = e && e.data;
218
+ if (!d || d.type !== "sapiom-canvas:select")
219
+ return;
220
+ const previous = document.querySelectorAll(".canvas-node.is-selected");
221
+ for (let i = 0; i < previous.length; i++)
222
+ previous[i].classList.remove("is-selected");
223
+ if (typeof d.id !== "string" || !d.id)
224
+ return;
225
+ const nodes = document.querySelectorAll(".canvas-node");
226
+ for (let i = 0; i < nodes.length; i++) {
227
+ const node = nodes[i];
228
+ if (node.getAttribute("data-step-id") === d.id ||
229
+ node.getAttribute("data-step-name") === d.id) {
230
+ node.classList.add("is-selected");
231
+ return;
232
+ }
233
+ }
234
+ });
235
+ }
199
236
  /**
200
237
  * Wires the view (pan/zoom) channel and announces the graph's natural size.
201
238
  *
@@ -299,7 +336,8 @@ export function bootCanvasGraph() {
299
336
  }
300
337
  }
301
338
  /**
302
- * Posts the workflow-level overview (`{ description, stats, notes }`) so the
339
+ * Posts the workflow-level overview (`{ description, stats, notes, badges,
340
+ * legend }`) so the
303
341
  * Canvas tab's bottom panel can show it — the deterministic equivalent of the
304
342
  * demo doc's overview. Embedded by `canvas-body.ts` as a `<script
305
343
  * type="application/json" id="sapiom-overview">` data block (read as text, same
@@ -319,6 +357,10 @@ export function bootCanvasOverview() {
319
357
  description: typeof data.description === "string" ? data.description : "",
320
358
  stats: typeof data.stats === "string" ? data.stats : "",
321
359
  notes: Array.isArray(data.notes) ? data.notes : [],
360
+ // Chrome the board no longer floats over the graph: the app renders
361
+ // both in the overview panel (see canvas-body.ts).
362
+ badges: Array.isArray(data.badges) ? data.badges : [],
363
+ legend: Array.isArray(data.legend) ? data.legend : [],
322
364
  }, "*");
323
365
  }
324
366
  catch {