@jini-ai/chat 0.6.15-rc.1 → 0.6.15

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 (93) hide show
  1. package/dist/core/accepted-input.js +29 -14
  2. package/dist/core/ag-ui/entry.js +3 -1
  3. package/dist/core/agent-plugin-chat-state.js +3 -1
  4. package/dist/core/assistant-client/ag-ui-transport.js +1 -1
  5. package/dist/core/assistant-client/attachment-liveness.js +1 -1
  6. package/dist/core/assistant-client/durable-run-subscription.js +2 -1
  7. package/dist/core/assistant-client/transport.js +13 -7
  8. package/dist/core/assistant-content.js +2 -1
  9. package/dist/core/composer-history.js +2 -1
  10. package/dist/core/durable-projection.js +2 -1
  11. package/dist/core/durable-runs/continuation.js +2 -1
  12. package/dist/core/messages.d.ts +5 -1
  13. package/dist/core/partial-json.js +18 -9
  14. package/dist/core/persistence/title.d.ts +1 -1
  15. package/dist/core/persistence/title.js +25 -7
  16. package/dist/core/question-answer.js +9 -4
  17. package/dist/core/question-form/normalize.js +1 -1
  18. package/dist/core/question-form/scan.js +25 -15
  19. package/dist/core/question-form/secret-answers.js +2 -1
  20. package/dist/core/run-activity.js +8 -4
  21. package/dist/core/run-events/entry.js +6 -2
  22. package/dist/core/transcript.js +13 -6
  23. package/dist/core/turn-usage.js +12 -4
  24. package/dist/core/user-text-redaction.d.ts +2 -5
  25. package/dist/core/user-text-redaction.js +3 -3
  26. package/dist/core/util/manifest.js +13 -11
  27. package/dist/core/util/markdown-context.d.ts +14 -0
  28. package/dist/core/util/markdown-context.js +42 -4
  29. package/dist/core/util/markup-attributes.js +1 -1
  30. package/dist/core/util/parser.js +7 -7
  31. package/dist/core/util/pointer.js +22 -6
  32. package/dist/core/util/recover.js +5 -8
  33. package/dist/core/util/strip.js +12 -15
  34. package/dist/core/util/validate.js +30 -18
  35. package/dist/embed-widget/browser/lazy-loader.js +16 -12
  36. package/dist/embed-widget/react/dialog.hooks.js +2 -2
  37. package/dist/embed-widget/react/embed.js +1 -1
  38. package/dist/embed-widget/react/header.hooks.js +1 -1
  39. package/dist/embed-widget/transports/fetch-sse.js +2 -1
  40. package/dist/embed-widget/vanilla/index.js +19 -12
  41. package/dist/embed-widget/vanilla/state.js +4 -2
  42. package/dist/react/components/AttachmentPreviewModal.hooks.js +2 -1
  43. package/dist/react/components/ChatSettingsDialog.js +18 -9
  44. package/dist/react/components/Composer.js +5 -4
  45. package/dist/react/components/ConversationList.js +5 -4
  46. package/dist/react/components/Markdown.js +29 -26
  47. package/dist/react/components/McpUiSurfaceCard.js +2 -1
  48. package/dist/react/components/MessageList.hooks.js +3 -2
  49. package/dist/react/components/MessageRow.js +23 -7
  50. package/dist/react/components/MessageRow.usage.js +7 -2
  51. package/dist/react/components/QuestionForm.js +4 -5
  52. package/dist/react/components/SentAttachment.js +4 -1
  53. package/dist/react/components/TodoCard.js +9 -1
  54. package/dist/react/components/ToolCard.js +8 -7
  55. package/dist/react/components/composer-discovery.js +8 -8
  56. package/dist/react/features/chat-pane/components/AgentPluginUsage.js +1 -2
  57. package/dist/react/features/chat-pane/components/AgentRuntimePicker.d.ts +1 -1
  58. package/dist/react/features/chat-pane/components/AgentRuntimePicker.js +15 -5
  59. package/dist/react/features/chat-pane/components/ChatPane.js +5 -8
  60. package/dist/react/features/chat-pane/components/RuntimeDropUp.js +1 -1
  61. package/dist/react/features/chat-pane/create-daemon-attachment-uploader.js +1 -1
  62. package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.js +2 -2
  63. package/dist/react/features/chat-pane/hooks/useChatPane.hooks.js +12 -7
  64. package/dist/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.js +18 -22
  65. package/dist/react/features/chat-pane/hooks/useChatPaneControlsHeight.hooks.js +1 -1
  66. package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.js +2 -2
  67. package/dist/react/features/chat-pane/hooks/useChatPaneWorkingDirectory.hooks.js +2 -2
  68. package/dist/react/features/chat-pane/hooks/useRuntimeDropUp.hooks.js +2 -2
  69. package/dist/react/features/chat-pane/model-options.js +4 -2
  70. package/dist/react/features/chat-pane/styles.d.ts +1 -1
  71. package/dist/react/features/chat-pane/styles.js +26 -3
  72. package/dist/react/features/chat-pane/types.d.ts +8 -0
  73. package/dist/react/hooks/assistant-chats.js +22 -8
  74. package/dist/react/hooks/useArtifactStream.js +2 -1
  75. package/dist/react/hooks/useComposer.js +2 -2
  76. package/dist/react/hooks/useComposerHistoryKeys.hooks.js +2 -2
  77. package/dist/react/hooks/useConversation.js +9 -4
  78. package/dist/react/hooks/useExtEventGroups.js +4 -2
  79. package/dist/react/hooks/useLatestOperation.js +2 -1
  80. package/dist/react/hooks/useQuestionForms.js +32 -22
  81. package/dist/react/hooks/useRunStream.js +4 -2
  82. package/dist/react/message-blocks.js +4 -2
  83. package/dist/react/styles/reference.css +9 -0
  84. package/dist/react/tool-call-display.js +1 -2
  85. package/dist/server/durable-runs/recover.js +13 -5
  86. package/dist/server/run-finalizer/entry.js +1 -0
  87. package/dist/store/runtime/chat-history-store.js +9 -3
  88. package/dist/store/runtime/durable-run-store.js +34 -24
  89. package/dist/store/runtime/run-ledger.js +7 -4
  90. package/dist/store/sql/boundary.js +3 -1
  91. package/dist/store/sql/cursor.js +8 -3
  92. package/dist/store/sql/store.js +36 -28
  93. package/package.json +15 -15
