@jskit-ai/assistant-runtime 0.1.131-oldline.2 → 0.1.131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/package.json +84 -8
  2. package/patterns/assistant-surface/PATTERN.md +77 -0
  3. package/patterns/assistant-surface/example/config/public.js +19 -0
  4. package/patterns/assistant-surface/example/config/server.js +9 -0
  5. package/patterns/assistant-surface/example/src/pages/admin/assistant/index.vue +7 -0
  6. package/patterns/assistant-surface/example/src/pages/admin/settings/assistant/index.vue +7 -0
  7. package/patterns/assistant-surface/example/src/placement.js +38 -0
  8. package/src/client/components/AssistantSettingsClientElement.vue +1 -1
  9. package/src/client/composables/useAssistantRuntime.js +2 -2
  10. package/src/client/providers/AssistantClientProvider.js +9 -11
  11. package/src/server/AssistantProvider.js +74 -109
  12. package/src/server/actions.js +37 -17
  13. package/src/server/registerRoutes.js +4 -9
  14. package/src/server/repositories/assistantConfigRepository.js +1 -1
  15. package/src/server/repositories/conversationsRepository.js +1 -1
  16. package/src/server/repositories/messagesRepository.js +1 -1
  17. package/src/server/repositories/repositoryPersistenceUtils.js +29 -0
  18. package/src/server/support/createSurfaceAwareToolCatalog.js +5 -5
  19. package/test/actionDefinitions.test.js +49 -142
  20. package/test/assistantSurfacePattern.test.js +30 -0
  21. package/test/createSurfaceAwareToolCatalog.test.js +4 -2
  22. package/test/featureRuntime.test.js +76 -0
  23. package/test/lazyAppConfig.test.js +16 -47
  24. package/test/packageMetadata.test.js +38 -0
  25. package/package.descriptor.mjs +0 -155
  26. package/src/server/support/workspaceScopeSupport.js +0 -47
  27. package/test/packageDescriptor.test.js +0 -38
  28. /package/{templates/migrations → migrations}/assistant_config_initial.cjs +0 -0
  29. /package/{templates/migrations → migrations}/assistant_transcripts_initial.cjs +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/assistant-runtime",
3
- "version": "0.1.131-oldline.2",
3
+ "version": "0.1.131",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./client": "./src/client/index.js",
@@ -8,18 +8,94 @@
8
8
  "./server/actionIds": "./src/server/actionIds.js"
9
9
  },
10
10
  "dependencies": {
11
- "@jskit-ai/assistant-core": "0.1.124",
12
- "@jskit-ai/database-runtime": "0.1.147",
13
- "@jskit-ai/http-runtime": "0.1.146",
14
- "@jskit-ai/kernel": "0.1.147",
15
- "@jskit-ai/shell-web": "0.1.148",
16
- "@jskit-ai/users-core": "0.1.161",
17
- "@jskit-ai/users-web": "0.1.178-oldline.3",
11
+ "@jskit-ai/assistant-core": "0.1.136",
12
+ "@jskit-ai/database-runtime": "0.1.160",
13
+ "@jskit-ai/http-web": "0.1.5",
14
+ "@jskit-ai/http-runtime": "0.1.158",
15
+ "@jskit-ai/kernel": "0.1.160",
16
+ "@jskit-ai/shell-web": "0.1.164",
18
17
  "json-rest-schema": "^1.0.17"
19
18
  },
