@jini-ai/chat 0.5.0 → 0.5.2

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 (35) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/dist/core/index.d.ts +1 -0
  3. package/dist/core/index.js +1 -0
  4. package/dist/core/surface-expiry.d.ts +42 -0
  5. package/dist/core/surface-expiry.js +42 -0
  6. package/dist/react/chat-pane.d.ts +2 -2
  7. package/dist/react/chat-pane.js +1 -1
  8. package/dist/react/components/AttachmentPreviewModal.hooks.d.ts +19 -2
  9. package/dist/react/components/AttachmentPreviewModal.hooks.js +53 -38
  10. package/dist/react/components/McpUiSurfaceCard.d.ts +7 -1
  11. package/dist/react/components/McpUiSurfaceCard.js +23 -38
  12. package/dist/react/components/MessageList.d.ts +11 -0
  13. package/dist/react/components/MessageList.hooks.d.ts +19 -0
  14. package/dist/react/components/MessageList.hooks.js +76 -0
  15. package/dist/react/components/MessageList.js +3 -71
  16. package/dist/react/components/MessageList.rules.d.ts +25 -0
  17. package/dist/react/components/MessageList.rules.js +23 -0
  18. package/dist/react/components/mcp-ui-surface-state.d.ts +27 -0
  19. package/dist/react/components/mcp-ui-surface-state.js +33 -0
  20. package/dist/react/features/chat-pane/components/ChatPane.d.ts +1 -1
  21. package/dist/react/features/chat-pane/components/ChatPane.js +6 -5
  22. package/dist/react/features/chat-pane/create-typed-answer-poster.d.ts +54 -0
  23. package/dist/react/features/chat-pane/create-typed-answer-poster.js +46 -0
  24. package/dist/react/features/chat-pane/hooks/useChatPane.hooks.d.ts +17 -1
  25. package/dist/react/features/chat-pane/hooks/useChatPane.hooks.js +120 -4
  26. package/dist/react/features/chat-pane/index.d.ts +2 -1
  27. package/dist/react/features/chat-pane/index.js +1 -0
  28. package/dist/react/features/chat-pane/rules.d.ts +56 -1
  29. package/dist/react/features/chat-pane/rules.js +71 -0
  30. package/dist/react/features/chat-pane/types.d.ts +34 -0
  31. package/dist/react/hooks/useSurfaceExpiry.d.ts +20 -0
  32. package/dist/react/hooks/useSurfaceExpiry.js +35 -0
  33. package/dist/react/index.d.ts +4 -2
  34. package/dist/react/index.js +2 -1
  35. package/package.json +8 -8
@@ -1,4 +1,5 @@
1
- import type { ByokRuntimeSummary, ChatPaneAgent, ChatPaneAgentSelection } from './types.js';
1
+ import type { ChatMessage } from '@jini-ai/chat';
2
+ import type { ByokRuntimeSummary, ChatPaneAgent, ChatPaneAgentSelection, TypedAnswerNotice } from './types.js';
2
3
  export declare function defaultChatPaneSelection({ agent }: {
3
4
  agent: ChatPaneAgent;
4
5
  }): ChatPaneAgentSelection;
