@aleph-alpha/chat-kit 1.6.0 → 1.9.1

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.
@@ -489,7 +489,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
489
489
  }
490
490
  });
491
491
  const CkFeedbackButton = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-245705b8"]]);
492
- const CHAT_HISTORY_ACTIVE_INDICATOR_CLASS = 'before:absolute before:z-10 before:top-1/2 before:left-0 before:h-1/2 before:w-0.5 before:-translate-y-1/2 before:origin-left before:scale-x-0 before:rounded-full before:bg-background-accent-default before:opacity-0 before:transition-[transform,opacity] before:duration-200 before:ease-linear before:content-[""] data-[active=true]:before:scale-x-100 data-[active=true]:before:opacity-100';
492
+ const CHAT_HISTORY_ACTIVE_INDICATOR_CLASS = "ui-active-indicator";
493
493
  const _hoisted_1$3 = ["data-active"];
494
494
  const _hoisted_2$2 = { class: "min-w-0 flex-1" };
495
495
  const _hoisted_3$1 = { class: "truncate body-14-regular text-content-on-surface-primary" };
@@ -18,20 +18,26 @@ export interface ResponseOutputTextPart {
18
18
  annotations?: ResponseAnnotation[];
19
19
  }
20
20
  /**
21
- * One reasoning fragment inside a `ResponseOutputReasoning`. The Responses
22
- * API streams chain-of-thought under `reasoning_text`; the body is exposed
23
- * for consumers that want to render it (chat-kit itself only surfaces a
21
+ * One reasoning summary fragment inside a `ResponseOutputReasoning`. The
22
+ * Responses API exposes the human-readable chain-of-thought trail under
23
+ * `summary` as an array of `summary_text` parts; the body is surfaced for
24
+ * consumers that want to render it (chat-kit itself only surfaces a
24
25
  * "thinking" indicator).
26
+ *
27
+ * This part shape is **specific to reasoning outputs** — it never appears
28
+ * mixed with `ResponseOutputTextPart` inside a `ResponseOutputMessage`.
25
29
  */
26
30
  export interface ResponseReasoningTextPart {
27
- type: 'reasoning_text';
31
+ type: 'summary_text';
28
32
  text: string;
29
33
  annotations?: ResponseAnnotation[];
30
34
  }
31
35
  /**
32
36
  * Forward-compatible catch-all for content parts whose `type` chat-kit does
33
- * not yet model (e.g. refusals, future part kinds). Consumers narrow on
34
- * `type` themselves when they need richer handling.
37
+ * not yet model (e.g. refusals, future part kinds inside `unknown`-typed
38
+ * fields). Consumers narrow on `type` themselves when they need richer
39
+ * handling. Not used inside `ResponseOutputMessage` or
40
+ * `ResponseOutputReasoning`, whose content shapes are fixed.
35
41
  */
