@jskit-ai/assistant-core 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  export default Object.freeze({
2
2
  packageVersion: 1,
3
3
  packageId: "@jskit-ai/assistant-core",
4
- version: "0.1.8",
4
+ version: "0.1.10",
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.31",
49
- "@jskit-ai/kernel": "0.1.32",
50
- "@jskit-ai/users-core": "0.1.42",
48
+ "@jskit-ai/http-runtime": "0.1.33",
49
+ "@jskit-ai/kernel": "0.1.34",
50
+ "@jskit-ai/users-core": "0.1.44",
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.8",
3
+ "version": "0.1.10",
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/http-runtime": "0.1.31",
15
- "@jskit-ai/kernel": "0.1.32",
16
- "@jskit-ai/users-core": "0.1.42",
14
+ "@jskit-ai/database-runtime": "0.1.34",
15
+ "@jskit-ai/http-runtime": "0.1.33",
16
+ "@jskit-ai/kernel": "0.1.34",
17
+ "@jskit-ai/users-core": "0.1.44",
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 = Number(conversation?.createdByUserId);
619
- if (Number.isInteger(userId) && userId > 0) {
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 = Number(conversation?.id) || 0;
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
- if (Array.isArray(insertResult) && insertResult.length > 0) {
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 = toPositiveInteger(source.conversationId, 0);
28
- if (conversationId > 0) {
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 = toPositiveInteger(source.cursor, 0);
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: toPositiveInteger(source.conversationId, 0)
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: toPositiveInteger(source.id, 0),
119
- workspaceId: toPositiveInteger(source.workspaceId, 0) || null,
121
+ id: normalizeRecordId(source.id, { fallback: "" }),
122
+ workspaceId: normalizeRecordId(source.workspaceId, { fallback: null }),
120
123
  title: normalizeText(source.title),
121
- createdByUserId: toPositiveInteger(source.createdByUserId, 0) || null,
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: toPositiveInteger(source.id, 0),
140
- conversationId: toPositiveInteger(source.conversationId, 0),
141
- workspaceId: toPositiveInteger(source.workspaceId, 0) || null,
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: toPositiveInteger(source.actorUserId, 0) || null,
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(Type.Integer({ minimum: 1 })),
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: Type.Integer({ minimum: 1 }),
185
- workspaceId: Type.Union([Type.Integer({ minimum: 1 }), Type.Null()]),
187
+ id: recordIdSchema,
188
+ workspaceId: nullableRecordIdSchema,
186
189
  title: Type.String(),
187
- createdByUserId: Type.Union([Type.Integer({ minimum: 1 }), Type.Null()]),
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: Type.Integer({ minimum: 1 }),
210
- conversationId: Type.Integer({ minimum: 1 }),
211
- workspaceId: Type.Union([Type.Integer({ minimum: 1 }), Type.Null()]),
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: Type.Union([Type.Integer({ minimum: 1 }), Type.Null()]),
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: createOptionalPositiveIntegerQuerySchema(),
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: Type.Union([
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 { normalizeObjectInput } from "@jskit-ai/kernel/shared/validators";
4
- import { toPositiveInteger } from "./support/positiveInteger.js";
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: Type.Union([Type.Integer({ minimum: 1 }), Type.Null()]),
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: toPositiveInteger(source.workspaceId, 0) || null,
58
+ workspaceId: normalizeRecordId(source.workspaceId, { fallback: null }),
57
59
  settings: {
58
60
  systemPrompt: String(settings.systemPrompt || "")
59
61
  }
@@ -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 = 0 } = {}) {
21
- const normalizedWorkspaceId = normalizePositiveInteger(workspaceId, 0);
22
+ function normalizeScopeKey({ targetSurfaceId = "", workspaceSlug = "", workspaceId = null } = {}) {
23
+ const normalizedWorkspaceId = normalizeRecordId(workspaceId, { fallback: null });
22
24
  const normalizedSurfaceId = normalizeSurfaceId(targetSurfaceId);
23
- if (normalizedWorkspaceId > 0) {
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 String(normalizePositiveInteger(value, 0) || "none");
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 integer", () => {
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
  });
@@ -28,7 +28,10 @@ test("assistant query keys normalize scope and paging", () => {
28
28
  ]);
29
29
 
30
30
  assert.deepEqual(
31
- assistantConversationsListQueryKey({ targetSurfaceId: "admin", workspaceId: 9 }, { limit: 10, status: "ACTIVE" }),
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