@xemahq/ui-kernel 0.11.1 → 0.12.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 (257) hide show
  1. package/dist/errors/http-error-status.d.ts +17 -0
  2. package/dist/errors/http-error-status.d.ts.map +1 -0
  3. package/dist/errors/http-error-status.js +59 -0
  4. package/dist/errors/http-error-status.js.map +1 -0
  5. package/dist/errors/index.d.ts +2 -0
  6. package/dist/errors/index.d.ts.map +1 -0
  7. package/dist/errors/index.js +2 -0
  8. package/dist/errors/index.js.map +1 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/lib/biome-host/errors.d.ts.map +1 -1
  14. package/dist/lib/biome-host/errors.js +1 -19
  15. package/dist/lib/biome-host/errors.js.map +1 -1
  16. package/dist/offline/index.d.ts.map +1 -1
  17. package/dist/offline/index.js.map +1 -1
  18. package/dist/offline/online-controller.d.ts.map +1 -1
  19. package/dist/offline/online-controller.js +6 -1
  20. package/dist/offline/online-controller.js.map +1 -1
  21. package/dist/offline/outbox.d.ts.map +1 -1
  22. package/dist/offline/outbox.js +2 -24
  23. package/dist/offline/outbox.js.map +1 -1
  24. package/package.json +1 -2
  25. package/src/index.ts +0 -17
  26. package/src/lib/biome-host/agent-validation.ts +0 -239
  27. package/src/lib/biome-host/biome-builders.ts +0 -112
  28. package/src/lib/biome-host/biome-mode.ts +0 -6
  29. package/src/lib/biome-host/biome-navigation.ts +0 -37
  30. package/src/lib/biome-host/biome-registry.ts +0 -299
  31. package/src/lib/biome-host/biome-scope-hooks.ts +0 -41
  32. package/src/lib/biome-host/biome-scope.tsx +0 -52
  33. package/src/lib/biome-host/biome-scoped-query.ts +0 -134
  34. package/src/lib/biome-host/create-biome-orval-config.ts +0 -82
  35. package/src/lib/biome-host/define-web-biome.spec.ts +0 -221
  36. package/src/lib/biome-host/define-web-biome.ts +0 -222
  37. package/src/lib/biome-host/errors.ts +0 -220
  38. package/src/lib/biome-host/frontend-biome.ts +0 -256
  39. package/src/lib/biome-host/host-bridge.ts +0 -281
  40. package/src/lib/biome-host/host-sources.ts +0 -54
  41. package/src/lib/biome-host/i18n-hooks.ts +0 -51
  42. package/src/lib/biome-host/i18n-port.test.ts +0 -50
  43. package/src/lib/biome-host/i18n-port.ts +0 -96
  44. package/src/lib/biome-host/index.ts +0 -35
  45. package/src/lib/biome-host/realtime-hooks.ts +0 -75
  46. package/src/lib/biome-host/realtime-port.ts +0 -115
  47. package/src/lib/biome-host/session-contributions.ts +0 -296
  48. package/src/lib/biome-host/use-mutation-with-error-toast.ts +0 -90
  49. package/src/lib/biome-host/use-page-state.ts +0 -248
  50. package/src/lib/capabilities/capability-context.ts +0 -25
  51. package/src/lib/capabilities/capability-provider.tsx +0 -73
  52. package/src/lib/capabilities/index.ts +0 -17
  53. package/src/lib/capabilities/types.ts +0 -69
  54. package/src/lib/capabilities/use-capability.ts +0 -79
  55. package/src/lib/contribution-registry/contribution-registry.spec.ts +0 -141
  56. package/src/lib/contribution-registry/contribution-registry.ts +0 -204
  57. package/src/lib/contribution-registry/index.ts +0 -9
  58. package/src/lib/contribution-registry/renderable-registry.ts +0 -142
  59. package/src/lib/system-bus/capability-invoke.ts +0 -92
  60. package/src/lib/system-bus/deeplink.ts +0 -210
  61. package/src/lib/system-bus/enums.ts +0 -86
  62. package/src/lib/system-bus/host-ports.ts +0 -93
  63. package/src/lib/system-bus/index.ts +0 -16
  64. package/src/lib/system-bus/intent-registry.ts +0 -109
  65. package/src/lib/system-bus/intents.ts +0 -113
  66. package/src/lib/system-bus/palette.ts +0 -78
  67. package/src/lib/system-bus/system-bus-builder.ts +0 -159
  68. package/src/lib/system-bus/system-bus.ts +0 -37
  69. package/src/lib/system-bus/windows.ts +0 -51
  70. package/src/offline/id.ts +0 -16
  71. package/src/offline/index.ts +0 -54
  72. package/src/offline/mutation.ts +0 -75
  73. package/src/offline/offline-status-badge.tsx +0 -51
  74. package/src/offline/online-controller.ts +0 -105
  75. package/src/offline/outbox.test.ts +0 -172
  76. package/src/offline/outbox.ts +0 -348
  77. package/src/offline/react-hooks.ts +0 -40
  78. package/src/offline/react.tsx +0 -32
  79. package/src/offline/storage.ts +0 -112
  80. package/src/offline/types.ts +0 -77
  81. package/src/org-db/components/DbResultTable.tsx +0 -176
  82. package/src/org-db/index.ts +0 -1
  83. package/src/pdf/index.ts +0 -11
  84. package/src/registry/index.ts +0 -9
  85. package/src/registry/lib/agent-validation-host.ts +0 -36
  86. package/src/registry/lib/biome-slot.tsx +0 -50
  87. package/src/registry/lib/biomes-enabled-context.ts +0 -20
  88. package/src/registry/lib/extension-points.ts +0 -134
  89. package/src/registry/lib/primitives/SessionEventCard.tsx +0 -164
  90. package/src/registry/lib/primitives/SessionEventTimeline.tsx +0 -95
  91. package/src/registry/lib/primitives/SessionMutationBar.tsx +0 -76
  92. package/src/registry/lib/primitives/SessionTabbedDrawer.tsx +0 -165
  93. package/src/registry/lib/primitives/index.ts +0 -18
  94. package/src/registry/lib/session-context-builder.ts +0 -84
  95. package/src/registry/lib/session-context-provider.tsx +0 -33
  96. package/src/registry/lib/session-context.ts +0 -21
  97. package/src/registry/lib/session-selectors.ts +0 -272
  98. package/src/session/comments/CommentRail.tsx +0 -164
  99. package/src/session/index.ts +0 -3
  100. package/src/session/lib/cn.ts +0 -11
  101. package/src/session/shell/SessionWorkspaceShell.tsx +0 -147
  102. package/src/session-kit/approvals/ApprovalButton.tsx +0 -89
  103. package/src/session-kit/approvals/ApprovalCard.tsx +0 -341
  104. package/src/session-kit/approvals/ApprovalsCenter.tsx +0 -336
  105. package/src/session-kit/approvals/CapabilityApprovalStickyBar.tsx +0 -118
  106. package/src/session-kit/approvals/Obligation.tsx +0 -111
  107. package/src/session-kit/approvals/ScopedBody.tsx +0 -392
  108. package/src/session-kit/approvals/approval-icons.ts +0 -31
  109. package/src/session-kit/approvals/approval-model.ts +0 -204
  110. package/src/session-kit/approvals/index.ts +0 -22
  111. package/src/session-kit/approvals/obligation-display.ts +0 -100
  112. package/src/session-kit/approvals/risk-accent.ts +0 -47
  113. package/src/session-kit/approvals/scope-icons.ts +0 -19
  114. package/src/session-kit/combobox/Combobox.tsx +0 -358
  115. package/src/session-kit/combobox/use-click-outside.ts +0 -21
  116. package/src/session-kit/display/ContextHeader.tsx +0 -148
  117. package/src/session-kit/display/FileDiffCard.tsx +0 -140
  118. package/src/session-kit/display/MD.tsx +0 -162
  119. package/src/session-kit/display/MessageTurn.tsx +0 -157
  120. package/src/session-kit/display/ThinkingPanel.tsx +0 -81
  121. package/src/session-kit/display/TodoChecklist.tsx +0 -120
  122. package/src/session-kit/display/TokenMeter.tsx +0 -89
  123. package/src/session-kit/display/ToolStrip.tsx +0 -278
  124. package/src/session-kit/display/TypingDots.tsx +0 -24
  125. package/src/session-kit/index.ts +0 -44
  126. package/src/session-kit/lib/enums.ts +0 -66
  127. package/src/session-kit/lib/portal-accent.ts +0 -30
  128. package/src/session-kit/lib/status-dot.ts +0 -68
  129. package/src/session-kit/primitives/Avatar.tsx +0 -44
  130. package/src/session-kit/primitives/PortalGlyph.tsx +0 -51
  131. package/src/session-kit/primitives/RiskPill.tsx +0 -95
  132. package/src/session-kit/primitives/ScopeDot.tsx +0 -47
  133. package/src/session-kit/primitives/Segmented.tsx +0 -71
  134. package/src/ui/branding/app-branding-context.ts +0 -20
  135. package/src/ui/branding/app-branding-provider.tsx +0 -123
  136. package/src/ui/branding/sanitize.ts +0 -89
  137. package/src/ui/breakpoints.ts +0 -14
  138. package/src/ui/capture/document-preview.tsx +0 -166
  139. package/src/ui/capture/field-spec-to-zod.test.ts +0 -81
  140. package/src/ui/capture/field-spec-to-zod.ts +0 -174
  141. package/src/ui/capture/field-spec-validate.ts +0 -236
  142. package/src/ui/capture/field-spec.test.ts +0 -49
  143. package/src/ui/capture/field-spec.ts +0 -274
  144. package/src/ui/capture/index.ts +0 -51
  145. package/src/ui/capture/schema-field-input.tsx +0 -620
  146. package/src/ui/capture/schema-form.tsx +0 -149
  147. package/src/ui/capture/submit-values.test.ts +0 -70
  148. package/src/ui/capture/submit-values.ts +0 -63
  149. package/src/ui/capture/use-prefill.ts +0 -186
  150. package/src/ui/capture/use-schema-validation.ts +0 -145
  151. package/src/ui/capture/use-wizard.ts +0 -180
  152. package/src/ui/capture/value-format.ts +0 -32
  153. package/src/ui/capture/wizard.tsx +0 -105
  154. package/src/ui/charts/bar-chart.tsx +0 -139
  155. package/src/ui/charts/chart-frame.tsx +0 -125
  156. package/src/ui/charts/chart-types.ts +0 -52
  157. package/src/ui/charts/chart-utils.ts +0 -190
  158. package/src/ui/charts/charts.test.tsx +0 -204
  159. package/src/ui/charts/donut-chart.tsx +0 -129
  160. package/src/ui/charts/index.ts +0 -27
  161. package/src/ui/charts/line-chart.tsx +0 -202
  162. package/src/ui/charts/sparkline.tsx +0 -109
  163. package/src/ui/chrome/AsyncBoundary.tsx +0 -74
  164. package/src/ui/chrome/EmptyState.tsx +0 -257
  165. package/src/ui/chrome/ErrorCard.tsx +0 -63
  166. package/src/ui/chrome/LoadingState.tsx +0 -61
  167. package/src/ui/chrome/PageHeader.tsx +0 -137
  168. package/src/ui/chrome/RecordCardList.tsx +0 -98
  169. package/src/ui/chrome/StateCard.tsx +0 -150
  170. package/src/ui/chrome/confirm-delete-dialog.tsx +0 -59
  171. package/src/ui/chrome/page-shell.spec.tsx +0 -117
  172. package/src/ui/chrome/page-shell.tsx +0 -221
  173. package/src/ui/chrome/scope-badge.tsx +0 -40
  174. package/src/ui/chrome/status-badge.tsx +0 -79
  175. package/src/ui/cn.ts +0 -32
  176. package/src/ui/design-tokens.ts +0 -372
  177. package/src/ui/hooks/use-debounced-value.ts +0 -16
  178. package/src/ui/hooks/use-is-mobile.ts +0 -28
  179. package/src/ui/index.ts +0 -110
  180. package/src/ui/pdf/pdf-preview.tsx +0 -122
  181. package/src/ui/primitives/alert-dialog.tsx +0 -104
  182. package/src/ui/primitives/async-combobox.tsx +0 -182
  183. package/src/ui/primitives/badge-variants.ts +0 -21
  184. package/src/ui/primitives/badge.tsx +0 -25
  185. package/src/ui/primitives/button-variants.ts +0 -31
  186. package/src/ui/primitives/button.tsx +0 -29
  187. package/src/ui/primitives/card.tsx +0 -43
  188. package/src/ui/primitives/checkbox.tsx +0 -26
  189. package/src/ui/primitives/collapsible.tsx +0 -9
  190. package/src/ui/primitives/dialog.tsx +0 -103
  191. package/src/ui/primitives/dropdown-menu.tsx +0 -179
  192. package/src/ui/primitives/form-stepper.tsx +0 -94
  193. package/src/ui/primitives/form-stepper.types.ts +0 -15
  194. package/src/ui/primitives/input.tsx +0 -22
  195. package/src/ui/primitives/label.tsx +0 -17
  196. package/src/ui/primitives/overflow-tabs.tsx +0 -331
  197. package/src/ui/primitives/popover.tsx +0 -33
  198. package/src/ui/primitives/preview-device-frame.tsx +0 -213
  199. package/src/ui/primitives/radio-group.tsx +0 -36
  200. package/src/ui/primitives/resizable.tsx +0 -67
  201. package/src/ui/primitives/scroll-area.tsx +0 -38
  202. package/src/ui/primitives/select.tsx +0 -143
  203. package/src/ui/primitives/separator.tsx +0 -20
  204. package/src/ui/primitives/sheet.tsx +0 -107
  205. package/src/ui/primitives/skeleton.tsx +0 -99
  206. package/src/ui/primitives/switch.tsx +0 -27
  207. package/src/ui/primitives/table.tsx +0 -72
  208. package/src/ui/primitives/tabs.tsx +0 -53
  209. package/src/ui/primitives/tag-multi-select.tsx +0 -261
  210. package/src/ui/primitives/textarea.tsx +0 -21
  211. package/src/ui/primitives/tooltip.tsx +0 -30
  212. package/src/ui/primitives/url-preview-chrome.tsx +0 -103
  213. package/src/vista/GenericCatalogueSurface.tsx +0 -179
  214. package/src/vista/SurfaceFallbackCard.tsx +0 -109
  215. package/src/vista/VistaPanel.tsx +0 -163
  216. package/src/vista/form-payload.spec.ts +0 -139
  217. package/src/vista/html/CustomUiFrame.spec.tsx +0 -127
  218. package/src/vista/html/CustomUiFrame.tsx +0 -206
  219. package/src/vista/html/custom-ui-frame-bridge.spec.ts +0 -191
  220. package/src/vista/html/custom-ui-frame-bridge.ts +0 -98
  221. package/src/vista/html/custom-ui-frame-contract.ts +0 -88
  222. package/src/vista/html/custom-ui-intents.spec.ts +0 -135
  223. package/src/vista/html/custom-ui-intents.ts +0 -155
  224. package/src/vista/html/custom-ui-srcdoc.spec.ts +0 -151
  225. package/src/vista/html/custom-ui-srcdoc.ts +0 -193
  226. package/src/vista/html/index.ts +0 -13
  227. package/src/vista/index.ts +0 -52
  228. package/src/vista/surface-catalogue.spec.ts +0 -140
  229. package/src/vista/surface-catalogue.ts +0 -90
  230. package/src/vista/surface-icons.ts +0 -57
  231. package/src/vista/surface-registry.ts +0 -56
  232. package/src/vista/surfaces/ChartSurface.tsx +0 -34
  233. package/src/vista/surfaces/FilesSurface.tsx +0 -202
  234. package/src/vista/surfaces/FormSurface.tsx +0 -380
  235. package/src/vista/surfaces/HtmlSurface.tsx +0 -43
  236. package/src/vista/surfaces/TableSurface.tsx +0 -100
  237. package/src/vista/surfaces/UrlSurface.tsx +0 -40
  238. package/src/vista/surfaces/blob-surfaces.tsx +0 -139
  239. package/src/vista/surfaces/elicitation-transport.spec.ts +0 -369
  240. package/src/vista/surfaces/elicitation-transport.ts +0 -367
  241. package/src/vista/surfaces/file-surface-utils.ts +0 -69
  242. package/src/vista/surfaces/index.ts +0 -24
  243. package/src/vista/surfaces/register-surfaces.tsx +0 -139
  244. package/src/vista/surfaces/text-surfaces.tsx +0 -132
  245. package/src/vista/use-vista-tabs.ts +0 -196
  246. package/src/vista/vista-code-renderer-context.ts +0 -16
  247. package/src/vista/vista-code-renderer.tsx +0 -35
  248. package/src/vista/vista-file-context.ts +0 -14
  249. package/src/vista/vista-file-source.tsx +0 -141
  250. package/src/vista/vista-form-context.ts +0 -20
  251. package/src/vista/vista-form-host.tsx +0 -48
  252. package/src/vista/vista-model.ts +0 -137
  253. package/src/vista/vista-open-context.tsx +0 -27
  254. package/src/vista/vista-open-state.ts +0 -11
  255. package/src/vista/vista-payloads.ts +0 -635
  256. package/src/vista/vista-tabs-manifest.ts +0 -138
  257. package/src/vista/vista-tools.ts +0 -232
