@jskit-ai/assistant 0.1.37 → 0.1.39

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.descriptor.mjs +84 -319
  2. package/package.json +2 -2
  3. package/src/server/buildTemplateContext.js +39 -14
  4. package/templates/src/pages/assistant/index.vue +2 -2
  5. package/templates/src/pages/settings/assistant/index.vue +7 -0
  6. package/test/buildTemplateContext.test.js +42 -27
  7. package/test/packageDescriptor.test.js +26 -55
  8. package/test/templateContracts.test.js +8 -6
  9. package/templates/migrations/assistant_config_initial.cjs +0 -25
  10. package/templates/migrations/assistant_transcripts_initial.cjs +0 -56
  11. package/templates/src/local-package/client/components/AssistantSettingsClientElement.vue +0 -88
  12. package/templates/src/local-package/client/components/AssistantSurfaceClientElement.vue +0 -10
  13. package/templates/src/local-package/client/composables/useAssistantRuntime.js +0 -754
  14. package/templates/src/local-package/client/index.js +0 -4
  15. package/templates/src/local-package/client/providers/AssistantClientProvider.js +0 -16
  16. package/templates/src/local-package/package.descriptor.mjs +0 -85
  17. package/templates/src/local-package/package.json +0 -11
  18. package/templates/src/local-package/server/AssistantProvider.js +0 -143
  19. package/templates/src/local-package/server/actionIds.js +0 -9
  20. package/templates/src/local-package/server/actions.js +0 -183
  21. package/templates/src/local-package/server/registerRoutes.js +0 -296
  22. package/templates/src/local-package/server/repositories/assistantConfigRepository.js +0 -141
  23. package/templates/src/local-package/server/repositories/conversationsRepository.js +0 -240
  24. package/templates/src/local-package/server/repositories/messagesRepository.js +0 -166
  25. package/templates/src/local-package/server/services/assistantConfigService.js +0 -90
  26. package/templates/src/local-package/server/services/chatService.js +0 -995
  27. package/templates/src/local-package/server/services/transcriptService.js +0 -308
  28. package/templates/src/local-package/shared/assistantRuntimeConfig.js +0 -13
  29. package/templates/src/local-package/shared/index.js +0 -1
