@happyvertical/smrt-agents 0.39.4 → 0.39.6

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.
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "version": "1.0.0",
3
- "timestamp": 1783819628552,
3
+ "timestamp": 1783845602986,
4
4
  "packageName": "@happyvertical/smrt-agents",
5
- "packageVersion": "0.39.4",
5
+ "packageVersion": "0.39.6",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-agents:Agent": {
8
8
  "name": "agent",
9
9
  "className": "Agent",
10
10
  "qualifiedName": "@happyvertical/smrt-agents:Agent",
11
11
  "collection": "agents",
12
- "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-b6zmd/smrt/smrt/packages/agents/src/agent.ts",
12
+ "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-xv52x/smrt/smrt/packages/agents/src/agent.ts",
13
13
  "packageName": "@happyvertical/smrt-agents",
14
14
  "fields": {
15
15
  "created_at": {
@@ -542,6 +542,20 @@
542
542
  "isStatic": false,
543
543
  "isPublic": true
544
544
  },
545
+ "getConfigOwnerId": {
546
+ "name": "getConfigOwnerId",
547
+ "async": false,
548
+ "parameters": [
549
+ {
550
+ "name": "slotId",
551
+ "type": "string",
552
+ "optional": true
553
+ }
554
+ ],
555
+ "returnType": "string | null",
556
+ "isStatic": false,
557
+ "isPublic": true
558
+ },
545
559
  "getDispatchSubscriber": {
546
560
  "name": "getDispatchSubscriber",
547
561
  "async": false,
@@ -785,7 +799,7 @@
785
799
  "className": "AgentConfig",
786
800
  "qualifiedName": "@happyvertical/smrt-agents:AgentConfig",
787
801
  "collection": "agentconfigs",
788
- "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-b6zmd/smrt/smrt/packages/agents/src/config.ts",
802
+ "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-xv52x/smrt/smrt/packages/agents/src/config.ts",
789
803
  "packageName": "@happyvertical/smrt-agents",
790
804
  "fields": {
791
805
  "tenantId": {
@@ -1028,7 +1042,7 @@
1028
1042
  "className": "AgentConfigCollection",
1029
1043
  "qualifiedName": "@happyvertical/smrt-agents:AgentConfigCollection",
1030
1044
  "collection": "agentconfigs",
1031
- "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-b6zmd/smrt/smrt/packages/agents/src/config.ts",
1045
+ "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-xv52x/smrt/smrt/packages/agents/src/config.ts",
1032
1046
  "packageName": "@happyvertical/smrt-agents",
1033
1047
  "fields": {},
1034
1048
  "methods": {
@@ -1130,7 +1144,7 @@
1130
1144
  "className": "AgentSchedule",
1131
1145
  "qualifiedName": "@happyvertical/smrt-agents:AgentSchedule",
1132
1146
  "collection": "agentschedules",
1133
- "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-b6zmd/smrt/smrt/packages/agents/src/schedule.ts",
1147
+ "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-xv52x/smrt/smrt/packages/agents/src/schedule.ts",
1134
1148
  "packageName": "@happyvertical/smrt-agents",
1135
1149
  "fields": {
1136
1150
  "tenantId": {
@@ -1512,7 +1526,7 @@
1512
1526
  "className": "AgentScheduleCollection",
1513
1527
  "qualifiedName": "@happyvertical/smrt-agents:AgentScheduleCollection",
1514
1528
  "collection": "agentschedules",
1515
- "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-b6zmd/smrt/smrt/packages/agents/src/schedule.ts",
1529
+ "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-xv52x/smrt/smrt/packages/agents/src/schedule.ts",
1516
1530
  "packageName": "@happyvertical/smrt-agents",
1517
1531
  "fields": {},
1518
1532
  "methods": {
@@ -1652,7 +1666,7 @@
1652
1666
  "className": "TenantAgent",
1653
1667
  "qualifiedName": "@happyvertical/smrt-agents:TenantAgent",
1654
1668
  "collection": "tenantagents",
1655
- "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-b6zmd/smrt/smrt/packages/agents/src/tenant-agent.ts",
1669
+ "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-xv52x/smrt/smrt/packages/agents/src/tenant-agent.ts",
1656
1670
  "packageName": "@happyvertical/smrt-agents",
1657
1671
  "fields": {
1658
1672
  "tenantId": {
@@ -1821,7 +1835,7 @@
1821
1835
  "className": "TenantAgentCollection",
1822
1836
  "qualifiedName": "@happyvertical/smrt-agents:TenantAgentCollection",
1823
1837
  "collection": "tenantagents",
1824
- "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-b6zmd/smrt/smrt/packages/agents/src/tenant-agent.ts",
1838
+ "filePath": "/home/runner/.local/share/pnpm/store/.workspaces/arc-happyvertical-node-phdrb-runner-xv52x/smrt/smrt/packages/agents/src/tenant-agent.ts",
1825
1839
  "packageName": "@happyvertical/smrt-agents",
1826
1840
  "fields": {},
1827
1841
  "methods": {
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-07-12T01:27:13.570Z",
3
+ "generatedAt": "2026-07-12T08:40:06.105Z",
4
4
  "packageName": "@happyvertical/smrt-agents",
5
- "packageVersion": "0.39.4",
5
+ "packageVersion": "0.39.6",
6
6
  "sourceManifestPath": "dist/manifest.json",
7
7
  "agentDocPath": "AGENTS.md",
8
8
  "sourceHashes": {
9
- "manifest": "e4fc0faa6812755258868acc31b464fd50d581e58f6d46a8b5a66b485715ede2",
10
- "packageJson": "0f10523a4333352bcd600f3c4a19c38d28741f85fc6f620a1a7d9c1851316463",
11
- "agents": "0abf501785ff63b6c01fe714286761181f8ce4de1c08b689e6f691423dc25a87"
9
+ "manifest": "80f41958f3d38f9313a6f012d13e8e5da04f49296e0592e1a2626849936ada41",
10
+ "packageJson": "90070f497e52fdf47df2d7b00d4086c2be8e51f25143331c9fc626c91b817f5a",
11
+ "agents": "737f345126de4f98e96586ac78c8b366f838296a7e85d2fa90fad4f3ed6c7ed6"
12
12
  },
13
13
  "exports": [
14
14
  ".",
@@ -118,6 +118,7 @@
118
118
  "generateEmbeddings",
119
119
  "getAiUsageSnapshot",
120
120
  "getAvailableTools",
121
+ "getConfigOwnerId",
121
122
  "getDispatch",
122
123
  "getDispatchSubscriber",
123
124
  "getEmbedding",
@@ -983,5 +984,5 @@
983
984
  "polymorphicAssociations": 0,
984
985
  "uuidColumns": 11
985
986
  },
986
- "agentDoc": "# @happyvertical/smrt-agents\n\nAgent framework for autonomous actors with inter-agent messaging, interest-based object discovery, scheduling, and multi-tenant bindings.\n\n## Agent Lifecycle\n\n`initialize()` → `validate()` → `run()` → `shutdown()`\n\n- Extend `Agent` (which extends `SmrtObject`) and implement `run()`\n- Status tracking: `idle → initializing → running → error/shutdown`\n- `execute()` runs the full lifecycle automatically\n- Process signal handling is opt-in via `manageProcessSignals: true` and is intended for single-agent processes\n\n## DispatchBus — Inter-Agent Communication\n\nAgents communicate via persistent async messaging through core's DispatchBus:\n\n```typescript\n// Emitting (in any agent)\nconst bus = await this.getDispatch();\nawait bus.emit('campaign.completed', { campaignId: '123' }, { source: 'Suasor' });\n\n// Subscribing (in receiving agent)\nasync handleDispatch(payload: unknown, metadata: DispatchMetadata): Promise<void> {\n if (metadata.type === 'campaign.completed') await this.recordRevenue(payload);\n}\nasync run() { await this.processDispatches(); } // processes via handleDispatch()\n```\n\nCLI: `smrt dispatch:list`, `dispatch:process --subscriber Fiscus`, `dispatch:retry`, `dispatch:cleanup`\n\n## Interests — Object Discovery\n\nAgents query objects they care about via declarative filters:\n\n```typescript\nconstructor(options) {\n super({ ...options, interests: {\n objects: { Meeting: { filter: { status: 'upcoming' }, handler: async (m) => ({ action: 'recap' }) } },\n qualify: async (items) => items.filter(/* AI-based post-filter */),\n }});\n}\nasync run() { for (const { type, data } of await this.interesting()) { ... } }\n```\n\n## Configuration\n\n- **File-based**: `getModuleConfig('agent-name', defaults)` from `smrt.config.ts`\n- **DB-persisted**: `saveSlotConfig(slotId, data)` for UI overrides\n- **Merged**: `getMergedConfig('slotId')` — DB overrides file config\n- **UI slots**: `static uiSlots` declares admin panels (id, label, icon, order)\n\n## TenantAgent — Multi-Tenant Bindings\n\nJunction table (`tenant_agents`) binding agents to tenants with permission overrides and hierarchy resolution:\n- Explicit binding: row exists for tenant (source: 'explicit')\n- Inherited: walks up tenant hierarchy (source: 'inherited')\n- Permissions: manifest defaults merged with per-tenant overrides\n\n## AgentSchedule\n\nCron-based scheduling stored in `_smrt_agent_schedules`. Fields: `agentType`, `cron`, `method` (default: 'run'), `maxConcurrent`, `timeout`. Executed by ScheduleRunner from smrt-jobs.\n\n## Lazy agent_config Resolution (issue #1161)\n\nPersisted `agent_config` snapshots env-derived values at sync time, so rotated env vars don't reach already-stored schedule rows. Two complementary mechanisms unfreeze them:\n\n1. **`$env` sentinels in persisted config** — register a global resolver and reference it from the JSON:\n\n ```ts\n import { registerConfigResolver } from '@happyvertical/smrt-agents';\n registerConfigResolver('sharedAssetStorage', () => resolveSharedAssetStorage());\n // persisted: { \"assetStorage\": { \"$env\": \"sharedAssetStorage\" } }\n ```\n\n2. **`static configResolvers` on the agent class** — declarative, discoverable via the class itself:\n\n ```ts\n class Praeco extends Agent {\n static override configResolvers = {\n assetStorage: () => resolveSharedAssetStorage(),\n };\n }\n ```\n\nThe TaskRunner calls `resolveLazyConfig()` immediately before constructing the agent, so live values always win over snapshotted ones. Re-exported from `@happyvertical/smrt-core` (`resolveLazyConfig`, `registerConfigResolver`, `getClassConfigResolvers`, …) for cases where agents isn't on the import path.\n\n## Learning Trait (issue #1886) — opt-in\n\nAny agent can opt into a confidence-scored **recall-before / capture-after** loop backed by core's `LearningMemory` (over `_smrt_contexts` + `_smrt_embeddings`). **Off by default** — a non-opted agent behaves byte-for-byte as today; the lifecycle's learning branches are never entered.\n\n```typescript\n@smrt()\nclass InvoiceAgent extends Agent {\n static override learning = true; // or { minConfidence: 0.8, scope: 'invoices', ... }\n protected config = {};\n\n async run() {\n // recall-before-run already populated `recalledMemories` (confidence >= floor)\n const cached = this.recalledMemories.find((m) => m.key === this.docUrl);\n const strategy = cached?.value ?? (await this.generateStrategy());\n\n // stage the episode; the lifecycle reinforces it after run()\n this.stageLearning({ scope: this.learningScope(), key: this.docUrl, value: strategy });\n\n // a validated failure decays the memory without throwing\n if (!ok) this.reportLearningOutcome({ success: false, error: 'no match' });\n }\n}\n```\n\n- **`capture` semantics** (`LearningMemory`): success strengthens `confidence` toward 1.0 and increments `success_count`; failure decays toward `failureConfidence` (0.3) and increments `failure_count`. A single failure drops a confident memory below the reuse floor (0.7), so recall stops returning it. Refreshes `last_used_at`; honours `expires_at` and optional time-decay.\n- **Memory isolation**: bound to `(agentType, agentInstanceId)` as `(owner_class, owner_id)`, so two tenants on the same agent class never share memory. `tenantId` is threaded into the optional semantic-search `where`.\n- **Seams to override**: `learningScope()`, `recallForRun(memory)`, `captureForRun(memory, outcome)`, `getLearningSemanticSearch()`. Helpers for `run()`: `stageLearning(episode)`, `reportLearningOutcome(outcome)`, `getLearningMemory()`, and the `recalledMemories` field.\n- **Config**: `static learning: boolean | AgentLearningConfig` — `{ enabled?, scope?, minConfidence?, successConfidence?, failureConfidence?, reinforcement?, decayHalfLifeMs? }`. `LearningMemory` and its types are re-exported from `@happyvertical/smrt-core`.\n\n## Multi-Instance Agents (issue #1890) — opt-in\n\n`static multiInstance = false` by default: a class is a **singleton** (the N=1 case) and is byte-for-byte unchanged — one dispatch subscriber keyed by the agent type, one memory scope, class-wide interests. Set `static multiInstance = true` to run N durable instances (personas, from `@happyvertical/smrt-personas`) of one class per tenant, each independent.\n\nThe framework provides only the per-instance **identity**; a package scopes its own dispatch/interests to the instance's config by overriding the seams.\n\n- **`AgentOptions.instanceKey`** — the durable per-instance key (typically the persona id). Honored **only** when `multiInstance` is true, so passing it to a non-opted agent is a no-op.\n- **`getInstanceKey()`** → the key, or `null` for a singleton (opt-in off, or no key).\n- **`getDispatchSubscriber()`** → `` `${agentType}#${key}` `` for a multi-instance agent, the bare `agentType` for a singleton. Used everywhere the agent subscribes/seeds/processes, so each instance has its own subscription rows and pending-dispatch queue — two instances never compete for or double-process each other's dispatches. Composed by the exported `instanceScopedSubscriber(agentType, key)`.\n- **`learningScope()`** — suffixed with `#<key>` for a multi-instance agent, so instances learn independently (singleton scope unchanged).\n- **Seams to override** (both default to singleton behavior):\n - `resolveSignalSubscriptions()` — derive **instance-scoped** signal types from the instance config so an emit meant for one instance only matches its subscription.\n - `instanceInterestFilter()` — an `ObjectFilter` AND-merged (as the base layer) into every `interesting()` query so instances partition the objects they process.\n\nThe **`default` persona reuses the singleton identity** (a `null` key), which is what makes the singleton→multi upgrade non-destructive — see `@happyvertical/smrt-personas` (`personaInstanceKey`, `upgradeSingletonToDefaultPersona`).\n\n## Principal Execution (issue #1888)\n\n`executeAsPrincipal(options, fn)` runs agent work **AS a persona's bound user**, reusing the existing RBAC cascade with no snapshotting. It publishes `(user_id, tenant_id, permissions[])` onto the DB session (Postgres RLS then bounds every query per-`(table, action)` and per-tenant) and hands `fn` a `PrincipalRun` whose `assertToolAllowed()` / `assertOperation()` enforce the persona tool ceiling and the RLS-off catalog gate. Effective authority = **bound-user RBAC ∩ agent-class ceiling ∩ persona `allowedTools`**. Actions audit as on-behalf-of the originating user via a `PrincipalAuditSink`.\n\n## Agent Orchestration (issue #1892) — invoke-agent + principal delegation\n\nA conversational (orchestrator) agent can invoke worker agents with **principal delegation**. This is *not* a new engine — it is a standard `invoke-agent` tool plus a completion-dispatch convention on top of `executeAsPrincipal` + the DispatchBus.\n\n```typescript\nimport { createInvokeAgentTool, rootDelegationEnvelope } from '@happyvertical/smrt-agents';\n\nconst tool = createInvokeAgentTool({\n db,\n parentEnvelope: rootDelegationEnvelope({ runAsUserId, tenantId, onBehalfOfUserId }),\n worker: async ({ run, agentClass, task }) => runWorker(run, agentClass, task),\n});\n// Offered through the chat tool loop as an `extraTools` entry, gated by the\n// persona's allowedTools like any other tool (slug: 'agents.invoke').\n```\n\n- **`DelegationEnvelope`** carries the **immutable principal** (`runAsUserId` + `tenantId` + originating `onBehalfOfUserId`) and a bounded `depth`. `deriveDelegationEnvelope()` copies the principal verbatim and asserts `depth <= MAX_DELEGATION_DEPTH` (3) — a worker cannot invoke a further worker under a broader principal (`PrincipalWideningError` / `DelegationDepthExceededError`).\n- **`createInvokeAgentTool()`** → a `PrincipalTool` whose handler derives the child envelope with the principal taken **from the live run context, never the tool args**, so the invoke-agent tool is structurally immune to principal widening.\n- **`executeDelegatedInvocation()`** runs the worker via `executeAsPrincipal` under that same principal and emits a correlated `agent.completed` dispatch; **`surfaceAgentCompletions(bus, correlationId)`** reads it back into the conversation.\n- **Transports** (pluggable): the default `inlineInvokeAgentTransport` runs the worker in-process (completion surfaces in the same turn); `createDispatchInvokeTransport(bus)` emits an `agent.invoke` signal a worker processes via `processAgentInvocations()` (async). A job-queue transport (enqueue on the `agents` queue) is a consumer-supplied `InvokeAgentTransport` — orchestration never hard-depends on `@happyvertical/smrt-jobs`, which sits *below* agents in the dependency graph.\n\n## Key Files\n\n| File | Purpose |\n|------|---------|\n| `src/agent.ts` | Base Agent class — lifecycle, dispatch, interests, config, opt-in learning trait, multi-instance identity |\n| `src/execute-as-principal.ts` | `executeAsPrincipal` / `PrincipalRun` — run agent work as a persona's bound user (#1888) |\n| `src/delegation.ts` | `DelegationEnvelope` — immutable principal + bounded delegation depth (#1892) |\n| `src/invoke-agent.ts` | `invoke-agent` tool, worker executor, completion-dispatch convention, transports (#1892) |\n| `src/learning.ts` | `AgentLearningConfig` + `resolveAgentLearning()` declaration normalisation |\n| `src/schedule.ts` | AgentSchedule model — cron, execution tracking |\n| `src/tenant-agent.ts` | TenantAgent — junction table, hierarchical resolution |\n| `src/interests.ts` | Interest filter types and configuration |\n| `src/config.ts` | File + DB config management, UI slots |\n"
987
+ "agentDoc": "# @happyvertical/smrt-agents\n\nAgent framework for autonomous actors with inter-agent messaging, interest-based object discovery, scheduling, and multi-tenant bindings.\n\n## Agent Lifecycle\n\n`initialize()` → `validate()` → `run()` → `shutdown()`\n\n- Extend `Agent` (which extends `SmrtObject`) and implement `run()`\n- Status tracking: `idle → initializing → running → error/shutdown`\n- `execute()` runs the full lifecycle automatically\n- Process signal handling is opt-in via `manageProcessSignals: true` and is intended for single-agent processes\n\n## DispatchBus — Inter-Agent Communication\n\nAgents communicate via persistent async messaging through core's DispatchBus:\n\n```typescript\n// Emitting (in any agent)\nconst bus = await this.getDispatch();\nawait bus.emit('campaign.completed', { campaignId: '123' }, { source: 'Suasor' });\n\n// Subscribing (in receiving agent)\nasync handleDispatch(payload: unknown, metadata: DispatchMetadata): Promise<void> {\n if (metadata.type === 'campaign.completed') await this.recordRevenue(payload);\n}\nasync run() { await this.processDispatches(); } // processes via handleDispatch()\n```\n\nCLI: `smrt dispatch:list`, `dispatch:process --subscriber Fiscus`, `dispatch:retry`, `dispatch:cleanup`\n\n## Interests — Object Discovery\n\nAgents query objects they care about via declarative filters:\n\n```typescript\nconstructor(options) {\n super({ ...options, interests: {\n objects: { Meeting: { filter: { status: 'upcoming' }, handler: async (m) => ({ action: 'recap' }) } },\n qualify: async (items) => items.filter(/* AI-based post-filter */),\n }});\n}\nasync run() { for (const { type, data } of await this.interesting()) { ... } }\n```\n\n## Configuration\n\n- **File-based**: `getModuleConfig('agent-name', defaults)` from `smrt.config.ts`\n- **DB-persisted**: `saveSlotConfig(slotId, data)` for UI overrides. Persona-backed\n agents use `AgentOptions.personaId` as the durable config owner; legacy agents\n use the saved Agent row id.\n- **Merged**: `getMergedConfig('slotId')` — DB overrides file config\n- **UI slots**: `static uiSlots` declares admin panels (id, label, icon, order,\n `scope`, optional versioned `settingsSchema`). Without a registered custom\n component, `AgentSettingsForm` renders that schema.\n\n## TenantAgent — Multi-Tenant Bindings\n\nJunction table (`tenant_agents`) binding agents to tenants with permission overrides and hierarchy resolution:\n- Explicit binding: row exists for tenant (source: 'explicit')\n- Inherited: walks up tenant hierarchy (source: 'inherited')\n- Permissions: manifest defaults merged with per-tenant overrides\n\n## AgentSchedule\n\nCron-based scheduling stored in `_smrt_agent_schedules`. Fields: `agentType`, `cron`, `method` (default: 'run'), `maxConcurrent`, `timeout`. Executed by ScheduleRunner from smrt-jobs.\n\n## Lazy agent_config Resolution (issue #1161)\n\nPersisted `agent_config` snapshots env-derived values at sync time, so rotated env vars don't reach already-stored schedule rows. Two complementary mechanisms unfreeze them:\n\n1. **`$env` sentinels in persisted config** — register a global resolver and reference it from the JSON:\n\n ```ts\n import { registerConfigResolver } from '@happyvertical/smrt-agents';\n registerConfigResolver('sharedAssetStorage', () => resolveSharedAssetStorage());\n // persisted: { \"assetStorage\": { \"$env\": \"sharedAssetStorage\" } }\n ```\n\n2. **`static configResolvers` on the agent class** — declarative, discoverable via the class itself:\n\n ```ts\n class Praeco extends Agent {\n static override configResolvers = {\n assetStorage: () => resolveSharedAssetStorage(),\n };\n }\n ```\n\nThe TaskRunner calls `resolveLazyConfig()` immediately before constructing the agent, so live values always win over snapshotted ones. Re-exported from `@happyvertical/smrt-core` (`resolveLazyConfig`, `registerConfigResolver`, `getClassConfigResolvers`, …) for cases where agents isn't on the import path.\n\n## Learning Trait (issue #1886) — opt-in\n\nAny agent can opt into a confidence-scored **recall-before / capture-after** loop backed by core's `LearningMemory` (over `_smrt_contexts` + `_smrt_embeddings`). **Off by default** — a non-opted agent behaves byte-for-byte as today; the lifecycle's learning branches are never entered.\n\n```typescript\n@smrt()\nclass InvoiceAgent extends Agent {\n static override learning = true; // or { minConfidence: 0.8, scope: 'invoices', ... }\n protected config = {};\n\n async run() {\n // recall-before-run already populated `recalledMemories` (confidence >= floor)\n const cached = this.recalledMemories.find((m) => m.key === this.docUrl);\n const strategy = cached?.value ?? (await this.generateStrategy());\n\n // stage the episode; the lifecycle reinforces it after run()\n this.stageLearning({ scope: this.learningScope(), key: this.docUrl, value: strategy });\n\n // a validated failure decays the memory without throwing\n if (!ok) this.reportLearningOutcome({ success: false, error: 'no match' });\n }\n}\n```\n\n- **`capture` semantics** (`LearningMemory`): success strengthens `confidence` toward 1.0 and increments `success_count`; failure decays toward `failureConfidence` (0.3) and increments `failure_count`. A single failure drops a confident memory below the reuse floor (0.7), so recall stops returning it. Refreshes `last_used_at`; honours `expires_at` and optional time-decay.\n- **Memory isolation**: bound to `(agentType, agentInstanceId)` as `(owner_class, owner_id)`, so two tenants on the same agent class never share memory. `tenantId` is threaded into the optional semantic-search `where`.\n- **Seams to override**: `learningScope()`, `recallForRun(memory)`, `captureForRun(memory, outcome)`, `getLearningSemanticSearch()`. Helpers for `run()`: `stageLearning(episode)`, `reportLearningOutcome(outcome)`, `getLearningMemory()`, and the `recalledMemories` field.\n- **Config**: `static learning: boolean | AgentLearningConfig` — `{ enabled?, scope?, minConfidence?, successConfidence?, failureConfidence?, reinforcement?, decayHalfLifeMs? }`. `LearningMemory` and its types are re-exported from `@happyvertical/smrt-core`.\n\n## Multi-Instance Agents (issue #1890) — opt-in\n\n`static multiInstance = false` by default: a class is a **singleton** (the N=1 case) and is byte-for-byte unchanged — one dispatch subscriber keyed by the agent type, one memory scope, class-wide interests. Set `static multiInstance = true` to run N durable instances (personas, from `@happyvertical/smrt-personas`) of one class per tenant, each independent.\n\nThe framework provides only the per-instance **identity**; a package scopes its own dispatch/interests to the instance's config by overriding the seams.\n\n- **`AgentOptions.personaId`** — durable persona/settings identity, including\n the default persona. Independent from execution instance identity.\n- **`AgentOptions.instanceKey`** — the durable execution-instance key (typically\n the persona id, but null for the default persona). Honored **only** when\n `multiInstance` is true, so passing it to a non-opted agent is a no-op.\n- **`getInstanceKey()`** → the key, or `null` for a singleton (opt-in off, or no key).\n- **`getDispatchSubscriber()`** → `` `${agentType}#${key}` `` for a multi-instance agent, the bare `agentType` for a singleton. Used everywhere the agent subscribes/seeds/processes, so each instance has its own subscription rows and pending-dispatch queue — two instances never compete for or double-process each other's dispatches. Composed by the exported `instanceScopedSubscriber(agentType, key)`.\n- **`learningScope()`** — suffixed with `#<key>` for a multi-instance agent, so instances learn independently (singleton scope unchanged).\n- **Seams to override** (both default to singleton behavior):\n - `resolveSignalSubscriptions()` — derive **instance-scoped** signal types from the instance config so an emit meant for one instance only matches its subscription.\n - `instanceInterestFilter()` — an `ObjectFilter` AND-merged (as the base layer) into every `interesting()` query so instances partition the objects they process.\n\nThe **`default` persona reuses the singleton identity** (a `null` key), which is what makes the singleton→multi upgrade non-destructive — see `@happyvertical/smrt-personas` (`personaInstanceKey`, `upgradeSingletonToDefaultPersona`).\n\n## Principal Execution (issue #1888)\n\n`executeAsPrincipal(options, fn)` runs agent work **AS a persona's bound user**, reusing the existing RBAC cascade with no snapshotting. It publishes `(user_id, tenant_id, permissions[])` onto the DB session (Postgres RLS then bounds every query per-`(table, action)` and per-tenant) and hands `fn` a `PrincipalRun` whose `assertToolAllowed()` / `assertOperation()` enforce the persona tool ceiling and the RLS-off catalog gate. Effective authority = **bound-user RBAC ∩ agent-class ceiling ∩ persona `allowedTools`**. Actions audit as on-behalf-of the originating user via a `PrincipalAuditSink`.\n\n## Agent Orchestration (issue #1892) — invoke-agent + principal delegation\n\nA conversational (orchestrator) agent can invoke worker agents with **principal delegation**. This is *not* a new engine — it is a standard `invoke-agent` tool plus a completion-dispatch convention on top of `executeAsPrincipal` + the DispatchBus.\n\n```typescript\nimport { createInvokeAgentTool, rootDelegationEnvelope } from '@happyvertical/smrt-agents';\n\nconst tool = createInvokeAgentTool({\n db,\n parentEnvelope: rootDelegationEnvelope({ runAsUserId, tenantId, onBehalfOfUserId }),\n worker: async ({ run, agentClass, task }) => runWorker(run, agentClass, task),\n});\n// Offered through the chat tool loop as an `extraTools` entry, gated by the\n// persona's allowedTools like any other tool (slug: 'agents.invoke').\n```\n\n- **`DelegationEnvelope`** carries the **immutable principal** (`runAsUserId` + `tenantId` + originating `onBehalfOfUserId`) and a bounded `depth`. `deriveDelegationEnvelope()` copies the principal verbatim and asserts `depth <= MAX_DELEGATION_DEPTH` (3) — a worker cannot invoke a further worker under a broader principal (`PrincipalWideningError` / `DelegationDepthExceededError`).\n- **`createInvokeAgentTool()`** → a `PrincipalTool` whose handler derives the child envelope with the principal taken **from the live run context, never the tool args**, so the invoke-agent tool is structurally immune to principal widening.\n- **`executeDelegatedInvocation()`** runs the worker via `executeAsPrincipal` under that same principal and emits a correlated `agent.completed` dispatch; **`surfaceAgentCompletions(bus, correlationId)`** reads it back into the conversation.\n- **Transports** (pluggable): the default `inlineInvokeAgentTransport` runs the worker in-process (completion surfaces in the same turn); `createDispatchInvokeTransport(bus)` emits an `agent.invoke` signal a worker processes via `processAgentInvocations()` (async). A job-queue transport (enqueue on the `agents` queue) is a consumer-supplied `InvokeAgentTransport` — orchestration never hard-depends on `@happyvertical/smrt-jobs`, which sits *below* agents in the dependency graph.\n\n## Key Files\n\n| File | Purpose |\n|------|---------|\n| `src/agent.ts` | Base Agent class — lifecycle, dispatch, interests, config, opt-in learning trait, multi-instance identity |\n| `src/execute-as-principal.ts` | `executeAsPrincipal` / `PrincipalRun` — run agent work as a persona's bound user (#1888) |\n| `src/delegation.ts` | `DelegationEnvelope` — immutable principal + bounded delegation depth (#1892) |\n| `src/invoke-agent.ts` | `invoke-agent` tool, worker executor, completion-dispatch convention, transports (#1892) |\n| `src/learning.ts` | `AgentLearningConfig` + `resolveAgentLearning()` declaration normalisation |\n| `src/schedule.ts` | AgentSchedule model — cron, execution tracking |\n| `src/tenant-agent.ts` | TenantAgent — junction table, hierarchical resolution |\n| `src/interests.ts` | Interest filter types and configuration |\n| `src/config.ts` | File + DB config management, UI slots |\n"
987
988
  }
@@ -11,10 +11,12 @@
11
11
  import type { ComponentProps } from 'svelte';
12
12
  import AgentAdminPanel from './components/AgentAdminPanel.svelte';
13
13
  import AgentAdminTabs from './components/AgentAdminTabs.svelte';
14
+ import AgentSettingsForm from './components/AgentSettingsForm.svelte';
14
15
  import AgentSettingsShell from './components/AgentSettingsShell.svelte';
15
- export { AgentAdminPanel, AgentAdminTabs, AgentSettingsShell };
16
+ export { AgentAdminPanel, AgentAdminTabs, AgentSettingsForm, AgentSettingsShell, };
16
17
  export type AgentAdminPanelProps = ComponentProps<typeof AgentAdminPanel>;
17
18
  export type AgentAdminTabsProps = ComponentProps<typeof AgentAdminTabs>;
18
19
  export type AgentSettingsShellProps = ComponentProps<typeof AgentSettingsShell>;
19
- export type { AdminPanelBaseProps, AgentUIComponentRegistry, AgentUISlot, AgentUISlots, } from '../ui.js';
20
+ export type AgentSettingsFormProps = ComponentProps<typeof AgentSettingsForm>;
21
+ export type { AdminPanelBaseProps, AgentSettingField, AgentSettingFieldType, AgentSettingOption, AgentSettingsSchema, AgentUIComponentRegistry, AgentUISlot, AgentUISlots, } from '../ui.js';
20
22
  //# sourceMappingURL=admin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../src/svelte/admin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,eAAe,MAAM,qCAAqC,CAAC;AAClE,OAAO,cAAc,MAAM,oCAAoC,CAAC;AAChE,OAAO,kBAAkB,MAAM,wCAAwC,CAAC;AAExE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;AAE/D,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1E,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC;AACxE,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAKhF,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,YAAY,GACb,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../src/svelte/admin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,eAAe,MAAM,qCAAqC,CAAC;AAClE,OAAO,cAAc,MAAM,oCAAoC,CAAC;AAChE,OAAO,iBAAiB,MAAM,uCAAuC,CAAC;AACtE,OAAO,kBAAkB,MAAM,wCAAwC,CAAC;AAExE,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1E,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC;AACxE,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChF,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAK9E,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,YAAY,GACb,MAAM,UAAU,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import AgentAdminPanel from './components/AgentAdminPanel.svelte';
2
2
  import AgentAdminTabs from './components/AgentAdminTabs.svelte';
3
+ import AgentSettingsForm from './components/AgentSettingsForm.svelte';
3
4
  import AgentSettingsShell from './components/AgentSettingsShell.svelte';
4
- export { AgentAdminPanel, AgentAdminTabs, AgentSettingsShell };
5
+ export { AgentAdminPanel, AgentAdminTabs, AgentSettingsForm, AgentSettingsShell, };
@@ -6,6 +6,7 @@ import type {
6
6
  AgentUISlot,
7
7
  } from '../../ui.js';
8
8
  import { M } from '../i18n.js';
9
+ import AgentSettingsForm from './AgentSettingsForm.svelte';
9
10
 
10
11
  const { t } = useI18n();
11
12
 
@@ -53,10 +54,17 @@ async function handleSave(newConfig: unknown) {
53
54
  <Component
54
55
  {config}
55
56
  onSave={handleSave}
56
- {readonly}
57
+ readonly={readonly || !onSave}
57
58
  {fileConfig}
58
59
  {dbConfig}
59
60
  />
61
+ {:else if slot.settingsSchema}
62
+ <AgentSettingsForm
63
+ config={(config ?? {}) as Record<string, unknown>}
64
+ schema={slot.settingsSchema}
65
+ onSave={handleSave}
66
+ readonly={readonly || !onSave}
67
+ />
60
68
  {:else}
61
69
  <div class="no-panel">
62
70
  <div class="no-panel-icon">⚙️</div>
@@ -1 +1 @@
1
- {"version":3,"file":"AgentAdminPanel.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AgentAdminPanel.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,wBAAwB,EACxB,WAAW,EACZ,MAAM,aAAa,CAAC;AAIrB,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
+ {"version":3,"file":"AgentAdminPanel.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AgentAdminPanel.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,wBAAwB,EACxB,WAAW,EACZ,MAAM,aAAa,CAAC;AAKrB,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;AAiDD,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -0,0 +1,204 @@
1
+ <script lang="ts">
2
+ import { Form, Input, Select, Textarea } from '@happyvertical/smrt-ui/forms';
3
+ import { Button } from '@happyvertical/smrt-ui/ui';
4
+ import type { AgentSettingsSchema } from '../../ui.js';
5
+
6
+ export interface Props {
7
+ config: Record<string, unknown>;
8
+ schema: AgentSettingsSchema;
9
+ onSave?: (config: Record<string, unknown>) => Promise<void>;
10
+ readonly?: boolean;
11
+ }
12
+
13
+ let { config, schema, onSave, readonly = false }: Props = $props();
14
+
15
+ let draft = $state<Record<string, string | boolean>>({});
16
+ let errors = $state<Record<string, string>>({});
17
+ let saving = $state(false);
18
+ let appliedConfig: Record<string, unknown> | undefined;
19
+
20
+ function displayValue(value: unknown, type: string): string | boolean {
21
+ if (type === 'boolean') return Boolean(value);
22
+ if (type === 'json' && value !== undefined) {
23
+ return JSON.stringify(value, null, 2);
24
+ }
25
+ return value === undefined || value === null ? '' : String(value);
26
+ }
27
+
28
+ $effect(() => {
29
+ if (appliedConfig === config) return;
30
+ appliedConfig = config;
31
+ draft = Object.fromEntries(
32
+ schema.fields.map((field) => [
33
+ field.id,
34
+ displayValue(config[field.id] ?? field.default, field.type),
35
+ ]),
36
+ );
37
+ errors = {};
38
+ });
39
+
40
+ function setText(id: string, event: Event) {
41
+ draft[id] = (event.currentTarget as HTMLInputElement).value;
42
+ }
43
+
44
+ function setBoolean(id: string, event: Event) {
45
+ draft[id] = (event.currentTarget as HTMLInputElement).checked;
46
+ }
47
+
48
+ async function handleSubmit() {
49
+ const next: Record<string, unknown> = { ...config };
50
+ const nextErrors: Record<string, string> = {};
51
+
52
+ for (const field of schema.fields) {
53
+ const value = draft[field.id];
54
+ if (field.required && (value === '' || value === undefined)) {
55
+ nextErrors[field.id] = `${field.label} is required`;
56
+ continue;
57
+ }
58
+
59
+ if (field.type === 'number') {
60
+ if (value === '') {
61
+ delete next[field.id];
62
+ } else {
63
+ const numberValue = Number(value);
64
+ if (!Number.isFinite(numberValue)) {
65
+ nextErrors[field.id] = `${field.label} must be a number`;
66
+ } else {
67
+ next[field.id] = numberValue;
68
+ }
69
+ }
70
+ } else if (field.type === 'json') {
71
+ if (value === '') {
72
+ delete next[field.id];
73
+ } else {
74
+ try {
75
+ next[field.id] = JSON.parse(String(value));
76
+ } catch {
77
+ nextErrors[field.id] = `${field.label} must contain valid JSON`;
78
+ }
79
+ }
80
+ } else if (field.type === 'boolean') {
81
+ next[field.id] = Boolean(value);
82
+ } else if (value === '') {
83
+ delete next[field.id];
84
+ } else {
85
+ next[field.id] = value;
86
+ }
87
+ }
88
+
89
+ errors = nextErrors;
90
+ if (Object.keys(nextErrors).length > 0 || !onSave) return;
91
+
92
+ saving = true;
93
+ try {
94
+ await onSave(next);
95
+ } finally {
96
+ saving = false;
97
+ }
98
+ }
99
+ </script>
100
+
101
+ <Form class="agent-settings-form" onsubmit={handleSubmit}>
102
+ {#each schema.fields as field (field.id)}
103
+ <div class="field">
104
+ {#if field.type === 'boolean'}
105
+ <label class="checkbox" for={field.id}>
106
+ <!-- raw-primitive-allow: native checkbox preserves checkbox semantics without requiring a Provider -->
107
+ <input
108
+ id={field.id}
109
+ type="checkbox"
110
+ checked={Boolean(draft[field.id])}
111
+ onchange={(event) => setBoolean(field.id, event)}
112
+ disabled={readonly || saving}
113
+ />
114
+ <span>{field.label}</span>
115
+ </label>
116
+ {:else}
117
+ <label for={field.id}>{field.label}</label>
118
+ {#if field.type === 'select'}
119
+ <Select
120
+ id={field.id}
121
+ value={String(draft[field.id] ?? '')}
122
+ onchange={(event) => setText(field.id, event)}
123
+ required={field.required}
124
+ disabled={readonly || saving}
125
+ >
126
+ <option value="">Select…</option>
127
+ {#each field.options ?? [] as option}
128
+ <option value={option.value}>{option.label}</option>
129
+ {/each}
130
+ </Select>
131
+ {:else if field.type === 'textarea' || field.type === 'json'}
132
+ <Textarea
133
+ id={field.id}
134
+ value={String(draft[field.id] ?? '')}
135
+ oninput={(event) => setText(field.id, event)}
136
+ placeholder={field.placeholder}
137
+ required={field.required}
138
+ disabled={readonly || saving}
139
+ rows={field.type === 'json' ? 8 : 4}
140
+ />
141
+ {:else}
142
+ <Input
143
+ id={field.id}
144
+ type={field.type === 'number' ? 'number' : 'text'}
145
+ value={String(draft[field.id] ?? '')}
146
+ oninput={(event) => setText(field.id, event)}
147
+ placeholder={field.placeholder}
148
+ required={field.required}
149
+ min={field.min}
150
+ max={field.max}
151
+ disabled={readonly || saving}
152
+ />
153
+ {/if}
154
+ {/if}
155
+ {#if field.description}<small>{field.description}</small>{/if}
156
+ {#if errors[field.id]}<p class="error">{errors[field.id]}</p>{/if}
157
+ </div>
158
+ {/each}
159
+
160
+ {#if !readonly}
161
+ <div class="actions">
162
+ <Button type="submit" disabled={saving}>{saving ? 'Saving…' : 'Save settings'}</Button>
163
+ </div>
164
+ {/if}
165
+ </Form>
166
+
167
+ <style>
168
+ :global(.agent-settings-form) {
169
+ display: grid;
170
+ gap: var(--smrt-spacing-5, 1.25rem);
171
+ }
172
+
173
+ .field {
174
+ display: grid;
175
+ gap: var(--smrt-spacing-2, 0.5rem);
176
+ }
177
+
178
+ label {
179
+ font-weight: var(--smrt-typography-weight-semibold, 600);
180
+ }
181
+
182
+ .checkbox {
183
+ display: flex;
184
+ align-items: center;
185
+ gap: var(--smrt-spacing-2, 0.5rem);
186
+ }
187
+
188
+ small {
189
+ color: var(--smrt-color-on-surface-variant, #64748b);
190
+ }
191
+
192
+ .error {
193
+ margin: 0;
194
+ color: var(--smrt-color-error, #b91c1c);
195
+ font-size: var(--smrt-typography-body-medium-size, 0.875rem);
196
+ line-height: var(--smrt-typography-body-medium-line-height, 1.25rem);
197
+ letter-spacing: var(--smrt-typography-body-medium-tracking, 0.015625rem);
198
+ }
199
+
200
+ .actions {
201
+ display: flex;
202
+ justify-content: flex-end;
203
+ }
204
+ </style>
@@ -0,0 +1,11 @@
1
+ import type { AgentSettingsSchema } from '../../ui.js';
2
+ export interface Props {
3
+ config: Record<string, unknown>;
4
+ schema: AgentSettingsSchema;
5
+ onSave?: (config: Record<string, unknown>) => Promise<void>;
6
+ readonly?: boolean;
7
+ }
8
+ declare const AgentSettingsForm: import("svelte").Component<Props, {}, "">;
9
+ type AgentSettingsForm = ReturnType<typeof AgentSettingsForm>;
10
+ export default AgentSettingsForm;
11
+ //# sourceMappingURL=AgentSettingsForm.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentSettingsForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AgentSettingsForm.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGvD,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAuID,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,37 @@
1
+ // @vitest-environment jsdom
2
+ import { createUIRegistry } from '@happyvertical/smrt-agents/ui';
3
+ import { render, screen } from '@testing-library/svelte';
4
+ import { describe, expect, it, vi } from 'vitest';
5
+ import AgentAdminPanel from '../AgentAdminPanel.svelte';
6
+ const slot = {
7
+ id: 'settings',
8
+ label: 'Settings',
9
+ settingsSchema: {
10
+ version: 1,
11
+ fields: [{ id: 'name', label: 'Display name', type: 'string' }],
12
+ },
13
+ };
14
+ function renderPanel(onSave) {
15
+ return render(AgentAdminPanel, {
16
+ props: {
17
+ registry: createUIRegistry(),
18
+ agentClass: 'Praeco',
19
+ slotId: slot.id,
20
+ slot,
21
+ config: { name: 'Current name' },
22
+ onSave,
23
+ },
24
+ });
25
+ }
26
+ describe('AgentAdminPanel schema fallback', () => {
27
+ it('is read-only when the host does not provide a save handler', () => {
28
+ renderPanel();
29
+ expect(screen.getByLabelText('Display name')).toBeDisabled();
30
+ expect(screen.queryByRole('button', { name: 'Save settings' })).not.toBeInTheDocument();
31
+ });
32
+ it('remains editable when the host provides a save handler', () => {
33
+ renderPanel(vi.fn().mockResolvedValue(undefined));
34
+ expect(screen.getByLabelText('Display name')).toBeEnabled();
35
+ expect(screen.getByRole('button', { name: 'Save settings' })).toBeInTheDocument();
36
+ });
37
+ });
@@ -16,9 +16,10 @@ import AgentDashboard from './components/AgentDashboard.svelte';
16
16
  import AgentRunHistory from './components/AgentRunHistory.svelte';
17
17
  import AgentScheduleForm from './components/AgentScheduleForm.svelte';
18
18
  import AgentScheduleList from './components/AgentScheduleList.svelte';
19
+ import AgentSettingsForm from './components/AgentSettingsForm.svelte';
19
20
  import AgentSettingsShell from './components/AgentSettingsShell.svelte';
20
21
  import ScheduleStatusBadge from './components/ScheduleStatusBadge.svelte';
21
- export { AgentAdminPanel, AgentAdminTabs, AgentDashboard, AgentRunHistory, AgentScheduleForm, AgentScheduleList, AgentSettingsShell, ScheduleStatusBadge, };
22
+ export { AgentAdminPanel, AgentAdminTabs, AgentDashboard, AgentRunHistory, AgentScheduleForm, AgentScheduleList, AgentSettingsForm, AgentSettingsShell, ScheduleStatusBadge, };
22
23
  export type AgentAdminPanelProps = ComponentProps<typeof AgentAdminPanel>;
23
24
  export type AgentAdminTabsProps = ComponentProps<typeof AgentAdminTabs>;
24
25
  export type AgentDashboardProps = ComponentProps<typeof AgentDashboard>;
@@ -26,8 +27,9 @@ export type AgentRunHistoryProps = ComponentProps<typeof AgentRunHistory>;
26
27
  export type AgentScheduleFormProps = ComponentProps<typeof AgentScheduleForm>;
27
28
  export type AgentScheduleListProps = ComponentProps<typeof AgentScheduleList>;
28
29
  export type AgentSettingsShellProps = ComponentProps<typeof AgentSettingsShell>;
30
+ export type AgentSettingsFormProps = ComponentProps<typeof AgentSettingsForm>;
29
31
  export type ScheduleStatusBadgeProps = ComponentProps<typeof ScheduleStatusBadge>;
30
- export type { AdminPanelBaseProps, AgentUIComponentRegistry, AgentUISlot, AgentUISlots, } from '../ui.js';
32
+ export type { AdminPanelBaseProps, AgentSettingField, AgentSettingFieldType, AgentSettingOption, AgentSettingsSchema, AgentUIComponentRegistry, AgentUISlot, AgentUISlots, } from '../ui.js';
31
33
  export type { AgentDashboardProps as AgentDashboardPropsLegacy, AgentRunHistoryEntry, AgentRunHistoryProps as AgentRunHistoryPropsLegacy, AgentScheduleData, AgentScheduleFormProps as AgentScheduleFormPropsLegacy, AgentScheduleListProps as AgentScheduleListPropsLegacy, RunStatus, ScheduleFormData, ScheduleStatus, } from './types.js';
32
34
  export { calculateSuccessRate, formatCronExpression, formatDuration, formatRelativeTime, getRunStatusVariant, getScheduleStatusVariant, } from './types.js';
33
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAI7C,OAAO,eAAe,MAAM,qCAAqC,CAAC;AAClE,OAAO,cAAc,MAAM,oCAAoC,CAAC;AAChE,OAAO,cAAc,MAAM,oCAAoC,CAAC;AAChE,OAAO,eAAe,MAAM,qCAAqC,CAAC;AAClE,OAAO,iBAAiB,MAAM,uCAAuC,CAAC;AACtE,OAAO,iBAAiB,MAAM,uCAAuC,CAAC;AACtE,OAAO,kBAAkB,MAAM,wCAAwC,CAAC;AACxE,OAAO,mBAAmB,MAAM,yCAAyC,CAAC;AAG1E,OAAO,EACL,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACpB,CAAC;AAGF,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1E,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC;AACxE,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC;AACxE,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1E,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9E,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9E,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChF,MAAM,MAAM,wBAAwB,GAAG,cAAc,CACnD,OAAO,mBAAmB,CAC3B,CAAC;AAMF,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,YAAY,GACb,MAAM,UAAU,CAAC;AAGlB,YAAY,EACV,mBAAmB,IAAI,yBAAyB,EAChD,oBAAoB,EACpB,oBAAoB,IAAI,0BAA0B,EAClD,iBAAiB,EACjB,sBAAsB,IAAI,4BAA4B,EACtD,sBAAsB,IAAI,4BAA4B,EACtD,SAAS,EACT,gBAAgB,EAChB,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAI7C,OAAO,eAAe,MAAM,qCAAqC,CAAC;AAClE,OAAO,cAAc,MAAM,oCAAoC,CAAC;AAChE,OAAO,cAAc,MAAM,oCAAoC,CAAC;AAChE,OAAO,eAAe,MAAM,qCAAqC,CAAC;AAClE,OAAO,iBAAiB,MAAM,uCAAuC,CAAC;AACtE,OAAO,iBAAiB,MAAM,uCAAuC,CAAC;AACtE,OAAO,iBAAiB,MAAM,uCAAuC,CAAC;AACtE,OAAO,kBAAkB,MAAM,wCAAwC,CAAC;AACxE,OAAO,mBAAmB,MAAM,yCAAyC,CAAC;AAG1E,OAAO,EACL,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACpB,CAAC;AAGF,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1E,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC;AACxE,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC;AACxE,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1E,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9E,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9E,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChF,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9E,MAAM,MAAM,wBAAwB,GAAG,cAAc,CACnD,OAAO,mBAAmB,CAC3B,CAAC;AAMF,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,YAAY,GACb,MAAM,UAAU,CAAC;AAGlB,YAAY,EACV,mBAAmB,IAAI,yBAAyB,EAChD,oBAAoB,EACpB,oBAAoB,IAAI,0BAA0B,EAClD,iBAAiB,EACjB,sBAAsB,IAAI,4BAA4B,EACtD,sBAAsB,IAAI,4BAA4B,EACtD,SAAS,EACT,gBAAgB,EAChB,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
@@ -18,10 +18,11 @@ import AgentDashboard from './components/AgentDashboard.svelte';
18
18
  import AgentRunHistory from './components/AgentRunHistory.svelte';
19
19
  import AgentScheduleForm from './components/AgentScheduleForm.svelte';
20
20
  import AgentScheduleList from './components/AgentScheduleList.svelte';
21
+ import AgentSettingsForm from './components/AgentSettingsForm.svelte';
21
22
  import AgentSettingsShell from './components/AgentSettingsShell.svelte';
22
23
  import ScheduleStatusBadge from './components/ScheduleStatusBadge.svelte';
23
24
  // Export components
24
- export { AgentAdminPanel, AgentAdminTabs, AgentDashboard, AgentRunHistory, AgentScheduleForm, AgentScheduleList, AgentSettingsShell, ScheduleStatusBadge, };
25
+ export { AgentAdminPanel, AgentAdminTabs, AgentDashboard, AgentRunHistory, AgentScheduleForm, AgentScheduleList, AgentSettingsForm, AgentSettingsShell, ScheduleStatusBadge, };
25
26
  export { calculateSuccessRate, formatCronExpression, formatDuration, formatRelativeTime, getRunStatusVariant, getScheduleStatusVariant, } from './types.js';
26
27
  // Auto-register with ModuleUIRegistry
27
28
  ModuleUIRegistry.registerModule(AGENTS_MODULE_META);
package/dist/ui.d.ts CHANGED
@@ -50,6 +50,29 @@ export interface AdminPanelBaseProps<TConfig = unknown> {
50
50
  */
51
51
  dbConfig?: TConfig;
52
52
  }
53
+ export type AgentSettingFieldType = 'string' | 'number' | 'boolean' | 'select' | 'textarea' | 'json';
54
+ export interface AgentSettingOption {
55
+ value: string;
56
+ label: string;
57
+ }
58
+ /** A non-secret setting that a host app can render without custom UI code. */
59
+ export interface AgentSettingField {
60
+ id: string;
61
+ label: string;
62
+ type: AgentSettingFieldType;
63
+ description?: string;
64
+ required?: boolean;
65
+ default?: unknown;
66
+ placeholder?: string;
67
+ options?: AgentSettingOption[];
68
+ min?: number;
69
+ max?: number;
70
+ }
71
+ /** Versioned contract for a schema-rendered agent settings panel. */
72
+ export interface AgentSettingsSchema {
73
+ version: number;
74
+ fields: AgentSettingField[];
75
+ }
53
76
  /**
54
77
  * Definition of a UI slot that an agent declares
55
78
  *
@@ -68,6 +91,10 @@ export interface AgentUISlot {
68
91
  order?: number;
69
92
  /** Whether the slot is currently unavailable in the admin UI */
70
93
  disabled?: boolean;
94
+ /** Durable owner for settings written through this slot. */
95
+ scope?: 'agent' | 'persona';
96
+ /** Optional fallback form when the agent does not register a custom panel. */
97
+ settingsSchema?: AgentSettingsSchema;
71
98
  }
72
99
  /**
73
100
  * Map of slot IDs to their definitions
package/dist/ui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}