@happyvertical/smrt-svelte 0.33.1 → 0.34.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/AGENTS.md +2 -3
- package/README.md +3 -4
- package/dist/i18n/strings.workspace.d.ts +5 -9
- package/dist/i18n/strings.workspace.d.ts.map +1 -1
- package/dist/i18n/strings.workspace.js +5 -12
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/package.json +4 -11
- package/dist/components/admin/AgentAdminPanel.svelte +0 -111
- package/dist/components/admin/AgentAdminPanel.svelte.d.ts +0 -25
- package/dist/components/admin/AgentAdminPanel.svelte.d.ts.map +0 -1
- package/dist/components/admin/AgentAdminTabs.svelte +0 -280
- package/dist/components/admin/AgentAdminTabs.svelte.d.ts +0 -23
- package/dist/components/admin/AgentAdminTabs.svelte.d.ts.map +0 -1
- package/dist/components/admin/AgentSettingsShell.svelte +0 -325
- package/dist/components/admin/AgentSettingsShell.svelte.d.ts +0 -33
- package/dist/components/admin/AgentSettingsShell.svelte.d.ts.map +0 -1
- package/dist/components/admin/__tests__/AgentSettingsShell.tablist.test.js +0 -93
- package/dist/components/admin/index.d.ts +0 -5
- package/dist/components/admin/index.d.ts.map +0 -1
- package/dist/components/admin/index.js +0 -6
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @happyvertical/smrt-svelte
|
|
2
2
|
|
|
3
|
-
Top-of-stack Svelte 5 integration layer for SMRT: the app `Provider`, auth / AI hooks, browser AI (STT/TTS/LLM), forms, server-side i18n, and the domain-aware composites (
|
|
3
|
+
Top-of-stack Svelte 5 integration layer for SMRT: the app `Provider`, auth / AI hooks, browser AI (STT/TTS/LLM), forms, server-side i18n, and the domain-aware composites (module, workspace). The domain-agnostic UI primitives, i18n client, theme system, and module UI registry now live in `@happyvertical/smrt-ui` (#1582) — import those from there (e.g. `@happyvertical/smrt-ui/ui`, `@happyvertical/smrt-ui/i18n`). The agent-admin shells (`AgentAdminPanel` / `AgentAdminTabs` / `AgentSettingsShell`) moved to `@happyvertical/smrt-agents` (#1589) so this package no longer depends on `smrt-agents` — import them from `@happyvertical/smrt-agents/svelte/admin` (side-effect-free) or `@happyvertical/smrt-agents/svelte`.
|
|
4
4
|
|
|
5
5
|
## The UI split — primitive-adoption contract (#1589)
|
|
6
6
|
|
|
@@ -69,7 +69,6 @@ the top-of-stack, domain-aware pieces:
|
|
|
69
69
|
|----------|------------|
|
|
70
70
|
| AI | `Provider`, `AILoadingOverlay`, `CapabilityGate`, `DownloadProgress`, `STTTest`, `VoiceInput` |
|
|
71
71
|
| Forms (`/forms`) | `TextInput`, `Select`, `MoneyInput`, `DateTimeInput`, `Toggle`, `FileUpload`, `AddressInput`, + more (AI-wired inputs use the hooks/browser-ai here) |
|
|
72
|
-
| Admin (`/admin`) | `AgentAdminPanel`, `AgentAdminTabs`, `AgentSettingsShell` (import `@happyvertical/smrt-agents/ui`) |
|
|
73
72
|
| Module | `ModulePanel` |
|
|
74
73
|
| Workspace (`/workspace`) | `WorkspaceShell`, `NavTree`, `Breadcrumbs`, `ToolsDock`, `RoleShell` |
|
|
75
74
|
|
|
@@ -219,7 +218,7 @@ await expectNoA11yViolations(container); // axe; color-contrast off (jsdom has n
|
|
|
219
218
|
## Dependencies
|
|
220
219
|
|
|
221
220
|
- `@happyvertical/smrt-types` (shared types) — includes the identity data contracts (`User`, `Role`, `Membership`, `Tenant`) the role/membership components type against, so no dependency on `smrt-users` / `smrt-profiles` is needed
|
|
222
|
-
- `@happyvertical/smrt-ui` (UI runtime: primitives, theme system, i18n client, module registry)
|
|
221
|
+
- `@happyvertical/smrt-ui` (UI runtime: primitives, theme system, i18n client, module registry) is a hard `dependency`. The agent-admin shells that used to type against `@happyvertical/smrt-agents/ui` moved to `@happyvertical/smrt-agents/svelte` (#1589), so `smrt-agents` is no longer a dependency here — this drops smrt-svelte below smrt-agents in the package DAG.
|
|
223
222
|
- `@happyvertical/smrt-languages` is a hard `dependency` (not an optional peer): the Node-only `/i18n/server` subpath imports its resolver. The browser bundle still excludes it — the client `/i18n` layer never imports the languages root, so it tree-shakes out.
|
|
224
223
|
- `@happyvertical/logger` (SDK) is a `dependency` — the browser-safe console logger used for voice/AI error reporting in the form components.
|
|
225
224
|
- Peer (all optional): `svelte` >=5.18.2, plus the browser-AI engines (`@huggingface/transformers`, `@mlc-ai/web-llm`, `@remotion/whisper-web`, `@xenova/transformers`) and `chrono-node`.
|
package/README.md
CHANGED
|
@@ -131,7 +131,6 @@ const editorSections = navTreeFromManifest(manifest, {
|
|
|
131
131
|
| Import Path | Contents |
|
|
132
132
|
|-------------|----------|
|
|
133
133
|
| `@happyvertical/smrt-svelte` | Provider, DataTable, permission utilities, hooks, state, components |
|
|
134
|
-
| `@happyvertical/smrt-svelte/admin` | Agent admin panel components |
|
|
135
134
|
| `@happyvertical/smrt-svelte/calendar` | Calendar and DayView |
|
|
136
135
|
| `@happyvertical/smrt-svelte/forms` | Form inputs (TextInput, Select, MoneyInput, etc.) |
|
|
137
136
|
| `@happyvertical/smrt-svelte/layout` | Layout (Container, Grid, Header, Footer, Masthead, etc.) |
|
|
@@ -161,10 +160,10 @@ const editorSections = navTreeFromManifest(manifest, {
|
|
|
161
160
|
|
|
162
161
|
**Permissions**: `PermissionCheck`, `RoleBadge`, `RoleSelector`
|
|
163
162
|
|
|
164
|
-
**Admin**: `AgentAdminPanel`, `AgentAdminTabs`, `AgentSettingsShell`
|
|
165
|
-
|
|
166
163
|
**Other**: `Calendar`, `DayView`, `MembershipCard`, `MembershipList`, `ModulePanel`
|
|
167
164
|
|
|
165
|
+
> The agent-admin shells (`AgentAdminPanel`, `AgentAdminTabs`, `AgentSettingsShell`) moved to `@happyvertical/smrt-agents/svelte` (#1589).
|
|
166
|
+
|
|
168
167
|
**Browser AI**: `AILoadingOverlay`, `CapabilityGate`, `DownloadProgress`, `STTTest`, `VoiceInput`
|
|
169
168
|
|
|
170
169
|
### Hooks
|
|
@@ -182,4 +181,4 @@ const editorSections = navTreeFromManifest(manifest, {
|
|
|
182
181
|
## Dependencies
|
|
183
182
|
|
|
184
183
|
- `@happyvertical/smrt-types` -- shared type definitions
|
|
185
|
-
- Peer: `svelte` >=5.18.2, `@happyvertical/smrt-
|
|
184
|
+
- Peer: `svelte` >=5.18.2, `@happyvertical/smrt-jobs`, `@happyvertical/smrt-profiles`, `@happyvertical/smrt-users` (all optional)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Workspace /
|
|
2
|
+
* Workspace / browser-AI message catalog (i18n, Sweep S13 #1418).
|
|
3
3
|
*
|
|
4
|
-
* English code defaults for user-facing strings in the workspace shell
|
|
5
|
-
*
|
|
4
|
+
* English code defaults for user-facing strings in the workspace shell and
|
|
5
|
+
* browser-AI test components. (The agent-admin shells + their `ui.agent_admin_*`
|
|
6
|
+
* keys moved to `@happyvertical/smrt-agents` in #1589.) Keys use the `ui`
|
|
7
|
+
* namespace and follow
|
|
6
8
|
* `ui.<component_snake>.<descriptor_snake>`. Client-safe (no languages root
|
|
7
9
|
* import). Registered via `defineMessages` so the client `t` / `<Trans>` fall
|
|
8
10
|
* back to these defaults when no server snapshot is present.
|
|
@@ -15,12 +17,6 @@ export declare const M: {
|
|
|
15
17
|
readonly 'ui.stt_test.status_initializing': "ui.stt_test.status_initializing";
|
|
16
18
|
readonly 'ui.stt_test.status_ready': "ui.stt_test.status_ready";
|
|
17
19
|
readonly 'ui.stt_test.status_not_initialized': "ui.stt_test.status_not_initialized";
|
|
18
|
-
readonly 'ui.agent_admin_panel.no_panel_message': "ui.agent_admin_panel.no_panel_message";
|
|
19
|
-
readonly 'ui.agent_admin_panel.no_panel_hint': "ui.agent_admin_panel.no_panel_hint";
|
|
20
|
-
readonly 'ui.agent_admin_tabs.no_slots': "ui.agent_admin_tabs.no_slots";
|
|
21
|
-
readonly 'ui.agent_admin_tabs.tablist_label': "ui.agent_admin_tabs.tablist_label";
|
|
22
|
-
readonly 'ui.agent_settings_shell.no_agents_message': "ui.agent_settings_shell.no_agents_message";
|
|
23
|
-
readonly 'ui.agent_settings_shell.no_agents_hint': "ui.agent_settings_shell.no_agents_hint";
|
|
24
20
|
readonly 'ui.workspace_shell.close_navigation': "ui.workspace_shell.close_navigation";
|
|
25
21
|
readonly 'ui.workspace_shell.close_inspector': "ui.workspace_shell.close_inspector";
|
|
26
22
|
readonly 'ui.workspace_shell.primary_navigation': "ui.workspace_shell.primary_navigation";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.workspace.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.workspace.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"strings.workspace.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,eAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;CAuBZ,CAAC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Workspace /
|
|
2
|
+
* Workspace / browser-AI message catalog (i18n, Sweep S13 #1418).
|
|
3
3
|
*
|
|
4
|
-
* English code defaults for user-facing strings in the workspace shell
|
|
5
|
-
*
|
|
4
|
+
* English code defaults for user-facing strings in the workspace shell and
|
|
5
|
+
* browser-AI test components. (The agent-admin shells + their `ui.agent_admin_*`
|
|
6
|
+
* keys moved to `@happyvertical/smrt-agents` in #1589.) Keys use the `ui`
|
|
7
|
+
* namespace and follow
|
|
6
8
|
* `ui.<component_snake>.<descriptor_snake>`. Client-safe (no languages root
|
|
7
9
|
* import). Registered via `defineMessages` so the client `t` / `<Trans>` fall
|
|
8
10
|
* back to these defaults when no server snapshot is present.
|
|
@@ -17,15 +19,6 @@ export const M = defineMessages({
|
|
|
17
19
|
'ui.stt_test.status_initializing': 'Initializing...',
|
|
18
20
|
'ui.stt_test.status_ready': 'Ready',
|
|
19
21
|
'ui.stt_test.status_not_initialized': 'Not initialized',
|
|
20
|
-
// components/admin/AgentAdminPanel.svelte
|
|
21
|
-
'ui.agent_admin_panel.no_panel_message': 'No admin panel registered for',
|
|
22
|
-
'ui.agent_admin_panel.no_panel_hint': "Import the agent's admin package to register its panels.",
|
|
23
|
-
// components/admin/AgentAdminTabs.svelte
|
|
24
|
-
'ui.agent_admin_tabs.no_slots': 'No configuration slots available for this agent.',
|
|
25
|
-
'ui.agent_admin_tabs.tablist_label': 'Agent configuration tabs',
|
|
26
|
-
// components/admin/AgentSettingsShell.svelte
|
|
27
|
-
'ui.agent_settings_shell.no_agents_message': 'No agents configured for this site.',
|
|
28
|
-
'ui.agent_settings_shell.no_agents_hint': 'Agents are discovered by matching their context field to the site domain.',
|
|
29
22
|
// components/workspace/WorkspaceShell.svelte
|
|
30
23
|
'ui.workspace_shell.close_navigation': 'Close navigation',
|
|
31
24
|
'ui.workspace_shell.close_inspector': 'Close inspector',
|
package/dist/index.d.ts
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Top-of-stack Svelte 5 integration layer for SMRT: the app `Provider`, auth /
|
|
5
5
|
* AI hooks, browser-AI adapters, server-side i18n, and the domain-aware
|
|
6
|
-
* composite components (
|
|
6
|
+
* composite components (module, workspace, forms).
|
|
7
7
|
*
|
|
8
8
|
* Domain-agnostic UI primitives, the i18n client, the theme system, and the
|
|
9
9
|
* module UI registry now live in `@happyvertical/smrt-ui` — import those from
|
|
10
|
-
* there (e.g. `@happyvertical/smrt-ui/ui`, `@happyvertical/smrt-ui/i18n`).
|
|
10
|
+
* there (e.g. `@happyvertical/smrt-ui/ui`, `@happyvertical/smrt-ui/i18n`). The
|
|
11
|
+
* agent-admin shells (AgentAdminPanel / AgentAdminTabs / AgentSettingsShell)
|
|
12
|
+
* moved to `@happyvertical/smrt-agents/svelte`.
|
|
11
13
|
*/
|
|
12
|
-
export * from './components/admin/index.js';
|
|
13
14
|
export * from './components/forms/index.js';
|
|
14
15
|
export * from './components/module/index.js';
|
|
15
16
|
export * from './hooks/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,cAAc,6BAA6B,CAAC;AAE5C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,kBAAkB,CAAC;AAEjC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAExD,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Top-of-stack Svelte 5 integration layer for SMRT: the app `Provider`, auth /
|
|
5
5
|
* AI hooks, browser-AI adapters, server-side i18n, and the domain-aware
|
|
6
|
-
* composite components (
|
|
6
|
+
* composite components (module, workspace, forms).
|
|
7
7
|
*
|
|
8
8
|
* Domain-agnostic UI primitives, the i18n client, the theme system, and the
|
|
9
9
|
* module UI registry now live in `@happyvertical/smrt-ui` — import those from
|
|
10
|
-
* there (e.g. `@happyvertical/smrt-ui/ui`, `@happyvertical/smrt-ui/i18n`).
|
|
10
|
+
* there (e.g. `@happyvertical/smrt-ui/ui`, `@happyvertical/smrt-ui/i18n`). The
|
|
11
|
+
* agent-admin shells (AgentAdminPanel / AgentAdminTabs / AgentSettingsShell)
|
|
12
|
+
* moved to `@happyvertical/smrt-agents/svelte`.
|
|
11
13
|
*/
|
|
12
|
-
// Admin components
|
|
13
|
-
export * from './components/admin/index.js';
|
|
14
14
|
// Form components
|
|
15
15
|
export * from './components/forms/index.js';
|
|
16
16
|
// Module components (for dynamic module UI rendering)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "Svelte 5 components for SMRT user management - auth, users, tenants, roles, permissions, groups",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -13,12 +13,6 @@
|
|
|
13
13
|
"import": "./dist/index.js",
|
|
14
14
|
"default": "./dist/index.js"
|
|
15
15
|
},
|
|
16
|
-
"./admin": {
|
|
17
|
-
"types": "./dist/components/admin/index.d.ts",
|
|
18
|
-
"svelte": "./dist/components/admin/index.js",
|
|
19
|
-
"import": "./dist/components/admin/index.js",
|
|
20
|
-
"default": "./dist/components/admin/index.js"
|
|
21
|
-
},
|
|
22
16
|
"./forms": {
|
|
23
17
|
"types": "./dist/components/forms/index.d.ts",
|
|
24
18
|
"svelte": "./dist/components/forms/index.js",
|
|
@@ -83,10 +77,9 @@
|
|
|
83
77
|
"dependencies": {
|
|
84
78
|
"@happyvertical/logger": "^0.74.7",
|
|
85
79
|
"esm-env": "^1.2.2",
|
|
86
|
-
"@happyvertical/smrt-
|
|
87
|
-
"@happyvertical/smrt-
|
|
88
|
-
"@happyvertical/smrt-ui": "0.
|
|
89
|
-
"@happyvertical/smrt-languages": "0.33.1"
|
|
80
|
+
"@happyvertical/smrt-languages": "0.34.0",
|
|
81
|
+
"@happyvertical/smrt-types": "0.34.0",
|
|
82
|
+
"@happyvertical/smrt-ui": "0.34.0"
|
|
90
83
|
},
|
|
91
84
|
"peerDependencies": {
|
|
92
85
|
"@huggingface/transformers": ">=3.0.0",
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type {
|
|
3
|
-
AdminPanelBaseProps,
|
|
4
|
-
AgentUIComponentRegistry,
|
|
5
|
-
AgentUISlot,
|
|
6
|
-
} from '@happyvertical/smrt-agents/ui';
|
|
7
|
-
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
8
|
-
import { M } from '../../i18n/strings.workspace.js';
|
|
9
|
-
|
|
10
|
-
const { t } = useI18n();
|
|
11
|
-
|
|
12
|
-
export interface Props {
|
|
13
|
-
/** The registry to look up components from */
|
|
14
|
-
registry: AgentUIComponentRegistry;
|
|
15
|
-
/** The agent class name (e.g., 'Praeco') */
|
|
16
|
-
agentClass: string;
|
|
17
|
-
/** The slot ID to render */
|
|
18
|
-
slotId: string;
|
|
19
|
-
/** The slot definition */
|
|
20
|
-
slot: AgentUISlot;
|
|
21
|
-
/** The current configuration for this slot */
|
|
22
|
-
config: unknown;
|
|
23
|
-
/** Callback when config is saved */
|
|
24
|
-
onSave?: (config: unknown) => Promise<void>;
|
|
25
|
-
/** Whether the panel is read-only */
|
|
26
|
-
readonly?: boolean;
|
|
27
|
-
/** File-based config defaults */
|
|
28
|
-
fileConfig?: unknown;
|
|
29
|
-
/** Database-persisted config overrides */
|
|
30
|
-
dbConfig?: unknown;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const {
|
|
34
|
-
registry,
|
|
35
|
-
agentClass,
|
|
36
|
-
slotId,
|
|
37
|
-
slot,
|
|
38
|
-
config,
|
|
39
|
-
onSave,
|
|
40
|
-
readonly = false,
|
|
41
|
-
fileConfig,
|
|
42
|
-
dbConfig,
|
|
43
|
-
}: Props = $props();
|
|
44
|
-
|
|
45
|
-
const Component = $derived(registry.get(agentClass, slotId));
|
|
46
|
-
|
|
47
|
-
async function handleSave(newConfig: unknown) {
|
|
48
|
-
await onSave?.(newConfig);
|
|
49
|
-
}
|
|
50
|
-
</script>
|
|
51
|
-
|
|
52
|
-
{#if Component}
|
|
53
|
-
<Component
|
|
54
|
-
{config}
|
|
55
|
-
onSave={handleSave}
|
|
56
|
-
{readonly}
|
|
57
|
-
{fileConfig}
|
|
58
|
-
{dbConfig}
|
|
59
|
-
/>
|
|
60
|
-
{:else}
|
|
61
|
-
<div class="no-panel">
|
|
62
|
-
<div class="no-panel-icon">⚙️</div>
|
|
63
|
-
<p class="no-panel-message">
|
|
64
|
-
{t(M['ui.agent_admin_panel.no_panel_message'])} <code>{agentClass}.{slotId}</code>
|
|
65
|
-
</p>
|
|
66
|
-
<p class="no-panel-hint">
|
|
67
|
-
{t(M['ui.agent_admin_panel.no_panel_hint'])}
|
|
68
|
-
</p>
|
|
69
|
-
</div>
|
|
70
|
-
{/if}
|
|
71
|
-
|
|
72
|
-
<style>
|
|
73
|
-
.no-panel {
|
|
74
|
-
display: flex;
|
|
75
|
-
flex-direction: column;
|
|
76
|
-
align-items: center;
|
|
77
|
-
justify-content: center;
|
|
78
|
-
padding: 3rem 2rem;
|
|
79
|
-
text-align: center;
|
|
80
|
-
background: var(--smrt-color-surface-container-low, #f8fafc);
|
|
81
|
-
border: 1px dashed var(--smrt-color-outline-variant, #e2e8f0);
|
|
82
|
-
border-radius: var(--smrt-radius-medium, 8px);
|
|
83
|
-
min-height: 200px;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.no-panel-icon {
|
|
87
|
-
font-size: var(--smrt-typography-display-medium-size, 2.5rem);
|
|
88
|
-
margin-bottom: 1rem;
|
|
89
|
-
opacity: 0.5;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.no-panel-message {
|
|
93
|
-
margin: 0 0 0.5rem 0;
|
|
94
|
-
font-size: var(--smrt-typography-body-large-size, 0.9375rem);
|
|
95
|
-
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.no-panel-message code {
|
|
99
|
-
background: var(--smrt-color-surface-container-high, #e2e8f0);
|
|
100
|
-
padding: var(--smrt-spacing-1, 0.125rem) var(--smrt-spacing-2, 0.375rem);
|
|
101
|
-
border-radius: var(--smrt-radius-small, 4px);
|
|
102
|
-
font-family: var(--smrt-font-family-mono, 'SF Mono', Monaco, Consolas, monospace);
|
|
103
|
-
font-size: var(--smrt-typography-body-medium-size, 0.875rem);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.no-panel-hint {
|
|
107
|
-
margin: 0;
|
|
108
|
-
font-size: var(--smrt-typography-body-medium-size, 0.8125rem);
|
|
109
|
-
color: var(--smrt-color-on-surface-variant, #94a3b8);
|
|
110
|
-
}
|
|
111
|
-
</style>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { AgentUIComponentRegistry, AgentUISlot } from '@happyvertical/smrt-agents/ui';
|
|
2
|
-
export interface Props {
|
|
3
|
-
/** The registry to look up components from */
|
|
4
|
-
registry: AgentUIComponentRegistry;
|
|
5
|
-
/** The agent class name (e.g., 'Praeco') */
|
|
6
|
-
agentClass: string;
|
|
7
|
-
/** The slot ID to render */
|
|
8
|
-
slotId: string;
|
|
9
|
-
/** The slot definition */
|
|
10
|
-
slot: AgentUISlot;
|
|
11
|
-
/** The current configuration for this slot */
|
|
12
|
-
config: unknown;
|
|
13
|
-
/** Callback when config is saved */
|
|
14
|
-
onSave?: (config: unknown) => Promise<void>;
|
|
15
|
-
/** Whether the panel is read-only */
|
|
16
|
-
readonly?: boolean;
|
|
17
|
-
/** File-based config defaults */
|
|
18
|
-
fileConfig?: unknown;
|
|
19
|
-
/** Database-persisted config overrides */
|
|
20
|
-
dbConfig?: unknown;
|
|
21
|
-
}
|
|
22
|
-
declare const AgentAdminPanel: import("svelte").Component<Props, {}, "">;
|
|
23
|
-
type AgentAdminPanel = ReturnType<typeof AgentAdminPanel>;
|
|
24
|
-
export default AgentAdminPanel;
|
|
25
|
-
//# sourceMappingURL=AgentAdminPanel.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AgentAdminPanel.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AgentAdminPanel.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,wBAAwB,EACxB,WAAW,EACZ,MAAM,+BAA+B,CAAC;AAKvC,MAAM,WAAW,KAAK;IACpB,8CAA8C;IAC9C,QAAQ,EAAE,wBAAwB,CAAC;IACnC,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,8CAA8C;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,oCAAoC;IACpC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA8CD,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type {
|
|
3
|
-
AgentUIComponentRegistry,
|
|
4
|
-
AgentUISlots,
|
|
5
|
-
} from '@happyvertical/smrt-agents/ui';
|
|
6
|
-
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
7
|
-
import { M } from '../../i18n/strings.workspace.js';
|
|
8
|
-
import AgentAdminPanel from './AgentAdminPanel.svelte';
|
|
9
|
-
|
|
10
|
-
const { t } = useI18n();
|
|
11
|
-
|
|
12
|
-
export interface Props {
|
|
13
|
-
/** The registry to look up components from */
|
|
14
|
-
registry: AgentUIComponentRegistry;
|
|
15
|
-
/** The agent class name (e.g., 'Praeco') */
|
|
16
|
-
agentClass: string;
|
|
17
|
-
/** UI slots declared by the agent */
|
|
18
|
-
slots: AgentUISlots;
|
|
19
|
-
/** Config data for each slot (keyed by slotId) */
|
|
20
|
-
configs: Record<string, unknown>;
|
|
21
|
-
/** Callback when a slot config is saved */
|
|
22
|
-
onSave?: (slotId: string, config: unknown) => Promise<void>;
|
|
23
|
-
/** Whether all panels are read-only */
|
|
24
|
-
readonly?: boolean;
|
|
25
|
-
/** File-based configs for each slot */
|
|
26
|
-
fileConfigs?: Record<string, unknown>;
|
|
27
|
-
/** Database configs for each slot */
|
|
28
|
-
dbConfigs?: Record<string, unknown>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const {
|
|
32
|
-
registry,
|
|
33
|
-
agentClass,
|
|
34
|
-
slots,
|
|
35
|
-
configs,
|
|
36
|
-
onSave,
|
|
37
|
-
readonly = false,
|
|
38
|
-
fileConfigs = {},
|
|
39
|
-
dbConfigs = {},
|
|
40
|
-
}: Props = $props();
|
|
41
|
-
|
|
42
|
-
// Sort slots by order, then by label
|
|
43
|
-
const sortedSlots = $derived(
|
|
44
|
-
Object.entries(slots).sort(([, a], [, b]) => {
|
|
45
|
-
const orderA = a.order ?? 99;
|
|
46
|
-
const orderB = b.order ?? 99;
|
|
47
|
-
if (orderA !== orderB) return orderA - orderB;
|
|
48
|
-
return a.label.localeCompare(b.label);
|
|
49
|
-
}),
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
let activeSlotId = $state<string | null>(null);
|
|
53
|
-
let tablistEl: HTMLElement | null = $state(null);
|
|
54
|
-
|
|
55
|
-
// Initialize active slot to first sorted slot
|
|
56
|
-
$effect(() => {
|
|
57
|
-
if (activeSlotId === null && sortedSlots.length > 0) {
|
|
58
|
-
activeSlotId = sortedSlots[0][0];
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
function handleSlotClick(slotId: string) {
|
|
63
|
-
activeSlotId = slotId;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Handle keyboard navigation for accessibility
|
|
68
|
-
*/
|
|
69
|
-
function handleKeydown(event: KeyboardEvent, currentSlotId: string) {
|
|
70
|
-
const enabledSlots = sortedSlots;
|
|
71
|
-
const currentIndex = enabledSlots.findIndex(([id]) => id === currentSlotId);
|
|
72
|
-
|
|
73
|
-
if (currentIndex === -1) return;
|
|
74
|
-
|
|
75
|
-
let nextIndex: number | null = null;
|
|
76
|
-
|
|
77
|
-
switch (event.key) {
|
|
78
|
-
case 'ArrowRight':
|
|
79
|
-
event.preventDefault();
|
|
80
|
-
nextIndex = (currentIndex + 1) % enabledSlots.length;
|
|
81
|
-
break;
|
|
82
|
-
case 'ArrowLeft':
|
|
83
|
-
event.preventDefault();
|
|
84
|
-
nextIndex =
|
|
85
|
-
(currentIndex - 1 + enabledSlots.length) % enabledSlots.length;
|
|
86
|
-
break;
|
|
87
|
-
case 'Home':
|
|
88
|
-
event.preventDefault();
|
|
89
|
-
nextIndex = 0;
|
|
90
|
-
break;
|
|
91
|
-
case 'End':
|
|
92
|
-
event.preventDefault();
|
|
93
|
-
nextIndex = enabledSlots.length - 1;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (nextIndex !== null && nextIndex !== currentIndex) {
|
|
98
|
-
const [nextSlotId] = enabledSlots[nextIndex];
|
|
99
|
-
activeSlotId = nextSlotId;
|
|
100
|
-
// Focus the next tab after DOM update
|
|
101
|
-
requestAnimationFrame(() => {
|
|
102
|
-
const tabButton = tablistEl?.querySelector(
|
|
103
|
-
`[data-tab-id="${CSS.escape(nextSlotId)}"]`,
|
|
104
|
-
) as HTMLElement;
|
|
105
|
-
tabButton?.focus();
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async function handleSave(config: unknown) {
|
|
111
|
-
if (activeSlotId && onSave) {
|
|
112
|
-
await onSave(activeSlotId, config);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
</script>
|
|
116
|
-
|
|
117
|
-
<div class="agent-admin-tabs">
|
|
118
|
-
<div class="tabs-nav" role="tablist" aria-label={t(M['ui.agent_admin_tabs.tablist_label'])} bind:this={tablistEl}>
|
|
119
|
-
{#each sortedSlots as [slotId, slot]}
|
|
120
|
-
<button
|
|
121
|
-
class="tab-button"
|
|
122
|
-
class:active={activeSlotId === slotId}
|
|
123
|
-
role="tab"
|
|
124
|
-
aria-selected={activeSlotId === slotId}
|
|
125
|
-
aria-controls="panel-{slotId}"
|
|
126
|
-
id="tab-{slotId}"
|
|
127
|
-
data-tab-id={slotId}
|
|
128
|
-
tabindex={activeSlotId === slotId ? 0 : -1}
|
|
129
|
-
onclick={() => handleSlotClick(slotId)}
|
|
130
|
-
onkeydown={(e) => handleKeydown(e, slotId)}
|
|
131
|
-
>
|
|
132
|
-
{#if slot.icon}
|
|
133
|
-
<span class="tab-icon" aria-hidden="true">{slot.icon}</span>
|
|
134
|
-
{/if}
|
|
135
|
-
<span class="tab-label">{slot.label}</span>
|
|
136
|
-
</button>
|
|
137
|
-
{/each}
|
|
138
|
-
</div>
|
|
139
|
-
|
|
140
|
-
<div class="tab-content">
|
|
141
|
-
{#if activeSlotId && slots[activeSlotId]}
|
|
142
|
-
{@const activeSlot = slots[activeSlotId]}
|
|
143
|
-
<div
|
|
144
|
-
id="panel-{activeSlotId}"
|
|
145
|
-
class="tab-panel"
|
|
146
|
-
role="tabpanel"
|
|
147
|
-
aria-labelledby="tab-{activeSlotId}"
|
|
148
|
-
>
|
|
149
|
-
{#if activeSlot.description}
|
|
150
|
-
<p class="slot-description">{activeSlot.description}</p>
|
|
151
|
-
{/if}
|
|
152
|
-
|
|
153
|
-
<AgentAdminPanel
|
|
154
|
-
{registry}
|
|
155
|
-
{agentClass}
|
|
156
|
-
slotId={activeSlotId}
|
|
157
|
-
slot={activeSlot}
|
|
158
|
-
config={configs[activeSlotId] ?? {}}
|
|
159
|
-
onSave={handleSave}
|
|
160
|
-
{readonly}
|
|
161
|
-
fileConfig={fileConfigs[activeSlotId]}
|
|
162
|
-
dbConfig={dbConfigs[activeSlotId]}
|
|
163
|
-
/>
|
|
164
|
-
</div>
|
|
165
|
-
{:else}
|
|
166
|
-
<div class="no-slots">
|
|
167
|
-
<p>{t(M['ui.agent_admin_tabs.no_slots'])}</p>
|
|
168
|
-
</div>
|
|
169
|
-
{/if}
|
|
170
|
-
</div>
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
<style>
|
|
174
|
-
.agent-admin-tabs {
|
|
175
|
-
display: flex;
|
|
176
|
-
flex-direction: column;
|
|
177
|
-
gap: 1rem;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.tabs-nav {
|
|
181
|
-
display: flex;
|
|
182
|
-
gap: 0.25rem;
|
|
183
|
-
border-bottom: 1px solid var(--smrt-color-outline-variant, #e2e8f0);
|
|
184
|
-
padding-bottom: 0;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
.tab-button {
|
|
188
|
-
display: flex;
|
|
189
|
-
align-items: center;
|
|
190
|
-
gap: 0.5rem;
|
|
191
|
-
padding: 0.75rem 1rem;
|
|
192
|
-
border: none;
|
|
193
|
-
background: transparent;
|
|
194
|
-
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
195
|
-
font-size: var(--smrt-typography-label-large-size, 0.875rem);
|
|
196
|
-
font-weight: var(--smrt-typography-weight-medium, 500);
|
|
197
|
-
cursor: pointer;
|
|
198
|
-
border-bottom: 2px solid transparent;
|
|
199
|
-
margin-bottom: -1px;
|
|
200
|
-
transition:
|
|
201
|
-
color var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease),
|
|
202
|
-
border-color var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
.tab-button:hover:not(:disabled) {
|
|
206
|
-
color: var(--smrt-color-on-surface, #334155);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
.tab-button.active {
|
|
210
|
-
color: var(--smrt-color-primary, #3b82f6);
|
|
211
|
-
border-bottom-color: var(--smrt-color-primary, #3b82f6);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
.tab-button:disabled {
|
|
215
|
-
opacity: 0.38;
|
|
216
|
-
cursor: not-allowed;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
.tab-button:focus-visible {
|
|
220
|
-
outline: 2px solid var(--smrt-color-primary, #3b82f6);
|
|
221
|
-
outline-offset: 2px;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
.tab-icon {
|
|
225
|
-
font-size: var(--smrt-typography-title-medium-size, 1rem);
|
|
226
|
-
opacity: 0.8;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
.tab-label {
|
|
230
|
-
white-space: nowrap;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
.tab-content {
|
|
234
|
-
min-height: 300px;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
.tab-panel {
|
|
238
|
-
animation: fadeIn var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease-out);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
@keyframes fadeIn {
|
|
242
|
-
from {
|
|
243
|
-
opacity: 0;
|
|
244
|
-
transform: translateY(4px);
|
|
245
|
-
}
|
|
246
|
-
to {
|
|
247
|
-
opacity: 1;
|
|
248
|
-
transform: translateY(0);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
@media (prefers-reduced-motion: reduce) {
|
|
253
|
-
.tab-panel {
|
|
254
|
-
animation: none;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
.slot-description {
|
|
259
|
-
margin: 0 0 1rem 0;
|
|
260
|
-
padding: 0.75rem 1rem;
|
|
261
|
-
background: var(--smrt-color-primary-container, #f0f9ff);
|
|
262
|
-
border-left: 3px solid var(--smrt-color-primary, #3b82f6);
|
|
263
|
-
border-radius: 0 var(--smrt-radius-md, 8px) var(--smrt-radius-md, 8px) 0;
|
|
264
|
-
font-size: var(--smrt-typography-body-medium-size, 0.875rem);
|
|
265
|
-
color: var(--smrt-color-on-primary-container, #1e40af);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
.no-slots {
|
|
269
|
-
display: flex;
|
|
270
|
-
align-items: center;
|
|
271
|
-
justify-content: center;
|
|
272
|
-
min-height: 200px;
|
|
273
|
-
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
274
|
-
font-size: var(--smrt-typography-body-medium-size, 0.9375rem);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
.no-slots p {
|
|
278
|
-
margin: 0;
|
|
279
|
-
}
|
|
280
|
-
</style>
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { AgentUIComponentRegistry, AgentUISlots } from '@happyvertical/smrt-agents/ui';
|
|
2
|
-
export interface Props {
|
|
3
|
-
/** The registry to look up components from */
|
|
4
|
-
registry: AgentUIComponentRegistry;
|
|
5
|
-
/** The agent class name (e.g., 'Praeco') */
|
|
6
|
-
agentClass: string;
|
|
7
|
-
/** UI slots declared by the agent */
|
|
8
|
-
slots: AgentUISlots;
|
|
9
|
-
/** Config data for each slot (keyed by slotId) */
|
|
10
|
-
configs: Record<string, unknown>;
|
|
11
|
-
/** Callback when a slot config is saved */
|
|
12
|
-
onSave?: (slotId: string, config: unknown) => Promise<void>;
|
|
13
|
-
/** Whether all panels are read-only */
|
|
14
|
-
readonly?: boolean;
|
|
15
|
-
/** File-based configs for each slot */
|
|
16
|
-
fileConfigs?: Record<string, unknown>;
|
|
17
|
-
/** Database configs for each slot */
|
|
18
|
-
dbConfigs?: Record<string, unknown>;
|
|
19
|
-
}
|
|
20
|
-
declare const AgentAdminTabs: import("svelte").Component<Props, {}, "">;
|
|
21
|
-
type AgentAdminTabs = ReturnType<typeof AgentAdminTabs>;
|
|
22
|
-
export default AgentAdminTabs;
|
|
23
|
-
//# sourceMappingURL=AgentAdminTabs.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AgentAdminTabs.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AgentAdminTabs.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,wBAAwB,EACxB,YAAY,EACb,MAAM,+BAA+B,CAAC;AAMvC,MAAM,WAAW,KAAK;IACpB,8CAA8C;IAC9C,QAAQ,EAAE,wBAAwB,CAAC;IACnC,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,KAAK,EAAE,YAAY,CAAC;IACpB,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,2CAA2C;IAC3C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAkID,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type {
|
|
3
|
-
AgentUIComponentRegistry,
|
|
4
|
-
AgentUISlots,
|
|
5
|
-
} from '@happyvertical/smrt-agents/ui';
|
|
6
|
-
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
7
|
-
import { M } from '../../i18n/strings.workspace.js';
|
|
8
|
-
import AgentAdminTabs from './AgentAdminTabs.svelte';
|
|
9
|
-
|
|
10
|
-
const { t } = useI18n();
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Serialized agent data passed from server
|
|
14
|
-
* (Agent instances can't be passed directly to client)
|
|
15
|
-
*/
|
|
16
|
-
interface AgentData {
|
|
17
|
-
id: string;
|
|
18
|
-
name?: string;
|
|
19
|
-
/** Agent class name (e.g., 'Praeco') - determined from _meta_type or explicit */
|
|
20
|
-
agentClass: string;
|
|
21
|
-
/** UI slots for this agent */
|
|
22
|
-
slots: AgentUISlots;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface Props {
|
|
26
|
-
/** The registry to look up components from */
|
|
27
|
-
registry: AgentUIComponentRegistry;
|
|
28
|
-
/** List of agents to display (serialized data, not instances) */
|
|
29
|
-
agents: AgentData[];
|
|
30
|
-
/** Config data for each agent and slot: agentId -> slotId -> config */
|
|
31
|
-
configs: Record<string, Record<string, unknown>>;
|
|
32
|
-
/** Callback when a config is saved */
|
|
33
|
-
onSave?: (agentId: string, slotId: string, config: unknown) => Promise<void>;
|
|
34
|
-
/** Whether all panels are read-only */
|
|
35
|
-
readonly?: boolean;
|
|
36
|
-
/** File configs: agentId -> slotId -> config */
|
|
37
|
-
fileConfigs?: Record<string, Record<string, unknown>>;
|
|
38
|
-
/** Database configs: agentId -> slotId -> config */
|
|
39
|
-
dbConfigs?: Record<string, Record<string, unknown>>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const {
|
|
43
|
-
registry,
|
|
44
|
-
agents,
|
|
45
|
-
configs,
|
|
46
|
-
onSave,
|
|
47
|
-
readonly = false,
|
|
48
|
-
fileConfigs = {},
|
|
49
|
-
dbConfigs = {},
|
|
50
|
-
}: Props = $props();
|
|
51
|
-
|
|
52
|
-
// Stable per-instance id base so multiple shells don't collide on tab/panel ids.
|
|
53
|
-
const idBase = $props.id();
|
|
54
|
-
|
|
55
|
-
let activeAgentId = $state<string | null>(null);
|
|
56
|
-
let tablistEl: HTMLElement | null = $state(null);
|
|
57
|
-
|
|
58
|
-
// Initialize to first agent
|
|
59
|
-
$effect(() => {
|
|
60
|
-
if (activeAgentId === null && agents.length > 0) {
|
|
61
|
-
activeAgentId = agents[0].id;
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const activeAgent = $derived(agents.find((a) => a.id === activeAgentId));
|
|
66
|
-
|
|
67
|
-
function handleAgentClick(agentId: string) {
|
|
68
|
-
activeAgentId = agentId;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Roving-tabindex keyboard navigation for the agent switcher (C8). The list is
|
|
73
|
-
* a vertical tablist, so Up/Down move between agents (plus Home/End); mirrors
|
|
74
|
-
* the horizontal pattern in AgentAdminTabs.
|
|
75
|
-
*/
|
|
76
|
-
function handleAgentKeydown(event: KeyboardEvent, currentAgentId: string) {
|
|
77
|
-
const currentIndex = agents.findIndex((a) => a.id === currentAgentId);
|
|
78
|
-
if (currentIndex === -1) return;
|
|
79
|
-
|
|
80
|
-
let nextIndex: number | null = null;
|
|
81
|
-
switch (event.key) {
|
|
82
|
-
case 'ArrowDown':
|
|
83
|
-
case 'ArrowRight':
|
|
84
|
-
event.preventDefault();
|
|
85
|
-
nextIndex = (currentIndex + 1) % agents.length;
|
|
86
|
-
break;
|
|
87
|
-
case 'ArrowUp':
|
|
88
|
-
case 'ArrowLeft':
|
|
89
|
-
event.preventDefault();
|
|
90
|
-
nextIndex = (currentIndex - 1 + agents.length) % agents.length;
|
|
91
|
-
break;
|
|
92
|
-
case 'Home':
|
|
93
|
-
event.preventDefault();
|
|
94
|
-
nextIndex = 0;
|
|
95
|
-
break;
|
|
96
|
-
case 'End':
|
|
97
|
-
event.preventDefault();
|
|
98
|
-
nextIndex = agents.length - 1;
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (nextIndex !== null && nextIndex !== currentIndex) {
|
|
103
|
-
const nextAgentId = agents[nextIndex].id;
|
|
104
|
-
activeAgentId = nextAgentId;
|
|
105
|
-
// Focus the newly-selected tab after the DOM updates.
|
|
106
|
-
requestAnimationFrame(() => {
|
|
107
|
-
const tabButton = tablistEl?.querySelector(
|
|
108
|
-
`[data-agent-id="${CSS.escape(nextAgentId)}"]`,
|
|
109
|
-
) as HTMLElement | null;
|
|
110
|
-
tabButton?.focus();
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async function handleSave(slotId: string, config: unknown) {
|
|
116
|
-
if (activeAgentId && onSave) {
|
|
117
|
-
await onSave(activeAgentId, slotId, config);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
</script>
|
|
121
|
-
|
|
122
|
-
<div class="agent-settings-shell" class:single-agent={agents.length === 1}>
|
|
123
|
-
{#if agents.length > 1}
|
|
124
|
-
<aside class="agents-sidebar">
|
|
125
|
-
<h3 class="sidebar-title" id="{idBase}-agents-title">Agents</h3>
|
|
126
|
-
<div
|
|
127
|
-
class="agents-list"
|
|
128
|
-
role="tablist"
|
|
129
|
-
aria-orientation="vertical"
|
|
130
|
-
aria-labelledby="{idBase}-agents-title"
|
|
131
|
-
bind:this={tablistEl}
|
|
132
|
-
>
|
|
133
|
-
{#each agents as agent}
|
|
134
|
-
<button
|
|
135
|
-
class="agent-button"
|
|
136
|
-
class:active={activeAgentId === agent.id}
|
|
137
|
-
role="tab"
|
|
138
|
-
aria-selected={activeAgentId === agent.id}
|
|
139
|
-
aria-controls="{idBase}-panel"
|
|
140
|
-
id="{idBase}-tab-{agent.id}"
|
|
141
|
-
data-agent-id={agent.id}
|
|
142
|
-
tabindex={activeAgentId === agent.id ? 0 : -1}
|
|
143
|
-
onclick={() => handleAgentClick(agent.id)}
|
|
144
|
-
onkeydown={(e) => handleAgentKeydown(e, agent.id)}
|
|
145
|
-
>
|
|
146
|
-
<span class="agent-class">{agent.agentClass}</span>
|
|
147
|
-
{#if agent.name}
|
|
148
|
-
<span class="agent-name">{agent.name}</span>
|
|
149
|
-
{/if}
|
|
150
|
-
</button>
|
|
151
|
-
{/each}
|
|
152
|
-
</div>
|
|
153
|
-
</aside>
|
|
154
|
-
{/if}
|
|
155
|
-
|
|
156
|
-
<main
|
|
157
|
-
class="agent-content"
|
|
158
|
-
id="{idBase}-panel"
|
|
159
|
-
role={agents.length > 1 ? 'tabpanel' : undefined}
|
|
160
|
-
aria-labelledby={agents.length > 1 && activeAgentId
|
|
161
|
-
? `${idBase}-tab-${activeAgentId}`
|
|
162
|
-
: undefined}
|
|
163
|
-
>
|
|
164
|
-
{#if activeAgent}
|
|
165
|
-
<header class="agent-header">
|
|
166
|
-
<h2 class="agent-title">{activeAgent.agentClass}</h2>
|
|
167
|
-
{#if activeAgent.name}
|
|
168
|
-
<p class="agent-subtitle">{activeAgent.name}</p>
|
|
169
|
-
{/if}
|
|
170
|
-
</header>
|
|
171
|
-
|
|
172
|
-
<AgentAdminTabs
|
|
173
|
-
{registry}
|
|
174
|
-
agentClass={activeAgent.agentClass}
|
|
175
|
-
slots={activeAgent.slots}
|
|
176
|
-
configs={configs[activeAgent.id] ?? {}}
|
|
177
|
-
onSave={handleSave}
|
|
178
|
-
{readonly}
|
|
179
|
-
fileConfigs={fileConfigs[activeAgent.id]}
|
|
180
|
-
dbConfigs={dbConfigs[activeAgent.id]}
|
|
181
|
-
/>
|
|
182
|
-
{:else if agents.length === 0}
|
|
183
|
-
<div class="no-agents">
|
|
184
|
-
<div class="no-agents-icon">🤖</div>
|
|
185
|
-
<p class="no-agents-message">{t(M['ui.agent_settings_shell.no_agents_message'])}</p>
|
|
186
|
-
<p class="no-agents-hint">
|
|
187
|
-
{t(M['ui.agent_settings_shell.no_agents_hint'])}
|
|
188
|
-
</p>
|
|
189
|
-
</div>
|
|
190
|
-
{/if}
|
|
191
|
-
</main>
|
|
192
|
-
</div>
|
|
193
|
-
|
|
194
|
-
<style>
|
|
195
|
-
.agent-settings-shell {
|
|
196
|
-
display: grid;
|
|
197
|
-
grid-template-columns: 220px 1fr;
|
|
198
|
-
gap: 1.5rem;
|
|
199
|
-
min-height: 400px;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.agent-settings-shell.single-agent {
|
|
203
|
-
grid-template-columns: 1fr;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
.agents-sidebar {
|
|
207
|
-
background: var(--smrt-color-surface-container-low, #f8fafc);
|
|
208
|
-
border-radius: var(--smrt-radius-medium, 8px);
|
|
209
|
-
padding: var(--smrt-spacing-4, 1rem);
|
|
210
|
-
border: 1px solid var(--smrt-color-outline-variant, #e2e8f0);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
.sidebar-title {
|
|
214
|
-
margin: 0 0 0.75rem 0;
|
|
215
|
-
padding: 0 0.5rem 0.75rem;
|
|
216
|
-
font-size: var(--smrt-typography-label-medium-size, 0.75rem);
|
|
217
|
-
font-weight: var(--smrt-typography-weight-semibold, 600);
|
|
218
|
-
text-transform: uppercase;
|
|
219
|
-
letter-spacing: var(--smrt-typography-label-medium-tracking, 0.05em);
|
|
220
|
-
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
221
|
-
border-bottom: 1px solid var(--smrt-color-outline-variant, #e2e8f0);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
.agents-list {
|
|
225
|
-
display: flex;
|
|
226
|
-
flex-direction: column;
|
|
227
|
-
gap: 0.25rem;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
.agent-button {
|
|
231
|
-
display: flex;
|
|
232
|
-
flex-direction: column;
|
|
233
|
-
align-items: flex-start;
|
|
234
|
-
gap: 0.125rem;
|
|
235
|
-
padding: 0.625rem 0.75rem;
|
|
236
|
-
border: none;
|
|
237
|
-
background: transparent;
|
|
238
|
-
border-radius: var(--smrt-radius-md, 8px);
|
|
239
|
-
cursor: pointer;
|
|
240
|
-
text-align: left;
|
|
241
|
-
width: 100%;
|
|
242
|
-
transition:
|
|
243
|
-
background-color var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease),
|
|
244
|
-
color var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
.agent-button:hover {
|
|
248
|
-
background: var(--smrt-color-surface-container-high, #e2e8f0);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.agent-button.active {
|
|
252
|
-
background: var(--smrt-color-primary, #3b82f6);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
.agent-button.active .agent-class,
|
|
256
|
-
.agent-button.active .agent-name {
|
|
257
|
-
color: var(--smrt-color-on-primary, white);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.agent-class {
|
|
261
|
-
font-size: var(--smrt-typography-title-small-size, 0.875rem);
|
|
262
|
-
font-weight: var(--smrt-typography-weight-semibold, 600);
|
|
263
|
-
color: var(--smrt-color-on-surface, #1e293b);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
.agent-name {
|
|
267
|
-
font-size: var(--smrt-typography-body-small-size, 0.75rem);
|
|
268
|
-
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
.agent-content {
|
|
272
|
-
min-width: 0;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.agent-header {
|
|
276
|
-
margin-bottom: 1.5rem;
|
|
277
|
-
padding-bottom: 1rem;
|
|
278
|
-
border-bottom: 1px solid var(--smrt-color-outline-variant, #e2e8f0);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
.agent-title {
|
|
282
|
-
margin: 0;
|
|
283
|
-
font-size: var(--smrt-typography-headline-medium-size, 1.5rem);
|
|
284
|
-
font-weight: var(--smrt-typography-weight-semibold, 600);
|
|
285
|
-
color: var(--smrt-color-on-surface);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
.agent-subtitle {
|
|
289
|
-
margin: 0.25rem 0 0;
|
|
290
|
-
font-size: var(--smrt-typography-body-medium-size, 0.9375rem);
|
|
291
|
-
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
.no-agents {
|
|
295
|
-
display: flex;
|
|
296
|
-
flex-direction: column;
|
|
297
|
-
align-items: center;
|
|
298
|
-
justify-content: center;
|
|
299
|
-
padding: 4rem 2rem;
|
|
300
|
-
text-align: center;
|
|
301
|
-
background: var(--smrt-color-surface-variant);
|
|
302
|
-
border: 1px dashed var(--smrt-color-outline-variant);
|
|
303
|
-
border-radius: var(--smrt-radius-md, 8px);
|
|
304
|
-
min-height: 300px;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
.no-agents-icon {
|
|
308
|
-
font-size: var(--smrt-typography-display-medium-size, 3rem);
|
|
309
|
-
margin-bottom: 1rem;
|
|
310
|
-
opacity: 0.5;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
.no-agents-message {
|
|
314
|
-
margin: 0 0 0.5rem 0;
|
|
315
|
-
font-size: var(--smrt-typography-body-large-size, 1rem);
|
|
316
|
-
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
.no-agents-hint {
|
|
320
|
-
margin: 0;
|
|
321
|
-
font-size: var(--smrt-typography-body-medium-size, 0.875rem);
|
|
322
|
-
color: var(--smrt-color-on-surface-variant, #94a3b8);
|
|
323
|
-
max-width: 400px;
|
|
324
|
-
}
|
|
325
|
-
</style>
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { AgentUIComponentRegistry, AgentUISlots } from '@happyvertical/smrt-agents/ui';
|
|
2
|
-
/**
|
|
3
|
-
* Serialized agent data passed from server
|
|
4
|
-
* (Agent instances can't be passed directly to client)
|
|
5
|
-
*/
|
|
6
|
-
interface AgentData {
|
|
7
|
-
id: string;
|
|
8
|
-
name?: string;
|
|
9
|
-
/** Agent class name (e.g., 'Praeco') - determined from _meta_type or explicit */
|
|
10
|
-
agentClass: string;
|
|
11
|
-
/** UI slots for this agent */
|
|
12
|
-
slots: AgentUISlots;
|
|
13
|
-
}
|
|
14
|
-
export interface Props {
|
|
15
|
-
/** The registry to look up components from */
|
|
16
|
-
registry: AgentUIComponentRegistry;
|
|
17
|
-
/** List of agents to display (serialized data, not instances) */
|
|
18
|
-
agents: AgentData[];
|
|
19
|
-
/** Config data for each agent and slot: agentId -> slotId -> config */
|
|
20
|
-
configs: Record<string, Record<string, unknown>>;
|
|
21
|
-
/** Callback when a config is saved */
|
|
22
|
-
onSave?: (agentId: string, slotId: string, config: unknown) => Promise<void>;
|
|
23
|
-
/** Whether all panels are read-only */
|
|
24
|
-
readonly?: boolean;
|
|
25
|
-
/** File configs: agentId -> slotId -> config */
|
|
26
|
-
fileConfigs?: Record<string, Record<string, unknown>>;
|
|
27
|
-
/** Database configs: agentId -> slotId -> config */
|
|
28
|
-
dbConfigs?: Record<string, Record<string, unknown>>;
|
|
29
|
-
}
|
|
30
|
-
declare const AgentSettingsShell: import("svelte").Component<Props, {}, "">;
|
|
31
|
-
type AgentSettingsShell = ReturnType<typeof AgentSettingsShell>;
|
|
32
|
-
export default AgentSettingsShell;
|
|
33
|
-
//# sourceMappingURL=AgentSettingsShell.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AgentSettingsShell.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AgentSettingsShell.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,wBAAwB,EACxB,YAAY,EACb,MAAM,+BAA+B,CAAC;AAMvC;;;GAGG;AACH,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,KAAK;IACpB,8CAA8C;IAC9C,QAAQ,EAAE,wBAAwB,CAAC;IACnC,iEAAiE;IACjE,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACjD,sCAAsC;IACtC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACrD;AAwID,QAAA,MAAM,kBAAkB,2CAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Regression: the agent switcher is a proper ARIA tablist (C8).
|
|
3
|
-
*
|
|
4
|
-
* It was a <nav> of <button>s acting as single-select tabs, with no
|
|
5
|
-
* role/aria-selected/roving-tabindex/arrow-key nav — unlike sibling
|
|
6
|
-
* AgentAdminTabs which does the full tablist. The fix adds role="tablist" +
|
|
7
|
-
* role="tab" + aria-selected + roving tabindex + Up/Down/Home/End navigation,
|
|
8
|
-
* and marks the content panel role="tabpanel".
|
|
9
|
-
*/
|
|
10
|
-
import { createUIRegistry } from '@happyvertical/smrt-agents/ui';
|
|
11
|
-
import { render, screen, waitFor, within } from '@testing-library/svelte';
|
|
12
|
-
import userEvent from '@testing-library/user-event';
|
|
13
|
-
import { describe, expect, it } from 'vitest';
|
|
14
|
-
import AgentSettingsShell from '../AgentSettingsShell.svelte';
|
|
15
|
-
/**
|
|
16
|
-
* Roving focus moves via requestAnimationFrame, so wait for the expected tab to
|
|
17
|
-
* actually receive focus before dispatching the next key (otherwise the next
|
|
18
|
-
* keydown fires on the previously-focused tab).
|
|
19
|
-
*/
|
|
20
|
-
async function expectFocused(el) {
|
|
21
|
-
await waitFor(() => expect(el).toHaveFocus());
|
|
22
|
-
}
|
|
23
|
-
function agents() {
|
|
24
|
-
return [
|
|
25
|
-
{ id: 'a1', agentClass: 'Praeco', name: 'Alpha', slots: {} },
|
|
26
|
-
{ id: 'a2', agentClass: 'Caelus', name: 'Beta', slots: {} },
|
|
27
|
-
{ id: 'a3', agentClass: 'Nimbus', name: 'Gamma', slots: {} },
|
|
28
|
-
];
|
|
29
|
-
}
|
|
30
|
-
function renderShell() {
|
|
31
|
-
return render(AgentSettingsShell, {
|
|
32
|
-
props: {
|
|
33
|
-
registry: createUIRegistry(),
|
|
34
|
-
agents: agents(),
|
|
35
|
-
configs: {},
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* The shell embeds AgentAdminTabs (its own slot tablist), so scope queries to
|
|
41
|
-
* the agent-switcher tablist — identified by its "Agents" accessible name.
|
|
42
|
-
*/
|
|
43
|
-
function switcher() {
|
|
44
|
-
return screen.getByRole('tablist', { name: 'Agents' });
|
|
45
|
-
}
|
|
46
|
-
function switcherTabs() {
|
|
47
|
-
return within(switcher()).getAllByRole('tab');
|
|
48
|
-
}
|
|
49
|
-
describe('AgentSettingsShell — agent switcher tablist (C8)', () => {
|
|
50
|
-
it('renders a tablist of tabs with the first selected', () => {
|
|
51
|
-
renderShell();
|
|
52
|
-
expect(switcher()).toBeInTheDocument();
|
|
53
|
-
const tabs = switcherTabs();
|
|
54
|
-
expect(tabs).toHaveLength(3);
|
|
55
|
-
expect(tabs[0]).toHaveAttribute('aria-selected', 'true');
|
|
56
|
-
expect(tabs[1]).toHaveAttribute('aria-selected', 'false');
|
|
57
|
-
});
|
|
58
|
-
it('uses a roving tabindex (only the selected tab is tabbable)', () => {
|
|
59
|
-
renderShell();
|
|
60
|
-
const tabs = switcherTabs();
|
|
61
|
-
expect(tabs[0]).toHaveAttribute('tabindex', '0');
|
|
62
|
-
expect(tabs[1]).toHaveAttribute('tabindex', '-1');
|
|
63
|
-
expect(tabs[2]).toHaveAttribute('tabindex', '-1');
|
|
64
|
-
});
|
|
65
|
-
it('moves selection with ArrowDown / ArrowUp', async () => {
|
|
66
|
-
renderShell();
|
|
67
|
-
switcherTabs()[0].focus();
|
|
68
|
-
await userEvent.keyboard('{ArrowDown}');
|
|
69
|
-
expect(switcherTabs()[1]).toHaveAttribute('aria-selected', 'true');
|
|
70
|
-
await expectFocused(switcherTabs()[1]);
|
|
71
|
-
await userEvent.keyboard('{ArrowUp}');
|
|
72
|
-
expect(switcherTabs()[0]).toHaveAttribute('aria-selected', 'true');
|
|
73
|
-
await expectFocused(switcherTabs()[0]);
|
|
74
|
-
});
|
|
75
|
-
it('jumps to last/first with End / Home', async () => {
|
|
76
|
-
renderShell();
|
|
77
|
-
switcherTabs()[0].focus();
|
|
78
|
-
await userEvent.keyboard('{End}');
|
|
79
|
-
expect(switcherTabs()[2]).toHaveAttribute('aria-selected', 'true');
|
|
80
|
-
await expectFocused(switcherTabs()[2]);
|
|
81
|
-
await userEvent.keyboard('{Home}');
|
|
82
|
-
expect(switcherTabs()[0]).toHaveAttribute('aria-selected', 'true');
|
|
83
|
-
await expectFocused(switcherTabs()[0]);
|
|
84
|
-
});
|
|
85
|
-
it('exposes a tabpanel wired to the selected tab', () => {
|
|
86
|
-
renderShell();
|
|
87
|
-
const panel = screen.getByRole('tabpanel');
|
|
88
|
-
const selectedTab = switcherTabs().find((t) => t.getAttribute('aria-selected') === 'true');
|
|
89
|
-
expect(selectedTab).toBeTruthy();
|
|
90
|
-
expect(panel).toHaveAttribute('aria-labelledby', selectedTab?.id);
|
|
91
|
-
expect(selectedTab).toHaveAttribute('aria-controls', panel.id);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export type { AdminPanelBaseProps, AgentUIComponentRegistry, AgentUISlot, AgentUISlots, } from '@happyvertical/smrt-agents/ui';
|
|
2
|
-
export { default as AgentAdminPanel } from './AgentAdminPanel.svelte';
|
|
3
|
-
export { default as AgentAdminTabs } from './AgentAdminTabs.svelte';
|
|
4
|
-
export { default as AgentSettingsShell } from './AgentSettingsShell.svelte';
|
|
5
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/admin/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,YAAY,GACb,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// Admin Panel Components
|
|
2
|
-
// These components work with @happyvertical/smrt-agents to render
|
|
3
|
-
// agent admin panels dynamically based on the AgentUIRegistry.
|
|
4
|
-
export { default as AgentAdminPanel } from './AgentAdminPanel.svelte';
|
|
5
|
-
export { default as AgentAdminTabs } from './AgentAdminTabs.svelte';
|
|
6
|
-
export { default as AgentSettingsShell } from './AgentSettingsShell.svelte';
|