@aleph-alpha/chat-kit 1.11.1 → 1.12.0

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,4 +1,4 @@
1
- import type { ConversationTree } from '../types';
1
+ import type { ConversationTree, MessageMetadata, TreeMessage } from '../types';
2
2
  /**
3
3
  * Annotation attached to a Responses-API content part (citations, file
4
4
  * references, etc.). chat-kit does not render annotations itself; the shape
@@ -157,6 +157,21 @@ export interface ResponseAttachment {
157
157
  fileName: string;
158
158
  searchStoreId: string;
159
159
  }
160
+ /**
161
+ * Render-side attachment shape produced by `responsesToTree`. Stored under
162
+ * `metadata.attachments` on the user `TreeMessage` (chat-kit's `BaseMessage`
163
+ * /`TreeMessage` carry `metadata` as an opaque `Record<string, unknown>`).
164
+ *
165
+ * The shape is intentionally minimal — a human-readable `name` plus the
166
+ * optional ids needed to resolve a public URL for the file. Consumers
167
+ * using a different attachment shape can either skip this adapter or
168
+ * project this onto their own type at the read site.
169
+ */
170
+ export interface ResponseMessageAttachment {
171
+ name: string;
172
+ fileId?: string;
173
+ searchStoreId?: string;
174
+ }
160
175
  /**
161
176
  * One stored response from the OpenAI-style Responses API, as returned by
162
177
  * `GET /conversations/:id/responses`. `previous_response_id` chains
@@ -174,7 +189,7 @@ export interface StoredResponse {
174
189
  output: ResponseOutput[];
175
190
  request_input: Record<string, unknown>[];
176
191
  metadata?: Record<string, unknown> & {
177
- attachments?: ResponseAttachment[];
192
+ attachments?: string;
178
193
  };
179
194
  conversation?: {
180
195
  id: string;
@@ -192,6 +207,38 @@ export interface ResponseList {
192
207
  object: 'list';
193
208
  data: StoredResponse[];
194
209
  }
210
+ /**
211
+ * Per-node metadata produced by `responsesToTree`. The adapter is the
212
+ * single point that knows about the Responses-API wire format, so it
213
+ * stamps the originating `responseId` onto every node it emits. Anything
214
+ * downstream that reads it (typically a host app linking a tree message
215
+ * back to its server-side response) does so via this narrower metadata
216
+ * shape — chat-kit core stays oblivious to the field and treats it as
217
+ * opaque metadata.
218
+ */
219
+ export type ResponseTreeMessageMetadata = MessageMetadata & {
220
+ responseId: string;
221
+ attachments?: ResponseMessageAttachment[];
222
+ };
223
+ /**
224
+ * Tree node emitted by `responsesToTree`. Structurally a `TreeMessage`,
225
+ * but with `metadata` narrowed to {@link ResponseTreeMessageMetadata} and
226
+ * promoted from optional to required: every node carries at least the
227
+ * originating `responseId`. Assignable to `TreeMessage` so the resulting
228
+ * tree can be passed directly to `useMessageHandler().setTree(...)`.
229
+ */
230
+ export type ResponseTreeMessage = Omit<TreeMessage, 'metadata'> & {
231
+ metadata: ResponseTreeMessageMetadata;
232
+ };
233
+ /**
234
+ * `ConversationTree` returned by `responsesToTree`. Same shape as the
235
+ * core `ConversationTree`, with every node typed as a
236
+ * {@link ResponseTreeMessage} so callers can read `metadata.responseId`
237
+ * without re-narrowing. Structurally assignable to `ConversationTree`.
238
+ */
239
+ export interface ResponseConversationTree extends ConversationTree {
240
+ nodes: Record<string, ResponseTreeMessage>;
241
+ }
195
242
  /**
196
243
  * Convert an OpenAI Responses API list (already ordered by `created_at`
197
244
  * ascending) into a chat-kit `ConversationTree`.
@@ -202,8 +249,10 @@ export interface ResponseList {
202
249
  * last message immediately. Sibling responses (same `previous_response_id`)
203
250
  * surface as branches; the latest one wins as the active branch.
204
251
  *
205
- * Pair with `useMessageHandler().setTree(responsesToTree(responses))` when
206
- * you want to hydrate a handler.
252
+ * Every emitted node carries `metadata.responseId` pointing back to the
253
+ * originating `StoredResponse.id` (see {@link ResponseTreeMessage}). The
254
+ * return type is assignable to `ConversationTree`, so you can pipe it
255
+ * straight into `useMessageHandler().setTree(...)`.
207
256
  */
