@north-light/crouter 0.3.198 → 0.3.199

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 (314) hide show
  1. package/dist/api/client.d.ts +18 -18
  2. package/dist/api/client.js +29 -37
  3. package/dist/api/dto/broker-ops.d.ts +3 -1
  4. package/dist/api/dto/broker.d.ts +13 -2
  5. package/dist/api/dto/broker.js +4 -4
  6. package/dist/api/dto/human.d.ts +6 -5
  7. package/dist/api/dto/inbox.d.ts +81 -34
  8. package/dist/api/dto/nodes.d.ts +8 -2
  9. package/dist/api/dto/profiles.d.ts +23 -0
  10. package/dist/api/dto/profiles.js +2 -2
  11. package/dist/api/dto/worktree.d.ts +3 -5
  12. package/dist/api/routes.d.ts +3 -5
  13. package/dist/api/routes.js +4 -6
  14. package/dist/builtin-memory/00-runtime-base.md +6 -6
  15. package/dist/builtin-memory/01-spine/01-no-manager.md +1 -1
  16. package/dist/builtin-memory/02-lifecycle/00-terminal.md +3 -3
  17. package/dist/builtin-memory/04-orchestration-kernel.md +6 -6
  18. package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
  19. package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +2 -2
  20. package/dist/builtin-memory/05-kinds/review/00-base.md +2 -2
  21. package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -1
  22. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +1 -1
  23. package/dist/builtin-memory/insights/capture.md +2 -2
  24. package/dist/builtin-memory/insights/init.md +3 -3
  25. package/dist/builtin-memory/internal/INDEX.md +1 -1
  26. package/dist/builtin-memory/internal/memory-loading.md +1 -1
  27. package/dist/builtin-memory/internal/nodes-and-canvas.md +2 -2
  28. package/dist/builtin-memory/internal/plugins.md +59 -2
  29. package/dist/builtin-memory/internal/storage-tiers.md +3 -1
  30. package/dist/builtin-memory/spec/roadmap.md +2 -2
  31. package/dist/builtin-memory/testing.md +1 -1
  32. package/dist/clients/attach/chrome/bash-jobs.js +3 -3
  33. package/dist/clients/attach/render/chat-view.d.ts +26 -1
  34. package/dist/clients/attach/render/chat-view.js +61 -11
  35. package/dist/clients/attach/render/page-block.d.ts +34 -0
  36. package/dist/clients/attach/render/page-block.js +226 -0
  37. package/dist/clients/attach/session/whip.d.ts +2 -0
  38. package/dist/clients/attach/session/whip.js +2 -0
  39. package/dist/clients/attach/viewer.js +1419 -993
  40. package/dist/clients/conversation/projection.js +18 -3
  41. package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +9 -6
  42. package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +13 -21
  43. package/dist/clients/inbox/controller.js +10 -16
  44. package/dist/clients/inbox/page-adapter.d.ts +1 -3
  45. package/dist/clients/inbox/page-adapter.js +3 -4
  46. package/dist/clients/inbox/resolve.d.ts +1 -1
  47. package/dist/clients/inbox/resolve.js +3 -3
  48. package/dist/clients/inbox/review/document-surface.js +3 -1
  49. package/dist/clients/inbox/review/state.d.ts +2 -1
  50. package/dist/clients/inbox/review/state.js +5 -16
  51. package/dist/clients/inbox/tui/input.js +37 -19
  52. package/dist/clients/inbox/tui/panel.js +5 -31
  53. package/dist/clients/inbox/tui/render.d.ts +11 -0
  54. package/dist/clients/inbox/tui/render.js +71 -27
  55. package/dist/clients/inbox/tui/slots.d.ts +3 -1
  56. package/dist/clients/inbox/tui/slots.js +16 -12
  57. package/dist/clients/inbox/tui/types.d.ts +2 -7
  58. package/dist/clients/inbox/tui.js +2 -2
  59. package/dist/commands/__tests__/human.test.js +71 -114
  60. package/dist/commands/__tests__/node-message.test.js +14 -0
  61. package/dist/commands/attention.js +4 -4
  62. package/dist/commands/canvas-snapshot.js +1 -1
  63. package/dist/commands/canvas.js +1 -1
  64. package/dist/commands/dashboard.js +1 -1
  65. package/dist/commands/human/{html.d.ts → components.d.ts} +1 -1
  66. package/dist/commands/human/components.js +77 -0
  67. package/dist/commands/human/feedback.d.ts +2 -0
  68. package/dist/commands/human/feedback.js +108 -0
  69. package/dist/commands/human/prompts.d.ts +13 -5
  70. package/dist/commands/human/prompts.js +160 -97
  71. package/dist/commands/human/queue.js +57 -88
  72. package/dist/commands/human/shared.d.ts +2 -12
  73. package/dist/commands/human/shared.js +17 -11
  74. package/dist/commands/human.js +29 -21
  75. package/dist/commands/memory/origin.js +2 -2
  76. package/dist/commands/node/bash.js +4 -4
  77. package/dist/commands/node/inspect.js +3 -3
  78. package/dist/commands/node/lifecycle.js +1 -1
  79. package/dist/commands/node/message.js +2 -2
  80. package/dist/commands/node-worktree.js +8 -8
  81. package/dist/commands/pkg/browse.js +1 -1
  82. package/dist/commands/pkg/plugin-manage.js +129 -10
  83. package/dist/commands/profile/delete.js +41 -15
  84. package/dist/commands/profile.js +1 -1
  85. package/dist/commands/push.js +1 -1
  86. package/dist/commands/surface/node/focus.js +29 -14
  87. package/dist/commands/surface-edit.js +3 -3
  88. package/dist/commands/surface-inbox.d.ts +2 -0
  89. package/dist/commands/{human/inbox.js → surface-inbox.js} +14 -18
  90. package/dist/commands/surface.js +2 -1
  91. package/dist/commands/sys/doctor.js +60 -3
  92. package/dist/commands/sys/feedback.js +79 -25
  93. package/dist/commands/sys/settings.js +1 -1
  94. package/dist/core/__tests__/cron-broker-capacity.test.js +1 -1
  95. package/dist/core/__tests__/extension-abort.test.js +5 -2
  96. package/dist/core/__tests__/fixtures/fake-engine.d.ts +13 -2
  97. package/dist/core/__tests__/fixtures/fake-engine.js +47 -3
  98. package/dist/core/__tests__/human-cancel-guard.test.js +31 -10
  99. package/dist/core/__tests__/human-deliver.test.js +31 -26
  100. package/dist/core/__tests__/human-node-not-supervised.test.js +1 -1
  101. package/dist/core/__tests__/plugin-page-components.test.js +157 -0
  102. package/dist/core/__tests__/seam/dormancy-release.test.js +40 -0
  103. package/dist/core/__tests__/serial/flagship-lifecycle.test.js +2 -2
  104. package/dist/core/__tests__/serial/human-deliver-e2e.test.js +12 -6
  105. package/dist/core/__tests__/serial/live-mutation.test.js +1 -1
  106. package/dist/core/__tests__/serial/tmux-surface.test.js +4 -2
  107. package/dist/core/__tests__/serial/worktree.test.js +24 -198
  108. package/dist/core/__tests__/session-cycles.test.js +22 -0
  109. package/dist/core/__tests__/stop-guard.test.js +4 -4
  110. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +19 -4
  111. package/dist/core/bash-jobs.d.ts +6 -0
  112. package/dist/core/bash-jobs.js +10 -0
  113. package/dist/core/canvas/__tests__/attention.test.js +8 -5
  114. package/dist/core/canvas/__tests__/render-remote.test.js +5 -5
  115. package/dist/core/canvas/attention.js +8 -6
  116. package/dist/core/canvas/browse/model.d.ts +8 -2
  117. package/dist/core/canvas/browse/model.js +11 -4
  118. package/dist/core/canvas/canvas.d.ts +7 -0
  119. package/dist/core/canvas/canvas.js +37 -0
  120. package/dist/core/canvas/crons.d.ts +9 -0
  121. package/dist/core/canvas/crons.js +51 -0
  122. package/dist/core/canvas/node-order.d.ts +22 -1
  123. package/dist/core/canvas/node-order.js +26 -1
  124. package/dist/core/canvas/render-source.d.ts +5 -0
  125. package/dist/core/canvas/render-source.js +1 -0
  126. package/dist/core/canvas/types.d.ts +9 -3
  127. package/dist/core/command-plugins/bundle.d.ts +6 -1
  128. package/dist/core/command-plugins/bundle.js +26 -13
  129. package/dist/core/command.js +2 -1
  130. package/dist/core/config.d.ts +47 -1
  131. package/dist/core/config.js +137 -4
  132. package/dist/core/help.js +1 -1
  133. package/dist/core/human/__tests__/page-catalog.test.js +4 -0
  134. package/dist/core/human/__tests__/page-tickets.test.js +65 -52
  135. package/dist/core/human/__tests__/page.test.js +56 -98
  136. package/dist/core/human/__tests__/serial/inbox-core.test.js +6 -6
  137. package/dist/core/human/answer-text.js +3 -3
  138. package/dist/core/human/answer.d.ts +6 -4
  139. package/dist/core/human/answer.js +4 -10
  140. package/dist/core/human/component-docs.d.ts +11 -7
  141. package/dist/core/human/component-docs.js +361 -88
  142. package/dist/core/human/convention.d.ts +17 -3
  143. package/dist/core/human/convention.js +36 -5
  144. package/dist/core/human/feedback-companion.d.ts +20 -0
  145. package/dist/core/human/feedback-companion.js +98 -0
  146. package/dist/core/human/feedback.d.ts +65 -0
  147. package/dist/core/human/feedback.js +116 -0
  148. package/dist/core/human/page-catalog.d.ts +40 -5
  149. package/dist/core/human/page-catalog.js +102 -30
  150. package/dist/core/human/page-errors.d.ts +4 -0
  151. package/dist/core/human/page-errors.js +7 -0
  152. package/dist/core/human/page-eval.d.ts +20 -0
  153. package/dist/core/human/page-eval.js +123 -0
  154. package/dist/core/human/page-schema.d.ts +23 -191
  155. package/dist/core/human/page-schema.js +60 -89
  156. package/dist/core/human/page-synth.d.ts +1 -1
  157. package/dist/core/human/page-synth.js +15 -18
  158. package/dist/core/human/page.d.ts +12 -27
  159. package/dist/core/human/page.js +142 -474
  160. package/dist/core/human/root.d.ts +6 -2
  161. package/dist/core/human/root.js +12 -4
  162. package/dist/core/human/scan.d.ts +3 -4
  163. package/dist/core/human/scan.js +16 -15
  164. package/dist/core/human/summary.d.ts +1 -2
  165. package/dist/core/human/summary.js +2 -2
  166. package/dist/core/human/tickets.d.ts +20 -14
  167. package/dist/core/human/tickets.js +91 -31
  168. package/dist/core/human/types.d.ts +10 -2
  169. package/dist/core/preview-registry.js +8 -10
  170. package/dist/core/profiles/default-binding.d.ts +4 -0
  171. package/dist/core/profiles/default-binding.js +24 -0
  172. package/dist/core/profiles/deletion-reservation.d.ts +8 -0
  173. package/dist/core/profiles/deletion-reservation.js +38 -0
  174. package/dist/core/profiles/manifest.d.ts +3 -0
  175. package/dist/core/profiles/manifest.js +12 -0
  176. package/dist/core/profiles/select.js +2 -2
  177. package/dist/core/review/realize.js +3 -3
  178. package/dist/core/review/store.d.ts +6 -0
  179. package/dist/core/review/store.js +31 -0
  180. package/dist/core/runtime/bearings.d.ts +0 -4
  181. package/dist/core/runtime/bearings.js +4 -62
  182. package/dist/core/runtime/bin-contributions.d.ts +44 -0
  183. package/dist/core/runtime/bin-contributions.js +186 -0
  184. package/dist/core/runtime/broker/client-registry.d.ts +4 -0
  185. package/dist/core/runtime/broker/client-registry.js +13 -1
  186. package/dist/core/runtime/broker/extension-abort.d.ts +1 -1
  187. package/dist/core/runtime/broker/extension-abort.js +4 -2
  188. package/dist/core/runtime/broker/fault-retry.js +4 -0
  189. package/dist/core/runtime/broker/frame-dispatch.d.ts +3 -1
  190. package/dist/core/runtime/broker/frame-dispatch.js +5 -6
  191. package/dist/core/runtime/broker/read-ops.d.ts +1 -1
  192. package/dist/core/runtime/broker/read-ops.js +2 -2
  193. package/dist/core/runtime/broker/rebind.d.ts +1 -0
  194. package/dist/core/runtime/broker/rebind.js +6 -1
  195. package/dist/core/runtime/broker-extension-render.js +19 -0
  196. package/dist/core/runtime/broker-protocol.d.ts +14 -0
  197. package/dist/core/runtime/broker.d.ts +1 -1
  198. package/dist/core/runtime/broker.js +17 -6
  199. package/dist/core/runtime/front-door-env.d.ts +5 -0
  200. package/dist/core/runtime/front-door-env.js +16 -0
  201. package/dist/core/runtime/front-door.d.ts +1 -5
  202. package/dist/core/runtime/front-door.js +2 -5
  203. package/dist/core/runtime/host.d.ts +1 -1
  204. package/dist/core/runtime/invocation.d.ts +6 -0
  205. package/dist/core/runtime/invocation.js +10 -0
  206. package/dist/core/runtime/kickoff.js +34 -0
  207. package/dist/core/runtime/launch.d.ts +2 -6
  208. package/dist/core/runtime/node-read.js +4 -1
  209. package/dist/core/runtime/nodes.js +2 -0
  210. package/dist/core/runtime/promote.d.ts +1 -0
  211. package/dist/core/runtime/promote.js +3 -1
  212. package/dist/core/runtime/session-cycles.d.ts +6 -0
  213. package/dist/core/runtime/session-cycles.js +15 -1
  214. package/dist/core/runtime/session-visibility.d.ts +17 -8
  215. package/dist/core/runtime/session-visibility.js +19 -10
  216. package/dist/core/runtime/spawn-env.d.ts +9 -1
  217. package/dist/core/runtime/spawn-env.js +62 -2
  218. package/dist/core/runtime/stop-guard.d.ts +2 -2
  219. package/dist/core/runtime/stop-guard.js +2 -2
  220. package/dist/core/runtime/stop-signals.d.ts +1 -1
  221. package/dist/core/runtime/stop-signals.js +2 -2
  222. package/dist/core/runtime/tmux-bindings.js +1 -1
  223. package/dist/core/session-model/session-state.d.ts +4 -3
  224. package/dist/core/session-model/session-state.js +14 -1
  225. package/dist/core/user-settings.d.ts +21 -2
  226. package/dist/core/user-settings.js +32 -11
  227. package/dist/core/worktree.d.ts +15 -45
  228. package/dist/core/worktree.js +59 -261
  229. package/dist/daemon/api/__tests__/seam/profile-delete.test.d.ts +1 -0
  230. package/dist/daemon/api/__tests__/seam/profile-delete.test.js +386 -0
  231. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  232. package/dist/daemon/api/handlers/broker-ops.js +9 -5
  233. package/dist/daemon/api/handlers/feedback-comments.d.ts +2 -0
  234. package/dist/daemon/api/handlers/feedback-comments.js +207 -0
  235. package/dist/daemon/api/handlers/human.js +24 -20
  236. package/dist/daemon/api/handlers/inbox.d.ts +10 -0
  237. package/dist/daemon/api/handlers/inbox.js +39 -115
  238. package/dist/daemon/api/handlers/profiles.js +11 -29
  239. package/dist/daemon/api/map.d.ts +6 -1
  240. package/dist/daemon/api/map.js +23 -0
  241. package/dist/daemon/api/server.js +3 -1
  242. package/dist/daemon/companion-retire.d.ts +2 -0
  243. package/dist/daemon/companion-retire.js +33 -0
  244. package/dist/daemon/cron-run.js +14 -16
  245. package/dist/daemon/human/finish.d.ts +12 -7
  246. package/dist/daemon/human/finish.js +101 -38
  247. package/dist/daemon/human/sweep.js +5 -1
  248. package/dist/daemon/profile-delete.d.ts +7 -0
  249. package/dist/daemon/profile-delete.js +306 -0
  250. package/dist/daemon/reconcilers/broker-supervision.js +3 -1
  251. package/dist/daemon/review/deliver.js +3 -3
  252. package/dist/daemon/review/finish.d.ts +0 -2
  253. package/dist/daemon/review/finish.js +1 -29
  254. package/dist/pi-extensions/__tests__/canvas-bash-valve.test.js +56 -1
  255. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +4 -4
  256. package/dist/pi-extensions/canvas-bash-valve.js +19 -5
  257. package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1
  258. package/dist/pi-extensions/canvas-review-boundary.d.ts +4 -0
  259. package/dist/pi-extensions/canvas-review-boundary.js +18 -9
  260. package/dist/pi-extensions/canvas-stophook.js +4 -4
  261. package/dist/shared/generated-context.js +2 -2
  262. package/dist/types.d.ts +44 -2
  263. package/dist/types.js +7 -2
  264. package/package.json +4 -4
  265. package/runtime.lock.json +5 -33
  266. package/dist/builtin-memory/init.md +0 -38
  267. package/dist/builtin-memory/plan.md +0 -19
  268. package/dist/builtin-memory/spec.md +0 -19
  269. package/dist/commands/human/doc.d.ts +0 -2
  270. package/dist/commands/human/doc.js +0 -91
  271. package/dist/commands/human/html.js +0 -81
  272. package/dist/commands/human/inbox.d.ts +0 -2
  273. package/dist/core/human/__tests__/html-markdown.test.js +0 -52
  274. package/dist/core/human/__tests__/page-render.test.js +0 -66
  275. package/dist/core/human/html-markdown.d.ts +0 -3
  276. package/dist/core/human/html-markdown.js +0 -288
  277. package/dist/core/human/page-render.d.ts +0 -4
  278. package/dist/core/human/page-render.js +0 -105
  279. package/dist/pages/bundle.css +0 -1
  280. package/dist/pages/bundle.js +0 -1778
  281. package/dist/pages/comments.d.ts +0 -72
  282. package/dist/pages/comments.js +0 -176
  283. package/dist/pages/controls.d.ts +0 -98
  284. package/dist/pages/controls.js +0 -261
  285. package/dist/pages/elements/cards.d.ts +0 -28
  286. package/dist/pages/elements/cards.js +0 -915
  287. package/dist/pages/elements/chart.d.ts +0 -23
  288. package/dist/pages/elements/chart.js +0 -664
  289. package/dist/pages/elements/options.d.ts +0 -30
  290. package/dist/pages/elements/options.js +0 -742
  291. package/dist/pages/elements/pages.d.ts +0 -30
  292. package/dist/pages/elements/pages.js +0 -377
  293. package/dist/pages/elements/slot.d.ts +0 -26
  294. package/dist/pages/elements/slot.js +0 -112
  295. package/dist/pages/elements/table.d.ts +0 -36
  296. package/dist/pages/elements/table.js +0 -1043
  297. package/dist/pages/elements/text.d.ts +0 -31
  298. package/dist/pages/elements/text.js +0 -1175
  299. package/dist/pages/entry.d.ts +0 -8
  300. package/dist/pages/entry.js +0 -8
  301. package/dist/pages/host.d.ts +0 -134
  302. package/dist/pages/host.js +0 -165
  303. package/dist/pages/readonly.d.ts +0 -24
  304. package/dist/pages/readonly.js +0 -31
  305. package/dist/pages/register.d.ts +0 -2
  306. package/dist/pages/register.js +0 -3
  307. package/dist/pages/responses.d.ts +0 -37
  308. package/dist/pages/responses.js +0 -56
  309. package/dist/pages/slot-config.d.ts +0 -36
  310. package/dist/pages/slot-config.js +0 -50
  311. package/dist/pages/types.d.ts +0 -98
  312. package/dist/pages/types.js +0 -23
  313. /package/dist/{core/human/__tests__/html-markdown.test.d.ts → commands/__tests__/node-message.test.d.ts} +0 -0
  314. /package/dist/core/{human/__tests__/page-render.test.d.ts → __tests__/plugin-page-components.test.d.ts} +0 -0