20
19
  "peerDependencies": {
21
20
  "@tanstack/vue-query": "^5.90.5",
22
21
  "vue": "^3.5.13",
23
22
  "vuetify": "^4.0.0"
23
+ },
24
+ "description": "Capability-based assistant runtime with per-surface chat, transcripts, settings, and action tools.",
25
+ "jskit": {
26
+ "kind": "runtime",
27
+ "capabilities": {
28
+ "provides": [
29
+ "assistant.runtime"
30
+ ],
31
+ "requires": [
32
+ "runtime.actions",
33
+ "runtime.config",
34
+ "runtime.database",
35
+ "runtime.env",
36
+ "runtime.http",
37
+ "runtime.http-web",
38
+ "runtime.http-client"
39
+ ]
40
+ },
41
+ "runtime": {
42
+ "server": {
43
+ "providers": [
44
+ {
45
+ "entrypoint": "src/server/AssistantProvider.js",
46
+ "export": "AssistantFeature"
47
+ }
48
+ ]
49
+ },
50
+ "client": {
51
+ "providers": [
52
+ {
53
+ "entrypoint": "src/client/providers/AssistantClientProvider.js",
54
+ "export": "AssistantClientProvider"
55
+ }
56
+ ]
57
+ }
58
+ },
59
+ "metadata": {
60
+ "jskit": {
61
+ "tableOwnership": {
62
+ "tables": [
63
+ {
64
+ "tableName": "assistant_config"
65
+ },
66
+ {
67
+ "tableName": "assistant_conversations"
68
+ },
69
+ {
70
+ "tableName": "assistant_messages"
71
+ }
72
+ ]
73
+ }
74
+ },
75
+ "apiSummary": {
76
+ "surfaces": [
77
+ {
78
+ "subpath": "./client",
79
+ "summary": "Exports assistant runtime client elements and composables."
80
+ },
81
+ {
82
+ "subpath": "./shared",
83
+ "summary": "Exports assistant runtime shared config helpers."
84
+ },
85
+ {
86
+ "subpath": "./server/actionIds",
87
+ "summary": "Exports assistant runtime action identifiers."
88
+ }
89
+ ],
90
+ "capabilities": [
91
+ "assistant.runtime"
92
+ ]
93
+ }
94
+ },
95
+ "migrations": {
96
+ "directories": [
97
+ "migrations"
98
+ ]
99
+ }
24
100
  }
25
101
  }