208
- export declare function responsesToTree(responses: StoredResponse[]): ConversationTree;
257
+ export declare function responsesToTree(responses: StoredResponse[]): ResponseConversationTree;
209
258
  //# sourceMappingURL=responses-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"responses-api.d.ts","sourceRoot":"","sources":["../../src/adapters/responses-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"responses-api.d.ts","sourceRoot":"","sources":["../../src/adapters/responses-api.ts"],"names":[],"mappings":"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"}
@@ -83,21 +83,53 @@ function extractInputText(rawContent) {
83
83
  }
84
84
  return text.trim();
85
85
  }
86
+ function parseResponseAttachments(resp) {
87
+ const raw = resp.metadata?.attachments;
88
+ if (!raw) return null;
89
+ let attachments;
90
+ try {
91
+ attachments = JSON.parse(raw);
92
+ } catch {
93
+ console.warn(
94
+ "[chat-kit] Failed to parse metadata.attachments as JSON; skipping.",
95
+ raw
96
+ );
97
+ return null;
98
+ }
99
+ if (!Array.isArray(attachments) || attachments.length === 0) {
100
+ return null;
101
+ }
102
+ return attachments;
103
+ }
86
104
  function responseToMessageNodes(resp) {
87
105
  const nodes = [];
106
+ const responseAttachments = parseResponseAttachments(resp);
107
+ let userNodesPushed = 0;
88
108
  if (resp.request_input) {
89
109
  for (const [idx, input] of resp.request_input.entries()) {
90
110
  const role = input.role;
91
111
  const rawContent = input.content;
92
112
  const text = extractInputText(rawContent);
93
- if (role === "user" && text) {
94
- nodes.push({
95
- id: `user-${resp.id}-${idx}`,
96
- role: "user",
97
- content: [textPart(text)],
98
- createdAt: new Date(resp.created_at * 1e3)
99
- });
113
+ const userContent = text || responseAttachments?.length;
114
+ if (role !== "user" || !userContent) continue;
115
+ const metadata = { responseId: resp.id };
116
+ if (responseAttachments && userNodesPushed === 0) {
117
+ metadata.attachments = responseAttachments.map(
118
+ (a) => ({
119
+ name: a.fileName,
120
+ fileId: a.fileId,
121
+ searchStoreId: a.searchStoreId
122
+ })
123
+ );
100
124
  }
125
+ nodes.push({
126
+ id: `user-${resp.id}-${idx}`,
127
+ role: "user",
128
+ content: [textPart(text)],
129
+ createdAt: new Date(resp.created_at * 1e3),
130
+ metadata
131
+ });
132
+ userNodesPushed += 1;
101
133
  }
102
134
  }
103
135
  const assistantParts = toAssistantParts(resp);
@@ -106,7 +138,8 @@ function responseToMessageNodes(resp) {
106
138
  id: getAssistantNodeId(resp),
107
139
  role: "assistant",
108
140
  content: assistantParts,
109
- createdAt: new Date((resp.completed_at ?? resp.created_at) * 1e3)
141
+ createdAt: new Date((resp.completed_at ?? resp.created_at) * 1e3),
142
+ metadata: { responseId: resp.id }
110
143
  });
111
144
  }
112
145
  return nodes;
@@ -127,7 +160,8 @@ function responsesToTree(responses) {
127
160
  role: node.role,
128
161
  content: node.content,
129
162
  status: "completed",
130
- createdAt: node.createdAt
163
+ createdAt: node.createdAt,
164
+ metadata: node.metadata
131
165
  };
