@fv-ui/ai-chat 0.1.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.
@@ -0,0 +1,1912 @@
1
+ import * as vue from 'vue';
2
+ import { Component, Ref, ComputedRef } from 'vue';
3
+ import { ElAvatar, ElPopover } from 'element-plus';
4
+
5
+ /**
6
+ * markdown-it 插件形态(与 markdown-it 的 PluginWithParams 对齐)。
7
+ * 首参使用宽松类型:避免产物 d.ts 对 'markdown-it' 裸类型 import,
8
+ * 否则未安装 @types/markdown-it 的消费方会得到 TS7016 隐式 any 报错。
9
+ */
10
+ type MdPlugin = (md: any, ...params: unknown[]) => void;
11
+ interface CreateMarkdownOptions {
12
+ /** 代码高亮函数,未提供时 markdown-it 使用默认转义输出 */
13
+ highlight?: (str: string, lang: string) => string;
14
+ /** 额外的 markdown-it 插件 */
15
+ mdPlugins?: MdPlugin[];
16
+ }
17
+
18
+ type __VLS_Props$h = {
19
+ content: string;
20
+ mdPlugins?: CreateMarkdownOptions['mdPlugins'];
21
+ highlight?: (str: string, lang: string) => string;
22
+ /** 打字机模式下由父组件控制渲染策略,本组件保留透传占位 */
23
+ isTyping?: boolean;
24
+ };
25
+ declare const __VLS_export$h: vue.DefineComponent<__VLS_Props$h, {
26
+ getHtml: () => string;
27
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<__VLS_Props$h> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
28
+ declare const _default$h: typeof __VLS_export$h;
29
+
30
+ type __VLS_Props$g = {
31
+ content: string;
32
+ isMarkdown?: boolean;
33
+ isFog?: boolean | {
34
+ bgColor?: string;
35
+ width?: string;
36
+ };
37
+ typing?: boolean | {
38
+ step?: number;
39
+ interval?: number;
40
+ suffix?: string;
41
+ };
42
+ };
43
+ declare function interrupt$1(): void;
44
+ declare function continueTy$1(): void;
45
+ declare function restart$1(): void;
46
+ declare function destroy$1(): void;
47
+ declare const __VLS_export$g: vue.DefineComponent<__VLS_Props$g, {
48
+ interrupt: typeof interrupt$1;
49
+ continue: typeof continueTy$1;
50
+ restart: typeof restart$1;
51
+ destroy: typeof destroy$1;
52
+ renderedContent: vue.Ref<string, string>;
53
+ isTyping: vue.Ref<boolean, boolean>;
54
+ progress: vue.Ref<number, number>;
55
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
56
+ start: () => any;
57
+ finish: () => any;
58
+ writing: () => any;
59
+ }, string, vue.PublicProps, Readonly<__VLS_Props$g> & Readonly<{
60
+ onStart?: (() => any) | undefined;
61
+ onFinish?: (() => any) | undefined;
62
+ onWriting?: (() => any) | undefined;
63
+ }>, {
64
+ isMarkdown: boolean;
65
+ isFog: boolean | {
66
+ bgColor?: string;
67
+ width?: string;
68
+ };
69
+ typing: boolean | {
70
+ step?: number;
71
+ interval?: number;
72
+ suffix?: string;
73
+ };
74
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
75
+ declare const _default$g: typeof __VLS_export$g;
76
+
77
+ /** Typewriter 对外实例形态(defineExpose 经 proxyRefs 已自动解包,宽松兼容 Ref | 值) */
78
+ interface TypewriterExposed {
79
+ interrupt: () => void;
80
+ continue: () => void;
81
+ restart: () => void;
82
+ destroy: () => void;
83
+ renderedContent: Ref<string> | string;
84
+ isTyping: Ref<boolean> | boolean;
85
+ progress: Ref<number> | number;
86
+ }
87
+ type TypingConfig = {
88
+ step?: number;
89
+ interval?: number;
90
+ suffix?: string;
91
+ };
92
+ type __VLS_Props$f = {
93
+ /** 气泡内容 */
94
+ content?: string;
95
+ /** 对齐:start 靠左 / end 靠右(end 时头像随 row-reverse 翻转到右侧) */
96
+ placement?: 'start' | 'end';
97
+ /** 加载态:展示 #loading 插槽或内置三点动画 */
98
+ loading?: boolean;
99
+ /** 打字机模式:透传 Typewriter(falsy 时直接渲染内容) */
100
+ typing?: boolean | TypingConfig;
101
+ /** 内容按 markdown 渲染 */
102
+ isMarkdown?: boolean;
103
+ /** 雾化:透传 Typewriter(自定义气泡背景时传 bgColor) */
104
+ isFog?: boolean | {
105
+ bgColor?: string;
106
+ width?: string;
107
+ };
108
+ variant?: 'filled' | 'borderless' | 'outlined' | 'shadow';
109
+ shape?: 'round' | 'corner';
110
+ /** 头像图片地址(el-avatar src) */
111
+ avatar?: string;
112
+ /** 头像尺寸(el-avatar size,枚举或数值) */
113
+ avatarSize?: InstanceType<typeof ElAvatar>['size'] | number;
114
+ avatarGap?: string;
115
+ avatarShape?: 'circle' | 'square';
116
+ /** 头像图标组件(与 avatar 冲突时 icon 优先) */
117
+ avatarIcon?: Component;
118
+ avatarSrcSet?: string;
119
+ avatarAlt?: string;
120
+ /** 头像填充方式(el-avatar fit) */
121
+ avatarFit?: InstanceType<typeof ElAvatar>['fit'];
122
+ /** 内容区去内边距 */
123
+ noPadding?: boolean;
124
+ /** 去气泡样式(透明/无框/无阴影) */
125
+ noStyle?: boolean;
126
+ };
127
+ declare function interrupt(): void;
128
+ declare function continueTy(): void;
129
+ declare function restart(): void;
130
+ declare function destroy(): void;
131
+ declare var __VLS_1$9: {};
132
+ declare var __VLS_10$1: {};
133
+ declare var __VLS_12$1: {};
134
+ declare var __VLS_14$1: {};
135
+ declare var __VLS_32: {};
136
+ type __VLS_Slots$e = {} & {
137
+ avatar?: (props: typeof __VLS_1$9) => any;
138
+ } & {
139
+ header?: (props: typeof __VLS_10$1) => any;
140
+ } & {
141
+ loading?: (props: typeof __VLS_12$1) => any;
142
+ } & {
143
+ content?: (props: typeof __VLS_14$1) => any;
144
+ } & {
145
+ footer?: (props: typeof __VLS_32) => any;
146
+ };
147
+ declare const __VLS_base$e: vue.DefineComponent<__VLS_Props$f, {
148
+ interrupt: typeof interrupt;
149
+ continue: typeof continueTy;
150
+ restart: typeof restart;
151
+ destroy: typeof destroy;
152
+ renderedContent: vue.ComputedRef<string>;
153
+ isTyping: vue.ComputedRef<boolean>;
154
+ progress: vue.ComputedRef<number>;
155
+ twInstance: Ref<{
156
+ interrupt: () => void;
157
+ continue: () => void;
158
+ restart: () => void;
159
+ destroy: () => void;
160
+ renderedContent: string;
161
+ isTyping: boolean;
162
+ progress: number;
163
+ } | null, TypewriterExposed | {
164
+ interrupt: () => void;
165
+ continue: () => void;
166
+ restart: () => void;
167
+ destroy: () => void;
168
+ renderedContent: string;
169
+ isTyping: boolean;
170
+ progress: number;
171
+ } | null>;
172
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
173
+ start: () => any;
174
+ finish: () => any;
175
+ writing: () => any;
176
+ "avatar-error": (event: Event) => any;
177
+ }, string, vue.PublicProps, Readonly<__VLS_Props$f> & Readonly<{
178
+ onStart?: (() => any) | undefined;
179
+ onFinish?: (() => any) | undefined;
180
+ onWriting?: (() => any) | undefined;
181
+ "onAvatar-error"?: ((event: Event) => any) | undefined;
182
+ }>, {
183
+ content: string;
184
+ isMarkdown: boolean;
185
+ isFog: boolean | {
186
+ bgColor?: string;
187
+ width?: string;
188
+ };
189
+ typing: boolean | TypingConfig;
190
+ shape: "round" | "corner";
191
+ placement: "start" | "end";
192
+ loading: boolean;
193
+ variant: "filled" | "borderless" | "outlined" | "shadow";
194
+ avatar: string;
195
+ avatarSize: number | "" | "default" | "small" | "large";
196
+ avatarGap: string;
197
+ avatarShape: "circle" | "square";
198
+ avatarSrcSet: string;
199
+ avatarAlt: string;
200
+ avatarFit: InstanceType<typeof ElAvatar>["fit"];
201
+ noPadding: boolean;
202
+ noStyle: boolean;
203
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
204
+ declare const __VLS_export$f: __VLS_WithSlots$e<typeof __VLS_base$e, __VLS_Slots$e>;
205
+ declare const _default$f: typeof __VLS_export$f;
206
+
207
+ type __VLS_WithSlots$e<T, S> = T & {
208
+ new (): {
209
+ $slots: S;
210
+ };
211
+ };
212
+
213
+ /** 列表项 = Bubble props + key(key 仅供 v-for,不透传给 Bubble) */
214
+ interface BubbleListItemProps {
215
+ key: string | number;
216
+ [prop: string]: unknown;
217
+ }
218
+ type __VLS_Props$e = {
219
+ /** 气泡列表 */
220
+ list: BubbleListItemProps[];
221
+ /** 滚动容器最大高度(如 '350px'/'60vh') */
222
+ maxHeight?: string;
223
+ /** 始终显示滚动条(否则仅在滚动时显示,依赖浏览器 hover/scroll 实现) */
224
+ alwaysShowScrollbar?: boolean;
225
+ /** 是否显示回底按钮 */
226
+ showBackButton?: boolean;
227
+ /** 距底超过该像素显示回底按钮 */
228
+ backButtonThreshold?: number;
229
+ /** 回底按钮加载态 */
230
+ btnLoading?: boolean;
231
+ /** 回底按钮颜色(el-button color) */
232
+ btnColor?: string;
233
+ /** 回底按钮位置偏移 */
234
+ backButtonPosition?: {
235
+ bottom?: string;
236
+ left?: string;
237
+ };
238
+ /** 回底按钮图标尺寸 */
239
+ btnIconSize?: number;
240
+ /**
241
+ * @complete 触发索引:
242
+ * - 'only-last'(默认):仅最后一个 typing=true 的气泡完成时上抛
243
+ * - 'all':所有气泡完成都上抛
244
+ * - number[]:仅指定索引上抛(无效索引过滤并 console.warn)
245
+ */
246
+ triggerIndices?: 'only-last' | 'all' | number[];
247
+ };
248
+ declare function scrollToTop$1(): void;
249
+ declare function scrollToBottom$1(): void;
250
+ /** 定位第 index 个气泡到可视区 */
251
+ declare function scrollToBubble(index: number): void;
252
+ declare var __VLS_10: {
253
+ item: BubbleListItemProps;
254
+ index: number;
255
+ };
256
+ declare var __VLS_13: {
257
+ item: BubbleListItemProps;
258
+ index: number;
259
+ };
260
+ declare var __VLS_16$1: {
261
+ item: BubbleListItemProps;
262
+ index: number;
263
+ };
264
+ declare var __VLS_19$1: {
265
+ item: BubbleListItemProps;
266
+ index: number;
267
+ };
268
+ declare var __VLS_22: {
269
+ item: BubbleListItemProps;
270
+ index: number;
271
+ };
272
+ type __VLS_Slots$d = {} & {
273
+ avatar?: (props: typeof __VLS_10) => any;
274
+ } & {
275
+ header?: (props: typeof __VLS_13) => any;
276
+ } & {
277
+ content?: (props: typeof __VLS_16$1) => any;
278
+ } & {
279
+ loading?: (props: typeof __VLS_19$1) => any;
280
+ } & {
281
+ footer?: (props: typeof __VLS_22) => any;
282
+ };
283
+ declare const __VLS_base$d: vue.DefineComponent<__VLS_Props$e, {
284
+ scrollToTop: typeof scrollToTop$1;
285
+ scrollToBottom: typeof scrollToBottom$1;
286
+ scrollToBubble: typeof scrollToBubble;
287
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
288
+ complete: (instance: unknown, index: number) => any;
289
+ }, string, vue.PublicProps, Readonly<__VLS_Props$e> & Readonly<{
290
+ onComplete?: ((instance: unknown, index: number) => any) | undefined;
291
+ }>, {
292
+ list: BubbleListItemProps[];
293
+ maxHeight: string;
294
+ alwaysShowScrollbar: boolean;
295
+ showBackButton: boolean;
296
+ backButtonThreshold: number;
297
+ btnLoading: boolean;
298
+ btnColor: string;
299
+ backButtonPosition: {
300
+ bottom?: string;
301
+ left?: string;
302
+ };
303
+ btnIconSize: number;
304
+ triggerIndices: "only-last" | "all" | number[];
305
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
306
+ declare const __VLS_export$e: __VLS_WithSlots$d<typeof __VLS_base$d, __VLS_Slots$d>;
307
+ declare const _default$e: typeof __VLS_export$e;
308
+
309
+ type __VLS_WithSlots$d<T, S> = T & {
310
+ new (): {
311
+ $slots: S;
312
+ };
313
+ };
314
+
315
+ type __VLS_Props$d = {
316
+ /** 输入值(v-model) */
317
+ modelValue?: string;
318
+ placeholder?: string;
319
+ /** 自增高:minRows/maxRows(行高 22px) */
320
+ autosize?: {
321
+ minRows?: number;
322
+ maxRows?: number;
323
+ };
324
+ /** 输入字数上限:超限截断(det-oms 约定 ≤8000);缺省不限制 */
325
+ maxlength?: number;
326
+ /** 提交按键模式 */
327
+ submitType?: 'enter' | 'shiftEnter' | 'cmdOrCtrlEnter' | 'altEnter';
328
+ /** 加载态:显示停止按钮,输入区禁用 */
329
+ loading?: boolean;
330
+ disabled?: boolean;
331
+ readOnly?: boolean;
332
+ /** 显示清空按钮(有内容时) */
333
+ clearable?: boolean;
334
+ /** 输入区宽度(如 '60%',variant=default 时有效) */
335
+ inputWidth?: string;
336
+ /** default:输入+按钮同排;updown:上输入区下操作栏 */
337
+ variant?: 'default' | 'updown';
338
+ /** 发送按钮禁用(空内容禁用逻辑之外附加) */
339
+ submitBtnDisabled?: boolean;
340
+ /** 指令触发字符串(光标前命中时弹指令框) */
341
+ triggerStrings?: string[];
342
+ /** 指令弹框显隐(v-model:triggerPopoverVisible) */
343
+ triggerPopoverVisible?: boolean;
344
+ /** 指令弹框宽度 */
345
+ triggerPopoverWidth?: string;
346
+ /** 指令弹框 left 偏移(命中字符处) */
347
+ triggerPopoverLeft?: string;
348
+ /** 指令弹框距触发字符偏移量 */
349
+ triggerPopoverOffset?: number;
350
+ /** 指令弹框位置(el-popover placement) */
351
+ triggerPopoverPlacement?: InstanceType<typeof ElPopover>['placement'];
352
+ /** 显示语音按钮(useRecord 于 Task 15 接线,当前为 TODO 桩) */
353
+ allowSpeech?: boolean;
354
+ /** 允许空内容提交(附件场景:只发文件不输文字时提交按钮保持可点) */
355
+ allowEmptySubmit?: boolean;
356
+ };
357
+ declare function submit$1(): void;
358
+ declare function cancel$1(): void;
359
+ declare function clear$2(): void;
360
+ /** focus(pos):'all' 全选 | 'start' 光标到头 | 'end' 光标到尾(缺省 end) */
361
+ declare function focus$1(pos?: 'all' | 'start' | 'end'): void;
362
+ declare function blur$2(): void;
363
+ declare function openHeader$2(): void;
364
+ declare function closeHeader$2(): void;
365
+ declare var __VLS_1$8: {};
366
+ declare var __VLS_3$2: {};
367
+ declare var __VLS_5: {};
368
+ declare var __VLS_14: {
369
+ keyword: string;
370
+ };
371
+ declare var __VLS_16: {};
372
+ declare var __VLS_18: {};
373
+ declare var __VLS_96: {};
374
+ type __VLS_Slots$c = {} & {
375
+ header?: (props: typeof __VLS_1$8) => any;
376
+ } & {
377
+ 'body-top'?: (props: typeof __VLS_3$2) => any;
378
+ } & {
379
+ prefix?: (props: typeof __VLS_5) => any;
380
+ } & {
381
+ trigger?: (props: typeof __VLS_14) => any;
382
+ } & {
383
+ 'action-list'?: (props: typeof __VLS_16) => any;
384
+ } & {
385
+ 'action-left'?: (props: typeof __VLS_18) => any;
386
+ } & {
387
+ footer?: (props: typeof __VLS_96) => any;
388
+ };
389
+ declare const __VLS_base$c: vue.DefineComponent<__VLS_Props$d, {
390
+ submit: typeof submit$1;
391
+ cancel: typeof cancel$1;
392
+ clear: typeof clear$2;
393
+ focus: typeof focus$1;
394
+ blur: typeof blur$2;
395
+ openHeader: typeof openHeader$2;
396
+ closeHeader: typeof closeHeader$2;
397
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
398
+ submit: (value: string) => any;
399
+ trigger: (keyword: string, visible: boolean) => any;
400
+ "update:modelValue": (value: string) => any;
401
+ cancel: () => any;
402
+ change: (value: string) => any;
403
+ "recording-change": (recording: boolean) => any;
404
+ "paste-file": (file: File) => any;
405
+ "update:triggerPopoverVisible": (value: boolean) => any;
406
+ }, string, vue.PublicProps, Readonly<__VLS_Props$d> & Readonly<{
407
+ onSubmit?: ((value: string) => any) | undefined;
408
+ onTrigger?: ((keyword: string, visible: boolean) => any) | undefined;
409
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
410
+ onCancel?: (() => any) | undefined;
411
+ onChange?: ((value: string) => any) | undefined;
412
+ "onRecording-change"?: ((recording: boolean) => any) | undefined;
413
+ "onPaste-file"?: ((file: File) => any) | undefined;
414
+ "onUpdate:triggerPopoverVisible"?: ((value: boolean) => any) | undefined;
415
+ }>, {
416
+ loading: boolean;
417
+ variant: "default" | "updown";
418
+ disabled: boolean;
419
+ modelValue: string;
420
+ placeholder: string;
421
+ autosize: {
422
+ minRows?: number;
423
+ maxRows?: number;
424
+ };
425
+ maxlength: number;
426
+ submitType: "enter" | "shiftEnter" | "cmdOrCtrlEnter" | "altEnter";
427
+ readOnly: boolean;
428
+ clearable: boolean;
429
+ inputWidth: string;
430
+ submitBtnDisabled: boolean;
431
+ triggerStrings: string[];
432
+ triggerPopoverVisible: boolean;
433
+ triggerPopoverWidth: string;
434
+ triggerPopoverLeft: string;
435
+ triggerPopoverOffset: number;
436
+ triggerPopoverPlacement: InstanceType<typeof ElPopover>["placement"];
437
+ allowSpeech: boolean;
438
+ allowEmptySubmit: boolean;
439
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
440
+ declare const __VLS_export$d: __VLS_WithSlots$c<typeof __VLS_base$c, __VLS_Slots$c>;
441
+ declare const _default$d: typeof __VLS_export$d;
442
+
443
+ type __VLS_WithSlots$c<T, S> = T & {
444
+ new (): {
445
+ $slots: S;
446
+ };
447
+ };
448
+
449
+ /** 用户项(userList 元素 / asyncMatchFun 返回项) */
450
+ interface MentionUserInfo {
451
+ id: string;
452
+ name: string;
453
+ avatar?: string;
454
+ pinyin?: string;
455
+ }
456
+ /** 自定义触发组:prefix 命中时弹 tagList,dialogTitle 为弹层标题 */
457
+ interface MentionCustomTrigger {
458
+ dialogTitle: string;
459
+ prefix: string;
460
+ tagList: Array<{
461
+ id: string;
462
+ name: string;
463
+ pinyin?: string;
464
+ }>;
465
+ }
466
+ type __VLS_Props$c = {
467
+ /** 输入值(v-model) */
468
+ modelValue?: string;
469
+ /** @ 触发的候选用户列表 */
470
+ userList?: MentionUserInfo[];
471
+ /** 自定义触发组(prefix 命中弹对应 tagList) */
472
+ customTrigger?: MentionCustomTrigger[];
473
+ /** 异步候选:存在时防抖 300ms 拉取(后端负责过滤) */
474
+ asyncMatchFun?: (search: string) => Promise<MentionUserInfo[]>;
475
+ };
476
+ declare function submit(): void;
477
+ declare function cancel(): void;
478
+ declare function clear$1(): void;
479
+ /** focus(pos):'all' 全选 | 'start' 头 | 'end' 尾(缺省 end) */
480
+ declare function focus(pos?: 'all' | 'start' | 'end'): void;
481
+ declare function blur$1(): void;
482
+ declare function openHeader$1(): void;
483
+ declare function closeHeader$1(): void;
484
+ /** 程序化插入 @用户 标签(光标处) */
485
+ declare function setUserTag$1(userId: string): void;
486
+ /** 程序化插入自定义触发标签(光标处) */
487
+ declare function setCustomTag$1(prefix: string, id: string): void;
488
+ declare var __VLS_20: string;
489
+ declare var __VLS_21$2: any;
490
+ type __VLS_Slots$b = {} & {
491
+ [K in NonNullable<typeof __VLS_20>]?: (props: typeof __VLS_21$2) => any;
492
+ };
493
+ declare const __VLS_base$b: vue.DefineComponent<__VLS_Props$c, {
494
+ submit: typeof submit;
495
+ cancel: typeof cancel;
496
+ clear: typeof clear$1;
497
+ focus: typeof focus;
498
+ blur: typeof blur$1;
499
+ openHeader: typeof openHeader$1;
500
+ closeHeader: typeof closeHeader$1;
501
+ setUserTag: typeof setUserTag$1;
502
+ setCustomTag: typeof setCustomTag$1;
503
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
504
+ submit: (value: string) => any;
505
+ trigger: (keyword: string, visible: boolean) => any;
506
+ "update:modelValue": (value: string) => any;
507
+ cancel: () => any;
508
+ change: (value: string) => any;
509
+ "recording-change": (recording: boolean) => any;
510
+ "paste-file": (file: File) => any;
511
+ "update:triggerPopoverVisible": (value: boolean) => any;
512
+ "show-at-dialog": (visible: boolean) => any;
513
+ }, string, vue.PublicProps, Readonly<__VLS_Props$c> & Readonly<{
514
+ onSubmit?: ((value: string) => any) | undefined;
515
+ onTrigger?: ((keyword: string, visible: boolean) => any) | undefined;
516
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
517
+ onCancel?: (() => any) | undefined;
518
+ onChange?: ((value: string) => any) | undefined;
519
+ "onRecording-change"?: ((recording: boolean) => any) | undefined;
520
+ "onPaste-file"?: ((file: File) => any) | undefined;
521
+ "onUpdate:triggerPopoverVisible"?: ((value: boolean) => any) | undefined;
522
+ "onShow-at-dialog"?: ((visible: boolean) => any) | undefined;
523
+ }>, {
524
+ modelValue: string;
525
+ userList: MentionUserInfo[];
526
+ customTrigger: MentionCustomTrigger[];
527
+ asyncMatchFun: (search: string) => Promise<MentionUserInfo[]>;
528
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
529
+ declare const __VLS_export$c: __VLS_WithSlots$b<typeof __VLS_base$b, __VLS_Slots$b>;
530
+ declare const _default$c: typeof __VLS_export$c;
531
+
532
+ type __VLS_WithSlots$b<T, S> = T & {
533
+ new (): {
534
+ $slots: S;
535
+ };
536
+ };
537
+
538
+ /** 用户项(userList 元素 / asyncMatchFun 返回项) */
539
+ interface EditorUser {
540
+ id: string;
541
+ name: string;
542
+ avatar?: string;
543
+ pinyin?: string;
544
+ }
545
+ /** 自定义触发组:prefix 命中时弹 tagList,dialogTitle 为弹层标题 */
546
+ interface EditorCustomTrigger {
547
+ dialogTitle: string;
548
+ prefix: string;
549
+ tagList: Array<{
550
+ id: string;
551
+ name: string;
552
+ pinyin?: string;
553
+ }>;
554
+ }
555
+ /** 选择标签选项(selectList[].options 元素,preview 为预览图地址) */
556
+ interface EditorSelectOption {
557
+ id: string;
558
+ name: string;
559
+ preview?: string;
560
+ }
561
+ /** 选择标签分组 */
562
+ interface EditorSelectGroup {
563
+ dialogTitle: string;
564
+ key: string;
565
+ options: EditorSelectOption[];
566
+ }
567
+ /** 选择标签值(setSelectTag / tags.selectTags 元素) */
568
+ interface EditorSelectTag {
569
+ value: string;
570
+ name?: string;
571
+ key?: string;
572
+ }
573
+ /** 文档节点类型:纯文本与五类标签 */
574
+ type TagNodeType = 'text' | 'userTag' | 'selectTag' | 'inputTag' | 'customTag' | 'htmlTag';
575
+ /** 文档节点:标签引擎的最小单元,value 依类型不同(text→string,其余→对象) */
576
+ interface TagNode {
577
+ id: string;
578
+ type: TagNodeType;
579
+ value: any;
580
+ meta?: Record<string, any>;
581
+ }
582
+ /** 提交结果:text 为标签文本化后的纯文本,html 为编辑区内部 HTML,tags 为各类型标签集合 */
583
+ interface SubmitResult {
584
+ text: string;
585
+ html: string;
586
+ tags: {
587
+ userTags: EditorUser[];
588
+ selectTags: EditorSelectTag[];
589
+ inputTags: Array<{
590
+ id: string;
591
+ name: string;
592
+ }>;
593
+ customTags: Array<{
594
+ id: string;
595
+ name: string;
596
+ prefix?: string;
597
+ }>;
598
+ };
599
+ }
600
+ /** chat 方法(open-webui 对齐) */
601
+ type ChatMethod = 'insert' | 'update' | 'delete' | 'append';
602
+ /** 选择标签更新方法 */
603
+ type UpdateMethod = 'insertTag' | 'updateTagValue' | 'deleteTag' | 'updateTagStyle';
604
+ /** setMixTags 混合标签行元素:按 type 分发到对应 set* */
605
+ type MixTag = {
606
+ type: 'userTag';
607
+ id: string;
608
+ } | {
609
+ type: 'selectTag';
610
+ value: string;
611
+ name?: string;
612
+ key?: string;
613
+ } | {
614
+ type: 'inputTag';
615
+ id: string;
616
+ name: string;
617
+ } | {
618
+ type: 'customTag';
619
+ prefix: string;
620
+ id: string;
621
+ } | {
622
+ type: 'text';
623
+ value: string;
624
+ };
625
+ type __VLS_Props$b = {
626
+ placeholder?: string;
627
+ /** 设备形态:仅影响样式(pc 默认 / h5 紧凑) */
628
+ device?: 'pc' | 'h5';
629
+ autoFocus?: boolean;
630
+ /** default:输入+按钮同排;updown:上输入区下操作栏 */
631
+ variant?: 'default' | 'updown';
632
+ /** @ 触发的候选用户列表 */
633
+ userList?: EditorUser[];
634
+ /** 自定义触发组(prefix 命中弹对应 tagList) */
635
+ customTrigger?: EditorCustomTrigger[];
636
+ /** 选择标签分组(openSelectDialog 弹窗数据) */
637
+ selectList?: EditorSelectGroup[];
638
+ /** 纯文本最大长度(性能开销大,仅显式开启) */
639
+ maxLength?: number;
640
+ /** 提交按键模式 */
641
+ submitType?: 'enter' | 'shiftEnter';
642
+ /** 根节点自定义样式 */
643
+ customStyle?: Record<string, any>;
644
+ loading?: boolean;
645
+ disabled?: boolean;
646
+ /** 显示清空按钮(有内容时) */
647
+ clearable?: boolean;
648
+ /** 头部过渡时长(毫秒) */
649
+ headerAnimationTimer?: number;
650
+ /** 异步候选:存在时防抖 300ms 拉取(后端负责过滤) */
651
+ asyncMatchFun?: (search: string) => Promise<EditorUser[]>;
652
+ /** 自定义弹窗:true 时不弹内置选择弹窗,仅上抛 show-select-dialog 由外部接管 */
653
+ customDialog?: boolean;
654
+ };
655
+ /**
656
+ * 编辑器 API:state 为数据源,insert/update/delete/append 为对外操作面。
657
+ * 声明即带操作面签名再赋值实现,避免逐行 chat.insert = ... 展开时被类型推断收窄。
658
+ */
659
+ interface EditorChatApi {
660
+ state: {
661
+ nodes: TagNode[];
662
+ };
663
+ insert(options?: Record<string, any>): void;
664
+ update(options?: Record<string, any>): void;
665
+ delete(options?: Record<string, any>): void;
666
+ append(options?: Record<string, any>): void;
667
+ }
668
+ declare function getCurrentValue(): SubmitResult;
669
+ declare function placeCursorEnd(): void;
670
+ declare function focusToStart(): void;
671
+ declare function selectAll(): void;
672
+ declare function blur(): void;
673
+ declare function openSelectDialog(): void;
674
+ /** 打开 tip(nodeId 缺省取第一个 inputTag) */
675
+ declare function openTipTag(nodeId?: string): void;
676
+ declare function closeTipTag(): void;
677
+ /** 在光标处插入纯文本(不删除已有内容) */
678
+ declare function setText(text: string): void;
679
+ /** 插入用户标签(userList 按 id 查找,找不到以 id 兜底) */
680
+ declare function setUserTag(userId: string): void;
681
+ /** 插入自定义触发标签(customTrigger 按 prefix+id 查找) */
682
+ declare function setCustomTag(prefix: string, id: string): void;
683
+ /** 插入输入标签(可编辑 chip) */
684
+ declare function setInputTag(id: string, name: string): void;
685
+ /** 追加选择标签组 */
686
+ declare function setSelectTag(list: EditorSelectTag[]): void;
687
+ /** 外部直接传入用户对象插入(不经 userList) */
688
+ declare function customSetUser(user: EditorUser): void;
689
+ /** 外部直接传入标签对象插入(不经 customTrigger) */
690
+ declare function customSetTag(tag: {
691
+ id: string;
692
+ name: string;
693
+ prefix?: string;
694
+ }): void;
695
+ /** 整体写入 html:解析为 text/htmlTag 节点(替换现有内容) */
696
+ declare function setHtml(html: string): void;
697
+ /** 混合标签整体写入:清空后按 type 分发到对应 set*(覆盖写入) */
698
+ declare function setMixTags(rows: MixTag[][]): void;
699
+ declare function clear(): void;
700
+ declare function updateSelectTag(method: UpdateMethod, options?: Record<string, any>): void;
701
+ /** chat 方法分发:insert / update / delete / append */
702
+ declare function opNode(method: ChatMethod, options?: Record<string, any>): void;
703
+ /** 暴露文档状态(外部遍历 nodes) */
704
+ declare function chatState(): {
705
+ nodes: TagNode[];
706
+ };
707
+ declare function openHeader(): void;
708
+ declare function closeHeader(): void;
709
+ declare var __VLS_1$7: {};
710
+ declare var __VLS_3$1: {};
711
+ declare var __VLS_19: {
712
+ nodeId: string;
713
+ };
714
+ declare var __VLS_21$1: {};
715
+ declare var __VLS_80: {};
716
+ type __VLS_Slots$a = {} & {
717
+ header?: (props: typeof __VLS_1$7) => any;
718
+ } & {
719
+ prefix?: (props: typeof __VLS_3$1) => any;
720
+ } & {
721
+ 'tag-tip'?: (props: typeof __VLS_19) => any;
722
+ } & {
723
+ 'action-list'?: (props: typeof __VLS_21$1) => any;
724
+ } & {
725
+ footer?: (props: typeof __VLS_80) => any;
726
+ };
727
+ declare const __VLS_base$a: vue.DefineComponent<__VLS_Props$b, {
728
+ getCurrentValue: typeof getCurrentValue;
729
+ focusToStart: typeof focusToStart;
730
+ focusToEnd: typeof placeCursorEnd;
731
+ blur: typeof blur;
732
+ selectAll: typeof selectAll;
733
+ clear: typeof clear;
734
+ setSelectTag: typeof setSelectTag;
735
+ setInputTag: typeof setInputTag;
736
+ setUserTag: typeof setUserTag;
737
+ setCustomTag: typeof setCustomTag;
738
+ setMixTags: typeof setMixTags;
739
+ setHtml: typeof setHtml;
740
+ setText: typeof setText;
741
+ openSelectDialog: typeof openSelectDialog;
742
+ customSetUser: typeof customSetUser;
743
+ customSetTag: typeof customSetTag;
744
+ updateSelectTag: typeof updateSelectTag;
745
+ openTipTag: typeof openTipTag;
746
+ closeTipTag: typeof closeTipTag;
747
+ openHeader: typeof openHeader;
748
+ closeHeader: typeof closeHeader;
749
+ chat: EditorChatApi;
750
+ opNode: typeof opNode;
751
+ chatState: typeof chatState;
752
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
753
+ submit: (payload: SubmitResult) => any;
754
+ cancel: () => any;
755
+ change: (payload: SubmitResult) => any;
756
+ "show-at-dialog": (visible: boolean) => any;
757
+ "show-select-dialog": (visible: boolean) => any;
758
+ "show-tag-dialog": (visible: boolean) => any;
759
+ }, string, vue.PublicProps, Readonly<__VLS_Props$b> & Readonly<{
760
+ onSubmit?: ((payload: SubmitResult) => any) | undefined;
761
+ onCancel?: (() => any) | undefined;
762
+ onChange?: ((payload: SubmitResult) => any) | undefined;
763
+ "onShow-at-dialog"?: ((visible: boolean) => any) | undefined;
764
+ "onShow-select-dialog"?: ((visible: boolean) => any) | undefined;
765
+ "onShow-tag-dialog"?: ((visible: boolean) => any) | undefined;
766
+ }>, {
767
+ loading: boolean;
768
+ variant: "default" | "updown";
769
+ disabled: boolean;
770
+ placeholder: string;
771
+ submitType: "enter" | "shiftEnter";
772
+ clearable: boolean;
773
+ userList: EditorUser[];
774
+ customTrigger: EditorCustomTrigger[];
775
+ asyncMatchFun: (search: string) => Promise<EditorUser[]>;
776
+ device: "pc" | "h5";
777
+ autoFocus: boolean;
778
+ selectList: EditorSelectGroup[];
779
+ maxLength: number;
780
+ customStyle: Record<string, any>;
781
+ headerAnimationTimer: number;
782
+ customDialog: boolean;
783
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
784
+ declare const __VLS_export$b: __VLS_WithSlots$a<typeof __VLS_base$a, __VLS_Slots$a>;
785
+ declare const _default$b: typeof __VLS_export$b;
786
+
787
+ type __VLS_WithSlots$a<T, S> = T & {
788
+ new (): {
789
+ $slots: S;
790
+ };
791
+ };
792
+
793
+ type ThinkingStatus = 'start' | 'thinking' | 'end' | 'error';
794
+ type __VLS_Props$a = {
795
+ /** 展开/收起(v-model) */
796
+ modelValue?: boolean;
797
+ /** 思考内容(#content 插槽常嵌 XMarkdown/Typewriter 渲染思考流) */
798
+ content?: string;
799
+ /** 思考状态:start 起始 / thinking 思考中 / end 完成 / error 出错 */
800
+ status?: ThinkingStatus;
801
+ /** 禁用切换 */
802
+ disabled?: boolean;
803
+ /** status 变为 end 时自动收起 */
804
+ autoCollapse?: boolean;
805
+ /** 切换按钮区宽度(如 '150px') */
806
+ buttonWidth?: string;
807
+ /** 内容区最大宽度 */
808
+ maxWidth?: string;
809
+ /** 前景色(文字/图标,css color) */
810
+ color?: string;
811
+ /** 背景色 */
812
+ backgroundColor?: string;
813
+ };
814
+ /** 切换门控:start 起始态不可切换;thinking 中可展开查看思考流,end/error 后可自由收起展开 */
815
+ declare function toggle(): void;
816
+ declare var __VLS_1$6: {};
817
+ declare var __VLS_36: {};
818
+ declare var __VLS_38: {};
819
+ declare var __VLS_51: {};
820
+ declare var __VLS_53: {};
821
+ type __VLS_Slots$9 = {} & {
822
+ 'status-icon'?: (props: typeof __VLS_1$6) => any;
823
+ } & {
824
+ label?: (props: typeof __VLS_36) => any;
825
+ } & {
826
+ arrow?: (props: typeof __VLS_38) => any;
827
+ } & {
828
+ error?: (props: typeof __VLS_51) => any;
829
+ } & {
830
+ content?: (props: typeof __VLS_53) => any;
831
+ };
832
+ declare const __VLS_base$9: vue.DefineComponent<__VLS_Props$a, {
833
+ modelValue: vue.Ref<boolean, boolean>;
834
+ toggle: typeof toggle;
835
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
836
+ "update:modelValue": (value: boolean) => any;
837
+ }, string, vue.PublicProps, Readonly<__VLS_Props$a> & Readonly<{
838
+ "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
839
+ }>, {
840
+ content: string;
841
+ disabled: boolean;
842
+ color: string;
843
+ modelValue: boolean;
844
+ status: ThinkingStatus;
845
+ autoCollapse: boolean;
846
+ buttonWidth: string;
847
+ maxWidth: string;
848
+ backgroundColor: string;
849
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
850
+ declare const __VLS_export$a: __VLS_WithSlots$9<typeof __VLS_base$9, __VLS_Slots$9>;
851
+ declare const _default$a: typeof __VLS_export$a;
852
+
853
+ type __VLS_WithSlots$9<T, S> = T & {
854
+ new (): {
855
+ $slots: S;
856
+ };
857
+ };
858
+
859
+ type ChainItemStatus = 'pending' | 'success' | 'loading' | 'error';
860
+ interface ThoughtChainItem {
861
+ key: string | number;
862
+ title?: string;
863
+ status?: ChainItemStatus;
864
+ icon?: Component;
865
+ description?: string;
866
+ }
867
+ type __VLS_Props$9 = {
868
+ /** 步骤列表 */
869
+ items: ThoughtChainItem[];
870
+ /** 排列方向:vertical 纵向(带连接线)/ horizontal 横向 */
871
+ direction?: 'vertical' | 'horizontal';
872
+ };
873
+ declare var __VLS_45: {
874
+ item: ThoughtChainItem;
875
+ index: number;
876
+ };
877
+ type __VLS_Slots$8 = {} & {
878
+ content?: (props: typeof __VLS_45) => any;
879
+ };
880
+ declare const __VLS_base$8: vue.DefineComponent<__VLS_Props$9, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<__VLS_Props$9> & Readonly<{}>, {
881
+ items: ThoughtChainItem[];
882
+ direction: "vertical" | "horizontal";
883
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
884
+ declare const __VLS_export$9: __VLS_WithSlots$8<typeof __VLS_base$8, __VLS_Slots$8>;
885
+ declare const _default$9: typeof __VLS_export$9;
886
+
887
+ type __VLS_WithSlots$8<T, S> = T & {
888
+ new (): {
889
+ $slots: S;
890
+ };
891
+ };
892
+
893
+ type __VLS_Props$8 = {
894
+ /** 图标:字符串为图片地址;也可传组件;缺省渲染内置对话图标 */
895
+ icon?: string | Component;
896
+ /** 名称 */
897
+ name?: string;
898
+ /** 描述(纯文本) */
899
+ description?: string;
900
+ };
901
+ declare var __VLS_1$5: {};
902
+ declare var __VLS_24$1: {};
903
+ declare var __VLS_26$1: {};
904
+ type __VLS_Slots$7 = {} & {
905
+ icon?: (props: typeof __VLS_1$5) => any;
906
+ } & {
907
+ name?: (props: typeof __VLS_24$1) => any;
908
+ } & {
909
+ description?: (props: typeof __VLS_26$1) => any;
910
+ };
911
+ declare const __VLS_base$7: vue.DefineComponent<__VLS_Props$8, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<__VLS_Props$8> & Readonly<{}>, {
912
+ name: string;
913
+ icon: string | Component;
914
+ description: string;
915
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
916
+ declare const __VLS_export$8: __VLS_WithSlots$7<typeof __VLS_base$7, __VLS_Slots$7>;
917
+ declare const _default$8: typeof __VLS_export$8;
918
+
919
+ type __VLS_WithSlots$7<T, S> = T & {
920
+ new (): {
921
+ $slots: S;
922
+ };
923
+ };
924
+
925
+ interface PromptItem {
926
+ key: string | number;
927
+ label?: string;
928
+ description?: string;
929
+ icon?: string | Component;
930
+ disabled?: boolean;
931
+ }
932
+ type __VLS_Props$7 = {
933
+ /** 建议 prompt 列表 */
934
+ prompts?: PromptItem[];
935
+ /** 网格标题 */
936
+ title?: string;
937
+ };
938
+ declare var __VLS_1$4: {
939
+ item: PromptItem;
940
+ index: number;
941
+ };
942
+ type __VLS_Slots$6 = {} & {
943
+ default?: (props: typeof __VLS_1$4) => any;
944
+ };
945
+ declare const __VLS_base$6: vue.DefineComponent<__VLS_Props$7, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
946
+ select: (item: PromptItem) => any;
947
+ }, string, vue.PublicProps, Readonly<__VLS_Props$7> & Readonly<{
948
+ onSelect?: ((item: PromptItem) => any) | undefined;
949
+ }>, {
950
+ title: string;
951
+ prompts: PromptItem[];
952
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
953
+ declare const __VLS_export$7: __VLS_WithSlots$6<typeof __VLS_base$6, __VLS_Slots$6>;
954
+ declare const _default$7: typeof __VLS_export$7;
955
+
956
+ type __VLS_WithSlots$6<T, S> = T & {
957
+ new (): {
958
+ $slots: S;
959
+ };
960
+ };
961
+
962
+ type __VLS_Props$6 = {
963
+ /** 文件名 */
964
+ name: string;
965
+ /** 文件形态:image 渲染缩略图,file 渲染文档图标卡 */
966
+ fileType?: 'image' | 'file';
967
+ /** 文件大小(字节;也接受 '2KB' 这类已格式化字符串,原样展示) */
968
+ size?: number | string;
969
+ /** 图片地址:image 模式下渲染缩略图 */
970
+ url?: string;
971
+ /** 状态:loading 上传中 spinner / success 无标记 / error 红边 */
972
+ status?: 'loading' | 'success' | 'error';
973
+ /** 图片缩略图尺寸(image 模式) */
974
+ imageSize?: string;
975
+ /** 删除回调:右上删除按钮点击时调用 */
976
+ onDelete?: () => void;
977
+ };
978
+ declare var __VLS_1$3: {};
979
+ type __VLS_Slots$5 = {} & {
980
+ image?: (props: typeof __VLS_1$3) => any;
981
+ };
982
+ declare const __VLS_base$5: vue.DefineComponent<__VLS_Props$6, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<__VLS_Props$6> & Readonly<{}>, {
983
+ url: string;
984
+ name: string;
985
+ size: number | string;
986
+ status: "loading" | "success" | "error";
987
+ fileType: "image" | "file";
988
+ imageSize: string;
989
+ onDelete: () => void;
990
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
991
+ declare const __VLS_export$6: __VLS_WithSlots$5<typeof __VLS_base$5, __VLS_Slots$5>;
992
+ declare const _default$6: typeof __VLS_export$6;
993
+
994
+ type __VLS_WithSlots$5<T, S> = T & {
995
+ new (): {
996
+ $slots: S;
997
+ };
998
+ };
999
+
1000
+ /** 列表项:原始 File + 派生展示字段(name/size/url/status 透传 FilesCard) */
1001
+ interface AttachmentItem {
1002
+ uid: string | number;
1003
+ name: string;
1004
+ size?: number;
1005
+ url?: string;
1006
+ fileType?: 'image' | 'file';
1007
+ status?: 'loading' | 'success' | 'error';
1008
+ raw?: File;
1009
+ [key: string]: unknown;
1010
+ }
1011
+ type __VLS_Props$5 = {
1012
+ /** 附件列表(v-model) */
1013
+ modelValue?: object[];
1014
+ /** input[type=file] accept 属性,如 'image/*' */
1015
+ accept?: string;
1016
+ /** 内联提示文案(数量/格式说明) */
1017
+ tip?: string;
1018
+ /** 最大附件数,超出走 @exceed */
1019
+ count?: number;
1020
+ /** 上传前校验,返回 false(或 resolve false)拦截 */
1021
+ beforeUpload?: (file: File) => boolean | Promise<boolean>;
1022
+ /** 布局:inline(默认)按钮+列表+提示一行;triggerOnly 只渲染回形针按钮;listOnly 只渲染文件列表 */
1023
+ layout?: 'inline' | 'triggerOnly' | 'listOnly';
1024
+ };
1025
+ /** 重传:error 项重新置为 loading(具体上传由外部接线,这里只驱动状态流转) */
1026
+ declare function retry(item: AttachmentItem): void;
1027
+ declare function openSelect(): void;
1028
+ declare var __VLS_12: {
1029
+ item: object;
1030
+ index: number;
1031
+ };
1032
+ declare var __VLS_21: {
1033
+ item: object;
1034
+ index: number;
1035
+ };
1036
+ type __VLS_Slots$4 = {} & {
1037
+ 'list-item'?: (props: typeof __VLS_12) => any;
1038
+ } & {
1039
+ 'list-thumb'?: (props: typeof __VLS_21) => any;
1040
+ };
1041
+ declare const __VLS_base$4: vue.DefineComponent<__VLS_Props$5, {
1042
+ openSelect: typeof openSelect;
1043
+ retry: typeof retry;
1044
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1045
+ delete: (item: object) => any;
1046
+ "update:modelValue": (list: object[]) => any;
1047
+ change: (list: object[]) => any;
1048
+ exceed: (file: File) => any;
1049
+ }, string, vue.PublicProps, Readonly<__VLS_Props$5> & Readonly<{
1050
+ onDelete?: ((item: object) => any) | undefined;
1051
+ "onUpdate:modelValue"?: ((list: object[]) => any) | undefined;
1052
+ onChange?: ((list: object[]) => any) | undefined;
1053
+ onExceed?: ((file: File) => any) | undefined;
1054
+ }>, {
1055
+ modelValue: object[];
1056
+ accept: string;
1057
+ tip: string;
1058
+ count: number;
1059
+ beforeUpload: (file: File) => boolean | Promise<boolean>;
1060
+ layout: "inline" | "triggerOnly" | "listOnly";
1061
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
1062
+ declare const __VLS_export$5: __VLS_WithSlots$4<typeof __VLS_base$4, __VLS_Slots$4>;
1063
+ declare const _default$5: typeof __VLS_export$5;
1064
+
1065
+ type __VLS_WithSlots$4<T, S> = T & {
1066
+ new (): {
1067
+ $slots: S;
1068
+ };
1069
+ };
1070
+
1071
+ /** 会话项 */
1072
+ interface ConversationItem {
1073
+ key: string | number;
1074
+ label: string;
1075
+ group?: string;
1076
+ disabled?: boolean;
1077
+ }
1078
+ /** 分组结构:groupable 比较器作用于该对象 */
1079
+ interface ConversationGroup {
1080
+ group?: string;
1081
+ items: ConversationItem[];
1082
+ }
1083
+ /** 内置菜单指令 */
1084
+ type MenuCommand = 'rename' | 'delete';
1085
+ type __VLS_Props$4 = {
1086
+ /** 会话列表(按 group 字段分组,保持插入顺序) */
1087
+ items: ConversationItem[];
1088
+ /** 当前激活会话 key(v-model:active) */
1089
+ active?: string | number;
1090
+ /** 内置菜单按钮显隐方式:hover 悬停显示(默认)/ always 常显 */
1091
+ showBuiltInMenuType?: 'hover' | 'always';
1092
+ /** 分组排序比较器(定制分组顺序;缺省保持插入顺序) */
1093
+ groupable?: (a: ConversationGroup, b: ConversationGroup) => number;
1094
+ /** 下一页加载中(分页场景;loading 时滚动到底不再触发 load-more) */
1095
+ loading?: boolean;
1096
+ /** 是否还有更早分页(缺省 false 表示一次性全量,不触发 load-more) */
1097
+ hasMore?: boolean;
1098
+ };
1099
+ declare function handleMenuCommand(cmd: {
1100
+ item: ConversationItem;
1101
+ command: MenuCommand;
1102
+ }): void;
1103
+ /** renamePrompt(key):弹输入框,确认后 emit menu-command {command:'rename', value:新名称} */
1104
+ declare function renamePrompt(key: string | number): Promise<void>;
1105
+ /** deleteConfirm(key):弹确认框,确认后 emit menu-command {command:'delete'} */
1106
+ declare function deleteConfirm(key: string | number): Promise<void>;
1107
+ declare var __VLS_1$2: {
1108
+ group: string;
1109
+ };
1110
+ declare var __VLS_3: {
1111
+ item: ConversationItem;
1112
+ active: boolean;
1113
+ };
1114
+ declare var __VLS_31: {
1115
+ item: ConversationItem;
1116
+ };
1117
+ type __VLS_Slots$3 = {} & {
1118
+ 'group-title'?: (props: typeof __VLS_1$2) => any;
1119
+ } & {
1120
+ item?: (props: typeof __VLS_3) => any;
1121
+ } & {
1122
+ menu?: (props: typeof __VLS_31) => any;
1123
+ };
1124
+ declare const __VLS_base$3: vue.DefineComponent<__VLS_Props$4, {
1125
+ handleMenuCommand: typeof handleMenuCommand;
1126
+ renamePrompt: typeof renamePrompt;
1127
+ deleteConfirm: typeof deleteConfirm;
1128
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1129
+ change: (item: ConversationItem) => any;
1130
+ "update:active": (key: string | number) => any;
1131
+ "menu-command": (cmd: {
1132
+ item: ConversationItem;
1133
+ command: MenuCommand;
1134
+ value?: string;
1135
+ }) => any;
1136
+ "load-more": () => any;
1137
+ }, string, vue.PublicProps, Readonly<__VLS_Props$4> & Readonly<{
1138
+ onChange?: ((item: ConversationItem) => any) | undefined;
1139
+ "onUpdate:active"?: ((key: string | number) => any) | undefined;
1140
+ "onMenu-command"?: ((cmd: {
1141
+ item: ConversationItem;
1142
+ command: MenuCommand;
1143
+ value?: string;
1144
+ }) => any) | undefined;
1145
+ "onLoad-more"?: (() => any) | undefined;
1146
+ }>, {
1147
+ loading: boolean;
1148
+ items: ConversationItem[];
1149
+ active: string | number;
1150
+ showBuiltInMenuType: "hover" | "always";
1151
+ groupable: (a: ConversationGroup, b: ConversationGroup) => number;
1152
+ hasMore: boolean;
1153
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
1154
+ declare const __VLS_export$4: __VLS_WithSlots$3<typeof __VLS_base$3, __VLS_Slots$3>;
1155
+ declare const _default$4: typeof __VLS_export$4;
1156
+
1157
+ type __VLS_WithSlots$3<T, S> = T & {
1158
+ new (): {
1159
+ $slots: S;
1160
+ };
1161
+ };
1162
+
1163
+ /** adapter 层透传的 OpenAI 风格消息 */
1164
+ interface AdapterChatMessage {
1165
+ role: 'user' | 'assistant' | 'system' | string;
1166
+ content: string;
1167
+ }
1168
+ /** 发送请求体 */
1169
+ interface ChatAdapterRequest {
1170
+ /** 对话消息(时间正序) */
1171
+ messages: Array<{
1172
+ role: string;
1173
+ content: string;
1174
+ }>;
1175
+ /** 覆盖配置中的模型 */
1176
+ model?: string;
1177
+ /** 是否流式,默认 true */
1178
+ stream?: boolean;
1179
+ /** 外部中止信号(与 adapter 内部 abort 合并生效) */
1180
+ signal?: AbortSignal;
1181
+ }
1182
+ /** 服务端原始 usage(snake_case,按 OpenAI 规范原样回调) */
1183
+ interface RawUsage {
1184
+ prompt_tokens?: number;
1185
+ completion_tokens?: number;
1186
+ total_tokens?: number;
1187
+ }
1188
+ /** 流式/响应过程回调集合 */
1189
+ interface ChatAdapterHandlers {
1190
+ /** 正文增量 */
1191
+ onDelta(text: string): void;
1192
+ /** 思考链增量(reasoning_content) */
1193
+ onReasoning(text: string): void;
1194
+ /** token 用量(部分服务端在最后一帧携带) */
1195
+ onUsage(u: RawUsage): void;
1196
+ /**
1197
+ * 后端消息行 id 锚定(可选):流式 message_end 时携带的最终文本行 id,
1198
+ * 与 message_start 的首轮 GENERATING 行 id 可能不同(多轮工具循环),UI 落库/对账以它为准
1199
+ */
1200
+ onBackendMessageId?(id: string): void;
1201
+ /** 工具调用轨迹事件(可选):det-oms 风格 tool{status:start|done} */
1202
+ onTool?(ev: {
1203
+ toolName: string;
1204
+ status: 'start' | 'done';
1205
+ }): void;
1206
+ /** 正常结束(含非流式) */
1207
+ onDone(): void;
1208
+ /** 出错(HTTP 非 2xx / 网络 / 中断) */
1209
+ onError(e: Error): void;
1210
+ }
1211
+ /**
1212
+ * 聊天后端适配器:一次 send 对应一次完整生成(流式到 onDone 或出错进 onError)。
1213
+ * Task 17 useChat 消费该接口,可替换为自研后端/Ollama 等实现。
1214
+ */
1215
+ interface ChatAdapter {
1216
+ send(req: ChatAdapterRequest, handlers: ChatAdapterHandlers): Promise<void>;
1217
+ /** 中止全部进行中的请求(并发 send 各自独立可中止;已完成的请求不受影响) */
1218
+ abort(): void;
1219
+ }
1220
+ /** OpenAI 兼容服务配置 */
1221
+ interface OpenAIAdapterConfig {
1222
+ /** 服务根地址,如 https://api.openai.com/v1,内部拼接 /chat/completions */
1223
+ baseURL: string;
1224
+ /** Bearer Token 密钥 */
1225
+ apiKey?: string;
1226
+ /** 默认模型,可被 req.model 覆盖 */
1227
+ model?: string;
1228
+ }
1229
+ /**
1230
+ * OpenAI 兼容 ChatAdapter(/v1/chat/completions)。
1231
+ * 流式走 Task 2 的 createSSEParser 解析 SSE,兼容 deepseek 风格 reasoning_content。
1232
+ */
1233
+ declare function OpenAIAdapter(config: OpenAIAdapterConfig): ChatAdapter;
1234
+
1235
+ /**
1236
+ * det-oms(`/api/ai-chat/*`)风格聊天适配器:五事件 SSE 协议
1237
+ * (message_start / tool / delta / message_end / error),POST `/message/send`。
1238
+ * 协议细节见 det-oms 前端接入文档 §4;本适配器负责协议解析与事件分发,
1239
+ * 会话管理(列表/归档/删除等)由消费方直接调后端,不经此适配器。
1240
+ */
1241
+ /** send 请求体(sessionId 由工厂按当前会话惰性注入) */
1242
+ interface DetOmsSendBody {
1243
+ sessionId: string;
1244
+ content: string;
1245
+ }
1246
+ /** 工具事件载荷(det-oms SSE `tool` 事件 data) */
1247
+ interface DetOmsToolEvent {
1248
+ toolName: string;
1249
+ status: 'start' | 'done';
1250
+ }
1251
+ /** 会话列表项(`/session/list` records 行;total 等 IPage 字段为字符串需 parseInt) */
1252
+ interface DetOmsSessionItem {
1253
+ id: string;
1254
+ title: string;
1255
+ titleSource?: 'AUTO' | 'MANUAL';
1256
+ status?: 'ACTIVE' | 'ARCHIVED';
1257
+ archivedTime?: string | null;
1258
+ messageCount?: number;
1259
+ lastMessageExcerpt?: string | null;
1260
+ lastMessageTime?: string | null;
1261
+ createdTime?: string;
1262
+ updatedTime?: string;
1263
+ }
1264
+ /** 历史/详情消息行(assistant 行 toolCalls 为 JSON 字符串,消费方自行 JSON.parse) */
1265
+ interface DetOmsMessage {
1266
+ id: string;
1267
+ seq: number;
1268
+ role: 'user' | 'assistant' | 'tool';
1269
+ content: string | null;
1270
+ toolCalls?: string | null;
1271
+ toolCallId?: string | null;
1272
+ toolName?: string | null;
1273
+ status?: 'GENERATING' | 'SUCCESS' | 'FAILED' | 'INTERRUPTED' | null;
1274
+ failReason?: string | null;
1275
+ promptTokens?: number | null;
1276
+ completionTokens?: number | null;
1277
+ /** Long 全局转字符串 */
1278
+ elapsedMs?: string | null;
1279
+ createdTime?: string;
1280
+ }
1281
+ /** 会话详情出参(`/session/detail`) */
1282
+ interface DetOmsSessionDetail {
1283
+ session: DetOmsSessionItem;
1284
+ messages: DetOmsMessage[];
1285
+ }
1286
+ /** 消息 history 分页出参(`/message/history`) */
1287
+ interface DetOmsMessagePage {
1288
+ messages: DetOmsMessage[];
1289
+ hasMore: boolean;
1290
+ }
1291
+ interface DetOmsChatAdapterConfig {
1292
+ /** 服务根地址,如 https://host 或 /api(内部拼接 /ai-chat/message/send) */
1293
+ baseURL: string;
1294
+ /** 请求头(如 { Authorization: 'Bearer ' + token }),每次 send 惰性取用 */
1295
+ headers?: Record<string, string> | (() => Record<string, string>);
1296
+ /** 当前会话 id(工厂惰性取用:切换会话后下一次 send 即生效) */
1297
+ sessionId: string | (() => string);
1298
+ /** 业务错误码 → 提示文案映射(如 { 90602: '已有进行中的对话' });命中时 onError 的 message 用映射文案 */
1299
+ errorMessages?: Record<number, string>;
1300
+ }
1301
+ /** 带业务码的错误:同步段 JSON 错误(90601/90602/90603/90105)与 SSE error 事件统一走此形态 */
1302
+ declare class DetOmsError extends Error {
1303
+ code?: number | string;
1304
+ constructor(message: string, code?: number | string);
1305
+ }
1306
+ /**
1307
+ * det-oms 聊天适配器:消费五事件 SSE。
1308
+ * 同步段失败(会话不存在/单飞行闸/未启用/参数校验)发生在 SSE 建立前,
1309
+ * 响应是普通 JSON 错误——此处按 Content-Type 分流,命中 errorMessages 时用映射文案。
1310
+ * 消息三角色里的 tool 行(toolCallId 配对)是会话管理端的落库形态,
1311
+ * 流式期间只有 tool{status} 事件(无 tool 行),由 onTool 上抛给消费方展示工具状态。
1312
+ */
1313
+ declare function DetOmsChatAdapter(config: DetOmsChatAdapterConfig): ChatAdapter;
1314
+
1315
+ /**
1316
+ * 会话/消息持久化适配器。
1317
+ * Task 17 useChat 用它保存会话列表与 messageTree 序列化结果,
1318
+ * 接口为 async 以便未来替换为 IndexedDB/后端存储而不改调用方。
1319
+ */
1320
+ interface StorageAdapter {
1321
+ get<T>(key: string): Promise<T | undefined>;
1322
+ set<T>(key: string, val: T): Promise<void>;
1323
+ remove(key: string): Promise<void>;
1324
+ }
1325
+ /**
1326
+ * localStorage 存储适配器。
1327
+ * mock/SSR 环境探测失败时自动降级为内存实现(数据不持久化,但不崩)。
1328
+ */
1329
+ declare function createLocalStorageAdapter(): StorageAdapter;
1330
+ /** 纯内存存储适配器(测试/降级用,页面刷新即失) */
1331
+ declare function createMemoryAdapter(): StorageAdapter;
1332
+
1333
+ interface SSEEvent {
1334
+ event?: string;
1335
+ data: string;
1336
+ }
1337
+ interface SSEParser {
1338
+ push(chunk: string): void;
1339
+ end(): void;
1340
+ }
1341
+ declare function createSSEParser(onEvent: (ev: SSEEvent) => void, options?: {
1342
+ streamSeparator?: string;
1343
+ partSeparator?: string;
1344
+ kvSeparator?: string;
1345
+ }): SSEParser;
1346
+
1347
+ /**
1348
+ * @fv-ui/ai-chat 公共类型汇聚出口。
1349
+ * 标量/树形消息等基础类型在本文件直接定义(单一事实来源,消除 messageTree ↔ types 循环引用);
1350
+ * core 其余模块(adapter/storage/sse)的类型在此汇聚再导出,
1351
+ * 消费方 `import type { MessageNode, ChatAdapter, ... } from '@fv-ui/ai-chat'`。
1352
+ */
1353
+ /** 消息角色 */
1354
+ type MessageRole = 'user' | 'assistant';
1355
+ /** 消息生命周期状态 */
1356
+ type MessageStatus = 'pending' | 'streaming' | 'done' | 'error';
1357
+ /**
1358
+ * 工具调用轨迹项(det-oms 风格):assistant 行 toolCalls 展开后的单个工具调用。
1359
+ * 兼容 OpenAI function calling 形状(type/function.name/function.arguments)。
1360
+ */
1361
+ interface ToolCallItem {
1362
+ id: string;
1363
+ type?: string;
1364
+ function?: {
1365
+ name?: string;
1366
+ arguments?: string;
1367
+ };
1368
+ [k: string]: unknown;
1369
+ }
1370
+ /** token 用量(camelCase;adapter 层 snake_case 的 RawUsage 到此的映射责任在包装层) */
1371
+ interface MessageUsage {
1372
+ promptTokens?: number;
1373
+ completionTokens?: number;
1374
+ totalTokens?: number;
1375
+ }
1376
+ /** 消息附件文件描述(序列化安全:只含可 JSON 化字段,不含 File 原始对象) */
1377
+ interface ChatFile {
1378
+ /** 附件唯一标识 */
1379
+ id: string;
1380
+ /** 文件名 */
1381
+ name: string;
1382
+ /** 体积(字节) */
1383
+ size?: number;
1384
+ /** 预览/下载地址(data URL 或远程地址) */
1385
+ url?: string;
1386
+ /** 附件类别,缺省按 'file' 处理 */
1387
+ type?: 'image' | 'file';
1388
+ }
1389
+ /** 树形消息节点(同构 open-webui 会话消息:parentId/childrenIds 构成分支树) */
1390
+ interface MessageNode {
1391
+ id: string;
1392
+ role: MessageRole;
1393
+ content: string;
1394
+ /** 思考链全文(流式期间由包装层追加) */
1395
+ reasoning?: string;
1396
+ /** 附件列表 */
1397
+ files?: ChatFile[];
1398
+ /** 多模型对话中的模型序号(open-webui 语义) */
1399
+ modelIdx?: number;
1400
+ /** 生成模型名 */
1401
+ model?: string;
1402
+ /** 后端消息行 id(det-oms 等带会话管理后端):流式 message_end 时回填,UI 落库/对账锚定用 */
1403
+ backendId?: string;
1404
+ /** 中间轮工具调用列表(JSON 字符串或已展开数组;det-oms assistant 行 toolCalls 非空即中间轮) */
1405
+ toolCalls?: string | ToolCallItem[];
1406
+ /** 父节点 id,根消息为 null */
1407
+ parentId: string | null;
1408
+ /** 子节点 id 列表(多个子节点即多个分支回答) */
1409
+ childrenIds: string[];
1410
+ status?: MessageStatus;
1411
+ /** status 为 'error' 时的错误描述 */
1412
+ error?: string;
1413
+ /** 创建时间戳(ms) */
1414
+ createdAt: number;
1415
+ usage?: MessageUsage;
1416
+ }
1417
+ /** addMessage 入参:id/childrenIds 由树生成;parentId 缺省挂到当前焦点 */
1418
+ type MessageNodeInput = Omit<MessageNode, 'id' | 'parentId' | 'childrenIds' | 'createdAt'> & {
1419
+ /** 挂载父节点;undefined 挂到当前焦点,null 强制为根消息 */
1420
+ parentId?: string | null;
1421
+ /** 创建时间戳;缺省 Date.now() */
1422
+ createdAt?: number;
1423
+ };
1424
+ /** 分支导航方向 */
1425
+ type BranchDirection = 'prev' | 'next';
1426
+ /** 树形消息数据结构(纯函数对象,非响应式;useMessages 包装 reactive 驱动视图) */
1427
+ interface MessageTree {
1428
+ messages: Record<string, MessageNode>;
1429
+ currentId: string | null;
1430
+ addMessage(node: MessageNodeInput): string;
1431
+ deleteMessage(id: string): void;
1432
+ editMessage(id: string, patch: Partial<MessageNode>): void;
1433
+ appendContent(id: string, text: string): void;
1434
+ navigateBranch(id: string, dir: BranchDirection): string | null;
1435
+ setCurrent(id: string): void;
1436
+ getCurrentChain(): MessageNode[];
1437
+ getSiblings(id: string): MessageNode[];
1438
+ toJSON(): string;
1439
+ fromJSON(s: string): void;
1440
+ }
1441
+
1442
+ /** 建议项(Prompts PromptItem 同构:key 必填) */
1443
+ interface AiMessagesSuggestion {
1444
+ key: string | number;
1445
+ label?: string;
1446
+ description?: string;
1447
+ icon?: string | Component;
1448
+ disabled?: boolean;
1449
+ }
1450
+ type __VLS_Props$3 = {
1451
+ /** 当前链消息(根 → 焦点,时间正序) */
1452
+ messages: MessageNode[];
1453
+ /** 全量节点表(分支计算需查父节点 childrenIds) */
1454
+ nodes?: Record<string, MessageNode>;
1455
+ /** 空态欢迎页图标 */
1456
+ icon?: string | Component;
1457
+ /** 空态欢迎页名称 */
1458
+ name?: string;
1459
+ /** 空态欢迎页描述 */
1460
+ description?: string;
1461
+ /** 空态建议列表(Prompts) */
1462
+ suggestions?: AiMessagesSuggestion[];
1463
+ /** 空态建议区标题 */
1464
+ suggestionsTitle?: string;
1465
+ /** 用户上滚免打扰阈值(px):距底不超过该值才自动吸底 */
1466
+ scrollThreshold?: number;
1467
+ /** 显示消息操作按钮 */
1468
+ showActions?: boolean;
1469
+ /** 显示分支切换器 */
1470
+ showBranchSwitch?: boolean;
1471
+ };
1472
+ declare function scrollToBottom(smooth?: boolean): void;
1473
+ /** 回到顶部:与 scrollToBottom 同款 try/catch 回落(happy-dom 旧版 scrollTo(options) 可能缺实现) */
1474
+ declare function scrollToTop(): void;
1475
+ declare var __VLS_1$1: {};
1476
+ declare var __VLS_26: {
1477
+ message: MessageNode;
1478
+ };
1479
+ declare var __VLS_29: {
1480
+ message: MessageNode;
1481
+ };
1482
+ type __VLS_Slots$2 = {} & {
1483
+ empty?: (props: typeof __VLS_1$1) => any;
1484
+ } & {
1485
+ 'message-avatar'?: (props: typeof __VLS_26) => any;
1486
+ } & {
1487
+ 'message-actions'?: (props: typeof __VLS_29) => any;
1488
+ };
1489
+ declare const __VLS_base$2: vue.DefineComponent<__VLS_Props$3, {
1490
+ scrollToBottom: typeof scrollToBottom;
1491
+ scrollToTop: typeof scrollToTop;
1492
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1493
+ select: (item: AiMessagesSuggestion) => any;
1494
+ copy: (message: MessageNode) => any;
1495
+ regenerate: (message: MessageNode) => any;
1496
+ "branch-change": (dir: BranchDirection, message: MessageNode) => any;
1497
+ }, string, vue.PublicProps, Readonly<__VLS_Props$3> & Readonly<{
1498
+ onSelect?: ((item: AiMessagesSuggestion) => any) | undefined;
1499
+ onCopy?: ((message: MessageNode) => any) | undefined;
1500
+ onRegenerate?: ((message: MessageNode) => any) | undefined;
1501
+ "onBranch-change"?: ((dir: BranchDirection, message: MessageNode) => any) | undefined;
1502
+ }>, {
1503
+ name: string;
1504
+ icon: string | Component;
1505
+ nodes: Record<string, MessageNode>;
1506
+ description: string;
1507
+ showActions: boolean;
1508
+ showBranchSwitch: boolean;
1509
+ suggestions: AiMessagesSuggestion[];
1510
+ suggestionsTitle: string;
1511
+ scrollThreshold: number;
1512
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
1513
+ declare const __VLS_export$3: __VLS_WithSlots$2<typeof __VLS_base$2, __VLS_Slots$2>;
1514
+ declare const _default$3: typeof __VLS_export$3;
1515
+
1516
+ type __VLS_WithSlots$2<T, S> = T & {
1517
+ new (): {
1518
+ $slots: S;
1519
+ };
1520
+ };
1521
+
1522
+ /** 建议项(空态 Prompts)——空接口再导出仅为语义命名,保留 */
1523
+ interface AiChatSuggestion extends AiMessagesSuggestion {
1524
+ }
1525
+ /** 可选特性开关 */
1526
+ interface AiChatFeatures {
1527
+ artifacts?: boolean;
1528
+ tts?: boolean;
1529
+ queue?: boolean;
1530
+ continueGenerate?: boolean;
1531
+ fullscreenEditor?: boolean;
1532
+ }
1533
+ type __VLS_Props$2 = {
1534
+ /** 默认模型(顶栏单选展示;未传 models 时作为单模型) */
1535
+ model?: string;
1536
+ /** 可选模型列表(multiple 选择器) */
1537
+ models?: string[];
1538
+ /** OpenAI 兼容服务地址(未传 adapter 时用它构造 OpenAIAdapter) */
1539
+ baseURL?: string;
1540
+ /** OpenAI 兼容服务密钥 */
1541
+ apiKey?: string;
1542
+ /** 聊天适配器(与 baseURL 二选一,优先) */
1543
+ adapter?: ChatAdapter;
1544
+ /** 消息链(v-model:messages,扁平数组同步) */
1545
+ messages?: MessageNode[];
1546
+ /** 顶栏标题 */
1547
+ title?: string;
1548
+ /** 输入框占位 */
1549
+ placeholder?: string;
1550
+ /** 空态建议列表 */
1551
+ suggestions?: AiChatSuggestion[];
1552
+ /** 特性开关 */
1553
+ features?: AiChatFeatures;
1554
+ /** 开启输入区附件上传(输入框上方回形针 + 附件列表,发送时随 @send 上抛 files) */
1555
+ allowAttachments?: boolean;
1556
+ /** 附件 input accept 属性(透传 Attachments),如 'image/*' */
1557
+ accept?: string;
1558
+ /** 附件数量上限(透传 Attachments,0 不限) */
1559
+ attachmentLimit?: number;
1560
+ /** 主题:light/dark/auto(注入 html dark class) */
1561
+ theme?: 'light' | 'dark' | 'auto';
1562
+ };
1563
+ /** 停止生成:生成在途时置位 stopped(空闲时无待收口轮次,不置位避免残留误吞下一轮),再中止在途请求 */
1564
+ declare function stop(): void;
1565
+ /** 重生成:UI 与 ref 路径共用同一包装,完成后统一收口上抛事件(两条路径行为一致) */
1566
+ declare function regenerate(messageId?: string): void;
1567
+ declare function sendMessage(text: string, files?: ChatFile[]): void;
1568
+ /** 向指定消息追加文本(编辑/续写场景) */
1569
+ declare function appendToMessage(id: string, text: string): void;
1570
+ /** 清空消息树(整框重置) */
1571
+ declare function clearMessages(): void;
1572
+ /** 导出当前链为纯文本(角色: 内容 逐条) */
1573
+ declare function exportTxt(): string;
1574
+ /** 程序化打开某个 artifact(ref 方法) */
1575
+ declare function openArtifact(key: string): void;
1576
+ declare var __VLS_24: {
1577
+ message: MessageNode;
1578
+ };
1579
+ declare var __VLS_27: {
1580
+ message: MessageNode;
1581
+ };
1582
+ declare var __VLS_30: {};
1583
+ declare var __VLS_66: {};
1584
+ type __VLS_Slots$1 = {} & {
1585
+ 'message-avatar'?: (props: typeof __VLS_24) => any;
1586
+ } & {
1587
+ 'message-actions'?: (props: typeof __VLS_27) => any;
1588
+ } & {
1589
+ empty?: (props: typeof __VLS_30) => any;
1590
+ } & {
1591
+ 'sender-prefix'?: (props: typeof __VLS_66) => any;
1592
+ };
1593
+ declare const __VLS_base$1: vue.DefineComponent<__VLS_Props$2, {
1594
+ sendMessage: typeof sendMessage;
1595
+ stop: typeof stop;
1596
+ regenerate: typeof regenerate;
1597
+ appendToMessage: typeof appendToMessage;
1598
+ clearMessages: typeof clearMessages;
1599
+ exportTxt: typeof exportTxt;
1600
+ openArtifact: typeof openArtifact;
1601
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1602
+ error: (err: Error, message?: MessageNode | undefined) => any;
1603
+ "branch-change": (dir: BranchDirection, message: MessageNode) => any;
1604
+ "update:messages": (value: MessageNode[]) => any;
1605
+ send: (text: string, files?: ChatFile[] | undefined) => any;
1606
+ "message-complete": (message: MessageNode) => any;
1607
+ "attachment-exceed": (file: File) => any;
1608
+ "tool-event": (ev: {
1609
+ toolName: string;
1610
+ status: "start" | "done";
1611
+ }) => any;
1612
+ }, string, vue.PublicProps, Readonly<__VLS_Props$2> & Readonly<{
1613
+ onError?: ((err: Error, message?: MessageNode | undefined) => any) | undefined;
1614
+ "onBranch-change"?: ((dir: BranchDirection, message: MessageNode) => any) | undefined;
1615
+ "onUpdate:messages"?: ((value: MessageNode[]) => any) | undefined;
1616
+ onSend?: ((text: string, files?: ChatFile[] | undefined) => any) | undefined;
1617
+ "onMessage-complete"?: ((message: MessageNode) => any) | undefined;
1618
+ "onAttachment-exceed"?: ((file: File) => any) | undefined;
1619
+ "onTool-event"?: ((ev: {
1620
+ toolName: string;
1621
+ status: "start" | "done";
1622
+ }) => any) | undefined;
1623
+ }>, {
1624
+ title: string;
1625
+ placeholder: string;
1626
+ accept: string;
1627
+ baseURL: string;
1628
+ apiKey: string;
1629
+ model: string;
1630
+ messages: MessageNode[];
1631
+ suggestions: AiChatSuggestion[];
1632
+ models: string[];
1633
+ adapter: ChatAdapter;
1634
+ features: AiChatFeatures;
1635
+ allowAttachments: boolean;
1636
+ attachmentLimit: number;
1637
+ theme: "light" | "dark" | "auto";
1638
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
1639
+ declare const __VLS_export$2: __VLS_WithSlots$1<typeof __VLS_base$1, __VLS_Slots$1>;
1640
+ declare const _default$2: typeof __VLS_export$2;
1641
+
1642
+ type __VLS_WithSlots$1<T, S> = T & {
1643
+ new (): {
1644
+ $slots: S;
1645
+ };
1646
+ };
1647
+
1648
+ /** 单条消息展示需要的分支元数据(由 AiMessages 计算注入) */
1649
+ interface AiMessageBranchInfo {
1650
+ /** 同层分支总数 */
1651
+ count: number;
1652
+ /** 当前分支序号(1 起) */
1653
+ index: number;
1654
+ }
1655
+ type __VLS_Props$1 = {
1656
+ /** 消息节点(树节点代理,流式期间 content/reasoning 增长驱动更新) */
1657
+ message: MessageNode;
1658
+ /** 同层分支元数据;缺省视为单分支(不渲染切换器) */
1659
+ branch?: AiMessageBranchInfo;
1660
+ /** 显示操作按钮(复制/重生成;仅 assistant) */
1661
+ showActions?: boolean;
1662
+ /** 显示分支切换器(branch.count > 1 时) */
1663
+ showBranchSwitch?: boolean;
1664
+ /** Thinking autoCollapse 透传 */
1665
+ autoCollapse?: boolean;
1666
+ };
1667
+ declare var __VLS_1: {
1668
+ message: MessageNode;
1669
+ };
1670
+ declare var __VLS_25: {
1671
+ message: MessageNode;
1672
+ files: ChatFile[];
1673
+ };
1674
+ declare var __VLS_44: {
1675
+ message: MessageNode;
1676
+ };
1677
+ type __VLS_Slots = {} & {
1678
+ 'message-avatar'?: (props: typeof __VLS_1) => any;
1679
+ } & {
1680
+ 'message-files'?: (props: typeof __VLS_25) => any;
1681
+ } & {
1682
+ 'message-actions'?: (props: typeof __VLS_44) => any;
1683
+ };
1684
+ declare const __VLS_base: vue.DefineComponent<__VLS_Props$1, {
1685
+ message: vue.ComputedRef<MessageNode>;
1686
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1687
+ copy: (message: MessageNode) => any;
1688
+ regenerate: (message: MessageNode) => any;
1689
+ "branch-change": (dir: BranchDirection, message: MessageNode) => any;
1690
+ }, string, vue.PublicProps, Readonly<__VLS_Props$1> & Readonly<{
1691
+ onCopy?: ((message: MessageNode) => any) | undefined;
1692
+ onRegenerate?: ((message: MessageNode) => any) | undefined;
1693
+ "onBranch-change"?: ((dir: BranchDirection, message: MessageNode) => any) | undefined;
1694
+ }>, {
1695
+ autoCollapse: boolean;
1696
+ branch: AiMessageBranchInfo;
1697
+ showActions: boolean;
1698
+ showBranchSwitch: boolean;
1699
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
1700
+ declare const __VLS_export$1: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
1701
+ declare const _default$1: typeof __VLS_export$1;
1702
+
1703
+ type __VLS_WithSlots<T, S> = T & {
1704
+ new (): {
1705
+ $slots: S;
1706
+ };
1707
+ };
1708
+
1709
+ /** 单个 artifact 项 */
1710
+ interface AiArtifactItem {
1711
+ /** 唯一 key */
1712
+ key: string;
1713
+ /** 内容类型:html / svg */
1714
+ type: 'html' | 'svg';
1715
+ /** 原始内容(html 片段或完整 svg 文本) */
1716
+ content: string;
1717
+ /** 展示标题(缺省回退 key) */
1718
+ title?: string;
1719
+ }
1720
+ type __VLS_Props = {
1721
+ /** artifact 列表(从消息 ```html / ```svg 代码块提取组装) */
1722
+ artifacts: AiArtifactItem[];
1723
+ /** 当前展示的 artifact key;为空时面板隐藏 */
1724
+ activeKey?: string;
1725
+ };
1726
+ declare function open(key: string): void;
1727
+ declare function close(): void;
1728
+ declare const __VLS_export: vue.DefineComponent<__VLS_Props, {
1729
+ open: typeof open;
1730
+ close: typeof close;
1731
+ }, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1732
+ change: (key: string) => any;
1733
+ close: () => any;
1734
+ navigate: (href: string) => any;
1735
+ }, string, vue.PublicProps, Readonly<__VLS_Props> & Readonly<{
1736
+ onChange?: ((key: string) => any) | undefined;
1737
+ onClose?: (() => any) | undefined;
1738
+ onNavigate?: ((href: string) => any) | undefined;
1739
+ }>, {
1740
+ artifacts: AiArtifactItem[];
1741
+ activeKey: string;
1742
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
1743
+ declare const _default: typeof __VLS_export;
1744
+
1745
+ interface UseXStreamReturn {
1746
+ startStream(options: {
1747
+ readableStream: ReadableStream<Uint8Array>;
1748
+ transformStream?: TransformStream<any, any>;
1749
+ }): Promise<void>;
1750
+ cancel(): void;
1751
+ data: Ref<SSEEvent[]>;
1752
+ error: Ref<Error | null>;
1753
+ isLoading: Ref<boolean>;
1754
+ }
1755
+ declare function useXStream(): UseXStreamReturn;
1756
+
1757
+ /** send 请求参数 */
1758
+ interface SendOptions {
1759
+ /** 请求地址 */
1760
+ url: string;
1761
+ /** 请求方法,默认 POST */
1762
+ method?: string;
1763
+ /** 请求头 */
1764
+ headers?: Record<string, string>;
1765
+ /** 请求体对象(内部 JSON.stringify) */
1766
+ body?: object;
1767
+ /** 可选转换流,接在 TextDecoderStream 之后(如协议转换) */
1768
+ transformStream?: TransformStream<any, any>;
1769
+ /** 全部 SSE 事件透传(含 event 名;tool/message_start 等非 content 事件不再被吞) */
1770
+ onEvent?: (ev: SSEEvent) => void;
1771
+ /** 内容分片回调:SSE data 为 JSON 且含字符串 content 时逐块触发 */
1772
+ onChunk?: (text: string) => void;
1773
+ }
1774
+ interface UseSendReturn {
1775
+ /** 发起请求并消费 SSE 流(逐块回调 onChunk) */
1776
+ send: (options: SendOptions) => Promise<void>;
1777
+ /** 中止当前请求/流消费 */
1778
+ abort: () => void;
1779
+ loading: Ref<boolean>;
1780
+ error: Ref<Error | null>;
1781
+ }
1782
+ declare function useSend(): UseSendReturn;
1783
+ /**
1784
+ * XRequest:Promise 化的流式请求,resolve 累计全文。
1785
+ * options 同 SendOptions(url 由首参覆盖),onChunk 透传照常触发。
1786
+ */
1787
+ declare function XRequest(url: string, options?: Omit<SendOptions, 'url'>): Promise<string>;
1788
+
1789
+ interface UseRecordReturn {
1790
+ /** 开始录音(+实时转写);失败不抛出,写入 error */
1791
+ start: () => Promise<void>;
1792
+ /** 停止录音与转写,合成 audioUrl */
1793
+ stop: () => void;
1794
+ isRecording: Ref<boolean>;
1795
+ /** 实时转写文本(最终结果 + 中间结果拼接) */
1796
+ text: Ref<string>;
1797
+ /** 录音成品地址(Blob URL),stop 后生成,下次 start 前回收 */
1798
+ audioUrl: Ref<string | null>;
1799
+ error: Ref<Error | null>;
1800
+ }
1801
+ declare function useRecord(): UseRecordReturn;
1802
+
1803
+ /** useMessages 返回体 */
1804
+ interface UseMessagesReturn {
1805
+ /** 全量节点表(深层响应式;新增/删除键与节点字段变更均可被追踪) */
1806
+ messages: Ref<Record<string, MessageNode>>;
1807
+ /** 当前焦点节点 id(根到焦点构成当前链) */
1808
+ currentId: Ref<string | null>;
1809
+ /** 当前链(根 → 焦点,时间正序) */
1810
+ chain: ComputedRef<MessageNode[]>;
1811
+ /** 新增节点,parentId 缺省挂到当前焦点;返回带真实 id 的节点 */
1812
+ add(node: MessageNodeInput): MessageNode;
1813
+ /** 删除节点(子节点升级接替其在父 children 中的位置) */
1814
+ remove(id: string): void;
1815
+ /** 浅合并补丁(id/parentId/childrenIds 不可改) */
1816
+ edit(id: string, patch: Partial<MessageNode>): void;
1817
+ /** 追加正文 */
1818
+ appendContent(id: string, text: string): void;
1819
+ /** 分支导航,返回目标 id(越界返回 null);id 缺省取当前焦点 */
1820
+ navigate(id?: string, dir?: BranchDirection): string | null;
1821
+ /** 同步设置焦点节点(ref 写法经 watch 异步生效,此方法立即同步树内部状态) */
1822
+ setCurrent(id: string): void;
1823
+ /** 绑定/切换持久化适配器(不立即写盘;此后树变更自动去抖落盘) */
1824
+ setStorage(adapter?: StorageAdapter): void;
1825
+ /** 从存储恢复会话(覆盖当前树;无存储/无数据时保持原状) */
1826
+ load(): Promise<void>;
1827
+ /** 立即落盘(树变更后已自动调度,此为手动兜底,主要用于测试) */
1828
+ flush(): Promise<void>;
1829
+ /** 序列化整树({messages, currentId} JSON) */
1830
+ toJSON(): string;
1831
+ }
1832
+ /**
1833
+ * 聊天应用层状态中枢:把 Task 16 的纯数据 MessageTree 包装成响应式。
1834
+ *
1835
+ * 响应式策略:
1836
+ * - messages 用深层 ref 容器,其 .value(reactive 代理)注入树 —— 树内增删/字段写全部经由代理,可被追踪
1837
+ * - currentId 用 ref,与树内部 getter/setter 双向同步(watch 回写树,包装方法后拉取树)
1838
+ * - chain 为 computed,依赖上两者;节点对象本身是代理,消费方读 content 等字段同样响应
1839
+ *
1840
+ * @param initial 初始节点表/焦点(恢复会话时传入)
1841
+ */
1842
+ declare function useMessages(initial?: {
1843
+ messages?: Record<string, MessageNode>;
1844
+ currentId?: string | null;
1845
+ }): UseMessagesReturn;
1846
+
1847
+ /** useChat 配置 */
1848
+ interface UseChatOptions {
1849
+ /** 聊天适配器实例或工厂(工厂每次 send 惰性求值,便于按会话切模型) */
1850
+ adapter: ChatAdapter | (() => ChatAdapter);
1851
+ /** 选中模型列表(多模型生成多个 assistant;缺省单模型)。支持工厂函数,每次 send 惰性取用(顶栏切换模型即时生效) */
1852
+ models?: string[] | (() => string[]);
1853
+ /** 初始消息表/焦点(恢复会话时传入;透传 useMessages) */
1854
+ initial?: {
1855
+ messages?: Record<string, MessageNode>;
1856
+ currentId?: string | null;
1857
+ };
1858
+ /** 工具调用轨迹事件透传(det-oms 风格 tool{status}):展示「正在查询库存…」等中间态 */
1859
+ onToolEvent?: (ev: {
1860
+ toolName: string;
1861
+ status: 'start' | 'done';
1862
+ }) => void;
1863
+ }
1864
+ /** 待发送队列项 */
1865
+ interface QueueItem {
1866
+ text: string;
1867
+ files?: ChatFile[];
1868
+ }
1869
+ /** useChat 返回体 */
1870
+ interface UseChatReturn {
1871
+ /** 发送用户消息并生成回复;生成中再调用被拒(需要排队的走 enqueue) */
1872
+ send(text: string, files?: ChatFile[]): Promise<void>;
1873
+ /** 中止当前生成:adapter.abort + 在途消息置 done(保留已生成内容) */
1874
+ stop(): void;
1875
+ /** 重新生成:焦点回退到末 assistant 的父节点重发生成新分支(旧回答保留在树上);可指定消息 id */
1876
+ regenerate(messageId?: string): Promise<void>;
1877
+ /** 继续生成:以目标 assistant 既有内容为前缀再次请求,增量追加到同一节点 */
1878
+ continueGenerate(messageId?: string): Promise<void>;
1879
+ /** 待发送队列(生成中入队,完成后自动 flush 队首) */
1880
+ queue: Ref<Array<QueueItem>>;
1881
+ /** 生成中入队;空闲时直接发送 */
1882
+ enqueue(text: string, files?: ChatFile[]): void;
1883
+ /** 是否有生成在途 */
1884
+ isLoading: Ref<boolean>;
1885
+ /** 底层消息树读写面(appendToMessage/clearMessages 等整框层操作经此) */
1886
+ msgs: UseMessagesReturn;
1887
+ /** 全量节点表(ref;分支信息/遍历等场景直查,AiChat 整框 v-model 同步用) */
1888
+ messages: UseMessagesReturn['messages'];
1889
+ currentId: UseMessagesReturn['currentId'];
1890
+ chain: UseMessagesReturn['chain'];
1891
+ }
1892
+ /**
1893
+ * 聊天应用层编排:在 useMessages 树状态之上驱动"发送 → 流式回填 → 队列/重生成/续写"生命周期。
1894
+ * 消息形态同构 open-webui:user 消息挂树后追加 pending assistant 节点,adapter 回调增量回填,结束置 done。
1895
+ * 多模型(models 数组/modelIdx 字段)接口形状已对齐,各模型 assistant 挂 user 下互为兄弟分支并发回填。
1896
+ */
1897
+ declare function useChat(options: UseChatOptions): UseChatReturn;
1898
+
1899
+ /**
1900
+ * 创建树形消息数据结构。
1901
+ * 纯函数对象、非响应式;useMessages/useChat 包装 reactive 以驱动视图。
1902
+ * @param initial 初始节点表(恢复会话时传入),currentId 缺省取最后一个无子节点节点
1903
+ */
1904
+ declare function createMessageTree(initial?: {
1905
+ messages?: Record<string, MessageNode>;
1906
+ currentId?: string | null;
1907
+ }): MessageTree;
1908
+
1909
+ declare const version = "0.1.0";
1910
+
1911
+ export { DetOmsChatAdapter, DetOmsError, _default as FvAiArtifacts, _default$2 as FvAiChat, _default$1 as FvAiMessage, _default$3 as FvAiMessages, _default$5 as FvAttachments, _default$f as FvBubble, _default$e as FvBubbleList, _default$4 as FvConversations, _default$b as FvEditorSender, _default$6 as FvFilesCard, _default$h as FvMarkdown, _default$c as FvMentionSender, _default$7 as FvPrompts, _default$d as FvSender, _default$a as FvThinking, _default$9 as FvThoughtChain, _default$g as FvTypewriter, _default$8 as FvWelcome, OpenAIAdapter, XRequest, createLocalStorageAdapter, createMemoryAdapter, createMessageTree, createSSEParser, useChat, useMessages, useRecord, useSend, useXStream, version };
1912
+ export type { AdapterChatMessage, AiArtifactItem, AiChatFeatures, AiChatSuggestion, AiMessageBranchInfo, AiMessagesSuggestion, BranchDirection, ChatAdapter, ChatAdapterHandlers, ChatAdapterRequest, ChatFile, DetOmsChatAdapterConfig, DetOmsMessage, DetOmsMessagePage, DetOmsSendBody, DetOmsSessionDetail, DetOmsSessionItem, DetOmsToolEvent, MessageNode, MessageNodeInput, MessageRole, MessageStatus, MessageTree, MessageUsage, OpenAIAdapterConfig, QueueItem, RawUsage, SSEEvent, SSEParser, SendOptions, StorageAdapter, ToolCallItem, UseChatOptions, UseChatReturn, UseMessagesReturn, UseRecordReturn, UseSendReturn, UseXStreamReturn };