@gravity-ui/aikit 2.1.0 → 2.2.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.
- package/build/cjs/adapters/openai/helpers/applyContentUpdate.js +6 -1
- package/build/cjs/adapters/openai/helpers/applyContentUpdate.js.map +1 -1
- package/build/cjs/adapters/openai/helpers/getStreamEventContentUpdate.d.ts +6 -0
- package/build/cjs/adapters/openai/helpers/getStreamEventContentUpdate.js +9 -14
- package/build/cjs/adapters/openai/helpers/getStreamEventContentUpdate.js.map +1 -1
- package/build/cjs/adapters/openai/helpers/mapOutputToContent.js +4 -1
- package/build/cjs/adapters/openai/helpers/mapOutputToContent.js.map +1 -1
- package/build/cjs/adapters/openai/helpers/prettyPrintJson.d.ts +5 -0
- package/build/cjs/adapters/openai/helpers/prettyPrintJson.js +18 -0
- package/build/cjs/adapters/openai/helpers/prettyPrintJson.js.map +1 -0
- package/build/cjs/components/atoms/MarkdownRenderer/MarkdownRenderer.css +80 -1
- package/build/cjs/components/pages/AIStudioChat/AIStudioChat.js +19 -6
- package/build/cjs/components/pages/AIStudioChat/AIStudioChat.js.map +1 -1
- package/build/cjs/components/pages/AIStudioChat/McpToolRenderer.css +14 -0
- package/build/cjs/components/pages/AIStudioChat/McpToolRenderer.d.ts +5 -0
- package/build/cjs/components/pages/AIStudioChat/McpToolRenderer.js +21 -0
- package/build/cjs/components/pages/AIStudioChat/McpToolRenderer.js.map +1 -0
- package/build/cjs/components/pages/AIStudioChat/i18n/en.json +4 -0
- package/build/cjs/components/pages/AIStudioChat/i18n/index.d.ts +13 -0
- package/build/cjs/components/pages/AIStudioChat/i18n/index.js +10 -0
- package/build/cjs/components/pages/AIStudioChat/i18n/index.js.map +1 -0
- package/build/cjs/components/pages/AIStudioChat/i18n/ru.json +4 -0
- package/build/cjs/package.json +1 -1
- package/build/cjs/types/messages.d.ts +6 -1
- package/build/cjs/types/messages.js.map +1 -1
- package/build/esm/adapters/openai/helpers/applyContentUpdate.js +6 -1
- package/build/esm/adapters/openai/helpers/applyContentUpdate.js.map +1 -1
- package/build/esm/adapters/openai/helpers/getStreamEventContentUpdate.d.ts +6 -0
- package/build/esm/adapters/openai/helpers/getStreamEventContentUpdate.js +9 -14
- package/build/esm/adapters/openai/helpers/getStreamEventContentUpdate.js.map +1 -1
- package/build/esm/adapters/openai/helpers/mapOutputToContent.js +4 -1
- package/build/esm/adapters/openai/helpers/mapOutputToContent.js.map +1 -1
- package/build/esm/adapters/openai/helpers/prettyPrintJson.d.ts +5 -0
- package/build/esm/adapters/openai/helpers/prettyPrintJson.js +15 -0
- package/build/esm/adapters/openai/helpers/prettyPrintJson.js.map +1 -0
- package/build/esm/components/atoms/MarkdownRenderer/MarkdownRenderer.css +80 -1
- package/build/esm/components/pages/AIStudioChat/AIStudioChat.js +19 -6
- package/build/esm/components/pages/AIStudioChat/AIStudioChat.js.map +1 -1
- package/build/esm/components/pages/AIStudioChat/McpToolRenderer.css +14 -0
- package/build/esm/components/pages/AIStudioChat/McpToolRenderer.d.ts +5 -0
- package/build/esm/components/pages/AIStudioChat/McpToolRenderer.js +18 -0
- package/build/esm/components/pages/AIStudioChat/McpToolRenderer.js.map +1 -0
- package/build/esm/components/pages/AIStudioChat/i18n/en.json +4 -0
- package/build/esm/components/pages/AIStudioChat/i18n/index.d.ts +13 -0
- package/build/esm/components/pages/AIStudioChat/i18n/index.js +6 -0
- package/build/esm/components/pages/AIStudioChat/i18n/index.js.map +1 -0
- package/build/esm/components/pages/AIStudioChat/i18n/ru.json +4 -0
- package/build/esm/package.json +1 -1
- package/build/esm/types/messages.d.ts +6 -1
- package/build/esm/types/messages.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { prettyPrintJson } from "./prettyPrintJson.js";
|
|
1
2
|
function pushBlocksForMessage(msg, blocks) {
|
|
2
3
|
var _a;
|
|
3
4
|
for (const part of (_a = msg.content) !== null && _a !== void 0 ? _a : []) {
|
|
@@ -39,10 +40,12 @@ function pushBlocksForMcpCall(mcp, blocks) {
|
|
|
39
40
|
else if (typeof mcp.output === 'string' && mcp.output.length > 0) {
|
|
40
41
|
bodyText = mcp.output;
|
|
41
42
|
}
|
|
43
|
+
const mcpRequest = prettyPrintJson(mcp.arguments);
|
|
44
|
+
const mcpResponse = prettyPrintJson(bodyText);
|
|
42
45
|
blocks.push({
|
|
43
46
|
type: 'tool',
|
|
44
47
|
id: mcp.id,
|
|
45
|
-
data: Object.assign({ toolName: (_d = (_c = mcp.name) !== null && _c !== void 0 ? _c : mcp.server_label) !== null && _d !== void 0 ? _d : 'MCP', status }, (bodyText ? { bodyContent: bodyText } : {})),
|
|
48
|
+
data: Object.assign(Object.assign(Object.assign({ toolName: (_d = (_c = mcp.name) !== null && _c !== void 0 ? _c : mcp.server_label) !== null && _d !== void 0 ? _d : 'MCP', status }, (bodyText ? { bodyContent: bodyText } : {})), (mcpRequest ? { mcpRequest } : {})), (mcpResponse ? { mcpResponse } : {})),
|
|
46
49
|
});
|
|
47
50
|
}
|
|
48
51
|
function pushBlocksForItem(item, blocks) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapOutputToContent.js","sourceRoot":"../../../../../src","sources":["adapters/openai/helpers/mapOutputToContent.ts"],"names":[],"mappings":"AASA,SAAS,oBAAoB,CACzB,GAAgC,EAChC,MAA8B;;IAE9B,KAAK,MAAM,IAAI,IAAI,MAAA,GAAG,CAAC,OAAO,mCAAI,EAAE,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAC,EAAC,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAC,EAAC,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC;AACL,CAAC;AAED,SAAS,sBAAsB,CAC3B,SAAsC,EACtC,MAA8B;;IAE9B,MAAM,OAAO,GACT,MAAA,MAAA,MAAA,SAAS,CAAC,OAAO,0CAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,mCAAI,MAAA,SAAS,CAAC,OAAO,0CAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,mCAAI,EAAE,CAAC;IACzF,MAAM,CAAC,IAAI,iCACJ,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAC,EAAE,EAAE,SAAS,CAAC,EAAE,EAAC,CAAC,KAChD,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE;YACF,OAAO,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAA,OAAO,CAAC,CAAC,CAAC,mCAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO;YAC3D,MAAM,EAAE,SAAS;YACjB,eAAe,EAAE,KAAK;SACzB,IACH,CAAC;AACP,CAAC;AAED,SAAS,yBAAyB,CAC9B,EAAkC,EAClC,MAA8B;IAE9B,MAAM,CAAC,IAAI,CAAC;QACR,IAAI,EAAE,MAAM;QACZ,EAAE,EAAE,EAAE,CAAC,OAAO;QACd,IAAI,EAAE,EAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAC;KAC/C,CAAC,CAAC;AACP,CAAC;AAED,SAAS,oBAAoB,CACzB,GAA8B,EAC9B,MAA8B;;IAE9B,MAAM,iBAAiB,GAAoD;QACvE,SAAS,EAAE,SAAS;QACpB,MAAM,EAAE,OAAO;KAClB,CAAC;IACF,MAAM,MAAM,GAAG,MAAA,iBAAiB,CAAC,MAAA,GAAG,CAAC,MAAM,mCAAI,EAAE,CAAC,mCAAI,SAAS,CAAC;IAChE,IAAI,QAA4B,CAAC;IACjC,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC;IACzB,CAAC;SAAM,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjE,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC;IAC1B,CAAC;IACD,MAAM,CAAC,IAAI,CAAC;QACR,IAAI,EAAE,MAAM;QACZ,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,
|
|
1
|
+
{"version":3,"file":"mapOutputToContent.js","sourceRoot":"../../../../../src","sources":["adapters/openai/helpers/mapOutputToContent.ts"],"names":[],"mappings":"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","sourcesContent":["import type {TAssistantMessage, TMessageContentUnion} from '../../../types';\nimport {\n OpenAIResponseFunctionToolCall,\n OpenAIResponseMcpCallLike,\n OpenAIResponseOutputItem,\n OpenAIResponseOutputMessage,\n OpenAIResponseReasoningItem,\n} from '../types/openAiTypes';\n\nimport {prettyPrintJson} from './prettyPrintJson';\n\nfunction pushBlocksForMessage(\n msg: OpenAIResponseOutputMessage,\n blocks: TMessageContentUnion[],\n): void {\n for (const part of msg.content ?? []) {\n if (part.type === 'output_text') {\n blocks.push({type: 'text', data: {text: part.text}});\n }\n if (part.type === 'refusal') {\n blocks.push({type: 'text', data: {text: part.refusal}});\n }\n }\n}\n\nfunction pushBlocksForReasoning(\n reasoning: OpenAIResponseReasoningItem,\n blocks: TMessageContentUnion[],\n): void {\n const content =\n reasoning.content?.map((c) => c.text) ?? reasoning.summary?.map((s) => s.text) ?? [];\n blocks.push({\n ...(Boolean(reasoning.id) && {id: reasoning.id}),\n type: 'thinking',\n data: {\n content: content.length <= 1 ? (content[0] ?? '') : content,\n status: 'thought',\n defaultExpanded: false,\n },\n });\n}\n\nfunction pushBlocksForFunctionCall(\n fn: OpenAIResponseFunctionToolCall,\n blocks: TMessageContentUnion[],\n): void {\n blocks.push({\n type: 'tool',\n id: fn.call_id,\n data: {toolName: fn.name, status: 'loading'},\n });\n}\n\nfunction pushBlocksForMcpCall(\n mcp: OpenAIResponseMcpCallLike,\n blocks: TMessageContentUnion[],\n): void {\n const statusByMcpStatus: Record<string, 'success' | 'error' | 'loading'> = {\n completed: 'success',\n failed: 'error',\n };\n const status = statusByMcpStatus[mcp.status ?? ''] ?? 'loading';\n let bodyText: string | undefined;\n if (typeof mcp.error === 'string' && mcp.error.length > 0) {\n bodyText = mcp.error;\n } else if (typeof mcp.output === 'string' && mcp.output.length > 0) {\n bodyText = mcp.output;\n }\n const mcpRequest = prettyPrintJson(mcp.arguments);\n const mcpResponse = prettyPrintJson(bodyText);\n blocks.push({\n type: 'tool',\n id: mcp.id,\n data: {\n toolName: mcp.name ?? mcp.server_label ?? 'MCP',\n status,\n ...(bodyText ? {bodyContent: bodyText} : {}),\n ...(mcpRequest ? {mcpRequest} : {}),\n ...(mcpResponse ? {mcpResponse} : {}),\n },\n });\n}\n\nfunction pushBlocksForItem(item: OpenAIResponseOutputItem, blocks: TMessageContentUnion[]): void {\n if (item.type === 'message' && 'role' in item && item.role === 'assistant') {\n pushBlocksForMessage(item as OpenAIResponseOutputMessage, blocks);\n return;\n }\n if (item.type === 'reasoning') {\n pushBlocksForReasoning(item as OpenAIResponseReasoningItem, blocks);\n return;\n }\n if (item.type === 'function_call') {\n pushBlocksForFunctionCall(item as OpenAIResponseFunctionToolCall, blocks);\n return;\n }\n if (item.type === 'mcp_call') {\n pushBlocksForMcpCall(item as OpenAIResponseMcpCallLike, blocks);\n }\n}\n\n/** OpenAI response output (flat array of message/reasoning/function_call) → TAssistantMessage content. */\n\nexport function mapOutputToContent(\n output: OpenAIResponseOutputItem[] | null | undefined,\n): TAssistantMessage['content'] {\n const blocks: TMessageContentUnion[] = [];\n for (const item of output ?? []) {\n pushBlocksForItem(item, blocks);\n }\n if (blocks.length === 0) return '';\n if (blocks.length === 1 && blocks[0].type === 'text') return blocks[0].data.text;\n return blocks;\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pretty-print a string that may contain JSON. Falls back to the original string
|
|
3
|
+
* if it doesn't parse as JSON, so non-JSON payloads render unchanged.
|
|
4
|
+
*/
|
|
5
|
+
export function prettyPrintJson(s) {
|
|
6
|
+
if (!s)
|
|
7
|
+
return undefined;
|
|
8
|
+
try {
|
|
9
|
+
return JSON.stringify(JSON.parse(s), null, 2);
|
|
10
|
+
}
|
|
11
|
+
catch (_a) {
|
|
12
|
+
return s;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=prettyPrintJson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prettyPrintJson.js","sourceRoot":"../../../../../src","sources":["adapters/openai/helpers/prettyPrintJson.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,CAAqB;IACjD,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,WAAM,CAAC;QACL,OAAO,CAAC,CAAC;IACb,CAAC;AACL,CAAC","sourcesContent":["/**\n * Pretty-print a string that may contain JSON. Falls back to the original string\n * if it doesn't parse as JSON, so non-JSON payloads render unchanged.\n */\nexport function prettyPrintJson(s: string | undefined): string | undefined {\n if (!s) return undefined;\n try {\n return JSON.stringify(JSON.parse(s), null, 2);\n } catch {\n return s;\n }\n}\n"]}
|
|
@@ -1,8 +1,87 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
1
2
|
@import '@diplodoc/transform/dist/css/yfm.css';
|
|
3
|
+
/**
|
|
4
|
+
* YFM theming.
|
|
5
|
+
*
|
|
6
|
+
* @diplodoc/transform ships a single (light) set of `--yfm-color-*` values.
|
|
7
|
+
* Here we re-map them onto Gravity UI tokens (`--g-color-*`) so the markdown
|
|
8
|
+
* content follows the active Gravity theme (`.g-root_theme_light` /
|
|
9
|
+
* `.g-root_theme_dark`) automatically — no dedicated dark-theme block needed.
|
|
10
|
+
*/
|
|
11
|
+
.yfm {
|
|
12
|
+
--yfm-color-base: var(--g-color-base-background);
|
|
13
|
+
--yfm-color-text: var(--g-color-text-primary);
|
|
14
|
+
--yfm-color-link: var(--g-color-text-link);
|
|
15
|
+
--yfm-color-link-hover: var(--g-color-text-link-hover);
|
|
16
|
+
--yfm-color-border: var(--g-color-line-generic);
|
|
17
|
+
--yfm-color-accent: var(--g-color-base-brand);
|
|
18
|
+
--yfm-color-inline-code: var(--g-color-text-misc);
|
|
19
|
+
--yfm-color-inline-code-background: var(--g-color-base-misc-light);
|
|
20
|
+
--yfm-color-code-background: var(--g-color-base-misc-light);
|
|
21
|
+
--yfm-color-code-hovered-background: var(--g-color-base-misc-light-hover);
|
|
22
|
+
--yfm-color-hljs-background: var(--g-color-base-generic);
|
|
23
|
+
--yfm-color-hljs-subst: var(--g-color-text-primary);
|
|
24
|
+
--yfm-color-hljs-comment: var(--g-color-text-hint);
|
|
25
|
+
--yfm-color-hljs-section: var(--g-color-text-info-heavy);
|
|
26
|
+
--yfm-color-hljs-deletion: var(--g-color-text-positive);
|
|
27
|
+
--yfm-color-hljs-addition: var(--g-color-text-positive);
|
|
28
|
+
--yfm-color-hljs-literal: var(--g-color-text-warning);
|
|
29
|
+
--yfm-color-hljs-pseudo: var(--g-color-text-utility);
|
|
30
|
+
--yfm-color-hljs-meta: var(--g-color-text-info);
|
|
31
|
+
--yfm-color-hljs-meta-string: var(--g-color-text-positive);
|
|
32
|
+
--yfm-color-note-tip: var(--g-color-text-positive);
|
|
33
|
+
--yfm-color-note-tip-background: var(--g-color-base-positive-light);
|
|
34
|
+
--yfm-color-note-info: var(--g-color-text-info);
|
|
35
|
+
--yfm-color-note-info-background: var(--g-color-base-info-light);
|
|
36
|
+
--yfm-color-note-warning: var(--g-color-text-warning);
|
|
37
|
+
--yfm-color-note-warning-background: var(--g-color-base-warning-light);
|
|
38
|
+
--yfm-color-note-important: var(--g-color-text-danger);
|
|
39
|
+
--yfm-color-note-important-background: var(--g-color-base-danger-light);
|
|
40
|
+
--yfm-color-table: var(--g-color-text-primary);
|
|
41
|
+
--yfm-color-table-border: var(--g-color-line-generic);
|
|
42
|
+
--yfm-color-table-background: var(--g-color-base-background);
|
|
43
|
+
--yfm-color-table-row-background: var(--g-color-base-generic);
|
|
44
|
+
color: var(--g-color-text-primary);
|
|
45
|
+
}
|
|
46
|
+
.yfm a {
|
|
47
|
+
color: var(--g-color-text-link);
|
|
48
|
+
text-decoration: none;
|
|
49
|
+
border-radius: var(--g-focus-border-radius);
|
|
50
|
+
}
|
|
51
|
+
.yfm a:hover {
|
|
52
|
+
color: var(--g-color-text-link-hover);
|
|
53
|
+
}
|
|
54
|
+
.yfm a:focus-visible {
|
|
55
|
+
outline: 2px solid var(--g-color-line-focus);
|
|
56
|
+
}
|
|
57
|
+
.yfm b,
|
|
58
|
+
.yfm strong {
|
|
59
|
+
font-weight: var(--g-text-accent-font-weight);
|
|
60
|
+
}
|
|
61
|
+
.yfm hr {
|
|
62
|
+
background-color: var(--g-color-base-background);
|
|
63
|
+
}
|
|
64
|
+
.yfm blockquote {
|
|
65
|
+
border-left-color: var(--g-color-base-brand);
|
|
66
|
+
}
|
|
67
|
+
.yfm code {
|
|
68
|
+
background: var(--g-color-base-misc-light);
|
|
69
|
+
color: var(--g-color-text-misc);
|
|
70
|
+
}
|
|
71
|
+
.yfm .yfm-note {
|
|
72
|
+
background-color: var(--g-color-base-float);
|
|
73
|
+
border-color: var(--g-color-line-generic);
|
|
74
|
+
}
|
|
75
|
+
.yfm .yfm-tab.active {
|
|
76
|
+
border-bottom-color: var(--g-color-base-brand);
|
|
77
|
+
}
|
|
78
|
+
.yfm a.yfm-anchor {
|
|
79
|
+
display: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
2
82
|
.g-aikit-markdown-renderer {
|
|
3
83
|
max-width: 100%;
|
|
4
84
|
overflow-x: auto;
|
|
5
|
-
color: var(--g-color-text-primary);
|
|
6
85
|
/* Tables inside message wrappers: reset inherited word-break; scroll on this root when wide */
|
|
7
86
|
}
|
|
8
87
|
.g-aikit-markdown-renderer table {
|
|
@@ -4,8 +4,10 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
4
4
|
import { v4 as uuidv4 } from 'uuid';
|
|
5
5
|
import { fetchResponseToStreamEvents, useOpenAIStreamAdapter } from "../../../adapters/openai/index.js";
|
|
6
6
|
import { BaseMessageActionType } from "../../../types/index.js";
|
|
7
|
+
import { createMessageRendererRegistry, mergeMessageRendererRegistries, registerMessageRenderer, } from "../../../utils/messageTypeRegistry.js";
|
|
7
8
|
import { InputContextProvider, useInputContext } from "../../molecules/InputContext/index.js";
|
|
8
9
|
import { ChatContainer } from "../ChatContainer/index.js";
|
|
10
|
+
import { McpToolRenderer } from "./McpToolRenderer.js";
|
|
9
11
|
import { normalizeMcpCallIds, omitMcpListToolsEvents } from "./transforms/index.js";
|
|
10
12
|
function isFileAttachment(value) {
|
|
11
13
|
if (!value || typeof value !== 'object')
|
|
@@ -312,15 +314,26 @@ function AIStudioChatInner(props) {
|
|
|
312
314
|
}
|
|
313
315
|
}, []);
|
|
314
316
|
/**
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
317
|
+
* Build the final messageListConfig:
|
|
318
|
+
* - Wrap consumer-provided Like/Dislike actions so the library toggles `userRating`
|
|
319
|
+
* automatically before delegating to the original `onClick`. Other actions and
|
|
320
|
+
* non-default (ReactNode) entries pass through unchanged.
|
|
321
|
+
* - Inject a custom 'tool' renderer that renders MCP request/response sections when
|
|
322
|
+
* `mcpRequest`/`mcpResponse` are present in the tool content. A consumer-provided
|
|
323
|
+
* `messageRendererRegistry` wins on overlap.
|
|
318
324
|
*/
|
|
319
325
|
const messageListConfig = useMemo(() => {
|
|
326
|
+
var _a;
|
|
320
327
|
const original = chatContainerProps.messageListConfig;
|
|
328
|
+
const baseRegistry = createMessageRendererRegistry();
|
|
329
|
+
registerMessageRenderer(baseRegistry, 'tool', {
|
|
330
|
+
component: McpToolRenderer,
|
|
331
|
+
});
|
|
332
|
+
const messageRendererRegistry = mergeMessageRendererRegistries(baseRegistry, (_a = original === null || original === void 0 ? void 0 : original.messageRendererRegistry) !== null && _a !== void 0 ? _a : {});
|
|
321
333
|
const originalAssistantActions = original === null || original === void 0 ? void 0 : original.assistantActions;
|
|
322
|
-
if (!originalAssistantActions)
|
|
323
|
-
return original;
|
|
334
|
+
if (!originalAssistantActions) {
|
|
335
|
+
return Object.assign(Object.assign({}, original), { messageRendererRegistry });
|
|
336
|
+
}
|
|
324
337
|
const wrappedAssistantActions = originalAssistantActions.map((action) => {
|
|
325
338
|
const typed = action;
|
|
326
339
|
const isLike = typed.type === BaseMessageActionType.Like;
|
|
@@ -337,7 +350,7 @@ function AIStudioChatInner(props) {
|
|
|
337
350
|
originalOnClick(message);
|
|
338
351
|
} });
|
|
339
352
|
});
|
|
340
|
-
return Object.assign(Object.assign({}, original), { assistantActions: wrappedAssistantActions });
|
|
353
|
+
return Object.assign(Object.assign({}, original), { assistantActions: wrappedAssistantActions, messageRendererRegistry });
|
|
341
354
|
}, [chatContainerProps.messageListConfig, setUserRating]);
|
|
342
355
|
return (_jsx(ChatContainer, Object.assign({}, chatContainerProps, { messageListConfig: messageListConfig, messages: displayMessages, status: status, error: streamResult.error, onSendMessage: handleSendMessage, onCancel: handleCancel, onRetry: handleRetry, chats: showHistory ? chats : undefined, activeChat: showHistory ? activeChat : undefined, onSelectChat: showHistory ? handleSelectChat : undefined, onCreateChat: showHistory ? handleCreateChat : undefined, onDeleteChat: showHistory ? handleDeleteChat : undefined, showHistory: showHistory, showNewChat: showNewChat, promptInputProps: Object.assign(Object.assign({}, chatContainerProps.promptInputProps), { view: 'full', headerProps: Object.assign(Object.assign({}, (_c = chatContainerProps.promptInputProps) === null || _c === void 0 ? void 0 : _c.headerProps), { contextItems: (_f = (_e = (_d = chatContainerProps.promptInputProps) === null || _d === void 0 ? void 0 : _d.headerProps) === null || _e === void 0 ? void 0 : _e.contextItems) !== null && _f !== void 0 ? _f : contextItems }), footerProps: Object.assign(Object.assign({}, (_g = chatContainerProps.promptInputProps) === null || _g === void 0 ? void 0 : _g.footerProps), { attachmentContent: (_k = (_j = (_h = chatContainerProps.promptInputProps) === null || _h === void 0 ? void 0 : _h.footerProps) === null || _j === void 0 ? void 0 : _j.attachmentContent) !== null && _k !== void 0 ? _k : attachmentContent }) }) })));
|
|
343
356
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AIStudioChat.js","sourceRoot":"../../../../../src","sources":["components/pages/AIStudioChat/AIStudioChat.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useCallback, useEffect, useMemo, useRef, useState} from 'react';\n\nimport {v4 as uuidv4} from 'uuid';\n\nimport {fetchResponseToStreamEvents, useOpenAIStreamAdapter} from '../../../adapters/openai';\nimport type {OpenAIStreamSource} from '../../../adapters/openai';\nimport {BaseMessageActionType} from '../../../types';\nimport type {\n ChatStatus,\n ChatType,\n DefaultMessageAction,\n FileAttachment,\n TAssistantMessage,\n TChatMessage,\n TSubmitData,\n TUserMessage,\n UserRating,\n} from '../../../types';\nimport {InputContextProvider, useInputContext} from '../../molecules/InputContext';\nimport type {MessageListConfig} from '../ChatContainer';\nimport {ChatContainer} from '../ChatContainer';\n\nimport {normalizeMcpCallIds, omitMcpListToolsEvents} from './transforms';\nimport type {AIStudioChatProps} from './types';\n\nfunction isFileAttachment(value: unknown): value is FileAttachment {\n if (!value || typeof value !== 'object') return false;\n const v = value as Record<string, unknown>;\n return typeof v.id === 'string' && typeof v.name === 'string';\n}\n\nfunction resolveFileAttachments(\n attachments: FileAttachment[] | undefined,\n fileIds: string[] | undefined,\n): FileAttachment[] | undefined {\n if (attachments && attachments.length > 0) return attachments;\n if (fileIds && fileIds.length > 0) return fileIds.map((id) => ({id, name: id}));\n return undefined;\n}\n\ntype ApiMessageContentPart =\n | {type: 'text'; text: string}\n | {type: 'image_url'; image_url: {url: string}};\n\ntype ApiMessage = {\n role: 'user' | 'assistant' | 'system';\n content: string | ApiMessageContentPart[];\n};\n\ntype StreamOptions = {\n initialMessages: TChatMessage[];\n assistantMessageId: string;\n};\n\n/**\n * Extracts plain text content from any TChatMessage variant.\n */\nfunction getMessageTextContent(message: TChatMessage): string {\n if (message.role === 'user') {\n return typeof message.content === 'string' ? message.content : '';\n }\n\n const {content} = message as TAssistantMessage;\n\n if (typeof content === 'string') {\n return content;\n }\n\n if (Array.isArray(content)) {\n return content\n .map((item) => {\n if (typeof item === 'string') return item;\n if (item.type === 'text' && item.data?.text) return item.data.text;\n return '';\n })\n .join('\\n');\n }\n\n if (content && typeof content === 'object' && 'type' in content) {\n if (content.type === 'text' && content.data?.text) {\n return content.data.text;\n }\n }\n\n return '';\n}\n\n/**\n * Derives a human-readable chat name from the first user message.\n */\nfunction deriveChatName(content: string): string {\n const trimmed = content.trim();\n return trimmed.length > 40 ? `${trimmed.slice(0, 40)}...` : trimmed || 'New chat';\n}\n\ntype AIStudioChatInnerProps = Omit<AIStudioChatProps, 'fileUpload' | 'fileDialogTitle'>;\n\n/**\n * AIStudioChat - a ready-to-use chat component with built-in OpenAI streaming support.\n *\n * Wraps ChatContainer and handles all state internally: streaming, message history,\n * multi-chat management, and cancellation. Requires only an `apiUrl` to start working.\n *\n * @param props - component props\n * @returns React component\n */\nexport function AIStudioChat(props: AIStudioChatProps) {\n const {fileUpload, fileDialogTitle, ...rest} = props;\n return (\n <InputContextProvider fileUpload={fileUpload} fileDialogTitle={fileDialogTitle}>\n <AIStudioChatInner {...rest} />\n </InputContextProvider>\n );\n}\n\nfunction AIStudioChatInner(props: AIStudioChatInnerProps) {\n const {\n apiUrl,\n initialMessages = [],\n showHistory = false,\n showNewChat = showHistory,\n systemPrompt,\n requestInit,\n extraRequestParams,\n trackTokenUsage = true,\n onBeforeSend,\n ...chatContainerProps\n } = props;\n\n const {prepareFilesForSend, reset, contextItems, attachmentContent} = useInputContext();\n\n // Current chat messages\n const [messages, setMessages] = useState<TChatMessage[]>(initialMessages);\n\n // Multi-chat state (used when showHistory=true)\n const [chats, setChats] = useState<ChatType[]>([]);\n const [activeChat, setActiveChat] = useState<ChatType | null>(null);\n\n // Per-chat message store (ref to avoid unnecessary re-renders on switch)\n const chatMessagesRef = useRef<Record<string, TChatMessage[]>>({});\n\n // Always-current reference to activeChat for use inside async callbacks\n // (intentionally mutable ref — not a forgotten dependency)\n const activeChatRef = useRef<ChatType | null>(null);\n activeChatRef.current = activeChat;\n\n // Tracks the last response id for conversation continuity (previous_response_id)\n const responseIdRef = useRef<string | null>(null);\n\n // Streaming state\n const [controller, setController] = useState<AbortController | null>(null);\n const [isFetching, setIsFetching] = useState(false);\n const [streamSource, setStreamSource] = useState<OpenAIStreamSource | null>(null);\n const [streamOptions, setStreamOptions] = useState<StreamOptions | null>(null);\n\n const handleStreamEnd = useCallback((finalMessages: TChatMessage[]) => {\n const committed = finalMessages.filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n );\n\n setMessages(committed);\n setStreamSource(null);\n setStreamOptions(null);\n\n // Persist messages and update the last message preview in history\n const chat = activeChatRef.current;\n if (chat) {\n chatMessagesRef.current[chat.id] = committed;\n\n const lastMsg = committed[committed.length - 1];\n if (lastMsg) {\n setChats((prev) =>\n prev.map((c) =>\n c.id === chat.id ? {...c, lastMessage: getMessageTextContent(lastMsg)} : c,\n ),\n );\n }\n }\n }, []);\n\n const streamResult = useOpenAIStreamAdapter(streamSource, {\n initialMessages: streamOptions?.initialMessages ?? [],\n assistantMessageId: streamOptions?.assistantMessageId ?? 'assistant-idle',\n onStreamEnd: handleStreamEnd,\n trackTokenUsage,\n });\n\n // Sync latest responseId to ref so next request can use it as previousResponseId\n useEffect(() => {\n if (streamResult.responseId) {\n responseIdRef.current = streamResult.responseId;\n }\n }, [streamResult.responseId]);\n\n const hasSource = Boolean(streamSource);\n\n const displayMessages =\n hasSource && streamResult.messages.length > 0 ? streamResult.messages : messages;\n\n const status = useMemo((): ChatStatus => {\n if (!hasSource) {\n return isFetching ? 'submitted' : 'ready';\n }\n if (streamResult.status === 'streaming') return 'streaming';\n if (streamResult.status === 'error') return 'error';\n return 'ready';\n }, [hasSource, isFetching, streamResult.status]);\n\n /**\n * Core send function. Takes an already-resolved set of previous messages and\n * pre-converted base64 images so it can be called both from handleSendMessage\n * (which converts File objects) and from handleRetry (which reuses stored images).\n */\n const performSend = useCallback(\n async ({\n previousMessages,\n content,\n base64Images = [],\n perSendParams = {},\n }: {\n previousMessages: TChatMessage[];\n content: string;\n base64Images?: string[];\n perSendParams?: Record<string, unknown>;\n }) => {\n // Auto-create a chat when history is enabled and no chat is active yet\n if (showHistory && !activeChatRef.current) {\n const newChat: ChatType = {\n id: uuidv4(),\n name: deriveChatName(content),\n createTime: new Date().toISOString(),\n };\n chatMessagesRef.current[newChat.id] = [];\n activeChatRef.current = newChat;\n setActiveChat(newChat);\n setChats((prev) => [newChat, ...prev]);\n }\n\n const rawFileIds = Array.isArray(perSendParams.fileIds)\n ? (perSendParams.fileIds as string[])\n : undefined;\n const rawFileAttachments = Array.isArray(perSendParams.fileAttachments)\n ? (perSendParams.fileAttachments as unknown[]).filter(isFileAttachment)\n : undefined;\n const userMessage: TUserMessage = {\n id: uuidv4(),\n role: 'user',\n content,\n images: base64Images.length > 0 ? base64Images : undefined,\n fileAttachments: resolveFileAttachments(rawFileAttachments, rawFileIds),\n };\n const messagesWithUser: TChatMessage[] = [...previousMessages, userMessage];\n const assistantMessageId = uuidv4();\n\n setMessages(messagesWithUser);\n setIsFetching(true);\n\n const abortController = new AbortController();\n setController(abortController);\n\n try {\n // Last user message: plain text or multipart (text + images)\n const lastUserContent: ApiMessage['content'] =\n base64Images.length > 0\n ? [\n {type: 'text', text: content},\n ...base64Images.map((url) => ({\n type: 'image_url' as const,\n image_url: {url},\n })),\n ]\n : content;\n\n const apiMessages: ApiMessage[] = [\n ...(systemPrompt ? [{role: 'system' as const, content: systemPrompt}] : []),\n ...previousMessages\n .filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n )\n .map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: getMessageTextContent(msg),\n })),\n {role: 'user' as const, content: lastUserContent},\n ];\n\n const response = await fetch(apiUrl, {\n ...requestInit,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...requestInit?.headers,\n },\n body: JSON.stringify({\n messages: apiMessages,\n ...extraRequestParams,\n ...perSendParams,\n ...(responseIdRef.current\n ? {previousResponseId: responseIdRef.current}\n : {}),\n }),\n signal: abortController.signal,\n });\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n setStreamSource(\n normalizeMcpCallIds(\n omitMcpListToolsEvents(fetchResponseToStreamEvents(response)),\n ),\n );\n setStreamOptions({initialMessages: messagesWithUser, assistantMessageId});\n } catch (error) {\n if ((error as Error).name !== 'AbortError') {\n const errorMessage: TAssistantMessage = {\n id: uuidv4(),\n role: 'assistant',\n content: (error as Error).message,\n };\n setMessages((prev) => {\n const filtered = prev.filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n );\n return [...filtered, errorMessage];\n });\n }\n setStreamSource(null);\n setStreamOptions(null);\n } finally {\n setIsFetching(false);\n setController(null);\n }\n },\n [showHistory, systemPrompt, requestInit, apiUrl, extraRequestParams],\n );\n\n const handleSendMessage = useCallback(\n async (data: TSubmitData) => {\n // Call onBeforeSend hook — allows caller to inject per-request params or cancel send\n let perSendParams: Record<string, unknown> = {};\n if (onBeforeSend) {\n const result = await onBeforeSend({content: data.content});\n if (result === false || result === null) return;\n if (result) perSendParams = result;\n }\n\n const {base64Images, perSendFileParams} = await prepareFilesForSend(data.attachments);\n\n await performSend({\n previousMessages: messages,\n content: data.content,\n base64Images,\n perSendParams: {\n ...perSendParams,\n ...perSendFileParams,\n },\n });\n\n reset();\n },\n [messages, onBeforeSend, performSend, prepareFilesForSend, reset],\n );\n\n const handleCancel = useCallback(async () => {\n controller?.abort();\n setStreamSource(null);\n setStreamOptions(null);\n }, [controller]);\n\n const handleRetry = useCallback(async () => {\n const lastUserMsg = [...messages]\n .reverse()\n .find((m): m is TUserMessage => m.role === 'user');\n if (!lastUserMsg) return;\n\n const lastUserIndex = messages.lastIndexOf(lastUserMsg);\n const trimmedMessages = messages.slice(0, lastUserIndex);\n\n await performSend({\n previousMessages: trimmedMessages,\n content: lastUserMsg.content,\n // Reuse images stored on the original message — no FileReader needed\n base64Images: lastUserMsg.images ?? [],\n });\n }, [messages, performSend]);\n\n const handleCreateChat = useCallback(() => {\n const current = activeChatRef.current;\n if (current) {\n chatMessagesRef.current[current.id] = messages;\n }\n\n responseIdRef.current = null;\n\n const newChat: ChatType = {\n id: uuidv4(),\n name: 'New chat',\n createTime: new Date().toISOString(),\n };\n chatMessagesRef.current[newChat.id] = [];\n setChats((prev) => [newChat, ...prev]);\n setActiveChat(newChat);\n setMessages([]);\n reset();\n }, [messages, reset]);\n\n const handleSelectChat = useCallback(\n (chat: ChatType) => {\n const current = activeChatRef.current;\n if (current) {\n chatMessagesRef.current[current.id] = messages;\n }\n\n responseIdRef.current = null;\n setActiveChat(chat);\n setMessages(chatMessagesRef.current[chat.id] ?? []);\n reset();\n },\n [messages, reset],\n );\n\n const handleDeleteChat = useCallback(\n async (chat: ChatType) => {\n delete chatMessagesRef.current[chat.id];\n setChats((prev) => prev.filter((c) => c.id !== chat.id));\n\n if (activeChatRef.current?.id === chat.id) {\n responseIdRef.current = null;\n setActiveChat(null);\n setMessages([]);\n reset();\n }\n },\n [reset],\n );\n\n /**\n * Update `userRating` on an assistant message inside the internal store.\n * Mirrors the change into the per-chat history map so it survives chat switches.\n */\n const setUserRating = useCallback((messageId: string, rating: UserRating | undefined) => {\n const updateRating = (msgs: TChatMessage[]): TChatMessage[] =>\n msgs.map((msg) =>\n msg.role === 'assistant' && msg.id === messageId\n ? {...msg, userRating: rating}\n : msg,\n );\n\n setMessages(updateRating);\n\n const chat = activeChatRef.current;\n if (chat && chatMessagesRef.current[chat.id]) {\n chatMessagesRef.current[chat.id] = updateRating(chatMessagesRef.current[chat.id]);\n }\n }, []);\n\n /**\n * Wrap consumer-provided Like/Unlike actions so the library toggles `userRating`\n * automatically before delegating to the original `onClick`. Other actions and\n * non-default (ReactNode) entries pass through unchanged.\n */\n const messageListConfig = useMemo<MessageListConfig | undefined>(() => {\n const original = chatContainerProps.messageListConfig;\n const originalAssistantActions = original?.assistantActions;\n if (!originalAssistantActions) return original;\n\n const wrappedAssistantActions = originalAssistantActions.map((action) => {\n const typed = action as DefaultMessageAction<TAssistantMessage>;\n const isLike = typed.type === BaseMessageActionType.Like;\n const isDislike = typed.type === BaseMessageActionType.Dislike;\n if (!isLike && !isDislike) return action;\n\n const targetRating: UserRating = isLike ? 'like' : 'dislike';\n const originalOnClick = typed.onClick;\n\n return {\n ...typed,\n onClick: (message: TAssistantMessage) => {\n if (message.id) {\n const nextRating =\n message.userRating === targetRating ? undefined : targetRating;\n setUserRating(message.id, nextRating);\n }\n originalOnClick(message);\n },\n };\n });\n\n return {\n ...original,\n assistantActions: wrappedAssistantActions,\n };\n }, [chatContainerProps.messageListConfig, setUserRating]);\n\n return (\n <ChatContainer\n {...chatContainerProps}\n messageListConfig={messageListConfig}\n messages={displayMessages}\n status={status}\n error={streamResult.error}\n onSendMessage={handleSendMessage}\n onCancel={handleCancel}\n onRetry={handleRetry}\n chats={showHistory ? chats : undefined}\n activeChat={showHistory ? activeChat : undefined}\n onSelectChat={showHistory ? handleSelectChat : undefined}\n onCreateChat={showHistory ? handleCreateChat : undefined}\n onDeleteChat={showHistory ? handleDeleteChat : undefined}\n showHistory={showHistory}\n showNewChat={showNewChat}\n promptInputProps={{\n ...chatContainerProps.promptInputProps,\n view: 'full',\n headerProps: {\n ...chatContainerProps.promptInputProps?.headerProps,\n contextItems:\n chatContainerProps.promptInputProps?.headerProps?.contextItems ??\n contextItems,\n },\n footerProps: {\n ...chatContainerProps.promptInputProps?.footerProps,\n attachmentContent:\n chatContainerProps.promptInputProps?.footerProps?.attachmentContent ??\n attachmentContent,\n },\n }}\n />\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AIStudioChat.js","sourceRoot":"../../../../../src","sources":["components/pages/AIStudioChat/AIStudioChat.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useCallback, useEffect, useMemo, useRef, useState} from 'react';\n\nimport {v4 as uuidv4} from 'uuid';\n\nimport {fetchResponseToStreamEvents, useOpenAIStreamAdapter} from '../../../adapters/openai';\nimport type {OpenAIStreamSource} from '../../../adapters/openai';\nimport {BaseMessageActionType} from '../../../types';\nimport type {\n ChatStatus,\n ChatType,\n DefaultMessageAction,\n FileAttachment,\n TAssistantMessage,\n TChatMessage,\n TSubmitData,\n TUserMessage,\n UserRating,\n} from '../../../types';\nimport type {ToolMessageContent} from '../../../types/messages';\nimport {\n createMessageRendererRegistry,\n mergeMessageRendererRegistries,\n registerMessageRenderer,\n} from '../../../utils/messageTypeRegistry';\nimport {InputContextProvider, useInputContext} from '../../molecules/InputContext';\nimport type {MessageListConfig} from '../ChatContainer';\nimport {ChatContainer} from '../ChatContainer';\n\nimport {McpToolRenderer} from './McpToolRenderer';\nimport {normalizeMcpCallIds, omitMcpListToolsEvents} from './transforms';\nimport type {AIStudioChatProps} from './types';\n\nfunction isFileAttachment(value: unknown): value is FileAttachment {\n if (!value || typeof value !== 'object') return false;\n const v = value as Record<string, unknown>;\n return typeof v.id === 'string' && typeof v.name === 'string';\n}\n\nfunction resolveFileAttachments(\n attachments: FileAttachment[] | undefined,\n fileIds: string[] | undefined,\n): FileAttachment[] | undefined {\n if (attachments && attachments.length > 0) return attachments;\n if (fileIds && fileIds.length > 0) return fileIds.map((id) => ({id, name: id}));\n return undefined;\n}\n\ntype ApiMessageContentPart =\n | {type: 'text'; text: string}\n | {type: 'image_url'; image_url: {url: string}};\n\ntype ApiMessage = {\n role: 'user' | 'assistant' | 'system';\n content: string | ApiMessageContentPart[];\n};\n\ntype StreamOptions = {\n initialMessages: TChatMessage[];\n assistantMessageId: string;\n};\n\n/**\n * Extracts plain text content from any TChatMessage variant.\n */\nfunction getMessageTextContent(message: TChatMessage): string {\n if (message.role === 'user') {\n return typeof message.content === 'string' ? message.content : '';\n }\n\n const {content} = message as TAssistantMessage;\n\n if (typeof content === 'string') {\n return content;\n }\n\n if (Array.isArray(content)) {\n return content\n .map((item) => {\n if (typeof item === 'string') return item;\n if (item.type === 'text' && item.data?.text) return item.data.text;\n return '';\n })\n .join('\\n');\n }\n\n if (content && typeof content === 'object' && 'type' in content) {\n if (content.type === 'text' && content.data?.text) {\n return content.data.text;\n }\n }\n\n return '';\n}\n\n/**\n * Derives a human-readable chat name from the first user message.\n */\nfunction deriveChatName(content: string): string {\n const trimmed = content.trim();\n return trimmed.length > 40 ? `${trimmed.slice(0, 40)}...` : trimmed || 'New chat';\n}\n\ntype AIStudioChatInnerProps = Omit<AIStudioChatProps, 'fileUpload' | 'fileDialogTitle'>;\n\n/**\n * AIStudioChat - a ready-to-use chat component with built-in OpenAI streaming support.\n *\n * Wraps ChatContainer and handles all state internally: streaming, message history,\n * multi-chat management, and cancellation. Requires only an `apiUrl` to start working.\n *\n * @param props - component props\n * @returns React component\n */\nexport function AIStudioChat(props: AIStudioChatProps) {\n const {fileUpload, fileDialogTitle, ...rest} = props;\n return (\n <InputContextProvider fileUpload={fileUpload} fileDialogTitle={fileDialogTitle}>\n <AIStudioChatInner {...rest} />\n </InputContextProvider>\n );\n}\n\nfunction AIStudioChatInner(props: AIStudioChatInnerProps) {\n const {\n apiUrl,\n initialMessages = [],\n showHistory = false,\n showNewChat = showHistory,\n systemPrompt,\n requestInit,\n extraRequestParams,\n trackTokenUsage = true,\n onBeforeSend,\n ...chatContainerProps\n } = props;\n\n const {prepareFilesForSend, reset, contextItems, attachmentContent} = useInputContext();\n\n // Current chat messages\n const [messages, setMessages] = useState<TChatMessage[]>(initialMessages);\n\n // Multi-chat state (used when showHistory=true)\n const [chats, setChats] = useState<ChatType[]>([]);\n const [activeChat, setActiveChat] = useState<ChatType | null>(null);\n\n // Per-chat message store (ref to avoid unnecessary re-renders on switch)\n const chatMessagesRef = useRef<Record<string, TChatMessage[]>>({});\n\n // Always-current reference to activeChat for use inside async callbacks\n // (intentionally mutable ref — not a forgotten dependency)\n const activeChatRef = useRef<ChatType | null>(null);\n activeChatRef.current = activeChat;\n\n // Tracks the last response id for conversation continuity (previous_response_id)\n const responseIdRef = useRef<string | null>(null);\n\n // Streaming state\n const [controller, setController] = useState<AbortController | null>(null);\n const [isFetching, setIsFetching] = useState(false);\n const [streamSource, setStreamSource] = useState<OpenAIStreamSource | null>(null);\n const [streamOptions, setStreamOptions] = useState<StreamOptions | null>(null);\n\n const handleStreamEnd = useCallback((finalMessages: TChatMessage[]) => {\n const committed = finalMessages.filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n );\n\n setMessages(committed);\n setStreamSource(null);\n setStreamOptions(null);\n\n // Persist messages and update the last message preview in history\n const chat = activeChatRef.current;\n if (chat) {\n chatMessagesRef.current[chat.id] = committed;\n\n const lastMsg = committed[committed.length - 1];\n if (lastMsg) {\n setChats((prev) =>\n prev.map((c) =>\n c.id === chat.id ? {...c, lastMessage: getMessageTextContent(lastMsg)} : c,\n ),\n );\n }\n }\n }, []);\n\n const streamResult = useOpenAIStreamAdapter(streamSource, {\n initialMessages: streamOptions?.initialMessages ?? [],\n assistantMessageId: streamOptions?.assistantMessageId ?? 'assistant-idle',\n onStreamEnd: handleStreamEnd,\n trackTokenUsage,\n });\n\n // Sync latest responseId to ref so next request can use it as previousResponseId\n useEffect(() => {\n if (streamResult.responseId) {\n responseIdRef.current = streamResult.responseId;\n }\n }, [streamResult.responseId]);\n\n const hasSource = Boolean(streamSource);\n\n const displayMessages =\n hasSource && streamResult.messages.length > 0 ? streamResult.messages : messages;\n\n const status = useMemo((): ChatStatus => {\n if (!hasSource) {\n return isFetching ? 'submitted' : 'ready';\n }\n if (streamResult.status === 'streaming') return 'streaming';\n if (streamResult.status === 'error') return 'error';\n return 'ready';\n }, [hasSource, isFetching, streamResult.status]);\n\n /**\n * Core send function. Takes an already-resolved set of previous messages and\n * pre-converted base64 images so it can be called both from handleSendMessage\n * (which converts File objects) and from handleRetry (which reuses stored images).\n */\n const performSend = useCallback(\n async ({\n previousMessages,\n content,\n base64Images = [],\n perSendParams = {},\n }: {\n previousMessages: TChatMessage[];\n content: string;\n base64Images?: string[];\n perSendParams?: Record<string, unknown>;\n }) => {\n // Auto-create a chat when history is enabled and no chat is active yet\n if (showHistory && !activeChatRef.current) {\n const newChat: ChatType = {\n id: uuidv4(),\n name: deriveChatName(content),\n createTime: new Date().toISOString(),\n };\n chatMessagesRef.current[newChat.id] = [];\n activeChatRef.current = newChat;\n setActiveChat(newChat);\n setChats((prev) => [newChat, ...prev]);\n }\n\n const rawFileIds = Array.isArray(perSendParams.fileIds)\n ? (perSendParams.fileIds as string[])\n : undefined;\n const rawFileAttachments = Array.isArray(perSendParams.fileAttachments)\n ? (perSendParams.fileAttachments as unknown[]).filter(isFileAttachment)\n : undefined;\n const userMessage: TUserMessage = {\n id: uuidv4(),\n role: 'user',\n content,\n images: base64Images.length > 0 ? base64Images : undefined,\n fileAttachments: resolveFileAttachments(rawFileAttachments, rawFileIds),\n };\n const messagesWithUser: TChatMessage[] = [...previousMessages, userMessage];\n const assistantMessageId = uuidv4();\n\n setMessages(messagesWithUser);\n setIsFetching(true);\n\n const abortController = new AbortController();\n setController(abortController);\n\n try {\n // Last user message: plain text or multipart (text + images)\n const lastUserContent: ApiMessage['content'] =\n base64Images.length > 0\n ? [\n {type: 'text', text: content},\n ...base64Images.map((url) => ({\n type: 'image_url' as const,\n image_url: {url},\n })),\n ]\n : content;\n\n const apiMessages: ApiMessage[] = [\n ...(systemPrompt ? [{role: 'system' as const, content: systemPrompt}] : []),\n ...previousMessages\n .filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n )\n .map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: getMessageTextContent(msg),\n })),\n {role: 'user' as const, content: lastUserContent},\n ];\n\n const response = await fetch(apiUrl, {\n ...requestInit,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...requestInit?.headers,\n },\n body: JSON.stringify({\n messages: apiMessages,\n ...extraRequestParams,\n ...perSendParams,\n ...(responseIdRef.current\n ? {previousResponseId: responseIdRef.current}\n : {}),\n }),\n signal: abortController.signal,\n });\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n setStreamSource(\n normalizeMcpCallIds(\n omitMcpListToolsEvents(fetchResponseToStreamEvents(response)),\n ),\n );\n setStreamOptions({initialMessages: messagesWithUser, assistantMessageId});\n } catch (error) {\n if ((error as Error).name !== 'AbortError') {\n const errorMessage: TAssistantMessage = {\n id: uuidv4(),\n role: 'assistant',\n content: (error as Error).message,\n };\n setMessages((prev) => {\n const filtered = prev.filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n );\n return [...filtered, errorMessage];\n });\n }\n setStreamSource(null);\n setStreamOptions(null);\n } finally {\n setIsFetching(false);\n setController(null);\n }\n },\n [showHistory, systemPrompt, requestInit, apiUrl, extraRequestParams],\n );\n\n const handleSendMessage = useCallback(\n async (data: TSubmitData) => {\n // Call onBeforeSend hook — allows caller to inject per-request params or cancel send\n let perSendParams: Record<string, unknown> = {};\n if (onBeforeSend) {\n const result = await onBeforeSend({content: data.content});\n if (result === false || result === null) return;\n if (result) perSendParams = result;\n }\n\n const {base64Images, perSendFileParams} = await prepareFilesForSend(data.attachments);\n\n await performSend({\n previousMessages: messages,\n content: data.content,\n base64Images,\n perSendParams: {\n ...perSendParams,\n ...perSendFileParams,\n },\n });\n\n reset();\n },\n [messages, onBeforeSend, performSend, prepareFilesForSend, reset],\n );\n\n const handleCancel = useCallback(async () => {\n controller?.abort();\n setStreamSource(null);\n setStreamOptions(null);\n }, [controller]);\n\n const handleRetry = useCallback(async () => {\n const lastUserMsg = [...messages]\n .reverse()\n .find((m): m is TUserMessage => m.role === 'user');\n if (!lastUserMsg) return;\n\n const lastUserIndex = messages.lastIndexOf(lastUserMsg);\n const trimmedMessages = messages.slice(0, lastUserIndex);\n\n await performSend({\n previousMessages: trimmedMessages,\n content: lastUserMsg.content,\n // Reuse images stored on the original message — no FileReader needed\n base64Images: lastUserMsg.images ?? [],\n });\n }, [messages, performSend]);\n\n const handleCreateChat = useCallback(() => {\n const current = activeChatRef.current;\n if (current) {\n chatMessagesRef.current[current.id] = messages;\n }\n\n responseIdRef.current = null;\n\n const newChat: ChatType = {\n id: uuidv4(),\n name: 'New chat',\n createTime: new Date().toISOString(),\n };\n chatMessagesRef.current[newChat.id] = [];\n setChats((prev) => [newChat, ...prev]);\n setActiveChat(newChat);\n setMessages([]);\n reset();\n }, [messages, reset]);\n\n const handleSelectChat = useCallback(\n (chat: ChatType) => {\n const current = activeChatRef.current;\n if (current) {\n chatMessagesRef.current[current.id] = messages;\n }\n\n responseIdRef.current = null;\n setActiveChat(chat);\n setMessages(chatMessagesRef.current[chat.id] ?? []);\n reset();\n },\n [messages, reset],\n );\n\n const handleDeleteChat = useCallback(\n async (chat: ChatType) => {\n delete chatMessagesRef.current[chat.id];\n setChats((prev) => prev.filter((c) => c.id !== chat.id));\n\n if (activeChatRef.current?.id === chat.id) {\n responseIdRef.current = null;\n setActiveChat(null);\n setMessages([]);\n reset();\n }\n },\n [reset],\n );\n\n /**\n * Update `userRating` on an assistant message inside the internal store.\n * Mirrors the change into the per-chat history map so it survives chat switches.\n */\n const setUserRating = useCallback((messageId: string, rating: UserRating | undefined) => {\n const updateRating = (msgs: TChatMessage[]): TChatMessage[] =>\n msgs.map((msg) =>\n msg.role === 'assistant' && msg.id === messageId\n ? {...msg, userRating: rating}\n : msg,\n );\n\n setMessages(updateRating);\n\n const chat = activeChatRef.current;\n if (chat && chatMessagesRef.current[chat.id]) {\n chatMessagesRef.current[chat.id] = updateRating(chatMessagesRef.current[chat.id]);\n }\n }, []);\n\n /**\n * Build the final messageListConfig:\n * - Wrap consumer-provided Like/Dislike actions so the library toggles `userRating`\n * automatically before delegating to the original `onClick`. Other actions and\n * non-default (ReactNode) entries pass through unchanged.\n * - Inject a custom 'tool' renderer that renders MCP request/response sections when\n * `mcpRequest`/`mcpResponse` are present in the tool content. A consumer-provided\n * `messageRendererRegistry` wins on overlap.\n */\n const messageListConfig = useMemo<MessageListConfig | undefined>(() => {\n const original = chatContainerProps.messageListConfig;\n\n const baseRegistry = createMessageRendererRegistry();\n registerMessageRenderer<ToolMessageContent>(baseRegistry, 'tool', {\n component: McpToolRenderer,\n });\n const messageRendererRegistry = mergeMessageRendererRegistries(\n baseRegistry,\n original?.messageRendererRegistry ?? {},\n );\n\n const originalAssistantActions = original?.assistantActions;\n if (!originalAssistantActions) {\n return {...original, messageRendererRegistry};\n }\n\n const wrappedAssistantActions = originalAssistantActions.map((action) => {\n const typed = action as DefaultMessageAction<TAssistantMessage>;\n const isLike = typed.type === BaseMessageActionType.Like;\n const isDislike = typed.type === BaseMessageActionType.Dislike;\n if (!isLike && !isDislike) return action;\n\n const targetRating: UserRating = isLike ? 'like' : 'dislike';\n const originalOnClick = typed.onClick;\n\n return {\n ...typed,\n onClick: (message: TAssistantMessage) => {\n if (message.id) {\n const nextRating =\n message.userRating === targetRating ? undefined : targetRating;\n setUserRating(message.id, nextRating);\n }\n originalOnClick(message);\n },\n };\n });\n\n return {\n ...original,\n assistantActions: wrappedAssistantActions,\n messageRendererRegistry,\n };\n }, [chatContainerProps.messageListConfig, setUserRating]);\n\n return (\n <ChatContainer\n {...chatContainerProps}\n messageListConfig={messageListConfig}\n messages={displayMessages}\n status={status}\n error={streamResult.error}\n onSendMessage={handleSendMessage}\n onCancel={handleCancel}\n onRetry={handleRetry}\n chats={showHistory ? chats : undefined}\n activeChat={showHistory ? activeChat : undefined}\n onSelectChat={showHistory ? handleSelectChat : undefined}\n onCreateChat={showHistory ? handleCreateChat : undefined}\n onDeleteChat={showHistory ? handleDeleteChat : undefined}\n showHistory={showHistory}\n showNewChat={showNewChat}\n promptInputProps={{\n ...chatContainerProps.promptInputProps,\n view: 'full',\n headerProps: {\n ...chatContainerProps.promptInputProps?.headerProps,\n contextItems:\n chatContainerProps.promptInputProps?.headerProps?.contextItems ??\n contextItems,\n },\n footerProps: {\n ...chatContainerProps.promptInputProps?.footerProps,\n attachmentContent:\n chatContainerProps.promptInputProps?.footerProps?.attachmentContent ??\n attachmentContent,\n },\n }}\n />\n );\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
.g-aikit-aistudio-mcp-tool {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: var(--g-spacing-2);
|
|
5
|
+
}
|
|
6
|
+
.g-aikit-aistudio-mcp-tool__section {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: var(--g-spacing-1);
|
|
10
|
+
}
|
|
11
|
+
.g-aikit-aistudio-mcp-tool__section-label {
|
|
12
|
+
color: var(--g-color-text-secondary);
|
|
13
|
+
font-weight: 500;
|
|
14
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { block } from "../../../utils/cn.js";
|
|
4
|
+
import { MarkdownRenderer } from "../../atoms/MarkdownRenderer/index.js";
|
|
5
|
+
import { ToolMessage } from "../../organisms/ToolMessage/index.js";
|
|
6
|
+
import { i18n } from "./i18n/index.js";
|
|
7
|
+
import "./McpToolRenderer.css";
|
|
8
|
+
const b = block('aistudio-mcp-tool');
|
|
9
|
+
export function McpToolRenderer({ part }) {
|
|
10
|
+
const _a = part.data, { mcpRequest, mcpResponse } = _a, rest = __rest(_a, ["mcpRequest", "mcpResponse"]);
|
|
11
|
+
const hasMcp = Boolean(mcpRequest || mcpResponse);
|
|
12
|
+
if (!hasMcp) {
|
|
13
|
+
return _jsx(ToolMessage, Object.assign({}, rest));
|
|
14
|
+
}
|
|
15
|
+
const body = (_jsxs("div", { className: b(), children: [mcpRequest && (_jsxs("div", { className: b('section'), children: [_jsx("div", { className: b('section-label'), children: i18n('mcp_request') }), _jsx(MarkdownRenderer, { content: `\`\`\`json\n${mcpRequest}\n\`\`\`` })] })), mcpResponse && (_jsxs("div", { className: b('section'), children: [_jsx("div", { className: b('section-label'), children: i18n('mcp_response') }), _jsx(MarkdownRenderer, { content: `\`\`\`json\n${mcpResponse}\n\`\`\`` })] }))] }));
|
|
16
|
+
return _jsx(ToolMessage, Object.assign({}, rest, { bodyContent: body }));
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=McpToolRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpToolRenderer.js","sourceRoot":"../../../../../src","sources":["components/pages/AIStudioChat/McpToolRenderer.tsx"],"names":[],"mappings":";;AACA,OAAO,EAAC,KAAK,EAAC,6BAA0B;AACxC,OAAO,EAAC,gBAAgB,EAAC,8CAAqC;AAC9D,OAAO,EAAC,WAAW,EAAC,6CAAoC;AAExD,OAAO,EAAC,IAAI,EAAC,wBAAe;AAE5B,+BAAgC;AAEhC,MAAM,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,CAAC;AAErC,MAAM,UAAU,eAAe,CAAC,EAAC,IAAI,EAA6B;IAC9D,MAAM,KAAqC,IAAI,CAAC,IAAI,EAA9C,EAAC,UAAU,EAAE,WAAW,OAAsB,EAAjB,IAAI,cAAjC,6BAAkC,CAAY,CAAC;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,IAAI,WAAW,CAAC,CAAC;IAElD,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,OAAO,KAAC,WAAW,oBAAK,IAAI,EAAI,CAAC;IACrC,CAAC;IAED,MAAM,IAAI,GAAG,CACT,eAAK,SAAS,EAAE,CAAC,EAAE,aACd,UAAU,IAAI,CACX,eAAK,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,aACxB,cAAK,SAAS,EAAE,CAAC,CAAC,eAAe,CAAC,YAAG,IAAI,CAAC,aAAa,CAAC,GAAO,EAC/D,KAAC,gBAAgB,IAAC,OAAO,EAAE,eAAe,UAAU,UAAU,GAAI,IAChE,CACT,EACA,WAAW,IAAI,CACZ,eAAK,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,aACxB,cAAK,SAAS,EAAE,CAAC,CAAC,eAAe,CAAC,YAAG,IAAI,CAAC,cAAc,CAAC,GAAO,EAChE,KAAC,gBAAgB,IAAC,OAAO,EAAE,eAAe,WAAW,UAAU,GAAI,IACjE,CACT,IACC,CACT,CAAC;IAEF,OAAO,KAAC,WAAW,oBAAK,IAAI,IAAE,WAAW,EAAE,IAAI,IAAI,CAAC;AACxD,CAAC","sourcesContent":["import type {ToolMessageContent} from '../../../types/messages';\nimport {block} from '../../../utils/cn';\nimport {MarkdownRenderer} from '../../atoms/MarkdownRenderer';\nimport {ToolMessage} from '../../organisms/ToolMessage';\n\nimport {i18n} from './i18n';\n\nimport './McpToolRenderer.scss';\n\nconst b = block('aistudio-mcp-tool');\n\nexport function McpToolRenderer({part}: {part: ToolMessageContent}) {\n const {mcpRequest, mcpResponse, ...rest} = part.data;\n const hasMcp = Boolean(mcpRequest || mcpResponse);\n\n if (!hasMcp) {\n return <ToolMessage {...rest} />;\n }\n\n const body = (\n <div className={b()}>\n {mcpRequest && (\n <div className={b('section')}>\n <div className={b('section-label')}>{i18n('mcp_request')}</div>\n <MarkdownRenderer content={`\\`\\`\\`json\\n${mcpRequest}\\n\\`\\`\\``} />\n </div>\n )}\n {mcpResponse && (\n <div className={b('section')}>\n <div className={b('section-label')}>{i18n('mcp_response')}</div>\n <MarkdownRenderer content={`\\`\\`\\`json\\n${mcpResponse}\\n\\`\\`\\``} />\n </div>\n )}\n </div>\n );\n\n return <ToolMessage {...rest} bodyContent={body} />;\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const i18n: ((key: "mcp_request" | "mcp_response", params?: import("@gravity-ui/i18n").Params) => string) & {
|
|
2
|
+
Translation: import("react").ComponentType<{
|
|
3
|
+
children: (props: {
|
|
4
|
+
t: (key: "mcp_request" | "mcp_response", params?: import("@gravity-ui/i18n").Params) => string;
|
|
5
|
+
}) => React.ReactNode;
|
|
6
|
+
}>;
|
|
7
|
+
useTranslation: () => {
|
|
8
|
+
t: (key: "mcp_request" | "mcp_response", params?: import("@gravity-ui/i18n").Params) => string;
|
|
9
|
+
};
|
|
10
|
+
keysetData: {
|
|
11
|
+
"g-aikit-AIStudioChat": Record<"mcp_request" | "mcp_response", import("@gravity-ui/i18n").KeyData>;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { addComponentKeysets } from '@gravity-ui/uikit/i18n';
|
|
2
|
+
import { NAMESPACE } from "../../../../utils/cn.js";
|
|
3
|
+
import en from "./en.json";
|
|
4
|
+
import ru from "./ru.json";
|
|
5
|
+
export const i18n = addComponentKeysets({ en, ru }, `${NAMESPACE}AIStudioChat`);
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"../../../../../../src","sources":["components/pages/AIStudioChat/i18n/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAC,SAAS,EAAC,gCAA6B;AAE/C,OAAO,EAAE,kBAAkB;AAC3B,OAAO,EAAE,kBAAkB;AAE3B,MAAM,CAAC,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAC,EAAE,EAAE,EAAE,EAAC,EAAE,GAAG,SAAS,cAAc,CAAC,CAAC","sourcesContent":["import {addComponentKeysets} from '@gravity-ui/uikit/i18n';\n\nimport {NAMESPACE} from '../../../../utils/cn';\n\nimport en from './en.json';\nimport ru from './ru.json';\n\nexport const i18n = addComponentKeysets({en, ru}, `${NAMESPACE}AIStudioChat`);\n"]}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"2.
|
|
1
|
+
{"version":"2.2.0","type":"module","sideEffects":["*.css","*.scss"]}
|
|
@@ -117,7 +117,12 @@ export type ThinkingMessageContentData = {
|
|
|
117
117
|
qa?: string;
|
|
118
118
|
};
|
|
119
119
|
export type ThinkingMessageContent = TMessageContent<'thinking', ThinkingMessageContentData>;
|
|
120
|
-
export type ToolMessageContentData = ToolMessageProps
|
|
120
|
+
export type ToolMessageContentData = ToolMessageProps & {
|
|
121
|
+
/** MCP arguments, pretty-printed JSON. Read by AIStudioChat's tool renderer. */
|
|
122
|
+
mcpRequest?: string;
|
|
123
|
+
/** MCP output (or error), pretty-printed JSON. Read by AIStudioChat's tool renderer. */
|
|
124
|
+
mcpResponse?: string;
|
|
125
|
+
};
|
|
121
126
|
export type ToolMessageContent = TMessageContent<'tool', ToolMessageContentData>;
|
|
122
127
|
export type TDefaultMessageContent = TextMessageContent | ThinkingMessageContent | ToolMessageContent;
|
|
123
128
|
export type TMessageContentUnion<TCustomMessageContent extends TMessageContent = never> = TDefaultMessageContent | TCustomMessageContent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"../../../src","sources":["types/messages.ts"],"names":[],"mappings":"AAmDA,MAAM,CAAN,IAAY,qBAOX;AAPD,WAAY,qBAAqB;IAC7B,sCAAa,CAAA;IACb,sCAAa,CAAA;IACb,wCAAe,CAAA;IACf,sCAAa,CAAA;IACb,4CAAmB,CAAA;IACnB,0CAAiB,CAAA;AACrB,CAAC,EAPW,qBAAqB,KAArB,qBAAqB,QAOhC","sourcesContent":["import type React from 'react';\n\nimport type {ButtonView, PopupPlacement} from '@gravity-ui/uikit';\n\nimport {ActionConfig} from './common';\nimport {ToolMessageProps} from './tool';\n\n/**\n * Context object passed to popup content generator function\n */\nexport interface ActionPopupContext {\n /** Update popup content without closing it */\n setContent: (content: React.ReactNode) => void;\n /** Update popup title dynamically */\n setTitle: (title: string | undefined) => void;\n /** Update popup subtitle dynamically */\n setSubtitle: (subtitle: string | undefined) => void;\n /** Programmatically close the popup */\n closePopup: () => void;\n}\n\n/**\n * Configuration for action popup\n */\nexport interface ActionPopupConfig<TMessage> {\n /** Function that generates popup content */\n getContent: (message: TMessage, context: ActionPopupContext) => React.ReactNode;\n /** Optional popup title (can be overridden by actionPopupProps) */\n title?: string;\n /** Optional popup subtitle (can be overridden by actionPopupProps) */\n subtitle?: string;\n /** Optional popup placement (can be overridden by actionPopupProps) */\n placement?: PopupPlacement;\n}\n\nexport type BaseMessageActionConfig<TMessage = unknown> = ActionConfig & {\n /** Optional popup configuration for this action */\n popup?: ActionPopupConfig<TMessage>;\n};\n\n/**\n * BaseMessage action can be either:\n * - BaseMessageActionConfig object with properties (including type for default icons)\n * - React.ReactNode for fully custom content\n */\nexport type BaseMessageAction<TMessage = unknown> =\n | BaseMessageActionConfig<TMessage>\n | React.ReactNode;\n\nexport type UserRating = 'like' | 'dislike';\n\nexport enum BaseMessageActionType {\n Copy = 'copy',\n Edit = 'edit',\n Retry = 'retry',\n Like = 'like',\n Dislike = 'dislike',\n Delete = 'delete',\n}\n\n/**\n * Default action descriptor for message action buttons.\n * Generic over the message type to provide typed onClick handler.\n */\nexport type DefaultMessageAction<TMessage> = {\n type?: string;\n onClick: (message: TMessage) => void;\n icon?: React.ReactNode;\n /**\n * Arbitrary button content (text, badges, or any ReactNode).\n * Takes precedence over `icon` when both are provided.\n * Can be a static ReactNode or a render function that receives the message,\n * allowing dynamic content based on message data (e.g. token count from metadata).\n */\n children?: React.ReactNode | ((message: TMessage) => React.ReactNode);\n label?: string;\n view?: ButtonView;\n /** Optional popup configuration for this action */\n popup?: ActionPopupConfig<TMessage>;\n};\n\n/**\n * React component used to render extra contextual info for a message\n * (e.g. token count, latency). Receives the message as a `message` prop.\n */\nexport type MessageExtraInfoComponent<TMessage> = React.ComponentType<{message: TMessage}>;\n\nexport type BaseMessageProps<TMessage = unknown> = {\n children: React.ReactNode;\n role: TMessageRole;\n actions?: BaseMessageAction<TMessage>[];\n /** Extra info node rendered alongside the action buttons (e.g. token count). */\n extraInfo?: React.ReactNode;\n userRating?: UserRating;\n timestamp?: string;\n showTimestamp?: boolean;\n showActionsOnHover?: boolean;\n className?: string;\n qa?: string;\n /** Callback when action with popup config is clicked */\n onActionPopup?: (action: BaseMessageActionConfig<TMessage>, anchorElement: HTMLElement) => void;\n};\n\nexport type TMessageMetadata = Record<string, unknown>;\n\nexport type TSubmitData = {\n content: string;\n attachments?: File[];\n metadata?: TMessageMetadata;\n};\n\nexport type TMessageRole = 'user' | 'assistant' | 'system';\n\nexport type TMessageContent<Type extends string = string, Data = unknown> = {\n id?: string;\n type: Type;\n data: Data;\n};\n\nexport type TextMessageContentData = {\n text: string;\n};\n\nexport type TextMessageContent = TMessageContent<'text', TextMessageContentData>;\n\nexport type ThinkingMessageContentData = {\n title?: string;\n content: string | string[];\n status: 'thinking' | 'thought';\n defaultExpanded?: boolean;\n showStatusIndicator?: boolean;\n onCopyClick?: () => void;\n enabledCopy?: boolean;\n className?: string;\n qa?: string;\n};\n\nexport type ThinkingMessageContent = TMessageContent<'thinking', ThinkingMessageContentData>;\n\nexport type ToolMessageContentData = ToolMessageProps;\n\nexport type ToolMessageContent = TMessageContent<'tool', ToolMessageContentData>;\n\nexport type TDefaultMessageContent =\n | TextMessageContent\n | ThinkingMessageContent\n | ToolMessageContent;\n\nexport type TMessageContentUnion<TCustomMessageContent extends TMessageContent = never> =\n | TDefaultMessageContent\n | TCustomMessageContent;\n\nexport type TAssistantMessageContent<TCustomMessageContent extends TMessageContent = never> =\n | string\n | TMessageContentUnion<TCustomMessageContent>\n | TMessageContentUnion<TCustomMessageContent>[];\n\nexport type TBaseMessage<Metadata = TMessageMetadata> = Pick<\n BaseMessageProps,\n 'actions' | 'timestamp'\n> & {\n id?: string;\n error?: unknown;\n metadata?: Metadata;\n};\n\nexport type FileAttachment = {\n id: string;\n name: string;\n mimeType?: string;\n};\n\nexport type TUserMessage<Metadata = TMessageMetadata> = TBaseMessage<Metadata> & {\n role: 'user';\n content: string;\n format?: 'plain' | 'markdown';\n avatarUrl?: string;\n /** Base64 data URLs or regular image URLs attached to the message */\n images?: string[];\n /** File attachments sent with this message */\n fileAttachments?: FileAttachment[];\n};\n\nexport type TAssistantMessage<\n TCustomMessageContent extends TMessageContent = never,\n Metadata = TMessageMetadata,\n> = TBaseMessage<Metadata> & {\n role: 'assistant';\n content: TAssistantMessageContent<TCustomMessageContent>;\n userRating?: UserRating;\n};\n\nexport type TChatMessage<\n TCustomMessageContent extends TMessageContent = never,\n Metadata = TMessageMetadata,\n> = TUserMessage<Metadata> | TAssistantMessage<TCustomMessageContent, Metadata>;\n"]}
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"../../../src","sources":["types/messages.ts"],"names":[],"mappings":"AAmDA,MAAM,CAAN,IAAY,qBAOX;AAPD,WAAY,qBAAqB;IAC7B,sCAAa,CAAA;IACb,sCAAa,CAAA;IACb,wCAAe,CAAA;IACf,sCAAa,CAAA;IACb,4CAAmB,CAAA;IACnB,0CAAiB,CAAA;AACrB,CAAC,EAPW,qBAAqB,KAArB,qBAAqB,QAOhC","sourcesContent":["import type React from 'react';\n\nimport type {ButtonView, PopupPlacement} from '@gravity-ui/uikit';\n\nimport {ActionConfig} from './common';\nimport {ToolMessageProps} from './tool';\n\n/**\n * Context object passed to popup content generator function\n */\nexport interface ActionPopupContext {\n /** Update popup content without closing it */\n setContent: (content: React.ReactNode) => void;\n /** Update popup title dynamically */\n setTitle: (title: string | undefined) => void;\n /** Update popup subtitle dynamically */\n setSubtitle: (subtitle: string | undefined) => void;\n /** Programmatically close the popup */\n closePopup: () => void;\n}\n\n/**\n * Configuration for action popup\n */\nexport interface ActionPopupConfig<TMessage> {\n /** Function that generates popup content */\n getContent: (message: TMessage, context: ActionPopupContext) => React.ReactNode;\n /** Optional popup title (can be overridden by actionPopupProps) */\n title?: string;\n /** Optional popup subtitle (can be overridden by actionPopupProps) */\n subtitle?: string;\n /** Optional popup placement (can be overridden by actionPopupProps) */\n placement?: PopupPlacement;\n}\n\nexport type BaseMessageActionConfig<TMessage = unknown> = ActionConfig & {\n /** Optional popup configuration for this action */\n popup?: ActionPopupConfig<TMessage>;\n};\n\n/**\n * BaseMessage action can be either:\n * - BaseMessageActionConfig object with properties (including type for default icons)\n * - React.ReactNode for fully custom content\n */\nexport type BaseMessageAction<TMessage = unknown> =\n | BaseMessageActionConfig<TMessage>\n | React.ReactNode;\n\nexport type UserRating = 'like' | 'dislike';\n\nexport enum BaseMessageActionType {\n Copy = 'copy',\n Edit = 'edit',\n Retry = 'retry',\n Like = 'like',\n Dislike = 'dislike',\n Delete = 'delete',\n}\n\n/**\n * Default action descriptor for message action buttons.\n * Generic over the message type to provide typed onClick handler.\n */\nexport type DefaultMessageAction<TMessage> = {\n type?: string;\n onClick: (message: TMessage) => void;\n icon?: React.ReactNode;\n /**\n * Arbitrary button content (text, badges, or any ReactNode).\n * Takes precedence over `icon` when both are provided.\n * Can be a static ReactNode or a render function that receives the message,\n * allowing dynamic content based on message data (e.g. token count from metadata).\n */\n children?: React.ReactNode | ((message: TMessage) => React.ReactNode);\n label?: string;\n view?: ButtonView;\n /** Optional popup configuration for this action */\n popup?: ActionPopupConfig<TMessage>;\n};\n\n/**\n * React component used to render extra contextual info for a message\n * (e.g. token count, latency). Receives the message as a `message` prop.\n */\nexport type MessageExtraInfoComponent<TMessage> = React.ComponentType<{message: TMessage}>;\n\nexport type BaseMessageProps<TMessage = unknown> = {\n children: React.ReactNode;\n role: TMessageRole;\n actions?: BaseMessageAction<TMessage>[];\n /** Extra info node rendered alongside the action buttons (e.g. token count). */\n extraInfo?: React.ReactNode;\n userRating?: UserRating;\n timestamp?: string;\n showTimestamp?: boolean;\n showActionsOnHover?: boolean;\n className?: string;\n qa?: string;\n /** Callback when action with popup config is clicked */\n onActionPopup?: (action: BaseMessageActionConfig<TMessage>, anchorElement: HTMLElement) => void;\n};\n\nexport type TMessageMetadata = Record<string, unknown>;\n\nexport type TSubmitData = {\n content: string;\n attachments?: File[];\n metadata?: TMessageMetadata;\n};\n\nexport type TMessageRole = 'user' | 'assistant' | 'system';\n\nexport type TMessageContent<Type extends string = string, Data = unknown> = {\n id?: string;\n type: Type;\n data: Data;\n};\n\nexport type TextMessageContentData = {\n text: string;\n};\n\nexport type TextMessageContent = TMessageContent<'text', TextMessageContentData>;\n\nexport type ThinkingMessageContentData = {\n title?: string;\n content: string | string[];\n status: 'thinking' | 'thought';\n defaultExpanded?: boolean;\n showStatusIndicator?: boolean;\n onCopyClick?: () => void;\n enabledCopy?: boolean;\n className?: string;\n qa?: string;\n};\n\nexport type ThinkingMessageContent = TMessageContent<'thinking', ThinkingMessageContentData>;\n\nexport type ToolMessageContentData = ToolMessageProps & {\n /** MCP arguments, pretty-printed JSON. Read by AIStudioChat's tool renderer. */\n mcpRequest?: string;\n /** MCP output (or error), pretty-printed JSON. Read by AIStudioChat's tool renderer. */\n mcpResponse?: string;\n};\n\nexport type ToolMessageContent = TMessageContent<'tool', ToolMessageContentData>;\n\nexport type TDefaultMessageContent =\n | TextMessageContent\n | ThinkingMessageContent\n | ToolMessageContent;\n\nexport type TMessageContentUnion<TCustomMessageContent extends TMessageContent = never> =\n | TDefaultMessageContent\n | TCustomMessageContent;\n\nexport type TAssistantMessageContent<TCustomMessageContent extends TMessageContent = never> =\n | string\n | TMessageContentUnion<TCustomMessageContent>\n | TMessageContentUnion<TCustomMessageContent>[];\n\nexport type TBaseMessage<Metadata = TMessageMetadata> = Pick<\n BaseMessageProps,\n 'actions' | 'timestamp'\n> & {\n id?: string;\n error?: unknown;\n metadata?: Metadata;\n};\n\nexport type FileAttachment = {\n id: string;\n name: string;\n mimeType?: string;\n};\n\nexport type TUserMessage<Metadata = TMessageMetadata> = TBaseMessage<Metadata> & {\n role: 'user';\n content: string;\n format?: 'plain' | 'markdown';\n avatarUrl?: string;\n /** Base64 data URLs or regular image URLs attached to the message */\n images?: string[];\n /** File attachments sent with this message */\n fileAttachments?: FileAttachment[];\n};\n\nexport type TAssistantMessage<\n TCustomMessageContent extends TMessageContent = never,\n Metadata = TMessageMetadata,\n> = TBaseMessage<Metadata> & {\n role: 'assistant';\n content: TAssistantMessageContent<TCustomMessageContent>;\n userRating?: UserRating;\n};\n\nexport type TChatMessage<\n TCustomMessageContent extends TMessageContent = never,\n Metadata = TMessageMetadata,\n> = TUserMessage<Metadata> | TAssistantMessage<TCustomMessageContent, Metadata>;\n"]}
|