@@ -1,3 +1,5 @@
1
+ const MESSAGE_POSITION = 'm.position';
2
+ const CONVERSATION_UPDATED_AT = 'c.updated_at';
1
3
  /** One SQL query body upstreamed from the existing host adapter; no resource/schema ownership. */
2
4
  // Legacy project/conversation CRUD trusts access to a local database file; this owner-bound store
3
5
  // serves shared databases instead. Choose by trust model: borrowing a handle must not grant access
@@ -96,7 +98,9 @@ function runFields(row) {
96
98
  }
97
99
  /** Reject an unbounded or malformed history read before any query runs. */
98
100
  function assertHistoryReadBounds({ limit, fromPosition }) {
99
- if (!Number.isInteger(limit) || limit < 1 || limit > 100 || (fromPosition !== undefined && (!Number.isSafeInteger(fromPosition) || fromPosition < 0))) {
101
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100)
102
+ throw new ChatStoreError({ code: 'invalid-input' });
103
+ if (fromPosition !== undefined && (!Number.isSafeInteger(fromPosition) || fromPosition < 0)) {
100
104
  throw new ChatStoreError({ code: 'invalid-input' });
101
105
  }
102
106
  }
@@ -139,7 +143,7 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
139
143
  "c.title",
140
144
  "c.title_source",
