@happyvertical/smrt-svelte 0.53.2 → 0.53.4

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 (43) hide show
  1. package/AGENTS.md +4 -1
  2. package/README.md +2 -0
  3. package/agents/i18n.md +3 -0
  4. package/agents/workspace.md +29 -0
  5. package/dist/components/app/AppShell.svelte +149 -0
  6. package/dist/components/app/AppShell.svelte.d.ts +53 -0
  7. package/dist/components/app/AppShell.svelte.d.ts.map +1 -0
  8. package/dist/components/app/OwnerSetupForm.svelte +89 -0
  9. package/dist/components/app/OwnerSetupForm.svelte.d.ts +22 -0
  10. package/dist/components/app/OwnerSetupForm.svelte.d.ts.map +1 -0
  11. package/dist/components/app/RuntimeDiagnosticsWebMcp.svelte +18 -0
  12. package/dist/components/app/RuntimeDiagnosticsWebMcp.svelte.d.ts +10 -0
  13. package/dist/components/app/RuntimeDiagnosticsWebMcp.svelte.d.ts.map +1 -0
  14. package/dist/components/app/ShellSettingsPage.svelte +32 -0
  15. package/dist/components/app/ShellSettingsPage.svelte.d.ts +19 -0
  16. package/dist/components/app/ShellSettingsPage.svelte.d.ts.map +1 -0
  17. package/dist/components/app/index.d.ts +14 -0
  18. package/dist/components/app/index.d.ts.map +1 -0
  19. package/dist/components/app/index.js +12 -0
  20. package/dist/components/app/owner-setup-types.d.ts +14 -0
  21. package/dist/components/app/owner-setup-types.d.ts.map +1 -0
  22. package/dist/components/app/owner-setup-types.js +1 -0
  23. package/dist/components/app/runtime-diagnostics-webmcp.d.ts +33 -0
  24. package/dist/components/app/runtime-diagnostics-webmcp.d.ts.map +1 -0
  25. package/dist/components/app/runtime-diagnostics-webmcp.js +68 -0
  26. package/dist/i18n/server.d.ts +1 -0
  27. package/dist/i18n/server.d.ts.map +1 -1
  28. package/dist/i18n/server.js +1 -0
  29. package/dist/i18n/strings.workspace.d.ts +11 -0
  30. package/dist/i18n/strings.workspace.d.ts.map +1 -1
  31. package/dist/i18n/strings.workspace.js +12 -0
  32. package/dist/mcp-apps/McpAppsBridge.svelte +123 -0
  33. package/dist/mcp-apps/McpAppsBridge.svelte.d.ts +38 -0
  34. package/dist/mcp-apps/McpAppsBridge.svelte.d.ts.map +1 -0
  35. package/dist/mcp-apps/index.d.ts +1 -0
  36. package/dist/mcp-apps/index.d.ts.map +1 -1
  37. package/dist/mcp-apps/index.js +1 -0
  38. package/dist/mcp-apps/mcp-apps.svelte.d.ts.map +1 -1
  39. package/dist/mcp-apps/mcp-apps.svelte.js +10 -1
  40. package/dist/mcp-apps/strings.d.ts +7 -0
  41. package/dist/mcp-apps/strings.d.ts.map +1 -0
  42. package/dist/mcp-apps/strings.js +7 -0
  43. package/package.json +25 -14
package/AGENTS.md CHANGED
@@ -14,6 +14,7 @@ subpath you are editing. This file keeps what holds in every module.
14
14
  | `src/themes/` + `src/theme/` | which theme system is canonical and the full `--smrt-*` design-token vocabulary with its alias rules | [agents/themes.md](agents/themes.md) |
15
15
  | `src/test-support/` + `__tests__/` | the golden-test harness and pattern for Svelte component tests | [agents/testing.md](agents/testing.md) |
16
16
  | `src/components/settings/` (`./settings`) | `SettingsCatalog`, `paginateSettingsCatalog`, and the summary-vs-detail scalability contract | [agents/settings.md](agents/settings.md) |