36
42
  export interface ResponseUnknownContentPart {
37
43
  type: string;
@@ -39,35 +45,36 @@ export interface ResponseUnknownContentPart {
39
45
  annotations?: ResponseAnnotation[];
40
46
  [key: string]: unknown;
41
47
  }
42
- /**
43
- * Discriminated union of content parts that can appear inside a Responses-
44
- * API output item. `ResponseOutputTextPart` and `ResponseReasoningTextPart`
45
- * cover the rendered shapes; the catch-all keeps the union open.
46
- */
47
- export type OutputContentPart = ResponseOutputTextPart | ResponseReasoningTextPart | ResponseUnknownContentPart;
48
48
  /**
49
49
  * Visible message produced by a Responses-API turn (assistant reply or
50
50
  * echoed user input). Carries the renderable text content; `responsesToTree`
51
- * extracts text from `content` to build the chat tree.
51
+ * extracts text from `content` to build the chat tree. All entries are
52
+ * `ResponseOutputTextPart`s — no reasoning or unknown parts are mixed in.
52
53
  */
53
54
  export interface ResponseOutputMessage {
54
55
  type: 'message';
55
56
  id: string;
56
57
  status: string;
57
58
  role: 'assistant' | 'user';
58
- content: string | OutputContentPart[];
59
+ content: ResponseOutputTextPart[];
59
60
  }
60
61
  /**
61
- * Chain-of-thought trail produced by the assistant during a turn. Surfaced
62
- * in chat-kit only as a "thinking" indicator; consumers may render the
63
- * underlying `reasoning_text` parts directly when desired.
62
+ * Chain-of-thought trail produced by the assistant during a turn. The
63
+ * human-readable summary lives on `summary` as an array of
64
+ * `ResponseReasoningTextPart`s (all `summary_text`); `content` is reserved
65
+ * for the opaque/raw reasoning payload the API may attach and is kept
66
+ * `unknown` so consumers can downcast it on their own.
67
+ *
68
+ * Surfaced in chat-kit only as a "thinking" indicator; consumers may render
69
+ * the `summary` parts directly when desired.
64
70
  */
65
71
  export interface ResponseOutputReasoning {
66
72
  type: 'reasoning';
67
73
  id: string;
68
74
  status: string;
69
75
  role?: 'assistant' | null;
70
- content: OutputContentPart[];
76
+ summary: ResponseReasoningTextPart[];
77
+ content: unknown;
71
78
  }
72
79
  /**
73
80
  * Single tool entry returned inside `mcp_list_tools` (and similar tool-
@@ -86,6 +93,22 @@ export interface ResponseToolDescriptor {
86
93
  * today; extend it as new tool kinds are introduced upstream.
87
94
  */
88
95
  export type ResponseOutputToolType = 'mcp_list_tools' | 'mcp_call' | 'tool_call' | 'function_call' | 'web_search_call' | 'file_search_call' | 'code_interpreter_call' | 'image_generation_call' | 'local_shell_call';
96
+ /**
97
+ * Server-provided rendering hints for a tool invocation. The server emits a
98
+ * human-readable `text` (e.g. "Searching the web…") and a lucide.dev `icon`
99
+ * name to display alongside the tool, plus a `phase` describing the current
100
+ * lifecycle stage so the UI can swap labels/icons as the call progresses.
101
+ *
102
+ * Only `'done'` is received in a response today.
103
+ */
104
+ export interface ResponseOutputToolDisplay {
105
+ /** Human-readable label to render for the tool (server-controlled). */
106
+ text: string;
107
+ /** Lucide.dev icon name to render next to the label. */
108
+ icon: string;
109
+ /** Lifecycle phase of the tool call. */
110
+ phase: 'done';
111
+ }
89
112
  /**
90
113
  * Tool-related output produced during a Responses-API turn. Covers tool
91
114
  * discovery (`mcp_list_tools`), invocation (`mcp_call`, `function_call`,
@@ -109,6 +132,12 @@ export interface ResponseOutputTool {
109
132
  call_id?: string;
110
133
  /** Tool result payload (shape depends on the tool kind). */
111
134
  output?: unknown;
135
+ /**
136
+ * Optional server-provided display hints (label, icon, phase). When
137
+ * present, `responsesToTree` forwards `text` and `icon` onto the
138
+ * resulting `MessageToolContent` so the UI can render them directly.
139
+ */
140
+ display?: ResponseOutputToolDisplay;
112
141
  [key: string]: unknown;
113
142
  }
