@sapiom/harness 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/dist/core/account-plan.d.ts +51 -0
  3. package/dist/core/account-plan.d.ts.map +1 -0
  4. package/dist/core/account-plan.js +174 -0
  5. package/dist/core/account-plan.js.map +1 -0
  6. package/dist/core/bracketed-paste.d.ts +55 -0
  7. package/dist/core/bracketed-paste.d.ts.map +1 -0
  8. package/dist/core/bracketed-paste.js +97 -0
  9. package/dist/core/bracketed-paste.js.map +1 -0
  10. package/dist/core/canvas-body.d.ts +9 -0
  11. package/dist/core/canvas-body.d.ts.map +1 -1
  12. package/dist/core/canvas-body.js +30 -12
  13. package/dist/core/canvas-body.js.map +1 -1
  14. package/dist/core/canvas-manifest-check.d.ts.map +1 -1
  15. package/dist/core/canvas-manifest-check.js +33 -5
  16. package/dist/core/canvas-manifest-check.js.map +1 -1
  17. package/dist/core/canvas-run-state.d.ts +19 -1
  18. package/dist/core/canvas-run-state.d.ts.map +1 -1
  19. package/dist/core/canvas-run-state.js +43 -1
  20. package/dist/core/canvas-run-state.js.map +1 -1
  21. package/dist/core/canvas-svg.d.ts.map +1 -1
  22. package/dist/core/canvas-svg.js +9 -1
  23. package/dist/core/canvas-svg.js.map +1 -1
  24. package/dist/core/canvas-template.d.ts.map +1 -1
  25. package/dist/core/canvas-template.js +40 -10
  26. package/dist/core/canvas-template.js.map +1 -1
  27. package/dist/core/session-manager.d.ts.map +1 -1
  28. package/dist/core/session-manager.js +23 -2
  29. package/dist/core/session-manager.js.map +1 -1
  30. package/dist/server/account.d.ts +23 -0
  31. package/dist/server/account.d.ts.map +1 -0
  32. package/dist/server/account.js +32 -0
  33. package/dist/server/account.js.map +1 -0
  34. package/dist/server/index.d.ts.map +1 -1
  35. package/dist/server/index.js +7 -0
  36. package/dist/server/index.js.map +1 -1
  37. package/dist/server/rest.d.ts.map +1 -1
  38. package/dist/server/rest.js +3 -1
  39. package/dist/server/rest.js.map +1 -1
  40. package/dist/shared/types.d.ts +56 -2
  41. package/dist/shared/types.d.ts.map +1 -1
  42. package/dist/shared/types.js +10 -0
  43. package/dist/shared/types.js.map +1 -1
  44. package/dist/web/assets/index-C-h9_B2u.js +468 -0
  45. package/dist/web/assets/index-Dcvwqho4.css +32 -0
  46. package/dist/web/canvas/sess-boot/index.html +4 -10
  47. package/dist/web/index.html +2 -2
  48. package/package.json +4 -4
  49. package/dist/web/assets/index-CoTrWYef.css +0 -32
  50. package/dist/web/assets/index-D97Llt9O.js +0 -463