17
+ | `src/components/app/` (`./app`) | `AppShell` (Provider + ThemeProvider + theme CSS + AdminShell + nav/dock slots), `OwnerSetupForm` (props-driven first-run owner form), `ShellSettingsPage`, `RuntimeDiagnosticsWebMcp`. Browser-only; no `$app/*` or server imports | [agents/workspace.md](agents/workspace.md#app-shell-and-owner-setup-app) |
17
18
  | `src/components/workspace/` (`./workspace` + `./web`) | the AdminShell family and its principles, the legacy ToolsDock surface, the `./web` activity-feed and `updateAvailable` adapters, and server-side dock gates | [agents/workspace.md](agents/workspace.md) |
18
19
  | `src/web/remote-query.svelte.ts` | Svelte 5 binding for query-shaped remote pages: rows, page, totals, loading/refreshing/stale/error, retry, last-updated, and query-scoped live subscriptions (#2445) | — |
19
20
  | `src/web/list-data-surface.svelte.ts` (`mountListDataSurface`) | One-call registration of an existing, non-`DataTable` list (already mirroring a headless `DataTableController`) as a mounted `DataSurfaceDescriptor` — a same-behavior port of `registerContentListDataSurface`'s registration/translation logic (`@happyvertical/smrt-content/svelte`), generalized off ContentList's view-mode concept, so any custom list markup can adopt it directly instead of hand-mirroring the registry contract. Not yet unified behind a shared `@happyvertical/smrt-ui/data` implementation (#2917) — this copy is currently ahead; see its own module doc comment for the current, authoritative list of divergences #2917 must adopt rather than assume parity (#2906) | — |
@@ -44,7 +45,9 @@ versioned normalizers and the conformance fixture together.
44
45
  The explicit `./mcp-apps` subpath owns portable MCP Apps mount/dispose bindings.
45
46
  It reuses `compileViewIntentToolSpec` for local registry interactions, never
46
47
  advertises browser closures as remote tools, and does not use
47
- `document.modelContext`. See [bridge contract](../mcp-apps/README.md). Its browser
48
+ `document.modelContext`. `McpAppsBridge` is the shipped view shell: portable
49
+ display-mode request only when the host advertises it, otherwise inline status;
50
+ no OpenAI helpers. See [bridge contract](../mcp-apps/README.md). Its browser
48
51
  gate is `e2e/mcp-apps.spec.ts`, including trusted human staged-review enforcement.
49
52
 
50
53
  ## The UI split — primitive-adoption contract (#1589)
package/README.md CHANGED
@@ -505,6 +505,8 @@ importable, even if it appears in `dist/`.
505
505
  | `@happyvertical/smrt-svelte/forms` | Form inputs (TextInput, Select, MoneyInput, DateTimeInput, Toggle, etc.) |
506
506
  | `@happyvertical/smrt-svelte/settings` | Server-paged settings search, selection, and list/detail layout (`SettingsCatalog`, `paginateSettingsCatalog`) |
507
507
  | `@happyvertical/smrt-svelte/workspace` | AdminShell, ShellState, tenant nav, focus tools, settings, activities, and system/app panels |
508
+ | `@happyvertical/smrt-svelte/app` | `AppShell` (Provider + themes + AdminShell + nav/dock slots), `OwnerSetupForm` (first-run owner setup), `ShellSettingsPage`, `RuntimeDiagnosticsWebMcp` |
509
+ | `@happyvertical/smrt-svelte/app/runtime-diagnostics` | Svelte-free diagnostics WebMCP registration and its tool name/endpoint constants, importable from server routes |
508
510
  | `@happyvertical/smrt-svelte/workspace/legacy` | Opt-in ToolsDock compatibility surface for applications migrating to AdminShell |
509
511
  | `@happyvertical/smrt-svelte/workspace/server` | Server-side workspace helpers (Node only) |
510
512
  | `@happyvertical/smrt-svelte/workspace/live` | `systemFeed` — the AdminShell system scope (jobs/schedules/dispatch) polled from an app status endpoint; deliberately carries no `smrt-web` dependency |
package/agents/i18n.md CHANGED
@@ -30,6 +30,9 @@ languages root is imported only by the Node-only `/i18n/server` subpath. See
30
30
  — a consumer's load function calls it for the request locale and passes the
31
31
  result to `<Provider>`. It seeds the languages registry from `defineMessages`
32
32
  defaults, then resolves each key through the override/tenant/locale chain.
33
+ `server.ts` side-effect-imports every shipped catalog (including
34
+ `mcp-apps/strings.ts`) so its keys resolve even when the components are
35
+ never imported server-side; add new catalogs there.
33
36
  - Enforcement: `scripts/check-hardcoded-strings.mjs` (`pnpm
34
37
  check:hardcoded-strings`) flags hardcoded prose in `.svelte` markup —
35
38
  report-only until a package's extraction completes, then add it to the
@@ -149,3 +149,32 @@ failure; a context change or later successful refresh clears the signal, and
149
149
  success applies the new snapshot.
150
150
  Availability is never an authorization boundary—server operations must still
151
151
  enforce permissions.
152
+
153
+ ## App shell and owner setup (`./app`)
154
+
155
+ `@happyvertical/smrt-svelte/app` (`src/components/app/`) is browser-only. It
156
+ lives beside, not inside, `./workspace` so the AdminShell barrel stays free of
157
+ `Provider` and its tests.
158
+
159
+ - `AppShell` composes `Provider` (`webmcp`, `user`, `permissions` pass through
160
+ unchanged), `ThemeProvider`, the theme CSS (`themes/styles/{all,fonts}.css`
161
+ are imported by the component — forgetting them leaves `--smrt-*` unresolved),
162
+ `AdminShell`, `TenantNav` from the consumer's `nav`/`navGroups`/`currentHref`,
163
+ and an `AppScopePanel`. Panels start collapsed as in `AdminShell`; pass
164
+ `config` to change that. `dock` is a snippet rendered inside the shell: a host
165
+ places its assistant there in a `ShellDockTool`, so this package never
166
+ imports `smrt-chat`. `runtimeDiagnostics` (default false) mounts the
167
+ read-only `smrt.runtime.diagnostics.read` WebMCP tool. Server code that
168
+ lists that tool (the diagnostics route's `toolNames`) imports
169
+ `RUNTIME_DIAGNOSTICS_WEBMCP_TOOL_NAME` from `./app/runtime-diagnostics`,
170
+ which is plain TypeScript; the `./app` barrel loads Svelte components and
171
+ theme CSS.
172
+ - `OwnerSetupForm` is props-driven and imports nothing server-side. Contract
173
+ (lane 3369 server): `default` form action; fields `token` (hidden), `name`,
174
+ `email`, optional `tenantName` (`askTenantName`); `load` data
175
+ `{ available, token }` (`available: false` renders a neutral unavailable
176
+ state); failures `fail(status, { code, message })`, `message` shown as given
177
+ and never branched on. Pass `data` and `form` straight from the route. The
178
+ form is a plain `method="POST"`; pass `enhance` from `$app/forms` to enhance
179
+ it. The token is a hidden field only and is never stored, logged or shown.
180
+ Single-use, loopback-only enforcement stays server-side.
@@ -0,0 +1,149 @@
1
+ <script lang="ts">
2
+ import {
3
+ type ColorScheme,
4
+ type ThemePreset,
5
+ ThemeProvider,
6
+ } from '@happyvertical/smrt-ui/themes';
7
+ import '@happyvertical/smrt-ui/themes/styles/all.css';
8
+ import '@happyvertical/smrt-ui/themes/styles/fonts.css';
9
+ import { useI18n } from '@happyvertical/smrt-ui/i18n';
10
+ import type { Snippet } from 'svelte';
11
+ import { M } from '../../i18n/strings.workspace.js';
12
+ import Provider from '../../Provider.svelte';
13
+ import type { User } from '../../state/app-state.js';
14
+ import type { WebMcpProviderConfig } from '../../web/webmcp-provider.js';
15
+ import AdminShell from '../workspace/admin-shell/AdminShell.svelte';
16
+ import AppScopePanel from '../workspace/admin-shell/AppScopePanel.svelte';
17
+ import TenantNav from '../workspace/admin-shell/TenantNav.svelte';
18
+ import type {
19
+ ShellNavGroup,
20
+ ShellNavItem,
21
+ ShellPanelDefaults,
22
+ } from '../workspace/admin-shell/types.js';
23
+ import RuntimeDiagnosticsWebMcp from './RuntimeDiagnosticsWebMcp.svelte';
24
+
25
+ interface Props {
26
+ /** Application name shown in the shell brand and app panel. */
27
+ title?: string;
28
+ /** Secondary line under the application name in the shell brand. */
29
+ subtitle?: string;
30
+ /** localStorage key for the user's shell layout preferences. */
31
+ storageKey?: string;
32
+ /** Navigation rendered in the tenant (left) panel. */
33
+ nav?: ShellNavItem[];
34
+ /** Grouped navigation sections rendered below the flat `nav` items. */
35
+ navGroups?: ShellNavGroup[];
36
+ /** Current path, used to highlight the active link (e.g. `page.url.pathname`). */
37
+ currentHref?: string;
38
+ /** Tenant label shown in the app panel. */
39
+ tenantLabel?: string;
40
+ /** Environment badge text (e.g. `local`). */
41
+ environment?: string;
42
+ /** When set, the app panel links here (e.g. a settings route). */
43
+ settingsHref?: string;
44
+ /** Options for the Provider's WebMCP integration; passed through unchanged. */
45
+ webmcp?: boolean | WebMcpProviderConfig;
46
+ /** Authenticated user forwarded to the Provider; `null` renders the shell signed out. */
47
+ user?: User | null;
48
+ /** The user's resolved permission slugs, forwarded to the Provider for permission-gated UI. */
49
+ permissions?: string[];
50
+ /** Register the read-only runtime diagnostics WebMCP tool. */
51
+ runtimeDiagnostics?: boolean;
52
+ /** Initial panel states and presentation; forwarded to AdminShell. */
53
+ config?: ShellPanelDefaults;
54
+ /** Theme preset applied by the ThemeProvider. */
55
+ preset?: ThemePreset;
56
+ /** Light, dark or system color scheme; the user's persisted choice wins. */
57
+ colorScheme?: ColorScheme;
58
+ /** Extra app-panel content (e.g. selected-tenant notes). */
59
+ appPanelDocs?: Snippet;
60
+ /**
61
+ * Dock slot, rendered inside the shell so a host can place an assistant in
62
+ * a `ShellDockTool` without this package depending on it.
63
+ */
64
+ dock?: Snippet;
65
+ children: Snippet;
66
+ }
67
+
68
+ let {
69
+ title = 'SMRT',
70
+ subtitle,
71
+ storageKey = 'smrt-app-shell',
72
+ nav = [],
73
+ navGroups = [],
74
+ currentHref = '',
75
+ tenantLabel = '',
76
+ environment = 'local',
77
+ settingsHref,
78
+ webmcp = false,
79
+ user = null,
80
+ permissions = [],
81
+ runtimeDiagnostics = false,
82
+ config,
83
+ preset = 'smrt',
84
+ colorScheme = 'system',
85
+ appPanelDocs,
86
+ dock,
87
+ children,
88
+ }: Props = $props();
89
+ const { t } = useI18n();
90
+ const hasNav = $derived(nav.length > 0 || navGroups.length > 0);
91
+ </script>
92
+
93
+ <Provider {webmcp} {user} {permissions}>
94
+ <RuntimeDiagnosticsWebMcp enabled={runtimeDiagnostics} />
95
+ <ThemeProvider {preset} {colorScheme} persist={true}>
96
+ <AdminShell {title} {subtitle} {storageKey} {config} path={currentHref}>
97
+ {#snippet appPanel()}
98
+ <AppScopePanel
99
+ appName={title}
100
+ tenantName={tenantLabel}
101
+ {environment}
102
+ showSettings={false}
103
+ >
104
+ {#snippet docs()}
105
+ {@render appPanelDocs?.()}
106
+ {#if settingsHref}
107
+ <a href={settingsHref}>{t(M['ui.app_shell.settings_link'])}</a>
108
+ {/if}
109
+ {/snippet}
110
+ </AppScopePanel>
111
+ {/snippet}
112
+
113
+ {#snippet tenantPanel()}
114
+ {#if hasNav}
115
+ <TenantNav
116
+ items={nav}
117
+ groups={navGroups}
118
+ {currentHref}
119
+ aria-label={t(M['ui.app_shell.navigation'])}
120
+ />
121
+ {/if}
122
+ {/snippet}
123
+
124
+ {@render dock?.()}
125
+ {@render children()}
126
+ </AdminShell>
127
+ </ThemeProvider>
128
+ </Provider>
129
+
130
+ <style>
131
+ :global(*),
132
+ :global(*::before),
133
+ :global(*::after) {
134
+ box-sizing: border-box;
135
+ }
136
+ :global(html),
137
+ :global(body) {
138
+ min-height: 100%;
139
+ margin: 0;
140
+ }
141
+ :global(body) {
142
+ background: var(--smrt-color-background);
143
+ color: var(--smrt-color-on-background);
144
+ font-family: var(--smrt-font-family, Inter, system-ui, sans-serif);
145
+ }
146
+ a {
147
+ color: var(--smrt-color-primary);
148
+ }
149
+ </style>
@@ -0,0 +1,53 @@
1
+ import { type ColorScheme, type ThemePreset } from '@happyvertical/smrt-ui/themes';
2
+ import '@happyvertical/smrt-ui/themes/styles/all.css';
3
+ import '@happyvertical/smrt-ui/themes/styles/fonts.css';
4
+ import type { Snippet } from 'svelte';
5
+ import type { User } from '../../state/app-state.js';
6
+ import type { WebMcpProviderConfig } from '../../web/webmcp-provider.js';
7
+ import type { ShellNavGroup, ShellNavItem, ShellPanelDefaults } from '../workspace/admin-shell/types.js';
8
+ interface Props {
9
+ /** Application name shown in the shell brand and app panel. */
10
+ title?: string;
11
+ /** Secondary line under the application name in the shell brand. */
12
+ subtitle?: string;
13
+ /** localStorage key for the user's shell layout preferences. */
14
+ storageKey?: string;
15
+ /** Navigation rendered in the tenant (left) panel. */
16
+ nav?: ShellNavItem[];
17
+ /** Grouped navigation sections rendered below the flat `nav` items. */
18
+ navGroups?: ShellNavGroup[];
19
+ /** Current path, used to highlight the active link (e.g. `page.url.pathname`). */
20
+ currentHref?: string;
21
+ /** Tenant label shown in the app panel. */
22
+ tenantLabel?: string;
23
+ /** Environment badge text (e.g. `local`). */
24
+ environment?: string;
25
+ /** When set, the app panel links here (e.g. a settings route). */
26
+ settingsHref?: string;
27
+ /** Options for the Provider's WebMCP integration; passed through unchanged. */
28
+ webmcp?: boolean | WebMcpProviderConfig;
29
+ /** Authenticated user forwarded to the Provider; `null` renders the shell signed out. */
30
+ user?: User | null;
31
+ /** The user's resolved permission slugs, forwarded to the Provider for permission-gated UI. */
32
+ permissions?: string[];
33
+ /** Register the read-only runtime diagnostics WebMCP tool. */
34
+ runtimeDiagnostics?: boolean;
35
+ /** Initial panel states and presentation; forwarded to AdminShell. */
36
+ config?: ShellPanelDefaults;
37
+ /** Theme preset applied by the ThemeProvider. */
38
+ preset?: ThemePreset;
39
+ /** Light, dark or system color scheme; the user's persisted choice wins. */
40
+ colorScheme?: ColorScheme;
41
+ /** Extra app-panel content (e.g. selected-tenant notes). */
42
+ appPanelDocs?: Snippet;
43
+ /**
44
+ * Dock slot, rendered inside the shell so a host can place an assistant in
45
+ * a `ShellDockTool` without this package depending on it.
46
+ */
47
+ dock?: Snippet;
48
+ children: Snippet;
49
+ }
50
+ declare const AppShell: import("svelte").Component<Props, {}, "">;
51
+ type AppShell = ReturnType<typeof AppShell>;
52
+ export default AppShell;
53
+ //# sourceMappingURL=AppShell.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppShell.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/app/AppShell.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,8CAA8C,CAAC;AACtD,OAAO,gDAAgD,CAAC;AAExD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAIzE,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EACnB,MAAM,mCAAmC,CAAC;AAI3C,UAAU,KAAK;IACb,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC;IACrB,uEAAuE;IACvE,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,GAAG,oBAAoB,CAAC;IACxC,yFAAyF;IACzF,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,+FAA+F;IAC/F,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sEAAsE;IACtE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,iDAAiD;IACjD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB;AA0ED,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,89 @@
1
+ <script lang="ts">
2
+ import { Input } from '@happyvertical/smrt-ui/forms';
3
+ import { useI18n } from '@happyvertical/smrt-ui/i18n';
4
+ import { Button } from '@happyvertical/smrt-ui/ui';
5
+ import { M } from '../../i18n/strings.workspace.js';
6
+ import type {
7
+ OwnerSetupData,
8
+ OwnerSetupFormResult,
9
+ } from './owner-setup-types.js';
10
+
11
+ interface Props {
12
+ /** The route's `load` data. The token is rendered only as a hidden field. */
13
+ data: OwnerSetupData;
14
+ /** The route's `form` prop (action failure data). */
15
+ form?: OwnerSetupFormResult | null;
16
+ /** Also ask for an optional workspace name (field `tenantName`). */
17
+ askTenantName?: boolean;
18
+ /** Form action URL; omit to post to the current route's default action. */
19
+ action?: string;
20
+ /**
21
+ * SvelteKit's `enhance` from `$app/forms`, for progressive enhancement.
22
+ * Optional: without it the form is a plain POST that works without JS.
23
+ */
24
+ enhance?: (form: HTMLFormElement) => { destroy?: () => void } | void;
25
+ }
26
+
27
+ let {
28
+ data,
29
+ form = null,
30
+ askTenantName = false,
31
+ action,
32
+ enhance,
33
+ }: Props = $props();
34
+ const { t } = useI18n();
35
+
36
+ function enhanceForm(form: HTMLFormElement) {
37
+ const handle = enhance?.(form);
38
+ return () => handle?.destroy?.();
39
+ }
40
+ </script>
41
+
42
+ <main class="smrt-owner-setup">
43
+ <h1>{t(M['ui.owner_setup.heading'])}</h1>
44
+ {#if !data.available}
45
+ <p data-owner-setup="unavailable">{t(M['ui.owner_setup.unavailable'])}</p>
46
+ {:else}
47
+ <p>{t(M['ui.owner_setup.intro'])}</p>
48
+ {#if form?.message}<p role="alert" data-owner-setup="error">{form.message}</p>{/if}
49
+ <!-- raw-primitive-allow: native POST form so owner setup works without JavaScript; the host's SvelteKit `enhance` is attached when available -->
50
+ <form method="POST" {action} {@attach enhanceForm}>
51
+ <!-- raw-primitive-allow: hidden, non-interactive carrier for the single-use bootstrap token -->
52
+ <input type="hidden" name="token" value={data.token} />
53
+ <label>
54
+ {t(M['ui.owner_setup.name'])}
55
+ <Input name="name" autocomplete="name" required />
56
+ </label>
57
+ <label>
58
+ {t(M['ui.owner_setup.email'])}
59
+ <Input name="email" type="email" autocomplete="email" required />
60
+ </label>
61
+ {#if askTenantName}
62
+ <label>
63
+ {t(M['ui.owner_setup.tenant_name'])}
64
+ <Input name="tenantName" autocomplete="organization" />
65
+ </label>
66
+ {/if}
67
+ <Button type="submit">{t(M['ui.owner_setup.submit'])}</Button>
68
+ </form>
69
+ {/if}
70
+ </main>
71
+
72
+ <style>
73
+ .smrt-owner-setup {
74
+ max-width: 36rem;
75
+ margin: 4rem auto;
76
+ padding: 1.5rem;
77
+ }
78
+ form {
79
+ display: grid;
80
+ gap: 1rem;
81
+ }
82
+ label {
83
+ display: grid;
84
+ gap: 0.35rem;
85
+ }
86
+ [role='alert'] {
87
+ color: var(--smrt-color-error, #b3261e);
88
+ }
89
+ </style>
@@ -0,0 +1,22 @@
1
+ import type { OwnerSetupData, OwnerSetupFormResult } from './owner-setup-types.js';
2
+ interface Props {
3
+ /** The route's `load` data. The token is rendered only as a hidden field. */
4
+ data: OwnerSetupData;
5
+ /** The route's `form` prop (action failure data). */
6
+ form?: OwnerSetupFormResult | null;
7
+ /** Also ask for an optional workspace name (field `tenantName`). */
8
+ askTenantName?: boolean;
9
+ /** Form action URL; omit to post to the current route's default action. */
10
+ action?: string;
11
+ /**
12
+ * SvelteKit's `enhance` from `$app/forms`, for progressive enhancement.
13
+ * Optional: without it the form is a plain POST that works without JS.
14
+ */
15
+ enhance?: (form: HTMLFormElement) => {
16
+ destroy?: () => void;
17
+ } | void;
18
+ }
19
+ declare const OwnerSetupForm: import("svelte").Component<Props, {}, "">;
20
+ type OwnerSetupForm = ReturnType<typeof OwnerSetupForm>;
21
+ export default OwnerSetupForm;
22
+ //# sourceMappingURL=OwnerSetupForm.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OwnerSetupForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/app/OwnerSetupForm.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAGhC,UAAU,KAAK;IACb,6EAA6E;IAC7E,IAAI,EAAE,cAAc,CAAC;IACrB,qDAAqD;IACrD,IAAI,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACnC,oEAAoE;IACpE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK;QAAE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;CACtE;AA0DD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ import { registerRuntimeDiagnosticsWebMcp } from './runtime-diagnostics-webmcp.js';
3
+
4
+ interface Props {
5
+ /** Register the read-only diagnostics tool while true. */
6
+ enabled?: boolean;
7
+ /** Same-origin diagnostics endpoint. */
8
+ endpoint?: string;
9
+ }
10
+
11
+ let { enabled = true, endpoint }: Props = $props();
12
+
13
+ $effect(() => {
14
+ if (!enabled) return;
15
+ const owner = registerRuntimeDiagnosticsWebMcp({ endpoint });
16
+ return () => owner?.dispose();
17
+ });
18
+ </script>
@@ -0,0 +1,10 @@
1
+ interface Props {
2
+ /** Register the read-only diagnostics tool while true. */
3
+ enabled?: boolean;
4
+ /** Same-origin diagnostics endpoint. */
5
+ endpoint?: string;
6
+ }
7
+ declare const RuntimeDiagnosticsWebMcp: import("svelte").Component<Props, {}, "">;
8
+ type RuntimeDiagnosticsWebMcp = ReturnType<typeof RuntimeDiagnosticsWebMcp>;
9
+ export default RuntimeDiagnosticsWebMcp;
10
+ //# sourceMappingURL=RuntimeDiagnosticsWebMcp.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RuntimeDiagnosticsWebMcp.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/app/RuntimeDiagnosticsWebMcp.svelte.ts"],"names":[],"mappings":"AAMA,UAAU,KAAK;IACb,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAgBD,QAAA,MAAM,wBAAwB,2CAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
@@ -0,0 +1,32 @@
1
+ <script lang="ts">
2
+ import { useI18n } from '@happyvertical/smrt-ui/i18n';
3
+ import { M } from '../../i18n/strings.workspace.js';
4
+ import ShellSettingsPanel from '../workspace/admin-shell/ShellSettingsPanel.svelte';
5
+
6
+ const { t } = useI18n();
7
+ </script>
8
+
9
+ <section class="smrt-shell-settings-page">
10
+ <header>
11
+ <h1>{t(M['ui.shell_settings_page.heading'])}</h1>
12
+ <p>{t(M['ui.shell_settings_page.description'])}</p>
13
+ </header>
14
+ <ShellSettingsPanel />
15
+ </section>
16
+
17
+ <style>
18
+ .smrt-shell-settings-page {
19
+ display: grid;
20
+ gap: var(--smrt-spacing-6, 1.5rem);
21
+ max-width: 720px;
22
+ padding: var(--smrt-spacing-8, 2rem);
23
+ }
24
+ header {
25
+ display: grid;
26
+ gap: var(--smrt-spacing-2, 0.5rem);
27
+ }
28
+ h1,
29
+ p {
30
+ margin: 0;
31
+ }
32
+ </style>
@@ -0,0 +1,19 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const ShellSettingsPage: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type ShellSettingsPage = InstanceType<typeof ShellSettingsPage>;
18
+ export default ShellSettingsPage;
19
+ //# sourceMappingURL=ShellSettingsPage.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShellSettingsPage.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/app/ShellSettingsPage.svelte.ts"],"names":[],"mappings":"AA2BA,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,iBAAiB;;kBAA+E,CAAC;AACrF,KAAK,iBAAiB,GAAG,YAAY,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAClE,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @happyvertical/smrt-svelte/app
3
+ *
4
+ * Packaged application shell and first-run owner setup UI. Browser-only: no
5
+ * server or `$app/*` imports. Pair with the server `load`/`actions` from
6
+ * `@happyvertical/smrt-app-runtime/sveltekit`.
7
+ */
8
+ export { default as AppShell } from './AppShell.svelte';
9
+ export { default as OwnerSetupForm } from './OwnerSetupForm.svelte';
10
+ export type { OwnerSetupData, OwnerSetupFormResult, } from './owner-setup-types.js';
11
+ export { default as RuntimeDiagnosticsWebMcp } from './RuntimeDiagnosticsWebMcp.svelte';
12
+ export { createRuntimeDiagnosticsWebMcpTool, type RegisterRuntimeDiagnosticsWebMcpOptions, RUNTIME_DIAGNOSTICS_ENDPOINT, RUNTIME_DIAGNOSTICS_WEBMCP_TOOL_NAME, type RuntimeDiagnosticsWebMcpOwner, registerRuntimeDiagnosticsWebMcp, } from './runtime-diagnostics-webmcp.js';
13
+ export { default as ShellSettingsPage } from './ShellSettingsPage.svelte';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/app/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,YAAY,EACV,cAAc,EACd,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EACL,kCAAkC,EAClC,KAAK,uCAAuC,EAC5C,4BAA4B,EAC5B,oCAAoC,EACpC,KAAK,6BAA6B,EAClC,gCAAgC,GACjC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @happyvertical/smrt-svelte/app
3
+ *
4
+ * Packaged application shell and first-run owner setup UI. Browser-only: no
5
+ * server or `$app/*` imports. Pair with the server `load`/`actions` from
6
+ * `@happyvertical/smrt-app-runtime/sveltekit`.
7
+ */
8
+ export { default as AppShell } from './AppShell.svelte';
9
+ export { default as OwnerSetupForm } from './OwnerSetupForm.svelte';
10
+ export { default as RuntimeDiagnosticsWebMcp } from './RuntimeDiagnosticsWebMcp.svelte';
11
+ export { createRuntimeDiagnosticsWebMcpTool, RUNTIME_DIAGNOSTICS_ENDPOINT, RUNTIME_DIAGNOSTICS_WEBMCP_TOOL_NAME, registerRuntimeDiagnosticsWebMcp, } from './runtime-diagnostics-webmcp.js';
12
+ export { default as ShellSettingsPage } from './ShellSettingsPage.svelte';
@@ -0,0 +1,14 @@
1
+ /** Shape of the setup route's `load` data. */
2
+ export interface OwnerSetupData {
3
+ /** False (with an empty token) when setup is not offered. */
4
+ available: boolean;
5
+ /** Single-use bootstrap token carried from the setup link. */
6
+ token: string;
7
+ }
8
+ /** Shape of the setup action's failure data (`fail(status, { code, message })`). */
9
+ export interface OwnerSetupFormResult {
10
+ code?: string;
11
+ /** Fixed server-provided text; displayed as given. */
12
+ message?: string;
13
+ }
14
+ //# sourceMappingURL=owner-setup-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-setup-types.d.ts","sourceRoot":"","sources":["../../../src/components/app/owner-setup-types.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAC;IACnB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,oFAAoF;AACpF,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ export declare const RUNTIME_DIAGNOSTICS_WEBMCP_TOOL_NAME = "smrt.runtime.diagnostics.read";
2
+ interface RuntimeDiagnosticsTool {
3
+ readonly name: string;
4
+ readonly description: string;
5
+ readonly inputSchema: Record<string, unknown>;
6
+ readonly annotations: {
7
+ readonly readOnlyHint: true;
8
+ readonly destructiveHint: false;
9
+ readonly idempotentHint: true;
10
+ readonly openWorldHint: false;
11
+ };
12
+ readonly execute: (args: Record<string, unknown>) => Promise<string>;
13
+ }
14
+ interface RuntimeDiagnosticsModelContext {
15
+ registerTool(tool: RuntimeDiagnosticsTool, options: {
16
+ signal: AbortSignal;
17
+ }): void | Promise<void>;
18
+ }
19
+ export interface RuntimeDiagnosticsWebMcpOwner {
20
+ readonly dispose: () => void;
21
+ }
22
+ export declare const RUNTIME_DIAGNOSTICS_ENDPOINT = "/api/_runtime/diagnostics";
23
+ export interface RegisterRuntimeDiagnosticsWebMcpOptions {
24
+ readonly fetchFn?: typeof fetch;
25
+ /** Same-origin diagnostics endpoint. Defaults to `/api/_runtime/diagnostics`. */
26
+ readonly endpoint?: string;
27
+ readonly modelContext?: RuntimeDiagnosticsModelContext;
28
+ }
29
+ /** Register exactly one page-user, read-only diagnostics tool for its owner. */
30
+ export declare function registerRuntimeDiagnosticsWebMcp(options?: RegisterRuntimeDiagnosticsWebMcpOptions): RuntimeDiagnosticsWebMcpOwner | null;
31
+ export declare function createRuntimeDiagnosticsWebMcpTool(fetchFn: typeof fetch, endpoint?: string): RuntimeDiagnosticsTool;
32
+ export {};
33
+ //# sourceMappingURL=runtime-diagnostics-webmcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-diagnostics-webmcp.d.ts","sourceRoot":"","sources":["../../../src/components/app/runtime-diagnostics-webmcp.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oCAAoC,kCAChB,CAAC;AAElC,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,QAAQ,CAAC,WAAW,EAAE;QACpB,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;QAC5B,QAAQ,CAAC,eAAe,EAAE,KAAK,CAAC;QAChC,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC;QAC9B,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC;KAC/B,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACtE;AAED,UAAU,8BAA8B;IACtC,YAAY,CACV,IAAI,EAAE,sBAAsB,EAC5B,OAAO,EAAE;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,GAC/B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,eAAO,MAAM,4BAA4B,8BAA8B,CAAC;AAExE,MAAM,WAAW,uCAAuC;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IAChC,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,CAAC,EAAE,8BAA8B,CAAC;CACxD;AAED,gFAAgF;AAChF,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,uCAA4C,GACpD,6BAA6B,GAAG,IAAI,CA0BtC;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,OAAO,KAAK,EACrB,QAAQ,GAAE,MAAqC,GAC9C,sBAAsB,CA2CxB"}
@@ -0,0 +1,68 @@
1
+ export const RUNTIME_DIAGNOSTICS_WEBMCP_TOOL_NAME = 'smrt.runtime.diagnostics.read';
2
+ export const RUNTIME_DIAGNOSTICS_ENDPOINT = '/api/_runtime/diagnostics';
3
+ /** Register exactly one page-user, read-only diagnostics tool for its owner. */
4
+ export function registerRuntimeDiagnosticsWebMcp(options = {}) {
5
+ const modelContext = options.modelContext ??
6
+ globalThis.document?.modelContext;
7
+ if (!modelContext || typeof modelContext.registerTool !== 'function') {
8
+ return null;
9
+ }
10
+ const controller = new AbortController();
11
+ const tool = createRuntimeDiagnosticsWebMcpTool(options.fetchFn ?? fetch, options.endpoint);
12
+ try {
13
+ const registration = modelContext.registerTool(tool, {
14
+ signal: controller.signal,
15
+ });
16
+ void Promise.resolve(registration).catch(() => controller.abort());
17
+ }
18
+ catch {
19
+ controller.abort();
20
+ }
21
+ return Object.freeze({ dispose: () => controller.abort() });
22
+ }
23
+ export function createRuntimeDiagnosticsWebMcpTool(fetchFn, endpoint = RUNTIME_DIAGNOSTICS_ENDPOINT) {
24
+ return Object.freeze({
25
+ name: RUNTIME_DIAGNOSTICS_WEBMCP_TOOL_NAME,
26
+ description: 'Read the authenticated, redacted application runtime diagnostics.',
27
+ inputSchema: Object.freeze({
28
+ type: 'object',
29
+ properties: Object.freeze({}),
30
+ additionalProperties: false,
31
+ }),
32
+ annotations: Object.freeze({
33
+ readOnlyHint: true,
34
+ destructiveHint: false,
35
+ idempotentHint: true,
36
+ openWorldHint: false,
37
+ }),
38
+ async execute() {
39
+ let response;
40
+ try {
41
+ response = await fetchFn(endpoint, {
42
+ method: 'GET',
43
+ credentials: 'same-origin',
44
+ headers: { accept: 'application/json' },
45
+ });
46
+ }
47
+ catch {
48
+ return stableToolError('diagnostics_unavailable');
49
+ }
50
+ if (!response.ok) {
51
+ return stableToolError(response.status === 401
52
+ ? 'authentication_required'
53
+ : response.status === 403
54
+ ? 'authorization_denied'
55
+ : 'diagnostics_unavailable');
56
+ }
57
+ try {
58
+ return JSON.stringify(await response.json());
59
+ }
60
+ catch {
61
+ return stableToolError('diagnostics_unavailable');
62
+ }
63
+ },
64
+ });
65
+ }
66
+ function stableToolError(code) {
67
+ return JSON.stringify({ ok: false, error: { code } });
68
+ }
@@ -21,6 +21,7 @@ import '@happyvertical/smrt-ui/i18n';
21
21
  import './strings.forms.js';
22
22
  import './strings.board.js';
23
23
  import './strings.workspace.js';
24
+ import '../mcp-apps/strings.js';
24
25
  export interface BuildI18nSnapshotOptions {
25
26
  /** Target locale (BCP-47-ish, e.g. `fr-CA`). */
26
27
  locale: string;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/i18n/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAGL,KAAK,4BAA4B,EAElC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,6BAA6B,CAAC;AAMrC,OAAO,6BAA6B,CAAC;AACrC,OAAO,oBAAoB,CAAC;AAC5B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,wBAAwB,CAAC;AAEhC,MAAM,WAAW,wBAAwB;IACvC,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,4BAA4B,CAAC,UAAU,CAAC,CAAC;IACpD;;;OAGG;IACH,EAAE,CAAC,EAAE,4BAA4B,CAAC,IAAI,CAAC,CAAC;IACxC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,YAAY,CAAC,CA4BvB"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/i18n/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAGL,KAAK,4BAA4B,EAElC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,6BAA6B,CAAC;AAMrC,OAAO,6BAA6B,CAAC;AACrC,OAAO,oBAAoB,CAAC;AAC5B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,wBAAwB,CAAC;AAChC,OAAO,wBAAwB,CAAC;AAEhC,MAAM,WAAW,wBAAwB;IACvC,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,4BAA4B,CAAC,UAAU,CAAC,CAAC;IACpD;;;OAGG;IACH,EAAE,CAAC,EAAE,4BAA4B,CAAC,IAAI,CAAC,CAAC;IACxC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,YAAY,CAAC,CA4BvB"}
@@ -26,6 +26,7 @@ import '@happyvertical/smrt-ui/i18n';
26
26
  import './strings.forms.js';
27
27
  import './strings.board.js';
28
28
  import './strings.workspace.js';
29
+ import '../mcp-apps/strings.js';
29
30
  /**
30
31
  * Resolve a per-locale dictionary of message **templates** for the keys an app
31
32
  * uses. Seeds `LanguageRegistry` from the English defaults registered via
@@ -53,6 +53,17 @@ export declare const M: {
53
53
  readonly 'ui.activity_item.cancel': "ui.activity_item.cancel";
54
54
  readonly 'ui.activity_list.empty': "ui.activity_list.empty";
55
55
  readonly 'ui.app_scope_panel.app_scope': "ui.app_scope_panel.app_scope";
56
+ readonly 'ui.app_shell.settings_link': "ui.app_shell.settings_link";
57
+ readonly 'ui.app_shell.navigation': "ui.app_shell.navigation";
58
+ readonly 'ui.owner_setup.heading': "ui.owner_setup.heading";
59
+ readonly 'ui.owner_setup.unavailable': "ui.owner_setup.unavailable";
60
+ readonly 'ui.owner_setup.intro': "ui.owner_setup.intro";
61
+ readonly 'ui.owner_setup.name': "ui.owner_setup.name";
62
+ readonly 'ui.owner_setup.email': "ui.owner_setup.email";
63
+ readonly 'ui.owner_setup.tenant_name': "ui.owner_setup.tenant_name";
64
+ readonly 'ui.owner_setup.submit': "ui.owner_setup.submit";
65
+ readonly 'ui.shell_settings_page.heading': "ui.shell_settings_page.heading";
66
+ readonly 'ui.shell_settings_page.description': "ui.shell_settings_page.description";
56
67
  readonly 'ui.hotkey_input.capture_title': "ui.hotkey_input.capture_title";
57
68
  readonly 'ui.hotkey_input.conflicts_with': "ui.hotkey_input.conflicts_with";
58
69
  readonly 'ui.shell_settings_panel.shell_settings': "ui.shell_settings_panel.shell_settings";
@@ -1 +1 @@
1
- {"version":3,"file":"strings.workspace.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,eAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0GZ,CAAC"}
1
+ {"version":3,"file":"strings.workspace.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,eAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0HZ,CAAC"}
@@ -58,6 +58,18 @@ export const M = defineMessages({
58
58
  'ui.activity_item.cancel': 'Cancel',
59
59
  'ui.activity_list.empty': 'No activities',
60
60
  'ui.app_scope_panel.app_scope': 'App scope',
61
+ // components/app/*.svelte
62
+ 'ui.app_shell.settings_link': 'Shell settings',
63
+ 'ui.app_shell.navigation': 'Application navigation',
64
+ 'ui.owner_setup.heading': 'Set up your local application',
65
+ 'ui.owner_setup.unavailable': 'Local owner setup is unavailable or has already been completed.',
66
+ 'ui.owner_setup.intro': 'Create the real local owner account. This invitation works once and stays on this device.',
67
+ 'ui.owner_setup.name': 'Name',
68
+ 'ui.owner_setup.email': 'Email',
69
+ 'ui.owner_setup.tenant_name': 'Workspace name (optional)',
70
+ 'ui.owner_setup.submit': 'Create owner',
71
+ 'ui.shell_settings_page.heading': 'Settings',
72
+ 'ui.shell_settings_page.description': 'Adjust the workspace shell — panel layout and keyboard shortcuts.',
61
73
  'ui.hotkey_input.capture_title': 'Press a key to capture it',
62
74
  'ui.hotkey_input.conflicts_with': 'Conflicts with',
63
75
  'ui.shell_settings_panel.shell_settings': 'Shell settings',
@@ -0,0 +1,123 @@
1
+ <!--
2
+ @component
3
+ Shipped portable MCP Apps view shell. Owns one mount-scoped host bridge
4
+ (`useMcpApp`), renders the app's own content, and offers a portable
5
+ display-mode request only when the bound host advertises that mode. Any
6
+ host failure or missing capability keeps the view inline with a status
7
+ message; the view never requires host controls. Browser-only: imports no
8
+ server code, credentials, or OpenAI-specific helpers.
9
+ -->
10
+ <script lang="ts">
11
+ import type { DisplayMode } from '@happyvertical/smrt-mcp-apps';
12
+ import { useI18n } from '@happyvertical/smrt-ui/i18n';
13
+ import { Button } from '@happyvertical/smrt-ui/ui';
14
+ import type { Snippet } from 'svelte';
15
+ import { type McpAppState, useMcpApp } from './mcp-apps.svelte.js';
16
+ import { M } from './strings.js';
17
+
18
+ interface McpAppsBridgeProps {
19
+ /** Exact, application-configured host origin. Never derive this from URL input. */
20
+ hostOrigin: string;
21
+ /** View identity sent in `ui/initialize`. */
22
+ appInfo: { name: string; version: string };
23
+ /** Visible view heading, already localized by the application. */
24
+ title: string;
25
+ /** Optional lead text, already localized by the application. */
26
+ description?: string;
27
+ /** Modes this view supports. Defaults to `['inline', 'fullscreen']`. */
28
+ availableDisplayModes?: DisplayMode[];
29
+ /** Mode offered by the expand control. Defaults to `'fullscreen'`. */
30
+ expandMode?: Exclude<DisplayMode, 'inline'>;
31
+ /** Host window override for tests. Defaults to the immediate parent. */
32
+ hostWindow?: () => Window;
33
+ /** Request timeout in milliseconds (1–120000). */
34
+ timeoutMs?: number;
35
+ /** App content; receives the bridge state for capability-gated calls. */
36
+ children?: Snippet<[McpAppState]>;
37
+ }
38
+
39
+ let {
40
+ hostOrigin,
41
+ appInfo,
42
+ title,
43
+ description,
44
+ availableDisplayModes = ['inline', 'fullscreen'],
45
+ expandMode = 'fullscreen',
46
+ hostWindow,
47
+ timeoutMs,
48
+ children,
49
+ }: McpAppsBridgeProps = $props();
50
+
51
+ const { t } = useI18n();
52
+ const headingId = $props.id();
53
+ let requestFailed = $state(false);
54
+ let requesting = $state(false);
55
+
56
+ // Options are read once, at mount, in the browser; SSR constructs nothing.
57
+ const app = useMcpApp(() => ({
58
+ appInfo: { ...appInfo },
59
+ availableDisplayModes: [...availableDisplayModes],
60
+ hostOrigin,
61
+ hostWindow: hostWindow ? hostWindow() : window.parent,
62
+ ...(timeoutMs === undefined ? {} : { timeoutMs }),
63
+ }));
64
+
65
+ const ready = $derived(app.snapshot?.state === 'ready');
66
+ const canExpand = $derived(
67
+ ready &&
68
+ !app.error &&
69
+ !requestFailed &&
70
+ availableDisplayModes.includes(expandMode) &&
71
+ (app.snapshot?.hostContext.availableDisplayModes ?? ['inline']).includes(
72
+ expandMode,
73
+ ) &&
74
+ app.snapshot?.hostContext.displayMode !== expandMode,
75
+ );
76
+ const inlineOnly = $derived(
77
+ Boolean(app.error) ||
78
+ requestFailed ||
79
+ (ready &&
80
+ !(app.snapshot?.hostContext.availableDisplayModes ?? ['inline']).includes(
81
+ expandMode,
82
+ )),
83
+ );
84
+
85
+ async function expand() {
86
+ const bridge = app.bridge;
87
+ if (!bridge || requesting) return;
88
+ requesting = true;
89
+ try {
90
+ await bridge.requestDisplayMode(expandMode);
91
+ } catch {
92
+ requestFailed = true;
93
+ } finally {
94
+ requesting = false;
95
+ }
96
+ }
97
+ </script>
98
+
99
+ <section aria-labelledby={headingId} class="smrt-mcp-apps-bridge">
100
+ <h1 id={headingId}>{title}</h1>
101
+ {#if description}<p>{description}</p>{/if}
102
+ {#if inlineOnly}
103
+ <p role="status">{t(M['ui.mcp_apps.inline_only'])}</p>
104
+ {:else if canExpand}
105
+ <Button type="button" onclick={expand} loading={requesting}>
106
+ {t(M['ui.mcp_apps.expand'])}
107
+ </Button>
108
+ {:else if !ready}
109
+ <p role="status" class="smrt-mcp-apps-bridge__pending">
110
+ {t(M['ui.mcp_apps.connecting'])}
111
+ </p>
112
+ {/if}
113
+ {@render children?.(app)}
114
+ </section>
115
+
116
+ <style>
117
+ .smrt-mcp-apps-bridge {
118
+ display: grid;
119
+ gap: var(--smrt-spacing-3, 0.75rem);
120
+ min-width: 0;
121
+ overflow-wrap: anywhere;
122
+ }
123
+ </style>
@@ -0,0 +1,38 @@
1
+ import type { DisplayMode } from '@happyvertical/smrt-mcp-apps';
2
+ import type { Snippet } from 'svelte';
3
+ import { type McpAppState } from './mcp-apps.svelte.js';
4
+ interface McpAppsBridgeProps {
5
+ /** Exact, application-configured host origin. Never derive this from URL input. */
6
+ hostOrigin: string;
7
+ /** View identity sent in `ui/initialize`. */
8
+ appInfo: {
9
+ name: string;
10
+ version: string;
11
+ };
12
+ /** Visible view heading, already localized by the application. */
13
+ title: string;
14
+ /** Optional lead text, already localized by the application. */
15
+ description?: string;
16
+ /** Modes this view supports. Defaults to `['inline', 'fullscreen']`. */
17
+ availableDisplayModes?: DisplayMode[];
18
+ /** Mode offered by the expand control. Defaults to `'fullscreen'`. */
19
+ expandMode?: Exclude<DisplayMode, 'inline'>;
20
+ /** Host window override for tests. Defaults to the immediate parent. */
21
+ hostWindow?: () => Window;
22
+ /** Request timeout in milliseconds (1–120000). */
23
+ timeoutMs?: number;
24
+ /** App content; receives the bridge state for capability-gated calls. */
25
+ children?: Snippet<[McpAppState]>;
26
+ }
27
+ /**
28
+ * Shipped portable MCP Apps view shell. Owns one mount-scoped host bridge
29
+ * (`useMcpApp`), renders the app's own content, and offers a portable
30
+ * display-mode request only when the bound host advertises that mode. Any
31
+ * host failure or missing capability keeps the view inline with a status
32
+ * message; the view never requires host controls. Browser-only: imports no
33
+ * server code, credentials, or OpenAI-specific helpers.
34
+ */
35
+ declare const McpAppsBridge: import("svelte").Component<McpAppsBridgeProps, {}, "">;
36
+ type McpAppsBridge = ReturnType<typeof McpAppsBridge>;
37
+ export default McpAppsBridge;
38
+ //# sourceMappingURL=McpAppsBridge.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"McpAppsBridge.svelte.d.ts","sourceRoot":"","sources":["../../src/mcp-apps/McpAppsBridge.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAGhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,sBAAsB,CAAC;AAInE,UAAU,kBAAkB;IAC1B,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,qBAAqB,CAAC,EAAE,WAAW,EAAE,CAAC;IACtC,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC5C,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC;IAC1B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;CACnC;AA4FD;;;;;;;GAOG;AACH,QAAA,MAAM,aAAa,wDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -1,3 +1,4 @@
1
+ export { default as McpAppsBridge } from './McpAppsBridge.svelte';
1
2
  export type { McpAppState } from './mcp-apps.svelte.js';
2
3
  export { useMcpApp, useMcpAppIntent } from './mcp-apps.svelte.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp-apps/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp-apps/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1 +1,2 @@
1
+ export { default as McpAppsBridge } from './McpAppsBridge.svelte';
1
2
  export { useMcpApp, useMcpAppIntent } from './mcp-apps.svelte.js';
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-apps.svelte.d.ts","sourceRoot":"","sources":["../../src/mcp-apps/mcp-apps.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EAClB,MAAM,iCAAiC,CAAC;AAIzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AACD,qFAAqF;AACrF,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,mBAAmB,GAAG,WAAW,CAiCzE;AACD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,iBAAiB,GACzB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAerD"}
1
+ {"version":3,"file":"mcp-apps.svelte.d.ts","sourceRoot":"","sources":["../../src/mcp-apps/mcp-apps.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EAClB,MAAM,iCAAiC,CAAC;AAIzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AACD,qFAAqF;AACrF,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,mBAAmB,GAAG,WAAW,CAyCzE;AACD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,iBAAiB,GACzB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAerD"}
@@ -8,7 +8,16 @@ export function useMcpApp(options) {
8
8
  let error = $state();
9
9
  onMount(() => {
10
10
  let active = true;
11
- const current = new McpAppBridge(options());
11
+ let current;
12
+ try {
13
+ current = new McpAppBridge(options());
14
+ }
15
+ catch (failure) {
16
+ // E.g. opened top-level (no embedding host) or an invalid origin: keep
17
+ // the view's ordinary fallback instead of failing the component mount.
18
+ error = failure instanceof Error ? failure.message : 'Host unavailable';
19
+ return;
20
+ }
12
21
  bridge = current;
13
22
  const unsubscribe = current.subscribe((next) => {
14
23
  if (active)
@@ -0,0 +1,7 @@
1
+ /** English defaults for the shipped MCP Apps bridge component. */
2
+ export declare const M: {
3
+ readonly 'ui.mcp_apps.expand': "ui.mcp_apps.expand";
4
+ readonly 'ui.mcp_apps.connecting': "ui.mcp_apps.connecting";
5
+ readonly 'ui.mcp_apps.inline_only': "ui.mcp_apps.inline_only";
6
+ };
7
+ //# sourceMappingURL=strings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/mcp-apps/strings.ts"],"names":[],"mappings":"AAEA,kEAAkE;AAClE,eAAO,MAAM,CAAC;;;;CAKZ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { defineMessages } from '@happyvertical/smrt-ui/i18n';
2
+ /** English defaults for the shipped MCP Apps bridge component. */
3
+ export const M = defineMessages({
4
+ 'ui.mcp_apps.expand': 'Expand view',
5
+ 'ui.mcp_apps.connecting': 'Connecting to the host…',
6
+ 'ui.mcp_apps.inline_only': 'Host controls are unavailable; this view remains inline.',
7
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-svelte",
3
- "version": "0.53.2",
3
+ "version": "0.53.4",
4
4
  "smrtJsdoc": "strict",
5
5
  "description": "Svelte 5 components for SMRT user management - auth, users, tenants, roles, permissions, groups",
6
6
  "type": "module",
@@ -55,6 +55,17 @@
55
55
  "import": "./dist/components/workspace/server/index.js",
56
56
  "default": "./dist/components/workspace/server/index.js"
57
57
  },
58
+ "./app": {
59
+ "types": "./dist/components/app/index.d.ts",
60
+ "svelte": "./dist/components/app/index.js",
61
+ "import": "./dist/components/app/index.js",
62
+ "default": "./dist/components/app/index.js"
63
+ },
64
+ "./app/runtime-diagnostics": {
65
+ "types": "./dist/components/app/runtime-diagnostics-webmcp.d.ts",
66
+ "import": "./dist/components/app/runtime-diagnostics-webmcp.js",
67
+ "default": "./dist/components/app/runtime-diagnostics-webmcp.js"
68
+ },
58
69
  "./workspace/live": {
59
70
  "types": "./dist/components/workspace/live/index.d.ts",
60
71
  "svelte": "./dist/components/workspace/live/index.js",
@@ -127,11 +138,11 @@
127
138
  },
128
139
  "dependencies": {
129
140
  "@happyvertical/logger": "^0.98.0",
130
- "@happyvertical/smrt-languages": "0.53.2",
131
- "@happyvertical/smrt-mcp-apps": "0.53.2",
132
- "@happyvertical/smrt-types": "0.53.2",
133
- "@happyvertical/smrt-ui": "0.53.2",
134
- "@happyvertical/smrt-web": "0.53.2",
141
+ "@happyvertical/smrt-languages": "0.53.4",
142
+ "@happyvertical/smrt-mcp-apps": "0.53.4",
143
+ "@happyvertical/smrt-types": "0.53.4",
144
+ "@happyvertical/smrt-ui": "0.53.4",
145
+ "@happyvertical/smrt-web": "0.53.4",
135
146
  "@tanstack/db": "^0.6.14",
136
147
  "@tanstack/svelte-db": "^0.1.91",
137
148
  "esm-env": "^1.2.2"
@@ -166,14 +177,14 @@
166
177
  }
167
178
  },
168
179
  "devDependencies": {
169
- "@happyvertical/smrt-agents": "0.53.2",
170
- "@happyvertical/smrt-chat": "0.53.2",
171
- "@happyvertical/smrt-content": "0.53.2",
172
- "@happyvertical/smrt-core": "0.53.2",
173
- "@happyvertical/smrt-reports": "0.53.2",
174
- "@happyvertical/smrt-scanner": "0.53.2",
175
- "@happyvertical/smrt-tenancy": "0.53.2",
176
- "@happyvertical/smrt-users": "0.53.2",
180
+ "@happyvertical/smrt-agents": "0.53.4",
181
+ "@happyvertical/smrt-chat": "0.53.4",
182
+ "@happyvertical/smrt-content": "0.53.4",
183
+ "@happyvertical/smrt-core": "0.53.4",
184
+ "@happyvertical/smrt-reports": "0.53.4",
185
+ "@happyvertical/smrt-scanner": "0.53.4",
186
+ "@happyvertical/smrt-tenancy": "0.53.4",
187
+ "@happyvertical/smrt-users": "0.53.4",
177
188
  "@sveltejs/package": "^2.5.8",
178
189
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
179
190
  "@testing-library/jest-dom": "^7.0.1",