114
143
  /**
@@ -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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"}
@@ -1,9 +1,5 @@
1
1
  import { g as generateId } from "../generateId-BHf0W4Rq.js";
2
- function extractMessageText(content) {
3
- if (typeof content === "string") return content.trim();
4
- return extractTextFromParts(content);
5
- }
6
- function extractTextFromParts(parts) {
2
+ function extractMessageText(parts) {
7
3
  let text = "";
8
4
  for (const part of parts) {
9
5
  if (part.type === "output_text" || part.type === "text") {
@@ -12,10 +8,10 @@ function extractTextFromParts(parts) {
12
8
  }
13
9
  return text.trim();
14
10
  }
15
- function extractReasoningText(parts) {
11
+ function extractReasoningSummary(parts) {
16
12
  let text = "";
17
13
  for (const part of parts) {
18
- if (part.type === "reasoning_text") {
14
+ if (part.type === "summary_text") {
19
15
  text += part.text ?? "";
20
16
  }
21
17
  }
@@ -24,12 +20,20 @@ function extractReasoningText(parts) {
24
20
  function textPart(text, id) {
25
21
  return { type: "text", id: id ?? generateId(), text, status: "completed" };
26
22
  }
23
+ function toolPart(out) {
24
+ return {
25
+ type: "tool",
26
+ id: out.id,
27
+ name: out.name ?? out.type,
28
+ ...out.display ? { text: out.display.text, icon: out.display.icon } : {}
29
+ };
30
+ }
27
31
  function toAssistantParts(resp) {
28
32
  const parts = [];
29
33
  for (const out of resp.output ?? []) {
30
34
  switch (out.type) {
31
35
  case "reasoning": {
32
- const text = extractReasoningText(out.content);
36
+ const text = extractReasoningSummary(out.summary ?? []);
33
37
  parts.push({
34
38
  type: "reasoning",
35
39
  id: out.id,
@@ -51,11 +55,7 @@ function toAssistantParts(resp) {
51
55
  case "mcp_call":
52
56
  case "function_call":
53
57
  case "tool_call": {
54
- parts.push({
55
- type: "tool",
56
- id: out.id,
57
- name: out.name ?? out.type
58
- });
58
+ parts.push(toolPart(out));
59
59
  break;
60
60
  }
61
61
  }
@@ -72,10 +72,16 @@ function getAssistantNodeId(resp) {
72
72
  }
73
73
  function extractInputText(rawContent) {
74
74
  if (typeof rawContent === "string") return rawContent.trim();
75
- if (Array.isArray(rawContent)) {
76
- return extractTextFromParts(rawContent);
75
+ if (!Array.isArray(rawContent)) return "";
76
+ let text = "";
77
+ for (const raw of rawContent) {
78
+ if (!raw || typeof raw !== "object") continue;
79
+ const part = raw;
80
+ if ((part.type === "input_text" || part.type === "output_text" || part.type === "text") && typeof part.text === "string") {
81
+ text += part.text;
82
+ }
77
83
  }
78
- return "";
84
+ return text.trim();
79
85
  }
80
86
  function responseToMessageNodes(resp) {
81
87
  const nodes = [];
@@ -1,15 +1,5 @@
1
1
  /**
2
- * Shared class string for the left-edge active indicator used by a chat
3
- * history row.
4
- *
5
- * The `::before` pseudo-element is always mounted so CSS has something to
6
- * transition. At rest it's painted from `scale-x-0` + `opacity-0` with its
7
- * transform anchored on the left edge (`origin-left`); when the row's
8
- * `data-active="true"` flips on, the bar paints in from left to right while
9
- * fading in, using a 200ms linear curve.
10
- *
11
- * Kept as a string constant (rather than generated via `cn`) so UnoCSS's
12
- * static scanner picks up every utility class for atomic CSS generation.
2
+ * Uses the shared UI library active indicator preflight class.
13
3
  */
14
- export declare const CHAT_HISTORY_ACTIVE_INDICATOR_CLASS = "before:absolute before:z-10 before:top-1/2 before:left-0 before:h-1/2 before:w-0.5 before:-translate-y-1/2 before:origin-left before:scale-x-0 before:rounded-full before:bg-background-accent-default before:opacity-0 before:transition-[transform,opacity] before:duration-200 before:ease-linear before:content-[\"\"] data-[active=true]:before:scale-x-100 data-[active=true]:before:opacity-100";
4
+ export declare const CHAT_HISTORY_ACTIVE_INDICATOR_CLASS = "ui-active-indicator";
15
5
  //# sourceMappingURL=activeIndicator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"activeIndicator.d.ts","sourceRoot":"","sources":["../../../../src/components/base/CkHistoryItem/activeIndicator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mCAAmC,2YACwV,CAAC"}