package/CHANGELOG.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # @sapiom/harness
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 928a639: Studio: a new agent's workspace folder now appears in the rail the instant you
8
+ start creating it — from the composer or a template — as an optimistic
9
+ "Creating agent…" row, pinned to the top and focusable. It stays put through
10
+ session-landing and the clone, and across the brief window after the session
11
+ binds but before its `sapiom.json` is registered, so switching sessions
12
+ mid-creation can never strand the in-progress agent.
13
+
14
+ Also fixes two rail/canvas issues:
15
+
16
+ - **Canvas no longer clips the terminal step.** A revise loop (a step pointing
17
+ back to an earlier one) left a gap in the layer numbering; the SVG height was
18
+ derived from the layer _count_ while nodes were positioned by their raw layer
19
+ _index_, so the deepest node (a terminal like `deliver`) fell below the
20
+ viewBox and was drawn off-screen with a dangling edge. Rows are now compacted
21
+ to consecutive positions, which also removes the empty band the gap produced.
22
+ - **Cloned agents show a short name in the rail.** The row now reads
23
+ `newsletter-autopilot` rather than the full package name
24
+ `@sapiom/example-newsletter-autopilot` (npm scope and a leading `example-`
25
+ stripped for display only — the full name is on hover, and the raw name still
26
+ keys testids and lookups).
27
+
28
+ - 5c0c646: Rail footer: live plan & balance card, and an "Update now" card for a downloaded desktop update
29
+
30
+ The rail's footer gains two shaded cards above the account row.
31
+
32
+ - **Plan & balance card** (both hosts): the harness server relays core reads at
33
+ `GET /api/account/plan` — the API key never reaches the page — showing the
34
+ org's plan name and one honest money line: daily spend against the org's
35
+ spend-limit rule (the same "$used / $cap" pair the dashboard renders),
36
+ falling back to the prepaid available balance, else nothing. An Upgrade pill
37
+ and a ⋮ menu deep-link to billing/usage on the dashboard (checkout is
38
+ dashboard-session-only). Signed-out or unreachable hides the card — it never
39
+ invents a number.
40
+ - **"Update now" card** (desktop only): when an update has finished
41
+ downloading, the main process pushes state over a new receive-only
42
+ `onUpdateState` bridge member (re-pushed on page load, buffered in the
43
+ preload so a reload can't drop it) and the card appears with the target
44
+ version. Clicking it goes through the existing `checkForUpdates()` — the
45
+ pending branch re-raises the update window — so there is still no
46
+ page-reachable install channel. It outlives "Later"; "Skip this version"
47
+ suppresses and retracts it (and now also disarms auto-install-on-quit for a
48
+ skipped build that was already staged).
49
+
50
+ ### Patch Changes
51
+
52
+ - 651c407: Canvas extraction failures now name the project directory they bundled. The Canvas is the only `check()` caller whose directory the user never typed — it comes from the bound workflow row — so a report of "check, run_local and deploy succeed but the Canvas fails on the same project" was unfalsifiable from the panel alone; esbuild's own paths are printed relative to the invoking package, which reads like the bundler resolving `node_modules` from the wrong root.
53
+ - 7bef8b2: Stop the empty-board auto-collapse from closing a canvas pane the user just opened. The collapse fires once per (session, binding), which was meant to make a redundant "still empty" probe harmless — but the pane's expand control is most often used right after starting a session on an agent, i.e. _before_ `activeSessionId` exists, so the probe that follows arrives under a different key and slams the pane shut a beat after the click (measured: 3–5 of 12 runs of the action-bar e2e, on `main`). A manual expand now claims the session, and a claim made while none is active adopts the one that reports next; switching sessions still re-arms the collapse.
54
+ - 95241fb: Give the rail toggle a resting surface while the app window is blurred: macOS hides the traffic lights it sits beside, so the bare glyph read as a gap on the left of the header.
55
+ - 21bb3f0: Let "Open in editor" target the editor you actually use.
56
+
57
+ The session menu hardcoded `vscode://file…`, so on a machine with Cursor (or
58
+ Windsurf, Zed, VS Code Insiders) and no VS Code the item silently did nothing —
59
+ the OS resolves the scheme and never reports back, so an unhandled scheme is
60
+ indistinguishable from a working one. Settings now carries an editor picker
61
+ (`HarnessSettings.editor`, `PATCH /api/settings`), the menu item names the
62
+ chosen editor ("Open in Cursor"), and a toast says where the folder was sent.
63
+ Windows paths are normalized to the `/C:/…` shape the handlers expect.
64
+
65
+ - Updated dependencies [651c407]
66
+ - @sapiom/agent-core@0.10.6
67
+
68
+ ## 0.5.1
69
+
70
+ ### Patch Changes
71
+
72
+ - 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.
73
+
3
74
  ## 0.5.0
4
75
 
5
76
  ### Minor Changes
@@ -0,0 +1,51 @@
1
+ /**
2
+ * account-plan — the rail's plan card, read from the Sapiom CORE surface so it
3
+ * can never disagree with the dashboard's own billing views.
4
+ *
5
+ * Three reads, folded into one `AccountPlanView`:
6
+ *
7
+ * - `GET /v1/dashboard/plan` → plan name + status
8
+ * - `GET /v1/spending-rules/spend-limit-summary` → today's settled spend vs
9
+ * the org's spend-limit rule — the exact "$used / $cap" pair the dashboard's
10
+ * balance card renders (JSON:API envelope; all-null attributes when no rule)
11
+ * - `GET /v1/accounts/spend` → `availableBalanceUsd`,
12
+ * the prepaid fallback when no limit rule exists
13
+ *
14
+ * Same auth contract as template-catalog.ts (and verified there): core takes
15
+ * `Authorization: Bearer`, NOT the agents surface's `x-sapiom-api-key`, and
16
+ * every path is prefixed `/v1`. The key stays server-side; a 401/403 triggers
17
+ * exactly one credential refresh + retry.
18
+ *
19
+ * These endpoints are excluded from core's public OpenAPI surface, so their
20
+ * shapes are contracts by observation, not by document. Every field is
21
+ * narrowed defensively and any drift degrades the readout to `none` (or the
22
+ * whole view to `fallback`) rather than throwing — a broken billing read must
23
+ * never take the rail down.
24
+ */
25
+ import type { AccountPlanView } from "../shared/types.js";
26
+ import { type ApiKeyProvider } from "./api-key-provider.js";
27
+ export interface AccountPlanReader {
28
+ /** The assembled card view. Never throws: signed-out and unreachable both
29
+ * come back as `source: "fallback"` with an honest empty readout. */
30
+ view(): Promise<AccountPlanView>;
31
+ }
32
+ /** `{ data: { plan: { name, status } | null } }` → the card's plan line. */
33
+ export declare function extractPlan(body: unknown): AccountPlanView["plan"];
34
+ /** JSON:API `{ data: { attributes: { limitUsd, windowSpendUsd } } }` → the
35
+ * "$used / $cap" pair, or null when no qualifying rule exists (all-null
36
+ * attributes is that endpoint's documented "no rule" answer, not an error). */
37
+ export declare function extractLimit(body: unknown): {
38
+ usedUsd: number;
39
+ limitUsd: number;
40
+ } | null;
41
+ /** `{ data: { availableBalanceUsd } }` → the prepaid balance, or null. */
42
+ export declare function extractBalance(body: unknown): number | null;
43
+ export declare function createAccountPlanReader(opts: {
44
+ /** Accepts a provider (preferred — enables refresh-on-401) or a bare key. */
45
+ apiKey: string | null | ApiKeyProvider;
46
+ /** Override the core base URL (resolved from env by default). Test seam. */
47
+ baseUrl?: string;
48
+ /** Injectable fetch. Test seam. */
49
+ fetchImpl?: typeof fetch;
50
+ }): AccountPlanReader;
51
+ //# sourceMappingURL=account-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-plan.d.ts","sourceRoot":"","sources":["../../src/core/account-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,uBAAuB,CAAC;AAa/B,MAAM,WAAW,iBAAiB;IAChC;0EACsE;IACtE,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;CAClC;AAsBD,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAIlE;AAED;;gFAEgF;AAChF,wBAAgB,YAAY,CAC1B,IAAI,EAAE,OAAO,GACZ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAO9C;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,6EAA6E;IAC7E,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAC;IACvC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,GAAG,iBAAiB,CA0GpB"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * account-plan — the rail's plan card, read from the Sapiom CORE surface so it
3
+ * can never disagree with the dashboard's own billing views.
4
+ *
5
+ * Three reads, folded into one `AccountPlanView`:
6
+ *
7
+ * - `GET /v1/dashboard/plan` → plan name + status
8
+ * - `GET /v1/spending-rules/spend-limit-summary` → today's settled spend vs
9
+ * the org's spend-limit rule — the exact "$used / $cap" pair the dashboard's
10
+ * balance card renders (JSON:API envelope; all-null attributes when no rule)
11
+ * - `GET /v1/accounts/spend` → `availableBalanceUsd`,
12
+ * the prepaid fallback when no limit rule exists
13
+ *
14
+ * Same auth contract as template-catalog.ts (and verified there): core takes
15
+ * `Authorization: Bearer`, NOT the agents surface's `x-sapiom-api-key`, and
16
+ * every path is prefixed `/v1`. The key stays server-side; a 401/403 triggers
17
+ * exactly one credential refresh + retry.
18
+ *
19
+ * These endpoints are excluded from core's public OpenAPI surface, so their
20
+ * shapes are contracts by observation, not by document. Every field is
21
+ * narrowed defensively and any drift degrades the readout to `none` (or the
22
+ * whole view to `fallback`) rather than throwing — a broken billing read must
23
+ * never take the rail down.
24
+ */
25
+ import { staticApiKeyProvider, } from "./api-key-provider.js";
26
+ import { resolveCoreBaseUrl } from "./definition-slug-resolver.js";
27
+ /** Mirrors template-catalog.ts: statuses worth one refresh + retry. */
28
+ function isAuthRejection(status) {
29
+ return status === 401 || status === 403;
30
+ }
31
+ /** How long a successful view is reused. Spend moves on the order of runs, not
32
+ * keystrokes; the dashboard's own hooks poll at 30–60s, and the SPA re-asks on
33
+ * its own cadence — a short TTL just absorbs bursts (mount + auth flip). */
34
+ const CACHE_TTL_MS = 60000;
35
+ function asObject(value) {
36
+ return typeof value === "object" && value !== null && !Array.isArray(value)
37
+ ? value
38
+ : null;
39
+ }
40
+ /** A finite number, from a JSON number or a decimal string (the ledger returns
41
+ * decimal(36,18) strings; the spend read model returns numbers). */
42
+ function usd(value) {
43
+ if (typeof value === "number")
44
+ return Number.isFinite(value) ? value : null;
45
+ if (typeof value === "string" && value.trim() !== "") {
46
+ const parsed = Number(value);
47
+ return Number.isFinite(parsed) ? parsed : null;
48
+ }
49
+ return null;
50
+ }
51
+ /** `{ data: { plan: { name, status } | null } }` → the card's plan line. */
52
+ export function extractPlan(body) {
53
+ const plan = asObject(asObject(asObject(body)?.data)?.plan);
54
+ if (!plan || typeof plan.name !== "string" || plan.name === "")
55
+ return null;
56
+ return { name: plan.name, status: plan.status === "active" ? "active" : "inactive" };
57
+ }
58
+ /** JSON:API `{ data: { attributes: { limitUsd, windowSpendUsd } } }` → the
59
+ * "$used / $cap" pair, or null when no qualifying rule exists (all-null
60
+ * attributes is that endpoint's documented "no rule" answer, not an error). */
61
+ export function extractLimit(body) {
62
+ const attrs = asObject(asObject(asObject(body)?.data)?.attributes);
63
+ if (!attrs)
64
+ return null;
65
+ const limitUsd = usd(attrs.limitUsd);
66
+ const usedUsd = usd(attrs.windowSpendUsd);
67
+ if (limitUsd === null || usedUsd === null)
68
+ return null;
69
+ return { usedUsd, limitUsd };
70
+ }
71
+ /** `{ data: { availableBalanceUsd } }` → the prepaid balance, or null. */
72
+ export function extractBalance(body) {
73
+ return usd(asObject(asObject(body)?.data)?.availableBalanceUsd);
74
+ }
75
+ export function createAccountPlanReader(opts) {
76
+ const provider = opts.apiKey !== null && typeof opts.apiKey === "object"
77
+ ? opts.apiKey
78
+ : staticApiKeyProvider(opts.apiKey);
79
+ const baseUrl = opts.baseUrl ?? resolveCoreBaseUrl();
80
+ const fetchImpl = opts.fetchImpl ?? fetch;
81
+ let cache = null;
82
+ // One line per distinct failure reason, not per poll — the SPA re-asks every
83
+ // minute and a persistent misconfiguration shouldn't flood the log.
84
+ const logged = new Set();
85
+ const warnOnce = (reason) => {
86
+ if (logged.has(reason))
87
+ return;
88
+ logged.add(reason);
89
+ console.error(`[harness] account plan unavailable from ${baseUrl} (${reason}); ` +
90
+ "the rail hides the plan card — check the harness is signed in " +
91
+ "and SAPIOM_CORE_URL points at a reachable Sapiom API");
92
+ };
93
+ /**
94
+ * GET `path` from the core surface with the held key, refreshing + retrying
95
+ * once on an auth rejection. Returns the parsed body, or null on any failure.
96
+ */
97
+ const getJson = async (path) => {
98
+ let apiKey = provider.getKey();
99
+ if (!apiKey)
100
+ return null;
101
+ const attempt = async (key) => {
102
+ try {
103
+ return await fetchImpl(`${baseUrl}${path}`, {
104
+ // Core (`api.*`) takes a Bearer token — see template-catalog.ts.
105
+ headers: { Authorization: `Bearer ${key}` },
106
+ });
107
+ }
108
+ catch (err) {
109
+ warnOnce(err instanceof Error ? err.message : String(err));
110
+ return null;
111
+ }
112
+ };
113
+ let response = await attempt(apiKey);
114
+ if (!response)
115
+ return null;
116
+ if (isAuthRejection(response.status)) {
117
+ const refreshed = await provider.refresh();
118
+ if (refreshed && refreshed !== apiKey) {
119
+ apiKey = refreshed;
120
+ response = await attempt(refreshed);
121
+ if (!response)
122
+ return null;
123
+ }
124
+ }
125
+ if (!response.ok) {
126
+ warnOnce(`HTTP ${response.status} on ${path}`);
127
+ return null;
128
+ }
129
+ try {
130
+ return await response.json();
131
+ }
132
+ catch {
133
+ warnOnce("response body was not JSON");
134
+ return null;
135
+ }
136
+ };
137
+ return {
138
+ async view() {
139
+ const fresh = cache && Date.now() - cache.at < CACHE_TTL_MS;
140
+ if (fresh && cache)
141
+ return cache.value;
142
+ // Signed out is an expected state (a harness launched without auth), not
143
+ // a fault — the card simply doesn't render.
144
+ if (!provider.getKey()) {
145
+ return { plan: null, readout: { kind: "none" }, source: "fallback", reason: "signed-out" };
146
+ }
147
+ // Three independent reads; each may fail alone. A plan with no numbers
148
+ // and numbers with no plan are both better than nothing, so partial
149
+ // success builds a partial view instead of discarding what answered.
150
+ const [planBody, limitBody, spendBody] = await Promise.all([
151
+ getJson("/v1/dashboard/plan"),
152
+ getJson("/v1/spending-rules/spend-limit-summary"),
153
+ getJson("/v1/accounts/spend"),
154
+ ]);
155
+ if (planBody === null && limitBody === null && spendBody === null) {
156
+ // Nothing answered — unreachable (or every shape drifted). Not cached:
157
+ // the next poll should get to try again.
158
+ return { plan: null, readout: { kind: "none" }, source: "fallback", reason: "unreachable" };
159
+ }
160
+ const plan = extractPlan(planBody);
161
+ const limit = extractLimit(limitBody);
162
+ const balance = extractBalance(spendBody);
163
+ const readout = limit
164
+ ? { kind: "limit", ...limit }
165
+ : balance !== null
166
+ ? { kind: "balance", availableUsd: balance }
167
+ : { kind: "none" };
168
+ const value = { plan, readout, source: "live" };
169
+ cache = { at: Date.now(), value };
170
+ return value;
171
+ },
172
+ };
173
+ }
174
+ //# sourceMappingURL=account-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-plan.js","sourceRoot":"","sources":["../../src/core/account-plan.ts"],"names":[],"mappings":"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"}
@@ -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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"canvas-manifest-check.d.ts","sourceRoot":"","sources":["../../src/core/canvas-manifest-check.ts"],"names":[],"mappings":"AAoEA,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,IAAI,CAAC;IACT,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,GAAG,oBAAoB,CAAC;AAE9E;;2DAE2D;AAC3D,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAsChF"}
1
+ {"version":3,"file":"canvas-manifest-check.d.ts","sourceRoot":"","sources":["../../src/core/canvas-manifest-check.ts"],"names":[],"mappings":"AAoEA,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,IAAI,CAAC;IACT,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,GAAG,oBAAoB,CAAC;AAqB9E;;2DAE2D;AAC3D,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,CAAC,CAyD9B"}