141
145
  "c.created_at",
142
- "c.updated_at",
146
+ CONVERSATION_UPDATED_AT,
143
147
  "c.expires_at",
144
148
  eb
145
149
  .selectFrom("ai_chat_messages as m")
@@ -182,7 +186,7 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
182
186
  }
183
187
  /** Read owned messages in persisted position order; foreign IDs produce no rows. */
184
188
  async function messages({ conversationId }, _optional = {}) {
185
- const rows = await run(db => ownedMessages(db, conversationId).orderBy('m.position').execute());
189
+ const rows = await run(db => ownedMessages(db, conversationId).orderBy(MESSAGE_POSITION).execute());
186
190
  return rows.map(toMessage);
187
191
  }
188
192
  /** Writes and projects one message inside the borrowed transaction; null for absent/foreign IDs. */
@@ -226,18 +230,7 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
226
230
  started_at: m.startedAt ?? null,
227
231
  ended_at: m.endedAt ?? null,
228
232
  })
229
- .onConflict((oc) => oc
230
- .column("id")
231
- .doUpdateSet((eb) => ({
232
- content: eb.ref("excluded.content"),
233
- events_json: eb.ref("excluded.events_json"),
234
- attachments_json: eb.ref("excluded.attachments_json"),
235
- run_id: eb.ref("excluded.run_id"),
236
- run_status: eb.ref("excluded.run_status"),
237
- started_at: eb.ref("excluded.started_at"),
238
- ended_at: eb.ref("excluded.ended_at"),
239
- }))
240
- .where((eb) => eb("ai_chat_messages.conversation_id", "=", eb.ref("excluded.conversation_id"))))
233
+ .onConflict(updateOwnedMessageConflict)
241
234
  .execute());
242
235
  // A new message is activity: the list orders by `updated_at`.
243
236
  await run((db) => db.updateTable("ai_chats").set({ updated_at: clock.nowMs() }).where("id", "=", conversationId).execute());
@@ -260,7 +253,9 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
260
253
  * @complexity The database scans owned content for search; only limit rows cross the port.
261
254
  */
262
255
  async list(_required, { query, limit = 20 } = {}) {
263
- if (!Number.isInteger(limit) || limit < 1 || limit > 50 || (query !== undefined && (typeof query !== 'string' || query.length > 200))) {
256
+ if (!Number.isInteger(limit) || limit < 1 || limit > 50)
257
+ throw new ChatStoreError({ code: 'invalid-input' });
258
+ if (query !== undefined && (typeof query !== 'string' || query.length > 200)) {
264
259
  throw new ChatStoreError({ code: 'invalid-input' });
265
260
  }
266
261
  const rows = await run(db => {
@@ -277,7 +272,7 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
277
272
  .where(sql `lower(found.content) like ${pattern} escape '!'`)),
278
273
  ]));
279
274
  }
280
- return statement.orderBy('c.updated_at', 'desc').orderBy(ordinalId(kernel.dialect, 'c.id')).limit(limit).execute();
275
+ return statement.orderBy(CONVERSATION_UPDATED_AT, 'desc').orderBy(ordinalId(kernel.dialect, 'c.id')).limit(limit).execute();
281
276
  });
282
277
  return rows.map(row => ({ ...toConversation(row), firstUserLine: row.first_user_line ?? '' }));
283
278
  },
@@ -286,12 +281,12 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
286
281
  assertHistoryReadBounds({ limit, fromPosition });
