@xemahq/ui-kernel 0.9.1 → 0.9.2

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 (275) hide show
  1. package/README.md +2 -2
  2. package/dist/lib/biome-host/biome-builders.d.ts.map +1 -1
  3. package/dist/lib/biome-host/biome-builders.js +3 -1
  4. package/dist/lib/biome-host/biome-builders.js.map +1 -1
  5. package/dist/lib/biome-host/biome-registry.d.ts.map +1 -1
  6. package/dist/lib/biome-host/biome-registry.js.map +1 -1
  7. package/dist/lib/biome-host/biome-scope-hooks.d.ts +11 -0
  8. package/dist/lib/biome-host/biome-scope-hooks.d.ts.map +1 -0
  9. package/dist/lib/biome-host/biome-scope-hooks.js +25 -0
  10. package/dist/lib/biome-host/biome-scope-hooks.js.map +1 -0
  11. package/dist/lib/biome-host/biome-scope.d.ts +1 -10
  12. package/dist/lib/biome-host/biome-scope.d.ts.map +1 -1
  13. package/dist/lib/biome-host/biome-scope.js +1 -24
  14. package/dist/lib/biome-host/biome-scope.js.map +1 -1
  15. package/dist/lib/biome-host/biome-scoped-query.d.ts +1 -1
  16. package/dist/lib/biome-host/biome-scoped-query.d.ts.map +1 -1
  17. package/dist/lib/biome-host/biome-scoped-query.js +1 -1
  18. package/dist/lib/biome-host/biome-scoped-query.js.map +1 -1
  19. package/dist/lib/biome-host/create-biome-orval-config.js +2 -2
  20. package/dist/lib/biome-host/create-biome-orval-config.js.map +1 -1
  21. package/dist/lib/biome-host/errors.js.map +1 -1
  22. package/dist/lib/biome-host/index.d.ts +1 -1
  23. package/dist/lib/biome-host/index.d.ts.map +1 -1
  24. package/dist/lib/biome-host/index.js +1 -1
  25. package/dist/lib/biome-host/index.js.map +1 -1
  26. package/dist/lib/biome-host/session-profiles.d.ts.map +1 -1
  27. package/dist/lib/biome-host/session-profiles.js +4 -1
  28. package/dist/lib/biome-host/session-profiles.js.map +1 -1
  29. package/dist/lib/capabilities/capability-context.d.ts +9 -0
  30. package/dist/lib/capabilities/capability-context.d.ts.map +1 -0
  31. package/dist/lib/capabilities/capability-context.js +13 -0
  32. package/dist/lib/capabilities/capability-context.js.map +1 -0
  33. package/dist/lib/capabilities/capability-provider.d.ts +2 -8
  34. package/dist/lib/capabilities/capability-provider.d.ts.map +1 -1
  35. package/dist/lib/capabilities/capability-provider.js +1 -12
  36. package/dist/lib/capabilities/capability-provider.js.map +1 -1
  37. package/dist/lib/capabilities/index.d.ts +1 -0
  38. package/dist/lib/capabilities/index.d.ts.map +1 -1
  39. package/dist/lib/capabilities/index.js +1 -0
  40. package/dist/lib/capabilities/index.js.map +1 -1
  41. package/dist/lib/capabilities/use-capability.d.ts.map +1 -1
  42. package/dist/lib/capabilities/use-capability.js +1 -1
  43. package/dist/lib/capabilities/use-capability.js.map +1 -1
  44. package/dist/lib/system-bus/deeplink.js.map +1 -1
  45. package/dist/lib/system-bus/host-ports.d.ts +2 -1
  46. package/dist/lib/system-bus/host-ports.d.ts.map +1 -1
  47. package/dist/lib/system-bus/intent-registry.d.ts.map +1 -1
  48. package/dist/lib/system-bus/intent-registry.js.map +1 -1
  49. package/dist/offline/index.d.ts +2 -1
  50. package/dist/offline/index.d.ts.map +1 -1
  51. package/dist/offline/index.js +2 -1
  52. package/dist/offline/index.js.map +1 -1
  53. package/dist/offline/offline-status-badge.js +1 -1
  54. package/dist/offline/offline-status-badge.js.map +1 -1
  55. package/dist/offline/outbox.js.map +1 -1
  56. package/dist/offline/react-hooks.d.ts +7 -0
  57. package/dist/offline/react-hooks.d.ts.map +1 -0
  58. package/dist/offline/react-hooks.js +25 -0
  59. package/dist/offline/react-hooks.js.map +1 -0
  60. package/dist/offline/react.d.ts +0 -4
  61. package/dist/offline/react.d.ts.map +1 -1
  62. package/dist/offline/react.js +2 -24
  63. package/dist/offline/react.js.map +1 -1
  64. package/dist/offline/storage.d.ts.map +1 -1
  65. package/dist/offline/storage.js +8 -5
  66. package/dist/offline/storage.js.map +1 -1
  67. package/dist/registry/index.d.ts +1 -0
  68. package/dist/registry/index.d.ts.map +1 -1
  69. package/dist/registry/index.js +1 -0
  70. package/dist/registry/index.js.map +1 -1
  71. package/dist/registry/lib/primitives/SessionEventCard.d.ts.map +1 -1
  72. package/dist/registry/lib/primitives/SessionEventCard.js +1 -1
  73. package/dist/registry/lib/primitives/SessionEventCard.js.map +1 -1
  74. package/dist/registry/lib/session-context-provider.d.ts +1 -3
  75. package/dist/registry/lib/session-context-provider.d.ts.map +1 -1
  76. package/dist/registry/lib/session-context-provider.js +2 -15
  77. package/dist/registry/lib/session-context-provider.js.map +1 -1
  78. package/dist/registry/lib/session-context.d.ts +5 -0
  79. package/dist/registry/lib/session-context.d.ts.map +1 -0
  80. package/dist/registry/lib/session-context.js +15 -0
  81. package/dist/registry/lib/session-context.js.map +1 -0
  82. package/dist/registry/lib/session-selectors.d.ts.map +1 -1
  83. package/dist/registry/lib/session-selectors.js +3 -1
  84. package/dist/registry/lib/session-selectors.js.map +1 -1
  85. package/dist/ui/branding/app-branding-context.d.ts +9 -0
  86. package/dist/ui/branding/app-branding-context.d.ts.map +1 -0
  87. package/dist/ui/branding/app-branding-context.js +10 -0
  88. package/dist/ui/branding/app-branding-context.js.map +1 -0
  89. package/dist/ui/branding/app-branding-provider.d.ts +0 -6
  90. package/dist/ui/branding/app-branding-provider.d.ts.map +1 -1
  91. package/dist/ui/branding/app-branding-provider.js +1 -8
  92. package/dist/ui/branding/app-branding-provider.js.map +1 -1
  93. package/dist/ui/capture/schema-field-input.js +1 -1
  94. package/dist/ui/capture/schema-field-input.js.map +1 -1
  95. package/dist/ui/capture/use-prefill.d.ts.map +1 -1
  96. package/dist/ui/capture/use-prefill.js +3 -1
  97. package/dist/ui/capture/use-prefill.js.map +1 -1
  98. package/dist/ui/capture/use-wizard.d.ts +1 -1
  99. package/dist/ui/capture/use-wizard.d.ts.map +1 -1
  100. package/dist/ui/capture/use-wizard.js +1 -1
  101. package/dist/ui/capture/use-wizard.js.map +1 -1
  102. package/dist/ui/capture/wizard.d.ts.map +1 -1
  103. package/dist/ui/capture/wizard.js.map +1 -1
  104. package/dist/ui/index.d.ts +5 -1
  105. package/dist/ui/index.d.ts.map +1 -1
  106. package/dist/ui/index.js +5 -1
  107. package/dist/ui/index.js.map +1 -1
  108. package/dist/ui/primitives/alert-dialog.js +1 -1
  109. package/dist/ui/primitives/alert-dialog.js.map +1 -1
  110. package/dist/ui/primitives/badge-variants.d.ts +4 -0
  111. package/dist/ui/primitives/badge-variants.d.ts.map +1 -0
  112. package/dist/ui/primitives/badge-variants.js +15 -0
  113. package/dist/ui/primitives/badge-variants.js.map +1 -0
  114. package/dist/ui/primitives/badge.d.ts +3 -5
  115. package/dist/ui/primitives/badge.d.ts.map +1 -1
  116. package/dist/ui/primitives/badge.js +2 -15
  117. package/dist/ui/primitives/badge.js.map +1 -1
  118. package/dist/ui/primitives/button-variants.d.ts +5 -0
  119. package/dist/ui/primitives/button-variants.d.ts.map +1 -0
  120. package/dist/ui/primitives/button-variants.js +24 -0
  121. package/dist/ui/primitives/button-variants.js.map +1 -0
  122. package/dist/ui/primitives/button.d.ts +3 -6
  123. package/dist/ui/primitives/button.d.ts.map +1 -1
  124. package/dist/ui/primitives/button.js +2 -24
  125. package/dist/ui/primitives/button.js.map +1 -1
  126. package/dist/ui/primitives/form-stepper.d.ts +1 -13
  127. package/dist/ui/primitives/form-stepper.d.ts.map +1 -1
  128. package/dist/ui/primitives/form-stepper.js +1 -6
  129. package/dist/ui/primitives/form-stepper.js.map +1 -1
  130. package/dist/ui/primitives/form-stepper.types.d.ts +14 -0
  131. package/dist/ui/primitives/form-stepper.types.d.ts.map +1 -0
  132. package/dist/ui/primitives/form-stepper.types.js +7 -0
  133. package/dist/ui/primitives/form-stepper.types.js.map +1 -0
  134. package/dist/ui/primitives/preview-device-frame.js +1 -1
  135. package/dist/ui/primitives/preview-device-frame.js.map +1 -1
  136. package/dist/ui/primitives/tag-multi-select.d.ts.map +1 -1
  137. package/dist/ui/primitives/tag-multi-select.js +1 -1
  138. package/dist/ui/primitives/tag-multi-select.js.map +1 -1
  139. package/dist/vista/index.d.ts +4 -0
  140. package/dist/vista/index.d.ts.map +1 -1
  141. package/dist/vista/index.js +4 -0
  142. package/dist/vista/index.js.map +1 -1
  143. package/dist/vista/surfaces/FilesSurface.d.ts +1 -12
  144. package/dist/vista/surfaces/FilesSurface.d.ts.map +1 -1
  145. package/dist/vista/surfaces/FilesSurface.js +2 -46
  146. package/dist/vista/surfaces/FilesSurface.js.map +1 -1
  147. package/dist/vista/surfaces/FormSurface.d.ts.map +1 -1
  148. package/dist/vista/surfaces/FormSurface.js +39 -12
  149. package/dist/vista/surfaces/FormSurface.js.map +1 -1
  150. package/dist/vista/surfaces/elicitation-transport.d.ts +12 -3
  151. package/dist/vista/surfaces/elicitation-transport.d.ts.map +1 -1
  152. package/dist/vista/surfaces/elicitation-transport.js +96 -3
  153. package/dist/vista/surfaces/elicitation-transport.js.map +1 -1
  154. package/dist/vista/surfaces/file-surface-utils.d.ts +13 -0
  155. package/dist/vista/surfaces/file-surface-utils.d.ts.map +1 -0
  156. package/dist/vista/surfaces/file-surface-utils.js +46 -0
  157. package/dist/vista/surfaces/file-surface-utils.js.map +1 -0
  158. package/dist/vista/surfaces/index.d.ts +4 -3
  159. package/dist/vista/surfaces/index.d.ts.map +1 -1
  160. package/dist/vista/surfaces/index.js +4 -81
  161. package/dist/vista/surfaces/index.js.map +1 -1
  162. package/dist/vista/surfaces/register-surfaces.d.ts +2 -0
  163. package/dist/vista/surfaces/register-surfaces.d.ts.map +1 -0
  164. package/dist/vista/surfaces/register-surfaces.js +80 -0
  165. package/dist/vista/surfaces/register-surfaces.js.map +1 -0
  166. package/dist/vista/surfaces/text-surfaces.js +1 -1
  167. package/dist/vista/surfaces/text-surfaces.js.map +1 -1
  168. package/dist/vista/vista-code-renderer-context.d.ts +9 -0
  169. package/dist/vista/vista-code-renderer-context.d.ts.map +1 -0
  170. package/dist/vista/vista-code-renderer-context.js +6 -0
  171. package/dist/vista/vista-code-renderer-context.js.map +1 -0
  172. package/dist/vista/vista-code-renderer.d.ts +1 -6
  173. package/dist/vista/vista-code-renderer.d.ts.map +1 -1
  174. package/dist/vista/vista-code-renderer.js +1 -5
  175. package/dist/vista/vista-code-renderer.js.map +1 -1
  176. package/dist/vista/vista-file-context.d.ts +8 -0
  177. package/dist/vista/vista-file-context.d.ts.map +1 -0
  178. package/dist/vista/vista-file-context.js +6 -0
  179. package/dist/vista/vista-file-context.js.map +1 -0
  180. package/dist/vista/vista-file-source.d.ts +1 -6
  181. package/dist/vista/vista-file-source.d.ts.map +1 -1
  182. package/dist/vista/vista-file-source.js +2 -5
  183. package/dist/vista/vista-file-source.js.map +1 -1
  184. package/dist/vista/vista-form-context.d.ts +13 -0
  185. package/dist/vista/vista-form-context.d.ts.map +1 -0
  186. package/dist/vista/vista-form-context.js +6 -0
  187. package/dist/vista/vista-form-context.js.map +1 -0
  188. package/dist/vista/vista-form-host.d.ts +1 -10
  189. package/dist/vista/vista-form-host.d.ts.map +1 -1
  190. package/dist/vista/vista-form-host.js +1 -5
  191. package/dist/vista/vista-form-host.js.map +1 -1
  192. package/dist/vista/vista-open-context.d.ts +1 -3
  193. package/dist/vista/vista-open-context.d.ts.map +1 -1
  194. package/dist/vista/vista-open-context.js +1 -5
  195. package/dist/vista/vista-open-context.js.map +1 -1
  196. package/dist/vista/vista-open-state.d.ts +5 -0
  197. package/dist/vista/vista-open-state.d.ts.map +1 -0
  198. package/dist/vista/vista-open-state.js +6 -0
  199. package/dist/vista/vista-open-state.js.map +1 -0
  200. package/dist/vista/vista-payloads.d.ts +2 -3
  201. package/dist/vista/vista-payloads.d.ts.map +1 -1
  202. package/dist/vista/vista-payloads.js +18 -21
  203. package/dist/vista/vista-payloads.js.map +1 -1
  204. package/dist/vista/vista-tools.d.ts.map +1 -1
  205. package/dist/vista/vista-tools.js.map +1 -1
  206. package/package.json +3 -3
  207. package/src/lib/biome-host/biome-builders.ts +4 -1
  208. package/src/lib/biome-host/biome-registry.ts +0 -1
  209. package/src/lib/biome-host/biome-scope-hooks.ts +39 -0
  210. package/src/lib/biome-host/biome-scope.tsx +1 -68
  211. package/src/lib/biome-host/biome-scoped-query.ts +4 -1
  212. package/src/lib/biome-host/create-biome-orval-config.ts +2 -2
  213. package/src/lib/biome-host/errors.ts +1 -1
  214. package/src/lib/biome-host/index.ts +1 -1
  215. package/src/lib/biome-host/session-profiles.ts +7 -1
  216. package/src/lib/capabilities/capability-context.ts +25 -0
  217. package/src/lib/capabilities/capability-provider.tsx +5 -34
  218. package/src/lib/capabilities/index.ts +1 -0
  219. package/src/lib/capabilities/use-capability.ts +4 -1
  220. package/src/lib/system-bus/deeplink.ts +1 -1
  221. package/src/lib/system-bus/host-ports.ts +2 -1
  222. package/src/lib/system-bus/intent-registry.ts +1 -2
  223. package/src/offline/index.ts +4 -2
  224. package/src/offline/offline-status-badge.tsx +1 -1
  225. package/src/offline/outbox.test.ts +23 -16
  226. package/src/offline/outbox.ts +1 -1
  227. package/src/offline/react-hooks.ts +37 -0
  228. package/src/offline/react.tsx +1 -40
  229. package/src/offline/storage.ts +11 -6
  230. package/src/registry/index.ts +1 -0
  231. package/src/registry/lib/primitives/SessionEventCard.tsx +4 -2
  232. package/src/registry/lib/session-context-provider.tsx +8 -25
  233. package/src/registry/lib/session-context.ts +21 -0
  234. package/src/registry/lib/session-selectors.ts +3 -1
  235. package/src/ui/branding/app-branding-context.ts +20 -0
  236. package/src/ui/branding/app-branding-provider.tsx +5 -27
  237. package/src/ui/capture/schema-field-input.tsx +7 -1
  238. package/src/ui/capture/use-prefill.ts +4 -1
  239. package/src/ui/capture/use-wizard.ts +2 -2
  240. package/src/ui/capture/wizard.tsx +2 -1
  241. package/src/ui/index.ts +7 -2
  242. package/src/ui/primitives/alert-dialog.tsx +1 -1
  243. package/src/ui/primitives/badge-variants.ts +21 -0
  244. package/src/ui/primitives/badge.tsx +3 -19
  245. package/src/ui/primitives/button-variants.ts +31 -0
  246. package/src/ui/primitives/button.tsx +3 -28
  247. package/src/ui/primitives/form-stepper.tsx +1 -16
  248. package/src/ui/primitives/form-stepper.types.ts +15 -0
  249. package/src/ui/primitives/preview-device-frame.tsx +1 -1
  250. package/src/ui/primitives/tag-multi-select.tsx +3 -4
  251. package/src/vista/form-payload.spec.ts +71 -25
  252. package/src/vista/index.ts +4 -0
  253. package/src/vista/surfaces/FilesSurface.tsx +2 -68
  254. package/src/vista/surfaces/FormSurface.tsx +125 -26
  255. package/src/vista/surfaces/elicitation-transport.spec.ts +205 -23
  256. package/src/vista/surfaces/elicitation-transport.ts +192 -14
  257. package/src/vista/surfaces/file-surface-utils.ts +62 -0
  258. package/src/vista/surfaces/index.ts +24 -0
  259. package/src/vista/surfaces/{index.tsx → register-surfaces.tsx} +1 -21
  260. package/src/vista/surfaces/text-surfaces.tsx +1 -1
  261. package/src/vista/vista-code-renderer-context.ts +16 -0
  262. package/src/vista/vista-code-renderer.tsx +4 -16
  263. package/src/vista/vista-file-context.ts +14 -0
  264. package/src/vista/vista-file-source.tsx +5 -28
  265. package/src/vista/vista-form-context.ts +20 -0
  266. package/src/vista/vista-form-host.tsx +11 -36
  267. package/src/vista/vista-open-context.tsx +4 -14
  268. package/src/vista/vista-open-state.ts +11 -0
  269. package/src/vista/vista-payloads.ts +44 -46
  270. package/src/vista/vista-tools.ts +2 -2
  271. package/dist/lib/biome-host/response-envelope.d.ts +0 -3
  272. package/dist/lib/biome-host/response-envelope.d.ts.map +0 -1
  273. package/dist/lib/biome-host/response-envelope.js +0 -21
  274. package/dist/lib/biome-host/response-envelope.js.map +0 -1
  275. package/src/lib/biome-host/response-envelope.ts +0 -69
