@jskit-ai/assistant-core 0.1.7 → 0.1.9
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 +4 -4
- package/package.json +5 -4
- package/src/client/components/AssistantClientElement.vue +4 -3
- package/src/server/repositories/repositoryPersistenceUtils.js +2 -21
- package/src/shared/assistantResource.js +26 -26
- package/src/shared/assistantSettingsResource.js +7 -5
- package/src/shared/queryKeys.js +6 -4
- package/test/assistantResource.test.js +5 -5
- package/test/queryKeys.test.js +4 -1
package/package.descriptor.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
packageVersion: 1,
|
|
3
3
|
packageId: "@jskit-ai/assistant-core",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.9",
|
|
5
5
|
kind: "runtime",
|
|
6
6
|
description: "Reusable assistant client/server/shared primitives without surface-specific routes or settings ownership.",
|
|
7
7
|
dependsOn: [
|
|
@@ -45,9 +45,9 @@ export default Object.freeze({
|
|
|
45
45
|
mutations: {
|
|
46
46
|
dependencies: {
|
|
47
47
|
runtime: {
|
|
48
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
49
|
-
"@jskit-ai/kernel": "0.1.
|
|
50
|
-
"@jskit-ai/users-core": "0.1.
|
|
48
|
+
"@jskit-ai/http-runtime": "0.1.32",
|
|
49
|
+
"@jskit-ai/kernel": "0.1.33",
|
|
50
|
+
"@jskit-ai/users-core": "0.1.43",
|
|
51
51
|
"@tanstack/vue-query": "^5.90.5",
|
|
52
52
|
"dompurify": "^3.3.3",
|
|
53
53
|
"marked": "^17.0.4",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/assistant-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
"./shared": "./src/shared/index.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@jskit-ai/
|
|
15
|
-
"@jskit-ai/
|
|
16
|
-
"@jskit-ai/
|
|
14
|
+
"@jskit-ai/database-runtime": "0.1.33",
|
|
15
|
+
"@jskit-ai/http-runtime": "0.1.32",
|
|
16
|
+
"@jskit-ai/kernel": "0.1.33",
|
|
17
|
+
"@jskit-ai/users-core": "0.1.43",
|
|
17
18
|
"@tanstack/vue-query": "^5.90.5",
|
|
18
19
|
"dompurify": "^3.3.3",
|
|
19
20
|
"marked": "^17.0.4",
|
|
@@ -248,6 +248,7 @@ import { computed, nextTick, onActivated, onBeforeUnmount, onMounted, ref, shall
|
|
|
248
248
|
import { createComponentInteractionEmitter } from "@jskit-ai/kernel/client";
|
|
249
249
|
import {
|
|
250
250
|
normalizeObject,
|
|
251
|
+
normalizeRecordId,
|
|
251
252
|
normalizeText,
|
|
252
253
|
normalizeOneOf
|
|
253
254
|
} from "@jskit-ai/kernel/shared/support/normalize";
|
|
@@ -615,8 +616,8 @@ function resolveConversationActorLabel(conversation) {
|
|
|
615
616
|
return email;
|
|
616
617
|
}
|
|
617
618
|
|
|
618
|
-
const userId =
|
|
619
|
-
if (
|
|
619
|
+
const userId = normalizeRecordId(conversation?.createdByUserId, { fallback: null });
|
|
620
|
+
if (userId) {
|
|
620
621
|
return `User #${userId}`;
|
|
621
622
|
}
|
|
622
623
|
|
|
@@ -624,7 +625,7 @@ function resolveConversationActorLabel(conversation) {
|
|
|
624
625
|
}
|
|
625
626
|
|
|
626
627
|
function conversationSubtitle(conversation) {
|
|
627
|
-
const id =
|
|
628
|
+
const id = normalizeRecordId(conversation?.id, { fallback: "?" });
|
|
628
629
|
const status = normalizeConversationStatus(conversation?.status);
|
|
629
630
|
const startedAt = formatConversationStartedAt(conversation?.startedAt);
|
|
630
631
|
const messageCount = Number(conversation?.messageCount || 0);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveInsertedRecordId } from "@jskit-ai/database-runtime/shared";
|
|
1
2
|
import { parseJsonObject } from "../../shared/support/jsonObject.js";
|
|
2
3
|
|
|
3
4
|
function stringifyJsonObject(value) {
|
|
@@ -22,27 +23,7 @@ function toIso(value) {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
function resolveInsertedId(insertResult) {
|
|
25
|
-
|
|
26
|
-
const first = insertResult[0];
|
|
27
|
-
if (first && typeof first === "object" && !Array.isArray(first)) {
|
|
28
|
-
const objectId = Number(first.id);
|
|
29
|
-
if (Number.isInteger(objectId) && objectId > 0) {
|
|
30
|
-
return objectId;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const scalarId = Number(first);
|
|
35
|
-
if (Number.isInteger(scalarId) && scalarId > 0) {
|
|
36
|
-
return scalarId;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const directId = Number(insertResult);
|
|
41
|
-
if (Number.isInteger(directId) && directId > 0) {
|
|
42
|
-
return directId;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return 0;
|
|
26
|
+
return resolveInsertedRecordId(insertResult, { fallback: "" }) || "";
|
|
46
27
|
}
|
|
47
28
|
|
|
48
29
|
export { parseJsonObject, stringifyJsonObject, toIso, resolveInsertedId };
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import {
|
|
3
3
|
normalizeObjectInput,
|
|
4
|
-
createCursorListValidator
|
|
4
|
+
createCursorListValidator,
|
|
5
|
+
recordIdSchema,
|
|
6
|
+
recordIdInputSchema,
|
|
7
|
+
nullableRecordIdSchema
|
|
5
8
|
} from "@jskit-ai/kernel/shared/validators";
|
|
6
|
-
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
9
|
+
import { normalizeRecordId, normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
7
10
|
import { normalizeConversationStatus } from "./support/conversationStatus.js";
|
|
8
11
|
import { toPositiveInteger } from "./support/positiveInteger.js";
|
|
9
12
|
|
|
@@ -24,8 +27,8 @@ function normalizeChatStreamBody(payload = {}) {
|
|
|
24
27
|
input: normalizeText(source.input)
|
|
25
28
|
};
|
|
26
29
|
|
|
27
|
-
const conversationId =
|
|
28
|
-
if (conversationId
|
|
30
|
+
const conversationId = normalizeRecordId(source.conversationId, { fallback: null });
|
|
31
|
+
if (conversationId) {
|
|
29
32
|
normalized.conversationId = conversationId;
|
|
30
33
|
}
|
|
31
34
|
|
|
@@ -70,7 +73,7 @@ function normalizeConversationsListQuery(payload = {}) {
|
|
|
70
73
|
const normalized = {};
|
|
71
74
|
|
|
72
75
|
if (Object.hasOwn(source, "cursor")) {
|
|
73
|
-
normalized.cursor =
|
|
76
|
+
normalized.cursor = normalizeRecordId(source.cursor, { fallback: "" });
|
|
74
77
|
}
|
|
75
78
|
if (Object.hasOwn(source, "limit")) {
|
|
76
79
|
normalized.limit = toPositiveInteger(source.limit, 0);
|
|
@@ -94,7 +97,7 @@ function normalizeConversationMessagesQuery(payload = {}) {
|
|
|
94
97
|
function normalizeConversationMessagesParams(payload = {}) {
|
|
95
98
|
const source = normalizeObjectInput(payload);
|
|
96
99
|
return {
|
|
97
|
-
conversationId:
|
|
100
|
+
conversationId: normalizeRecordId(source.conversationId, { fallback: "" })
|
|
98
101
|
};
|
|
99
102
|
}
|
|
100
103
|
|
|
@@ -115,10 +118,10 @@ function normalizeConversationRecord(payload = {}) {
|
|
|
115
118
|
const source = normalizeObjectInput(payload);
|
|
116
119
|
|
|
117
120
|
return {
|
|
118
|
-
id:
|
|
119
|
-
workspaceId:
|
|
121
|
+
id: normalizeRecordId(source.id, { fallback: "" }),
|
|
122
|
+
workspaceId: normalizeRecordId(source.workspaceId, { fallback: null }),
|
|
120
123
|
title: normalizeText(source.title),
|
|
121
|
-
createdByUserId:
|
|
124
|
+
createdByUserId: normalizeRecordId(source.createdByUserId, { fallback: null }),
|
|
122
125
|
status: normalizeText(source.status),
|
|
123
126
|
provider: normalizeText(source.provider),
|
|
124
127
|
model: normalizeText(source.model),
|
|
@@ -136,14 +139,14 @@ function normalizeConversationMessageRecord(payload = {}) {
|
|
|
136
139
|
const source = normalizeObjectInput(payload);
|
|
137
140
|
|
|
138
141
|
return {
|
|
139
|
-
id:
|
|
140
|
-
conversationId:
|
|
141
|
-
workspaceId:
|
|
142
|
+
id: normalizeRecordId(source.id, { fallback: "" }),
|
|
143
|
+
conversationId: normalizeRecordId(source.conversationId, { fallback: "" }),
|
|
144
|
+
workspaceId: normalizeRecordId(source.workspaceId, { fallback: null }),
|
|
142
145
|
seq: toPositiveInteger(source.seq, 0),
|
|
143
146
|
role: normalizeText(source.role),
|
|
144
147
|
kind: normalizeText(source.kind),
|
|
145
148
|
clientMessageSid: normalizeText(source.clientMessageSid),
|
|
146
|
-
actorUserId:
|
|
149
|
+
actorUserId: normalizeRecordId(source.actorUserId, { fallback: null }),
|
|
147
150
|
contentText: source.contentText == null ? null : String(source.contentText),
|
|
148
151
|
metadata: normalizeObjectInput(source.metadata),
|
|
149
152
|
createdAt: normalizeText(source.createdAt)
|
|
@@ -161,7 +164,7 @@ const historyMessageSchema = Type.Object(
|
|
|
161
164
|
const chatStreamBodySchema = Type.Object(
|
|
162
165
|
{
|
|
163
166
|
messageId: Type.String({ minLength: 1, maxLength: 128 }),
|
|
164
|
-
conversationId: Type.Optional(
|
|
167
|
+
conversationId: Type.Optional(recordIdInputSchema),
|
|
165
168
|
input: Type.String({ minLength: 1, maxLength: MAX_INPUT_CHARS }),
|
|
166
169
|
history: Type.Optional(Type.Array(historyMessageSchema, { maxItems: MAX_HISTORY_MESSAGES })),
|
|
167
170
|
clientContext: Type.Optional(
|
|
@@ -181,10 +184,10 @@ const chatStreamBodySchema = Type.Object(
|
|
|
181
184
|
|
|
182
185
|
const conversationRecordSchema = Type.Object(
|
|
183
186
|
{
|
|
184
|
-
id:
|
|
185
|
-
workspaceId:
|
|
187
|
+
id: recordIdSchema,
|
|
188
|
+
workspaceId: nullableRecordIdSchema,
|
|
186
189
|
title: Type.String(),
|
|
187
|
-
createdByUserId:
|
|
190
|
+
createdByUserId: nullableRecordIdSchema,
|
|
188
191
|
status: Type.String(),
|
|
189
192
|
provider: Type.String(),
|
|
190
193
|
model: Type.String(),
|
|
@@ -206,14 +209,14 @@ const conversationRecordValidator = Object.freeze({
|
|
|
206
209
|
|
|
207
210
|
const messageRecordSchema = Type.Object(
|
|
208
211
|
{
|
|
209
|
-
id:
|
|
210
|
-
conversationId:
|
|
211
|
-
workspaceId:
|
|
212
|
+
id: recordIdSchema,
|
|
213
|
+
conversationId: recordIdSchema,
|
|
214
|
+
workspaceId: nullableRecordIdSchema,
|
|
212
215
|
seq: Type.Integer({ minimum: 1 }),
|
|
213
216
|
role: Type.String({ minLength: 1 }),
|
|
214
217
|
kind: Type.String({ minLength: 1 }),
|
|
215
218
|
clientMessageSid: Type.String(),
|
|
216
|
-
actorUserId:
|
|
219
|
+
actorUserId: nullableRecordIdSchema,
|
|
217
220
|
contentText: Type.Union([Type.String(), Type.Null()]),
|
|
218
221
|
metadata: Type.Record(Type.String(), Type.Unknown()),
|
|
219
222
|
createdAt: Type.String({ minLength: 1 })
|
|
@@ -243,7 +246,7 @@ const assistantResource = Object.freeze({
|
|
|
243
246
|
queryValidator: Object.freeze({
|
|
244
247
|
schema: Type.Object(
|
|
245
248
|
{
|
|
246
|
-
cursor:
|
|
249
|
+
cursor: Type.Optional(recordIdInputSchema),
|
|
247
250
|
limit: createOptionalPositiveIntegerQuerySchema(MAX_PAGE_SIZE),
|
|
248
251
|
status: Type.Optional(Type.String({ minLength: 1, maxLength: 32 }))
|
|
249
252
|
},
|
|
@@ -258,10 +261,7 @@ const assistantResource = Object.freeze({
|
|
|
258
261
|
paramsValidator: Object.freeze({
|
|
259
262
|
schema: Type.Object(
|
|
260
263
|
{
|
|
261
|
-
conversationId:
|
|
262
|
-
Type.Integer({ minimum: 1 }),
|
|
263
|
-
Type.String({ pattern: "^[1-9][0-9]*$" })
|
|
264
|
-
])
|
|
264
|
+
conversationId: recordIdInputSchema
|
|
265
265
|
},
|
|
266
266
|
{ additionalProperties: false }
|
|
267
267
|
),
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
|
-
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { normalizeText, normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
3
|
+
import {
|
|
4
|
+
normalizeObjectInput,
|
|
5
|
+
nullableRecordIdSchema
|
|
6
|
+
} from "@jskit-ai/kernel/shared/validators";
|
|
5
7
|
|
|
6
8
|
const MAX_SYSTEM_PROMPT_CHARS = 12_000;
|
|
7
9
|
|
|
@@ -9,7 +11,7 @@ const assistantConfigRecordSchema = Type.Object(
|
|
|
9
11
|
{
|
|
10
12
|
targetSurfaceId: Type.String({ minLength: 1, maxLength: 64 }),
|
|
11
13
|
scopeKey: Type.String({ minLength: 1, maxLength: 160 }),
|
|
12
|
-
workspaceId:
|
|
14
|
+
workspaceId: nullableRecordIdSchema,
|
|
13
15
|
settings: Type.Object(
|
|
14
16
|
{
|
|
15
17
|
systemPrompt: Type.String({ maxLength: MAX_SYSTEM_PROMPT_CHARS })
|
|
@@ -53,7 +55,7 @@ function normalizeConfigRecord(payload = {}) {
|
|
|
53
55
|
return {
|
|
54
56
|
targetSurfaceId: normalizeText(source.targetSurfaceId).toLowerCase(),
|
|
55
57
|
scopeKey: normalizeText(source.scopeKey),
|
|
56
|
-
workspaceId:
|
|
58
|
+
workspaceId: normalizeRecordId(source.workspaceId, { fallback: null }),
|
|
57
59
|
settings: {
|
|
58
60
|
systemPrompt: String(settings.systemPrompt || "")
|
|
59
61
|
}
|
package/src/shared/queryKeys.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
2
|
+
|
|
1
3
|
const ASSISTANT_QUERY_KEY_PREFIX = Object.freeze(["assistant"]);
|
|
2
4
|
|
|
3
5
|
function normalizeSurfaceId(value) {
|
|
@@ -17,10 +19,10 @@ function normalizePositiveInteger(value, fallback) {
|
|
|
17
19
|
return parsed;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
function normalizeScopeKey({ targetSurfaceId = "", workspaceSlug = "", workspaceId =
|
|
21
|
-
const normalizedWorkspaceId =
|
|
22
|
+
function normalizeScopeKey({ targetSurfaceId = "", workspaceSlug = "", workspaceId = null } = {}) {
|
|
23
|
+
const normalizedWorkspaceId = normalizeRecordId(workspaceId, { fallback: null });
|
|
22
24
|
const normalizedSurfaceId = normalizeSurfaceId(targetSurfaceId);
|
|
23
|
-
if (normalizedWorkspaceId
|
|
25
|
+
if (normalizedWorkspaceId) {
|
|
24
26
|
return `${normalizedSurfaceId}:workspace:${normalizedWorkspaceId}`;
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -38,7 +40,7 @@ function normalizeStatus(value) {
|
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
function normalizeConversationId(value) {
|
|
41
|
-
return
|
|
43
|
+
return normalizeRecordId(value, { fallback: "none" });
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
function assistantRootQueryKey() {
|
|
@@ -14,10 +14,10 @@ test("assistant output schemas accept normalized paginated payloads", () => {
|
|
|
14
14
|
|
|
15
15
|
const messagesPayload = {
|
|
16
16
|
conversation: {
|
|
17
|
-
id: 1,
|
|
18
|
-
workspaceId: 10,
|
|
17
|
+
id: "1",
|
|
18
|
+
workspaceId: "10",
|
|
19
19
|
title: "Conversation",
|
|
20
|
-
createdByUserId: 7,
|
|
20
|
+
createdByUserId: "7",
|
|
21
21
|
status: "active",
|
|
22
22
|
provider: "openai",
|
|
23
23
|
model: "gpt-4.1",
|
|
@@ -40,10 +40,10 @@ test("assistant output schemas accept normalized paginated payloads", () => {
|
|
|
40
40
|
assert.equal(Check(conversationMessagesSchema, messagesPayload), true);
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
test("assistant conversation message params accept numeric path strings and normalize to
|
|
43
|
+
test("assistant conversation message params accept numeric path strings and normalize to record-id strings", () => {
|
|
44
44
|
const paramsValidator = assistantResource.operations.conversationMessagesList.paramsValidator;
|
|
45
45
|
assert.equal(Check(paramsValidator.schema, { conversationId: "2" }), true);
|
|
46
46
|
assert.deepEqual(paramsValidator.normalize({ conversationId: "2" }), {
|
|
47
|
-
conversationId: 2
|
|
47
|
+
conversationId: "2"
|
|
48
48
|
});
|
|
49
49
|
});
|
package/test/queryKeys.test.js
CHANGED
|
@@ -28,7 +28,10 @@ test("assistant query keys normalize scope and paging", () => {
|
|
|
28
28
|
]);
|
|
29
29
|
|
|
30
30
|
assert.deepEqual(
|
|
31
|
-
assistantConversationsListQueryKey(
|
|
31
|
+
assistantConversationsListQueryKey(
|
|
32
|
+
{ targetSurfaceId: "admin", workspaceId: "9" },
|
|
33
|
+
{ limit: 10, status: "ACTIVE" }
|
|
34
|
+
),
|
|
32
35
|
["assistant", "admin:workspace:9", "conversations", "list", 10, "active"]
|
|
33
36
|
);
|
|
34
37
|
|