287
282
  const rows = await run(db => {
288
283
  let statement = ownedMessages(db, chatId).clearSelect().select([
289
- 'm.id', 'm.role', 'm.content', 'm.position', 'm.created_at',
284
+ 'm.id', 'm.role', 'm.content', MESSAGE_POSITION, 'm.created_at',
290
285
  ]);
291
286
  if (fromPosition !== undefined)
292
- statement = statement.where('m.position', '>=', fromPosition);
287
+ statement = statement.where(MESSAGE_POSITION, '>=', fromPosition);
293
288
  return statement.select(includeToolEvents ? sql `m.events_json`.as('events_json') : sql `null`.as('events_json'))
294
- .orderBy('m.position', fromPosition === undefined ? 'desc' : 'asc').limit(limit + 1).execute();
289
+ .orderBy(MESSAGE_POSITION, fromPosition === undefined ? 'desc' : 'asc').limit(limit + 1).execute();
295
290
  });
296
291
  const page = rows.slice(0, limit);
297
292
  if (fromPosition === undefined)
@@ -300,7 +295,7 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
300
295
  },
301
296
  },
302
297
  async list() {
303
- const rows = await run((db) => ownedConversations(db).orderBy("c.updated_at", "desc").execute());
298
+ const rows = await run((db) => ownedConversations(db).orderBy(CONVERSATION_UPDATED_AT, "desc").execute());
304
299
  return rows.map((row) => toConversation(row));
305
300
  },
306
301
  get,
@@ -387,10 +382,10 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
387
382
  let query = ownedConversations(db);
388
383
  if (anchor)
389
384
  query = query.where(eb => eb.or([
390
- eb('c.updated_at', '<', anchor[0]),
391
- eb.and([eb('c.updated_at', '=', anchor[0]), eb(id, '>', anchor[1])]),
385
+ eb(CONVERSATION_UPDATED_AT, '<', anchor[0]),
386
+ eb.and([eb(CONVERSATION_UPDATED_AT, '=', anchor[0]), eb(id, '>', anchor[1])]),
392
387
  ]));
393
- return query.orderBy('c.updated_at', 'desc').orderBy(id, 'asc').limit(limit + 1).execute();
388
+ return query.orderBy(CONVERSATION_UPDATED_AT, 'desc').orderBy(id, 'asc').limit(limit + 1).execute();
394
389
  });
395
390
  const items = rows.slice(0, limit).map(row => toConversation(row));
396
391
  const last = items.at(-1);
@@ -404,13 +399,13 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
404
399
  const id = ordinalId(kernel.dialect, 'm.id');
405
400
  // One join, at most limit+1 rows, including the ownership check; no parent pre-read.
406
401
  const rows = await run(db => {
407
- let query = ownedMessages(db, input.conversationId).select('m.position');
402
+ let query = ownedMessages(db, input.conversationId).select(MESSAGE_POSITION);
408
403
  if (anchor)
409
404
  query = query.where(eb => eb.or([
410
- eb('m.position', '>', anchor[0]),
411
- eb.and([eb('m.position', '=', anchor[0]), eb(id, '>', anchor[1])]),
405
+ eb(MESSAGE_POSITION, '>', anchor[0]),
406
+ eb.and([eb(MESSAGE_POSITION, '=', anchor[0]), eb(id, '>', anchor[1])]),
412
407
  ]));
413
- return query.orderBy('m.position', 'asc').orderBy(id, 'asc').limit(limit + 1).execute();
408
+ return query.orderBy(MESSAGE_POSITION, 'asc').orderBy(id, 'asc').limit(limit + 1).execute();
414
409
  });
415
410
  const page = rows.slice(0, limit), last = page.at(-1);