@@ -0,0 +1,24 @@
1
+ import './register-surfaces';
2
+
3
+ export { ChartSurface } from './ChartSurface';
4
+ export { FilesSurface } from './FilesSurface';
5
+ export {
6
+ fileExtMeta,
7
+ groupFilesByFolder,
8
+ type VistaFileGroup,
9
+ } from './file-surface-utils';
10
+ export { FormSurface } from './FormSurface';
11
+ export {
12
+ extractServiceMessage,
13
+ readElicitationStatus,
14
+ resolveTrustedElicitationEndpoints,
15
+ resolveTrustedElicitationLaunchUrl,
16
+ submitElicitationFields,
17
+ VistaFormSubmitError,
18
+ VistaFormTransportConfigError,
19
+ } from './elicitation-transport';
20
+ export { HtmlSurface } from './HtmlSurface';
21
+ export { TableSurface } from './TableSurface';
22
+ export { UrlSurface } from './UrlSurface';
23
+ export { CodeSurface, DiffSurface, JsonSurface } from './text-surfaces';
24
+ export { ImageSurface, MediaSurface, PdfSurface } from './blob-surfaces';
@@ -29,11 +29,7 @@
29
29
  */
30
30
  import { SurfaceKind } from '@xemahq/kernel-contracts/surface';
