@pactor-app/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.
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/dist/index.cjs +3368 -0
- package/dist/index.d.cts +1401 -0
- package/dist/index.d.ts +1401 -0
- package/dist/index.js +3353 -0
- package/package.json +76 -0
- package/styles.css +1704 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1401 @@
|
|
|
1
|
+
import { DslNode, Registry, PermissionConfig } from '@pactor-app/core';
|
|
2
|
+
import { ActionContext, ActionRegistry, RuntimeContext, ActionEngine } from '@pactor-app/runtime';
|
|
3
|
+
import { PermissionStore } from '@pactor-app/permission';
|
|
4
|
+
import * as react from 'react';
|
|
5
|
+
import { RefObject, ReactNode, ComponentType } from 'react';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 产出物模型与 ArtifactStore(spec: chat-artifact-panel,设计决策 D1)。
|
|
9
|
+
*
|
|
10
|
+
* 零 React,可纯 Node 测试;状态语义与 ConversationStore 同模式
|
|
11
|
+
* (不可变更新 + subscribe 通知,兼容 useSyncExternalStore)。
|
|
12
|
+
* store 只持当前一个产出物:多产出物 / 历史由业务层自行管理后注入。
|
|
13
|
+
*/
|
|
14
|
+
/** 产出物:dsl kind 的 content 为 DslNode 普通对象,其余 kind 为字符串 */
|
|
15
|
+
interface ChatArtifact {
|
|
16
|
+
id: string;
|
|
17
|
+
kind: 'markdown' | 'code' | 'text' | 'dsl';
|
|
18
|
+
title: string;
|
|
19
|
+
content: string | DslNode;
|
|
20
|
+
/** code kind 的语言标记(仅作角标展示) */
|
|
21
|
+
language?: string;
|
|
22
|
+
meta?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/** update 的补丁:id 不可改 */
|
|
25
|
+
type ArtifactPatch = Partial<Omit<ChatArtifact, 'id'>>;
|
|
26
|
+
/**
|
|
27
|
+
* ArtifactStore(设计决策 D1):当前产出物的可变容器。
|
|
28
|
+
* 可注入(services.artifactStore)或由组合层自持(ref 保持)。
|
|
29
|
+
* 对未 open 状态下的 update 宽容:console.warn 并忽略,不抛错。
|
|
30
|
+
*/
|
|
31
|
+
declare class ArtifactStore {
|
|
32
|
+
private artifact;
|
|
33
|
+
private readonly listeners;
|
|
34
|
+
/** 当前产出物(未打开时为 null;引用在不变时保持稳定) */
|
|
35
|
+
get(): ChatArtifact | null;
|
|
36
|
+
/** 打开(或替换)当前产出物 */
|
|
37
|
+
open(artifact: ChatArtifact): void;
|
|
38
|
+
/** 部分更新当前产出物(id 不可改);未 open 时告警并忽略 */
|
|
39
|
+
update(patch: ArtifactPatch): void;
|
|
40
|
+
/** 关闭面板(未打开时幂等,不重复通知) */
|
|
41
|
+
close(): void;
|
|
42
|
+
/** 订阅变更;返回退订函数 */
|
|
43
|
+
subscribe(listener: () => void): () => void;
|
|
44
|
+
private notify;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 消息模型(设计决策 D1,设计文档第 58/59/70 节):
|
|
49
|
+
* AI Message Rendering Protocol 的数据层——消息 + Part 联合类型 +
|
|
50
|
+
* 状态机。零 React,可纯 Node 测试。
|
|
51
|
+
*/
|
|
52
|
+
/** 消息角色 */
|
|
53
|
+
type ChatRole = 'user' | 'assistant' | 'system';
|
|
54
|
+
/** 消息状态机 */
|
|
55
|
+
type MessageStatus = 'pending' | 'streaming' | 'completed' | 'error' | 'cancelled';
|
|
56
|
+
/** Part 状态机(tool-call / tool-result / error / status 使用各自的状态字段) */
|
|
57
|
+
type PartStatus = 'pending' | 'streaming' | 'ready' | 'error';
|
|
58
|
+
/** tool-call part 的执行状态 */
|
|
59
|
+
type ToolCallStatus = 'waiting' | 'running' | 'success' | 'failed';
|
|
60
|
+
/**
|
|
61
|
+
* Part 联合类型:一条消息由有序 Part 数组组成,
|
|
62
|
+
* thinking 与正文分离(设计文档第 72 节)。
|
|
63
|
+
*
|
|
64
|
+
* 各 variant 的 `id` 可选:streaming 事件携带 partId 时按 id 定位,
|
|
65
|
+
* 缺省时 reducer 按"最后一个同类 part"定位。
|
|
66
|
+
*/
|
|
67
|
+
type ChatPart = {
|
|
68
|
+
id?: string;
|
|
69
|
+
type: 'text';
|
|
70
|
+
content: string;
|
|
71
|
+
status?: PartStatus;
|
|
72
|
+
} | {
|
|
73
|
+
id?: string;
|
|
74
|
+
type: 'markdown';
|
|
75
|
+
content: string;
|
|
76
|
+
status?: PartStatus;
|
|
77
|
+
} | {
|
|
78
|
+
id?: string;
|
|
79
|
+
type: 'dsl';
|
|
80
|
+
/** dsl.complete 事件写入;dsl.start 占位阶段缺省(渲染为占位) */
|
|
81
|
+
schema?: DslNode;
|
|
82
|
+
status?: PartStatus;
|
|
83
|
+
} | {
|
|
84
|
+
id?: string;
|
|
85
|
+
type: 'thinking';
|
|
86
|
+
content: string;
|
|
87
|
+
status?: PartStatus;
|
|
88
|
+
} | {
|
|
89
|
+
id?: string;
|
|
90
|
+
type: 'tool-call';
|
|
91
|
+
name: string;
|
|
92
|
+
title?: string;
|
|
93
|
+
/** 调用参数(tool.start 事件携带;供活动轨迹参数摘要 / 详情渲染) */
|
|
94
|
+
args?: unknown;
|
|
95
|
+
status: ToolCallStatus;
|
|
96
|
+
} | {
|
|
97
|
+
id?: string;
|
|
98
|
+
type: 'tool-result';
|
|
99
|
+
name: string;
|
|
100
|
+
status: 'success' | 'failed';
|
|
101
|
+
result?: unknown;
|
|
102
|
+
error?: string;
|
|
103
|
+
} | {
|
|
104
|
+
id?: string;
|
|
105
|
+
type: 'error';
|
|
106
|
+
message: string;
|
|
107
|
+
} | {
|
|
108
|
+
id?: string;
|
|
109
|
+
type: 'status';
|
|
110
|
+
text: string;
|
|
111
|
+
} | {
|
|
112
|
+
id?: string;
|
|
113
|
+
/** 产出物 part(spec: chat-artifact-panel,设计决策 D4):内联渲染为产出物卡片 */
|
|
114
|
+
type: 'artifact';
|
|
115
|
+
artifact: ChatArtifact;
|
|
116
|
+
status?: PartStatus;
|
|
117
|
+
};
|
|
118
|
+
/** 消息附件引用(上传与存储由调用方负责,包内只持有引用) */
|
|
119
|
+
interface ChatAttachment {
|
|
120
|
+
id: string;
|
|
121
|
+
name: string;
|
|
122
|
+
mimeType: string;
|
|
123
|
+
size?: number;
|
|
124
|
+
url?: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 上下文项(spec: chat-context-sources,设计决策 D6):
|
|
128
|
+
* 选中候选追加为 Composer 上方 chips;`label` 用于 chip 展示,
|
|
129
|
+
* `trigger` 标记来源入口('@' 提及 / '+' 菜单),`data` 为 source 项
|
|
130
|
+
* 原始数据(如 agentId),transport 可结构化消费。
|
|
131
|
+
*/
|
|
132
|
+
interface ChatContextItem {
|
|
133
|
+
id: string;
|
|
134
|
+
label: string;
|
|
135
|
+
trigger?: '@' | '+';
|
|
136
|
+
data?: unknown;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 上下文数据源(spec: chat-context-sources,设计决策 D1):
|
|
140
|
+
* `trigger` 标记入口('@' 提及弹层 / '+' 菜单);`items` 为静态候选
|
|
141
|
+
* 数组;`service` + `params` 为声明式服务引用,经注入的
|
|
142
|
+
* `ChatServices.callService(name, params)` 解析为 `ChatContextItem[]`
|
|
143
|
+
* (结果按 source 键会话级缓存)。全部为 DSL 可表达数据。
|
|
144
|
+
*/
|
|
145
|
+
interface ChatContextSource {
|
|
146
|
+
trigger: '@' | '+';
|
|
147
|
+
/** 来源名(弹层分组展示 / 错误提示用) */
|
|
148
|
+
label: string;
|
|
149
|
+
/** 静态候选数组;与 service 二选一 */
|
|
150
|
+
items?: ChatContextItem[];
|
|
151
|
+
/** 声明式服务引用(经 callService 解析) */
|
|
152
|
+
service?: string;
|
|
153
|
+
/** service 调用参数 */
|
|
154
|
+
params?: Record<string, unknown>;
|
|
155
|
+
}
|
|
156
|
+
/** 模型选项(spec: chat-model-selector):value 进 ChatInput.model,label 用于 chip 展示 */
|
|
157
|
+
interface ChatModelOption {
|
|
158
|
+
value: string;
|
|
159
|
+
label: string;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* 内建消息动作名(spec: chat-message-actions,设计决策 D1):
|
|
163
|
+
* 数组项为字符串时等价于 `{ id: <name>, builtin: <name> }`
|
|
164
|
+
*/
|
|
165
|
+
type BuiltinMessageAction = 'copy' | 'regenerate' | 'retry' | 'edit';
|
|
166
|
+
/**
|
|
167
|
+
* 消息操作条动作描述(spec: chat-message-actions,设计决策 D1):
|
|
168
|
+
* 全部为 DSL 可表达数据——`builtin` 指定时复用内建行为(label / icon /
|
|
169
|
+
* roles / visibleWhen 按字段覆盖内建默认描述);无 `builtin` 为自定义
|
|
170
|
+
* 动作,点击经 `ChatServices.callService(service, { actionId, message })`
|
|
171
|
+
* 派发并并行触发 `onMessageAction` 通知。
|
|
172
|
+
*/
|
|
173
|
+
interface ChatMessageAction {
|
|
174
|
+
/** 动作标识(服务派发 actionId 与事件 event.action 用) */
|
|
175
|
+
id: string;
|
|
176
|
+
/** 指定则复用内建行为与默认描述(可逐字段覆盖) */
|
|
177
|
+
builtin?: BuiltinMessageAction;
|
|
178
|
+
/** tooltip 文案;缺省用内建默认(自定义动作缺省回退为 id) */
|
|
179
|
+
label?: string;
|
|
180
|
+
/** 图标名(MESSAGE_ACTION_ICONS 白名单);未知名渲染占位图标 */
|
|
181
|
+
icon?: string;
|
|
182
|
+
/** 可见角色;自定义动作缺省 ['assistant'] */
|
|
183
|
+
roles?: Array<'user' | 'assistant'>;
|
|
184
|
+
/**
|
|
185
|
+
* 可见状态:'completed' 匹配非流式非错误终态(含 cancelled),
|
|
186
|
+
* 'error' 匹配 error,'always' 含 streaming;自定义动作缺省 'completed'
|
|
187
|
+
*/
|
|
188
|
+
visibleWhen?: 'completed' | 'error' | 'always';
|
|
189
|
+
/** 自定义动作的派发服务名(经注入的 callService 解析) */
|
|
190
|
+
service?: string;
|
|
191
|
+
}
|
|
192
|
+
/** Chat 消息 */
|
|
193
|
+
interface ChatMessage {
|
|
194
|
+
id: string;
|
|
195
|
+
role: ChatRole;
|
|
196
|
+
status: MessageStatus;
|
|
197
|
+
parts: ChatPart[];
|
|
198
|
+
createdAt?: number;
|
|
199
|
+
attachments?: ChatAttachment[];
|
|
200
|
+
}
|
|
201
|
+
/** updatePart 的定位参数:数组下标或 part id */
|
|
202
|
+
type PartRef = number | string;
|
|
203
|
+
/** updateMessage 的补丁:id 不可改 */
|
|
204
|
+
type MessagePatch = Partial<Omit<ChatMessage, 'id'>>;
|
|
205
|
+
/** updatePart 的补丁(宽类型:按目标 part variant 取子集) */
|
|
206
|
+
type PartPatch = Partial<{
|
|
207
|
+
content: string;
|
|
208
|
+
schema: DslNode;
|
|
209
|
+
status: string;
|
|
210
|
+
name: string;
|
|
211
|
+
title: string;
|
|
212
|
+
args: unknown;
|
|
213
|
+
result: unknown;
|
|
214
|
+
error: string;
|
|
215
|
+
message: string;
|
|
216
|
+
text: string;
|
|
217
|
+
artifact: ChatArtifact;
|
|
218
|
+
}>;
|
|
219
|
+
/** 生成 Chat 侧消息 / part id(单调后缀保证同毫秒唯一) */
|
|
220
|
+
declare function createChatId(prefix?: string): string;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* ConversationStore(设计决策 D1):消息列表的可变容器,零 React。
|
|
224
|
+
*
|
|
225
|
+
* 全部更新不可变:每次变更产生新的 messages 数组引用(被修改的
|
|
226
|
+
* 消息 / part 同样为新对象),`getMessages()` 引用仅在变化时改变,
|
|
227
|
+
* 兼容 React `useSyncExternalStore` 的 snapshot 语义。
|
|
228
|
+
*
|
|
229
|
+
* 对未知 messageId 的更新宽容:console.warn 并忽略,不抛错。
|
|
230
|
+
*/
|
|
231
|
+
declare class ConversationStore {
|
|
232
|
+
private messages;
|
|
233
|
+
private readonly listeners;
|
|
234
|
+
/** 当前消息数组(只读快照;引用在不变时保持稳定) */
|
|
235
|
+
getMessages(): ChatMessage[];
|
|
236
|
+
getMessage(id: string): ChatMessage | undefined;
|
|
237
|
+
/** 追加消息(id 重复时告警并忽略) */
|
|
238
|
+
appendMessage(message: ChatMessage): void;
|
|
239
|
+
/** 更新消息级字段(status / role / parts 等,id 不可改) */
|
|
240
|
+
updateMessage(id: string, patch: MessagePatch): void;
|
|
241
|
+
/** 追加 part 到目标消息 */
|
|
242
|
+
appendPart(messageId: string, part: ChatPart): void;
|
|
243
|
+
/**
|
|
244
|
+
* 更新目标 part:partRef 为数组下标或 part id。
|
|
245
|
+
* 未命中时告警并忽略(宽容约定同 updateMessage)。
|
|
246
|
+
*/
|
|
247
|
+
updatePart(messageId: string, partRef: PartRef, patch: PartPatch): void;
|
|
248
|
+
/** 设置消息状态 */
|
|
249
|
+
setStatus(id: string, status: MessageStatus): void;
|
|
250
|
+
/**
|
|
251
|
+
* 不可变地移除目标消息及其后全部消息(编辑重发 / 重新生成的截断基础)。
|
|
252
|
+
* 未知 id 时告警并忽略。
|
|
253
|
+
*/
|
|
254
|
+
removeMessagesFrom(messageId: string): void;
|
|
255
|
+
/** 清空会话 */
|
|
256
|
+
clear(): void;
|
|
257
|
+
/** 订阅变更;返回退订函数 */
|
|
258
|
+
subscribe(listener: () => void): () => void;
|
|
259
|
+
/** 以 mutator 更新单条消息(找不到时告警并忽略) */
|
|
260
|
+
private mutateMessage;
|
|
261
|
+
private commit;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Streaming 事件模型与 reducer(设计决策 D2,设计文档第 69 节)。
|
|
266
|
+
*
|
|
267
|
+
* 事件对齐 SSE 协议:`message.start` / `text.delta` / `thinking.delta`
|
|
268
|
+
* / `tool.start` / `tool.result` / `dsl.start` / `dsl.complete`
|
|
269
|
+
* / `artifact`(产出物,spec: chat-artifact-panel)/ `message.end`
|
|
270
|
+
* / `message.error`(`dsl.patch` V1 不实现)。
|
|
271
|
+
*/
|
|
272
|
+
type ChatEvent = {
|
|
273
|
+
type: 'message.start';
|
|
274
|
+
messageId: string;
|
|
275
|
+
role?: ChatMessage['role'];
|
|
276
|
+
} | {
|
|
277
|
+
type: 'text.delta';
|
|
278
|
+
messageId: string;
|
|
279
|
+
delta: string;
|
|
280
|
+
partId?: string;
|
|
281
|
+
/** 目标 part 类型(缺省 text;新建 part 时生效) */
|
|
282
|
+
format?: 'text' | 'markdown';
|
|
283
|
+
} | {
|
|
284
|
+
type: 'thinking.delta';
|
|
285
|
+
messageId: string;
|
|
286
|
+
delta: string;
|
|
287
|
+
partId?: string;
|
|
288
|
+
} | {
|
|
289
|
+
type: 'tool.start';
|
|
290
|
+
messageId: string;
|
|
291
|
+
name: string;
|
|
292
|
+
title?: string;
|
|
293
|
+
/** 调用参数(可选;reducer 存入 tool-call part 的 args) */
|
|
294
|
+
args?: unknown;
|
|
295
|
+
partId?: string;
|
|
296
|
+
} | {
|
|
297
|
+
type: 'tool.result';
|
|
298
|
+
messageId: string;
|
|
299
|
+
name: string;
|
|
300
|
+
status: 'success' | 'failed';
|
|
301
|
+
result?: unknown;
|
|
302
|
+
error?: string;
|
|
303
|
+
partId?: string;
|
|
304
|
+
} | {
|
|
305
|
+
type: 'dsl.start';
|
|
306
|
+
messageId: string;
|
|
307
|
+
partId?: string;
|
|
308
|
+
} | {
|
|
309
|
+
type: 'dsl.complete';
|
|
310
|
+
messageId: string;
|
|
311
|
+
schema: DslNode;
|
|
312
|
+
partId?: string;
|
|
313
|
+
} | {
|
|
314
|
+
/** 产出物到达(spec: chat-artifact-panel):一次性写入 ready 的 artifact part */
|
|
315
|
+
type: 'artifact';
|
|
316
|
+
messageId: string;
|
|
317
|
+
artifact: ChatArtifact;
|
|
318
|
+
partId?: string;
|
|
319
|
+
} | {
|
|
320
|
+
type: 'message.end';
|
|
321
|
+
messageId: string;
|
|
322
|
+
} | {
|
|
323
|
+
type: 'message.error';
|
|
324
|
+
messageId: string;
|
|
325
|
+
error: string;
|
|
326
|
+
};
|
|
327
|
+
/**
|
|
328
|
+
* applyChatEvent(设计决策 D2):纯函数 reducer,把单个流式事件
|
|
329
|
+
* 落到 ConversationStore。不抛错:
|
|
330
|
+
*
|
|
331
|
+
* - 乱序 / 缺失宽容:delta 先于 message.start 时自动建立 assistant
|
|
332
|
+
* 占位消息;目标 part 不存在时自动创建。
|
|
333
|
+
* - 未知事件:忽略并 console.warn。
|
|
334
|
+
*/
|
|
335
|
+
declare function applyChatEvent(store: ConversationStore, event: ChatEvent): void;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* 活动轨迹纯函数(设计决策 D1,spec: chat-activity-trace)。
|
|
339
|
+
*
|
|
340
|
+
* 零 React、Node 可测:流式状态头的模式推导与 tool-call / tool-result
|
|
341
|
+
* 的配对轨迹。视图层(ActivityTrace)只负责渲染这些函数的输出。
|
|
342
|
+
*/
|
|
343
|
+
/** 流式状态头的模式 */
|
|
344
|
+
type StreamingMode = 'reasoning' | 'tool' | 'responding';
|
|
345
|
+
/**
|
|
346
|
+
* 由消息 parts 推导当前流式模式:
|
|
347
|
+
*
|
|
348
|
+
* - 存在 waiting / running 的 tool-call → `tool`(未完结的工具调用
|
|
349
|
+
* 总是优先,即使更晚有正文 streaming);
|
|
350
|
+
* - 否则取最靠后的活动(streaming)part:thinking → `reasoning`,
|
|
351
|
+
* text / markdown / dsl → `responding`(更晚的活动 part 优先);
|
|
352
|
+
* - 消息不在 streaming / pending,或无活动 part → `null`。
|
|
353
|
+
*/
|
|
354
|
+
declare function detectStreamingMode(message: ChatMessage): StreamingMode | null;
|
|
355
|
+
/**
|
|
356
|
+
* 配对后的工具轨迹条目:单行可展开渲染所需的数据。
|
|
357
|
+
*
|
|
358
|
+
* 事件模型无 callId(设计决策 D1 的取舍),保留原始 part 下标
|
|
359
|
+
* (`callIndex` / `resultIndex`)便于将来升级 callId 配对。
|
|
360
|
+
*/
|
|
361
|
+
interface ToolTraceEntry {
|
|
362
|
+
/** 工具名(tool-call / tool-result 的 name) */
|
|
363
|
+
name: string;
|
|
364
|
+
/** 人类可读标题(来自 tool-call part) */
|
|
365
|
+
title?: string;
|
|
366
|
+
/** 调用参数(来自配对 tool-call part 的 args;供参数摘要 / 详情渲染) */
|
|
367
|
+
args?: unknown;
|
|
368
|
+
/**
|
|
369
|
+
* 派生状态:已配对 result 时取 result 的 success / failed,
|
|
370
|
+
* 否则保留 call 自身的 waiting / running。
|
|
371
|
+
*/
|
|
372
|
+
status: ToolCallStatus;
|
|
373
|
+
/** result 载荷(success 时) */
|
|
374
|
+
result?: unknown;
|
|
375
|
+
/** 错误信息(failed 时) */
|
|
376
|
+
error?: string;
|
|
377
|
+
/** tool-call part 在消息 parts 中的下标 */
|
|
378
|
+
callIndex: number;
|
|
379
|
+
/** 配对的 tool-result part 下标;未配对时缺省 */
|
|
380
|
+
resultIndex?: number;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* 将 tool-call 与 tool-result 按 name + 出现顺序配对:
|
|
384
|
+
* 每个 result 落到同名最早未配对的 call(顺序事件流下等价于
|
|
385
|
+
* "最早未完结的同名 call")。孤儿 result(无同名 call)忽略。
|
|
386
|
+
* 返回条目按 call 出现顺序排列。
|
|
387
|
+
*/
|
|
388
|
+
declare function pairToolTraces(parts: ChatPart[]): ToolTraceEntry[];
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* ChatTransport 与 turn 驱动(设计决策 D2)。
|
|
392
|
+
*
|
|
393
|
+
* 真实 SSE / WebSocket 客户端不在 V1 范围:业务按服务端协议自行实现
|
|
394
|
+
* `ChatTransport`(或后续补 `createSseTransport`);测试与手动驱动
|
|
395
|
+
* 场景使用 `createManualDriver()`。
|
|
396
|
+
*/
|
|
397
|
+
/** 一轮对话的输入 */
|
|
398
|
+
interface ChatInput {
|
|
399
|
+
text: string;
|
|
400
|
+
conversationId?: string;
|
|
401
|
+
/**
|
|
402
|
+
* 当前选中模型 value(spec: chat-streaming,设计决策 D2):
|
|
403
|
+
* 由视图层在发送时注入;可选字段,既有 transport 实现无需修改
|
|
404
|
+
*/
|
|
405
|
+
model?: string;
|
|
406
|
+
/**
|
|
407
|
+
* 当前生效的上下文 chips(spec: chat-streaming,设计决策 D2/D6):
|
|
408
|
+
* 由视图层在发送时注入;MUST NOT 拼接进 `text` 字段(不污染用户
|
|
409
|
+
* 原文),transport 自行结构化消费;可选字段,既有实现无需修改
|
|
410
|
+
*/
|
|
411
|
+
contexts?: ChatContextItem[];
|
|
412
|
+
}
|
|
413
|
+
/** Chat 传输层:发送输入,返回流式事件 */
|
|
414
|
+
interface ChatTransport {
|
|
415
|
+
send(input: ChatInput): AsyncIterable<ChatEvent>;
|
|
416
|
+
}
|
|
417
|
+
/** runChatTurn 的可选定制(id 生成等,测试可注入确定性 id) */
|
|
418
|
+
interface RunChatTurnOptions {
|
|
419
|
+
userMessageId?: string;
|
|
420
|
+
assistantMessageId?: string;
|
|
421
|
+
/** 取消信号:abort 时停止消费事件流,assistant 消息以 cancelled 收尾 */
|
|
422
|
+
signal?: AbortSignal;
|
|
423
|
+
/**
|
|
424
|
+
* 跳过 user 消息追加(重新生成复用已有 user 消息时使用):
|
|
425
|
+
* 仍追加 assistant 占位并 reduce 事件流。
|
|
426
|
+
*/
|
|
427
|
+
skipUserMessage?: boolean;
|
|
428
|
+
}
|
|
429
|
+
/** runChatTurn 结果:本 turn 建立的两条消息 id */
|
|
430
|
+
interface ChatTurnResult {
|
|
431
|
+
userMessageId: string;
|
|
432
|
+
assistantMessageId: string;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* 执行一轮对话:先 append user 消息(completed)与 assistant 占位
|
|
436
|
+
* (pending),再 for-await transport 事件流逐事件 reduce。
|
|
437
|
+
*
|
|
438
|
+
* transport 流中的事件统一归一到 assistant 占位消息(一个 turn 的
|
|
439
|
+
* 事件流即该回复的事件流);transport 抛错时收敛为 message.error,
|
|
440
|
+
* 不向上抛出。
|
|
441
|
+
*/
|
|
442
|
+
declare function runChatTurn(store: ConversationStore, transport: ChatTransport, input: ChatInput, options?: RunChatTurnOptions): Promise<ChatTurnResult>;
|
|
443
|
+
/**
|
|
444
|
+
* 重新生成末轮(设计决策 D2,spec: chat-streaming / 重新生成轮次):
|
|
445
|
+
* 定位 store 中最后一条 user 消息,移除其后全部消息(保留该 user
|
|
446
|
+
* 消息本身),再以其文本驱动一轮新 turn(skipUserMessage,不产生
|
|
447
|
+
* 新的 user 消息)。
|
|
448
|
+
*
|
|
449
|
+
* store 中无 user 消息时告警并正常返回(不抛错、不改 store)。
|
|
450
|
+
* `options.signal` 语义同 runChatTurn:abort 时新 assistant 消息以
|
|
451
|
+
* cancelled 收尾并正常返回。
|
|
452
|
+
*/
|
|
453
|
+
declare function runRegenerateTurn(store: ConversationStore, transport: ChatTransport, options?: RunChatTurnOptions): Promise<ChatTurnResult | undefined>;
|
|
454
|
+
/** 手动 driver:代码控制推送事件的 ChatTransport 实现 */
|
|
455
|
+
interface ManualChatDriver {
|
|
456
|
+
transport: ChatTransport;
|
|
457
|
+
/** 推送一个事件(在 send 之前推送的事件会排队,send 后依次产出) */
|
|
458
|
+
push(event: ChatEvent): void;
|
|
459
|
+
/** 结束事件流(send 的 for-await 正常退出) */
|
|
460
|
+
complete(): void;
|
|
461
|
+
/** 以错误终止事件流(runChatTurn 收敛为 message.error) */
|
|
462
|
+
fail(cause: unknown): void;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* 创建手动 driver(测试与业务手动驱动共用):
|
|
466
|
+
* `push` / `complete` / `fail` 控制事件流,`transport.send` 产出。
|
|
467
|
+
* 一个 driver 对应一次 send;send 之后不可复用。
|
|
468
|
+
*/
|
|
469
|
+
declare function createManualDriver(): ManualChatDriver;
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* 创建 Safe Registry:`allowed` ∩ `source` 之外的类型对渲染层不可见
|
|
473
|
+
* (get 返回 undefined,Renderer 走受控占位)。
|
|
474
|
+
*/
|
|
475
|
+
declare function createSafeRegistry(source: Registry<unknown>, allowed: string[]): Registry<unknown>;
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* capability 动作(设计决策 D4,设计文档第 64、81.5 节):
|
|
479
|
+
* AI DSL 触发业务能力的唯一通道,执行链为
|
|
480
|
+
* CapabilityRegistry → Permission → Confirmation → Execute。
|
|
481
|
+
*/
|
|
482
|
+
/** 业务能力 handler */
|
|
483
|
+
interface CapabilityHandler {
|
|
484
|
+
/** 声明权限:执行前经 PermissionAdapter 检查 */
|
|
485
|
+
permission?: PermissionConfig;
|
|
486
|
+
/** 风险等级;'high' 需经 confirm 确认(注入时) */
|
|
487
|
+
risk?: 'low' | 'high';
|
|
488
|
+
/** 以求值后的 params 执行,返回值作为动作 data */
|
|
489
|
+
execute(params: Record<string, unknown>, ctx: ActionContext): unknown | Promise<unknown>;
|
|
490
|
+
}
|
|
491
|
+
/** Capability Registry:能力名 → handler */
|
|
492
|
+
type ChatCapabilityRegistry = Registry<CapabilityHandler>;
|
|
493
|
+
/** 结构化权限检查器(兼容 @pactor-app/runtime PermissionAdapter 与 @pactor-app/permission createPermissionAdapter 的返回) */
|
|
494
|
+
interface ChatPermissionChecker {
|
|
495
|
+
check(permission: PermissionConfig): boolean;
|
|
496
|
+
}
|
|
497
|
+
/** 高风险确认请求 */
|
|
498
|
+
interface ChatConfirmRequest {
|
|
499
|
+
name: string;
|
|
500
|
+
params: Record<string, unknown>;
|
|
501
|
+
}
|
|
502
|
+
/** 高风险确认回调:返回 true 继续执行,false 取消(skipped 语义) */
|
|
503
|
+
type ChatConfirm = (request: ChatConfirmRequest) => Promise<boolean>;
|
|
504
|
+
interface CapabilityActionDeps {
|
|
505
|
+
capabilities: ChatCapabilityRegistry;
|
|
506
|
+
/** 缺省时视为全部放行 */
|
|
507
|
+
permission?: ChatPermissionChecker;
|
|
508
|
+
/** 缺省时高风险 capability 受控拒绝(design Risks 约定) */
|
|
509
|
+
confirm?: ChatConfirm;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* 注册 `capability` 动作(已注册的同名动作不会被覆盖)。
|
|
513
|
+
*
|
|
514
|
+
* DSL 侧:`{ action: 'capability', params: { name: '<能力名>', params: {...} } }`。
|
|
515
|
+
*
|
|
516
|
+
* 执行链(每步失败均为受控返回,不抛出):
|
|
517
|
+
* 1. `params.name` 查 CapabilityRegistry,未注册 → `{ ok: false }`
|
|
518
|
+
* 2. capability 声明 `permission` 且检查拒绝 → `{ ok: false }`
|
|
519
|
+
* 3. capability 声明 `risk: 'high'`:注入 confirm 时先确认,
|
|
520
|
+
* 取消 → `{ ok: true, skipped: true }`;未注入 confirm → `{ ok: false }`
|
|
521
|
+
* 4. `capability.execute(params.params, ctx)`,返回值作为动作 data
|
|
522
|
+
*/
|
|
523
|
+
declare function registerCapabilityAction(actions: ActionRegistry, deps: CapabilityActionDeps): void;
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Chat 作用域与 RuntimeContext 组装(设计决策 D5,设计文档第 73 节)。
|
|
527
|
+
*
|
|
528
|
+
* DSL part 经 runtime Renderer 渲染:ComponentRegistry 用 Safe Registry,
|
|
529
|
+
* 作用域在 runtime 全局作用域之上注入 `conversation` / `message` /
|
|
530
|
+
* `params`(`user` 经 RuntimeContext 注入)——沿用表达式引擎约束,
|
|
531
|
+
* 不暴露浏览器全局对象。
|
|
532
|
+
*/
|
|
533
|
+
/** DSL part 渲染的 chat 局部作用域 */
|
|
534
|
+
interface ChatScope {
|
|
535
|
+
conversation: {
|
|
536
|
+
id?: string;
|
|
537
|
+
};
|
|
538
|
+
message: {
|
|
539
|
+
id: string;
|
|
540
|
+
};
|
|
541
|
+
params?: Record<string, unknown>;
|
|
542
|
+
}
|
|
543
|
+
/** 组装 chat 局部作用域(作为 renderChildren 的 extraScope 传入) */
|
|
544
|
+
declare function buildChatScope(scope: ChatScope): Record<string, unknown>;
|
|
545
|
+
interface CreateChatRuntimeOptions {
|
|
546
|
+
/** Safe Registry;缺省时使用空注册表(dsl part 全部渲染受控占位) */
|
|
547
|
+
safeRegistry?: Registry<unknown>;
|
|
548
|
+
/** capability 白名单;缺省时不注册 capability 动作 */
|
|
549
|
+
capabilities?: ChatCapabilityRegistry;
|
|
550
|
+
/** 权限检查器(与 permissionStore 二选一,permission 优先) */
|
|
551
|
+
permission?: ChatPermissionChecker;
|
|
552
|
+
/** @pactor-app/permission 的 PermissionStore,用于构造权限检查器 */
|
|
553
|
+
permissionStore?: PermissionStore;
|
|
554
|
+
/** 高风险 capability 确认回调 */
|
|
555
|
+
confirm?: ChatConfirm;
|
|
556
|
+
/** 注入作用域 `user` */
|
|
557
|
+
user?: Record<string, unknown>;
|
|
558
|
+
}
|
|
559
|
+
interface ChatRuntime {
|
|
560
|
+
context: RuntimeContext;
|
|
561
|
+
engine: ActionEngine;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* 创建 Chat DSL 渲染运行时:
|
|
565
|
+
*
|
|
566
|
+
* - ComponentRegistry 为 Safe Registry(白名单之外的组件不可见)
|
|
567
|
+
* - 注册 runtime 内置动作(setState 等);注入 capabilities 时注册
|
|
568
|
+
* `capability` 动作(Safe Registry 只挡组件,动作侧由 capability
|
|
569
|
+
* 白名单兜底——AI DSL 建议只配置 capability 动作)
|
|
570
|
+
* - permissionStore 经 @pactor-app/permission 构造 PermissionAdapter,
|
|
571
|
+
* 供 Renderer 的 `permission` 字段与 capability 链共用
|
|
572
|
+
*/
|
|
573
|
+
declare function createChatRuntime(options?: CreateChatRuntimeOptions): ChatRuntime;
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* DSL part 的白名单守卫(设计决策 D3/D5):渲染前把白名单之外的
|
|
577
|
+
* 节点替换为受控"不允许"占位节点(`ChatDenied`),占位组件由
|
|
578
|
+
* PartRenderer 注册进 Safe Registry。
|
|
579
|
+
*
|
|
580
|
+
* 纯函数、零 React,可纯 Node 测试。
|
|
581
|
+
*
|
|
582
|
+
* 注意:只处理 DSL 树的 type / children 主干;props 内嵌的 DSL 子树
|
|
583
|
+
* (Table columns[].cell 等)由 runtime Renderer 的 UnsupportedComponent
|
|
584
|
+
* 兜底(Safe Registry get 未命中即受控占位,不会渲染真实组件)。
|
|
585
|
+
*/
|
|
586
|
+
/** 受控占位节点的 DSL 类型名(占用不可能与业务组件冲突的名称) */
|
|
587
|
+
declare const CHAT_DENIED_TYPE = "ChatDenied";
|
|
588
|
+
/**
|
|
589
|
+
* 递归守卫 DSL 树:白名单内的节点原样保留(children 递归处理);
|
|
590
|
+
* 白名单外的节点替换为 `{ type: 'ChatDenied', props: { deniedType } }`,
|
|
591
|
+
* 其 children 一并丢弃(不渲染其中任何内容)。
|
|
592
|
+
*/
|
|
593
|
+
declare function guardChatDsl(node: DslNode, registry: Registry<unknown>): DslNode;
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* useSmoothStreamText(技术选型参考 DeepTutor web 同名 hook,独立实现):
|
|
597
|
+
* 把"可见文本"的增长速率与流式 delta 的到达节奏解耦——上游 chunk 再
|
|
598
|
+
* 突发,用户看到的都是平滑的打字机揭示。
|
|
599
|
+
*
|
|
600
|
+
* 机制:
|
|
601
|
+
* - isStreaming 且 content 长于已揭示部分时,以 requestAnimationFrame
|
|
602
|
+
* 循环推进游标;每帧揭示 max(minCharsPerFrame, backlog / catchUpDivisor),
|
|
603
|
+
* 封顶 maxCharsPerFrame(长时间积压的大 chunk 不会龟速打字半分钟);
|
|
604
|
+
* - isStreaming 翻 false 时立即对齐全文(短消息不留残尾);
|
|
605
|
+
* - content 回缩(重新生成 / 分支切换)时立即回退游标,不显示幽灵尾巴;
|
|
606
|
+
* - enabled: false 时直通原文(调用方可对 streaming / 非 streaming 走同一
|
|
607
|
+
* 渲染路径)。
|
|
608
|
+
*/
|
|
609
|
+
interface UseSmoothStreamTextOptions {
|
|
610
|
+
/** 每帧揭示上限(字符),默认 120 */
|
|
611
|
+
maxCharsPerFrame?: number;
|
|
612
|
+
/** 每帧揭示下限(字符),默认 2 */
|
|
613
|
+
minCharsPerFrame?: number;
|
|
614
|
+
/** 积压除数:越大揭示越慢,约 5 比较自然,默认 5 */
|
|
615
|
+
catchUpDivisor?: number;
|
|
616
|
+
/** false 时直通原文,默认 true */
|
|
617
|
+
enabled?: boolean;
|
|
618
|
+
}
|
|
619
|
+
declare function useSmoothStreamText(content: string, isStreaming: boolean, options?: UseSmoothStreamTextOptions): string;
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* useChatAutoScroll(技术选型参考 DeepTutor web 同名 hook,独立实现):
|
|
623
|
+
* "钉在底部"的流式自动滚动。
|
|
624
|
+
*
|
|
625
|
+
* 机制:
|
|
626
|
+
* - 跟随时,唯一写者在 useLayoutEffect 里执行
|
|
627
|
+
* `scrollTop = scrollHeight`(避免多路写 scrollTop 造成的抖动);
|
|
628
|
+
* - 用户上翻超过 RELEASE_THRESHOLD(80px)释放跟随,可安静翻历史;
|
|
629
|
+
* 回到距底 REENGAGE_THRESHOLD(40px)内自动恢复跟随;
|
|
630
|
+
* - 释放跟随期间由调用方展示"回到底部"入口(isFollowing=false),
|
|
631
|
+
* 点击 scrollToBottom 恢复;
|
|
632
|
+
* - 滚动容器需配合 `overflow-anchor: none`(styles.css 已内置),
|
|
633
|
+
* 防止浏览器滚动锚定与跟随互相拉扯。
|
|
634
|
+
*/
|
|
635
|
+
interface UseChatAutoScrollOptions {
|
|
636
|
+
/** 消息总数(变化触发一次跟随判定) */
|
|
637
|
+
messageCount: number;
|
|
638
|
+
/** 最后一条消息的文本总长度(流式增长触发跟随) */
|
|
639
|
+
lastContentLength: number;
|
|
640
|
+
/** 是否处于流式中(仅流式中才需要高频跟随) */
|
|
641
|
+
isStreaming: boolean;
|
|
642
|
+
}
|
|
643
|
+
interface UseChatAutoScrollResult {
|
|
644
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
645
|
+
/** 是否处于跟随状态(false 时调用方应显示"回到底部"入口) */
|
|
646
|
+
isFollowing: boolean;
|
|
647
|
+
/** 恢复跟随并立即滚到底部 */
|
|
648
|
+
scrollToBottom: () => void;
|
|
649
|
+
}
|
|
650
|
+
declare function useChatAutoScroll({ messageCount, lastContentLength, isStreaming, }: UseChatAutoScrollOptions): UseChatAutoScrollResult;
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* EmptyState(spec: chat-empty-state,设计决策 D0/D1):空会话欢迎页。
|
|
654
|
+
*
|
|
655
|
+
* 数据以接口注入:greeting / subtitle / suggestions 均为受控 props;
|
|
656
|
+
* 点击建议经 `onSuggestionClick` 回调交还调用方(ChatView 接入时
|
|
657
|
+
* 复用 Composer 的同一条发送路径)。
|
|
658
|
+
*/
|
|
659
|
+
type ChatSuggestion = string | {
|
|
660
|
+
label: string;
|
|
661
|
+
prompt?: string;
|
|
662
|
+
};
|
|
663
|
+
interface EmptyStateProps {
|
|
664
|
+
/** 问候语(display 衬线字体栈渲染);缺省用默认文案 */
|
|
665
|
+
greeting?: string;
|
|
666
|
+
/** 可选副标题 */
|
|
667
|
+
subtitle?: string;
|
|
668
|
+
/** 起始建议;空数组 / 未传时不渲染建议区 */
|
|
669
|
+
suggestions?: ChatSuggestion[];
|
|
670
|
+
/** 点击建议回调,入参为该建议的 `prompt ?? label` */
|
|
671
|
+
onSuggestionClick?: (text: string) => void;
|
|
672
|
+
}
|
|
673
|
+
/** 默认问候语(可被 greeting prop 覆盖) */
|
|
674
|
+
declare const DEFAULT_CHAT_GREETING = "\u4F60\u597D\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u4F60\uFF1F";
|
|
675
|
+
declare function EmptyState({ greeting, subtitle, suggestions, onSuggestionClick, }: EmptyStateProps): react.JSX.Element;
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* 内建工作区 header(spec: chat-dsl-component / Header 配置,设计决策 D4):
|
|
679
|
+
* 标题(editableTitle 时点击进入编辑,Enter / blur 提交)+ 右侧操作组
|
|
680
|
+
* (按 headerActions 数组顺序渲染,位于 headerExtra 槽之前)。
|
|
681
|
+
*
|
|
682
|
+
* 默认行为总在包内执行,事件为并行通知(与 onSend 同款语义):
|
|
683
|
+
* - export:store.getMessages() 序列化 Markdown 并触发下载
|
|
684
|
+
* - theme:读 document.documentElement 当前 data-pactor-theme 并切换
|
|
685
|
+
* ('dark' ↔ 移除),事件带新 theme
|
|
686
|
+
* - clear:store.clear()
|
|
687
|
+
*
|
|
688
|
+
* 零渲染承诺:headerActions 缺省 / 空数组且未开 editableTitle 时,
|
|
689
|
+
* 渲染 DOM 与既有内建 header 逐字节一致。
|
|
690
|
+
*/
|
|
691
|
+
/** 内建 header 操作项(按数组顺序渲染) */
|
|
692
|
+
type ChatHeaderAction = 'export' | 'theme' | 'clear';
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* ChatWorkspace 宿主服务(spec: chat-dsl-page,设计决策 D1):
|
|
696
|
+
* 全部运行时依赖与交互回调由宿主注入——表达式作用域只承载
|
|
697
|
+
* 可序列化数据,函数 / 实例不进 DSL props。
|
|
698
|
+
* (chat-dsl-component 起同型复用为 ChatServices,经 ChatServicesProvider
|
|
699
|
+
* 注入;本工厂保留为 React 直连路径。)
|
|
700
|
+
*/
|
|
701
|
+
interface ChatWorkspaceServices {
|
|
702
|
+
/** 传输层(必填):发送即经 runChatTurn 驱动一轮对话 */
|
|
703
|
+
transport: ChatTransport;
|
|
704
|
+
/** 外部自持 store;与 storeFactory 二选一,缺省包内默认构造 */
|
|
705
|
+
store?: ConversationStore;
|
|
706
|
+
/** 缺省 store 的创建工厂(仅首渲染调用一次) */
|
|
707
|
+
storeFactory?: () => ConversationStore;
|
|
708
|
+
/** 产出物面板 store(spec: chat-artifact-panel);缺省包内默认构造 */
|
|
709
|
+
artifactStore?: ArtifactStore;
|
|
710
|
+
/** Safe Registry(createSafeRegistry 包装后的白名单注册表) */
|
|
711
|
+
safeRegistry?: Registry<unknown>;
|
|
712
|
+
/** capability 白名单与确认链 */
|
|
713
|
+
capabilities?: ChatCapabilityRegistry;
|
|
714
|
+
permission?: ChatPermissionChecker;
|
|
715
|
+
confirm?: ChatConfirm;
|
|
716
|
+
/** 注入 dsl part 作用域 user */
|
|
717
|
+
user?: Record<string, unknown>;
|
|
718
|
+
/**
|
|
719
|
+
* 附件伪上传 / 上传:粘贴、拖拽、文件选择产出的 File[] 交给宿主处理,
|
|
720
|
+
* 回传的 ChatAttachment[] 追加进受控附件区(支持异步);发送后清空
|
|
721
|
+
*/
|
|
722
|
+
onAttachFiles?: (files: File[]) => ChatAttachment[] | Promise<ChatAttachment[]>;
|
|
723
|
+
/** 附件卡片点击通知(预览等由宿主实现) */
|
|
724
|
+
onAttachmentClick?: (attachment: ChatAttachment) => void;
|
|
725
|
+
/** 发送回调(在 transport 驱动 turn 之前触发) */
|
|
726
|
+
onSend?: (text: string) => void;
|
|
727
|
+
/**
|
|
728
|
+
* 声明式数据源解析出口(spec: chat-context-sources,设计决策 D1):
|
|
729
|
+
* contexts 的 service 引用(`{ service, params? }`)经此调用解析为
|
|
730
|
+
* 候选数据;宿主桥到 ServiceRegistry 或自有实现。函数不进 DSL
|
|
731
|
+
* props,统一经 ChatServices 注入。
|
|
732
|
+
*/
|
|
733
|
+
callService?: (name: string, params?: Record<string, unknown>) => Promise<unknown>;
|
|
734
|
+
/** 词边界 `@` 输入触发:query 为 `@` 后文本,anchorRect 为弹层锚点 */
|
|
735
|
+
onMentionTrigger?: (query: string, anchorRect: DOMRect) => void;
|
|
736
|
+
/** "+" 按钮触发弹层入口 */
|
|
737
|
+
onPlusMenu?: (anchorRect: DOMRect) => void;
|
|
738
|
+
/** Composer 工具栏左 / 右槽(ReactNode 闭包槽,纯 React 与 DSL 场景均可用) */
|
|
739
|
+
toolbarStart?: ReactNode;
|
|
740
|
+
toolbarEnd?: ReactNode;
|
|
741
|
+
/** 工作区头部右侧扩展区(提供 title 或 headerExtra 时渲染头部) */
|
|
742
|
+
headerExtra?: ReactNode;
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* ChatWorkspace 的 DSL 安全 props(spec: chat-dsl-page / DSL 安全 props):
|
|
746
|
+
* 全部为 DSL 可表达的标量 / 数组 / 普通对象;函数与类实例一律不出现。
|
|
747
|
+
*/
|
|
748
|
+
interface ChatWorkspaceProps {
|
|
749
|
+
/** 工作区头部标题(提供 title 或服务注入 headerExtra 时渲染头部) */
|
|
750
|
+
title?: string;
|
|
751
|
+
/** 空会话问候语 */
|
|
752
|
+
greeting?: string;
|
|
753
|
+
/** 空会话副标题 */
|
|
754
|
+
subtitle?: string;
|
|
755
|
+
/** 空会话起始建议;空数组 / 未传时不渲染建议区 */
|
|
756
|
+
suggestions?: ChatSuggestion[];
|
|
757
|
+
/** 会话 id(注入 dsl part 作用域 conversation.id) */
|
|
758
|
+
conversationId?: string;
|
|
759
|
+
/** 注入 dsl part 作用域 params */
|
|
760
|
+
params?: Record<string, unknown>;
|
|
761
|
+
/**
|
|
762
|
+
* 侧栏 DslNode 槽(任务 1.1 结论:renderer 对内嵌 DslNode prop 跳过提前
|
|
763
|
+
* 求值,组件经 useRenderer().renderChildren 渲染)。提供时以 AppShell
|
|
764
|
+
* 包裹工作区(侧栏 + 移动端抽屉)。仅页面运行时上下文内有效。
|
|
765
|
+
*/
|
|
766
|
+
sidebar?: DslNode;
|
|
767
|
+
/** Composer 工具栏右端 DslNode 槽(与服务注入的 toolbarEnd 先后渲染) */
|
|
768
|
+
toolbarEnd?: DslNode;
|
|
769
|
+
/**
|
|
770
|
+
* 产出物面板受控 props(spec: chat-artifact-panel,决策 D2):
|
|
771
|
+
* 任一提供即全受控;都未提供时由内部 / 注入的 ArtifactStore 驱动
|
|
772
|
+
*/
|
|
773
|
+
artifact?: ChatArtifact | null;
|
|
774
|
+
panelOpen?: boolean;
|
|
775
|
+
/** 面板关闭回调(runtime 绑定 events.onPanelClose 时以函数形态传入) */
|
|
776
|
+
onPanelClose?: () => void;
|
|
777
|
+
/** 面板内容 DslNode 槽:提供时整体替代内建渲染器 */
|
|
778
|
+
inspector?: DslNode;
|
|
779
|
+
/** artifact part 就绪回调(runtime 绑定 events.onArtifact 时传入) */
|
|
780
|
+
onArtifact?: (artifact: ChatArtifact) => void;
|
|
781
|
+
/** 产出物卡片"在面板中打开"回调(runtime 绑定 events.onOpenArtifact 时传入) */
|
|
782
|
+
onOpenArtifact?: (artifact: ChatArtifact) => void;
|
|
783
|
+
/**
|
|
784
|
+
* 内建 header 操作组(spec: chat-dsl-component / Header 配置,决策 D4):
|
|
785
|
+
* 按数组顺序渲染(headerExtra 槽之前);缺省不渲染
|
|
786
|
+
*/
|
|
787
|
+
headerActions?: ChatHeaderAction[];
|
|
788
|
+
/** 标题可编辑(点击进入编辑,Enter / blur 提交);缺省 false */
|
|
789
|
+
editableTitle?: boolean;
|
|
790
|
+
onExport?: () => void;
|
|
791
|
+
onThemeChange?: (theme: 'light' | 'dark') => void;
|
|
792
|
+
onClear?: () => void;
|
|
793
|
+
onTitleChange?: (title: string) => void;
|
|
794
|
+
/** 内建模型选择(spec: chat-model-selector,决策 D5 受控规则) */
|
|
795
|
+
models?: ChatModelOption[];
|
|
796
|
+
model?: string;
|
|
797
|
+
onModelChange?: (value: string) => void;
|
|
798
|
+
/**
|
|
799
|
+
* 模型 chip 渲染位置(spec: chat-model-selector / 模型选择位置配置,
|
|
800
|
+
* 决策 D2;DSL 可序列化标量,缺省 'composer')。'header' 时头部渲染
|
|
801
|
+
* 条件扩展:仅配置 models(无 title / headerExtra)也渲染极简头部
|
|
802
|
+
*/
|
|
803
|
+
modelPlacement?: 'composer' | 'header';
|
|
804
|
+
/** 内建上下文数据源(spec: chat-context-sources) */
|
|
805
|
+
contexts?: ChatContextSource[];
|
|
806
|
+
onContextsChange?: (chips: ChatContextItem[]) => void;
|
|
807
|
+
/** 消息操作条声明式配置(spec: chat-message-actions;DSL 可序列化数据) */
|
|
808
|
+
messageActions?: Array<BuiltinMessageAction | ChatMessageAction>;
|
|
809
|
+
/** 消息动作点击通知(runtime 绑定 events.onMessageAction 时以函数形态传入) */
|
|
810
|
+
onMessageAction?: (actionId: string, message: ChatMessage) => void;
|
|
811
|
+
className?: string;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* createChatWorkspace(spec: chat-dsl-page / chat-dsl-component,决策 D5):
|
|
815
|
+
* 宿主闭包注入全部运行时服务,返回可注册进 DSL 组件注册表
|
|
816
|
+
* (options.components)的 ChatWorkspace 组件。
|
|
817
|
+
*
|
|
818
|
+
* 实现为 ChatServicesProvider + ChatComposition 的薄封装(与 Chat 组件
|
|
819
|
+
* 共用同一组合,逻辑单一来源);行为与 DSL props 契约保持不变。
|
|
820
|
+
*/
|
|
821
|
+
declare function createChatWorkspace(services: ChatWorkspaceServices): (props: ChatWorkspaceProps) => ReactNode;
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Chat 的运行时服务(spec: chat-dsl-component,设计决策 D1):
|
|
825
|
+
* 与 ChatWorkspaceServices 同型——transport 必填,其余可选。
|
|
826
|
+
* 表达式作用域只承载可序列化数据,函数 / 实例不进 DSL props,
|
|
827
|
+
* 故服务经 React Context 注入一次,`Chat` 组件就近读取。
|
|
828
|
+
*/
|
|
829
|
+
type ChatServices = ChatWorkspaceServices;
|
|
830
|
+
/**
|
|
831
|
+
* 宿主在应用根部注入一次聊天服务;其下所有 `Chat` 组件(含 DSL 页面
|
|
832
|
+
* 渲染的实例)经 context 消费。多层嵌套时就近原则生效。
|
|
833
|
+
*/
|
|
834
|
+
declare function ChatServicesProvider({ value, children, }: {
|
|
835
|
+
value: ChatServices;
|
|
836
|
+
children?: ReactNode;
|
|
837
|
+
}): ReactNode;
|
|
838
|
+
/** 读取最近的 ChatServicesProvider;无 provider 返回 null(不抛错) */
|
|
839
|
+
declare function useChatServices(): ChatServices | null;
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* 菜单项(spec: chat-dsl-component,设计决策 D2):纯数据驱动——
|
|
843
|
+
* DSL 可表达的标量字段,图标为字符串名(白名单映射内置 lucide 子集,
|
|
844
|
+
* 避免 DSL 携带组件)。`group` 为分组标题:与上一项 group 不同时
|
|
845
|
+
* 在该项之前渲染分组行。
|
|
846
|
+
*/
|
|
847
|
+
interface ChatMenuItem {
|
|
848
|
+
key: string;
|
|
849
|
+
label: string;
|
|
850
|
+
/** 字符串图标名(plus / chat / history / settings / star / search / user / folder);未知名渲染占位圆点 */
|
|
851
|
+
icon?: string;
|
|
852
|
+
badge?: string | number;
|
|
853
|
+
/** 状态圆点(spec: chat-dsl-component / 菜单项状态点,决策 D4):label 右侧渲染 danger 系小圆点;与 badge 可共存 */
|
|
854
|
+
dot?: boolean;
|
|
855
|
+
disabled?: boolean;
|
|
856
|
+
/** 分组标题(相邻同组只渲染一次) */
|
|
857
|
+
group?: string;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Chat 组件 props(spec: chat-dsl-component):标量 / 数组 / 普通对象为
|
|
861
|
+
* DSL 可表达配置;sidebar / headerExtra / header 槽同时接受 DslNode
|
|
862
|
+
* (页面运行时内经 renderChildren 渲染)与 ReactNode(纯 React 直连)。
|
|
863
|
+
*/
|
|
864
|
+
interface ChatProps {
|
|
865
|
+
/** 内建 header 标题 */
|
|
866
|
+
title?: string;
|
|
867
|
+
/** 空会话问候语 */
|
|
868
|
+
greeting?: string;
|
|
869
|
+
/** 空会话副标题 */
|
|
870
|
+
subtitle?: string;
|
|
871
|
+
/** 空会话起始建议;空数组 / 未传时不渲染建议区 */
|
|
872
|
+
suggestions?: ChatSuggestion[];
|
|
873
|
+
/** 会话 id(注入 dsl part 作用域 conversation.id) */
|
|
874
|
+
conversationId?: string;
|
|
875
|
+
/** 注入 dsl part 作用域 params */
|
|
876
|
+
params?: Record<string, unknown>;
|
|
877
|
+
/** 传 false 关闭 header;缺省渲染(header 槽整体替换 > title + headerExtra 内建 header) */
|
|
878
|
+
showHeader?: boolean;
|
|
879
|
+
/** 左侧菜单数据;提供时以 AppShell 承载内建侧栏 */
|
|
880
|
+
menu?: ChatMenuItem[];
|
|
881
|
+
/** 受控高亮项 key(DSL 侧可绑 ${state.x},经 onMenuSelect + setState 闭环) */
|
|
882
|
+
activeMenuKey?: string;
|
|
883
|
+
/** 侧栏槽:提供时替代内建菜单侧栏 */
|
|
884
|
+
sidebar?: DslNode | ReactNode;
|
|
885
|
+
/** 内建 header 标题右侧槽 */
|
|
886
|
+
headerExtra?: DslNode | ReactNode;
|
|
887
|
+
/** header 槽:整体替换内建 header */
|
|
888
|
+
header?: DslNode | ReactNode;
|
|
889
|
+
/**
|
|
890
|
+
* 内建 header 操作组(spec: chat-dsl-component / Header 配置,决策 D4):
|
|
891
|
+
* 按数组顺序渲染 export / theme / clear 图标按钮(headerExtra 槽之前);
|
|
892
|
+
* 缺省不渲染。默认行为总在包内执行,事件为并行通知
|
|
893
|
+
*/
|
|
894
|
+
headerActions?: ChatHeaderAction[];
|
|
895
|
+
/** 标题可编辑(点击进入编辑,Enter / blur 提交);缺省 false */
|
|
896
|
+
editableTitle?: boolean;
|
|
897
|
+
onExport?: () => void;
|
|
898
|
+
onThemeChange?: (theme: 'light' | 'dark') => void;
|
|
899
|
+
onClear?: () => void;
|
|
900
|
+
onTitleChange?: (title: string) => void;
|
|
901
|
+
/**
|
|
902
|
+
* 内建模型选择(spec: chat-model-selector):DSL 可表达数据;
|
|
903
|
+
* model + onModelChange 构成受控闭环(典型接法:
|
|
904
|
+
* model: ${state.model} + events.onModelChange → setState)
|
|
905
|
+
*/
|
|
906
|
+
models?: ChatModelOption[];
|
|
907
|
+
model?: string;
|
|
908
|
+
onModelChange?: (value: string) => void;
|
|
909
|
+
/** 模型 chip 渲染位置(spec: chat-model-selector / 模型选择位置配置,决策 D2;DSL 可序列化标量,缺省 'composer') */
|
|
910
|
+
modelPlacement?: 'composer' | 'header';
|
|
911
|
+
/** 内建上下文数据源(spec: chat-context-sources);service 引用经 ChatServices.callService 解析 */
|
|
912
|
+
contexts?: ChatContextSource[];
|
|
913
|
+
onContextsChange?: (chips: ChatContextItem[]) => void;
|
|
914
|
+
/**
|
|
915
|
+
* 消息操作条声明式配置(spec: chat-message-actions,决策 D1):
|
|
916
|
+
* DSL 可序列化数据;缺省渲染内建 copy / regenerate / retry / edit;
|
|
917
|
+
* 传入数组时严格按数组渲染(数组即真相),自定义动作 service 引用经
|
|
918
|
+
* ChatServices.callService 派发
|
|
919
|
+
*/
|
|
920
|
+
messageActions?: Array<BuiltinMessageAction | ChatMessageAction>;
|
|
921
|
+
/** 消息动作点击通知(event 作用域含 action 与 message;内建动作亦通知) */
|
|
922
|
+
onMessageAction?: (actionId: string, message: ChatMessage) => void;
|
|
923
|
+
/**
|
|
924
|
+
* 产出物面板(spec: chat-artifact-panel / chat-dsl-component,决策 D2):
|
|
925
|
+
* `artifact` / `panelOpen` 可绑 DSL state;任一提供即全受控,
|
|
926
|
+
* 都未提供时由内部 / 注入的 ArtifactStore 驱动
|
|
927
|
+
*/
|
|
928
|
+
artifact?: ChatArtifact | null;
|
|
929
|
+
panelOpen?: boolean;
|
|
930
|
+
/** 面板关闭按钮 / 窄屏遮罩点击回调(典型接法:setState panelOpen=false) */
|
|
931
|
+
onPanelClose?: () => void;
|
|
932
|
+
/** 面板内容槽:提供时整体替代面板内建渲染器 */
|
|
933
|
+
inspector?: DslNode | ReactNode;
|
|
934
|
+
/** artifact part 就绪时触发(event 作用域含 artifact;框架不擅自开面板) */
|
|
935
|
+
onArtifact?: (artifact: ChatArtifact) => void;
|
|
936
|
+
/** 产出物卡片"在面板中打开"按钮点击回调(event 作用域含 artifact;受控场景的开面板入口) */
|
|
937
|
+
onOpenArtifact?: (artifact: ChatArtifact) => void;
|
|
938
|
+
className?: string;
|
|
939
|
+
/** 发送回调:与 transport 驱动 turn 并行(同 ChatView onSend 语义) */
|
|
940
|
+
onSend?: (text: string) => void;
|
|
941
|
+
/** 菜单项点击回调(disabled 项不触发) */
|
|
942
|
+
onMenuSelect?: (key: string, item: ChatMenuItem) => void;
|
|
943
|
+
}
|
|
944
|
+
/** 菜单图标名 → lucide 子集(白名单式,未知名渲染占位圆点,不抛错) */
|
|
945
|
+
declare const MENU_ICONS: Record<string, ComponentType<{
|
|
946
|
+
size?: number;
|
|
947
|
+
strokeWidth?: number;
|
|
948
|
+
}>>;
|
|
949
|
+
/** 内建侧栏:menu 数据驱动的菜单(分组标题 + 图标 + badge + disabled);ChatShell 同款复用 */
|
|
950
|
+
declare function ChatSidebarMenu({ menu, activeMenuKey, onMenuSelect, }: {
|
|
951
|
+
menu: ChatMenuItem[];
|
|
952
|
+
activeMenuKey?: string;
|
|
953
|
+
onMenuSelect?: (key: string, item: ChatMenuItem) => void;
|
|
954
|
+
}): ReactNode;
|
|
955
|
+
/**
|
|
956
|
+
* Chat(spec: chat-dsl-component):一等 DSL 聊天工作区组件——
|
|
957
|
+
* 与 Button / Input 同级,注册后 `{ type: 'Chat', props, events }` 即可声明。
|
|
958
|
+
*
|
|
959
|
+
* 服务经最近的 ChatServicesProvider 读取(决策 D1);缺失时渲染受控
|
|
960
|
+
* 「未配置聊天服务」提示并 console.warn,不抛错。组合逻辑与
|
|
961
|
+
* createChatWorkspace 共用内部 ChatComposition(决策 D5)。
|
|
962
|
+
*/
|
|
963
|
+
declare function Chat({ title, greeting, subtitle, suggestions, conversationId, params, showHeader, menu, activeMenuKey, sidebar, headerExtra, header, headerActions, editableTitle, onExport, onThemeChange, onClear, onTitleChange, models, model, onModelChange, modelPlacement, contexts, onContextsChange, messageActions, onMessageAction, artifact, panelOpen, onPanelClose, inspector, onArtifact, onOpenArtifact, className, onSend, onMenuSelect, }: ChatProps): ReactNode;
|
|
964
|
+
/** Chat 的 DSL 组件类型名 */
|
|
965
|
+
declare const CHAT_COMPONENT_TYPE = "Chat";
|
|
966
|
+
/**
|
|
967
|
+
* 注册 Chat DSL 组件(spec: chat-dsl-component / Chat 组件注册):
|
|
968
|
+
* 已存在同名类型时不覆盖(沿用 registerChatLayout 的语义)。
|
|
969
|
+
* ChatShell(spec: chat-dsl-component / ChatShell 外壳组件,决策 D6)
|
|
970
|
+
* 一并注册,同样不覆盖已有同名类型。
|
|
971
|
+
*/
|
|
972
|
+
declare function registerChatComponent(registry: Registry<unknown>): void;
|
|
973
|
+
|
|
974
|
+
/**
|
|
975
|
+
* ChatShell(spec: chat-dsl-component / ChatShell 外壳组件,设计决策 D6):
|
|
976
|
+
* 菜单外壳 = AppShell + 内建菜单侧栏(复用 Chat 的 ChatMenuItem 数据 /
|
|
977
|
+
* 图标白名单 / activeMenuKey 高亮 / onMenuSelect 事件)+ 主区内容槽。
|
|
978
|
+
*
|
|
979
|
+
* 纯展示外壳:MUST NOT 含聊天逻辑与路由逻辑——菜单点击只发事件,
|
|
980
|
+
* 导航还是状态切换由宿主 / DSL 决定。典型用法:DSL 场景 content 槽内
|
|
981
|
+
* 放若干带 when 条件的子树(onMenuSelect → setState 闭环);应用场景
|
|
982
|
+
* content 传路由出口(onMenuSelect → bridge.push,刷新由路由还原)。
|
|
983
|
+
*/
|
|
984
|
+
interface ChatShellProps {
|
|
985
|
+
/** 左侧菜单数据;提供时以 AppShell 承载内建菜单侧栏 */
|
|
986
|
+
menu?: ChatMenuItem[];
|
|
987
|
+
/** 受控高亮项 key(DSL 侧可绑 ${state.x},经 onMenuSelect + setState 闭环) */
|
|
988
|
+
activeMenuKey?: string;
|
|
989
|
+
/** 品牌区(透传 AppShell):移动端顶栏 + 桌面侧栏顶部品牌行(决策 D3) */
|
|
990
|
+
brand?: ReactNode;
|
|
991
|
+
/** 桌面端可折叠为 icon rail(透传 AppShell;DSL 可序列化布尔,缺省 false) */
|
|
992
|
+
collapsible?: boolean;
|
|
993
|
+
/** 侧栏槽:提供时替代内建菜单侧栏 */
|
|
994
|
+
sidebar?: DslNode | ReactNode;
|
|
995
|
+
/** 侧栏底部固定槽(spec: chat-app-shell / 侧栏底部槽):DslNode 经 renderChildren 渲染,ReactNode 原样渲染 */
|
|
996
|
+
sidebarFooter?: DslNode | ReactNode;
|
|
997
|
+
/** 主区内容槽:DslNode 经 renderChildren 渲染;ReactNode 原样渲染(路由出口等) */
|
|
998
|
+
content?: DslNode | ReactNode;
|
|
999
|
+
className?: string;
|
|
1000
|
+
/** 菜单项点击回调(disabled 项不触发;DSL 侧 event 含 key 与 item) */
|
|
1001
|
+
onMenuSelect?: (key: string, item: ChatMenuItem) => void;
|
|
1002
|
+
}
|
|
1003
|
+
declare function ChatShell({ menu, activeMenuKey, brand, collapsible, sidebar, sidebarFooter, content, className, onMenuSelect, }: ChatShellProps): ReactNode;
|
|
1004
|
+
/** ChatShell 的 DSL 组件类型名 */
|
|
1005
|
+
declare const CHAT_SHELL_COMPONENT_TYPE = "ChatShell";
|
|
1006
|
+
/**
|
|
1007
|
+
* 注册 ChatShell DSL 组件:已存在同名类型时 MUST NOT 覆盖。
|
|
1008
|
+
* 一般由 registerChatComponent 一并调用(Chat 与 ChatShell 同源注册)。
|
|
1009
|
+
*/
|
|
1010
|
+
declare function registerChatShellComponent(registry: Registry<unknown>): void;
|
|
1011
|
+
|
|
1012
|
+
/**
|
|
1013
|
+
* ArtifactPanel(spec: chat-artifact-panel,设计决策 D2/D3):
|
|
1014
|
+
* 产出物预览面板 = 标题栏(标题 + kind 角标 + 关闭按钮)+ 内容区。
|
|
1015
|
+
*
|
|
1016
|
+
* 内容按 artifact.kind 分发内建渲染器:markdown 经 @pactor-app/markdown
|
|
1017
|
+
* 安全渲染;code 只读代码块(language 仅作角标,不引高亮依赖);
|
|
1018
|
+
* text 预格式文本;dsl 经 guardChatDsl 白名单守卫 + renderChildren
|
|
1019
|
+
* 活预览(与消息流 dsl part 同安全级),被拦截 / 渲染失败一律降级为
|
|
1020
|
+
* 受控占位块(ChatDenied 同款),MUST NOT 抛错。
|
|
1021
|
+
*
|
|
1022
|
+
* 纯展示组件:关闭只触发 onClose,不单方面修改外部状态。
|
|
1023
|
+
*/
|
|
1024
|
+
interface ArtifactPanelProps {
|
|
1025
|
+
/** 当前产出物;null 时内容区为空态(inspector 槽场景常见) */
|
|
1026
|
+
artifact?: ChatArtifact | null;
|
|
1027
|
+
/** 面板内容槽:提供时整体替代内建渲染器(标题栏保留) */
|
|
1028
|
+
inspector?: ReactNode;
|
|
1029
|
+
/** 关闭按钮 / 遮罩点击回调 */
|
|
1030
|
+
onClose?: () => void;
|
|
1031
|
+
/** dsl 产出物活预览的 Safe Registry;缺省时 dsl 内容渲染降级块 */
|
|
1032
|
+
safeRegistry?: Registry<unknown>;
|
|
1033
|
+
/** 注入 dsl 预览作用域 user */
|
|
1034
|
+
user?: Record<string, unknown>;
|
|
1035
|
+
className?: string;
|
|
1036
|
+
}
|
|
1037
|
+
declare function ArtifactPanel({ artifact, inspector, onClose, safeRegistry, user, className, }: ArtifactPanelProps): ReactNode;
|
|
1038
|
+
|
|
1039
|
+
declare function useSidebarDrawer(): {
|
|
1040
|
+
close: () => void;
|
|
1041
|
+
collapsed: boolean;
|
|
1042
|
+
} | null;
|
|
1043
|
+
interface AppShellProps {
|
|
1044
|
+
/** 侧栏内容(会话列表等),完全由调用方注入 */
|
|
1045
|
+
sidebar: ReactNode;
|
|
1046
|
+
/** 品牌区内容(logo / 名称):移动端渲染在顶栏;桌面端渲染在侧栏顶部品牌行(决策 D3) */
|
|
1047
|
+
brand?: ReactNode;
|
|
1048
|
+
/**
|
|
1049
|
+
* 路由 / 会话切换标识:值变化时抽屉在渲染期关闭
|
|
1050
|
+
* (compare-during-render,框架无关,替代路由 hook 耦合)
|
|
1051
|
+
*/
|
|
1052
|
+
locationKey?: string;
|
|
1053
|
+
/**
|
|
1054
|
+
* 侧栏底部固定区(spec: chat-app-shell / 侧栏底部槽):渲染在侧栏
|
|
1055
|
+
* 滚动区之后(不随菜单滚动);未提供时不渲染容器(零渲染承诺)
|
|
1056
|
+
*/
|
|
1057
|
+
sidebarFooter?: ReactNode;
|
|
1058
|
+
/**
|
|
1059
|
+
* 桌面端可折叠(spec: chat-app-shell / 桌面侧栏头部与折叠,决策 D3):
|
|
1060
|
+
* 为 true 时品牌行右端渲染折叠按钮,点击切换内部非受控 collapsed
|
|
1061
|
+
* 状态——折叠后桌面侧栏收窄为 icon rail;移动端不渲染折叠按钮、
|
|
1062
|
+
* 抽屉语义不受影响。缺省 false
|
|
1063
|
+
*/
|
|
1064
|
+
collapsible?: boolean;
|
|
1065
|
+
children: ReactNode;
|
|
1066
|
+
className?: string;
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* AppShell(spec: chat-app-shell):聊天工作区应用外壳 = 侧栏插槽 + 主区。
|
|
1070
|
+
*
|
|
1071
|
+
* 桌面(≥768px):侧栏与主区在 flex 行内同级排列;
|
|
1072
|
+
* 移动端(<768px):侧栏退出文档流变为左侧覆盖抽屉(遮罩 + 顶栏菜单按钮)。
|
|
1073
|
+
* 布局切换全部在 styles.css 媒体查询(`.pactor-chat-shell*`)中表达,
|
|
1074
|
+
* JS 只拥有抽屉开合状态 `drawerOpen`。
|
|
1075
|
+
*/
|
|
1076
|
+
declare function AppShell({ sidebar, brand, locationKey, sidebarFooter, collapsible, children, className }: AppShellProps): react.JSX.Element;
|
|
1077
|
+
|
|
1078
|
+
/**
|
|
1079
|
+
* 上下文数据源解析与候选列表(spec: chat-context-sources,设计决策 D1/D5):
|
|
1080
|
+
* 内部组件(不从 index.ts 导出),内建 @ 提及弹层与 + 菜单共用。
|
|
1081
|
+
*
|
|
1082
|
+
* - 静态 `items` 直用;`service` 引用经注入的 `callService(name, params)`
|
|
1083
|
+
* 异步解析,结果按 source 键(service 名 + params JSON)做会话级缓存
|
|
1084
|
+
* (Map 存 promise,同一弹层会话不重复请求)
|
|
1085
|
+
* - `callService` 未注入而 source 引用 service 时渲染内联错误提示,
|
|
1086
|
+
* 不抛错、不击穿组件树(与 Safe Registry 的受控降级同款取向)
|
|
1087
|
+
*/
|
|
1088
|
+
/** callService 服务桥签名(与 ChatServices.callService 同型) */
|
|
1089
|
+
type CallChatService = (name: string, params?: Record<string, unknown>) => Promise<unknown>;
|
|
1090
|
+
|
|
1091
|
+
/**
|
|
1092
|
+
* Composer(spec: chat-view / Composer + chat-composer-extensions):
|
|
1093
|
+
* 自适应高度 textarea + 状态机发送按钮(disabled / ready / streaming
|
|
1094
|
+
* 停止,同一按钮元素切换,streaming 态带纯 CSS 光环)。
|
|
1095
|
+
*
|
|
1096
|
+
* - IME 守卫(D6):compositionstart/end + keydown.isComposing 兜底,
|
|
1097
|
+
* 合成中 Enter 不发送
|
|
1098
|
+
* - 附件(D3):受控 `attachments` + `onAttachmentsChange`;拖拽悬停态、
|
|
1099
|
+
* 粘贴与文件选择产出 `File[]` 经 `onAttachFiles` 交给调用方(包内
|
|
1100
|
+
* 不上传);卡片点击经 `onAttachmentClick` 通知
|
|
1101
|
+
* - 扩展槽:`toolbarStart` / `toolbarEnd` 渲染槽;词边界 `@` 触发
|
|
1102
|
+
* `onMentionTrigger(query, anchorRect)`;"+" 按钮触发
|
|
1103
|
+
* `onPlusMenu(anchorRect)`(无回调不渲染入口)
|
|
1104
|
+
* - 内建特性(chat-builtin-features):models 非空时工具栏右端渲染
|
|
1105
|
+
* 模型 chip(AnchoredPopover 列表,toolbarEnd 之前);contexts 配置
|
|
1106
|
+
* 且未注入调用方回调时启用内建 @ 提及 / + 菜单弹层,选中项追加为
|
|
1107
|
+
* 输入区上方的上下文 chips(受控:contextChips + onContextChipsChange)
|
|
1108
|
+
*/
|
|
1109
|
+
interface ComposerProps {
|
|
1110
|
+
/** 发送回调;输入框在回调后清空 */
|
|
1111
|
+
onSend?: (text: string) => void;
|
|
1112
|
+
/** 流式中为 true:按钮变为停止,点击触发 onStop */
|
|
1113
|
+
streaming?: boolean;
|
|
1114
|
+
/** 停止当前 turn */
|
|
1115
|
+
onStop?: () => void;
|
|
1116
|
+
placeholder?: string;
|
|
1117
|
+
disabled?: boolean;
|
|
1118
|
+
/** 受控附件列表(提供即渲染附件区;上传与存储由调用方负责) */
|
|
1119
|
+
attachments?: ChatAttachment[];
|
|
1120
|
+
/** 附件列表变更(卡片移除后回调新数组) */
|
|
1121
|
+
onAttachmentsChange?: (attachments: ChatAttachment[]) => void;
|
|
1122
|
+
/** 粘贴 / 拖拽 / 文件选择产出的原始文件,交给调用方处理 */
|
|
1123
|
+
onAttachFiles?: (files: File[]) => void;
|
|
1124
|
+
/** 附件卡片点击通知(预览等由调用方实现) */
|
|
1125
|
+
onAttachmentClick?: (attachment: ChatAttachment) => void;
|
|
1126
|
+
/** 工具栏左 / 右渲染槽 */
|
|
1127
|
+
toolbarStart?: ReactNode;
|
|
1128
|
+
toolbarEnd?: ReactNode;
|
|
1129
|
+
/** 词边界 `@` 输入触发:query 为 `@` 后文本,anchorRect 为弹层锚点 */
|
|
1130
|
+
onMentionTrigger?: (query: string, anchorRect: DOMRect) => void;
|
|
1131
|
+
/** "+" 按钮触发弹层入口 */
|
|
1132
|
+
onPlusMenu?: (anchorRect: DOMRect) => void;
|
|
1133
|
+
/**
|
|
1134
|
+
* 内建模型选择(spec: chat-model-selector):非空时工具栏右端渲染
|
|
1135
|
+
* 内建模型 chip(位于 toolbarEnd 槽内容之前);缺省 / 空数组不渲染
|
|
1136
|
+
*/
|
|
1137
|
+
models?: ChatModelOption[];
|
|
1138
|
+
/** 当前选中模型 value(由 ChatView 经受控规则 D5 解析后传入) */
|
|
1139
|
+
model?: string;
|
|
1140
|
+
/** 弹层中选中模型时触发 */
|
|
1141
|
+
onModelChange?: (value: string) => void;
|
|
1142
|
+
/**
|
|
1143
|
+
* 内建上下文数据源(spec: chat-context-sources):存在 `trigger: '@'`
|
|
1144
|
+
* 的 source 且未注入 onMentionTrigger 时启用内建提及弹层;存在
|
|
1145
|
+
* `trigger: '+'` 的 source 且未注入 onPlusMenu 时渲染内建 "+" 入口
|
|
1146
|
+
*/
|
|
1147
|
+
contextSources?: ChatContextSource[];
|
|
1148
|
+
/** 上下文 chips(受控:由 ChatView 持有,渲染在输入区上方) */
|
|
1149
|
+
contextChips?: ChatContextItem[];
|
|
1150
|
+
/** chips 变更回调(选中追加 / 单独移除) */
|
|
1151
|
+
onContextChipsChange?: (chips: ChatContextItem[]) => void;
|
|
1152
|
+
/** service 引用解析出口(ChatServices.callService 透传) */
|
|
1153
|
+
callService?: CallChatService;
|
|
1154
|
+
}
|
|
1155
|
+
declare function Composer({ onSend, streaming, onStop, placeholder, disabled, attachments, onAttachmentsChange, onAttachFiles, onAttachmentClick, toolbarStart, toolbarEnd, onMentionTrigger, onPlusMenu, models, model, onModelChange, contextSources, contextChips, onContextChipsChange, callService, }: ComposerProps): react.JSX.Element;
|
|
1156
|
+
|
|
1157
|
+
/**
|
|
1158
|
+
* ChatView(设计决策 D6):消息列表(useSyncExternalStore 订阅
|
|
1159
|
+
* ConversationStore)+ Composer。
|
|
1160
|
+
*
|
|
1161
|
+
* 发送语义:`onSend` 回调先行(业务可完全自管);注入 `transport`
|
|
1162
|
+
* 时同时经 `runChatTurn` 驱动一轮对话(user 消息 + assistant 占位 +
|
|
1163
|
+
* 流式 reduce)。通常二选一。
|
|
1164
|
+
*
|
|
1165
|
+
* 流式交互(技术选型参考 DeepTutor web):
|
|
1166
|
+
* - 流式中 Composer 发送按钮变为停止按钮,点击 abort 当前 turn
|
|
1167
|
+
* (assistant 消息以 cancelled 收尾);
|
|
1168
|
+
* - 消息区贴底自动跟随,用户上翻释放、回底恢复,释放期间显示
|
|
1169
|
+
* "回到底部"浮动按钮。
|
|
1170
|
+
*
|
|
1171
|
+
* Composer 扩展 props(attachments / onAttachFiles / toolbar 槽 /
|
|
1172
|
+
* 提及与 "+" 触发等,见 ComposerProps)原样透传给内建 Composer。
|
|
1173
|
+
*/
|
|
1174
|
+
interface ChatViewProps extends Pick<ComposerProps, 'attachments' | 'onAttachmentsChange' | 'onAttachFiles' | 'onAttachmentClick' | 'toolbarStart' | 'toolbarEnd' | 'onMentionTrigger' | 'onPlusMenu'> {
|
|
1175
|
+
store: ConversationStore;
|
|
1176
|
+
/** 注入后发送即驱动 turn;缺省时仅触发 onSend */
|
|
1177
|
+
transport?: ChatTransport;
|
|
1178
|
+
onSend?: (text: string) => void;
|
|
1179
|
+
/** Safe Registry(createSafeRegistry 包装后的白名单注册表) */
|
|
1180
|
+
safeRegistry?: Registry<unknown>;
|
|
1181
|
+
/** capability 白名单与确认链(注入 capabilities 时注册 capability 动作) */
|
|
1182
|
+
capabilities?: ChatCapabilityRegistry;
|
|
1183
|
+
permission?: ChatPermissionChecker;
|
|
1184
|
+
confirm?: ChatConfirm;
|
|
1185
|
+
/** 会话 id(注入 dsl part 作用域 conversation.id) */
|
|
1186
|
+
conversationId?: string;
|
|
1187
|
+
/** 注入 dsl part 作用域 user / params */
|
|
1188
|
+
user?: Record<string, unknown>;
|
|
1189
|
+
params?: Record<string, unknown>;
|
|
1190
|
+
/** 空会话问候语(缺省用内置默认文案) */
|
|
1191
|
+
greeting?: string;
|
|
1192
|
+
/** 空会话副标题 */
|
|
1193
|
+
subtitle?: string;
|
|
1194
|
+
/** 空会话起始建议;空数组 / 未传时不渲染建议区 */
|
|
1195
|
+
suggestions?: ChatSuggestion[];
|
|
1196
|
+
/**
|
|
1197
|
+
* artifact part 就绪(status ready)时触发(spec: chat-dsl-component /
|
|
1198
|
+
* 产出物事件);同一 part 只触发一次,框架不擅自打开面板
|
|
1199
|
+
*/
|
|
1200
|
+
onArtifact?: (artifact: ChatArtifact) => void;
|
|
1201
|
+
/** artifact 卡片"在面板中打开"回调(透传 PartRenderer) */
|
|
1202
|
+
onOpenArtifact?: (artifact: ChatArtifact) => void;
|
|
1203
|
+
/**
|
|
1204
|
+
* 内建模型选择(spec: chat-model-selector,决策 D5):
|
|
1205
|
+
* `model` + `onModelChange` 同时提供即受控(以 props 为准);
|
|
1206
|
+
* 仅提供 `models` 时组件自持选中态(缺省 models[0]);
|
|
1207
|
+
* 未配置 models 时不渲染 chip 且 ChatInput.model 为 undefined
|
|
1208
|
+
*/
|
|
1209
|
+
models?: ChatModelOption[];
|
|
1210
|
+
model?: string;
|
|
1211
|
+
onModelChange?: (value: string) => void;
|
|
1212
|
+
/**
|
|
1213
|
+
* 模型 chip 渲染位置(spec: chat-model-selector / 模型选择位置配置,
|
|
1214
|
+
* 决策 D2):缺省 'composer'(Composer 工具栏右端);'header' 时
|
|
1215
|
+
* Composer 不再渲染 chip(chip 由 ChatComposition 渲染到工作区头部
|
|
1216
|
+
* 左端——ChatView 单独使用时 'header' 等效于不渲染 chip)
|
|
1217
|
+
*/
|
|
1218
|
+
modelPlacement?: 'composer' | 'header';
|
|
1219
|
+
/**
|
|
1220
|
+
* 内建上下文数据源(spec: chat-context-sources):chips 状态由
|
|
1221
|
+
* ChatView 自持(选中追加 / 单独移除 / 发送后清空),
|
|
1222
|
+
* `onContextsChange` 并行通知;未配置时不启用内建弹层与 "+" 入口
|
|
1223
|
+
*/
|
|
1224
|
+
contexts?: ChatContextSource[];
|
|
1225
|
+
onContextsChange?: (chips: ChatContextItem[]) => void;
|
|
1226
|
+
/** service 引用解析出口(ChatServices.callService 透传 Composer 与消息动作条) */
|
|
1227
|
+
callService?: CallChatService;
|
|
1228
|
+
/**
|
|
1229
|
+
* 消息操作条声明式配置(spec: chat-message-actions,决策 D1):
|
|
1230
|
+
* 缺省等价于 `['copy', 'regenerate', 'retry', 'edit']`(与历史行为一致);
|
|
1231
|
+
* 传入数组时严格按数组顺序与内容渲染,未列出的内建动作不出现
|
|
1232
|
+
*/
|
|
1233
|
+
messageActions?: Array<BuiltinMessageAction | ChatMessageAction>;
|
|
1234
|
+
/** 全部消息动作(含内建)点击的并行通知(event 语义,不影响内建默认行为) */
|
|
1235
|
+
onMessageAction?: (actionId: string, message: ChatMessage) => void;
|
|
1236
|
+
className?: string;
|
|
1237
|
+
}
|
|
1238
|
+
declare function ChatView({ store, transport, onSend, safeRegistry, capabilities, permission, confirm, conversationId, user, params, greeting, subtitle, suggestions, className, onArtifact, onOpenArtifact, attachments, onAttachmentsChange, onAttachFiles, onAttachmentClick, toolbarStart, toolbarEnd, onMentionTrigger, onPlusMenu, models, model, onModelChange, modelPlacement, contexts, onContextsChange, callService, messageActions, onMessageAction, }: ChatViewProps): react.JSX.Element;
|
|
1239
|
+
|
|
1240
|
+
/**
|
|
1241
|
+
* ActivityTrace(spec: chat-activity-trace,设计决策 D1/D4):
|
|
1242
|
+
* assistant 消息顶部的活动轨迹区。
|
|
1243
|
+
*
|
|
1244
|
+
* - 流式状态头(StreamingStatus):动画图标 + 呼吸状态文案 + 秒级计时,
|
|
1245
|
+
* 模式由纯函数 detectStreamingMode 推导;消息结束后定格为完成态;
|
|
1246
|
+
* - 配对工具轨迹(TraceRow):pairToolTraces 输出的单行可展开条目;
|
|
1247
|
+
* - thinking 折叠卡(ThinkingCard):markdown 正文,流式展开 + 进行中指示,
|
|
1248
|
+
* 答案阶段自动折叠,用户操作后 pin。
|
|
1249
|
+
*
|
|
1250
|
+
* 折叠状态机(每条消息独立,随组件实例记忆):`auto | pinned-open |
|
|
1251
|
+
* pinned-closed`——auto 跟随流式阶段;用户点击后 pin,不再自动变更。
|
|
1252
|
+
*/
|
|
1253
|
+
interface ActivityTraceProps {
|
|
1254
|
+
message: ChatMessage;
|
|
1255
|
+
}
|
|
1256
|
+
declare function ActivityTrace({ message }: ActivityTraceProps): react.JSX.Element;
|
|
1257
|
+
|
|
1258
|
+
/**
|
|
1259
|
+
* MessageBubble:按 role 区分呈现(参考 DeepTutor web 消息区设计)——
|
|
1260
|
+
* user 右侧圆角气泡;assistant 左侧通栏排版:顶部活动轨迹区
|
|
1261
|
+
* (ActivityTrace:状态头 + thinking + 配对工具轨迹),正文 parts 按序
|
|
1262
|
+
* 渲染;hover 操作条(MessageActions:复制 / 重新生成 / 编辑 / 重试);
|
|
1263
|
+
* system 居中弱提示。
|
|
1264
|
+
* 颜色经 `--pactor-chat-*` 变量表达。
|
|
1265
|
+
*/
|
|
1266
|
+
interface MessageBubbleProps {
|
|
1267
|
+
message: ChatMessage;
|
|
1268
|
+
/** 透传给 dsl part 的渲染运行时与作用域 */
|
|
1269
|
+
runtime?: ChatRuntime;
|
|
1270
|
+
scope?: Omit<ChatScope, 'message'>;
|
|
1271
|
+
params?: Record<string, unknown>;
|
|
1272
|
+
/** 末条已完成 assistant 消息:提供 onRegenerate 时出示重新生成入口 */
|
|
1273
|
+
showRegenerate?: boolean;
|
|
1274
|
+
/** 重新生成回调(spec: chat-message-actions / 重新生成) */
|
|
1275
|
+
onRegenerate?: () => void;
|
|
1276
|
+
/** error 消息重试回调(spec: chat-message-actions / 错误重试) */
|
|
1277
|
+
onRetry?: () => void;
|
|
1278
|
+
/**
|
|
1279
|
+
* user 消息编辑重发回调(spec: chat-message-actions / 用户消息编辑重发):
|
|
1280
|
+
* 提供时出示编辑入口;确认后以新文本回调(调用方负责截断 store 并重跑
|
|
1281
|
+
* turn);取消编辑不触任何回调。
|
|
1282
|
+
*/
|
|
1283
|
+
onEditResend?: (text: string) => void;
|
|
1284
|
+
/**
|
|
1285
|
+
* 消息操作条声明式配置(spec: chat-message-actions,透传 MessageActions):
|
|
1286
|
+
* 缺省渲染内建 copy / regenerate / retry / edit(与历史行为一致)
|
|
1287
|
+
*/
|
|
1288
|
+
messageActions?: Array<BuiltinMessageAction | ChatMessageAction>;
|
|
1289
|
+
/** 自定义动作服务派发出口(ChatServices.callService 透传) */
|
|
1290
|
+
callService?: CallChatService;
|
|
1291
|
+
/** 全部动作(含内建)点击的并行通知 */
|
|
1292
|
+
onMessageAction?: (actionId: string, message: ChatMessage) => void;
|
|
1293
|
+
/** artifact 卡片"在面板中打开"回调(透传 PartRenderer) */
|
|
1294
|
+
onOpenArtifact?: (artifact: ChatArtifact) => void;
|
|
1295
|
+
}
|
|
1296
|
+
declare function MessageBubble({ message, runtime, scope, showRegenerate, onRegenerate, onRetry, onEditResend, messageActions, callService, onMessageAction, onOpenArtifact, }: MessageBubbleProps): react.JSX.Element;
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* MessageActions(spec: chat-message-actions / 消息操作条):
|
|
1300
|
+
* 消息 hover 显现的操作条,数据驱动渲染——`actions` 缺省为
|
|
1301
|
+
* `['copy', 'regenerate', 'retry', 'edit']`(与历史硬编码渲染一致);
|
|
1302
|
+
* 传入数组时严格按数组顺序与内容渲染(数组即真相,未列出的内建动作
|
|
1303
|
+
* 不出现)。内建动作保留包内默认行为(复制写剪贴板 / 重新生成 / 重试 /
|
|
1304
|
+
* 编辑进内联编辑框),配置的 label / icon / roles / visibleWhen 按字段
|
|
1305
|
+
* 覆盖内建默认描述;「regenerate 仅末条 assistant」与 transport 依赖为
|
|
1306
|
+
* 不可覆盖的附加约束。自定义动作(无 builtin)点击经 callService 派发
|
|
1307
|
+
* (未注入时 console.warn 跳过,不抛错);全部动作点击并行触发
|
|
1308
|
+
* onMessageAction 通知。
|
|
1309
|
+
*
|
|
1310
|
+
* 接口边界(D0):组件只做展示与回调触发,turn 驱动由调用方
|
|
1311
|
+
* (ChatView)注入;无回调时对应内建入口不渲染。
|
|
1312
|
+
*/
|
|
1313
|
+
interface MessageActionsProps {
|
|
1314
|
+
message: ChatMessage;
|
|
1315
|
+
/**
|
|
1316
|
+
* 操作条声明式配置(spec: chat-message-actions,决策 D1):
|
|
1317
|
+
* 缺省等价于 `['copy', 'regenerate', 'retry', 'edit']`;
|
|
1318
|
+
* 字符串项等价于 `{ id: <name>, builtin: <name> }`
|
|
1319
|
+
*/
|
|
1320
|
+
actions?: Array<BuiltinMessageAction | ChatMessageAction>;
|
|
1321
|
+
/** 末条已完成 assistant:regenerate 附加约束(不可被配置覆盖) */
|
|
1322
|
+
showRegenerate?: boolean;
|
|
1323
|
+
/** 重新生成回调(未提供时 regenerate 不渲染) */
|
|
1324
|
+
onRegenerate?: () => void;
|
|
1325
|
+
/** user 消息编辑入口回调(未提供时 edit 不渲染) */
|
|
1326
|
+
onEdit?: () => void;
|
|
1327
|
+
/** error 消息重试回调(未提供时 retry 不渲染) */
|
|
1328
|
+
onRetry?: () => void;
|
|
1329
|
+
/** error 消息:重试入口常显(不依赖 hover) */
|
|
1330
|
+
forceVisible?: boolean;
|
|
1331
|
+
/** 自定义动作服务派发出口(ChatServices.callService 透传) */
|
|
1332
|
+
callService?: CallChatService;
|
|
1333
|
+
/** 全部动作(含内建)点击的并行通知 */
|
|
1334
|
+
onMessageAction?: (actionId: string, message: ChatMessage) => void;
|
|
1335
|
+
}
|
|
1336
|
+
/** 动作图标名 → lucide 子集(白名单式,同菜单 MENU_ICONS 口径;未知名渲染占位图标,不抛错) */
|
|
1337
|
+
declare const MESSAGE_ACTION_ICONS: Record<string, ComponentType<{
|
|
1338
|
+
size?: number;
|
|
1339
|
+
}>>;
|
|
1340
|
+
/** 收集消息的可复制文本(text / markdown part 按序拼接) */
|
|
1341
|
+
declare function collectMessageText(message: ChatMessage): string;
|
|
1342
|
+
declare function MessageActions({ message, actions, showRegenerate, onRegenerate, onEdit, onRetry, forceVisible, callService, onMessageAction, }: MessageActionsProps): react.JSX.Element | null;
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* PartRenderer:按 part 类型渲染。
|
|
1346
|
+
*
|
|
1347
|
+
* - text → 文本段落;markdown → @pactor-app/markdown 安全渲染器
|
|
1348
|
+
* (streaming 期间经 useSmoothStreamText 打字机揭示)
|
|
1349
|
+
* - dsl → runtime DslRenderer(Safe Registry + chat 作用域),
|
|
1350
|
+
* 白名单外节点经 guardChatDsl 替换为受控"不允许"占位
|
|
1351
|
+
* - tool-call / tool-result / thinking → 不在此渲染(由 assistant 消息
|
|
1352
|
+
* 顶部的 ActivityTrace 配对 / 折叠呈现,见 chat-activity-trace)
|
|
1353
|
+
* - error → 自绘警示条;status → 弱提示文本
|
|
1354
|
+
* - artifact → 产出物卡片(标题 + kind 角标 + "在面板中打开"按钮,
|
|
1355
|
+
* spec: chat-artifact-panel)
|
|
1356
|
+
*
|
|
1357
|
+
* 视图零 antd 依赖,颜色经 `@pactor-app/chat/styles.css` 的
|
|
1358
|
+
* `--pactor-chat-*` 变量表达。
|
|
1359
|
+
*/
|
|
1360
|
+
interface PartRendererProps {
|
|
1361
|
+
part: ChatPart;
|
|
1362
|
+
/** dsl part 渲染运行时(缺省时 dsl part 渲染受控占位) */
|
|
1363
|
+
runtime?: ChatRuntime;
|
|
1364
|
+
/** dsl part 的 chat 作用域 */
|
|
1365
|
+
scope?: ChatScope;
|
|
1366
|
+
/** 所属消息是否流式中(text/markdown 启用平滑揭示) */
|
|
1367
|
+
streaming?: boolean;
|
|
1368
|
+
/** artifact 卡片"在面板中打开"回调(spec: chat-artifact-panel) */
|
|
1369
|
+
onOpenArtifact?: (artifact: ChatArtifact) => void;
|
|
1370
|
+
}
|
|
1371
|
+
/** 白名单外组件的受控占位(注册名 ChatDenied,见 dsl-guard) */
|
|
1372
|
+
declare function ChatDenied({ deniedType }: {
|
|
1373
|
+
deniedType?: string;
|
|
1374
|
+
}): react.JSX.Element;
|
|
1375
|
+
declare function PartRenderer({ part, runtime, scope, streaming, onOpenArtifact }: PartRendererProps): react.JSX.Element | null;
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* ChatLayout(设计决策 D6):chat 布局 = header(title)+ ChatView 区。
|
|
1379
|
+
* V1 无会话历史侧栏。颜色经 `--pactor-chat-*` 变量表达
|
|
1380
|
+
* (`@pactor-app/chat/styles.css`),布局结构类样式同文件。
|
|
1381
|
+
*/
|
|
1382
|
+
interface ChatLayoutProps {
|
|
1383
|
+
title?: ReactNode;
|
|
1384
|
+
children?: ReactNode;
|
|
1385
|
+
}
|
|
1386
|
+
declare function ChatLayout({ title, children }: ChatLayoutProps): react.JSX.Element;
|
|
1387
|
+
/** 布局类型名(resolveLayout(registry, 'chat') 命中) */
|
|
1388
|
+
declare const CHAT_LAYOUT_TYPE = "chat";
|
|
1389
|
+
/**
|
|
1390
|
+
* 结构化 LayoutRegistry(兼容 @pactor-app/ui layout 层的 LayoutRegistry =
|
|
1391
|
+
* Registry<LayoutComponent>):以结构化类型声明,避免对
|
|
1392
|
+
* @pactor-app/ui 产生运行时依赖。
|
|
1393
|
+
*/
|
|
1394
|
+
interface ChatLayoutRegistry {
|
|
1395
|
+
has(name: string): boolean;
|
|
1396
|
+
register(name: string, component: ComponentType<any>): void;
|
|
1397
|
+
}
|
|
1398
|
+
/** 注册 chat 布局(已注册时不覆盖,与 createLayoutRegistry 约定一致) */
|
|
1399
|
+
declare function registerChatLayout(layoutRegistry: ChatLayoutRegistry): void;
|
|
1400
|
+
|
|
1401
|
+
export { ActivityTrace, type ActivityTraceProps, AppShell, type AppShellProps, ArtifactPanel, type ArtifactPanelProps, type ArtifactPatch, ArtifactStore, type BuiltinMessageAction, CHAT_COMPONENT_TYPE, CHAT_DENIED_TYPE, CHAT_LAYOUT_TYPE, CHAT_SHELL_COMPONENT_TYPE, type CapabilityActionDeps, type CapabilityHandler, Chat, type ChatArtifact, type ChatAttachment, type ChatCapabilityRegistry, type ChatConfirm, type ChatConfirmRequest, type ChatContextItem, type ChatContextSource, ChatDenied, type ChatEvent, type ChatHeaderAction, type ChatInput, ChatLayout, type ChatLayoutProps, type ChatLayoutRegistry, type ChatMenuItem, type ChatMessage, type ChatMessageAction, type ChatModelOption, type ChatPart, type ChatPermissionChecker, type ChatProps, type ChatRole, type ChatRuntime, type ChatScope, type ChatServices, ChatServicesProvider, ChatShell, type ChatShellProps, ChatSidebarMenu, type ChatSuggestion, type ChatTransport, type ChatTurnResult, ChatView, type ChatViewProps, type ChatWorkspaceProps, type ChatWorkspaceServices, Composer, type ComposerProps, ConversationStore, type CreateChatRuntimeOptions, DEFAULT_CHAT_GREETING, EmptyState, type EmptyStateProps, MENU_ICONS, MESSAGE_ACTION_ICONS, type ManualChatDriver, MessageActions, type MessageActionsProps, MessageBubble, type MessageBubbleProps, type MessagePatch, type MessageStatus, type PartPatch, type PartRef, PartRenderer, type PartRendererProps, type PartStatus, type RunChatTurnOptions, type StreamingMode, type ToolCallStatus, type ToolTraceEntry, type UseChatAutoScrollOptions, type UseChatAutoScrollResult, type UseSmoothStreamTextOptions, applyChatEvent, buildChatScope, collectMessageText, createChatId, createChatRuntime, createChatWorkspace, createManualDriver, createSafeRegistry, detectStreamingMode, guardChatDsl, pairToolTraces, registerCapabilityAction, registerChatComponent, registerChatLayout, registerChatShellComponent, runChatTurn, runRegenerateTurn, useChatAutoScroll, useChatServices, useSidebarDrawer, useSmoothStreamText };
|