@@ -0,0 +1,77 @@
1
+ ---
2
+ id: assistant/assistant-surface
3
+ title: Assistant surface and settings
4
+ summary: Configure an assistant runtime for one application surface and expose its chat and settings elements through ordinary pages and placements.
5
+ keywords: ai, assistant, chat, config, environment, page, placement, settings, surface
6
+ requires: @jskit-ai/assistant-runtime, @jskit-ai/shell-web
7
+ ---
8
+
9
+ # Assistant surface and settings
10
+
11
+ ## Use when
12
+
13
+ Use this pattern when an application should expose JSKIT's assistant runtime on
14
+ an enabled surface and provide a settings page for that assistant.
15
+
16
+ ## Do not use when
17
+
18
+ Do not use this pattern for an application that only needs a single
19
+ server-to-model call, or when the product has no conversational surface. Do not
20
+ copy the assistant runtime's repositories or transport into application code.
21
+
22
+ ## Product decisions
23
+
24
+ Choose the runtime surface, settings surface, global or workspace configuration
25
+ scope, page routes, placement roles, AI provider, model policy, and whether the
26
+ assistant begins disabled until credentials are supplied. Never put an API key
27
+ in source or a questionnaire transcript.
28
+
29
+ ## Invariants
30
+
31
+ - Both configured surfaces exist and are enabled.
32
+ - Workspace configuration is used only when both surfaces require a workspace.
33
+ - Each runtime surface appears once in `assistantSurfaces` and
34
+ `assistantServer`.
35
+ - The server config contains an environment prefix, never a credential value.
36
+ - Runtime and settings pages use the public assistant elements.
37
+ - Environment values are supplied through the application's normal secret
38
+ environment boundary.
39
+ - No generator markers, setup receipts, or overwrite state remain.
40
+
41
+ ## Framework APIs
42
+
43
+ Use `AssistantSurfaceClientElement` and `AssistantSettingsClientElement` from
44
+ `@jskit-ai/assistant-runtime/client`. Install the runtime package through the
45
+ normal package-capability path. Configure `assistantSurfaces` in public config
46
+ and `assistantServer` in server config.
47
+
48
+ ## Example files
49
+
50
+ `example/` contains concrete public/server config, assistant and settings pages,
51
+ and semantic placements for an `admin` surface. Adapt the complete files to the
52
+ application's existing config and placement registries.
53
+
54
+ ## Variation points
55
+
56
+ Change surface ids, settings location, config scope, environment prefix, routes,
57
+ labels, icons, and placement targets. A workspace-scoped application must retain
58
+ the current workspace in both routes and assistant requests through the runtime's
59
+ public workspace support.
60
+
61
+ ## Verification
62
+
63
+ - load both pages through their normal navigation
64
+ - verify the configured surface and settings target agree
65
+ - verify missing credentials disable assistant calls without exposing secrets
66
+ - exercise one successful and one provider-error conversation
67
+ - verify global or cross-workspace isolation, whichever applies
68
+ - run migrations, server/client tests, and focused browser coverage
69
+
70
+ ## Avoid
71
+
72
+ - API keys or provider secrets in source
73
+ - a second model client beside the assistant runtime
74
+ - implicit surface selection
75
+ - workspace scope on a non-workspace surface
76
+ - copied runtime repositories, actions, or routes
77
+ - generator commands, question metadata, receipts, or provenance
@@ -0,0 +1,19 @@
1
+ const config = {
2
+ surfaceDefaultId: "admin",
3
+ surfaceDefinitions: {
4
+ admin: {
5
+ id: "admin",
6
+ enabled: true,
7
+ requiresAuth: true,
8
+ requiresWorkspace: false
9
+ }
10
+ },
11
+ assistantSurfaces: {
12
+ admin: {
13
+ settingsSurfaceId: "admin",
14
+ configScope: "global"
15
+ }
16
+ }
17
+ };
18
+
19
+ export default config;
@@ -0,0 +1,9 @@
1
+ const config = {
2
+ assistantServer: {
3
+ admin: {
4
+ aiConfigPrefix: "ADMIN_ASSISTANT"
5
+ }
6
+ }
7
+ };
8
+
9
+ export default config;
@@ -0,0 +1,7 @@
1
+ <script setup>
2
+ import { AssistantSurfaceClientElement } from "@jskit-ai/assistant-runtime/client";
3
+ </script>
4
+
5
+ <template>
6
+ <AssistantSurfaceClientElement surface-id="admin" />
7
+ </template>
@@ -0,0 +1,7 @@
1
+ <script setup>
2
+ import { AssistantSettingsClientElement } from "@jskit-ai/assistant-runtime/client";
3
+ </script>
4
+
5
+ <template>
6
+ <AssistantSettingsClientElement target-surface-id="admin" />
7
+ </template>
@@ -0,0 +1,38 @@
1
+ import { createPlacementRegistry } from "@jskit-ai/shell-web/client/placement";
2
+
3
+ const registry = createPlacementRegistry();
4
+ const { addPlacement } = registry;
5
+
6
+ addPlacement({
7
+ id: "assistant.admin.chat.link",
8
+ target: "shell.primary-nav",
9
+ kind: "link",
10
+ surfaces: ["admin"],
11
+ order: 140,
12
+ props: {
13
+ label: "Assistant",
14
+ icon: "mdi-creation-outline",
15
+ surface: "admin",
16
+ scopedSuffix: "/assistant",
17
+ unscopedSuffix: "/assistant"
18
+ }
19
+ });
20
+
21
+ addPlacement({
22
+ id: "assistant.admin.settings.link",
23
+ target: "page.section-nav",
24
+ owner: "admin-settings",
25
+ kind: "link",
26
+ surfaces: ["admin"],
27
+ order: 160,
28
+ props: {
29
+ label: "Assistant",
30
+ surface: "admin",
31
+ scopedSuffix: "/settings/assistant",
32
+ unscopedSuffix: "/settings/assistant"
33
+ }
34
+ });
35
+
36
+ export default function getPlacements() {
37
+ return registry.build();
38
+ }
@@ -30,7 +30,7 @@ import { validateOperationSection } from "@jskit-ai/http-runtime/shared/validato
30
30
  import { assistantHttpClient, createAssistantApi, AssistantSettingsFormCard } from "@jskit-ai/assistant-core/client";
31
31
  import { assistantConfigResource, assistantSettingsQueryKey, buildAssistantApiPath } from "@jskit-ai/assistant-core/shared";
32
32
  import { useShellWebErrorRuntime } from "@jskit-ai/shell-web/client/error";
33
- import { useSurfaceRouteContext } from "@jskit-ai/users-web/client/composables/useSurfaceRouteContext";
33
+ import { useSurfaceRouteContext } from "@jskit-ai/shell-web/client/navigation/useSurfaceRouteContext";
34
34
  import { resolveAssistantSurfaceConfig } from "../../shared/assistantSurfaces.js";
35
35
  import { useWorkspaceWebScopeSupport } from "../support/workspaceScopeSupport.js";