31
31
 
32
- import {
33
- ImageSurface,
34
- MediaSurface,
35
- PdfSurface,
36
- } from './blob-surfaces';
32
+ import { ImageSurface, MediaSurface, PdfSurface } from './blob-surfaces';
37
33
  import { ChartSurface } from './ChartSurface';
38
34
  import { FilesSurface } from './FilesSurface';
39
35
  import { FormSurface } from './FormSurface';
@@ -139,19 +135,3 @@ vistaSurfaceRegistry.registerFirstParty(SurfaceKind.Form, {
139
135
  validate: validateFormPayload,
140
136
  render: (payload) => <FormSurface {...payload} />,
141
137
  });
142
-
143
- export { ChartSurface } from './ChartSurface';
144
- export { FilesSurface, fileExtMeta, groupFilesByFolder } from './FilesSurface';
145
- export { FormSurface } from './FormSurface';
146
- export {
147
- submitElicitationFields,
148
- readElicitationStatus,
149
- extractServiceMessage,
150
- VistaFormSubmitError,
151
- } from './elicitation-transport';
152
- export { HtmlSurface } from './HtmlSurface';
153
- export { TableSurface } from './TableSurface';
154
- export { UrlSurface } from './UrlSurface';
155
- export { CodeSurface, DiffSurface, JsonSurface } from './text-surfaces';
156
- export { ImageSurface, MediaSurface, PdfSurface } from './blob-surfaces';
157
- export type { VistaFileGroup } from './FilesSurface';
@@ -9,7 +9,7 @@
9
9
  * `plain` tab kind was collapsed into it; one kind, one renderer, no alias).