@@ -1,15 +1,15 @@
1
1
  export default Object.freeze({
2
2
  packageVersion: 1,
3
3
  packageId: "@jskit-ai/assistant",
4
- version: "0.1.37",
4
+ version: "0.1.39",
5
5
  kind: "generator",
6
- description: "Generate an app-local assistant runtime and settings integration from explicit surface choices.",
6
+ description: "Generate an assistant page and per-surface assistant config using the shared assistant runtime.",
7
7
  options: {
8
- "runtime-surface": {
8
+ surface: {
9
9
  required: true,
10
10
  inputType: "text",
11
- defaultValue: "",
12
- promptLabel: "Runtime surface",
11
+ defaultFromConfig: "surfaceDefaultId",
12
+ promptLabel: "Assistant surface",
13
13
  promptHint: "Enabled surface id where the assistant page will run."
14
14
  },
15
15
  "settings-surface": {
@@ -17,7 +17,14 @@ export default Object.freeze({
17
17
  inputType: "text",
18
18
  defaultValue: "",
19
19
  promptLabel: "Settings surface",
20
- promptHint: "Enabled surface id whose settings outlet will host the assistant settings form."
20
+ promptHint: "Enabled surface id whose settings pages will include the assistant settings section."
21
+ },
22
+ "settings-route-path": {
23
+ required: false,
24
+ inputType: "text",
25
+ defaultValue: "assistant",
26
+ promptLabel: "Settings route path",
27
+ promptHint: "Route segment to use for the assistant settings section page."
21
28
  },
22
29
  "config-scope": {
23
30
  required: true,
@@ -47,6 +54,13 @@ export default Object.freeze({
47
54
  promptLabel: "Menu label",
48
55
  promptHint: "Menu label for the assistant page entry."
49
56
  },
57
+ "ai-config-prefix": {
58
+ required: false,
59
+ inputType: "text",
60
+ defaultValue: "",
61
+ promptLabel: "AI config prefix",
62
+ promptHint: "Optional env/config prefix override. Defaults to <SURFACE>_ASSISTANT."
63
+ },
50
64
  "ai-provider": {
51
65
  required: true,
52
66
  defaultValue: "openai",
@@ -58,7 +72,7 @@ export default Object.freeze({
58
72
  allowEmpty: true,
59
73
  defaultValue: "",
60
74
  promptLabel: "AI API key",
61
- promptHint: "Leave empty to keep assistant disabled until you add a key."
75
+ promptHint: "Leave empty to keep the assistant disabled until you add a key."
62
76
  },
63
77
  "ai-base-url": {
64
78
  required: true,
@@ -74,7 +88,7 @@ export default Object.freeze({
74
88
  promptHint: "Abort AI requests after this many milliseconds."
75
89
  }
76
90
  },
77
- dependsOn: [],
91
+ dependsOn: ["@jskit-ai/assistant-runtime"],
78
92
  capabilities: {
79
93
  provides: ["assistant-generator"],
80
94
  requires: []
@@ -88,78 +102,6 @@ export default Object.freeze({
88
102
  }
89
103
  },
90
104
  metadata: {
91
- generatorPrimarySubcommand: "install",
92
- generatorSubcommands: {
93
- install: {
94
- description: "Generate and install an app-local assistant runtime from explicit surface choices.",
95
- examples: [
96
- {
97
- label: "App runtime, console settings, global config",
98
- lines: [
99
- "npx jskit generate @jskit-ai/assistant install \\",
100
- " --runtime-surface app \\",
101
- " --settings-surface console \\",
102
- " --config-scope global \\",
103
- " --placement shell-layout:primary-menu \\",
104
- " --menu-label Assistant \\",
105
- " --ai-provider openai \\",
106
- " --ai-api-key \"$OPENAI_API_KEY\" \\",
107
- " --ai-base-url \"\" \\",
108
- " --ai-timeout-ms 120000 \\",
109
- " --run-npm-install"
110
- ]
111
- },
112
- {
113
- label: "App runtime, app settings, global config",
114
- lines: [
115
- "npx jskit generate @jskit-ai/assistant install \\",
116
- " --runtime-surface app \\",
117
- " --settings-surface app \\",
118
- " --config-scope global \\",
119
- " --placement shell-layout:primary-menu \\",
120
- " --menu-label Assistant \\",
121
- " --ai-provider openai \\",
122
- " --ai-api-key \"$OPENAI_API_KEY\" \\",
123
- " --ai-base-url \"\" \\",
124
- " --ai-timeout-ms 120000 \\",
125
- " --run-npm-install"
126
- ]
127
- },
128
- {
129
- label: "Workspace runtime, console settings, global config",
130
- lines: [
131
- "npx jskit generate @jskit-ai/assistant install \\",
132
- " --runtime-surface admin \\",
133
- " --settings-surface console \\",
134
- " --config-scope global \\",
135
- " --placement shell-layout:primary-menu \\",
136
- " --menu-label Assistant \\",
137
- " --ai-provider openai \\",
138
- " --ai-api-key \"$OPENAI_API_KEY\" \\",
139
- " --ai-base-url \"\" \\",
140
- " --ai-timeout-ms 120000 \\",
141
- " --run-npm-install"
142
- ]
143
- },
144
- {
145
- label: "Workspace runtime, workspace settings, workspace config",
146
- lines: [
147
- "npx jskit generate @jskit-ai/assistant install \\",
148
- " --runtime-surface admin \\",
149
- " --settings-surface admin \\",
150
- " --config-scope workspace \\",
151
- " --placement shell-layout:primary-menu \\",
152
- " --menu-label Assistant \\",
153
- " --ai-provider openai \\",
154
- " --ai-api-key \"$OPENAI_API_KEY\" \\",
155
- " --ai-base-url \"\" \\",
156
- " --ai-timeout-ms 120000 \\",
157
- " --run-npm-install"
158
- ]
159
- }
160
- ]
161
- }
162
- },
163
105
  apiSummary: {
164
106
  surfaces: [
165
107
  {
@@ -175,18 +117,7 @@ export default Object.freeze({
175
117
  },
176
118
  mutations: {
177
119
  dependencies: {
178
- runtime: {
179
- "@local/assistant": "file:packages/assistant",
180
- "@jskit-ai/assistant-core": "0.1.4",
181
- "@jskit-ai/database-runtime": "0.1.28",
182
- "@jskit-ai/http-runtime": "0.1.27",
183
- "@jskit-ai/kernel": "0.1.28",
184
- "@jskit-ai/shell-web": "0.1.27",
185
- "@jskit-ai/users-core": "0.1.38",
186
- "@jskit-ai/users-web": "0.1.43",
187
- "@tanstack/vue-query": "^5.90.5",
188
- "vuetify": "^4.0.0"
189
- },
120
+ runtime: {},
190
121
  dev: {}
191
122
  },
192
123
  packageJson: {
@@ -195,236 +126,106 @@ export default Object.freeze({
195
126
  procfile: {},
196
127
  files: [
197
128
  {
198
- op: "install-migration",
199
- from: "templates/migrations/assistant_config_initial.cjs",
200
- toDir: "migrations",
201
- extension: ".cjs",
202
- reason: "Install assistant configuration schema migration.",
203
- category: "assistant",
204
- id: "assistant-config-initial-schema",
205
- templateContext: {
206
- entrypoint: "src/server/buildTemplateContext.js",
207
- export: "buildTemplateContext"
208
- }
209
- },
210
- {
211
- op: "install-migration",
212
- from: "templates/migrations/assistant_transcripts_initial.cjs",
213
- toDir: "migrations",
214
- extension: ".cjs",
215
- reason: "Install assistant transcript schema migration.",
216
- category: "assistant",
217
- id: "assistant-transcripts-initial-schema",
218
- templateContext: {
219
- entrypoint: "src/server/buildTemplateContext.js",
220
- export: "buildTemplateContext"
221
- }
222
- },
223
- {
224
- from: "templates/src/local-package/package.json",
225
- to: "packages/assistant/package.json",
226
- reason: "Install app-local assistant package manifest.",
227
- category: "assistant",
228
- id: "assistant-local-package-json"
229
- },
230
- {
231
- from: "templates/src/local-package/package.descriptor.mjs",
232
- to: "packages/assistant/package.descriptor.mjs",
233
- reason: "Install app-local assistant package descriptor.",
234
- category: "assistant",
235
- id: "assistant-local-package-descriptor"
236
- },
237
- {
238
- from: "templates/src/local-package/shared/assistantRuntimeConfig.js",
239
- to: "packages/assistant/src/shared/assistantRuntimeConfig.js",
240
- reason: "Install generated assistant runtime configuration.",
241
- category: "assistant",
242
- id: "assistant-local-runtime-config",
243
- templateContext: {
244
- entrypoint: "src/server/buildTemplateContext.js",
245
- export: "buildTemplateContext"
246
- }
247
- },
248
- {
249
- from: "templates/src/local-package/shared/index.js",
250
- to: "packages/assistant/src/shared/index.js",
251
- reason: "Install generated assistant shared exports.",
252
- category: "assistant",
253
- id: "assistant-local-shared-index"
254
- },
255
- {
256
- from: "templates/src/local-package/client/index.js",
257
- to: "packages/assistant/src/client/index.js",
258
- reason: "Install generated assistant client exports.",
259
- category: "assistant",
260
- id: "assistant-local-client-index"
261
- },
262
- {
263
- from: "templates/src/local-package/client/components/AssistantSurfaceClientElement.vue",
264
- to: "packages/assistant/src/client/components/AssistantSurfaceClientElement.vue",
265
- reason: "Install generated assistant surface page component.",
266
- category: "assistant",
267
- id: "assistant-local-surface-client-element",
268
- templateContext: {
269
- entrypoint: "src/server/buildTemplateContext.js",
270
- export: "buildTemplateContext"
271
- }
272
- },
273
- {
274
- from: "templates/src/local-package/client/components/AssistantSettingsClientElement.vue",
275
- to: "packages/assistant/src/client/components/AssistantSettingsClientElement.vue",
276
- reason: "Install generated assistant settings form component.",
277
- category: "assistant",
278
- id: "assistant-local-settings-client-element",
279
- templateContext: {
280
- entrypoint: "src/server/buildTemplateContext.js",
281
- export: "buildTemplateContext"
282
- }
283
- },
284
- {
285
- from: "templates/src/local-package/client/composables/useAssistantRuntime.js",
286
- to: "packages/assistant/src/client/composables/useAssistantRuntime.js",
287
- reason: "Install generated assistant runtime composable.",
288
- category: "assistant",
289
- id: "assistant-local-runtime-composable",
290
- templateContext: {
291
- entrypoint: "src/server/buildTemplateContext.js",
292
- export: "buildTemplateContext"
293
- }
294
- },
295
- {
296
- from: "templates/src/local-package/client/providers/AssistantClientProvider.js",
297
- to: "packages/assistant/src/client/providers/AssistantClientProvider.js",
298
- reason: "Install generated assistant client provider.",
299
- category: "assistant",
300
- id: "assistant-local-client-provider"
301
- },
302
- {
303
- from: "templates/src/local-package/server/AssistantProvider.js",
304
- to: "packages/assistant/src/server/AssistantProvider.js",
305
- reason: "Install generated assistant server provider.",
306
- category: "assistant",
307
- id: "assistant-local-server-provider",
308
- templateContext: {
309
- entrypoint: "src/server/buildTemplateContext.js",
310
- export: "buildTemplateContext"
311
- }
312
- },
313
- {
314
- from: "templates/src/local-package/server/actionIds.js",
315
- to: "packages/assistant/src/server/actionIds.js",
316
- reason: "Install generated assistant action identifiers.",
317
- category: "assistant",
318
- id: "assistant-local-action-ids"
319
- },
320
- {
321
- from: "templates/src/local-package/server/actions.js",
322
- to: "packages/assistant/src/server/actions.js",
323
- reason: "Install generated assistant action definitions.",
324
- category: "assistant",
325
- id: "assistant-local-actions",
326
- templateContext: {
327
- entrypoint: "src/server/buildTemplateContext.js",
328
- export: "buildTemplateContext"
329
- }
330
- },
331
- {
332
- from: "templates/src/local-package/server/registerRoutes.js",
333
- to: "packages/assistant/src/server/registerRoutes.js",
334
- reason: "Install generated assistant route registration.",
335
- category: "assistant",
336
- id: "assistant-local-register-routes",
337
- templateContext: {
338
- entrypoint: "src/server/buildTemplateContext.js",
339
- export: "buildTemplateContext"
340
- }
341
- },
342
- {
343
- from: "templates/src/local-package/server/repositories/assistantConfigRepository.js",
344
- to: "packages/assistant/src/server/repositories/assistantConfigRepository.js",
345
- reason: "Install generated assistant config repository.",
129
+ from: "templates/src/pages/assistant/index.vue",
130
+ toSurface: "${option:surface|lower}",
131
+ toSurfacePath: "assistant/index.vue",
132
+ reason: "Install generated assistant runtime page.",
346
133
  category: "assistant",
347
- id: "assistant-local-config-repository",
134
+ id: "assistant-page-runtime",
348
135
  templateContext: {
349
136
  entrypoint: "src/server/buildTemplateContext.js",
350
137
  export: "buildTemplateContext"
351
138
  }
352
139
  },
353
140
  {
354
- from: "templates/src/local-package/server/repositories/conversationsRepository.js",
355
- to: "packages/assistant/src/server/repositories/conversationsRepository.js",
356
- reason: "Install generated assistant conversations repository.",
141
+ from: "templates/src/pages/settings/assistant/index.vue",
142
+ toSurface: "${option:settings-surface|lower}",
143
+ toSurfacePath: "settings/${option:settings-route-path|path}/index.vue",
144
+ reason: "Install generated assistant settings section page.",
357
145
  category: "assistant",
358
- id: "assistant-local-conversations-repository",
146
+ id: "assistant-page-settings-standard",
147
+ when: {
148
+ option: "settings-surface",
149
+ notEquals: "admin"
150
+ },
359
151
  templateContext: {
360
152
  entrypoint: "src/server/buildTemplateContext.js",
361
153
  export: "buildTemplateContext"
362
154
  }
363
155
  },
364
156
  {
365
- from: "templates/src/local-package/server/repositories/messagesRepository.js",
366
- to: "packages/assistant/src/server/repositories/messagesRepository.js",
367
- reason: "Install generated assistant messages repository.",
157
+ from: "templates/src/pages/settings/assistant/index.vue",
158
+ toSurface: "${option:settings-surface|lower}",
159
+ toSurfacePath: "workspace/settings/${option:settings-route-path|path}/index.vue",
160
+ reason: "Install generated assistant settings section page.",
368
161
  category: "assistant",
369
- id: "assistant-local-messages-repository",
162
+ id: "assistant-page-settings-admin",
163
+ when: {
164
+ option: "settings-surface",
165
+ equals: "admin"
166
+ },
370
167
  templateContext: {
371
168
  entrypoint: "src/server/buildTemplateContext.js",
372
169
  export: "buildTemplateContext"
373
170
  }
374
- },
171
+ }
172
+ ],
173
+ text: [
375
174
  {
376
- from: "templates/src/local-package/server/services/assistantConfigService.js",
377
- to: "packages/assistant/src/server/services/assistantConfigService.js",
378
- reason: "Install generated assistant config service.",
175
+ op: "append-text",
176
+ file: "src/placement.js",
177
+ position: "bottom",
178
+ skipIfContains: "assistant.generated.menu:${option:surface|lower}",
179
+ value:
180
+ "\n// assistant.generated.menu:${option:surface|lower}\naddPlacement({\n id: \"assistant.generated.menu.${option:surface|kebab}\",\n host: \"__ASSISTANT_MENU_PLACEMENT_HOST__\",\n position: \"__ASSISTANT_MENU_PLACEMENT_POSITION__\",\n surfaces: [\"${option:surface|lower}\"],\n order: 310,\n componentToken: \"__ASSISTANT_MENU_COMPONENT_TOKEN__\",\n props: {\n label: \"__ASSISTANT_MENU_LABEL__\",\n surface: \"${option:surface|lower}\",\n workspaceSuffix: \"__ASSISTANT_MENU_WORKSPACE_SUFFIX__\",\n nonWorkspaceSuffix: \"__ASSISTANT_MENU_NON_WORKSPACE_SUFFIX__\"\n },\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
181
+ reason: "Append generated assistant runtime menu placement into app-owned placement registry.",
379
182
  category: "assistant",
380
- id: "assistant-local-config-service",
183
+ id: "assistant-placement-menu",
381
184
  templateContext: {
382
185
  entrypoint: "src/server/buildTemplateContext.js",
383
186
  export: "buildTemplateContext"
384
187
  }
385
188
  },
386
189
  {
387
- from: "templates/src/local-package/server/services/chatService.js",
388
- to: "packages/assistant/src/server/services/chatService.js",
389
- reason: "Install generated assistant chat service.",
190
+ op: "append-text",
191
+ file: "src/placement.js",
192
+ position: "bottom",
193
+ skipIfContains: "assistant.generated.settings.menu:${option:surface|lower}",
194
+ value:
195
+ "\n// assistant.generated.settings.menu:${option:surface|lower}\naddPlacement({\n id: \"assistant.generated.settings.menu.${option:surface|kebab}\",\n host: \"__ASSISTANT_SETTINGS_HOST__\",\n position: \"primary-menu\",\n surfaces: [\"${option:settings-surface|lower}\"],\n order: 250,\n componentToken: \"users.web.shell.surface-aware-menu-link-item\",\n props: {\n label: \"__ASSISTANT_SETTINGS_MENU_LABEL__\",\n surface: \"${option:settings-surface|lower}\",\n workspaceSuffix: \"__ASSISTANT_SETTINGS_MENU_WORKSPACE_SUFFIX__\",\n nonWorkspaceSuffix: \"__ASSISTANT_SETTINGS_MENU_NON_WORKSPACE_SUFFIX__\"\n },\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
196
+ reason: "Append generated assistant settings section menu placement into app-owned settings placements.",
390
197
  category: "assistant",
391
- id: "assistant-local-chat-service",
198
+ id: "assistant-settings-menu-placement",
392
199
  templateContext: {
393
200
  entrypoint: "src/server/buildTemplateContext.js",
394
201
  export: "buildTemplateContext"
395
202
  }
396
203
  },
397
204
  {
398
- from: "templates/src/local-package/server/services/transcriptService.js",
399
- to: "packages/assistant/src/server/services/transcriptService.js",
400
- reason: "Install generated assistant transcript service.",
205
+ op: "append-text",
206
+ file: "config/public.js",
207
+ position: "bottom",
208
+ skipIfContains: "config.assistantSurfaces.${option:surface|lower} = {",
209
+ value:
210
+ "\nconfig.assistantSurfaces.${option:surface|lower} = {\n settingsSurfaceId: \"__ASSISTANT_SETTINGS_SURFACE_ID__\",\n configScope: \"__ASSISTANT_CONFIG_SCOPE__\"\n};\n",
211
+ reason: "Register the generated assistant surface in public app config.",
401
212
  category: "assistant",
402
- id: "assistant-local-transcript-service",
213
+ id: "assistant-public-surface-config",
403
214
  templateContext: {
404
215
  entrypoint: "src/server/buildTemplateContext.js",
405
216
  export: "buildTemplateContext"
406
217
  }
407
218
  },
408
- {
409
- from: "templates/src/pages/assistant/index.vue",
410
- toSurface: "${option:runtime-surface|lower}",
411
- toSurfacePath: "assistant/index.vue",
412
- reason: "Install generated assistant runtime page.",
413
- category: "assistant",
414
- id: "assistant-page-runtime"
415
- }
416
- ],
417
- text: [
418
219
  {
419
220
  op: "append-text",
420
- file: "src/placement.js",
221
+ file: "config/server.js",
421
222
  position: "bottom",
422
- skipIfContains: "id: \"assistant.generated.menu\"",
223
+ skipIfContains: "config.assistantServer.${option:surface|lower} = {",
423
224
  value:
424
- "\naddPlacement({\n id: \"assistant.generated.menu\",\n host: \"__ASSISTANT_MENU_PLACEMENT_HOST__\",\n position: \"__ASSISTANT_MENU_PLACEMENT_POSITION__\",\n surfaces: [\"${option:runtime-surface|lower}\"],\n order: 310,\n componentToken: \"__ASSISTANT_MENU_COMPONENT_TOKEN__\",\n props: {\n label: \"__ASSISTANT_MENU_LABEL__\",\n surface: \"${option:runtime-surface|lower}\",\n workspaceSuffix: \"__ASSISTANT_MENU_WORKSPACE_SUFFIX__\",\n nonWorkspaceSuffix: \"__ASSISTANT_MENU_NON_WORKSPACE_SUFFIX__\"\n },\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
425
- reason: "Append generated assistant runtime menu placement into app-owned placement registry.",
225
+ "\nconfig.assistantServer.${option:surface|lower} = {\n aiConfigPrefix: \"__ASSISTANT_AI_CONFIG_PREFIX__\"\n};\n",
226
+ reason: "Register generated assistant server config for the selected surface.",
426
227
  category: "assistant",
427
- id: "assistant-placement-menu",
228
+ id: "assistant-server-surface-config",
428
229
  templateContext: {
429
230
  entrypoint: "src/server/buildTemplateContext.js",
430
231
  export: "buildTemplateContext"
@@ -432,54 +233,18 @@ export default Object.freeze({
432
233
  },
433
234
  {
434
235
  op: "append-text",
435
- file: "src/placement.js",
236
+ file: ".env",
436
237
  position: "bottom",
437
- skipIfContains: "id: \"assistant.generated.settings.form\"",
238
+ skipIfContains: "__ASSISTANT_AI_CONFIG_PREFIX___AI_PROVIDER=",
438
239
  value:
439
- "\naddPlacement({\n id: \"assistant.generated.settings.form\",\n host: \"__ASSISTANT_SETTINGS_HOST__\",\n position: \"forms\",\n surfaces: [\"${option:settings-surface|lower}\"],\n order: 250,\n componentToken: \"assistant.web.settings.element\",\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
440
- reason: "Append generated assistant settings form placement into app-owned settings placements.",
441
- category: "assistant",
442
- id: "assistant-settings-form-placement",
240
+ "\n__ASSISTANT_AI_CONFIG_PREFIX___AI_PROVIDER=${option:ai-provider}\n__ASSISTANT_AI_CONFIG_PREFIX___AI_API_KEY=${option:ai-api-key}\n__ASSISTANT_AI_CONFIG_PREFIX___AI_BASE_URL=${option:ai-base-url}\n__ASSISTANT_AI_CONFIG_PREFIX___AI_TIMEOUT_MS=${option:ai-timeout-ms}\n",
241
+ reason: "Append assistant AI env defaults for the generated surface prefix.",
242
+ category: "runtime-config",
243
+ id: "assistant-ai-prefixed-env",
443
244
  templateContext: {
444
245
  entrypoint: "src/server/buildTemplateContext.js",
445
246
  export: "buildTemplateContext"
446
247
  }
447
- },
448
- {
449
- file: ".env",
450
- op: "upsert-env",
451
- key: "AI_PROVIDER",
452
- value: "${option:ai-provider}",
453
- reason: "Configure assistant AI provider id.",
454
- category: "runtime-config",
455
- id: "assistant-ai-provider"
456
- },
457
- {
458
- file: ".env",
459
- op: "upsert-env",
460
- key: "AI_API_KEY",
461
- value: "${option:ai-api-key}",
462
- reason: "Configure assistant AI API key.",
463
- category: "runtime-config",
464
- id: "assistant-ai-api-key"
465
- },
466
- {
467
- file: ".env",
468
- op: "upsert-env",
469
- key: "AI_BASE_URL",
470
- value: "${option:ai-base-url}",
471
- reason: "Configure assistant AI base URL override.",
472
- category: "runtime-config",
473
- id: "assistant-ai-base-url"
474
- },
475
- {
476
- file: ".env",
477
- op: "upsert-env",
478
- key: "AI_TIMEOUT_MS",
479
- value: "${option:ai-timeout-ms}",
480
- reason: "Configure assistant AI timeout in milliseconds.",
481
- category: "runtime-config",
482
- id: "assistant-ai-timeout-ms"
483
248
  }
484
249
  ]
485
250
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/assistant",
3
- "version": "0.1.37",
3
+ "version": "0.1.39",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
@@ -9,6 +9,6 @@
9
9
  "./server/buildTemplateContext": "./src/server/buildTemplateContext.js"
10
10
  },
11
11
  "dependencies": {
12
- "@jskit-ai/kernel": "0.1.28"
12
+ "@jskit-ai/kernel": "0.1.30"
13
13
  }
14
14
  }
@@ -50,8 +50,32 @@ function resolveSurfaceDefinition(appConfig = {}, surfaceId = "", optionName = "
50
50
  });
51
51
  }
52
52
 
53
- function resolveTableSuffix(surfaceId = "") {
54
- return toSnakeCase(surfaceId) || "assistant";
53
+ function assertAssistantSurfaceIsAvailable(appConfig = {}, surfaceId = "") {
54
+ const assistantSurfaces =
55
+ appConfig && typeof appConfig.assistantSurfaces === "object" && !Array.isArray(appConfig.assistantSurfaces)
56
+ ? appConfig.assistantSurfaces
57
+ : {};
58
+ if (assistantSurfaces[surfaceId]) {
59
+ throw new Error(`assistant generator surface "${surfaceId}" already has an assistant configured in config/public.js.`);
60
+ }
61
+ }
62
+
63
+ function resolveAiConfigPrefix(surfaceId = "", explicitPrefix = "") {
64
+ const normalizedExplicitPrefix = normalizeText(explicitPrefix);
65
+ if (normalizedExplicitPrefix) {
66
+ return normalizedExplicitPrefix;
67
+ }
68
+
69
+ const surfacePrefix = toSnakeCase(surfaceId).toUpperCase();
70
+ return surfacePrefix ? `${surfacePrefix}_ASSISTANT` : "ASSISTANT";
71
+ }
72
+
73
+ function normalizeSettingsRoutePath(value = "") {
74
+ return normalizeText(value).toLowerCase().replace(/^\/+|\/+$/g, "") || "assistant";
75
+ }
76
+
77
+ function resolveSettingsRouteBase(surfaceId = "") {
78
+ return normalizeSurfaceId(surfaceId) === "admin" ? "/workspace/settings" : "/settings";
55
79
  }
56
80
 
57
81
  async function resolveMenuPlacementTarget(appRoot = "", options = {}) {
@@ -64,13 +88,16 @@ async function resolveMenuPlacementTarget(appRoot = "", options = {}) {
64
88
 
65
89
  async function buildTemplateContext({ appRoot, options } = {}) {
66
90
  const appConfig = await loadAppConfig(appRoot);
67
- const runtimeSurface = resolveSurfaceDefinition(appConfig, options?.["runtime-surface"], "runtime-surface");
91
+ const runtimeSurface = resolveSurfaceDefinition(appConfig, options?.surface, "surface");
68
92
  const settingsSurface = resolveSurfaceDefinition(appConfig, options?.["settings-surface"], "settings-surface");
69
93
  const configScope = normalizeConfigScope(options?.["config-scope"]);
94
+ const settingsRoutePath = normalizeSettingsRoutePath(options?.["settings-route-path"]);
95
+
96
+ assertAssistantSurfaceIsAvailable(appConfig, runtimeSurface.id);
70
97
 
71
98
  if (configScope === "workspace" && runtimeSurface.requiresWorkspace !== true) {
72
99
  throw new Error(
73
- `assistant generator config-scope "workspace" requires runtime surface "${runtimeSurface.id}" with requiresWorkspace=true.`
100
+ `assistant generator config-scope "workspace" requires surface "${runtimeSurface.id}" with requiresWorkspace=true.`
74
101
  );
75
102
  }
76
103
  if (configScope === "workspace" && settingsSurface.requiresWorkspace !== true) {
@@ -80,27 +107,25 @@ async function buildTemplateContext({ appRoot, options } = {}) {
80
107
  }
81
108
 
82
109
  const placementTarget = await resolveMenuPlacementTarget(appRoot, options);
83
- const tableSuffix = resolveTableSuffix(runtimeSurface.id);
84
110
  const menuComponentToken = normalizeText(options?.["placement-component-token"]) || DEFAULT_MENU_COMPONENT_TOKEN;
111
+ const settingsRouteBase = resolveSettingsRouteBase(settingsSurface.id);
112
+ const settingsMenuSuffix = `${settingsRouteBase}/${settingsRoutePath}`;
85
113
 
86
114
  return Object.freeze({
87
- "__ASSISTANT_RUNTIME_SURFACE_ID__": runtimeSurface.id,
115
+ "__ASSISTANT_SURFACE_ID__": runtimeSurface.id,
88
116
  "__ASSISTANT_SETTINGS_SURFACE_ID__": settingsSurface.id,
89
- "__ASSISTANT_RUNTIME_SURFACE_REQUIRES_WORKSPACE__": runtimeSurface.requiresWorkspace ? "true" : "false",
90
- "__ASSISTANT_SETTINGS_SURFACE_REQUIRES_WORKSPACE__": settingsSurface.requiresWorkspace ? "true" : "false",
91
- "__ASSISTANT_SETTINGS_SURFACE_REQUIRES_CONSOLE_OWNER__":
92
- settingsSurface.accessPolicyId === "console_owner" ? "true" : "false",
93
117
  "__ASSISTANT_CONFIG_SCOPE__": configScope,
94
118
  "__ASSISTANT_SETTINGS_HOST__": `${settingsSurface.id}-settings`,
95
- "__ASSISTANT_CONFIG_TABLE__": "assistant_config",
96
- "__ASSISTANT_CONVERSATIONS_TABLE__": `assistant_${tableSuffix}_conversations`,
97
- "__ASSISTANT_MESSAGES_TABLE__": `assistant_${tableSuffix}_messages`,
119
+ "__ASSISTANT_AI_CONFIG_PREFIX__": resolveAiConfigPrefix(runtimeSurface.id, options?.["ai-config-prefix"]),
98
120
  "__ASSISTANT_MENU_PLACEMENT_HOST__": placementTarget.host,
99
121
  "__ASSISTANT_MENU_PLACEMENT_POSITION__": placementTarget.position,
100
122
  "__ASSISTANT_MENU_COMPONENT_TOKEN__": menuComponentToken,
101
123
  "__ASSISTANT_MENU_LABEL__": normalizeText(options?.["menu-label"]) || "Assistant",
102
124
  "__ASSISTANT_MENU_WORKSPACE_SUFFIX__": "/assistant",
103
- "__ASSISTANT_MENU_NON_WORKSPACE_SUFFIX__": "/assistant"
125
+ "__ASSISTANT_MENU_NON_WORKSPACE_SUFFIX__": "/assistant",
126
+ "__ASSISTANT_SETTINGS_MENU_LABEL__": normalizeText(options?.["menu-label"]) || "Assistant",
127
+ "__ASSISTANT_SETTINGS_MENU_WORKSPACE_SUFFIX__": settingsMenuSuffix,
128
+ "__ASSISTANT_SETTINGS_MENU_NON_WORKSPACE_SUFFIX__": settingsMenuSuffix
104
129
  });
105
130
  }
106
131
 
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <AssistantSurfaceClientElement />
2
+ <AssistantSurfaceClientElement surface-id="__ASSISTANT_SURFACE_ID__" />
3
3
  </template>
4
4
 
5
5
  <script setup>
6
- import { AssistantSurfaceClientElement } from "@local/assistant/client";
6
+ import { AssistantSurfaceClientElement } from "@jskit-ai/assistant-runtime/client";
7
7
  </script>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <AssistantSettingsClientElement target-surface-id="__ASSISTANT_SURFACE_ID__" />
3
+ </template>
4
+
5
+ <script setup>
6
+ import { AssistantSettingsClientElement } from "@jskit-ai/assistant-runtime/client";
7
+ </script>