36
36
 
@@ -20,8 +20,8 @@ import {
20
20
  createAssistantApi
21
21
  } from "@jskit-ai/assistant-core/client";
22
22
  import { useShellWebErrorRuntime } from "@jskit-ai/shell-web/client/error";
23
- import { usePagedCollection } from "@jskit-ai/users-web/client/composables/usePagedCollection";
24
- import { useSurfaceRouteContext } from "@jskit-ai/users-web/client/composables/useSurfaceRouteContext";
23
+ import { usePagedCollection } from "@jskit-ai/http-web/client/composables/usePagedCollection";
24
+ import { useSurfaceRouteContext } from "@jskit-ai/shell-web/client/navigation/useSurfaceRouteContext";
25
25
  import { resolveAssistantSurfaceConfig } from "../../shared/assistantSurfaces.js";
26
26
  import { insertTextAtSelection } from "../support/composerInputSupport.js";
27
27
  import { useWorkspaceWebScopeSupport } from "../support/workspaceScopeSupport.js";
@@ -1,16 +1,14 @@
1
+ import { defineProvider } from "@jskit-ai/kernel/shared/capabilities";
1
2
  import AssistantSettingsClientElement from "../components/AssistantSettingsClientElement.vue";
2
3
 
3
- class AssistantClientProvider {
4
- static id = "assistant.web.client";
5
- static dependsOn = ["users.web.client"];
6
-
7
- register(app) {
8
- if (!app || typeof app.singleton !== "function") {
9
- throw new Error("AssistantClientProvider requires application singleton().");
10
- }
11
-
12
- app.singleton("assistant.web.settings.element", () => AssistantSettingsClientElement);
4
+ const AssistantClientProvider = defineProvider({
5
+ id: "assistant.web.client",
6
+ requires: {
7
+ components: "client.components"
8
+ },
9
+ setup({ components }) {
10
+ components.register("assistant.web.settings.element", AssistantSettingsClientElement);
13
11
  }
14
- }
12
+ });
15
13
 
16
14
  export { AssistantClientProvider };
@@ -1,8 +1,7 @@
1
- import { resolveAppConfig } from "@jskit-ai/kernel/server/support";
2
- import { withActionDefaults } from "@jskit-ai/kernel/shared/actions";
1
+ import { defineFeature } from "@jskit-ai/kernel/server/features";
3
2
  import { normalizeObject, normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
4
3
  import { createAiClient } from "@jskit-ai/assistant-core/server";
5
- import { assistantActions } from "./actions.js";
4
+ import { createAssistantActions } from "./actions.js";
6
5
  import { registerRoutes } from "./registerRoutes.js";
7
6
  import { createRepository as createAssistantConfigRepository } from "./repositories/assistantConfigRepository.js";
8
7
  import { createRepository as createConversationsRepository } from "./repositories/conversationsRepository.js";
@@ -12,23 +11,9 @@ import { createChatService } from "./services/chatService.js";
12
11
  import { createTranscriptService } from "./services/transcriptService.js";
13
12
  import { resolveAssistantAiConfig } from "./support/assistantServerConfig.js";
14
13
  import { createSurfaceAwareToolCatalog } from "./support/createSurfaceAwareToolCatalog.js";
15
- import { resolveWorkspaceServerScopeSupport } from "./support/workspaceScopeSupport.js";
16
-
17
- function resolveGlobalAssistantConfig(scope) {
18
- const appConfig = resolveAppConfig(scope);
19
- const env = scope.has("jskit.env") ? normalizeObject(scope.make("jskit.env")) : {};
20
-
21
- return Object.freeze({
22
- appConfig,
23
- env
24
- });
25
- }
26
14
 
27
15
  function createAssistantAiClientFactory(config = {}) {
28
- const resolveCurrentAppConfig =
29
- typeof config.resolveAppConfig === "function"
30
- ? () => normalizeObject(config.resolveAppConfig())
31
- : () => normalizeObject(config.appConfig);
16
+ const appConfig = normalizeObject(config.appConfig);
32
17
  const env = normalizeObject(config.env);
33
18
  const cache = new Map();
34
19
 
@@ -45,7 +30,7 @@ function createAssistantAiClientFactory(config = {}) {
45
30
 
46
31
  const assistantAiConfig = resolveAssistantAiConfig(
47
32
  {
48
- appConfig: resolveCurrentAppConfig(),
33
+ appConfig,
49
34
  env
50
35
  },
51
36
  normalizedTargetSurfaceId
@@ -57,99 +42,79 @@ function createAssistantAiClientFactory(config = {}) {
57
42
  });
58
43
  }
59
44
 
60
- class AssistantProvider {
61
- static id = "assistant.chat.service";
62
-
63
- static dependsOn = ["runtime.actions", "runtime.database", "auth.policy.fastify", "users.core"];
64
-
65
- register(app) {
66
- if (
67
- !app ||
68
- typeof app.singleton !== "function" ||
69
- typeof app.service !== "function" ||
70
- typeof app.actions !== "function"
71
- ) {
72
- throw new Error("AssistantProvider requires application singleton()/service()/actions().");
73
- }
74
-
75
- const config = resolveGlobalAssistantConfig(app);
76
- const resolveCurrentAppConfig = () => resolveAppConfig(app);
77
-
78
- app.singleton("assistant.config.repository", (scope) => {
79
- const knex = scope.make("jskit.database.knex");
80
- return createAssistantConfigRepository(knex);
81
- });
82
-
83
- app.singleton("assistant.conversation.repository", (scope) => {
84
- const knex = scope.make("jskit.database.knex");
85
- return createConversationsRepository(knex);
86
- });
45
+ function createAssistantRuntime({
46
+ actionCatalogue,
47
+ config,
48
+ consoleRuntime,
49
+ database,
50
+ env,
51
+ workspaces
52
+ } = {}) {
53
+ const assistantConfigRepository = createAssistantConfigRepository(database.knex);
54
+ const conversationsRepository = createConversationsRepository(database.knex);
55
+ const messagesRepository = createMessagesRepository(database.knex);
56
+ const workspaceScopeSupport = workspaces?.scope || null;
57
+ const aiClientFactory = createAssistantAiClientFactory({ appConfig: config, env });
58
+ const toolCatalog = createSurfaceAwareToolCatalog(actionCatalogue, { appConfig: config });
59
+ const configService = createAssistantConfigService({
60
+ assistantConfigRepository,
61
+ consoleService: consoleRuntime?.services?.access || null,
62
+ appConfig: config,
63
+ workspaceScopeSupport
64
+ });
65
+ const transcriptService = createTranscriptService({ conversationsRepository, messagesRepository });
66
+ const chatService = createChatService({
67
+ aiClientFactory,
68
+ transcriptService,
69
+ serviceToolCatalog: toolCatalog,
70
+ assistantConfigService: configService,
71
+ appConfig: config,
72
+ workspaceScopeSupport
73
+ });
87
74
 
88
- app.singleton("assistant.message.repository", (scope) => {
89
- const knex = scope.make("jskit.database.knex");
90
- return createMessagesRepository(knex);
91
- });
75
+ return Object.freeze({
76
+ repositories: Object.freeze({
77
+ config: assistantConfigRepository,
78
+ conversations: conversationsRepository,
79
+ messages: messagesRepository
80
+ }),
81
+ services: Object.freeze({ chat: chatService, config: configService, transcript: transcriptService }),
82
+ aiClientFactory,
83
+ toolCatalog
84
+ });
85
+ }
92
86
 
93
- app.singleton("assistant.ai.client.factory", () => {
94
- return createAssistantAiClientFactory({
95
- resolveAppConfig: resolveCurrentAppConfig,
96
- env: config.env
97
- });
87
+ const AssistantFeature = defineFeature({
88
+ id: "assistant.runtime",
89
+ domain: "assistant",
90
+ requires: {
91
+ config: "runtime.config",
92
+ database: "runtime.database",
93
+ env: "runtime.env",
94
+ http: "runtime.http"
95
+ },
96
+ optional: {
97
+ consoleRuntime: "console.core",
98
+ workspaces: "workspaces.core"
99
+ },
100
+ provides: {
101
+ assistant: "assistant.runtime"
102
+ },
103
+ setup(dependencies, { actionCatalogue }) {
104
+ const assistant = createAssistantRuntime({ ...dependencies, actionCatalogue });
105
+ registerRoutes(dependencies.http.router, {
106
+ config: dependencies.config,
107
+ workspaceScopeSupport: dependencies.workspaces?.scope || null
98
108
  });
99
-
100
- app.singleton("assistant.service.tool-catalog", (scope) => {
101
- return createSurfaceAwareToolCatalog(scope, {
102
- resolveAppConfig: resolveCurrentAppConfig
103
- });
109
+ return { assistant };
110
+ },
111
+ actions({ assistant, config }) {
112
+ return createAssistantActions({
113
+ assistantConfigService: assistant.services.config,
114
+ chatService: assistant.services.chat,
115
+ config
104
116
  });
105
-
106
- app.service(
107
- "assistant.config.service",
108
- (scope) =>
109
- createAssistantConfigService({
110
- assistantConfigRepository: scope.make("assistant.config.repository"),
111
- consoleService: scope.has("consoleService") ? scope.make("consoleService") : null,
112
- resolveAppConfig: resolveCurrentAppConfig,
113
- workspaceScopeSupport: resolveWorkspaceServerScopeSupport(scope)
114
- })
115
- );
116
-
117
- app.service(
118
- "assistant.transcript.service",
119
- (scope) =>
120
- createTranscriptService({
121
- conversationsRepository: scope.make("assistant.conversation.repository"),
122
- messagesRepository: scope.make("assistant.message.repository")
123
- })
124
- );
125
-
126
- app.service(
127
- "assistant.chat.service",
128
- (scope) =>
129
- createChatService({
130
- aiClientFactory: scope.make("assistant.ai.client.factory"),
131
- transcriptService: scope.make("assistant.transcript.service"),
132
- serviceToolCatalog: scope.make("assistant.service.tool-catalog"),
133
- assistantConfigService: scope.make("assistant.config.service"),
134
- resolveAppConfig: resolveCurrentAppConfig,
135
- workspaceScopeSupport: resolveWorkspaceServerScopeSupport(scope)
136
- })
137
- );
138
-
139
- app.actions(
140
- withActionDefaults(assistantActions, {
141
- domain: "assistant",
142
- dependencies: {
143
- chatService: "assistant.chat.service",
144
- assistantConfigService: "assistant.config.service"
145
- }
146
- })
147
- );
148
117
  }
118
+ });
149
119
 
150
- boot(app) {
151
- registerRoutes(app);
152
- }
153
- }
154
-
155
- export { AssistantProvider };
120
+ export { AssistantFeature, createAssistantAiClientFactory, createAssistantRuntime };
@@ -12,6 +12,10 @@ import {
12
12
  } from "@jskit-ai/assistant-core/shared";
13
13
  import { actionIds } from "./actionIds.js";
14
14
  import { assistantTargetSurfaceInputValidator } from "./inputSchemas.js";
15
+ import {
16
+ resolveAssistantSurfaceConfig,
17
+ resolveAssistantSurfacesConfig
18
+ } from "../shared/assistantSurfaces.js";
15
19
 
16
20
  const runtimeConversationsListQueryInputValidator = deepFreeze({
17
21
  schema: createSchema({
@@ -87,13 +91,28 @@ const settingsUpdateInputValidator = composeSchemaDefinitions(
87
91
  }
88
92
  );
89
93
 
90
- const assistantActions = Object.freeze([
94
+ function configuredAssistantSurfaces(config = {}) {
95
+ return Object.keys(resolveAssistantSurfacesConfig(config))
96
+ .map((surfaceId) => resolveAssistantSurfaceConfig(config, surfaceId))
97
+ .filter(Boolean);
98
+ }
99
+
100
+ function createAssistantActions({ assistantConfigService, chatService, config = {} } = {}) {
101
+ if (!assistantConfigService || !chatService) {
102
+ throw new TypeError("createAssistantActions requires assistantConfigService and chatService.");
103
+ }
104
+ const configuredSurfaces = configuredAssistantSurfaces(config);
105
+ const runtimeSurfaces = [...new Set(configuredSurfaces.map((entry) => entry.targetSurfaceId))];
106
+ const settingsSurfaces = [...new Set(configuredSurfaces.map((entry) => entry.settingsSurfaceId))];
107
+ if (runtimeSurfaces.length === 0 || settingsSurfaces.length === 0) return [];
108
+
109
+ return Object.freeze([
91
110
  {
92
111
  id: actionIds.chatStream,
93
112
  version: 1,
94
113
  kind: "stream",
95
114
  channels: ["api", "internal"],
96
- surfacesFrom: "enabled",
115
+ surfaces: runtimeSurfaces,
97
116
  permission: {
98
117
  require: "authenticated"
99
118
  },
@@ -104,7 +123,7 @@ const assistantActions = Object.freeze([
104
123
  },
105
124
  observability: {},
106
125
  async execute(input, context, deps) {
107
- return deps.chatService.streamChat(input, {
126
+ return chatService.streamChat(input, {
108
127
  context,
109
128
  streamWriter: deps.streamWriter,
110
129
  abortSignal: deps.abortSignal
@@ -116,7 +135,7 @@ const assistantActions = Object.freeze([
116
135
  version: 1,
117
136
  kind: "query",
118
137
  channels: ["api", "internal"],
119
- surfacesFrom: "enabled",
138
+ surfaces: runtimeSurfaces,
120
139
  permission: {
121
140
  require: "authenticated"
122
141
  },
@@ -127,8 +146,8 @@ const assistantActions = Object.freeze([
127
146
  actionName: actionIds.conversationsList
128
147
  },
129
148
  observability: {},
130
- async execute(input, context, deps) {
131
- return returnJsonApiData(await deps.chatService.listConversations(input.query, {
149
+ async execute(input, context) {
150
+ return returnJsonApiData(await chatService.listConversations(input.query, {
132
151
  context,
133
152
  input
134
153
  }));
@@ -139,7 +158,7 @@ const assistantActions = Object.freeze([
139
158
  version: 1,
140
159
  kind: "query",
141
160
  channels: ["api", "internal"],
142
- surfacesFrom: "enabled",
161
+ surfaces: runtimeSurfaces,
143
162
  permission: {
144
163
  require: "authenticated"
145
164
  },
@@ -150,8 +169,8 @@ const assistantActions = Object.freeze([
150
169
  actionName: actionIds.conversationMessagesList
151
170
  },
152
171
  observability: {},
153
- async execute(input, context, deps) {
154
- return returnJsonApiData(await deps.chatService.getConversationMessages(input.conversationId, input.query, {
172
+ async execute(input, context) {
173
+ return returnJsonApiData(await chatService.getConversationMessages(input.conversationId, input.query, {
155
174
  context,
156
175
  input
157
176
  }));
@@ -162,7 +181,7 @@ const assistantActions = Object.freeze([
162
181
  version: 1,
163
182
  kind: "query",
164
183
  channels: ["api", "automation", "internal"],
165
- surfacesFrom: "enabled",
184
+ surfaces: settingsSurfaces,
166
185
  permission: {
167
186
  require: "authenticated"
168
187
  },
@@ -173,8 +192,8 @@ const assistantActions = Object.freeze([
173
192
  actionName: actionIds.settingsRead
174
193
  },
175
194
  observability: {},
176
- async execute(input, context, deps) {
177
- return returnJsonApiData(await deps.assistantConfigService.getSettings(input, {
195
+ async execute(input, context) {
196
+ return returnJsonApiData(await assistantConfigService.getSettings(input, {
178
197
  context
179
198
  }));
180
199
  }
@@ -184,7 +203,7 @@ const assistantActions = Object.freeze([
184
203
  version: 1,
185
204
  kind: "command",
186
205
  channels: ["api", "automation", "internal"],
187
- surfacesFrom: "enabled",
206
+ surfaces: settingsSurfaces,
188
207
  permission: {
189
208
  require: "authenticated"
190
209
  },
@@ -195,12 +214,13 @@ const assistantActions = Object.freeze([
195
214
  actionName: actionIds.settingsUpdate
196
215
  },
197
216
  observability: {},
198
- async execute(input, context, deps) {
199
- return returnJsonApiData(await deps.assistantConfigService.updateSettings(input, input.patch, {
217
+ async execute(input, context) {
218
+ return returnJsonApiData(await assistantConfigService.updateSettings(input, input.patch, {
200
219
  context
201
220
  }));
202
221
  }
203
222
  }
204
- ]);
223
+ ]);
224
+ }
205
225
 
206
- export { assistantActions };
226
+ export { createAssistantActions };