10
10
  */
11
11
 
12
- import { useVistaCodeRenderer } from '../vista-code-renderer';
12
+ import { useVistaCodeRenderer } from '../vista-code-renderer-context';
13
13
  import { VistaFileText } from '../vista-file-source';
14
14
 
15
15
  import type { VistaTextPayload } from '../vista-payloads';
@@ -0,0 +1,16 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ import type { ReactNode } from 'react';
4
+
5
+ export type VistaCodeRenderer = (args: {
6
+ readonly content: string;
7
+ readonly path?: string;
8
+ readonly language?: string;
9
+ }) => ReactNode;
10
+
11
+ export const VistaCodeRendererContext =
12
+ createContext<VistaCodeRenderer | null>(null);
13
+
14
+ export function useVistaCodeRenderer(): VistaCodeRenderer | null {
15
+ return useContext(VistaCodeRendererContext);
16
+ }
@@ -14,20 +14,13 @@
14
14
  * the intended rendering. Neither is an error path.
15
15
  */
16
16
  import {
17
- createContext,
18
- useContext,
19
17
  type ReactElement,
20
18
  type ReactNode,
21
19
  } from 'react';
22
-
23
- /** Draw a code body. `path` is present for a file-backed surface. */
24
- export type VistaCodeRenderer = (args: {
25
- readonly content: string;
26
- readonly path?: string;
27
- readonly language?: string;
28
- }) => ReactNode;
29
-
30
- const VistaCodeRendererContext = createContext<VistaCodeRenderer | null>(null);
20
+ import {
21
+ VistaCodeRendererContext,
22
+ type VistaCodeRenderer,
23
+ } from './vista-code-renderer-context';
31
24
 