@@ -1,8 +0,0 @@
1
- import './bundle.css';
2
- import './elements/options.js';
3
- import './elements/text.js';
4
- import './elements/table.js';
5
- import './elements/cards.js';
6
- import './elements/chart.js';
7
- import './elements/pages.js';
8
- import './elements/slot.js';
@@ -1,8 +0,0 @@
1
- import './bundle.css';
2
- import './elements/options.js';
3
- import './elements/text.js';
4
- import './elements/table.js';
5
- import './elements/cards.js';
6
- import './elements/chart.js';
7
- import './elements/pages.js';
8
- import './elements/slot.js';
@@ -1,134 +0,0 @@
1
- /**
2
- * `window.crtr` — the one door out of a page.
3
- *
4
- * An element renders inside a host (Northlight's srcdoc host today, a crtrd-served
5
- * page later) that installs this bridge before the bundle loads. Everything an element
6
- * needs from the outside world arrives through it: there is no `fetch`, no `XMLHttpRequest`,
7
- * no direct network access anywhere under `src/pages/`. An element that cannot get what it
8
- * needs renders a named unavailable state; it never falls back to reaching out itself.
9
- *
10
- * Two things the bridge deliberately does NOT have:
11
- *
12
- * - **No `save` and no `dismiss`.** Both are host chrome — a frame around the page, not
13
- * markup inside it — so they are the host's own UI actions and are never advertised to
14
- * page code.
15
- * - **No per-element resolution.** `respond()` is a local-state write plus a request that
16
- * the host autosave the partial map; it does not resolve the ticket. Only the pager's
17
- * submit affordance calls `submit()`, which posts the complete map once.
18
- *
19
- * `respond()` has one counterpart, `savedResponse()`: the host hands back the response it is
20
- * currently holding for a slot, so a page reopened after a partial answer re-mounts SHOWING
21
- * that answer instead of blank. Every response-bearing element reads it at mount and seeds
22
- * its visible state from it — that is what keeps "what submit sends" and "what the screen
23
- * shows" the same thing.
24
- *
25
- * The host is optional at the type level (`window.crtr?`) because a page can be opened
26
- * bare — dropped in a browser, or rendered by a host that installs nothing. Elements read
27
- * the bridge through the accessors below rather than touching `window.crtr` directly, so
28
- * that absence is typed and total instead of an `as any` at each call site.
29
- */
30
- import type { SlotResponse } from './types.js';
31
- /** Live host theme tokens, as `--crtr-*` custom-property names mapped to values. */
32
- export interface CrtrThemeBridge {
33
- current(): Record<string, string>;
34
- /** Registers `listener` for later theme changes; returns its unsubscribe. */
35
- subscribe(listener: (tokens: Record<string, string>) => void): () => void;
36
- }
37
- /** What `mountWorkspaceComponent` can answer: the host rendered it, or it has no renderer. */
38
- export type WorkspaceMountOutcome = 'mounted' | 'unavailable';
39
- /** The bridge a host installs at `window.crtr`. */
40
- export interface CrtrHost {
41
- /**
42
- * Records this slot's complete current response and asks the host to autosave the
43
- * partial map. Called on every user change. NOT ticket resolution.
44
- */
45
- respond(slotId: string, response: SlotResponse): void;
46
- /**
47
- * The response the host currently holds for this slot — an autosaved partial answer on a
48
- * reopened page, or the published answer on a resolved one. `undefined` when the host has
49
- * nothing for the slot. Elements read it at mount; it is the inbound half of `respond`.
50
- */
51
- savedResponse(slotId: string): SlotResponse | undefined;
52
- /** Posts the complete response map once. Only the pager's submit affordance calls it. */
53
- submit(): Promise<void>;
54
- /** Flushes the pending autosave of the partial map. */
55
- progress(): Promise<void>;
56
- readonly theme: CrtrThemeBridge;
57
- /**
58
- * Asks the host to render a product-registered (`unvalidated`) slot into `element`.
59
- * A host with no renderer for `kind` answers `'unavailable'`.
60
- */
61
- mountWorkspaceComponent(element: HTMLElement, kind: string, config: Record<string, unknown>): Promise<WorkspaceMountOutcome>;
62
- }
63
- declare global {
64
- interface Window {
65
- /**
66
- * Installed by the host before the bundle loads. Optional: a page opened bare has
67
- * no bridge, and every element must still render.
68
- */
69
- crtr?: CrtrHost;
70
- }
71
- }
72
- /**
73
- * The outcome of a bridge call. `unavailable` means the door is not there — no host, or a
74
- * host that does not implement this method. `failed` means the host was asked and said no,
75
- * and `reason` is what it said. Elements distinguish them because "this page is not hosted"
76
- * and "the server rejected your answer" are different things to show a person.
77
- */
78
- export type HostCall = {
79
- status: 'ok';
80
- } | {
81
- status: 'unavailable';
82
- reason: string;
83
- } | {
84
- status: 'failed';
85
- reason: string;
86
- };
87
- /** The installed bridge, or `undefined` on a bare page. */
88
- export declare function host(): CrtrHost | undefined;
89
- /**
90
- * Writes this slot's complete current response to the host's in-frame map and requests an
91
- * autosave. Elements call this on every user change with the whole response object, never a
92
- * delta. Safe on a bare page: the element's own local state is authoritative for rendering,
93
- * so an unavailable host only means the answer is not being persisted.
94
- */
95
- export declare function respond(slotId: string, response: SlotResponse): HostCall;
96
- /**
97
- * The response the host already holds for this slot, or `undefined` when it holds none — a
98
- * bare page, a first open, or a host without the channel. Elements call this once at mount
99
- * and seed their visible state from it, so a reopened page shows the answers the host would
100
- * submit rather than an empty form beside a full response map.
101
- *
102
- * `T` is asserted, not verified, exactly like `readSlotConfig`'s config: the host's saved map
103
- * was validated against this slot's kind before it was stored. What is not guaranteed is that
104
- * a host implements the channel at all, which is what the `undefined` covers — so seed with
105
- * the same defensiveness you would give any outside value (`savedIds`, `adoptComments`).
106
- */
107
- export declare function savedResponse<T extends SlotResponse = SlotResponse>(slotId: string): T | undefined;
108
- /** The string ids of a saved selection field, with anything else in it dropped. */
109
- export declare function savedIds(value: unknown): string[];
110
- /**
111
- * Posts the complete response map once, resolving the ticket. Only the pager's submit
112
- * affordance calls this.
113
- */
114
- export declare function submit(): Promise<HostCall>;
115
- /** Flushes the host's pending autosave of the partial map. Never resolves the ticket. */
116
- export declare function progress(): Promise<HostCall>;
117
- /**
118
- * The host's current theme token values. Empty on a bare page — which is correct and needs
119
- * no handling, because `bundle.css` declares every `--crtr-*` token at zero specificity and
120
- * elements style through those custom properties rather than through this map. Read it only
121
- * when a value must reach somewhere CSS cannot, such as an SVG attribute.
122
- */
123
- export declare function themeTokens(): Record<string, string>;
124
- /**
125
- * Subscribes to later theme changes. Always returns an unsubscribe, so a caller can wire it
126
- * to `disconnectedCallback` without checking whether a host was there.
127
- */
128
- export declare function subscribeTheme(listener: (tokens: Record<string, string>) => void): () => void;
129
- /**
130
- * Asks the host to render a product-registered slot into `element`. A bare page, a host with
131
- * no registry, and a host whose mount threw all answer `'unavailable'` — the escape element's
132
- * named unavailable state is the only other outcome.
133
- */
134
- export declare function mountWorkspaceComponent(element: HTMLElement, kind: string, config: Record<string, unknown>): Promise<WorkspaceMountOutcome>;
@@ -1,165 +0,0 @@
1
- /**
2
- * `window.crtr` — the one door out of a page.
3
- *
4
- * An element renders inside a host (Northlight's srcdoc host today, a crtrd-served
5
- * page later) that installs this bridge before the bundle loads. Everything an element
6
- * needs from the outside world arrives through it: there is no `fetch`, no `XMLHttpRequest`,
7
- * no direct network access anywhere under `src/pages/`. An element that cannot get what it
8
- * needs renders a named unavailable state; it never falls back to reaching out itself.
9
- *
10
- * Two things the bridge deliberately does NOT have:
11
- *
12
- * - **No `save` and no `dismiss`.** Both are host chrome — a frame around the page, not
13
- * markup inside it — so they are the host's own UI actions and are never advertised to
14
- * page code.
15
- * - **No per-element resolution.** `respond()` is a local-state write plus a request that
16
- * the host autosave the partial map; it does not resolve the ticket. Only the pager's
17
- * submit affordance calls `submit()`, which posts the complete map once.
18
- *
19
- * `respond()` has one counterpart, `savedResponse()`: the host hands back the response it is
20
- * currently holding for a slot, so a page reopened after a partial answer re-mounts SHOWING
21
- * that answer instead of blank. Every response-bearing element reads it at mount and seeds
22
- * its visible state from it — that is what keeps "what submit sends" and "what the screen
23
- * shows" the same thing.
24
- *
25
- * The host is optional at the type level (`window.crtr?`) because a page can be opened
26
- * bare — dropped in a browser, or rendered by a host that installs nothing. Elements read
27
- * the bridge through the accessors below rather than touching `window.crtr` directly, so
28
- * that absence is typed and total instead of an `as any` at each call site.
29
- */
30
- /** The installed bridge, or `undefined` on a bare page. */
31
- export function host() {
32
- return typeof window === 'undefined' ? undefined : window.crtr;
33
- }
34
- function reasonOf(error) {
35
- if (error instanceof Error && error.message !== '')
36
- return error.message;
37
- const text = String(error);
38
- return text === '' ? 'unknown error' : text;
39
- }
40
- function missing(method) {
41
- return { status: 'unavailable', reason: `host bridge does not provide ${method}()` };
42
- }
43
- /**
44
- * Writes this slot's complete current response to the host's in-frame map and requests an
45
- * autosave. Elements call this on every user change with the whole response object, never a
46
- * delta. Safe on a bare page: the element's own local state is authoritative for rendering,
47
- * so an unavailable host only means the answer is not being persisted.
48
- */
49
- export function respond(slotId, response) {
50
- const bridge = host();
51
- if (typeof bridge?.respond !== 'function')
52
- return missing('respond');
53
- try {
54
- bridge.respond(slotId, response);
55
- return { status: 'ok' };
56
- }
57
- catch (error) {
58
- return { status: 'failed', reason: reasonOf(error) };
59
- }
60
- }
61
- /**
62
- * The response the host already holds for this slot, or `undefined` when it holds none — a
63
- * bare page, a first open, or a host without the channel. Elements call this once at mount
64
- * and seed their visible state from it, so a reopened page shows the answers the host would
65
- * submit rather than an empty form beside a full response map.
66
- *
67
- * `T` is asserted, not verified, exactly like `readSlotConfig`'s config: the host's saved map
68
- * was validated against this slot's kind before it was stored. What is not guaranteed is that
69
- * a host implements the channel at all, which is what the `undefined` covers — so seed with
70
- * the same defensiveness you would give any outside value (`savedIds`, `adoptComments`).
71
- */
72
- export function savedResponse(slotId) {
73
- const bridge = host();
74
- if (typeof bridge?.savedResponse !== 'function')
75
- return undefined;
76
- try {
77
- const saved = bridge.savedResponse(slotId);
78
- return typeof saved === 'object' && saved !== null && !Array.isArray(saved) ? saved : undefined;
79
- }
80
- catch {
81
- return undefined;
82
- }
83
- }
84
- /** The string ids of a saved selection field, with anything else in it dropped. */
85
- export function savedIds(value) {
86
- return Array.isArray(value) ? value.filter((id) => typeof id === 'string') : [];
87
- }
88
- /**
89
- * Posts the complete response map once, resolving the ticket. Only the pager's submit
90
- * affordance calls this.
91
- */
92
- export async function submit() {
93
- const bridge = host();
94
- if (typeof bridge?.submit !== 'function')
95
- return missing('submit');
96
- try {
97
- await bridge.submit();
98
- return { status: 'ok' };
99
- }
100
- catch (error) {
101
- return { status: 'failed', reason: reasonOf(error) };
102
- }
103
- }
104
- /** Flushes the host's pending autosave of the partial map. Never resolves the ticket. */
105
- export async function progress() {
106
- const bridge = host();
107
- if (typeof bridge?.progress !== 'function')
108
- return missing('progress');
109
- try {
110
- await bridge.progress();
111
- return { status: 'ok' };
112
- }
113
- catch (error) {
114
- return { status: 'failed', reason: reasonOf(error) };
115
- }
116
- }
117
- /**
118
- * The host's current theme token values. Empty on a bare page — which is correct and needs
119
- * no handling, because `bundle.css` declares every `--crtr-*` token at zero specificity and
120
- * elements style through those custom properties rather than through this map. Read it only
121
- * when a value must reach somewhere CSS cannot, such as an SVG attribute.
122
- */
123
- export function themeTokens() {
124
- const bridge = host();
125
- if (typeof bridge?.theme?.current !== 'function')
126
- return {};
127
- try {
128
- return bridge.theme.current();
129
- }
130
- catch {
131
- return {};
132
- }
133
- }
134
- /**
135
- * Subscribes to later theme changes. Always returns an unsubscribe, so a caller can wire it
136
- * to `disconnectedCallback` without checking whether a host was there.
137
- */
138
- export function subscribeTheme(listener) {
139
- const bridge = host();
140
- if (typeof bridge?.theme?.subscribe !== 'function')
141
- return () => { };
142
- try {
143
- const unsubscribe = bridge.theme.subscribe(listener);
144
- return typeof unsubscribe === 'function' ? unsubscribe : () => { };
145
- }
146
- catch {
147
- return () => { };
148
- }
149
- }
150
- /**
151
- * Asks the host to render a product-registered slot into `element`. A bare page, a host with
152
- * no registry, and a host whose mount threw all answer `'unavailable'` — the escape element's
153
- * named unavailable state is the only other outcome.
154
- */
155
- export async function mountWorkspaceComponent(element, kind, config) {
156
- const bridge = host();
157
- if (typeof bridge?.mountWorkspaceComponent !== 'function')
158
- return 'unavailable';
159
- try {
160
- return await bridge.mountWorkspaceComponent(element, kind, config);
161
- }
162
- catch {
163
- return 'unavailable';
164
- }
165
- }
@@ -1,24 +0,0 @@
1
- /**
2
- * Read-only presentation for a page that can no longer take an answer.
3
- *
4
- * A resolved or canceled page is still opened, read, and saved — the host renders it exactly
5
- * as before and marks it out of reach: `inert` on each response-bearing element (Northlight's
6
- * srcdoc host does this on every `[slot-id]`), and `disabled` on the pager so submit is gone.
7
- * `inert` blocks pointer and keyboard interaction, but it is only a hit-testing rule: the
8
- * controls underneath still LOOK live, and a scripted click still flips a checkbox. So the
9
- * elements take the same signal and put it where a person can see it — every input renders
10
- * disabled and every writing box read-only, which is also what makes the state unreachable
11
- * rather than merely unclickable.
12
- *
13
- * The signal is read from the DOM rather than from a new attribute, because both halves of it
14
- * already exist: `inert` is a standard reflected attribute the host sets, and `disabled` on
15
- * `<crtr-pages>` is the attribute the pager itself observes.
16
- */
17
- /** Whether this element sits on a page that can no longer take an answer. */
18
- export declare function isReadOnly(element: HTMLElement): boolean;
19
- /**
20
- * Paints `root`'s controls read-only (or live again). Inputs go `disabled` — greyed, skipped
21
- * by the tab order, and deaf even to a scripted `click()` — and writing boxes go `readOnly`,
22
- * which keeps their text selectable and copyable while refusing every edit.
23
- */
24
- export declare function applyReadOnly(root: ParentNode, readOnly: boolean): void;
@@ -1,31 +0,0 @@
1
- /**
2
- * Read-only presentation for a page that can no longer take an answer.
3
- *
4
- * A resolved or canceled page is still opened, read, and saved — the host renders it exactly
5
- * as before and marks it out of reach: `inert` on each response-bearing element (Northlight's
6
- * srcdoc host does this on every `[slot-id]`), and `disabled` on the pager so submit is gone.
7
- * `inert` blocks pointer and keyboard interaction, but it is only a hit-testing rule: the
8
- * controls underneath still LOOK live, and a scripted click still flips a checkbox. So the
9
- * elements take the same signal and put it where a person can see it — every input renders
10
- * disabled and every writing box read-only, which is also what makes the state unreachable
11
- * rather than merely unclickable.
12
- *
13
- * The signal is read from the DOM rather than from a new attribute, because both halves of it
14
- * already exist: `inert` is a standard reflected attribute the host sets, and `disabled` on
15
- * `<crtr-pages>` is the attribute the pager itself observes.
16
- */
17
- /** Whether this element sits on a page that can no longer take an answer. */
18
- export function isReadOnly(element) {
19
- return element.closest('[inert], crtr-pages[disabled]') !== null;
20
- }
21
- /**
22
- * Paints `root`'s controls read-only (or live again). Inputs go `disabled` — greyed, skipped
23
- * by the tab order, and deaf even to a scripted `click()` — and writing boxes go `readOnly`,
24
- * which keeps their text selectable and copyable while refusing every edit.
25
- */
26
- export function applyReadOnly(root, readOnly) {
27
- for (const input of root.querySelectorAll('input'))
28
- input.disabled = readOnly;
29
- for (const area of root.querySelectorAll('textarea'))
30
- area.readOnly = readOnly;
31
- }
@@ -1,2 +0,0 @@
1
- export type CrtrElementName = `crtr-${string}`;
2
- export declare function registerElement(name: CrtrElementName, element: CustomElementConstructor): void;
@@ -1,3 +0,0 @@
1
- export function registerElement(name, element) {
2
- customElements.define(name, element);
3
- }
@@ -1,37 +0,0 @@
1
- /**
2
- * What the page would submit — every response-bearing slot, not only the touched ones.
3
- *
4
- * `respond()` is a user-change channel: an element calls it when the person changes
5
- * something, so a slot nobody touched has never crossed the bridge and the host's map does
6
- * not name it. A final submit must name every response-bearing slot, and crtrd rejects a
7
- * map that does not — correctly, because "this slot has no answer" and "the page forgot to
8
- * mention it" would otherwise be the same thing on the wire.
9
- *
10
- * The answer for an untouched slot is not a guess and it is not a per-kind default anyone
11
- * has to re-derive: it is exactly what that slot is showing right now — a text slot's
12
- * authored text, unedited; a selection nobody made. Each element already builds that object
13
- * for `respond()`. So each one registers its reader here at mount, and the pager reports all
14
- * of them through `respond()` immediately before it submits.
15
- *
16
- * Registration itself writes nothing and asks for no autosave: opening a page and closing it
17
- * again saves exactly what it saved before. The reporting happens at submit, where the
18
- * autosave the reports schedule is flushed by the submit itself.
19
- */
20
- import type { SlotResponse } from './types.js';
21
- /**
22
- * Registers this element as the answer for `slotId`. Call it once at mount, after the slot's
23
- * config has been read and its state hydrated, and only from an element whose slot actually
24
- * bears a response — reporting a response for a display-only slot is a submit the host will
25
- * reject by name. `read` is called at submit time, so it must return the slot's complete
26
- * current response, exactly what `respond()` is handed on a user change.
27
- */
28
- export declare function registerSlotResponse(element: HTMLElement, slotId: string, read: () => SlotResponse): void;
29
- /**
30
- * Hands the host every registered slot's current response, so the map it holds is the whole
31
- * page. Only the pager calls this, and only immediately before `submit()`.
32
- *
33
- * A reader whose element has left the document names a slot that is no longer on screen, and
34
- * a reader that throws has no answer to give; both are dropped rather than reported, which
35
- * leaves the host's map exactly as complete as the page really is.
36
- */
37
- export declare function reportSlotResponses(): void;
@@ -1,56 +0,0 @@
1
- /**
2
- * What the page would submit — every response-bearing slot, not only the touched ones.
3
- *
4
- * `respond()` is a user-change channel: an element calls it when the person changes
5
- * something, so a slot nobody touched has never crossed the bridge and the host's map does
6
- * not name it. A final submit must name every response-bearing slot, and crtrd rejects a
7
- * map that does not — correctly, because "this slot has no answer" and "the page forgot to
8
- * mention it" would otherwise be the same thing on the wire.
9
- *
10
- * The answer for an untouched slot is not a guess and it is not a per-kind default anyone
11
- * has to re-derive: it is exactly what that slot is showing right now — a text slot's
12
- * authored text, unedited; a selection nobody made. Each element already builds that object
13
- * for `respond()`. So each one registers its reader here at mount, and the pager reports all
14
- * of them through `respond()` immediately before it submits.
15
- *
16
- * Registration itself writes nothing and asks for no autosave: opening a page and closing it
17
- * again saves exactly what it saved before. The reporting happens at submit, where the
18
- * autosave the reports schedule is flushed by the submit itself.
19
- */
20
- import { respond } from './host.js';
21
- /** One entry per slot id; a second registration for an id replaces the first. */
22
- const readers = new Map();
23
- /**
24
- * Registers this element as the answer for `slotId`. Call it once at mount, after the slot's
25
- * config has been read and its state hydrated, and only from an element whose slot actually
26
- * bears a response — reporting a response for a display-only slot is a submit the host will
27
- * reject by name. `read` is called at submit time, so it must return the slot's complete
28
- * current response, exactly what `respond()` is handed on a user change.
29
- */
30
- export function registerSlotResponse(element, slotId, read) {
31
- readers.set(slotId, { element, read });
32
- }
33
- /**
34
- * Hands the host every registered slot's current response, so the map it holds is the whole
35
- * page. Only the pager calls this, and only immediately before `submit()`.
36
- *
37
- * A reader whose element has left the document names a slot that is no longer on screen, and
38
- * a reader that throws has no answer to give; both are dropped rather than reported, which
39
- * leaves the host's map exactly as complete as the page really is.
40
- */
41
- export function reportSlotResponses() {
42
- for (const [slotId, reader] of [...readers]) {
43
- if (!reader.element.isConnected) {
44
- readers.delete(slotId);
45
- continue;
46
- }
47
- let response;
48
- try {
49
- response = reader.read();
50
- }
51
- catch {
52
- continue;
53
- }
54
- respond(slotId, response);
55
- }
56
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * Reading a slot's config out of the DOM.
3
- *
4
- * The host renders each slot as
5
- * `<crtr-KIND slot-id="ID"><script type="application/json">CONFIG_JSON</script></crtr-KIND>`,
6
- * and every element does the same three things in `connectedCallback`: find that script child,
7
- * parse it, and render a named error state instead of throwing when it is missing or malformed.
8
- * That is one behaviour, so it lives here once.
9
- *
10
- * **What is and is not checked.** The JSON's *shape* was already validated by
11
- * `validatePageManifest` before the manifest was stored, and the renderer emits from that
12
- * validated manifest — so an element may trust the parsed object against its own config type.
13
- * What is not guaranteed is that the script child is there at all and that its text parses: a
14
- * page can be hand-written, truncated, or rendered by something else. Those two failures are
15
- * what this module reports.
16
- */
17
- /** A parsed config, or the reason the element should render an error state instead. */
18
- export type SlotConfigResult<T> = {
19
- status: 'ok';
20
- config: T;
21
- } | {
22
- status: 'invalid';
23
- reason: string;
24
- };
25
- /**
26
- * Reads and parses the JSON script child of `element`.
27
- *
28
- * `T` is the element's own mirrored config type and is asserted, not verified — see the note
29
- * above on why that is sound. Never throws.
30
- */
31
- export declare function readSlotConfig<T = Record<string, unknown>>(element: HTMLElement): SlotConfigResult<T>;
32
- /**
33
- * The slot id the host addressed this element by — the key `respond()` takes. Absent on a
34
- * display-only slot, which has no id and produces no response.
35
- */
36
- export declare function readSlotId(element: HTMLElement): string | undefined;
@@ -1,50 +0,0 @@
1
- /**
2
- * Reading a slot's config out of the DOM.
3
- *
4
- * The host renders each slot as
5
- * `<crtr-KIND slot-id="ID"><script type="application/json">CONFIG_JSON</script></crtr-KIND>`,
6
- * and every element does the same three things in `connectedCallback`: find that script child,
7
- * parse it, and render a named error state instead of throwing when it is missing or malformed.
8
- * That is one behaviour, so it lives here once.
9
- *
10
- * **What is and is not checked.** The JSON's *shape* was already validated by
11
- * `validatePageManifest` before the manifest was stored, and the renderer emits from that
12
- * validated manifest — so an element may trust the parsed object against its own config type.
13
- * What is not guaranteed is that the script child is there at all and that its text parses: a
14
- * page can be hand-written, truncated, or rendered by something else. Those two failures are
15
- * what this module reports.
16
- */
17
- /**
18
- * Reads and parses the JSON script child of `element`.
19
- *
20
- * `T` is the element's own mirrored config type and is asserted, not verified — see the note
21
- * above on why that is sound. Never throws.
22
- */
23
- export function readSlotConfig(element) {
24
- const script = element.querySelector('script[type="application/json"]');
25
- if (script === null)
26
- return { status: 'invalid', reason: 'slot has no application/json config' };
27
- const text = script.textContent ?? '';
28
- if (text.trim() === '')
29
- return { status: 'invalid', reason: 'slot config is empty' };
30
- let parsed;
31
- try {
32
- parsed = JSON.parse(text);
33
- }
34
- catch (error) {
35
- const detail = error instanceof Error && error.message !== '' ? error.message : 'invalid JSON';
36
- return { status: 'invalid', reason: `slot config is not valid JSON: ${detail}` };
37
- }
38
- if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
39
- return { status: 'invalid', reason: 'slot config must be a JSON object' };
40
- }
41
- return { status: 'ok', config: parsed };
42
- }
43
- /**
44
- * The slot id the host addressed this element by — the key `respond()` takes. Absent on a
45
- * display-only slot, which has no id and produces no response.
46
- */
47
- export function readSlotId(element) {
48
- const id = element.getAttribute('slot-id')?.trim();
49
- return id === undefined || id === '' ? undefined : id;
50
- }
@@ -1,98 +0,0 @@
1
- /**
2
- * The response contract the page bundle produces, as plain browser-safe types.
3
- *
4
- * These mirror `src/core/human/page-schema.ts` field-for-field — `commentSchema`,
5
- * `commentAnchorSchema`, and the four `*ResponseSchema`s — and are deliberately a
6
- * separate declaration rather than an import: nothing under `src/pages/` may reach
7
- * a runtime package (zod) or a module outside this directory, because the bundle is
8
- * a browser IIFE. The schemas remain the source of truth; a change there is a change
9
- * that must land here in the same commit.
10
- *
11
- * Two rules the shapes are built around:
12
- *
13
- * 1. **One comment shape everywhere.** Every response-bearing element carries
14
- * comments, and every comment is `{ id, anchor, text }`. A comment on an option,
15
- * a table row, a card, or a range of prose differs only in its `anchor`.
16
- * 2. **Selection is ids, never indexes or values.** The agent authored the ids it is
17
- * asking about, so the response keys straight off them.
18
- *
19
- * Config types are NOT here: a config is one element's private input, mirrored in that
20
- * element's own module. A response is what crosses `window.crtr.respond`, so it is
21
- * shared.
22
- */
23
- /** What a comment is attached to. One union across every element. */
24
- export type CommentAnchor =
25
- /** The presented content as a whole. */
26
- {
27
- kind: 'whole';
28
- }
29
- /** One option of an `options` element. */
30
- | {
31
- kind: 'option';
32
- optionId: string;
33
- }
34
- /** One row of a `table`. */
35
- | {
36
- kind: 'row';
37
- rowId: string;
38
- }
39
- /** One column of a `table`. */
40
- | {
41
- kind: 'column';
42
- columnId: string;
43
- }
44
- /** One card of a `cards` grid. */
45
- | {
46
- kind: 'card';
47
- cardId: string;
48
- }
49
- /**
50
- * A character range of a `text` element's final text, review-style. `quote` is the
51
- * text as it read when the comment was left, so the comment survives (readably) an
52
- * edit that moves the offsets.
53
- */
54
- | {
55
- kind: 'range';
56
- start: number;
57
- end: number;
58
- quote: string;
59
- };
60
- /** A user comment. The same shape in every element's response. */
61
- export type Comment = {
62
- /** Stable per comment; frame-local, minted by `newCommentId()`. */
63
- id: string;
64
- anchor: CommentAnchor;
65
- text: string;
66
- };
67
- /** `options` — single or multi select, per-option comments, optional freetext. */
68
- export type OptionsResponse = {
69
- /** Always an array; a single-select answer is a one-element array. */
70
- selectedOptionIds: string[];
71
- comments: Comment[];
72
- /** Present only when the config allows freetext and the user typed something. */
73
- freetext?: string;
74
- };
75
- /** `text` — an edited draft and/or anchored comments on presented prose. */
76
- export type TextResponse = {
77
- /** The text as the user is leaving it. */
78
- text: string;
79
- /** True once `text` differs from what the agent presented. */
80
- edited: boolean;
81
- comments: Comment[];
82
- };
83
- /** `table` — row and/or column selection with anchored comments. */
84
- export type TableResponse = {
85
- selectedRowIds: string[];
86
- selectedColumnIds: string[];
87
- comments: Comment[];
88
- };
89
- /** `cards` — card selection with per-card comments. */
90
- export type CardsResponse = {
91
- selectedCardIds: string[];
92
- comments: Comment[];
93
- };
94
- /**
95
- * Any slot response. The open member covers a product-registered `unvalidated` slot,
96
- * whose shape only the product renderer knows.
97
- */
98
- export type SlotResponse = OptionsResponse | TextResponse | TableResponse | CardsResponse | Record<string, unknown>;