@@ -71,6 +72,60 @@ export declare function describeChatPaneSendBlocker(blocker: ChatPaneSendBlocker
71
72
  export declare function isChatPaneQueueableBlocker({ blocker }: {
72
73
  blocker: ChatPaneSendBlocker | null;
73
74
  }): boolean;
75
+ /**
76
+ * Whether the run in flight is holding a question open for the human: the newest message is the
77
+ * assistant's, and it carries an interactive surface (`kind: 'ext'`, e.g. an MCP-UI card) that
78
+ * arrived inside a still-open call to the host's question tool (`toolName`). That is the one moment
79
+ * text typed into the composer is an ANSWER rather than a next turn — the tool is parked waiting on
80
+ * it, and queueing the text behind the run would only deliver it after the question had expired, as
81
+ * a new paid run.
82
+ *
83
+ * Only the question tool counts. Other tools park on cards too — a delete confirm, an approval —
84
+ * but they take no typed answer: the server routes typed text only to the question tool, so treating
85
+ * those as waiting would refuse the text with "no longer waiting" and drop it instead of queueing.
86
+ * A call is the question tool when ANY `tool_use` for its id names it, since a vendor's wrapper row
87
+ * (`execute_delegated_tool`) and the daemon's canonical row share the id and may arrive in either
88
+ * order.
89
+ *
90
+ * A surface is attributed to the newest call still open when it arrived — the same rule
91
+ * `useExtEventGroups` uses to give a card its `call` — so an older call returning does not settle
92
+ * it. Once its call returns (answered, expired, abandoned), typing is a next turn again.
93
+ *
94
+ * @complexity O(e·c): e events in the newest message, c calls open at once (one or two in practice).
95
+ */
96
+ export declare function isAwaitingTypedAnswer({ messages, toolName }: {
97
+ messages: readonly ChatMessage[];
98
+ toolName: string;
99
+ }): boolean;
100
+ /**
101
+ * The tool-use id of the question {@link isAwaitingTypedAnswer} sees waiting, or `null` — the newest
102
+ * one when several are open. The id lets the pane tell one question from the next: a draft typed
103
+ * for a question stays tied to THAT question after it closes (see `useChatPane`'s held answer).
104
+ *
105
+ * @complexity O(e·c), as {@link isAwaitingTypedAnswer}.
106
+ */
107
+ export declare function findAwaitedTypedAnswerId({ messages, toolName }: {
108
+ messages: readonly ChatMessage[];
109
+ toolName: string;
110
+ }): string | null;
111
+ /**
112
+ * Whether a composer send is an answer to a waiting question rather than a next turn: a run is
113
+ * streaming ({@link isChatPaneQueueableBlocker}), the turn has no attachments (a typed answer
114
+ * carries text only), and that run is holding the `toolName` question open
115
+ * ({@link isAwaitingTypedAnswer}).
116
+ *
117
+ * @complexity O(e·c), from {@link isAwaitingTypedAnswer}.
118
+ */
119
+ export declare function isTypedAnswerTurn({ blocker, attachmentCount, messages, toolName }: {
120
+ blocker: ChatPaneSendBlocker | null;
121
+ attachmentCount: number;
122
+ messages: readonly ChatMessage[];
123
+ toolName: string;
124
+ }): boolean;
125
+ /** The English copy (and i18n key) for why a typed answer was not sent. */
126
+ export declare function describeTypedAnswerNotice({ notice }: {
127
+ notice: TypedAnswerNotice;
128
+ }): string;
74
129
  export declare function orderChatPaneAgents({ agents }: {
75
130
  agents: readonly ChatPaneAgent[];
76
131
  }): ChatPaneAgent[];
@@ -105,6 +105,77 @@ export function describeChatPaneSendBlocker(blocker) {
105
105
  export function isChatPaneQueueableBlocker({ blocker }) {
106
106
  return blocker === 'streaming';
107
107
  }
108
+ /**
109
+ * Whether the run in flight is holding a question open for the human: the newest message is the
110
+ * assistant's, and it carries an interactive surface (`kind: 'ext'`, e.g. an MCP-UI card) that
111
+ * arrived inside a still-open call to the host's question tool (`toolName`). That is the one moment
112
+ * text typed into the composer is an ANSWER rather than a next turn — the tool is parked waiting on
113
+ * it, and queueing the text behind the run would only deliver it after the question had expired, as
114
+ * a new paid run.
115
+ *
116
+ * Only the question tool counts. Other tools park on cards too — a delete confirm, an approval —
117
+ * but they take no typed answer: the server routes typed text only to the question tool, so treating
118
+ * those as waiting would refuse the text with "no longer waiting" and drop it instead of queueing.
119
+ * A call is the question tool when ANY `tool_use` for its id names it, since a vendor's wrapper row
120
+ * (`execute_delegated_tool`) and the daemon's canonical row share the id and may arrive in either
121
+ * order.
122
+ *
123
+ * A surface is attributed to the newest call still open when it arrived — the same rule
124
+ * `useExtEventGroups` uses to give a card its `call` — so an older call returning does not settle
125
+ * it. Once its call returns (answered, expired, abandoned), typing is a next turn again.
126
+ *
127
+ * @complexity O(e·c): e events in the newest message, c calls open at once (one or two in practice).
128
+ */
129
+ export function isAwaitingTypedAnswer({ messages, toolName }) {
130
+ return findAwaitedTypedAnswerId({ messages, toolName }) !== null;
131
+ }
132
+ /**
133
+ * The tool-use id of the question {@link isAwaitingTypedAnswer} sees waiting, or `null` — the newest
134
+ * one when several are open. The id lets the pane tell one question from the next: a draft typed
135
+ * for a question stays tied to THAT question after it closes (see `useChatPane`'s held answer).
136
+ *
137
+ * @complexity O(e·c), as {@link isAwaitingTypedAnswer}.
138
+ */
139
+ export function findAwaitedTypedAnswerId({ messages, toolName }) {
140
+ const newest = messages.at(-1);
141
+ if (newest?.role !== 'assistant')
142
+ return null;
143
+ // Open call id -> whether it is the question tool. Insertion-ordered, so the last entry is the
144
+ // newest call still open; a repeat id keeps its slot and only ORs in its name.
145
+ const openCalls = new Map();
146
+ const awaited = new Set();
147
+ for (const event of newest.events ?? []) {
148
+ if (event.kind === 'tool_use')
149
+ openCalls.set(event.id, openCalls.get(event.id) === true || event.name === toolName);
150
+ if (event.kind === 'tool_result') {
151
+ openCalls.delete(event.toolUseId);
152
+ awaited.delete(event.toolUseId);
153
+ }
154
+ const owner = event.kind === 'ext' ? [...openCalls].at(-1) : undefined;
155
+ if (owner?.[1] === true)
156
+ awaited.add(owner[0]);
157
+ }
158
+ return [...awaited].at(-1) ?? null;
159
+ }
160
+ /**
161
+ * Whether a composer send is an answer to a waiting question rather than a next turn: a run is
162
+ * streaming ({@link isChatPaneQueueableBlocker}), the turn has no attachments (a typed answer
163
+ * carries text only), and that run is holding the `toolName` question open
164
+ * ({@link isAwaitingTypedAnswer}).
165
+ *
166
+ * @complexity O(e·c), from {@link isAwaitingTypedAnswer}.
167
+ */
168
+ export function isTypedAnswerTurn({ blocker, attachmentCount, messages, toolName }) {
169
+ return isChatPaneQueueableBlocker({ blocker }) && attachmentCount === 0 && isAwaitingTypedAnswer({ messages, toolName });
170
+ }
171
+ const TYPED_ANSWER_NOTICES = {
172
+ 'not-pending': 'That question is no longer waiting for an answer, so your message was not sent.',
173
+ failed: 'Your answer could not be delivered. Try sending it again.',
174
+ };
175
+ /** The English copy (and i18n key) for why a typed answer was not sent. */
176
+ export function describeTypedAnswerNotice({ notice }) {
177
+ return TYPED_ANSWER_NOTICES[notice];
178
+ }
108
179
  export function orderChatPaneAgents({ agents }) {
109
180
  return [...agents].sort((left, right) => {
110
181
  const availability = Number(left.available === false) - Number(right.available === false);
@@ -120,6 +120,28 @@ export interface ChatPaneComposerHandle {
120
120
  */
121
121
  insertText: (text: string) => void;
122
122
  }
123
+ /**
124
+ * What happened to text typed while the running agent waits on a question (see
125
+ * {@link ChatPaneProps.deliverTypedAnswer}): `'delivered'` — the question took it as its answer;
126
+ * `'not-pending'` — nothing is waiting any more (already answered, expired, or never open);
127
+ * `'failed'` — the host could not tell (network error, unexpected status).
128
+ */
129
+ export type TypedAnswerDelivery = 'delivered' | 'not-pending' | 'failed';
130
+ /** Why the pane did not send a typed answer — shown to the human until the next send or reset. */
131
+ export type TypedAnswerNotice = Exclude<TypedAnswerDelivery, 'delivered'>;
132
+ /**
133
+ * Delivers text typed into the composer to the question the running agent is waiting on.
134
+ *
135
+ * Carries `toolName`, the host's question tool id, so the pane routes typed text here only while a
136
+ * card raised by THAT tool is open — any other pending card (a confirm, an approval) still queues the
137
+ * text behind the run. One value, so the tool the pane waits on and the tool the answer is posted to
138
+ * cannot drift apart; `createTypedAnswerPoster` sets it.
139
+ */
140
+ export type DeliverTypedAnswer = ((input: {
141
+ text: string;
142
+ }) => Promise<TypedAnswerDelivery>) & {
143
+ readonly toolName: string;
144
+ };
123
145
  export interface ChatPaneProps {
124
146
  transport: ChatTransport;
125
147
  agents?: readonly ChatPaneAgent[];
@@ -170,6 +192,18 @@ export interface ChatPaneProps {
170
192
  * before the pane exists has nothing to call.
171
193
  */
172
194
  composerHandle?: RefObject<ChatPaneComposerHandle | null>;
195
+ /**
196
+ * Called instead of queueing when the human types while the running agent is holding a question
197
+ * open in the transcript (an interactive surface whose call to `deliverTypedAnswer.toolName` has
198
+ * not returned — `isAwaitingTypedAnswer`) and the turn carries no attachments. `'delivered'` clears the draft
199
+ * (only if unchanged since it went out); any other outcome, or a throw, leaves the draft in place with a
200
+ * notice and NEVER queues it — a queued answer would go out after the run ends as a new, paid run
201
+ * answering nothing. A draft typed while the question waited stays held after it closes, until the
202
+ * human clears it or picks "Send as a new message" (`useChatPane`'s `sendAsNewMessage`).
203
+ *
204
+ * Omit it and typing while a run streams queues exactly as before.
205
+ */
206
+ deliverTypedAnswer?: DeliverTypedAnswer;
173
207
  placeholder?: string;
174
208
  /**
175
209
  * Rotating composer suggestions, cycled every few seconds in place of one fixed `placeholder` —
@@ -0,0 +1,20 @@
1
+ import { type SurfaceExpiry } from '../../core/index.js';
2
+ /** The clock port: the current time, and a repeating ticker that returns its own stop function. */
3
+ export interface SurfaceExpiryClock {
4
+ nowMs(): number;
5
+ every(intervalMs: number, tick: () => void): () => void;
6
+ }
7
+ /** The wall clock and `setInterval`; the default when a caller injects none. */
8
+ export declare const SYSTEM_SURFACE_EXPIRY_CLOCK: SurfaceExpiryClock;
9
+ /**
10
+ * @param input.expiresAtMs - The card's deadline (epoch ms), or `undefined` when it has none.
11
+ * @param options.clock - Time source and ticker. Defaults to {@link SYSTEM_SURFACE_EXPIRY_CLOCK}.
12
+ * @returns The deadline's state at the last tick, or `undefined` when there is no deadline.
13
+ * @complexity O(1) per render; one ticker while live.
14
+ */
15
+ export declare function useSurfaceExpiry({ expiresAtMs }: {
16
+ expiresAtMs: number | undefined;
17
+ }, { clock }?: {
18
+ clock?: SurfaceExpiryClock;
19
+ }): SurfaceExpiry | undefined;
20
+ //# sourceMappingURL=useSurfaceExpiry.d.ts.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @module useSurfaceExpiry
3
+ *
4
+ * The live countdown for a pending MCP-UI card: `describeSurfaceExpiry` re-read once a second on an
5
+ * injected clock. Ticks only while the card is answerable and has a deadline; an expired card or one
6
+ * without a deadline runs no timer.
7
+ */
8
+ import { useEffect, useState } from 'react';
9
+ import { describeSurfaceExpiry, SURFACE_EXPIRY_TICK_MS } from '../../core/index.js';
10
+ /** The wall clock and `setInterval`; the default when a caller injects none. */
11
+ export const SYSTEM_SURFACE_EXPIRY_CLOCK = {
12
+ nowMs: () => Date.now(),
13
+ every: (intervalMs, tick) => {
14
+ const timer = setInterval(tick, intervalMs);
15
+ return () => clearInterval(timer);
16
+ },
17
+ };
18
+ /**
19
+ * @param input.expiresAtMs - The card's deadline (epoch ms), or `undefined` when it has none.
20
+ * @param options.clock - Time source and ticker. Defaults to {@link SYSTEM_SURFACE_EXPIRY_CLOCK}.
21
+ * @returns The deadline's state at the last tick, or `undefined` when there is no deadline.
22
+ * @complexity O(1) per render; one ticker while live.
23
+ */
24
+ export function useSurfaceExpiry({ expiresAtMs }, { clock = SYSTEM_SURFACE_EXPIRY_CLOCK } = {}) {
25
+ const [nowMs, setNowMs] = useState(() => clock.nowMs());
26
+ const expiry = expiresAtMs === undefined ? undefined : describeSurfaceExpiry({ expiresAtMs, nowMs });
27
+ const live = expiry?.expired === false;
28
+ useEffect(() => {
29
+ if (!live)
30
+ return undefined;
31
+ return clock.every(SURFACE_EXPIRY_TICK_MS, () => setNowMs(clock.nowMs()));
32
+ }, [live, clock]);
33
+ return expiry;
34
+ }
35
+ //# sourceMappingURL=useSurfaceExpiry.js.map
@@ -36,8 +36,8 @@ export type { ExtEventRenderProps, ExtEventRenderer, ExtEventRendererOptions, Ex
36
36
  * This alias has no removal date scheduled yet; see `chat-pane.ts` for the canonical surface and
37
37
  * the module doc there for why the split exists.
38
38
  */
39
- export { AgentRuntimePicker, CHAT_PANE_AGENT_TOOLS, ChatPane, createDaemonAttachmentUploader, createMcpUiToolCaller, defaultChatPaneSelection, orderChatPaneAgents, resolveChatPaneSelection, useChatPane, useChatPaneAgentControl, useChatPaneRuntimeInventory, useChatPaneWorkingDirectory, } from './chat-pane.js';
40
- export type { AgentRuntimePickerProps, ByokRuntimeSummary, ChatPaneActivity, ChatPaneAgent, ChatPaneAgentBridgeAccess, ChatPaneAgentControlOptions, ChatPaneAgentOption, ChatPaneAgentSelection, ChatPaneAgentToolAction, ChatPaneAgentToolDef, ChatPaneAgentToolInputSchema, ChatPaneAgentToolRisk, ChatPaneAttachmentUploadOptions, ChatPaneComposerHandle, ChatPaneProps, ChatPaneRunContext, ChatPaneRunContextInput, ChatPaneRuntimeAccess, ChatPaneVariant, ChatPaneWorkingDirectoryAccess, CreateDaemonAttachmentUploaderOptions, CreateMcpUiToolCallerOptions, McpUiToolCallRequest, RuntimePickerPlacement, UseChatPaneAgentControlOptions, UseChatPaneOptions, UseChatPaneResult, UseChatPaneRuntimeInventoryOptions, UseChatPaneRuntimeInventoryResult, UseChatPaneWorkingDirectoryOptions, UseChatPaneWorkingDirectoryResult, } from './chat-pane.js';
39
+ export { AgentRuntimePicker, CHAT_PANE_AGENT_TOOLS, ChatPane, createDaemonAttachmentUploader, createMcpUiToolCaller, createTypedAnswerPoster, defaultChatPaneSelection, orderChatPaneAgents, resolveChatPaneSelection, useChatPane, useChatPaneAgentControl, useChatPaneRuntimeInventory, useChatPaneWorkingDirectory, } from './chat-pane.js';
40
+ export type { AgentRuntimePickerProps, ByokRuntimeSummary, ChatPaneActivity, ChatPaneAgent, ChatPaneAgentBridgeAccess, ChatPaneAgentControlOptions, ChatPaneAgentOption, ChatPaneAgentSelection, ChatPaneAgentToolAction, ChatPaneAgentToolDef, ChatPaneAgentToolInputSchema, ChatPaneAgentToolRisk, ChatPaneAttachmentUploadOptions, ChatPaneComposerHandle, ChatPaneProps, ChatPaneRunContext, ChatPaneRunContextInput, ChatPaneRuntimeAccess, ChatPaneVariant, ChatPaneWorkingDirectoryAccess, CreateDaemonAttachmentUploaderOptions, CreateMcpUiToolCallerOptions, CreateTypedAnswerPosterOptions, DeliverTypedAnswer, McpUiToolCallRequest, RuntimePickerPlacement, TypedAnswerDelivery, TypedAnswerNotice, UseChatPaneAgentControlOptions, UseChatPaneOptions, UseChatPaneResult, UseChatPaneRuntimeInventoryOptions, UseChatPaneRuntimeInventoryResult, UseChatPaneWorkingDirectoryOptions, UseChatPaneWorkingDirectoryResult, } from './chat-pane.js';
41
41
  export { useRunStream, } from './hooks/useRunStream.js';
42
42
  export type { RunStreamState, RunStreamStatus, StartRunOptions, UseRunStreamResult, } from './hooks/useRunStream.js';
43
43
  export { useConversation, } from './hooks/useConversation.js';
@@ -48,6 +48,8 @@ export { useToolTimeline, } from './hooks/useToolTimeline.js';
48
48
  export type { ToolTimelineRow, UseToolTimelineOptions, UseToolTimelineResult, } from './hooks/useToolTimeline.js';
49
49
  export { useExtEventGroups, } from './hooks/useExtEventGroups.js';
50
50
  export type { ExtEventGroup, } from './hooks/useExtEventGroups.js';
51
+ export { SYSTEM_SURFACE_EXPIRY_CLOCK, useSurfaceExpiry, } from './hooks/useSurfaceExpiry.js';
52
+ export type { SurfaceExpiryClock, } from './hooks/useSurfaceExpiry.js';
51
53
  export { usePinnedTodos, } from './hooks/usePinnedTodos.js';
52
54
  export type { UsePinnedTodosResult, } from './hooks/usePinnedTodos.js';
53
55
  export { parseSubmittedAnswers, useQuestionForms, } from './hooks/useQuestionForms.js';
@@ -26,12 +26,13 @@ export { clearExtEventRenderers, extEventSlot, getExtEventRenderer, registerExtE
26
26
  * This alias has no removal date scheduled yet; see `chat-pane.ts` for the canonical surface and
27
27
  * the module doc there for why the split exists.
28
28
  */
29
- export { AgentRuntimePicker, CHAT_PANE_AGENT_TOOLS, ChatPane, createDaemonAttachmentUploader, createMcpUiToolCaller, defaultChatPaneSelection, orderChatPaneAgents, resolveChatPaneSelection, useChatPane, useChatPaneAgentControl, useChatPaneRuntimeInventory, useChatPaneWorkingDirectory, } from './chat-pane.js';
29
+ export { AgentRuntimePicker, CHAT_PANE_AGENT_TOOLS, ChatPane, createDaemonAttachmentUploader, createMcpUiToolCaller, createTypedAnswerPoster, defaultChatPaneSelection, orderChatPaneAgents, resolveChatPaneSelection, useChatPane, useChatPaneAgentControl, useChatPaneRuntimeInventory, useChatPaneWorkingDirectory, } from './chat-pane.js';
30
30
  export { useRunStream, } from './hooks/useRunStream.js';
31
31
  export { useConversation, } from './hooks/useConversation.js';
32
32
  export { useComposer, } from './hooks/useComposer.js';
33
33
  export { useToolTimeline, } from './hooks/useToolTimeline.js';
34
34
  export { useExtEventGroups, } from './hooks/useExtEventGroups.js';
35
+ export { SYSTEM_SURFACE_EXPIRY_CLOCK, useSurfaceExpiry, } from './hooks/useSurfaceExpiry.js';
35
36
  export { usePinnedTodos, } from './hooks/usePinnedTodos.js';
36
37
  export { parseSubmittedAnswers, useQuestionForms, } from './hooks/useQuestionForms.js';
37
38
  export { useArtifactStream, } from './hooks/useArtifactStream.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/chat",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
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": {
@@ -145,15 +145,15 @@
145
145
  "registry": "https://registry.npmjs.org"
146
146
  },
147
147
  "dependencies": {
148
- "@jini-ai/protocol": "0.4.0",
149
- "@jini-ai/agentic": "0.4.0",
150
- "@jini-ai/ui": "0.4.0",
151
- "@jini-ai/core": "0.4.0"
148
+ "@jini-ai/agentic": "^0.4.1",
149
+ "@jini-ai/ui": "^0.4.3",
150
+ "@jini-ai/core": "^0.4.1",
151
+ "@jini-ai/protocol": "^0.4.0"
152
152
  },
153
153
  "peerDependencies": {
154
154
  "react": "^18.3.0 || ^19.0.0",
155
155
  "react-dom": "^18.3.0 || ^19.0.0",
156
- "@jini-ai/db": "^0.2.0",
156
+ "@jini-ai/db": "^0.2.0 || ^0.3.0",
157
157
  "kysely": "^0.29.6",
158
158
  "better-sqlite3": "^13.0.0",
159
159
  "@electric-sql/pglite": "0.5.8",
@@ -238,8 +238,8 @@
238
238
  "@electric-sql/pglite": "0.5.8",
239
239
  "pg": "8.23.0",
240
240
  "@ag-ui/core": "0.0.58",
241
- "@jini-ai/db": "0.2.0",
242
- "@jini-ai/agent-runtime": "0.4.0"
241
+ "@jini-ai/agent-runtime": "0.4.0",
242
+ "@jini-ai/db": "0.3.0"
243
243
  },
244
244
  "typesVersions": {
245
245
  "*": {