32
25
  export function VistaCodeRendererProvider({
33
26
  renderer,
@@ -39,8 +32,3 @@ export function VistaCodeRendererProvider({
39
32
  </VistaCodeRendererContext.Provider>
40
33
  );
41
34
  }
42
-
43
- /** The host's code renderer, or `null` for the built-in mono pane. */
44
- export function useVistaCodeRenderer(): VistaCodeRenderer | null {
45
- return useContext(VistaCodeRendererContext);
46
- }
@@ -0,0 +1,14 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ export interface VistaFileSource {
4
+ readText(path: string): Promise<string>;
5
+ resolveUrl(path: string): Promise<string>;
6
+ readonly revision?: string | number;
7
+ }
8
+
9
+ export const VistaFileSourceContext =
10
+ createContext<VistaFileSource | null>(null);
11
+
12
+ export function useVistaFileSource(): VistaFileSource | null {
13
+ return useContext(VistaFileSourceContext);
14
+ }
@@ -13,34 +13,16 @@
13
13
  * "content unavailable".
14
14
  */
15
15
  import {
16
- createContext,
17
- useContext,
18
16
  useEffect,
19
17
  useState,
20
18
  type ReactElement,
21
19
  type ReactNode,
22
20
  } from 'react';
23
-
24
- /** Host-supplied byte access for path-backed surfaces. */
25
- export interface VistaFileSource {
26
- /** Read a workspace-relative path as text. Rejects on failure. */
27
- readText(path: string): Promise<string>;
28
- /**
29
- * Resolve a workspace-relative path to a fetchable URL (`blob:`, `data:`, or
30
- * a durable `https:` URL) for binary surfaces. Rejects on failure.
31
- *
32
- * The host owns the lifetime of anything it creates (e.g. revoking an object
33
- * URL); the surface only reads.
34
- */
35
- resolveUrl(path: string): Promise<string>;
36
- /**
37
- * Opaque revision token. Change it to make every mounted path-backed surface
38
- * re-read (the host bumps it on a workspace file-change event).
39
- */
40
- readonly revision?: string | number;
41
- }
42
-
43
- const VistaFileSourceContext = createContext<VistaFileSource | null>(null);
21
+ import {
22
+ VistaFileSourceContext,
23
+ useVistaFileSource,
24
+ type VistaFileSource,
25
+ } from './vista-file-context';
44
26
 
45
27
  export function VistaFileSourceProvider({
46
28
  source,
@@ -53,11 +35,6 @@ export function VistaFileSourceProvider({
53
35
  );
54
36
  }
55
37
 
56
- /** The active file source, or `null` when no provider is mounted. */
57
- export function useVistaFileSource(): VistaFileSource | null {
58
- return useContext(VistaFileSourceContext);
59
- }
60
-
61
38
  /** Async load state for a path-backed surface. */
62
39
  type LoadState =
63
40
  | { readonly status: 'loading' }
@@ -0,0 +1,20 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ export interface VistaFormOutcome {
4
+ readonly submitted: true;
5
+ readonly ref: string;
6
+ readonly connectionId: string | null;
7
+ }
8
+
9
+ export interface VistaFormHost {
10
+ readonly elicitationApiBaseUrl: string;
11
+ getAccessToken(): Promise<string>;
12
+ onOutcome(outcome: VistaFormOutcome): void;
13
+ }
14
+
15
+ export const VistaFormHostContext =
16
+ createContext<VistaFormHost | null>(null);
17
+
18
+ export function useVistaFormHost(): VistaFormHost | null {
19
+ return useContext(VistaFormHostContext);
20
+ }
@@ -18,16 +18,22 @@
18
18
  * 2. `getAccessToken` returns the SUBJECT's token. The host binds it to the
19
19
  * logged-in user's session; it is never a service token and never the
20
20
  * agent's token, so the service authorizes the human, not the model.
21
- * 3. The surface's transport posts to an ABSOLUTE service URL taken from the
22
- * validated payload (see `validateFormPayload`, which rejects a relative
23
- * URL). There is no host-relative path, so it cannot be pointed at the
24
- * app's own BFF/chat transport.
21
+ * 3. `elicitationApiBaseUrl` is supplied by trusted host configuration, never
22
+ * by the agent-controlled payload. The kernel validates its scheme and
23
+ * canonical authority/path before deriving the status/submit endpoints.
25
24
  *
26
25
  * There is deliberately NO default host: a `form` surface mounted without a
27
26
  * provider renders a visible refusal and cannot submit. Fail-closed — a form
28
27
  * that silently posts nowhere would be worse than one that says it cannot.
29
28
  */
30
- import { createContext, useContext, type ReactElement, type ReactNode } from 'react';
29
+ import {
30
+ type ReactElement,
31
+ type ReactNode,
32
+ } from 'react';
33
+ import {
34
+ VistaFormHostContext,
35
+ type VistaFormHost,
36
+ } from './vista-form-context';
31
37
 
32
38
  /**
33
39
  * Everything a settled elicitation reports. Closed, scalar-only, and
@@ -35,32 +41,6 @@ import { createContext, useContext, type ReactElement, type ReactNode } from 're
35
41
  * persistence layer behind it has no column able to hold a field value, and
36
42
  * neither does this type.
37
43
  */
38
- export interface VistaFormOutcome {
39
- /** Always `true`: an unsettled elicitation produces no outcome at all. */
40
- readonly submitted: true;
41
- /** The elicitation reference the agent polls. Opaque, non-secret. */
42
- readonly ref: string;
43
- /** The connection the submission provisioned, when the service reported one. */
44
- readonly connectionId: string | null;
45
- }
46
-
47
- /** Host-supplied capabilities for the `form` surface. */
48
- export interface VistaFormHost {
49
- /**
50
- * The SUBJECT's own access token. Called once per request so a refreshed
51
- * token is picked up without remounting the surface.
52
- */
53
- getAccessToken(): Promise<string>;
54
- /**
55
- * Called exactly once when the elicitation settles. The host relays this to
56
- * whatever needs to know (cache invalidation, the agent session). By type it
57
- * can carry nothing but the outcome.
58
- */
59
- onOutcome(outcome: VistaFormOutcome): void;
60
- }
61
-
62
- const VistaFormHostContext = createContext<VistaFormHost | null>(null);
63
-
64
44
  export function VistaFormHostProvider({
65
45
  host,
66
46
  children,
@@ -71,8 +51,3 @@ export function VistaFormHostProvider({
71
51
  </VistaFormHostContext.Provider>
72
52
  );
73
53
  }
74
-
75
- /** The active form host, or `null` when no provider is mounted. */
76
- export function useVistaFormHost(): VistaFormHost | null {
77
- return useContext(VistaFormHostContext);
78
- }
@@ -12,18 +12,13 @@
12
12
  * silently does nothing.
13
13
  */
14
14
  import {
15
- createContext,
16
- useContext,
17
15
  type ReactElement,
18
16
  type ReactNode,
19
17
  } from 'react';
20
-
21
- import type { VistaTab } from './vista-model';
22
-
23
- /** Open (or replace) a tab and focus it. Mirrors `VistaTabsController.open`. */
24
- export type VistaOpenFn = (surface: VistaTab) => string;
25
-
26
- const VistaOpenContext = createContext<VistaOpenFn | null>(null);
18
+ import {
19
+ VistaOpenContext,
20
+ type VistaOpenFn,
21
+ } from './vista-open-state';
27
22
 
28
23
  export function VistaOpenProvider({
29
24
  open,
@@ -35,8 +30,3 @@ export function VistaOpenProvider({
35
30
  </VistaOpenContext.Provider>
36
31
  );
37
32
  }
38
-
39
- /** The panel's `open`, or `null` when no panel is mounted above. */
40
- export function useVistaOpen(): VistaOpenFn | null {
41
- return useContext(VistaOpenContext);
42
- }
@@ -0,0 +1,11 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ import type { VistaTab } from './vista-model';
4
+
5
+ export type VistaOpenFn = (surface: VistaTab) => string;
6
+
7
+ export const VistaOpenContext = createContext<VistaOpenFn | null>(null);
8
+
9
+ export function useVistaOpen(): VistaOpenFn | null {
10
+ return useContext(VistaOpenContext);
11
+ }
@@ -199,7 +199,8 @@ export interface VistaTablePayload {
199
199
  export function validateTablePayload(raw: unknown): VistaTablePayload | null {
200
200
  const record = asRecord(raw);
201
201
  if (record === null) return null;
202
- if (!Array.isArray(record.columns) || !Array.isArray(record.rows)) return null;
202
+ if (!Array.isArray(record.columns) || !Array.isArray(record.rows))
203
+ return null;
203
204
  if (!record.columns.every((c) => typeof c === 'string')) return null;
204
205
  if (!record.rows.every((r) => Array.isArray(r))) return null;
205
206
  return {
@@ -244,7 +245,8 @@ export function validateChartPayload(raw: unknown): VistaChartPayload | null {
244
245
  if (record === null) return null;
245
246
  if (typeof record.kind !== 'string' || !CHART_KINDS.includes(record.kind))
246
247
  return null;
247
- if (typeof record.title !== 'string' || record.title.length === 0) return null;
248
+ if (typeof record.title !== 'string' || record.title.length === 0)
249
+ return null;
248
250
  if (!Array.isArray(record.series) || record.series.length === 0) return null;
249
251
  const series: VistaChartSeries[] = [];
250
252
  for (const entry of record.series) {
@@ -377,37 +379,18 @@ export function validateWebPayload(raw: unknown): VistaWebPayload | null {
377
379
  : null;
378
380
  }
379
381
 
380
- /**
381
- * An `http(s)` ABSOLUTE URL, or `null`.
382
- *
383
- * Every URL on a {@link VistaFormPayload} must be absolute. That is the
384
- * structural half of "the value goes browser → service and never through the
385
- * agent": a relative path would resolve against the HOST app's origin — i.e.
386
- * its BFF, where the chat transport lives — so a relative submit target is
387
- * rejected outright rather than normalised.
388
- */
389
- function absoluteHttpUrl(value: unknown): string | null {
390
- if (typeof value !== 'string' || value.length === 0) return null;
391
- let parsed: URL;
392
- try {
393
- parsed = new URL(value);
394
- } catch {
395
- return null;
396
- }
397
- return parsed.protocol === 'https:' || parsed.protocol === 'http:' ? value : null;
398
- }
399
-
400
382
  /**
401
383
  * The consent / install handoff of a {@link VistaFormPayload}.
402
384
  *
403
385
  * Present when the connector's app auth is `oauth2` or `app_install`: there is
404
386
  * no field form to fill, only a link the user follows in another window. It is
405
- * fully generic — the URL is minted per-provider by the owning service and
406
- * carried here verbatim, so no provider is special-cased in the renderer.
387
+ * fully generic — the owning service supplies a path under the host-configured
388
+ * trusted service origin, so no provider is special-cased in the renderer and
389
+ * an agent-controlled payload never selects a network authority.
407
390
  */
408
391
  export interface VistaFormLaunch {
409
- /** ABSOLUTE consent / install URL, opened in a new window. */
410
- readonly url: string;
392
+ /** Root-relative consent / install path on the trusted elicitation service. */
393
+ readonly path: string;
411
394
  /** Button copy, e.g. "Install Acme" / "Continue to Acme". */
412
395
  readonly label: string;
413
396
  /** Optional explanation rendered above the button. */
@@ -421,10 +404,10 @@ export interface VistaFormLaunch {
421
404
  * never see. Two mutually-exclusive modes, chosen by the presence of
422
405
  * {@link launch}:
423
406
  *
424
- * • FIELD mode — render `fields`, POST them to `submitUrl` with the user's
425
- * own JWT;
407
+ * • FIELD mode — render `fields`, POST them through the host's trusted
408
+ * elicitation-service base URL with the user's own JWT;
426
409
  * • LAUNCH mode — render the consent/install link, then confirm completion
427
- * against `statusUrl`.
410
+ * through that same trusted service.
428
411
  *
429
412
  * Both settle into the same `{ submitted, ref }` shape, so the agent's view of
430
413
  * the world does not depend on which mode ran.
@@ -434,10 +417,6 @@ export interface VistaFormPayload {
434
417
  readonly ref: string;
435
418
  /** Why the credential is being asked for — shown to the user verbatim. */
436
419
  readonly purpose: string;
437
- /** ABSOLUTE service URL the captured fields are POSTed to. */
438
- readonly submitUrl: string;
439
- /** ABSOLUTE service URL reporting whether the elicitation has settled. */
440
- readonly statusUrl: string;
441
420
  /** The onboarding form's fields. MAY be empty — the service is the authority. */
442
421
  readonly fields: readonly CaptureFieldSpec[];
443
422
  /** Optional heading override (defaults to the tab title). */
@@ -448,16 +427,26 @@ export interface VistaFormPayload {
448
427
  readonly launch?: VistaFormLaunch;
449
428
  }
450
429
 
430
+ const VISTA_FORM_REF_PATTERN = /^[A-Za-z0-9_-]{1,256}$/;
431
+
432
+ /** Whether a value is one opaque base64url elicitation path segment. */
433
+ export function isValidVistaFormRef(value: unknown): value is string {
434
+ return typeof value === 'string' && VISTA_FORM_REF_PATTERN.test(value);
435
+ }
436
+
451
437
  export function validateFormPayload(raw: unknown): VistaFormPayload | null {
452
438
  const record = asRecord(raw);
453
439
  if (record === null) return null;
454
- if (typeof record.ref !== 'string' || record.ref.length === 0) return null;
440
+ // The service generates base64url refs. Keeping the accepted alphabet closed
441
+ // makes the ref safe as exactly one URL path segment; dot segments, slashes,
442
+ // percent escapes and Unicode lookalikes are all rejected.
443
+ if (!isValidVistaFormRef(record.ref)) {
444
+ return null;
445
+ }
455
446
  if (typeof record.purpose !== 'string') return null;
456
-
457
- const submitUrl = absoluteHttpUrl(record.submitUrl);
458
- if (submitUrl === null) return null;
459
- const statusUrl = absoluteHttpUrl(record.statusUrl);
460
- if (statusUrl === null) return null;
447
+ // Deliberately reject the old contract rather than silently ignoring its
448
+ // payload-selected network targets.
449
+ if ('submitUrl' in record || 'statusUrl' in record) return null;
461
450
 
462
451
  const fields = validateCaptureFields(record.fields);
463
452
  if (fields === null) return null;
@@ -471,24 +460,32 @@ export function validateFormPayload(raw: unknown): VistaFormPayload | null {
471
460
  if (record.launch !== undefined) {
472
461
  const raw_ = asRecord(record.launch);
473
462
  if (raw_ === null) return null;
474
- const url = absoluteHttpUrl(raw_.url);
475
- if (url === null) return null;
463
+ if ('url' in raw_) return null;
464
+ if (
465
+ typeof raw_.path !== 'string' ||
466
+ !raw_.path.startsWith('/') ||
467
+ raw_.path.startsWith('//') ||
468
+ raw_.path.includes('\\')
469
+ ) {
470
+ return null;
471
+ }
476
472
  if (typeof raw_.label !== 'string' || raw_.label.length === 0) return null;
477
473
  const hint = optionalString(raw_.hint);
478
474
  if (hint === null) return null;
479
- launch = hint === undefined ? { url, label: raw_.label } : { url, label: raw_.label, hint };
475
+ launch =
476
+ hint === undefined
477
+ ? { path: raw_.path, label: raw_.label }
478
+ : { path: raw_.path, label: raw_.label, hint };
480
479
  }
481
480
 
482
481
  const payload: {
483
482
  ref: string;
484
483
  purpose: string;
485
- submitUrl: string;
486
- statusUrl: string;
487
484
  fields: readonly CaptureFieldSpec[];
488
485
  heading?: string;
489
486
  submitLabel?: string;
490
487
  launch?: VistaFormLaunch;
491
- } = { ref: record.ref, purpose: record.purpose, submitUrl, statusUrl, fields };
488
+ } = { ref: record.ref, purpose: record.purpose, fields };
492
489
  if (heading !== undefined) payload.heading = heading;
493
490
  if (submitLabel !== undefined) payload.submitLabel = submitLabel;
494
491
  if (launch !== undefined) payload.launch = launch;
@@ -505,7 +502,8 @@ export interface VistaAppPayload {
505
502
  export function validateAppPayload(raw: unknown): VistaAppPayload | null {
506
503
  const record = asRecord(raw);
507
504
  if (record === null) return null;
508
- if (typeof record.appId !== 'string' || record.appId.length === 0) return null;
505
+ if (typeof record.appId !== 'string' || record.appId.length === 0)
506
+ return null;
509
507
  const path = optionalString(record.path);
510
508
  if (path === null) return null;
511
509
  return path === undefined
@@ -120,7 +120,7 @@ export const VistaToolResultSchema: z.ZodType<VistaToolResult> = z.union([
120
120
  error: z.nativeEnum(VistaToolError),
121
121
  detail: z.string().optional(),
122
122
  }),
123
- ]) as z.ZodType<VistaToolResult>;
123
+ ]);
124
124
 
125
125
  /**
126
126
  * Perform a relayed Vista tool call against a mounted panel's controller.
@@ -151,7 +151,7 @@ export function dispatchVistaTool(
151
151
  const { tabId, ...patch } = parsed.data;
152
152
  const refusal = refusalFor(controller, tabId);
153
153
  if (refusal !== null) return refusal;
154
- if (!controller.update(tabId, patch as VistaSurfacePatch)) {
154
+ if (!controller.update(tabId, patch)) {
155
155
  // The tab is listed but not opened-tab-owned: it is a HOST tab, and a
156
156
  // patch to it would be overwritten by the host's next reconcile.
157
157
  return {
@@ -1,3 +0,0 @@
1
- export declare function unwrapList<T>(value: unknown): T[];
2
- export declare function unwrapData<T>(value: unknown): T;
3
- //# sourceMappingURL=response-envelope.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"response-envelope.d.ts","sourceRoot":"","sources":["../../../src/lib/biome-host/response-envelope.ts"],"names":[],"mappings":"AA+BA,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,EAAE,CAYjD;AAeD,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAU/C"}
@@ -1,21 +0,0 @@
1
- export function unwrapList(value) {
2
- if (Array.isArray(value)) {
3
- return value;
4
- }
5
- if (value !== null &&
6
- typeof value === 'object' &&
7
- Array.isArray(value.data)) {
8
- return value.data;
9
- }
10
- return [];
11
- }
12
- export function unwrapData(value) {
13
- if (value !== null &&
14
- typeof value === 'object' &&
15
- 'data' in value &&
16
- !('pagination' in value)) {
17
- return value.data;
18
- }
19
- return value;
20
- }
21
- //# sourceMappingURL=response-envelope.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"response-envelope.js","sourceRoot":"","sources":["../../../src/lib/biome-host/response-envelope.ts"],"names":[],"mappings":"AA+BA,MAAM,UAAU,UAAU,CAAI,KAAc;IAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAY,CAAC;IACtB,CAAC;IACD,IACE,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,CAAC,OAAO,CAAE,KAA4B,CAAC,IAAI,CAAC,EACjD,CAAC;QACD,OAAQ,KAAuB,CAAC,IAAI,CAAC;IACvC,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAeD,MAAM,UAAU,UAAU,CAAI,KAAc;IAC1C,IACE,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,MAAM,IAAK,KAAiC;QAC5C,CAAC,CAAC,YAAY,IAAK,KAAiC,CAAC,EACrD,CAAC;QACD,OAAQ,KAAqB,CAAC,IAAI,CAAC;IACrC,CAAC;IACD,OAAO,KAAU,CAAC;AACpB,CAAC"}
@@ -1,69 +0,0 @@
1
- /**
2
- * Frontend mirror of the backend `ResponseEnvelopeInterceptor`.
3
- *
4
- * Every 2xx body the platform returns is wrapped as `{ data: T }`, or
5
- * `{ data: T[], pagination }` for a paginated list (single source of truth:
6
- * `@xemahq/platform-common`'s `ResponseEnvelopeInterceptor`). Orval's
7
- * `custom-fetch` mutators usually peel that envelope at the HTTP boundary, but
8
- * spec drift (a controller typed `T[]` that emits `{ data }`), public clients
9
- * that DON'T peel, and transient partial responses leave a `.data`-wrapped or
10
- * mis-shaped value where biome code expects a bare value/array — and a raw
11
- * `.map` on it white-screens the route.
12
- *
13
- * These are the ONE shared, pure unwrap helpers — no host context, no fetch.
14
- * Biomes (and the host shell's own `unwrap-list.ts`) should adopt these instead
15
- * of re-implementing the guard. This is the shared helper only; adopters are
16
- * migrated incrementally, not in a blanket rewrite.
17
- */
18
-
19
- /**
20
- * Resilient list unwrap for DISPLAY surfaces — normalises a React-Query `.data`
21
- * to an array so the page renders its empty/error state instead of crashing:
22
- *
23
- * - already an array → returned as-is
24
- * - `{ data: T[] }` envelope → `value.data`
25
- * - anything else → `[]`
26
- *
27
- * Deliberately NON-throwing: the query's own `isError`/`isLoading` flags drive
28
- * the visible error/empty UI; this only guards the render path. For
29
- * mutation/single-resource flows where an unexpected shape is a real bug, use
30
- * {@link unwrapData} (fail-fast) instead.
31
- */
32
- export function unwrapList<T>(value: unknown): T[] {
33
- if (Array.isArray(value)) {
34
- return value as T[];
35
- }
36
- if (
37
- value !== null &&
38
- typeof value === 'object' &&
39
- Array.isArray((value as { data?: unknown }).data)
40
- ) {
41
- return (value as { data: T[] }).data;
42
- }
43
- return [];
44
- }
45
-
46
- /**
47
- * Fail-fast single-resource unwrap. Returns `value.data` when the value is a
48
- * `{ data }` envelope; returns the value unchanged when it is already the
49
- * unwrapped resource (an Orval client that peeled the envelope at the boundary).
50
- *
51
- * Use this on mutation / single-resource flows where the response SHOULD be a
52
- * concrete object — unlike {@link unwrapList}, it does not silently coerce, so
53
- * a genuinely-unexpected shape surfaces as the value rather than being masked.
54
- *
55
- * A paginated envelope (`{ data, pagination }`) is returned INTACT — callers
56
- * that need both fields read them off the returned object; peeling only `data`
57
- * would drop the pagination cursor.
58
- */
59
- export function unwrapData<T>(value: unknown): T {
60
- if (
61
- value !== null &&
62
- typeof value === 'object' &&
63
- 'data' in (value as Record<string, unknown>) &&
64
- !('pagination' in (value as Record<string, unknown>))
65
- ) {
66
- return (value as { data: T }).data;
67
- }
68
- return value as T;
69
- }