416
411
  return { items: page.map(toMessage), ...(rows.length > limit && last ? {
@@ -435,4 +430,17 @@ export function createSqlChatStore({ kernel, scope: inputScope }, { clock = crea
435
430
  pageMessages: (required, optional = {}) => atStoreBoundary({ operation: () => store.pageMessages(required, optional) }),
436
431
  };
437
432
  }
433
+ function updateOwnedMessageConflict(oc) {
434
+ return oc.column("id")
435
+ .doUpdateSet((eb) => ({
436
+ content: eb.ref("excluded.content"),
437
+ events_json: eb.ref("excluded.events_json"),
438
+ attachments_json: eb.ref("excluded.attachments_json"),
439
+ run_id: eb.ref("excluded.run_id"),
440
+ run_status: eb.ref("excluded.run_status"),
441
+ started_at: eb.ref("excluded.started_at"),
442
+ ended_at: eb.ref("excluded.ended_at"),
443
+ }))
444
+ .where((eb) => eb("ai_chat_messages.conversation_id", "=", eb.ref("excluded.conversation_id")));
445
+ }
438
446
  //# sourceMappingURL=store.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/chat",
3
- "version": "0.6.15-rc.1",
3
+ "version": "0.6.15",
4
4
  "description": "Jini's chat/artifact frontend, consolidated into one package with two subpaths: framework-free chat vocabulary and pure parsers in `/core`, headless hooks + presentational components + slots in `/react`. Import only the layer you need.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -196,12 +196,12 @@
196
196
  "registry": "https://registry.npmjs.org"
197
197
  },
198
198
  "dependencies": {
199
- "@jini-ai/core": "^0.6.15-rc.1"
199
+ "@jini-ai/core": "^0.6.15"
200
200
  },
201
201
  "peerDependencies": {
202
202
  "react": "^18.3.0 || ^19.0.0",
203
203
  "react-dom": "^18.3.0 || ^19.0.0",
204
- "@jini-ai/db": "^0.6.15-rc.1",
204
+ "@jini-ai/db": "^0.6.10",
205
205
  "kysely": "^0.29.6",
206
206
  "better-sqlite3": "^13.0.0",
207
207
  "@electric-sql/pglite": "0.5.8",
@@ -213,11 +213,11 @@
213
213
  "@radix-ui/react-radio-group": "^1.4.7",
214
214
  "@radix-ui/react-select": "^2.3.7",
215
215
  "@radix-ui/react-slot": "^1.3.3",
216
- "@jini-ai/agent-runtime": "^0.6.15-rc.1",
217
- "@jini-ai/agentic": "^0.6.15-rc.1",
218
- "@jini-ai/protocol": "^0.6.15-rc.1",
219
- "@jini-ai/ui": "^0.6.15-rc.1",
220
- "@jini-ai/diagnostics": "^0.6.15-rc.1"
216
+ "@jini-ai/agent-runtime": "^0.6.10",
217
+ "@jini-ai/agentic": "^0.6.10",
218
+ "@jini-ai/protocol": "^0.6.10",
219
+ "@jini-ai/ui": "^0.6.10",
220
+ "@jini-ai/diagnostics": "^0.6.10"
221
221
  },
222
222
  "peerDependenciesMeta": {
223
223
  "react": {
@@ -303,13 +303,13 @@
303
303
  "pg": "8.23.0",
304
304
  "@ag-ui/core": "0.0.58",
305
305
  "fast-check": "4.3.0",
306
- "@jini-ai/db": "0.6.15-rc.1",
307
- "@jini-ai/ui": "^0.6.15-rc.1",
308
- "@jini-ai/agentic": "^0.6.15-rc.1",
309
- "@jini-ai/diagnostics": "^0.6.15-rc.1",
310
- "@jini-ai/core": "^0.6.15-rc.1",
311
- "@jini-ai/protocol": "^0.6.15-rc.1",
312
- "@jini-ai/agent-runtime": "0.6.15-rc.1"
306
+ "@jini-ai/db": "0.6.15",
307
+ "@jini-ai/agent-runtime": "0.6.15",
308
+ "@jini-ai/protocol": "^0.6.15",
309
+ "@jini-ai/agentic": "^0.6.15",
310
+ "@jini-ai/core": "^0.6.15",
311
+ "@jini-ai/diagnostics": "^0.6.15",
312
+ "@jini-ai/ui": "^0.6.15"
313
313
  },
314
314
  "typesVersions": {
315
315
  "*": {