132
166
  if (parentId !== null) {
133
167
  const parent = treeNodes[parentId];
@@ -1,4 +1,4 @@
1
- import { c, d, u, b, e, f } from "../index-BLq6_Lt2.js";
1
+ import { c, d, u, b, e, f } from "../index-Ct5hD214.js";
2
2
  export {
3
3
  c as createDocumentUploadProvider,
4
4
  d as defaultDocumentUploadConfig,
@@ -1,4 +1,4 @@
1
- import { u } from "../useMessageHandler-ZRC-gIOJ.js";
1
+ import { u } from "../useMessageHandler-CMdy-lm0.js";
2
2
  import { C, d, p, u as u2, a } from "../useChatKitLabels-ftC52m7f.js";
3
3
  export {
4
4
  C as CHAT_KIT_LABELS,
@@ -1,4 +1,4 @@
1
- import type { BaseMessage, ConversationTree, MessageContent, MessageRole, MessageStatus } from '../types';
1
+ import type { BaseMessage, ConversationTree, MessageContent, MessageMetadata, MessageRole, MessageStatus } from '../types';
2
2
  import { type Ref } from 'vue';
3
3
  export declare const useMessageHandler: () => {
4
4
  messages: Ref<BaseMessage[]>;
@@ -9,14 +9,18 @@ export declare const useMessageHandler: () => {
9
9
  content: MessageContent[];
10
10
  role: MessageRole;
11
11
  status: MessageStatus;
12
+ metadata?: MessageMetadata;
12
13
  }) => void;
13
14
  setCurrentUserMessage: (text: string) => void;
14
15
  getMessageById: (id: string) => BaseMessage | undefined;
15
16
  clearCurrentUserMessage: () => void;
16
- commitUserMessage: () => BaseMessage;
17
+ commitUserMessage: (opts?: {
18
+ metadata?: MessageMetadata;
19
+ }) => BaseMessage;
17
20
  updateMessageId: (oldId: string, newId: string) => void;
18
21
  clearMessages: () => void;
19
22
  setTree: (incoming: ConversationTree) => void;
20
23
  navigate: (targetId: string) => void;
24
+ cutBranchAfter: (messageId: string) => void;
21
25
  };
22
26
  //# sourceMappingURL=useMessageHandler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useMessageHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/useMessageHandler.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,aAAa,EAEd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAqC,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAElE,eAAO,MAAM,iBAAiB;cAuHJ,GAAG,CAAC,WAAW,EAAE,CAAC;;;6BApEV;QAC9B,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,cAAc,EAAE,CAAC;QAC1B,IAAI,EAAE,WAAW,CAAC;QAClB,MAAM,EAAE,aAAa,CAAC;KACvB;kCA7CoC,MAAM;yBAqEf,MAAM,KAAG,WAAW,GAAG,SAAS;;6BA7D9B,WAAW;6BAyET,MAAM,SAAS,MAAM;;wBAiB1B,gBAAgB;yBAKf,MAAM;CAkBnC,CAAC"}
1
+ {"version":3,"file":"useMessageHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/useMessageHandler.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,WAAW,EACX,aAAa,EAEd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAqC,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAElE,eAAO,MAAM,iBAAiB;cA6IJ,GAAG,CAAC,WAAW,EAAE,CAAC;;;6BArFV;QAC9B,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,cAAc,EAAE,CAAC;QAC1B,IAAI,EAAE,WAAW,CAAC;QAClB,MAAM,EAAE,aAAa,CAAC;QACtB,QAAQ,CAAC,EAAE,eAAe,CAAC;KAC5B;kCAnDoC,MAAM;yBAiFf,MAAM,KAAG,WAAW,GAAG,SAAS;;+BAzE1B;QAChC,QAAQ,CAAC,EAAE,eAAe,CAAC;KAC5B,KAAG,WAAW;6BAqFiB,MAAM,SAAS,MAAM;;wBAiB1B,gBAAgB;yBAKf,MAAM;gCAQC,MAAM;CAmB1C,CAAC"}
@@ -6,8 +6,17 @@ export declare function createEmptyTree(): ConversationTree;
6
6
  */
7
7
  export declare function getLinearPath(tree: ConversationTree): BaseMessage[];
8
8
  export declare function addNode(tree: ConversationTree, node: TreeMessage): void;
9
- export declare function updateNode(tree: ConversationTree, id: string, updates: Partial<Pick<TreeMessage, 'content' | 'status' | 'role'>>): void;
9
+ export declare function updateNode(tree: ConversationTree, id: string, updates: Partial<Pick<TreeMessage, 'content' | 'status' | 'role' | 'metadata'>>): void;
10
10
  export declare function updateNodeId(tree: ConversationTree, oldId: string, newId: string): void;
11
+ /**
12
+ * Remove every descendant of the node with the given id, keeping the node
13
+ * itself intact. The node's `childrenIds` is cleared and `activeChildIndex`
14
+ * is reset to 0, which makes the node the new leaf of its branch.
15
+ *
16
+ * Useful when editing a message and discarding the conversation that was
17
+ * generated after it.
18
+ */
19
+ export declare function cutBranchAfter(tree: ConversationTree, id: string): void;
11
20
  /**
12
21
  * Navigate to a different branch by updating the parent's activeChildIndex
13
22
  * to point at the target sibling.
@@ -1 +1 @@
1
- {"version":3,"file":"conversationTree.d.ts","sourceRoot":"","sources":["../../src/helpers/conversationTree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE3E,wBAAgB,eAAe,IAAI,gBAAgB,CAElD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,EAAE,CAkCnE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAYvE;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,gBAAgB,EACtB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC,GACjE,IAAI,CAON;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,IAAI,CAsBN;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAWvE"}
1
+ {"version":3,"file":"conversationTree.d.ts","sourceRoot":"","sources":["../../src/helpers/conversationTree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE3E,wBAAgB,eAAe,IAAI,gBAAgB,CAElD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,EAAE,CAmCnE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAYvE;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,gBAAgB,EACtB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CACd,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC,CAC9D,GACA,IAAI,CAUN;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,IAAI,CAsBN;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAevE;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAWvE"}
@@ -1,6 +1,6 @@
1
1
  import { g as generateId } from "./generateId-BHf0W4Rq.js";
2
2
  import { ref, shallowRef, computed, readonly, toRaw, toValue, watch } from "vue";
3
- import { u as useMessageHandler } from "./useMessageHandler-ZRC-gIOJ.js";
3
+ import { u as useMessageHandler } from "./useMessageHandler-CMdy-lm0.js";
4
4
  import "./purify.es-md74IFlY.js";
5
5
  function secondsToDate(seconds) {
6
6
  return new Date(seconds * 1e3);
package/dist/index.d.ts CHANGED
@@ -7,5 +7,5 @@ export { SdkError, createDocumentUploadProvider, defaultDocumentUploadConfig, de
7
7
  export type { DocumentUploadConfig, DocumentUploadProvider, FileEntry, FileStatus, } from './composables/fileUpload';
8
8
  export { CkAgentMessage, CkConversation, CkConversationLayout, CkCopyMessageActionButton, CkFeedbackButton, CkFileItemsList, CkHistory, CkHistoryItem, CkHistoryWrapper, CkInput, CkMarkdownRenderer, CkMessageActionButton, CkPromptActionButton, CkPromptStopButton, CkPromptInput, CkPromptInputDisclaimer, CkSendIcon, CkStopIcon, CkUserMessage, } from './components';
9
9
  export type { CkConversationLayoutProps, CkConversationProps, CkFeedbackButtonProps, CkFeedbackValue, CkFileEntry, CkFileItemsListEmits, CkFileItemsListProps, CkHistoryEmits, CkHistoryItemEmits, CkHistoryItemProps, CkHistoryProps, CkHistoryWrapperProps, CkMarkdownElementClasses, CkMarkdownRendererProps, CkUserMessageProps, } from './components';
10
- export type { BaseMessage, Conversation, ConversationTree, MessageContent, MessageContentStatus, MessageReasoningContent, MessageRole, MessageStatus, MessageTextContent, MessageToolContent, TreeMessage, } from './types';
10
+ export type { BaseMessage, Conversation, ConversationTree, MessageContent, MessageContentStatus, MessageMetadata, MessageReasoningContent, MessageRole, MessageStatus, MessageTextContent, MessageToolContent, TreeMessage, } from './types';
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AASpB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EACL,OAAO,EACP,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,eAAe,EACf,aAAa,EACb,6BAA6B,EAC7B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,QAAQ,EACR,4BAA4B,EAC5B,2BAA2B,EAC3B,gBAAgB,EAChB,kCAAkC,GACnC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,UAAU,GACX,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,OAAO,EACP,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,GACZ,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AASpB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EACL,OAAO,EACP,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,eAAe,EACf,aAAa,EACb,6BAA6B,EAC7B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,QAAQ,EACR,4BAA4B,EAC5B,2BAA2B,EAC3B,gBAAgB,EAChB,kCAAkC,GACnC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,UAAU,GACX,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,OAAO,EACP,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,GACZ,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { u } from "./useMessageHandler-ZRC-gIOJ.js";
1
+ import { u } from "./useMessageHandler-CMdy-lm0.js";
2
2
  import { C, d, p, u as u2, a } from "./useChatKitLabels-ftC52m7f.js";
3
- import { S, c, d as d2, a as a2, u as u3, b, e, f } from "./index-BLq6_Lt2.js";
3
+ import { S, c, d as d2, a as a2, u as u3, b, e, f } from "./index-Ct5hD214.js";
4
4
  import { _, a as a3, b as b2, C as C2, c as c2, d as d3, e as e2, f as f2, g, h, i, j, k, l, m, n, o, p as p2, q } from "./CkInput.vue_vue_type_script_setup_true_lang-C1Jnn1fK.js";
5
5
  export {
6
6
  C as CHAT_KIT_LABELS,
package/dist/types.d.ts CHANGED
@@ -57,6 +57,18 @@ export interface MessageReasoningContent {
57
57
  * Discriminated union of all content parts that can appear inside a message.
58
58
  */
59
59
  export type MessageContent = MessageTextContent | MessageToolContent | MessageReasoningContent;
60
+ /**
61
+ * Open-ended metadata bag carried alongside a message. chat-kit is
62
+ * intentionally agnostic about its contents — adapter authors
63
+ * (`responsesToTree`, …) and message handlers preserve the value verbatim
64
+ * through the tree → linear path projection, but never inspect it.
65
+ *
66
+ * Consumers attach their own well-known keys (attachments, citations,
67
+ * ratings, …) and define their own typed projections at the read site
68
+ * rather than extending this base type. That keeps the handler API stable
69
+ * even as the shape of what gets stored on a message evolves.
70
+ */
71
+ export type MessageMetadata = Record<string, unknown>;
60
72
  export interface BaseMessage {
61
73
  id: string;
62
74
  role: MessageRole;
@@ -65,6 +77,7 @@ export interface BaseMessage {
65
77
  status: MessageStatus;
66
78
  siblingIds?: string[];
67
79
  siblingIndex?: number;
80
+ metadata?: MessageMetadata;
68
81
  }
69
82
  export interface TreeMessage {
70
83
  id: string;
@@ -75,6 +88,7 @@ export interface TreeMessage {
75
88
  content: MessageContent[];
76
89
  status: MessageStatus;
77
90
  createdAt: Date;
91
+ metadata?: MessageMetadata;
78
92
  }
79
93
  export interface ConversationTree {
80
94
  nodes: Record<string, TreeMessage>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE1D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAE9E;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,kBAAkB,GAClB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE1D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAE9E;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,kBAAkB,GAClB,uBAAuB,CAAC;AAE5B;;;;;;;;;;GAUG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -16,7 +16,8 @@ function getLinearPath(tree) {
16
16
  role: node.role,
17
17
  content: node.content,
18
18
  createdAt: node.createdAt,
19
- status: node.status
19
+ status: node.status,
20
+ ...node.metadata !== void 0 ? { metadata: node.metadata } : {}
20
21
  };
21
22
  if (node.parentId !== null) {
22
23
  const parent = nodes[node.parentId];
@@ -49,6 +50,7 @@ function updateNode(tree, id, updates) {
49
50
  if (updates.content !== void 0) node.content = updates.content;
50
51
  if (updates.status !== void 0) node.status = updates.status;
51
52
  if (updates.role !== void 0) node.role = updates.role;
53
+ if ("metadata" in updates) node.metadata = updates.metadata;
52
54
  }
53
55
  function updateNodeId(tree, oldId, newId) {
54
56
  const node = tree.nodes[oldId];
@@ -69,6 +71,20 @@ function updateNodeId(tree, oldId, newId) {
69
71
  }
70
72
  if (tree.rootId === oldId) tree.rootId = newId;
71
73
  }
74
+ function cutBranchAfter(tree, id) {
75
+ const node = tree.nodes[id];
76
+ if (!node) return;
77
+ const stack = [...node.childrenIds];
78
+ while (stack.length > 0) {
79
+ const currentId = stack.pop();
80
+ const current = tree.nodes[currentId];
81
+ if (!current) continue;
82
+ stack.push(...current.childrenIds);
83
+ delete tree.nodes[currentId];
84
+ }
85
+ node.childrenIds = [];
86
+ node.activeChildIndex = 0;
87
+ }
72
88
  function navigate(tree, targetId) {
73
89
  const node = tree.nodes[targetId];
74
90
  if (!node || node.parentId === null) return;
@@ -92,7 +108,7 @@ const useMessageHandler = () => {
92
108
  function clearCurrentUserMessage() {
93
109
  currentUserMessage.value = "";
94
110
  }
95
- function commitUserMessage() {
111
+ function commitUserMessage(opts) {
96
112
  const id = generateId();
97
113
  const text = currentUserMessage.value.trim();
98
114
  if (!text) throw new Error("No message");
@@ -107,17 +123,20 @@ const useMessageHandler = () => {
107
123
  role: "user",
108
124
  content,
109
125
  status: "completed",
110
- createdAt: /* @__PURE__ */ new Date()
126
+ createdAt: /* @__PURE__ */ new Date(),
127
+ ...opts?.metadata !== void 0 ? { metadata: opts.metadata } : {}
111
128
  };
112
129
  addNode(tree, node);
113
130
  clearCurrentUserMessage();
114
- return {
131
+ const base = {
115
132
  id: node.id,
116
133
  role: node.role,
117
134
  content: node.content,
118
135
  createdAt: node.createdAt,
119
136
  status: node.status
120
137
  };
138
+ if (node.metadata !== void 0) base.metadata = node.metadata;
139
+ return base;
121
140
  }
122
141
  function updateMessage(message) {
123
142
  const existing = tree.nodes[message.id];
@@ -125,7 +144,8 @@ const useMessageHandler = () => {
125
144
  updateNode(tree, message.id, {
126
145
  content: message.content,
127
146
  role: message.role,
128
- status: message.status
147
+ status: message.status,
148
+ ...message.metadata !== void 0 ? { metadata: message.metadata } : {}
129
149
  });
130
150
  } else {
131
151
  const node = {
@@ -136,7 +156,8 @@ const useMessageHandler = () => {
136
156
  role: message.role,
137
157
  content: message.content,
138
158
  status: message.status,
139
- createdAt: /* @__PURE__ */ new Date()
159
+ createdAt: /* @__PURE__ */ new Date(),
160
+ ...message.metadata !== void 0 ? { metadata: message.metadata } : {}
140
161
  };
141
162
  addNode(tree, node);
142
163
  }
@@ -144,13 +165,15 @@ const useMessageHandler = () => {
144
165
  function getMessageById(id) {
145
166
  const node = tree.nodes[id];
146
167
  if (!node) return void 0;
147
- return {
168
+ const base = {
148
169
  id: node.id,
149
170
  role: node.role,
150
171
  content: node.content,
151
172
  createdAt: node.createdAt,
152
- status: node.status
173
+ status: node.status,
174
+ ...node.metadata !== void 0 ? { metadata: node.metadata } : {}
153
175
  };
176
+ return base;
154
177
  }
155
178
  function updateMessageId(oldId, newId) {
156
179
  updateNodeId(tree, oldId, newId);
@@ -165,6 +188,9 @@ const useMessageHandler = () => {
165
188
  function navigate$1(targetId) {
166
189
  navigate(tree, targetId);
167
190
  }
191
+ function cutBranchAfter$1(messageId) {
192
+ cutBranchAfter(tree, messageId);
193
+ }
168
194
  return {
169
195
  messages,
170
196
  currentUserMessage: readonly(currentUserMessage),
@@ -177,7 +203,8 @@ const useMessageHandler = () => {
177
203
  updateMessageId,
178
204
  clearMessages,
179
205
  setTree,
180
- navigate: navigate$1
206
+ navigate: navigate$1,
207
+ cutBranchAfter: cutBranchAfter$1
181
208
  };
182
209
  };
183
210
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aleph-alpha/chat-kit",
3
- "version": "1.11.1",
3
+ "version": "1.12.0",
4
4
  "description": "Chat kit package for building chat interfaces with Vue",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -371,6 +371,76 @@ describe('responsesToTree', () => {
371
371
  }
372
372
  });
373
373
 
374
+ it('stamps the originating responseId onto every emitted node', () => {
375
+ const tree = responsesToTree([
376
+ makeResponse({
377
+ id: 'r1',
378
+ request_input: [userInput('Hello')],
379
+ output: [assistantOutput('msg-a1', 'Hi')],
380
+ }),
381
+ makeResponse({
382
+ id: 'r2',
383
+ previous_response_id: 'r1',
384
+ request_input: [userInput('Follow-up')],
385
+ output: [assistantOutput('msg-a2', 'Reply')],
386
+ }),
387
+ ]);
388
+
389
+ expect(tree.nodes['user-r1-0']!.metadata.responseId).toBe('r1');
390
+ expect(tree.nodes['msg-a1']!.metadata.responseId).toBe('r1');
391
+ expect(tree.nodes['user-r2-0']!.metadata.responseId).toBe('r2');
392
+ expect(tree.nodes['msg-a2']!.metadata.responseId).toBe('r2');
393
+ });
394
+
395
+ it('parses metadata.attachments (JSON-encoded string) onto the first user node of a response', () => {
396
+ const tree = responsesToTree([
397
+ makeResponse({
398
+ id: 'r1',
399
+ request_input: [userInput('With files')],
400
+ output: [assistantOutput('msg-a1', 'OK')],
401
+ // The Responses API serialises attachments as a JSON-encoded
402
+ // string on the wire (transports flatten nested metadata).
403
+ metadata: {
404
+ attachments: JSON.stringify([
405
+ { fileName: 'report.pdf', fileId: 'f1', searchStoreId: 's1' },
406
+ ]),
407
+ },
408
+ }),
409
+ ]);
410
+
411
+ expect(tree.nodes['user-r1-0']!.metadata).toEqual({
412
+ responseId: 'r1',
413
+ attachments: [{ name: 'report.pdf', fileId: 'f1', searchStoreId: 's1' }],
414
+ });
415
+ // The assistant turn does not inherit attachments but still carries
416
+ // its responseId stamp.
417
+ expect(tree.nodes['msg-a1']!.metadata).toEqual({ responseId: 'r1' });
418
+ });
419
+
420
+ it('skips malformed metadata.attachments without polluting the tree', () => {
421
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
422
+ try {
423
+ const tree = responsesToTree([
424
+ makeResponse({
425
+ id: 'r1',
426
+ request_input: [userInput('Hello')],
427
+ output: [assistantOutput('msg-a1', 'Hi')],
428
+ metadata: {
429
+ attachments: '{not json',
430
+ },
431
+ }),
432
+ ]);
433
+
434
+ // The malformed attachments are dropped, but `responseId` is still
435
+ // stamped on every node the adapter emits.
436
+ expect(tree.nodes['user-r1-0']!.metadata).toEqual({ responseId: 'r1' });
437
+ expect(tree.nodes['user-r1-0']!.metadata.attachments).toBeUndefined();
438
+ expect(warn).toHaveBeenCalled();
439
+ } finally {
440
+ warn.mockRestore();
441
+ }
442
+ });
443
+
374
444
  it('chains the next response under a reasoning-only assistant turn', () => {
375
445
  const tree = responsesToTree([
376
446
  makeResponse({