@jskit-ai/assistant 0.1.32 → 0.1.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.descriptor.mjs +346 -142
- package/package.json +3 -19
- package/src/server/buildTemplateContext.js +107 -0
- package/templates/migrations/assistant_config_initial.cjs +25 -0
- package/templates/migrations/assistant_transcripts_initial.cjs +21 -14
- package/templates/src/local-package/client/components/AssistantSettingsClientElement.vue +88 -0
- package/templates/src/local-package/client/components/AssistantSurfaceClientElement.vue +10 -0
- package/{src/client/composables/useAssistantWorkspaceRuntime.js → templates/src/local-package/client/composables/useAssistantRuntime.js} +91 -114
- package/templates/src/local-package/client/index.js +3 -0
- package/templates/src/local-package/client/providers/AssistantClientProvider.js +16 -0
- package/templates/src/local-package/package.descriptor.mjs +85 -0
- package/templates/src/local-package/package.json +11 -0
- package/{src/server/AssistantServiceProvider.js → templates/src/local-package/server/AssistantProvider.js} +37 -61
- package/templates/src/local-package/server/actionIds.js +9 -0
- package/templates/src/local-package/server/actions.js +190 -0
- package/templates/src/local-package/server/registerRoutes.js +296 -0
- package/templates/src/local-package/server/repositories/assistantConfigRepository.js +141 -0
- package/{src → templates/src/local-package}/server/repositories/conversationsRepository.js +44 -45
- package/{src → templates/src/local-package}/server/repositories/messagesRepository.js +49 -34
- package/templates/src/local-package/server/services/assistantConfigService.js +90 -0
- package/{src → templates/src/local-package}/server/services/chatService.js +45 -37
- package/{src → templates/src/local-package}/server/services/transcriptService.js +61 -82
- package/templates/src/local-package/shared/assistantRuntimeConfig.js +13 -0
- package/templates/src/local-package/shared/index.js +1 -0
- package/templates/src/pages/assistant/index.vue +7 -0
- package/test/buildTemplateContext.test.js +112 -0
- package/test/packageDescriptor.test.js +69 -0
- package/src/client/components/AssistantClientElement.vue +0 -1316
- package/src/client/components/AssistantConsoleSettingsClientElement.vue +0 -70
- package/src/client/components/AssistantSettingsFormCard.vue +0 -76
- package/src/client/components/AssistantWorkspaceClientElement.vue +0 -15
- package/src/client/components/AssistantWorkspaceSettingsClientElement.vue +0 -72
- package/src/client/index.js +0 -10
- package/src/client/lib/assistantApi.js +0 -137
- package/src/client/lib/assistantHttpClient.js +0 -10
- package/src/client/lib/markdownRenderer.js +0 -31
- package/src/client/providers/AssistantWebClientProvider.js +0 -20
- package/src/server/actionIds.js +0 -11
- package/src/server/actions.js +0 -191
- package/src/server/lib/aiClient.js +0 -43
- package/src/server/lib/ndjson.js +0 -47
- package/src/server/lib/providers/anthropicClient.js +0 -375
- package/src/server/lib/providers/common.js +0 -150
- package/src/server/lib/providers/deepSeekClient.js +0 -22
- package/src/server/lib/providers/openAiClient.js +0 -13
- package/src/server/lib/providers/openAiCompatibleClient.js +0 -69
- package/src/server/lib/resolveWorkspaceSlug.js +0 -24
- package/src/server/lib/serviceToolCatalog.js +0 -459
- package/src/server/registerRoutes.js +0 -383
- package/src/server/repositories/assistantSettingsRepository.js +0 -100
- package/src/server/repositories/repositoryPersistenceUtils.js +0 -48
- package/src/server/services/assistantSettingsService.js +0 -149
- package/src/shared/assistantPaths.js +0 -50
- package/src/shared/assistantResource.js +0 -317
- package/src/shared/assistantSettingsResource.js +0 -197
- package/src/shared/index.js +0 -43
- package/src/shared/queryKeys.js +0 -69
- package/src/shared/settingsEvents.js +0 -6
- package/src/shared/streamEvents.js +0 -29
- package/src/shared/support/conversationStatus.js +0 -18
- package/src/shared/support/jsonObject.js +0 -18
- package/src/shared/support/positiveInteger.js +0 -9
- package/templates/migrations/assistant_settings_initial.cjs +0 -37
- package/templates/src/pages/admin/workspace/assistant/index.vue +0 -7
- package/test/aiConfigValidation.test.js +0 -15
- package/test/assistantApiSurfaceHeader.test.js +0 -64
- package/test/assistantResource.test.js +0 -53
- package/test/assistantSettingsResource.test.js +0 -48
- package/test/assistantSettingsService.test.js +0 -133
- package/test/chatService.test.js +0 -841
- package/test/descriptorSurfaceOption.test.js +0 -35
- package/test/queryKeys.test.js +0 -41
- package/test/resolveWorkspaceSlug.test.js +0 -83
- package/test/routeInputContracts.test.js +0 -286
- package/test/serviceToolCatalog.test.js +0 -1235
- package/test/transcriptService.test.js +0 -175
|
@@ -2,24 +2,27 @@ import { computed, ref, watch } from "vue";
|
|
|
2
2
|
import { useQueryClient } from "@tanstack/vue-query";
|
|
3
3
|
import { getClientAppConfig } from "@jskit-ai/kernel/client";
|
|
4
4
|
import { normalizeObject, normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
5
|
-
import {
|
|
6
|
-
import { useShellWebErrorRuntime } from "@jskit-ai/shell-web/client/error";
|
|
7
|
-
import { useWorkspaceRouteContext } from "@jskit-ai/users-web/client/composables/useWorkspaceRouteContext";
|
|
8
|
-
import { usePagedCollection } from "@jskit-ai/users-web/client/composables/usePagedCollection";
|
|
5
|
+
import { buildAssistantApiPath } from "@jskit-ai/assistant-core/shared";
|
|
9
6
|
import {
|
|
10
|
-
MAX_INPUT_CHARS,
|
|
11
7
|
ASSISTANT_STREAM_EVENT_TYPES,
|
|
12
8
|
MAX_HISTORY_MESSAGES,
|
|
9
|
+
MAX_INPUT_CHARS,
|
|
13
10
|
assistantConversationMessagesQueryKey,
|
|
14
11
|
assistantConversationsListQueryKey,
|
|
15
|
-
|
|
12
|
+
assistantScopeQueryKey,
|
|
16
13
|
normalizeAssistantStreamEventType,
|
|
17
14
|
normalizeConversationStatus as normalizeAssistantConversationStatus,
|
|
18
15
|
parseJsonObject,
|
|
19
16
|
toPositiveInteger
|
|
20
|
-
} from "
|
|
21
|
-
import {
|
|
22
|
-
|
|
17
|
+
} from "@jskit-ai/assistant-core/shared";
|
|
18
|
+
import {
|
|
19
|
+
assistantHttpClient,
|
|
20
|
+
createAssistantApi
|
|
21
|
+
} from "@jskit-ai/assistant-core/client";
|
|
22
|
+
import { useShellWebErrorRuntime } from "@jskit-ai/shell-web/client/error";
|
|
23
|
+
import { usePagedCollection } from "@jskit-ai/users-web/client/composables/usePagedCollection";
|
|
24
|
+
import { useWorkspaceRouteContext } from "@jskit-ai/users-web/client/composables/useWorkspaceRouteContext";
|
|
25
|
+
import { assistantRuntimeConfig } from "../../shared/assistantRuntimeConfig.js";
|
|
23
26
|
|
|
24
27
|
const DEFAULT_STREAM_TIMEOUT_MS = 120_000;
|
|
25
28
|
const DEFAULT_HISTORY_PAGE_SIZE = 20;
|
|
@@ -36,43 +39,31 @@ function toNonNegativeInteger(value, fallback = 0) {
|
|
|
36
39
|
return parsed;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
function
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return `assistant.activeConversationId:${normalizedWorkspaceSlug}`;
|
|
42
|
+
function buildScopeStorageKey(scope = {}) {
|
|
43
|
+
const runtimeSurfaceId = normalizeText(scope?.targetSurfaceId).toLowerCase() || "assistant";
|
|
44
|
+
const workspaceSlug = normalizeText(scope?.workspaceSlug).toLowerCase() || "global";
|
|
45
|
+
return `assistant.activeConversationId:${runtimeSurfaceId}:${workspaceSlug}`;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
function readStoredActiveConversationId(
|
|
48
|
+
function readStoredActiveConversationId(scope = {}) {
|
|
49
49
|
if (typeof window === "undefined" || !window.sessionStorage) {
|
|
50
50
|
return 0;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
const storageKey = buildActiveConversationStorageKey(workspaceSlug);
|
|
54
|
-
if (!storageKey) {
|
|
55
|
-
return 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
53
|
try {
|
|
59
|
-
return toPositiveInteger(window.sessionStorage.getItem(
|
|
54
|
+
return toPositiveInteger(window.sessionStorage.getItem(buildScopeStorageKey(scope)), 0);
|
|
60
55
|
} catch {
|
|
61
56
|
return 0;
|
|
62
57
|
}
|
|
63
58
|
}
|
|
64
59
|
|
|
65
|
-
function writeStoredActiveConversationId(
|
|
60
|
+
function writeStoredActiveConversationId(scope = {}, conversationId) {
|
|
66
61
|
if (typeof window === "undefined" || !window.sessionStorage) {
|
|
67
62
|
return;
|
|
68
63
|
}
|
|
69
64
|
|
|
70
|
-
const storageKey = buildActiveConversationStorageKey(workspaceSlug);
|
|
71
|
-
if (!storageKey) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
65
|
const normalizedConversationId = toPositiveInteger(conversationId, 0);
|
|
66
|
+
const storageKey = buildScopeStorageKey(scope);
|
|
76
67
|
try {
|
|
77
68
|
if (normalizedConversationId > 0) {
|
|
78
69
|
window.sessionStorage.setItem(storageKey, String(normalizedConversationId));
|
|
@@ -213,19 +204,6 @@ function mapTranscriptEntriesToAssistantState(entries) {
|
|
|
213
204
|
};
|
|
214
205
|
}
|
|
215
206
|
|
|
216
|
-
function resolveWorkspaceScope(bootstrapData = {}, workspaceSlug = "") {
|
|
217
|
-
const activeWorkspace = bootstrapData?.workspace && typeof bootstrapData.workspace === "object"
|
|
218
|
-
? bootstrapData.workspace
|
|
219
|
-
: bootstrapData?.activeWorkspace && typeof bootstrapData.activeWorkspace === "object"
|
|
220
|
-
? bootstrapData.activeWorkspace
|
|
221
|
-
: null;
|
|
222
|
-
|
|
223
|
-
return {
|
|
224
|
-
workspaceSlug: normalizeText(workspaceSlug),
|
|
225
|
-
workspaceId: toPositiveInteger(activeWorkspace?.id, 0)
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
|
|
229
207
|
function resolveRuntimePolicy() {
|
|
230
208
|
const appConfig = getClientAppConfig();
|
|
231
209
|
const assistantConfig = normalizeObject(appConfig?.assistant);
|
|
@@ -238,27 +216,24 @@ function resolveRuntimePolicy() {
|
|
|
238
216
|
});
|
|
239
217
|
}
|
|
240
218
|
|
|
241
|
-
function createRuntimeApi({ overrideApi = null, resolveSurfaceId = null } = {}) {
|
|
219
|
+
function createRuntimeApi({ overrideApi = null, resolveBasePath, resolveSurfaceId = null } = {}) {
|
|
242
220
|
if (overrideApi && typeof overrideApi.streamChat === "function") {
|
|
243
221
|
return overrideApi;
|
|
244
222
|
}
|
|
245
223
|
|
|
246
|
-
return
|
|
224
|
+
return createAssistantApi({
|
|
247
225
|
request: assistantHttpClient.request,
|
|
248
226
|
requestStream: assistantHttpClient.requestStream,
|
|
227
|
+
resolveBasePath,
|
|
249
228
|
resolveSurfaceId
|
|
250
229
|
});
|
|
251
230
|
}
|
|
252
231
|
|
|
253
|
-
function
|
|
232
|
+
function useAssistantRuntime({ api = null } = {}) {
|
|
254
233
|
const runtimePolicy = resolveRuntimePolicy();
|
|
255
234
|
const queryClient = useQueryClient();
|
|
256
235
|
const errorRuntime = useShellWebErrorRuntime();
|
|
257
|
-
const {
|
|
258
|
-
const runtimeApi = createRuntimeApi({
|
|
259
|
-
overrideApi: api,
|
|
260
|
-
resolveSurfaceId: () => normalizeText(currentSurfaceId.value).toLowerCase()
|
|
261
|
-
});
|
|
236
|
+
const { placementContext, currentSurfaceId, workspaceSlugFromRoute } = useWorkspaceRouteContext();
|
|
262
237
|
|
|
263
238
|
const messages = ref([]);
|
|
264
239
|
const input = ref("");
|
|
@@ -270,12 +245,45 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
270
245
|
const abortController = ref(null);
|
|
271
246
|
|
|
272
247
|
const placementSnapshot = computed(() => normalizeObject(placementContext.value));
|
|
273
|
-
const
|
|
274
|
-
|
|
248
|
+
const runtimeScope = computed(() => {
|
|
249
|
+
const workspaceSlug = assistantRuntimeConfig.runtimeSurfaceRequiresWorkspace
|
|
250
|
+
? normalizeText(workspaceSlugFromRoute.value).toLowerCase()
|
|
251
|
+
: "";
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
targetSurfaceId: assistantRuntimeConfig.runtimeSurfaceId,
|
|
255
|
+
workspaceSlug,
|
|
256
|
+
workspaceId: assistantRuntimeConfig.runtimeSurfaceRequiresWorkspace
|
|
257
|
+
? toPositiveInteger(placementSnapshot.value?.workspace?.id, 0)
|
|
258
|
+
: 0
|
|
259
|
+
};
|
|
260
|
+
});
|
|
261
|
+
const hasRuntimeScope = computed(() =>
|
|
262
|
+
assistantRuntimeConfig.runtimeSurfaceRequiresWorkspace ? Boolean(runtimeScope.value.workspaceSlug) : true
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
const runtimeApi = createRuntimeApi({
|
|
266
|
+
overrideApi: api,
|
|
267
|
+
resolveBasePath: () =>
|
|
268
|
+
buildAssistantApiPath({
|
|
269
|
+
requiresWorkspace: assistantRuntimeConfig.runtimeSurfaceRequiresWorkspace,
|
|
270
|
+
workspaceSlug: runtimeScope.value.workspaceSlug,
|
|
271
|
+
suffix: "/"
|
|
272
|
+
}),
|
|
273
|
+
resolveSurfaceId: () => normalizeText(currentSurfaceId.value).toLowerCase()
|
|
274
|
+
});
|
|
275
|
+
|
|
275
276
|
const activeConversationId = computed(() => normalizeText(conversationId.value));
|
|
276
|
-
const isAdminSurface = computed(() => currentSurfaceId.value === "admin");
|
|
277
|
-
const canSend = computed(() =>
|
|
278
|
-
|
|
277
|
+
const isAdminSurface = computed(() => normalizeText(currentSurfaceId.value).toLowerCase() === "admin");
|
|
278
|
+
const canSend = computed(() => {
|
|
279
|
+
return Boolean(
|
|
280
|
+
hasRuntimeScope.value &&
|
|
281
|
+
!isStreaming.value &&
|
|
282
|
+
!isRestoringConversation.value &&
|
|
283
|
+
normalizeText(input.value)
|
|
284
|
+
);
|
|
285
|
+
});
|
|
286
|
+
const canStartNewConversation = computed(() => Boolean(hasRuntimeScope.value && !isStreaming.value));
|
|
279
287
|
|
|
280
288
|
function setRuntimeError(message, dedupeKey = "") {
|
|
281
289
|
const normalizedMessage = normalizeText(message);
|
|
@@ -285,23 +293,23 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
285
293
|
}
|
|
286
294
|
|
|
287
295
|
errorRuntime.report({
|
|
288
|
-
source: "assistant.
|
|
296
|
+
source: "assistant.runtime",
|
|
289
297
|
message: normalizedMessage,
|
|
290
298
|
severity: "error",
|
|
291
299
|
channel: "banner",
|
|
292
|
-
dedupeKey: dedupeKey || `assistant.
|
|
300
|
+
dedupeKey: dedupeKey || `assistant.runtime:error:${normalizedMessage}`,
|
|
293
301
|
dedupeWindowMs: 3000
|
|
294
302
|
});
|
|
295
303
|
}
|
|
296
304
|
|
|
297
305
|
const conversationHistoryCollection = usePagedCollection({
|
|
298
306
|
queryKey: computed(() =>
|
|
299
|
-
assistantConversationsListQueryKey(
|
|
307
|
+
assistantConversationsListQueryKey(runtimeScope.value, {
|
|
300
308
|
limit: runtimePolicy.historyPageSize
|
|
301
309
|
})
|
|
302
310
|
),
|
|
303
311
|
queryFn: ({ pageParam = null }) =>
|
|
304
|
-
runtimeApi.listConversations(
|
|
312
|
+
runtimeApi.listConversations({
|
|
305
313
|
cursor: pageParam,
|
|
306
314
|
limit: runtimePolicy.historyPageSize
|
|
307
315
|
}),
|
|
@@ -310,7 +318,7 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
310
318
|
const conversationNumericId = toPositiveInteger(entry?.id, 0);
|
|
311
319
|
return conversationNumericId > 0 ? String(conversationNumericId) : normalizeText(entry?.id);
|
|
312
320
|
},
|
|
313
|
-
enabled: computed(() =>
|
|
321
|
+
enabled: computed(() => hasRuntimeScope.value),
|
|
314
322
|
queryOptions: {
|
|
315
323
|
staleTime: runtimePolicy.historyStaleTimeMs,
|
|
316
324
|
refetchOnMount: false,
|
|
@@ -328,46 +336,45 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
328
336
|
const conversationHistoryError = conversationHistoryCollection.loadError;
|
|
329
337
|
|
|
330
338
|
watch(conversationId, (nextConversationId, previousConversationId) => {
|
|
331
|
-
|
|
332
|
-
if (!workspaceSlug) {
|
|
339
|
+
if (!hasRuntimeScope.value) {
|
|
333
340
|
return;
|
|
334
341
|
}
|
|
335
342
|
|
|
336
343
|
const nextConversationNumericId = toPositiveInteger(nextConversationId, 0);
|
|
337
344
|
if (nextConversationNumericId > 0) {
|
|
338
|
-
writeStoredActiveConversationId(
|
|
345
|
+
writeStoredActiveConversationId(runtimeScope.value, nextConversationNumericId);
|
|
339
346
|
return;
|
|
340
347
|
}
|
|
341
348
|
|
|
342
349
|
const previousConversationNumericId = toPositiveInteger(previousConversationId, 0);
|
|
343
350
|
if (previousConversationNumericId > 0) {
|
|
344
|
-
writeStoredActiveConversationId(
|
|
351
|
+
writeStoredActiveConversationId(runtimeScope.value, 0);
|
|
345
352
|
}
|
|
346
353
|
});
|
|
347
354
|
|
|
348
355
|
watch(
|
|
349
356
|
[
|
|
350
|
-
|
|
357
|
+
hasRuntimeScope,
|
|
351
358
|
conversationHistoryLoading,
|
|
352
|
-
|
|
359
|
+
runtimeScope,
|
|
353
360
|
conversationId,
|
|
354
361
|
conversationHistory,
|
|
355
362
|
isRestoringConversation
|
|
356
363
|
],
|
|
357
364
|
async ([
|
|
358
|
-
|
|
365
|
+
nextHasRuntimeScope,
|
|
359
366
|
nextConversationHistoryLoading,
|
|
360
|
-
|
|
367
|
+
nextRuntimeScope,
|
|
361
368
|
nextConversationId,
|
|
362
369
|
nextConversationHistory,
|
|
363
370
|
nextIsRestoringConversation
|
|
364
371
|
]) => {
|
|
365
|
-
if (!
|
|
372
|
+
if (!nextHasRuntimeScope || nextConversationHistoryLoading || nextIsRestoringConversation) {
|
|
366
373
|
return;
|
|
367
374
|
}
|
|
368
375
|
|
|
369
|
-
const
|
|
370
|
-
if (
|
|
376
|
+
const activeConversationNumericId = toPositiveInteger(nextConversationId, 0);
|
|
377
|
+
if (activeConversationNumericId > 0) {
|
|
371
378
|
return;
|
|
372
379
|
}
|
|
373
380
|
|
|
@@ -376,7 +383,7 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
376
383
|
return;
|
|
377
384
|
}
|
|
378
385
|
|
|
379
|
-
const storedConversationId = readStoredActiveConversationId(
|
|
386
|
+
const storedConversationId = readStoredActiveConversationId(nextRuntimeScope);
|
|
380
387
|
if (!storedConversationId) {
|
|
381
388
|
return;
|
|
382
389
|
}
|
|
@@ -385,7 +392,7 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
385
392
|
(entry) => toPositiveInteger(entry?.id, 0) === storedConversationId
|
|
386
393
|
);
|
|
387
394
|
if (!hasStoredConversation) {
|
|
388
|
-
writeStoredActiveConversationId(
|
|
395
|
+
writeStoredActiveConversationId(nextRuntimeScope, 0);
|
|
389
396
|
return;
|
|
390
397
|
}
|
|
391
398
|
|
|
@@ -419,17 +426,17 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
419
426
|
}
|
|
420
427
|
|
|
421
428
|
async function invalidateConversationScope() {
|
|
422
|
-
if (!
|
|
429
|
+
if (!hasRuntimeScope.value) {
|
|
423
430
|
return;
|
|
424
431
|
}
|
|
425
432
|
|
|
426
433
|
await queryClient.invalidateQueries({
|
|
427
|
-
queryKey:
|
|
434
|
+
queryKey: assistantScopeQueryKey(runtimeScope.value)
|
|
428
435
|
});
|
|
429
436
|
}
|
|
430
437
|
|
|
431
438
|
async function refreshConversationHistory() {
|
|
432
|
-
if (!
|
|
439
|
+
if (!hasRuntimeScope.value) {
|
|
433
440
|
return;
|
|
434
441
|
}
|
|
435
442
|
|
|
@@ -442,7 +449,7 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
442
449
|
|
|
443
450
|
async function selectConversationById(nextConversationId) {
|
|
444
451
|
const normalizedConversationId = normalizeText(nextConversationId);
|
|
445
|
-
if (!normalizedConversationId || isStreaming.value || isRestoringConversation.value || !
|
|
452
|
+
if (!normalizedConversationId || isStreaming.value || isRestoringConversation.value || !hasRuntimeScope.value) {
|
|
446
453
|
return;
|
|
447
454
|
}
|
|
448
455
|
|
|
@@ -458,12 +465,12 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
458
465
|
|
|
459
466
|
try {
|
|
460
467
|
const response = await queryClient.fetchQuery({
|
|
461
|
-
queryKey: assistantConversationMessagesQueryKey(
|
|
468
|
+
queryKey: assistantConversationMessagesQueryKey(runtimeScope.value, parsedConversationId, {
|
|
462
469
|
page: RESTORE_MESSAGES_PAGE,
|
|
463
470
|
pageSize: runtimePolicy.restoreMessagesPageSize
|
|
464
471
|
}),
|
|
465
472
|
queryFn: () =>
|
|
466
|
-
runtimeApi.getConversationMessages(
|
|
473
|
+
runtimeApi.getConversationMessages(parsedConversationId, {
|
|
467
474
|
page: RESTORE_MESSAGES_PAGE,
|
|
468
475
|
pageSize: runtimePolicy.restoreMessagesPageSize
|
|
469
476
|
})
|
|
@@ -495,7 +502,7 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
495
502
|
input.value = "";
|
|
496
503
|
setRuntimeError("");
|
|
497
504
|
conversationId.value = null;
|
|
498
|
-
writeStoredActiveConversationId(
|
|
505
|
+
writeStoredActiveConversationId(runtimeScope.value, 0);
|
|
499
506
|
isStreaming.value = false;
|
|
500
507
|
isRestoringConversation.value = false;
|
|
501
508
|
abortController.value = null;
|
|
@@ -527,7 +534,7 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
527
534
|
|
|
528
535
|
async function sendMessage() {
|
|
529
536
|
const normalizedInput = normalizeText(input.value).slice(0, MAX_INPUT_CHARS);
|
|
530
|
-
if (!normalizedInput || isStreaming.value || isRestoringConversation.value || !
|
|
537
|
+
if (!normalizedInput || isStreaming.value || isRestoringConversation.value || !hasRuntimeScope.value) {
|
|
531
538
|
return;
|
|
532
539
|
}
|
|
533
540
|
|
|
@@ -567,7 +574,6 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
567
574
|
|
|
568
575
|
try {
|
|
569
576
|
await runtimeApi.streamChat(
|
|
570
|
-
workspaceScope.value.workspaceSlug,
|
|
571
577
|
{
|
|
572
578
|
messageId,
|
|
573
579
|
...(parsedConversationId > 0 ? { conversationId: parsedConversationId } : {}),
|
|
@@ -645,7 +651,7 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
645
651
|
if (eventType === ASSISTANT_STREAM_EVENT_TYPES.ERROR) {
|
|
646
652
|
setRuntimeError(
|
|
647
653
|
normalizeText(event?.message) || "Assistant request failed.",
|
|
648
|
-
"assistant.
|
|
654
|
+
"assistant.runtime:stream-event-error"
|
|
649
655
|
);
|
|
650
656
|
updateMessage(assistantMessageId, {
|
|
651
657
|
status: "error"
|
|
@@ -664,7 +670,7 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
664
670
|
const assistantMessageText = normalizeText(assistantMessage?.text);
|
|
665
671
|
if (!assistantMessageText && streamDoneStatus !== "aborted") {
|
|
666
672
|
if (!error.value) {
|
|
667
|
-
setRuntimeError("Assistant returned no output.", "assistant.
|
|
673
|
+
setRuntimeError("Assistant returned no output.", "assistant.runtime:empty-output");
|
|
668
674
|
}
|
|
669
675
|
updateMessage(assistantMessageId, {
|
|
670
676
|
status: "error"
|
|
@@ -698,35 +704,6 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
698
704
|
}
|
|
699
705
|
}
|
|
700
706
|
|
|
701
|
-
useRealtimeEvent({
|
|
702
|
-
event: "assistant.transcript.changed",
|
|
703
|
-
enabled: computed(() => hasWorkspaceScope.value),
|
|
704
|
-
matches({ payload }) {
|
|
705
|
-
if (!payload || typeof payload !== "object") {
|
|
706
|
-
return true;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
const scope = payload.scope && typeof payload.scope === "object" ? payload.scope : {};
|
|
710
|
-
const workspaceIdFromEvent = toPositiveInteger(scope.id || scope.workspaceId, 0);
|
|
711
|
-
const workspaceId = toPositiveInteger(workspaceScope.value.workspaceId, 0);
|
|
712
|
-
if (workspaceIdFromEvent > 0 && workspaceId > 0) {
|
|
713
|
-
return workspaceIdFromEvent === workspaceId;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
return true;
|
|
717
|
-
},
|
|
718
|
-
async onEvent({ payload }) {
|
|
719
|
-
await invalidateConversationScope();
|
|
720
|
-
const incomingConversationId = toPositiveInteger(payload?.conversationId, 0);
|
|
721
|
-
const activeId = toPositiveInteger(conversationId.value, 0);
|
|
722
|
-
if (!incomingConversationId || incomingConversationId !== activeId || !activeId) {
|
|
723
|
-
return;
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
await selectConversationById(activeId);
|
|
727
|
-
}
|
|
728
|
-
});
|
|
729
|
-
|
|
730
707
|
const viewer = computed(() => {
|
|
731
708
|
const user = normalizeObject(placementSnapshot.value.user);
|
|
732
709
|
|
|
@@ -774,4 +751,4 @@ function useAssistantWorkspaceRuntime({ api = null } = {}) {
|
|
|
774
751
|
});
|
|
775
752
|
}
|
|
776
753
|
|
|
777
|
-
export {
|
|
754
|
+
export { useAssistantRuntime };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { default as AssistantSurfaceClientElement } from "./components/AssistantSurfaceClientElement.vue";
|
|
2
|
+
export { default as AssistantSettingsClientElement } from "./components/AssistantSettingsClientElement.vue";
|
|
3
|
+
export { useAssistantRuntime } from "./composables/useAssistantRuntime.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import AssistantSettingsClientElement from "../components/AssistantSettingsClientElement.vue";
|
|
2
|
+
|
|
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);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { AssistantClientProvider };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export default Object.freeze({
|
|
2
|
+
packageVersion: 1,
|
|
3
|
+
packageId: "@local/assistant",
|
|
4
|
+
version: "0.1.0",
|
|
5
|
+
kind: "runtime",
|
|
6
|
+
description: "App-local generated assistant runtime.",
|
|
7
|
+
dependsOn: [
|
|
8
|
+
"@jskit-ai/assistant-core",
|
|
9
|
+
"@jskit-ai/database-runtime",
|
|
10
|
+
"@jskit-ai/http-runtime",
|
|
11
|
+
"@jskit-ai/shell-web",
|
|
12
|
+
"@jskit-ai/users-core",
|
|
13
|
+
"@jskit-ai/users-web"
|
|
14
|
+
],
|
|
15
|
+
capabilities: {
|
|
16
|
+
provides: ["assistant.runtime"],
|
|
17
|
+
requires: [
|
|
18
|
+
"runtime.actions",
|
|
19
|
+
"runtime.database",
|
|
20
|
+
"auth.policy",
|
|
21
|
+
"runtime.http-client",
|
|
22
|
+
"users.core",
|
|
23
|
+
"users.web"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
runtime: {
|
|
27
|
+
server: {
|
|
28
|
+
providers: [
|
|
29
|
+
{
|
|
30
|
+
entrypoint: "src/server/AssistantProvider.js",
|
|
31
|
+
export: "AssistantProvider"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
client: {
|
|
36
|
+
providers: [
|
|
37
|
+
{
|
|
38
|
+
entrypoint: "src/client/providers/AssistantClientProvider.js",
|
|
39
|
+
export: "AssistantClientProvider"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
metadata: {
|
|
45
|
+
apiSummary: {
|
|
46
|
+
surfaces: [
|
|
47
|
+
{
|
|
48
|
+
subpath: "./server/actionIds",
|
|
49
|
+
summary: "Generated assistant action identifiers."
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
subpath: "./client",
|
|
53
|
+
summary: "Generated assistant client wrappers."
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
subpath: "./shared",
|
|
57
|
+
summary: "Generated assistant runtime configuration."
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
containerTokens: {
|
|
61
|
+
server: [
|
|
62
|
+
"assistant.config.repository",
|
|
63
|
+
"assistant.conversation.repository",
|
|
64
|
+
"assistant.message.repository",
|
|
65
|
+
"assistant.ai.client",
|
|
66
|
+
"assistant.service.tool-catalog"
|
|
67
|
+
],
|
|
68
|
+
client: [
|
|
69
|
+
"assistant.web.settings.element"
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
mutations: {
|
|
75
|
+
dependencies: {
|
|
76
|
+
runtime: {},
|
|
77
|
+
dev: {}
|
|
78
|
+
},
|
|
79
|
+
packageJson: {
|
|
80
|
+
scripts: {}
|
|
81
|
+
},
|
|
82
|
+
procfile: {},
|
|
83
|
+
files: []
|
|
84
|
+
}
|
|
85
|
+
});
|