1
+ {"version":3,"file":"activeIndicator.d.ts","sourceRoot":"","sources":["../../../../src/components/base/CkHistoryItem/activeIndicator.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,mCAAmC,wBAAwB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { _, a, b, C, c, d, e, f, g, h, i, j, k, l, m, n, o, p } from "../CkInput.vue_vue_type_script_setup_true_lang-C5C09u0z.js";
1
+ import { _, a, b, C, c, d, e, f, g, h, i, j, k, l, m, n, o, p } from "../CkInput.vue_vue_type_script_setup_true_lang-CHPs-R5p.js";
2
2
  export {
3
3
  _ as CkAgentMessage,
4
4
  a as CkConversation,
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { u } from "./useMessageHandler-ZRC-gIOJ.js";
2
2
  import { C, d, p, u as u2, a } from "./useChatKitLabels-ftC52m7f.js";
3
3
  import { S, c, d as d2, a as a2, u as u3, b, e, f } from "./index-BLq6_Lt2.js";
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 } from "./CkInput.vue_vue_type_script_setup_true_lang-C5C09u0z.js";
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 } from "./CkInput.vue_vue_type_script_setup_true_lang-CHPs-R5p.js";
5
5
  export {
6
6
  C as CHAT_KIT_LABELS,
7
7
  _ as CkAgentMessage,
package/dist/types.d.ts CHANGED
@@ -24,19 +24,28 @@ export interface MessageTextContent {
24
24
  * Tool invocation triggered by the assistant during its turn. Only the tool
25
25
  * name is rendered; arguments and results are intentionally outside the
26
26
  * UI-facing model and should be tracked by the host application.
27
+ *
28
+ * `text` and `icon` are optional server-provided display hints (sourced from
29
+ * a `display` block on the wire payload, e.g.
30
+ * `ResponseOutputTool.display`). When present, the UI is expected to render
31
+ * the human-readable `text` and the lucide.dev `icon` instead of falling
32
+ * back to the raw tool `name`.
27
33
  */
28
34
  export interface MessageToolContent {
29
35
  type: 'tool';
30
36
  id: string;
31
37
  name: string;
38
+ text?: string;
39
+ icon?: string;
32
40
  }
33
41
  /**
34
42
  * Chain-of-thought / reasoning segment produced by the assistant. `text` is
35
43
  * the (optional) human-readable trail — populated when the underlying
36
44
  * transport exposes reasoning content (`REASONING_MESSAGE_CONTENT` deltas
37
- * during a live run, `reasoning_text` parts when re-hydrating from the
38
- * Responses API). Surfaces that only need a "Thinking…" / "Thought"
39
- * indicator can ignore it and rely on `status` alone.
45
+ * during a live run, `summary_text` parts under
46
+ * `ResponseOutputReasoning.summary` when re-hydrating from the Responses
47
+ * API). Surfaces that only need a "Thinking…" / "Thought" indicator can
48
+ * ignore it and rely on `status` alone.
40
49
  */
41
50
  export interface MessageReasoningContent {
42
51
  type: 'reasoning';
@@ -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;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;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,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aleph-alpha/chat-kit",
3
- "version": "1.6.0",
3
+ "version": "1.9.1",
4
4
  "description": "Chat kit package for building chat interfaces with Vue",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -52,8 +52,7 @@
52
52
  "node": ">=20.19.0"
53
53
  },
54
54
  "publishConfig": {
55
- "access": "public",
56
- "registry": "https://npm.pkg.github.com"
55
+ "access": "public"
57
56
  },
58
57
  "repository": {
59
58
  "type": "git",
@@ -72,7 +71,7 @@
72
71
  "remark-parse": "^11.0.0",
73
72
  "remark-rehype": "^11.1.2",
74
73
  "unified": "^11.0.5",
75
- "@aleph-alpha/ui-library": "2.4.3"
74
+ "@aleph-alpha/ui-library": "2.5.1"
76
75
  },
77
76
  "devDependencies": {
78
77
  "@storybook/addon-a11y": "10.2.17",
@@ -50,7 +50,8 @@ function reasoningOutput(id: string, text: string): ResponseOutputReasoning {
50
50
  id,
51
51
  status: 'completed',
52
52
  role: null,
53
- content: [{ type: 'reasoning_text', text }],
53
+ summary: [{ type: 'summary_text', text }],
54
+ content: null,
54
55
  };
55
56
  }
56
57
 
@@ -178,7 +179,6 @@ describe('responsesToTree', () => {
178
179
  role: 'assistant',
179
180
  content: [
180
181
  { type: 'output_text', text: 'first ' },
181
- { type: 'reasoning_summary', text: 'should-be-ignored' },
182
182
  { type: 'text', text: 'second' },
183
183
  ],
184
184
  },
@@ -271,6 +271,57 @@ describe('responsesToTree', () => {
271
271
  expect(assistant.content[2].type).toBe('text');
272
272
  });
273
273
 
274
+ it('forwards `display.text` and `display.icon` from a tool output onto the resulting tool content', () => {
275
+ const tree = responsesToTree([
276
+ makeResponse({
277
+ id: 'r1',
278
+ request_input: [userInput('Hello')],
279
+ output: [
280
+ toolOutput({
281
+ id: 'tool-1',
282
+ type: 'mcp_call',
283
+ name: 'firecrawl_scrape',
284
+ display: {
285
+ text: 'Searching the web',
286
+ icon: 'globe',
287
+ phase: 'done',
288
+ },
289
+ }),
290
+ assistantOutput('msg-a1', 'Done'),
291
+ ],
292
+ }),
293
+ ]);
294
+
295
+ const tool = tree.nodes['msg-a1']!.content[0];
296
+ expect(tool).toMatchObject({
297
+ type: 'tool',
298
+ id: 'tool-1',
299
+ name: 'firecrawl_scrape',
300
+ text: 'Searching the web',
301
+ icon: 'globe',
302
+ });
303
+ });
304
+
305
+ it('omits `text` / `icon` on tool content when the tool output has no `display` block', () => {
306
+ const tree = responsesToTree([
307
+ makeResponse({
308
+ id: 'r1',
309
+ request_input: [userInput('Hello')],
310
+ output: [
311
+ toolOutput({ id: 'tool-1', type: 'mcp_call', name: 'search' }),
312
+ assistantOutput('msg-a1', 'Done'),
313
+ ],
314
+ }),
315
+ ]);
316
+
317
+ const tool = tree.nodes['msg-a1']!.content[0];
318
+ expect(tool.type).toBe('tool');
319
+ if (tool.type === 'tool') {
320
+ expect(tool.text).toBeUndefined();
321
+ expect(tool.icon).toBeUndefined();
322
+ }
323
+ });
324
+
274
325
  it('creates an assistant node from reasoning / tool outputs even when no message output is present', () => {
275
326
  const tree = responsesToTree([
276
327
  makeResponse({
@@ -294,7 +345,7 @@ describe('responsesToTree', () => {
294
345
  expect(assistant.content[1].type).toBe('tool');
295
346
  });
296
347
 
297
- it('omits reasoning text when no reasoning_text parts are present', () => {
348
+ it('omits reasoning text when no summary_text parts are present', () => {
298
349
  const tree = responsesToTree([
299
350
  makeResponse({
300
351
  id: 'r1',
@@ -305,7 +356,8 @@ describe('responsesToTree', () => {
305
356
  id: 'rs-empty',
306
357
  status: 'completed',
307
358
  role: null,
308
- content: [],
359
+ summary: [],
360
+ content: null,
309
361
  },
310
362
  assistantOutput('msg-a1', 'Hi'),
311
363
  ],
@@ -52,21 +52,27 @@ export interface ResponseOutputTextPart {
52
52
  }
53
53
 
54
54
  /**
55
- * One reasoning fragment inside a `ResponseOutputReasoning`. The Responses
56
- * API streams chain-of-thought under `reasoning_text`; the body is exposed
57
- * for consumers that want to render it (chat-kit itself only surfaces a
55
+ * One reasoning summary fragment inside a `ResponseOutputReasoning`. The
56
+ * Responses API exposes the human-readable chain-of-thought trail under
57
+ * `summary` as an array of `summary_text` parts; the body is surfaced for
58
+ * consumers that want to render it (chat-kit itself only surfaces a
58
59
  * "thinking" indicator).
60
+ *
61
+ * This part shape is **specific to reasoning outputs** — it never appears
62
+ * mixed with `ResponseOutputTextPart` inside a `ResponseOutputMessage`.
59
63
  */
60
64
  export interface ResponseReasoningTextPart {
61
- type: 'reasoning_text';
65
+ type: 'summary_text';
62
66
  text: string;
63
67
  annotations?: ResponseAnnotation[];
64
68
  }
65
69
 
66
70
  /**
67
71
  * Forward-compatible catch-all for content parts whose `type` chat-kit does
68
- * not yet model (e.g. refusals, future part kinds). Consumers narrow on
69
- * `type` themselves when they need richer handling.
72
+ * not yet model (e.g. refusals, future part kinds inside `unknown`-typed
73
+ * fields). Consumers narrow on `type` themselves when they need richer
74
+ * handling. Not used inside `ResponseOutputMessage` or
75
+ * `ResponseOutputReasoning`, whose content shapes are fixed.
70
76
  */
71
77
  export interface ResponseUnknownContentPart {
72
78
  type: string;
@@ -75,40 +81,37 @@ export interface ResponseUnknownContentPart {
75
81
  [key: string]: unknown;
76
82
  }
77
83
 
78
- /**
79
- * Discriminated union of content parts that can appear inside a Responses-
80
- * API output item. `ResponseOutputTextPart` and `ResponseReasoningTextPart`
81
- * cover the rendered shapes; the catch-all keeps the union open.
82
- */
83
- export type OutputContentPart =
84
- | ResponseOutputTextPart
85
- | ResponseReasoningTextPart
86
- | ResponseUnknownContentPart;
87
-
88
84
  /**
89
85
  * Visible message produced by a Responses-API turn (assistant reply or
90
86
  * echoed user input). Carries the renderable text content; `responsesToTree`
91
- * extracts text from `content` to build the chat tree.
87
+ * extracts text from `content` to build the chat tree. All entries are
88
+ * `ResponseOutputTextPart`s — no reasoning or unknown parts are mixed in.
92
89
  */
93
90
  export interface ResponseOutputMessage {
94
91
  type: 'message';
95
92
  id: string;
96
93
  status: string;
97
94
  role: 'assistant' | 'user';
98
- content: string | OutputContentPart[];
95
+ content: ResponseOutputTextPart[];
99
96
  }
100
97
 
101
98
  /**
102
- * Chain-of-thought trail produced by the assistant during a turn. Surfaced
103
- * in chat-kit only as a "thinking" indicator; consumers may render the
104
- * underlying `reasoning_text` parts directly when desired.
99
+ * Chain-of-thought trail produced by the assistant during a turn. The
100
+ * human-readable summary lives on `summary` as an array of
101
+ * `ResponseReasoningTextPart`s (all `summary_text`); `content` is reserved
102
+ * for the opaque/raw reasoning payload the API may attach and is kept
103
+ * `unknown` so consumers can downcast it on their own.
104
+ *
105
+ * Surfaced in chat-kit only as a "thinking" indicator; consumers may render
106
+ * the `summary` parts directly when desired.
105
107
  */
106
108
  export interface ResponseOutputReasoning {
107
109
  type: 'reasoning';
108
110
  id: string;
109
111
  status: string;
110
112
  role?: 'assistant' | null;
111
- content: OutputContentPart[];
113
+ summary: ResponseReasoningTextPart[];
114
+ content: unknown;
112
115
  }
113
116
 
114
117
  /**
@@ -139,6 +142,23 @@ export type ResponseOutputToolType =
139
142
  | 'image_generation_call'
140
143
  | 'local_shell_call';
141
144
 
145
+ /**
146
+ * Server-provided rendering hints for a tool invocation. The server emits a
147
+ * human-readable `text` (e.g. "Searching the web…") and a lucide.dev `icon`
148
+ * name to display alongside the tool, plus a `phase` describing the current
149
+ * lifecycle stage so the UI can swap labels/icons as the call progresses.
150
+ *
151
+ * Only `'done'` is received in a response today.
152
+ */
153
+ export interface ResponseOutputToolDisplay {
154
+ /** Human-readable label to render for the tool (server-controlled). */
155
+ text: string;
156
+ /** Lucide.dev icon name to render next to the label. */
157
+ icon: string;
158
+ /** Lifecycle phase of the tool call. */
159
+ phase: 'done';
160
+ }
161
+
142
162
  /**
143
163
  * Tool-related output produced during a Responses-API turn. Covers tool
144
164
  * discovery (`mcp_list_tools`), invocation (`mcp_call`, `function_call`,
@@ -162,6 +182,12 @@ export interface ResponseOutputTool {
162
182
  call_id?: string;
163
183
  /** Tool result payload (shape depends on the tool kind). */
164
184
  output?: unknown;
185
+ /**
186
+ * Optional server-provided display hints (label, icon, phase). When
187
+ * present, `responsesToTree` forwards `text` and `icon` onto the
188
+ * resulting `MessageToolContent` so the UI can render them directly.
189
+ */
190
+ display?: ResponseOutputToolDisplay;
165
191
  [key: string]: unknown;
166
192
  }
167
193
 
@@ -233,12 +259,7 @@ interface ResponseMessageNode {
233
259
  createdAt: Date;
234
260
  }
235
261
 
236
- function extractMessageText(content: ResponseOutputMessage['content']): string {
237
- if (typeof content === 'string') return content.trim();
238
- return extractTextFromParts(content);
239
- }
240
-
241
- function extractTextFromParts(parts: OutputContentPart[]): string {
262
+ function extractMessageText(parts: ResponseOutputTextPart[]): string {
242
263
  let text = '';
243
264
  for (const part of parts) {
244
265
  if (part.type === 'output_text' || part.type === 'text') {
@@ -248,10 +269,10 @@ function extractTextFromParts(parts: OutputContentPart[]): string {
248
269
  return text.trim();
249
270
  }
250
271
 
251
- function extractReasoningText(parts: OutputContentPart[]): string {
272
+ function extractReasoningSummary(parts: ResponseReasoningTextPart[]): string {
252
273
  let text = '';
253
274
  for (const part of parts) {
254
- if (part.type === 'reasoning_text') {
275
+ if (part.type === 'summary_text') {
255
276
  text += part.text ?? '';
256
277
  }
257
278
  }
@@ -262,6 +283,18 @@ function textPart(text: string, id?: string): MessageContent {
262
283
  return { type: 'text', id: id ?? generateId(), text, status: 'completed' };
263
284
  }
264
285
 
286
+ // Build a `MessageToolContent` for one tool invocation, forwarding the
287
+ // optional server-provided `display.text` / `display.icon` hints when
288
+ // present so the UI can render them directly.
289
+ function toolPart(out: ResponseOutputTool): MessageContent {
290
+ return {
291
+ type: 'tool',
292
+ id: out.id,
293
+ name: out.name ?? out.type,
294
+ ...(out.display ? { text: out.display.text, icon: out.display.icon } : {}),
295
+ };
296
+ }
297
+
265
298
  // Build the `content` array for one assistant turn from a Responses-API
266
299
  // record. Reasoning trails, tool invocations, and visible text all belong to
267
300
  // the same turn and are kept in their original wire order so the UI can
@@ -271,7 +304,7 @@ function toAssistantParts(resp: StoredResponse): MessageContent[] {
271
304
  for (const out of resp.output ?? []) {
272
305
  switch (out.type) {
273
306
  case 'reasoning': {
274
- const text = extractReasoningText(out.content);
307
+ const text = extractReasoningSummary(out.summary ?? []);
275
308
  parts.push({
276
309
  type: 'reasoning',
277
310
  id: out.id,
@@ -293,11 +326,7 @@ function toAssistantParts(resp: StoredResponse): MessageContent[] {
293
326
  case 'mcp_call':
294
327
  case 'function_call':
295
328
  case 'tool_call': {
296
- parts.push({
297
- type: 'tool',
298
- id: out.id,
299
- name: out.name ?? out.type,
300
- });
329
+ parts.push(toolPart(out));
301
330
  break;
302
331
  }
303
332
  default:
@@ -320,19 +349,35 @@ function getAssistantNodeId(resp: StoredResponse): string {
320
349
  return `assistant-${resp.id}`;
321
350
  }
322
351
 
323
- // Within a single response, the visible messages chain linearly: every user
324
- // input is followed by exactly one assistant turn (whose reasoning, tool,
325
- // and text outputs are merged into one node). Across responses, branching
326
- // is encoded by `previous_response_id` so several responses can share the
327
- // same parent and form sibling subtrees.
352
+ // `request_input[].content` is wire-typed as `unknown` because user inputs
353
+ // can arrive as plain strings or as structured part arrays (e.g.
354
+ // `input_text`, `output_text`, `text`). We defensively pick up any
355
+ // text-bearing parts without relying on the strict output content shapes,
356
+ // which are reserved for `ResponseOutputMessage` / `ResponseOutputReasoning`.
328
357
  function extractInputText(rawContent: unknown): string {
329
358
  if (typeof rawContent === 'string') return rawContent.trim();
330
- if (Array.isArray(rawContent)) {
331
- return extractTextFromParts(rawContent as OutputContentPart[]);
359
+ if (!Array.isArray(rawContent)) return '';
360
+ let text = '';
361
+ for (const raw of rawContent) {
362
+ if (!raw || typeof raw !== 'object') continue;
363
+ const part = raw as { type?: unknown; text?: unknown };
364
+ if (
365
+ (part.type === 'input_text' ||
366
+ part.type === 'output_text' ||
367
+ part.type === 'text') &&
368
+ typeof part.text === 'string'
369
+ ) {
370
+ text += part.text;
371
+ }
332
372
  }
333
- return '';
373
+ return text.trim();
334
374
  }
335
375
 
376
+ // Within a single response, the visible messages chain linearly: every user
377
+ // input is followed by exactly one assistant turn (whose reasoning, tool,
378
+ // and text outputs are merged into one node). Across responses, branching
379
+ // is encoded by `previous_response_id` so several responses can share the
380
+ // same parent and form sibling subtrees.
336
381
  function responseToMessageNodes(resp: StoredResponse): ResponseMessageNode[] {
337
382
  const nodes: ResponseMessageNode[] = [];
338
383
  if (resp.request_input) {
@@ -1,15 +1,4 @@
1
1
  /**
2
- * Shared class string for the left-edge active indicator used by a chat
3
- * history row.
4
- *
5
- * The `::before` pseudo-element is always mounted so CSS has something to
6
- * transition. At rest it's painted from `scale-x-0` + `opacity-0` with its
7
- * transform anchored on the left edge (`origin-left`); when the row's
8
- * `data-active="true"` flips on, the bar paints in from left to right while
9
- * fading in, using a 200ms linear curve.
10
- *
11
- * Kept as a string constant (rather than generated via `cn`) so UnoCSS's
12
- * static scanner picks up every utility class for atomic CSS generation.
2
+ * Uses the shared UI library active indicator preflight class.
13
3
  */
14
- export const CHAT_HISTORY_ACTIVE_INDICATOR_CLASS =
15
- 'before:absolute before:z-10 before:top-1/2 before:left-0 before:h-1/2 before:w-0.5 before:-translate-y-1/2 before:origin-left before:scale-x-0 before:rounded-full before:bg-background-accent-default before:opacity-0 before:transition-[transform,opacity] before:duration-200 before:ease-linear before:content-[""] data-[active=true]:before:scale-x-100 data-[active=true]:before:opacity-100';
4
+ export const CHAT_HISTORY_ACTIVE_INDICATOR_CLASS = 'ui-active-indicator';
package/src/types.ts CHANGED
@@ -29,20 +29,29 @@ export interface MessageTextContent {
29
29
  * Tool invocation triggered by the assistant during its turn. Only the tool
30
30
  * name is rendered; arguments and results are intentionally outside the
31
31
  * UI-facing model and should be tracked by the host application.
32
+ *
33
+ * `text` and `icon` are optional server-provided display hints (sourced from
34
+ * a `display` block on the wire payload, e.g.
35
+ * `ResponseOutputTool.display`). When present, the UI is expected to render
36
+ * the human-readable `text` and the lucide.dev `icon` instead of falling
37
+ * back to the raw tool `name`.
32
38
  */
33
39
  export interface MessageToolContent {
34
40
  type: 'tool';
35
41
  id: string;
36
42
  name: string;
43
+ text?: string;
44
+ icon?: string;
37
45
  }
38
46
 
39
47
  /**
40
48
  * Chain-of-thought / reasoning segment produced by the assistant. `text` is
41
49
  * the (optional) human-readable trail — populated when the underlying
42
50
  * transport exposes reasoning content (`REASONING_MESSAGE_CONTENT` deltas
43
- * during a live run, `reasoning_text` parts when re-hydrating from the
44
- * Responses API). Surfaces that only need a "Thinking…" / "Thought"
45
- * indicator can ignore it and rely on `status` alone.
51
+ * during a live run, `summary_text` parts under
52
+ * `ResponseOutputReasoning.summary` when re-hydrating from the Responses
53
+ * API). Surfaces that only need a "Thinking…" / "Thought" indicator can
54
+ * ignore it and rely on `status` alone.
46
55
  */
47
56
  export interface MessageReasoningContent {
48
57
  type: 'reasoning';