@xemahq/ui-kernel 0.9.1 → 0.10.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.
- package/README.md +2 -2
- package/dist/lib/biome-host/biome-builders.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-builders.js +3 -1
- package/dist/lib/biome-host/biome-builders.js.map +1 -1
- package/dist/lib/biome-host/biome-registry.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-registry.js.map +1 -1
- package/dist/lib/biome-host/biome-scope-hooks.d.ts +11 -0
- package/dist/lib/biome-host/biome-scope-hooks.d.ts.map +1 -0
- package/dist/lib/biome-host/biome-scope-hooks.js +25 -0
- package/dist/lib/biome-host/biome-scope-hooks.js.map +1 -0
- package/dist/lib/biome-host/biome-scope.d.ts +1 -10
- package/dist/lib/biome-host/biome-scope.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-scope.js +1 -24
- package/dist/lib/biome-host/biome-scope.js.map +1 -1
- package/dist/lib/biome-host/biome-scoped-query.d.ts +1 -1
- package/dist/lib/biome-host/biome-scoped-query.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-scoped-query.js +1 -1
- package/dist/lib/biome-host/biome-scoped-query.js.map +1 -1
- package/dist/lib/biome-host/create-biome-orval-config.js +2 -2
- package/dist/lib/biome-host/create-biome-orval-config.js.map +1 -1
- package/dist/lib/biome-host/errors.js.map +1 -1
- package/dist/lib/biome-host/index.d.ts +1 -2
- package/dist/lib/biome-host/index.d.ts.map +1 -1
- package/dist/lib/biome-host/index.js +1 -2
- package/dist/lib/biome-host/index.js.map +1 -1
- package/dist/lib/biome-host/session-contributions.d.ts +9 -4
- package/dist/lib/biome-host/session-contributions.d.ts.map +1 -1
- package/dist/lib/capabilities/capability-context.d.ts +9 -0
- package/dist/lib/capabilities/capability-context.d.ts.map +1 -0
- package/dist/lib/capabilities/capability-context.js +13 -0
- package/dist/lib/capabilities/capability-context.js.map +1 -0
- package/dist/lib/capabilities/capability-provider.d.ts +2 -8
- package/dist/lib/capabilities/capability-provider.d.ts.map +1 -1
- package/dist/lib/capabilities/capability-provider.js +1 -12
- package/dist/lib/capabilities/capability-provider.js.map +1 -1
- package/dist/lib/capabilities/index.d.ts +1 -0
- package/dist/lib/capabilities/index.d.ts.map +1 -1
- package/dist/lib/capabilities/index.js +1 -0
- package/dist/lib/capabilities/index.js.map +1 -1
- package/dist/lib/capabilities/use-capability.d.ts.map +1 -1
- package/dist/lib/capabilities/use-capability.js +1 -1
- package/dist/lib/capabilities/use-capability.js.map +1 -1
- package/dist/lib/system-bus/deeplink.js.map +1 -1
- package/dist/lib/system-bus/host-ports.d.ts +2 -1
- package/dist/lib/system-bus/host-ports.d.ts.map +1 -1
- package/dist/lib/system-bus/intent-registry.d.ts.map +1 -1
- package/dist/lib/system-bus/intent-registry.js.map +1 -1
- package/dist/offline/index.d.ts +2 -1
- package/dist/offline/index.d.ts.map +1 -1
- package/dist/offline/index.js +2 -1
- package/dist/offline/index.js.map +1 -1
- package/dist/offline/offline-status-badge.js +1 -1
- package/dist/offline/offline-status-badge.js.map +1 -1
- package/dist/offline/outbox.js.map +1 -1
- package/dist/offline/react-hooks.d.ts +7 -0
- package/dist/offline/react-hooks.d.ts.map +1 -0
- package/dist/offline/react-hooks.js +25 -0
- package/dist/offline/react-hooks.js.map +1 -0
- package/dist/offline/react.d.ts +0 -4
- package/dist/offline/react.d.ts.map +1 -1
- package/dist/offline/react.js +2 -24
- package/dist/offline/react.js.map +1 -1
- package/dist/offline/storage.d.ts.map +1 -1
- package/dist/offline/storage.js +8 -5
- package/dist/offline/storage.js.map +1 -1
- package/dist/registry/index.d.ts +1 -0
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +1 -0
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/lib/primitives/SessionEventCard.d.ts.map +1 -1
- package/dist/registry/lib/primitives/SessionEventCard.js +1 -1
- package/dist/registry/lib/primitives/SessionEventCard.js.map +1 -1
- package/dist/registry/lib/session-context-builder.d.ts +10 -2
- package/dist/registry/lib/session-context-builder.d.ts.map +1 -1
- package/dist/registry/lib/session-context-builder.js +14 -7
- package/dist/registry/lib/session-context-builder.js.map +1 -1
- package/dist/registry/lib/session-context-provider.d.ts +1 -3
- package/dist/registry/lib/session-context-provider.d.ts.map +1 -1
- package/dist/registry/lib/session-context-provider.js +2 -15
- package/dist/registry/lib/session-context-provider.js.map +1 -1
- package/dist/registry/lib/session-context.d.ts +5 -0
- package/dist/registry/lib/session-context.d.ts.map +1 -0
- package/dist/registry/lib/session-context.js +15 -0
- package/dist/registry/lib/session-context.js.map +1 -0
- package/dist/registry/lib/session-selectors.d.ts.map +1 -1
- package/dist/registry/lib/session-selectors.js +3 -1
- package/dist/registry/lib/session-selectors.js.map +1 -1
- package/dist/ui/branding/app-branding-context.d.ts +9 -0
- package/dist/ui/branding/app-branding-context.d.ts.map +1 -0
- package/dist/ui/branding/app-branding-context.js +10 -0
- package/dist/ui/branding/app-branding-context.js.map +1 -0
- package/dist/ui/branding/app-branding-provider.d.ts +0 -6
- package/dist/ui/branding/app-branding-provider.d.ts.map +1 -1
- package/dist/ui/branding/app-branding-provider.js +1 -8
- package/dist/ui/branding/app-branding-provider.js.map +1 -1
- package/dist/ui/capture/schema-field-input.js +1 -1
- package/dist/ui/capture/schema-field-input.js.map +1 -1
- package/dist/ui/capture/use-prefill.d.ts.map +1 -1
- package/dist/ui/capture/use-prefill.js +3 -1
- package/dist/ui/capture/use-prefill.js.map +1 -1
- package/dist/ui/capture/use-wizard.d.ts +1 -1
- package/dist/ui/capture/use-wizard.d.ts.map +1 -1
- package/dist/ui/capture/use-wizard.js +1 -1
- package/dist/ui/capture/use-wizard.js.map +1 -1
- package/dist/ui/capture/wizard.d.ts.map +1 -1
- package/dist/ui/capture/wizard.js.map +1 -1
- package/dist/ui/index.d.ts +5 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +5 -1
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/primitives/alert-dialog.js +1 -1
- package/dist/ui/primitives/alert-dialog.js.map +1 -1
- package/dist/ui/primitives/badge-variants.d.ts +4 -0
- package/dist/ui/primitives/badge-variants.d.ts.map +1 -0
- package/dist/ui/primitives/badge-variants.js +15 -0
- package/dist/ui/primitives/badge-variants.js.map +1 -0
- package/dist/ui/primitives/badge.d.ts +3 -5
- package/dist/ui/primitives/badge.d.ts.map +1 -1
- package/dist/ui/primitives/badge.js +2 -15
- package/dist/ui/primitives/badge.js.map +1 -1
- package/dist/ui/primitives/button-variants.d.ts +5 -0
- package/dist/ui/primitives/button-variants.d.ts.map +1 -0
- package/dist/ui/primitives/button-variants.js +24 -0
- package/dist/ui/primitives/button-variants.js.map +1 -0
- package/dist/ui/primitives/button.d.ts +3 -6
- package/dist/ui/primitives/button.d.ts.map +1 -1
- package/dist/ui/primitives/button.js +2 -24
- package/dist/ui/primitives/button.js.map +1 -1
- package/dist/ui/primitives/form-stepper.d.ts +1 -13
- package/dist/ui/primitives/form-stepper.d.ts.map +1 -1
- package/dist/ui/primitives/form-stepper.js +1 -6
- package/dist/ui/primitives/form-stepper.js.map +1 -1
- package/dist/ui/primitives/form-stepper.types.d.ts +14 -0
- package/dist/ui/primitives/form-stepper.types.d.ts.map +1 -0
- package/dist/ui/primitives/form-stepper.types.js +7 -0
- package/dist/ui/primitives/form-stepper.types.js.map +1 -0
- package/dist/ui/primitives/preview-device-frame.js +1 -1
- package/dist/ui/primitives/preview-device-frame.js.map +1 -1
- package/dist/ui/primitives/tag-multi-select.d.ts.map +1 -1
- package/dist/ui/primitives/tag-multi-select.js +1 -1
- package/dist/ui/primitives/tag-multi-select.js.map +1 -1
- package/dist/vista/index.d.ts +4 -0
- package/dist/vista/index.d.ts.map +1 -1
- package/dist/vista/index.js +4 -0
- package/dist/vista/index.js.map +1 -1
- package/dist/vista/surfaces/FilesSurface.d.ts +1 -12
- package/dist/vista/surfaces/FilesSurface.d.ts.map +1 -1
- package/dist/vista/surfaces/FilesSurface.js +2 -46
- package/dist/vista/surfaces/FilesSurface.js.map +1 -1
- package/dist/vista/surfaces/FormSurface.d.ts.map +1 -1
- package/dist/vista/surfaces/FormSurface.js +39 -12
- package/dist/vista/surfaces/FormSurface.js.map +1 -1
- package/dist/vista/surfaces/elicitation-transport.d.ts +12 -3
- package/dist/vista/surfaces/elicitation-transport.d.ts.map +1 -1
- package/dist/vista/surfaces/elicitation-transport.js +96 -3
- package/dist/vista/surfaces/elicitation-transport.js.map +1 -1
- package/dist/vista/surfaces/file-surface-utils.d.ts +13 -0
- package/dist/vista/surfaces/file-surface-utils.d.ts.map +1 -0
- package/dist/vista/surfaces/file-surface-utils.js +46 -0
- package/dist/vista/surfaces/file-surface-utils.js.map +1 -0
- package/dist/vista/surfaces/index.d.ts +4 -3
- package/dist/vista/surfaces/index.d.ts.map +1 -1
- package/dist/vista/surfaces/index.js +4 -81
- package/dist/vista/surfaces/index.js.map +1 -1
- package/dist/vista/surfaces/register-surfaces.d.ts +2 -0
- package/dist/vista/surfaces/register-surfaces.d.ts.map +1 -0
- package/dist/vista/surfaces/register-surfaces.js +80 -0
- package/dist/vista/surfaces/register-surfaces.js.map +1 -0
- package/dist/vista/surfaces/text-surfaces.js +1 -1
- package/dist/vista/surfaces/text-surfaces.js.map +1 -1
- package/dist/vista/vista-code-renderer-context.d.ts +9 -0
- package/dist/vista/vista-code-renderer-context.d.ts.map +1 -0
- package/dist/vista/vista-code-renderer-context.js +6 -0
- package/dist/vista/vista-code-renderer-context.js.map +1 -0
- package/dist/vista/vista-code-renderer.d.ts +1 -6
- package/dist/vista/vista-code-renderer.d.ts.map +1 -1
- package/dist/vista/vista-code-renderer.js +1 -5
- package/dist/vista/vista-code-renderer.js.map +1 -1
- package/dist/vista/vista-file-context.d.ts +8 -0
- package/dist/vista/vista-file-context.d.ts.map +1 -0
- package/dist/vista/vista-file-context.js +6 -0
- package/dist/vista/vista-file-context.js.map +1 -0
- package/dist/vista/vista-file-source.d.ts +1 -6
- package/dist/vista/vista-file-source.d.ts.map +1 -1
- package/dist/vista/vista-file-source.js +2 -5
- package/dist/vista/vista-file-source.js.map +1 -1
- package/dist/vista/vista-form-context.d.ts +13 -0
- package/dist/vista/vista-form-context.d.ts.map +1 -0
- package/dist/vista/vista-form-context.js +6 -0
- package/dist/vista/vista-form-context.js.map +1 -0
- package/dist/vista/vista-form-host.d.ts +1 -10
- package/dist/vista/vista-form-host.d.ts.map +1 -1
- package/dist/vista/vista-form-host.js +1 -5
- package/dist/vista/vista-form-host.js.map +1 -1
- package/dist/vista/vista-open-context.d.ts +1 -3
- package/dist/vista/vista-open-context.d.ts.map +1 -1
- package/dist/vista/vista-open-context.js +1 -5
- package/dist/vista/vista-open-context.js.map +1 -1
- package/dist/vista/vista-open-state.d.ts +5 -0
- package/dist/vista/vista-open-state.d.ts.map +1 -0
- package/dist/vista/vista-open-state.js +6 -0
- package/dist/vista/vista-open-state.js.map +1 -0
- package/dist/vista/vista-payloads.d.ts +2 -3
- package/dist/vista/vista-payloads.d.ts.map +1 -1
- package/dist/vista/vista-payloads.js +18 -21
- package/dist/vista/vista-payloads.js.map +1 -1
- package/dist/vista/vista-tools.d.ts.map +1 -1
- package/dist/vista/vista-tools.js.map +1 -1
- package/package.json +3 -3
- package/src/lib/biome-host/biome-builders.ts +4 -1
- package/src/lib/biome-host/biome-registry.ts +0 -1
- package/src/lib/biome-host/biome-scope-hooks.ts +39 -0
- package/src/lib/biome-host/biome-scope.tsx +1 -68
- package/src/lib/biome-host/biome-scoped-query.ts +4 -1
- package/src/lib/biome-host/create-biome-orval-config.ts +2 -2
- package/src/lib/biome-host/errors.ts +1 -1
- package/src/lib/biome-host/index.ts +1 -2
- package/src/lib/biome-host/session-contributions.ts +21 -18
- package/src/lib/capabilities/capability-context.ts +25 -0
- package/src/lib/capabilities/capability-provider.tsx +5 -34
- package/src/lib/capabilities/index.ts +1 -0
- package/src/lib/capabilities/use-capability.ts +4 -1
- package/src/lib/system-bus/deeplink.ts +1 -1
- package/src/lib/system-bus/host-ports.ts +2 -1
- package/src/lib/system-bus/intent-registry.ts +1 -2
- package/src/offline/index.ts +4 -2
- package/src/offline/offline-status-badge.tsx +1 -1
- package/src/offline/outbox.test.ts +23 -16
- package/src/offline/outbox.ts +1 -1
- package/src/offline/react-hooks.ts +37 -0
- package/src/offline/react.tsx +1 -40
- package/src/offline/storage.ts +11 -6
- package/src/registry/index.ts +1 -0
- package/src/registry/lib/primitives/SessionEventCard.tsx +4 -2
- package/src/registry/lib/session-context-builder.ts +33 -17
- package/src/registry/lib/session-context-provider.tsx +8 -25
- package/src/registry/lib/session-context.ts +21 -0
- package/src/registry/lib/session-selectors.ts +3 -1
- package/src/ui/branding/app-branding-context.ts +20 -0
- package/src/ui/branding/app-branding-provider.tsx +5 -27
- package/src/ui/capture/schema-field-input.tsx +7 -1
- package/src/ui/capture/use-prefill.ts +4 -1
- package/src/ui/capture/use-wizard.ts +2 -2
- package/src/ui/capture/wizard.tsx +2 -1
- package/src/ui/index.ts +7 -2
- package/src/ui/primitives/alert-dialog.tsx +1 -1
- package/src/ui/primitives/badge-variants.ts +21 -0
- package/src/ui/primitives/badge.tsx +3 -19
- package/src/ui/primitives/button-variants.ts +31 -0
- package/src/ui/primitives/button.tsx +3 -28
- package/src/ui/primitives/form-stepper.tsx +1 -16
- package/src/ui/primitives/form-stepper.types.ts +15 -0
- package/src/ui/primitives/preview-device-frame.tsx +1 -1
- package/src/ui/primitives/tag-multi-select.tsx +3 -4
- package/src/vista/form-payload.spec.ts +71 -25
- package/src/vista/index.ts +4 -0
- package/src/vista/surfaces/FilesSurface.tsx +2 -68
- package/src/vista/surfaces/FormSurface.tsx +125 -26
- package/src/vista/surfaces/elicitation-transport.spec.ts +205 -23
- package/src/vista/surfaces/elicitation-transport.ts +192 -14
- package/src/vista/surfaces/file-surface-utils.ts +62 -0
- package/src/vista/surfaces/index.ts +24 -0
- package/src/vista/surfaces/{index.tsx → register-surfaces.tsx} +1 -21
- package/src/vista/surfaces/text-surfaces.tsx +1 -1
- package/src/vista/vista-code-renderer-context.ts +16 -0
- package/src/vista/vista-code-renderer.tsx +4 -16
- package/src/vista/vista-file-context.ts +14 -0
- package/src/vista/vista-file-source.tsx +5 -28
- package/src/vista/vista-form-context.ts +20 -0
- package/src/vista/vista-form-host.tsx +11 -36
- package/src/vista/vista-open-context.tsx +4 -14
- package/src/vista/vista-open-state.ts +11 -0
- package/src/vista/vista-payloads.ts +44 -46
- package/src/vista/vista-tools.ts +2 -2
- package/dist/lib/biome-host/response-envelope.d.ts +0 -3
- package/dist/lib/biome-host/response-envelope.d.ts.map +0 -1
- package/dist/lib/biome-host/response-envelope.js +0 -21
- package/dist/lib/biome-host/response-envelope.js.map +0 -1
- package/dist/lib/biome-host/session-profiles.d.ts +0 -18
- package/dist/lib/biome-host/session-profiles.d.ts.map +0 -1
- package/dist/lib/biome-host/session-profiles.js +0 -35
- package/dist/lib/biome-host/session-profiles.js.map +0 -1
- package/src/lib/biome-host/response-envelope.ts +0 -69
- package/src/lib/biome-host/session-profiles.ts +0 -99
|
@@ -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))
|
|
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)
|
|
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
|
|
406
|
-
*
|
|
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
|
-
/**
|
|
410
|
-
readonly
|
|
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
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
458
|
-
if (submitUrl
|
|
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
|
-
|
|
475
|
-
if (
|
|
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 =
|
|
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,
|
|
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)
|
|
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
|
package/src/vista/vista-tools.ts
CHANGED
|
@@ -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
|
-
])
|
|
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
|
|
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 +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,18 +0,0 @@
|
|
|
1
|
-
export declare const SessionCapabilities: {
|
|
2
|
-
readonly HasGit: "hasGit";
|
|
3
|
-
readonly HasWorkspaceFiles: "hasWorkspaceFiles";
|
|
4
|
-
readonly SupportsKbPush: "supportsKbPush";
|
|
5
|
-
readonly HasArtifacts: "hasArtifacts";
|
|
6
|
-
readonly SupportsForking: "supportsForking";
|
|
7
|
-
readonly SupportsSharing: "supportsSharing";
|
|
8
|
-
};
|
|
9
|
-
export type SessionCapability = (typeof SessionCapabilities)[keyof typeof SessionCapabilities];
|
|
10
|
-
export interface SessionProfileDescriptor {
|
|
11
|
-
readonly key: string;
|
|
12
|
-
readonly biomeId: string;
|
|
13
|
-
readonly label: string;
|
|
14
|
-
readonly description?: string;
|
|
15
|
-
readonly capabilities: readonly string[];
|
|
16
|
-
}
|
|
17
|
-
export declare function useSessionProfileDescriptor(biomeId: string | undefined, profileKey: string | undefined): SessionProfileDescriptor;
|
|
18
|
-
//# sourceMappingURL=session-profiles.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-profiles.d.ts","sourceRoot":"","sources":["../../../src/lib/biome-host/session-profiles.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,mBAAmB;;;;;;;CAatB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAC3B,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,OAAO,mBAAmB,CAAC,CAAC;AAEjE,MAAM,WAAW,wBAAwB;IAKvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAcD,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,wBAAwB,CAqB1B"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import { biomeRegistry, useBiomeRegistryRevision } from './biome-registry';
|
|
3
|
-
export const SessionCapabilities = {
|
|
4
|
-
HasGit: 'hasGit',
|
|
5
|
-
HasWorkspaceFiles: 'hasWorkspaceFiles',
|
|
6
|
-
SupportsKbPush: 'supportsKbPush',
|
|
7
|
-
HasArtifacts: 'hasArtifacts',
|
|
8
|
-
SupportsForking: 'supportsForking',
|
|
9
|
-
SupportsSharing: 'supportsSharing',
|
|
10
|
-
};
|
|
11
|
-
export function useSessionProfileDescriptor(biomeId, profileKey) {
|
|
12
|
-
const revision = useBiomeRegistryRevision();
|
|
13
|
-
return useMemo(() => {
|
|
14
|
-
const fallback = {
|
|
15
|
-
key: profileKey ?? 'unknown',
|
|
16
|
-
biomeId: biomeId ?? 'unknown',
|
|
17
|
-
label: profileKey ?? 'Unknown profile',
|
|
18
|
-
capabilities: [],
|
|
19
|
-
};
|
|
20
|
-
if (!profileKey)
|
|
21
|
-
return fallback;
|
|
22
|
-
let crossPluginMatch;
|
|
23
|
-
for (const biome of biomeRegistry.list()) {
|
|
24
|
-
for (const profile of biome.session?.profiles ?? []) {
|
|
25
|
-
if (profile.key !== profileKey)
|
|
26
|
-
continue;
|
|
27
|
-
if (biomeId != null && profile.biomeId === biomeId)
|
|
28
|
-
return profile;
|
|
29
|
-
crossPluginMatch ??= profile;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return crossPluginMatch ?? fallback;
|
|
33
|
-
}, [revision, biomeId, profileKey]);
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=session-profiles.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-profiles.js","sourceRoot":"","sources":["../../../src/lib/biome-host/session-profiles.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAU3E,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAEjC,MAAM,EAAE,QAAQ;IAEhB,iBAAiB,EAAE,mBAAmB;IAEtC,cAAc,EAAE,gBAAgB;IAEhC,YAAY,EAAE,cAAc;IAE5B,eAAe,EAAE,iBAAiB;IAElC,eAAe,EAAE,iBAAiB;CAC1B,CAAC;AAgCX,MAAM,UAAU,2BAA2B,CACzC,OAA2B,EAC3B,UAA8B;IAE9B,MAAM,QAAQ,GAAG,wBAAwB,EAAE,CAAC;IAC5C,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,MAAM,QAAQ,GAA6B;YACzC,GAAG,EAAE,UAAU,IAAI,SAAS;YAC5B,OAAO,EAAE,OAAO,IAAI,SAAS;YAC7B,KAAK,EAAE,UAAU,IAAI,iBAAiB;YACtC,YAAY,EAAE,EAAE;SACjB,CAAC;QACF,IAAI,CAAC,UAAU;YAAE,OAAO,QAAQ,CAAC;QACjC,IAAI,gBAAsD,CAAC;QAC3D,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;YACzC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,CAAC;gBACpD,IAAI,OAAO,CAAC,GAAG,KAAK,UAAU;oBAAE,SAAS;gBACzC,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO;oBAAE,OAAO,OAAO,CAAC;gBACnE,gBAAgB,KAAK,OAAO,CAAC;YAC/B,CAAC;QACH,CAAC;QACD,OAAO,gBAAgB,IAAI,QAAQ,CAAC;IAEtC,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;AACtC,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
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session profile descriptors — coarse capability flags that gate which
|
|
3
|
-
* UI surfaces a session shows. A profile is owned by exactly one biome
|
|
4
|
-
* (matched by `(biomeId, key)`) and declares a set of namespaced
|
|
5
|
-
* capability strings the host fans out as `SessionContext.capabilities`.
|
|
6
|
-
*
|
|
7
|
-
* Biomes consume capabilities through each contribution's `appliesTo`
|
|
8
|
-
* predicate — the host shell itself never branches on a capability
|
|
9
|
-
* string. This keeps the host neutral; a session that doesn't declare
|
|
10
|
-
* `hasGit` simply gets no git-touching contributions because every git
|
|
11
|
-
* contribution gates on `ctx.capabilities.has('hasGit')`.
|
|
12
|
-
*
|
|
13
|
-
* Capability namespacing: well-known capabilities are documented here as
|
|
14
|
-
* constants so first-party biomes agree on a vocabulary; third-party
|
|
15
|
-
* biomes MUST namespace their own capabilities (`<biome-id>:<flag>`)
|
|
16
|
-
* to avoid collisions.
|
|
17
|
-
*/
|
|
18
|
-
import { useMemo } from 'react';
|
|
19
|
-
|
|
20
|
-
import { biomeRegistry, useBiomeRegistryRevision } from './biome-registry';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Well-known capability flags first-party biomes share. Third-party
|
|
24
|
-
* biomes SHOULD prefer namespacing their own (`<biome-id>:<flag>`).
|
|
25
|
-
*
|
|
26
|
-
* Adding a constant here is a contract-stability statement — it
|
|
27
|
-
* documents a flag enough first-party biomes use that we want a stable
|
|
28
|
-
* spelling. Removing one is a breaking change.
|
|
29
|
-
*/
|
|
30
|
-
export const SessionCapabilities = {
|
|
31
|
-
/** Session backs a git workspace; branches, commits, push, PR. */
|
|
32
|
-
HasGit: 'hasGit',
|
|
33
|
-
/** Session emits workspace file mutations (created/edited/deleted). */
|
|
34
|
-
HasWorkspaceFiles: 'hasWorkspaceFiles',
|
|
35
|
-
/** Session can publish artefacts back to the knowledge base. */
|
|
36
|
-
SupportsKbPush: 'supportsKbPush',
|
|
37
|
-
/** Session can open / render in-workspace artefacts (apps, docs). */
|
|
38
|
-
HasArtifacts: 'hasArtifacts',
|
|
39
|
-
/** Session can fork to a new branch. */
|
|
40
|
-
SupportsForking: 'supportsForking',
|
|
41
|
-
/** Session can share its output (deliverable) to other surfaces. */
|
|
42
|
-
SupportsSharing: 'supportsSharing',
|
|
43
|
-
} as const;
|
|
44
|
-
|
|
45
|
-
export type SessionCapability =
|
|
46
|
-
(typeof SessionCapabilities)[keyof typeof SessionCapabilities];
|
|
47
|
-
|
|
48
|
-
export interface SessionProfileDescriptor {
|
|
49
|
-
/**
|
|
50
|
-
* Stable profile key — matches the backend's `Session.profileKey`
|
|
51
|
-
* (or the session manifest slug for newer profiles).
|
|
52
|
-
*/
|
|
53
|
-
readonly key: string;
|
|
54
|
-
/** Biome that owns this profile. */
|
|
55
|
-
readonly biomeId: string;
|
|
56
|
-
/** Displayed label. */
|
|
57
|
-
readonly label: string;
|
|
58
|
-
readonly description?: string;
|
|
59
|
-
/** Capability flags the host fans out as `SessionContext.capabilities`. */
|
|
60
|
-
readonly capabilities: readonly string[];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Hook returning the descriptor that matches a session's `(biomeId,
|
|
65
|
-
* profileKey)`. Falls back to a synthetic descriptor with the well-known
|
|
66
|
-
* core capabilities when no biome owns the profile — that's how
|
|
67
|
-
* sessions started before any biome loaded still get usable defaults
|
|
68
|
-
* (today's behaviour).
|
|
69
|
-
*
|
|
70
|
-
* Resolution order:
|
|
71
|
-
* 1. Exact match on `(biomeId, key)`.
|
|
72
|
-
* 2. Exact match on `key` alone (cross-biome profile name).
|
|
73
|
-
* 3. Synthetic fallback (`unknown` biome, empty capabilities).
|
|
74
|
-
*/
|
|
75
|
-
export function useSessionProfileDescriptor(
|
|
76
|
-
biomeId: string | undefined,
|
|
77
|
-
profileKey: string | undefined,
|
|
78
|
-
): SessionProfileDescriptor {
|
|
79
|
-
const revision = useBiomeRegistryRevision();
|
|
80
|
-
return useMemo(() => {
|
|
81
|
-
const fallback: SessionProfileDescriptor = {
|
|
82
|
-
key: profileKey ?? 'unknown',
|
|
83
|
-
biomeId: biomeId ?? 'unknown',
|
|
84
|
-
label: profileKey ?? 'Unknown profile',
|
|
85
|
-
capabilities: [],
|
|
86
|
-
};
|
|
87
|
-
if (!profileKey) return fallback;
|
|
88
|
-
let crossPluginMatch: SessionProfileDescriptor | undefined;
|
|
89
|
-
for (const biome of biomeRegistry.list()) {
|
|
90
|
-
for (const profile of biome.session?.profiles ?? []) {
|
|
91
|
-
if (profile.key !== profileKey) continue;
|
|
92
|
-
if (biomeId != null && profile.biomeId === biomeId) return profile;
|
|
93
|
-
crossPluginMatch ??= profile;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return crossPluginMatch ?? fallback;
|
|
97
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
98
|
-
}, [revision, biomeId, profileKey]);
|
|
99
|
-
}
|