@@ -1,204 +0,0 @@
1
- /**
2
- * `createContributionRegistry` — the ONE two-layer closed+open registry core
3
- * the Xema frontend uses everywhere a biome may contribute into a set the
4
- * platform also ships a closed first-party version of.
5
- *
6
- * Before this module the exact same bookkeeping was hand-written four times
7
- * (in-chat widgets, biome output renderers, open reply variants, and — next —
8
- * Vista surfaces), each with slightly different guards. This is that core,
9
- * extracted once (reuse register U1).
10
- *
11
- * ── The two layers ──────────────────────────────────────────────────────────
12
- * • a CLOSED first-party set, registered at module load and keyed by a
13
- * platform enum value;
14
- * • an OPEN biome set, registered at runtime (a biome registers from its
15
- * `FrontendBiome.init()` hook) and keyed by a namespaced `<biomeId>:<kind>`
16
- * slug.
17
- *
18
- * ── The invariants (all fail-loud, none silent) ─────────────────────────────
19
- * • RESERVED KINDS. Every first-party kind is reserved: `register()` throws
20
- * if a biome tries to claim one. The open set can never shadow the closed
21
- * one.
22
- * • DUPLICATE GUARD. Registering the EXACT same entry object twice is a
23
- * no-op (this is what tolerates React Fast Refresh / a double-invoked
24
- * `init()`); registering a DIFFERENT entry for a kind that is already
25
- * taken is an error — two biomes cannot silently shadow each other.
26
- * • The one exception is {@link DuplicateContributionPolicy.FirstWins}, for
27
- * registries rebuilt on a hot path where a throw would crash a render
28
- * (the biome output-renderer overlay). It is NOT a silent fallback: an
29
- * `onDuplicate` reporter is REQUIRED, and the registry factory throws at
30
- * construction if it is missing.
31
- *
32
- * Resolution itself lives in the caller (or in `renderable-registry.ts` for the
33
- * versioned + payload-validated flavour) and NEVER throws.
34
- */
35
-
36
- /** What to do when a DIFFERENT entry is registered for an already-taken kind. */
37
- export enum DuplicateContributionPolicy {
38
- /**
39
- * Throw. The default, and correct for every registry whose registrations
40
- * happen once at module load or once per biome `init()`.
41
- */
42
- Throw = 'throw',
43
- /**
44
- * Keep the first registration and report the loser through `onDuplicate`.
45
- * For registries REBUILT on a hot path (e.g. per render) where throwing
46
- * would take down the UI. Requires `onDuplicate` — there is no silent mode.
47
- */
48
- FirstWins = 'first-wins',
49
- }
50
-
51
- /** Options for {@link createContributionRegistry}. */
52
- export interface ContributionRegistryOptions<TEntry> {
53
- /** Registry name, used verbatim in every thrown message. */
54
- readonly name: string;
55
- /**
56
- * The CLOSED first-party kinds. Reserved: `register()` refuses them so a
57
- * biome can never shadow a platform kind. Typically `Object.values(SomeEnum)`.
58
- */
59
- readonly reservedKinds?: Iterable<string>;
60
- /** Duplicate handling. Defaults to {@link DuplicateContributionPolicy.Throw}. */
61
- readonly duplicatePolicy?: DuplicateContributionPolicy;
62
- /**
63
- * Reporter for a rejected duplicate under
64
- * {@link DuplicateContributionPolicy.FirstWins}. REQUIRED under that policy.
65
- */
66
- readonly onDuplicate?: (
67
- kind: string,
68
- existing: TEntry,
69
- rejected: TEntry,
70
- ) => void;
71
- }
72
-
73
- /** The two-layer registry surface. */
74
- export interface ContributionRegistry<TEntry> {
75
- /** Registry name (diagnostics). */
76
- readonly name: string;
77
- /**
78
- * Register a FIRST-PARTY entry for a closed platform kind. Called once per
79
- * kind at module load.
80
- */
81
- registerFirstParty(kind: string, entry: TEntry): void;
82
- /**
83
- * OPEN seam: register a biome entry under its namespaced `<biomeId>:<kind>`
84
- * slug. Throws when the slug is a reserved first-party kind.
85
- */
86
- register(kind: string, entry: TEntry): void;
87
- /** True when SOME entry (first-party or biome) is registered for the kind. */
88
- has(kind: string): boolean;
89
- /** The entry for a kind — first-party wins — or `undefined`. */
90
- get(kind: string): TEntry | undefined;
91
- /** True when the kind belongs to the closed first-party set. */
92
- isReserved(kind: string): boolean;
93
- /** Every registered kind (sorted) — diagnostics + tests. */
94
- list(): readonly string[];
95
- /** Only the OPEN (biome-contributed) kinds (sorted). */
96
- listOpen(): readonly string[];
97
- /** Flattened `kind -> entry` view, first-party wins. Diagnostics + overlays. */
98
- entries(): ReadonlyMap<string, TEntry>;
99
- /** Test-only: clear the OPEN set (the first-party set stays). */
100
- __resetOpenForTests(): void;
101
- }
102
-
103
- export function createContributionRegistry<TEntry>(
104
- options: ContributionRegistryOptions<TEntry>,
105
- ): ContributionRegistry<TEntry> {
106
- const {
107
- name,
108
- reservedKinds,
109
- duplicatePolicy = DuplicateContributionPolicy.Throw,
110
- onDuplicate,
111
- } = options;
112
-
113
- if (
114
- duplicatePolicy === DuplicateContributionPolicy.FirstWins &&
115
- onDuplicate === undefined
116
- ) {
117
- throw new Error(
118
- `${name} registry: DuplicateContributionPolicy.FirstWins requires an ` +
119
- `'onDuplicate' reporter — a dropped contribution must never be silent.`,
120
- );
121
- }
122
-
123
- const reserved = new Set<string>(reservedKinds ?? []);
124
- const firstParty = new Map<string, TEntry>();
125
- const open = new Map<string, TEntry>();
126
-
127
- /**
128
- * Idempotent for the IDENTICAL entry (Fast Refresh / double-invoked
129
- * `init()`); an error for a DIFFERENT one. Returns whether the entry landed.
130
- */
131
- function put(target: Map<string, TEntry>, kind: string, entry: TEntry): void {
132
- const existing = target.get(kind);
133
- if (existing === undefined) {
134
- target.set(kind, entry);
135
- return;
136
- }
137
- if (existing === entry) {
138
- return;
139
- }
140
- if (duplicatePolicy === DuplicateContributionPolicy.FirstWins) {
141
- // `onDuplicate` is guaranteed present under this policy (checked above).
142
- (onDuplicate as (k: string, e: TEntry, r: TEntry) => void)(
143
- kind,
144
- existing,
145
- entry,
146
- );
147
- return;
148
- }
149
- throw new Error(
150
- `${name} registry: a DIFFERENT entry is already registered for kind ` +
151
- `'${kind}'. Two contributors cannot claim the same slug.`,
152
- );
153
- }
154
-
155
- return {
156
- name,
157
-
158
- registerFirstParty(kind: string, entry: TEntry): void {
159
- put(firstParty, kind, entry);
160
- },
161
-
162
- register(kind: string, entry: TEntry): void {
163
- if (reserved.has(kind)) {
164
- throw new Error(
165
- `${name} registry: '${kind}' is a reserved first-party kind and ` +
166
- `cannot be overridden by a biome. Use a namespaced ` +
167
- `'<biomeId>:${kind}' slug.`,
168
- );
169
- }
170
- put(open, kind, entry);
171
- },
172
-
173
- has(kind: string): boolean {
174
- return firstParty.has(kind) || open.has(kind);
175
- },
176
-
177
- get(kind: string): TEntry | undefined {
178
- return firstParty.get(kind) ?? open.get(kind);
179
- },
180
-
181
- isReserved(kind: string): boolean {
182
- return reserved.has(kind);
183
- },
184
-
185
- list(): readonly string[] {
186
- return [...firstParty.keys(), ...open.keys()].sort();
187
- },
188
-
189
- listOpen(): readonly string[] {
190
- return [...open.keys()].sort();
191
- },
192
-
193
- entries(): ReadonlyMap<string, TEntry> {
194
- // First-party last so it wins on a key present in both (which `register`
195
- // already forbids for reserved kinds, but `entries()` must not depend on
196
- // that to be correct).
197
- return new Map<string, TEntry>([...open, ...firstParty]);
198
- },
199
-
200
- __resetOpenForTests(): void {
201
- open.clear();
202
- },
203
- };
204
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * The shared two-layer (closed first-party + open biome) contribution registry
3
- * core, and its versioned/validated renderable flavour.
4
- *
5
- * One implementation, four consumers: in-chat ChatWidgets, biome output
6
- * renderers, open reply variants, and Vista surfaces.
7
- */
8
- export * from './contribution-registry';
9
- export * from './renderable-registry';
@@ -1,142 +0,0 @@
1
- /**
2
- * The RENDERABLE flavour of {@link createContributionRegistry}: a two-layer
3
- * closed+open registry whose entries are versioned renderers with a narrowing
4
- * payload validator, plus the fail-safe resolution every such plane needs.
5
- *
6
- * This is the shape the in-chat ChatWidget plane and the Vista render plane
7
- * both want: an envelope `{ kind, version, payload }` arrives from an agent,
8
- * and the frontend must turn it into something drawable WITHOUT ever throwing
9
- * and WITHOUT ever silently drawing a coerced half-widget. Resolution returns a
10
- * typed reason instead, which the caller renders as a safe fallback card.
11
- */
12
- import {
13
- createContributionRegistry,
14
- type ContributionRegistry,
15
- type ContributionRegistryOptions,
16
- } from './contribution-registry';
17
-
18
- /**
19
- * Why an envelope fell back to the safe card. Populated on the resolution so
20
- * the Studio debugger (and dev logs) can see WHY — mirrors the Model Resolution
21
- * Matrix's `ResolvedModelDecision`. Closed set.
22
- */
23
- export enum ContributionFallbackReason {
24
- UnknownKind = 'unknown-kind',
25
- InvalidPayload = 'invalid-payload',
26
- UnsupportedVersion = 'unsupported-version',
27
- }
28
-
29
- /** The minimum an agent-emitted envelope must carry to be resolvable. */
30
- export interface ContributionEnvelope {
31
- readonly kind: string;
32
- readonly version: number;
33
- readonly payload: unknown;
34
- }
35
-
36
- /**
37
- * A versioned renderer. `validate` narrows the wire payload to the renderer's
38
- * own type (returning `null` routes to the fallback with `InvalidPayload`) and
39
- * MUST NOT throw; `render` draws from the narrowed payload.
40
- */
41
- export interface RenderableContributionEntry<TRendered, TPayload = unknown> {
42
- /** Highest schema version this renderer supports. */
43
- readonly version: number;
44
- /** Narrowing validator. Returns the typed payload, or `null`. MUST NOT throw. */
45
- validate(payload: unknown): TPayload | null;
46
- /** Draw from the narrowed payload. */
47
- render(payload: TPayload): TRendered;
48
- }
49
-
50
- /** The outcome of resolving an envelope — inspectable for the Studio debugger. */
51
- export type RenderableResolution<TRendered> =
52
- | {
53
- readonly matched: true;
54
- readonly kind: string;
55
- readonly version: number;
56
- readonly rendered: TRendered;
57
- }
58
- | {
59
- readonly matched: false;
60
- readonly kind: string;
61
- readonly reason: ContributionFallbackReason;
62
- };
63
-
64
- /** A {@link ContributionRegistry} of versioned renderers, plus `resolve`. */
65
- export interface RenderableContributionRegistry<TRendered>
66
- extends Omit<
67
- ContributionRegistry<RenderableContributionEntry<TRendered>>,
68
- 'registerFirstParty' | 'register'
69
- > {
70
- registerFirstParty<TPayload>(
71
- kind: string,
72
- entry: RenderableContributionEntry<TRendered, TPayload>,
73
- ): void;
74
- register<TPayload>(
75
- kind: string,
76
- entry: RenderableContributionEntry<TRendered, TPayload>,
77
- ): void;
78
- /**
79
- * Resolve an envelope. Pure + deterministic so it can run in render, and it
80
- * NEVER throws — an unknown kind, a payload the entry rejects, or a `version`
81
- * newer than the entry supports ALL yield `matched: false` with a typed
82
- * reason the caller renders as the safe fallback card.
83
- */
84
- resolve(envelope: ContributionEnvelope): RenderableResolution<TRendered>;
85
- }
86
-
87
- export function createRenderableContributionRegistry<TRendered>(
88
- options: ContributionRegistryOptions<RenderableContributionEntry<TRendered>>,
89
- ): RenderableContributionRegistry<TRendered> {
90
- const registry =
91
- createContributionRegistry<RenderableContributionEntry<TRendered>>(options);
92
-
93
- return {
94
- ...registry,
95
-
96
- registerFirstParty<TPayload>(
97
- kind: string,
98
- entry: RenderableContributionEntry<TRendered, TPayload>,
99
- ): void {
100
- registry.registerFirstParty(kind, entry);
101
- },
102
-
103
- register<TPayload>(
104
- kind: string,
105
- entry: RenderableContributionEntry<TRendered, TPayload>,
106
- ): void {
107
- registry.register(kind, entry);
108
- },
109
-
110
- resolve(envelope: ContributionEnvelope): RenderableResolution<TRendered> {
111
- const entry = registry.get(envelope.kind);
112
- if (entry === undefined) {
113
- return {
114
- matched: false,
115
- kind: envelope.kind,
116
- reason: ContributionFallbackReason.UnknownKind,
117
- };
118
- }
119
- if (envelope.version > entry.version) {
120
- return {
121
- matched: false,
122
- kind: envelope.kind,
123
- reason: ContributionFallbackReason.UnsupportedVersion,
124
- };
125
- }
126
- const narrowed = entry.validate(envelope.payload);
127
- if (narrowed === null) {
128
- return {
129
- matched: false,
130
- kind: envelope.kind,
131
- reason: ContributionFallbackReason.InvalidPayload,
132
- };
133
- }
134
- return {
135
- matched: true,
136
- kind: envelope.kind,
137
- version: entry.version,
138
- rendered: entry.render(narrowed),
139
- };
140
- },
141
- };
142
- }
@@ -1,92 +0,0 @@
1
- import type { CapabilityRef } from '@xemahq/kernel-contracts/capability';
2
- import type { SpaceRef } from '@xemahq/kernel-contracts/space';
3
-
4
- /**
5
- * Orchestration metadata the SystemBus carries on every
6
- * `capability.invoke` so the backend capability-router can build its
7
- * `ExecutionContext` envelope and record who invoked what, from where,
8
- * in which space, against which environment.
9
- *
10
- * **This is pure orchestration data. The SystemBus NEVER inspects it to
11
- * decide allow/deny.** The backend capability-router is the single
12
- * authority on auth / tenancy / policy / audit. The SystemBus's only job
13
- * is to faithfully relay this metadata to the router and pass the result
14
- * back; it adds no authorization of its own.
15
- *
16
- * The fields map 1:1 onto the gateway's per-invocation envelope:
17
- * - `sourceBiomeId` → `ExecutionContext.biome.id`
18
- * - `targetCapabilityRef` → `ExecutionContext.capability.ref`
19
- * - `spaceRef` → `ExecutionContext.space`
20
- * - `environmentId` → `ExecutionContext.environment.id`
21
- * - `actorId` → `ExecutionContext.subject` (the host resolves the
22
- * full SubjectRef from the actor's session).
23
- */
24
- export interface CapabilityInvokeMeta {
25
- /** Biome that originated the invocation (for provenance + audit). */
26
- readonly sourceBiomeId: string;
27
- /** The capability being invoked. Mirrors the `ref` argument; carried
28
- * explicitly so the metadata is self-describing in audit records. */
29
- readonly targetCapabilityRef: CapabilityRef;
30
- /** The space (5/7-tier scope) the invocation runs in. */
31
- readonly spaceRef: SpaceRef;
32
- /** Canonical `environment:<slug>` ref of the active execution environment. */
33
- readonly environmentId: string;
34
- /** The acting subject's id (user / agent / app). The host expands this
35
- * into the full `SubjectRef` server-side; the SystemBus only carries
36
- * the id, never a credential. */
37
- readonly actorId: string;
38
- }
39
-
40
- /**
41
- * Result of a `capability.invoke`. Mirrors the capability-router's
42
- * `InvokeMetaToolResponseDto` wire shape (`output? / auditId /
43
- * obligations`) without importing the generated client — the kernel
44
- * contract stays framework- and transport-agnostic.
45
- *
46
- * `output` is `undefined` on denial / approval-required outcomes; the
47
- * caller MUST treat its absence explicitly (fetch the structured denial
48
- * via `auditId`) rather than assume success. `auditId` is ALWAYS
49
- * populated, including on denial — this is the audit anchor.
50
- */
51
- export interface CapabilityInvokeResult<TOutput = unknown> {
52
- /** Capability output payload. Omitted on denial / approval-required. */
53
- readonly output?: TOutput;
54
- /** Audit entry id. Always populated, including on denial. */
55
- readonly auditId: string;
56
- /**
57
- * Closed-set policy obligations the caller must honour locally
58
- * (e.g. `redact-secrets`, `max-cost-usd`). Sourced verbatim from the
59
- * router response. The string union is left open at the contract layer
60
- * because the obligation enum is owned by `@xemahq/kernel-contracts/policy`;
61
- * the host maps these to the typed enum when it honours them.
62
- */
63
- readonly obligations: readonly string[];
64
- }
65
-
66
- /**
67
- * The `capability.invoke` surface of the SystemBus.
68
- *
69
- * `invoke()` routes the call to the host's capability-router client. The
70
- * backend enforces auth / tenancy / policy / audit; the SystemBus adds
71
- * NONE of those — it is pure orchestration. A non-2xx transport failure
72
- * rejects the returned promise (fail-fast); a *policy denial* resolves
73
- * with `output === undefined` + a populated `auditId` (the router's
74
- * structured outcome), so denial is observable, never silently swallowed.
75
- */
76
- export interface CapabilityBus {
77
- /**
78
- * Invoke a capability through the backend router.
79
- *
80
- * @param ref The capability to invoke (`<domain>:<resource>.<verb>@<major>`).
81
- * @param input The capability input payload (validated server-side
82
- * against the descriptor's `inputSchema`).
83
- * @param meta Orchestration metadata for the `ExecutionContext`.
84
- * The host fills `targetCapabilityRef` from `ref` if the
85
- * caller omits it; all other fields are required.
86
- */
87
- invoke<TInput = unknown, TOutput = unknown>(
88
- ref: CapabilityRef,
89
- input: TInput,
90
- meta: CapabilityInvokeMeta,
91
- ): Promise<CapabilityInvokeResult<TOutput>>;
92
- }
@@ -1,210 +0,0 @@
1
- import { DeeplinkTargetKind } from './enums';
2
-
3
- /**
4
- * Typed parse/resolve of the SystemBus `xema://` deeplink scheme.
5
- *
6
- * The deeplink scheme addresses *places in the running shell*. It is a
7
- * distinct, narrower grammar from the kernel's `XemaObjectRef`
8
- * (`xema://<scope>/<kind>/<slug>`): a deeplink's first segment is a
9
- * {@link DeeplinkTargetKind} discriminator, not a scope path. The two
10
- * schemes share the `xema://` scheme prefix but never the same body —
11
- * `parseDeeplink` rejects anything whose head is not a known target kind,
12
- * so an `XemaObjectRef` is only valid as a deeplink when wrapped as
13
- * `xema://object/<XemaObjectRef-without-scheme>`.
14
- *
15
- * Grammar:
16
- * xema://biome/<biomeId>/<route...>?<ctx> → BiomeRoute
17
- * xema://object/<scope>/<kind>/<slug>[@<ver>] → Object
18
- * xema://capability/<capability-ref>?<input> → Capability
19
- * xema://window/<windowId> → Window
20
- *
21
- * Every parse is fail-fast: an unknown target kind, a missing required
22
- * segment, or a malformed query is a {@link DeeplinkParseError}, never a
23
- * silent fallback.
24
- */
25
-
26
- const DEEPLINK_SCHEME = 'xema://';
27
-
28
- /** Structured, fail-fast error raised by `parseDeeplink`. */
29
- export class DeeplinkParseError extends Error {
30
- public readonly code = 'DEEPLINK_INVALID';
31
- public readonly raw: string;
32
- public readonly reason: string;
33
-
34
- public constructor(raw: string, reason: string) {
35
- super(`Invalid deeplink "${raw}": ${reason}`);
36
- this.name = 'DeeplinkParseError';
37
- this.raw = raw;
38
- this.reason = reason;
39
- }
40
- }
41
-
42
- /** A parsed `xema://biome/...` deeplink. */
43
- export interface BiomeRouteDeeplink {
44
- readonly kind: DeeplinkTargetKind.BiomeRoute;
45
- readonly biomeId: string;
46
- /** The route path within the biome, with a leading slash. */
47
- readonly route: string;
48
- /** Parsed `?ctx` query params, empty when absent. */
49
- readonly ctx: Readonly<Record<string, string>>;
50
- }
51
-
52
- /** A parsed `xema://object/...` deeplink. The body is the scheme-less
53
- * `XemaObjectRef` (e.g. `system/capability/kb.page.read@1`). */
54
- export interface ObjectDeeplink {
55
- readonly kind: DeeplinkTargetKind.Object;
56
- /** Full `XemaObjectRef` (`xema://` re-prefixed) for handing to the
57
- * kernel object resolver. */
58
- readonly objectRef: `xema://${string}`;
59
- }
60
-
61
- /** A parsed `xema://capability/...` deeplink. */
62
- export interface CapabilityDeeplink {
63
- readonly kind: DeeplinkTargetKind.Capability;
64
- /** The raw capability ref string (validated by the kernel
65
- * `parseCapabilityRef` when the host launches it). */
66
- readonly capabilityRef: string;
67
- /** Parsed `?...` query params used as launch input, empty when absent. */
68
- readonly input: Readonly<Record<string, string>>;
69
- }
70
-
71
- /** A parsed `xema://window/...` deeplink. */
72
- export interface WindowDeeplink {
73
- readonly kind: DeeplinkTargetKind.Window;
74
- readonly windowId: string;
75
- }
76
-
77
- /** Discriminated union of every deeplink target. */
78
- export type ParsedDeeplink =
79
- | BiomeRouteDeeplink
80
- | ObjectDeeplink
81
- | CapabilityDeeplink
82
- | WindowDeeplink;
83
-
84
- function parseQuery(search: string): Record<string, string> {
85
- const out: Record<string, string> = {};
86
- if (search.length === 0) {
87
- return out;
88
- }
89
- for (const pair of search.split('&')) {
90
- if (pair.length === 0) {
91
- continue;
92
- }
93
- const eq = pair.indexOf('=');
94
- if (eq === -1) {
95
- out[decodeURIComponent(pair)] = '';
96
- } else {
97
- out[decodeURIComponent(pair.slice(0, eq))] = decodeURIComponent(
98
- pair.slice(eq + 1),
99
- );
100
- }
101
- }
102
- return out;
103
- }
104
-
105
- /**
106
- * Parse a `xema://` deeplink string into a typed, discriminated
107
- * {@link ParsedDeeplink}. Throws {@link DeeplinkParseError} on any
108
- * malformed input — never returns null, never coerces.
109
- */
110
- export function parseDeeplink(raw: string): ParsedDeeplink {
111
- if (typeof raw !== 'string' || !raw.startsWith(DEEPLINK_SCHEME)) {
112
- throw new DeeplinkParseError(
113
- String(raw),
114
- `must start with "${DEEPLINK_SCHEME}"`,
115
- );
116
- }
117
- const afterScheme = raw.slice(DEEPLINK_SCHEME.length);
118
- if (afterScheme.length === 0) {
119
- throw new DeeplinkParseError(raw, 'empty body after scheme');
120
- }
121
-
122
- const qIndex = afterScheme.indexOf('?');
123
- const path = qIndex === -1 ? afterScheme : afterScheme.slice(0, qIndex);
124
- const search = qIndex === -1 ? '' : afterScheme.slice(qIndex + 1);
125
- const segments = path.split('/').filter((s) => s.length > 0);
126
-
127
- const head = segments[0];
128
- if (head === undefined) {
129
- throw new DeeplinkParseError(raw, 'missing target-kind head segment');
130
- }
131
-
132
- switch (head) {
133
- case DeeplinkTargetKind.BiomeRoute: {
134
- const biomeId = segments[1];
135
- if (biomeId === undefined) {
136
- throw new DeeplinkParseError(raw, 'biome deeplink missing <biomeId>');
137
- }
138
- const routeSegments = segments.slice(2);
139
- const route = `/${routeSegments.join('/')}`;
140
- return {
141
- kind: DeeplinkTargetKind.BiomeRoute,
142
- biomeId,
143
- route,
144
- ctx: parseQuery(search),
145
- };
146
- }
147
- case DeeplinkTargetKind.Object: {
148
- const body = segments.slice(1).join('/');
149
- if (body.length === 0) {
150
- throw new DeeplinkParseError(
151
- raw,
152
- 'object deeplink missing <XemaObjectRef>',
153
- );
154
- }
155
- return {
156
- kind: DeeplinkTargetKind.Object,
157
- objectRef: `${DEEPLINK_SCHEME}${body}`,
158
- };
159
- }
160
- case DeeplinkTargetKind.Capability: {
161
- const capabilityRef = segments.slice(1).join('/');
162
- if (capabilityRef.length === 0) {
163
- throw new DeeplinkParseError(
164
- raw,
165
- 'capability deeplink missing <capability-ref>',
166
- );
167
- }
168
- return {
169
- kind: DeeplinkTargetKind.Capability,
170
- capabilityRef,
171
- input: parseQuery(search),
172
- };
173
- }
174
- case DeeplinkTargetKind.Window: {
175
- const windowId = segments[1];
176
- if (windowId === undefined) {
177
- throw new DeeplinkParseError(raw, 'window deeplink missing <windowId>');
178
- }
179
- return { kind: DeeplinkTargetKind.Window, windowId };
180
- }
181
- default:
182
- throw new DeeplinkParseError(
183
- raw,
184
- `unknown deeplink target kind "${head}" (expected one of: ${Object.values(
185
- DeeplinkTargetKind,
186
- ).join(', ')})`,
187
- );
188
- }
189
- }
190
-
191
- /**
192
- * The `deeplink` surface of the SystemBus. `parse` is pure
193
- * (framework-agnostic) and re-exported from the runtime as
194
- * {@link parseDeeplink}. `resolve` navigates the running shell to the
195
- * parsed target; the host supplies the concrete navigation. Resolution
196
- * is orchestration only — for a capability target the actual auth check
197
- * happens when `capability.invoke` reaches the backend router.
198
- */
199
- export interface DeeplinkBus {
200
- /** Parse a `xema://` deeplink string. Throws on malformed input. */
201
- parse(raw: string): ParsedDeeplink;
202
- /**
203
- * Navigate the running shell to the deeplink target. The host
204
- * implements the actual navigation (biome route push, object detail
205
- * open, capability launch, window focus). Rejects if the target cannot
206
- * be resolved (e.g. unknown biome / window) — fail-fast, no silent
207
- * no-op.
208
- */
209
- resolve(target: string | ParsedDeeplink): Promise<void>;
210
- }