@coralai/sps-cli 0.65.33 → 0.65.34
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/dist/chat-protocol/events.d.ts +131 -0
- package/dist/chat-protocol/events.d.ts.map +1 -0
- package/dist/chat-protocol/events.js +134 -0
- package/dist/chat-protocol/events.js.map +1 -0
- package/dist/chat-protocol/form.d.ts +66 -0
- package/dist/chat-protocol/form.d.ts.map +1 -0
- package/dist/chat-protocol/form.js +25 -0
- package/dist/chat-protocol/form.js.map +1 -0
- package/dist/chat-protocol/index.d.ts +21 -0
- package/dist/chat-protocol/index.d.ts.map +1 -0
- package/dist/chat-protocol/index.js +17 -0
- package/dist/chat-protocol/index.js.map +1 -0
- package/dist/chat-protocol/reduce.d.ts +33 -0
- package/dist/chat-protocol/reduce.d.ts.map +1 -0
- package/dist/chat-protocol/reduce.js +204 -0
- package/dist/chat-protocol/reduce.js.map +1 -0
- package/dist/chat-protocol/types.d.ts +85 -0
- package/dist/chat-protocol/types.d.ts.map +1 -0
- package/dist/chat-protocol/types.js +9 -0
- package/dist/chat-protocol/types.js.map +1 -0
- package/dist/chat-protocol/typewriter.d.ts +25 -0
- package/dist/chat-protocol/typewriter.d.ts.map +1 -0
- package/dist/chat-protocol/typewriter.js +36 -0
- package/dist/chat-protocol/typewriter.js.map +1 -0
- package/dist/console/chatEventLog.d.ts +47 -0
- package/dist/console/chatEventLog.d.ts.map +1 -0
- package/dist/console/chatEventLog.js +79 -0
- package/dist/console/chatEventLog.js.map +1 -0
- package/dist/console/routes/chat.d.ts +3 -0
- package/dist/console/routes/chat.d.ts.map +1 -1
- package/dist/console/routes/chat.js +173 -114
- package/dist/console/routes/chat.js.map +1 -1
- package/dist/console-assets/assets/{ShowcasePage-NmXybDqC.js → ShowcasePage-x-qRvSx_.js} +1 -1
- package/dist/console-assets/assets/{index-DCAnGMiQ.js → index-Ifjq4orx.js} +216 -216
- package/dist/console-assets/index.html +1 -1
- package/dist/core/activityStream.d.ts +1 -1
- package/dist/core/activityStream.d.ts.map +1 -1
- package/dist/core/activityStream.js +7 -2
- package/dist/core/activityStream.js.map +1 -1
- package/dist/core/agents/AgentBackend.d.ts +11 -1
- package/dist/core/agents/AgentBackend.d.ts.map +1 -1
- package/dist/core/agents/AgentBackend.js.map +1 -1
- package/dist/core/interactions/formSpec.d.ts +57 -0
- package/dist/core/interactions/formSpec.d.ts.map +1 -0
- package/dist/core/interactions/formSpec.js +123 -0
- package/dist/core/interactions/formSpec.js.map +1 -0
- package/dist/openai-agent/interactions/broker.d.ts.map +1 -1
- package/dist/openai-agent/interactions/broker.js +38 -77
- package/dist/openai-agent/interactions/broker.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module chat-protocol/events
|
|
3
|
+
* @description 对话流的**唯一页面协议** `ChatStreamEvent`,以及现网 SSE 事件名 → 规范事件
|
|
4
|
+
* 的适配器。
|
|
5
|
+
*
|
|
6
|
+
* 为什么留适配器而不是直接改 SSE 事件名:现网三个前端都在监听 `chat.message.*`,
|
|
7
|
+
* 一次性改名会同时打断三端。适配器让**协议先统一、线上名后收敛**——先把三端搬到同一个
|
|
8
|
+
* reducer 上,线协议的清理是之后一个纯服务端动作。
|
|
9
|
+
*
|
|
10
|
+
* 零依赖规则见 `./types.ts` 头注释。
|
|
11
|
+
* @layer contract
|
|
12
|
+
* @boundedContext chat
|
|
13
|
+
*/
|
|
14
|
+
import type { InteractionRespond } from './form.js';
|
|
15
|
+
import type { ChatBlock, ChatMessage } from './types.js';
|
|
16
|
+
/**
|
|
17
|
+
* 协议版本。**不认识的版本要大声报错,不许静默降级**——版本不齐必须是一个明确的错误,
|
|
18
|
+
* 而不是又一个"两个页面显示不一样"的幽灵。
|
|
19
|
+
*/
|
|
20
|
+
export declare const CHAT_PROTOCOL_VERSION = 1;
|
|
21
|
+
/** 规范事件。名字按 `<名词>.<动作>`,名词与消息块类型一致。 */
|
|
22
|
+
export type ChatStreamEvent =
|
|
23
|
+
/** 回合开始(还没有任何内容)。 */
|
|
24
|
+
{
|
|
25
|
+
type: 'turn.pending';
|
|
26
|
+
sessionId: string;
|
|
27
|
+
turnId: string;
|
|
28
|
+
seq?: number;
|
|
29
|
+
}
|
|
30
|
+
/** 断线重连/切回时的在途快照:blocks 是当前完整状态,直接覆盖。 */
|
|
31
|
+
| {
|
|
32
|
+
type: 'turn.snapshot';
|
|
33
|
+
sessionId: string;
|
|
34
|
+
turnId: string;
|
|
35
|
+
blocks: ChatBlock[];
|
|
36
|
+
seq?: number;
|
|
37
|
+
} | {
|
|
38
|
+
type: 'text.delta';
|
|
39
|
+
sessionId: string;
|
|
40
|
+
turnId: string;
|
|
41
|
+
text: string;
|
|
42
|
+
seq?: number;
|
|
43
|
+
} | {
|
|
44
|
+
type: 'tool_use.started';
|
|
45
|
+
sessionId: string;
|
|
46
|
+
turnId: string;
|
|
47
|
+
id: string;
|
|
48
|
+
title: string;
|
|
49
|
+
kind: string;
|
|
50
|
+
status: string;
|
|
51
|
+
input?: unknown;
|
|
52
|
+
locations?: unknown;
|
|
53
|
+
seq?: number;
|
|
54
|
+
} | {
|
|
55
|
+
type: 'tool_use.updated';
|
|
56
|
+
sessionId: string;
|
|
57
|
+
turnId: string;
|
|
58
|
+
id: string;
|
|
59
|
+
status: string;
|
|
60
|
+
input?: unknown;
|
|
61
|
+
locations?: unknown;
|
|
62
|
+
seq?: number;
|
|
63
|
+
}
|
|
64
|
+
/** 需要用户交互(表单 / 选择器 / 审批)。schema 已在引擎侧完全展开。 */
|
|
65
|
+
| {
|
|
66
|
+
type: 'interaction.required';
|
|
67
|
+
sessionId: string;
|
|
68
|
+
turnId: string;
|
|
69
|
+
id: string;
|
|
70
|
+
kind: string;
|
|
71
|
+
title: string;
|
|
72
|
+
schema: unknown;
|
|
73
|
+
/** 答案怎么送回去(见 ./form 的 InteractionRespond)。 */
|
|
74
|
+
respond?: InteractionRespond;
|
|
75
|
+
revision: number;
|
|
76
|
+
seq?: number;
|
|
77
|
+
}
|
|
78
|
+
/** 交互有了结果。**同时作用于在途回合与已提交消息**——用户常在回合仍在跑时提交表单。 */
|
|
79
|
+
| {
|
|
80
|
+
type: 'interaction.updated';
|
|
81
|
+
sessionId: string;
|
|
82
|
+
interactionId: string;
|
|
83
|
+
status: 'answered' | 'cancelled';
|
|
84
|
+
revision: number;
|
|
85
|
+
answer?: unknown;
|
|
86
|
+
seq?: number;
|
|
87
|
+
}
|
|
88
|
+
/** 一条权威消息落库(用户消息,或补拉到的历史)。 */
|
|
89
|
+
| {
|
|
90
|
+
type: 'message.appended';
|
|
91
|
+
sessionId: string;
|
|
92
|
+
message: ChatMessage;
|
|
93
|
+
seq?: number;
|
|
94
|
+
}
|
|
95
|
+
/** 回合成功收尾,携带完整权威消息(增量丢失也能靠它自愈)。 */
|
|
96
|
+
| {
|
|
97
|
+
type: 'turn.completed';
|
|
98
|
+
sessionId: string;
|
|
99
|
+
turnId: string;
|
|
100
|
+
message: ChatMessage;
|
|
101
|
+
seq?: number;
|
|
102
|
+
}
|
|
103
|
+
/** 回合以错误/中断收尾。 */
|
|
104
|
+
| {
|
|
105
|
+
type: 'turn.failed';
|
|
106
|
+
sessionId: string;
|
|
107
|
+
turnId?: string;
|
|
108
|
+
message?: ChatMessage;
|
|
109
|
+
seq?: number;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 续传游标已失效(断点滚出服务端事件窗口)。**不能装作无缝续上** —— 客户端必须重新
|
|
113
|
+
* 拉取会话快照重建,否则会拿着一段有洞的序列以为自己是完整的。
|
|
114
|
+
*/
|
|
115
|
+
| {
|
|
116
|
+
type: 'resync.required';
|
|
117
|
+
sessionId: string;
|
|
118
|
+
reason?: string;
|
|
119
|
+
seq?: number;
|
|
120
|
+
};
|
|
121
|
+
/** 现网 SSE 事件名清单(订阅用)。 */
|
|
122
|
+
export declare const WIRE_EVENT_NAMES: readonly ["chat.message", "chat.message.pending", "chat.message.snapshot", "chat.message.chunk.text", "chat.message.chunk.tool_use", "chat.message.chunk.tool_update", "chat.message.chunk.interaction", "chat.message.interaction.updated", "chat.message.complete", "chat.message.error", "chat.resync.required"];
|
|
123
|
+
/**
|
|
124
|
+
* 把一条现网 SSE 事件翻成规范事件。不认识 / 字段缺失 → 返回 null(调用方忽略即可)。
|
|
125
|
+
* 解析 JSON 失败由调用方处理。
|
|
126
|
+
*
|
|
127
|
+
* `streamSessionId` = 这条 SSE 流所属的会话。**流的归属以 URL 为准**(`/stream/chat/:id`),
|
|
128
|
+
* payload 里的 `sessionId` 只作交叉校验:两者都在且不一致 → 丢弃(串台防线)。
|
|
129
|
+
*/
|
|
130
|
+
export declare function fromWireEvent(name: string, data: unknown, streamSessionId: string): ChatStreamEvent | null;
|
|
131
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/chat-protocol/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 协议版本。**不认识的版本要大声报错,不许静默降级**——版本不齐必须是一个明确的错误,
|
|
3
|
+
* 而不是又一个"两个页面显示不一样"的幽灵。
|
|
4
|
+
*/
|
|
5
|
+
export const CHAT_PROTOCOL_VERSION = 1;
|
|
6
|
+
// ── 现网 SSE 事件名 → 规范事件 ────────────────────────────────────────
|
|
7
|
+
/** 现网 SSE 事件名清单(订阅用)。 */
|
|
8
|
+
export const WIRE_EVENT_NAMES = [
|
|
9
|
+
'chat.message',
|
|
10
|
+
'chat.message.pending',
|
|
11
|
+
'chat.message.snapshot',
|
|
12
|
+
'chat.message.chunk.text',
|
|
13
|
+
'chat.message.chunk.tool_use',
|
|
14
|
+
'chat.message.chunk.tool_update',
|
|
15
|
+
'chat.message.chunk.interaction',
|
|
16
|
+
'chat.message.interaction.updated',
|
|
17
|
+
'chat.message.complete',
|
|
18
|
+
'chat.message.error',
|
|
19
|
+
'chat.resync.required',
|
|
20
|
+
];
|
|
21
|
+
function str(v) {
|
|
22
|
+
return typeof v === 'string' ? v : '';
|
|
23
|
+
}
|
|
24
|
+
function num(v, fallback) {
|
|
25
|
+
return typeof v === 'number' && Number.isFinite(v) ? v : fallback;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 把一条现网 SSE 事件翻成规范事件。不认识 / 字段缺失 → 返回 null(调用方忽略即可)。
|
|
29
|
+
* 解析 JSON 失败由调用方处理。
|
|
30
|
+
*
|
|
31
|
+
* `streamSessionId` = 这条 SSE 流所属的会话。**流的归属以 URL 为准**(`/stream/chat/:id`),
|
|
32
|
+
* payload 里的 `sessionId` 只作交叉校验:两者都在且不一致 → 丢弃(串台防线)。
|
|
33
|
+
*/
|
|
34
|
+
export function fromWireEvent(name, data, streamSessionId) {
|
|
35
|
+
if (!data || typeof data !== 'object' || !streamSessionId)
|
|
36
|
+
return null;
|
|
37
|
+
const d = data;
|
|
38
|
+
const payloadSession = str(d.sessionId);
|
|
39
|
+
if (payloadSession && payloadSession !== streamSessionId)
|
|
40
|
+
return null;
|
|
41
|
+
const sessionId = streamSessionId;
|
|
42
|
+
const seq = typeof d.seq === 'number' ? d.seq : undefined;
|
|
43
|
+
const turnId = str(d.assistantId) || str(d.turnId);
|
|
44
|
+
switch (name) {
|
|
45
|
+
case 'chat.message':
|
|
46
|
+
return d.message ? { type: 'message.appended', sessionId, message: d.message, seq } : null;
|
|
47
|
+
case 'chat.message.pending':
|
|
48
|
+
return turnId ? { type: 'turn.pending', sessionId, turnId, seq } : null;
|
|
49
|
+
case 'chat.message.snapshot':
|
|
50
|
+
return turnId
|
|
51
|
+
? { type: 'turn.snapshot', sessionId, turnId, blocks: d.blocks ?? [], seq }
|
|
52
|
+
: null;
|
|
53
|
+
case 'chat.message.chunk.text':
|
|
54
|
+
return turnId && typeof d.text === 'string'
|
|
55
|
+
? { type: 'text.delta', sessionId, turnId, text: d.text, seq }
|
|
56
|
+
: null;
|
|
57
|
+
case 'chat.message.chunk.tool_use':
|
|
58
|
+
return turnId && str(d.id)
|
|
59
|
+
? {
|
|
60
|
+
type: 'tool_use.started',
|
|
61
|
+
sessionId,
|
|
62
|
+
turnId,
|
|
63
|
+
id: str(d.id),
|
|
64
|
+
title: str(d.title),
|
|
65
|
+
kind: str(d.kind),
|
|
66
|
+
status: str(d.status),
|
|
67
|
+
input: d.input,
|
|
68
|
+
locations: d.locations,
|
|
69
|
+
seq,
|
|
70
|
+
}
|
|
71
|
+
: null;
|
|
72
|
+
case 'chat.message.chunk.tool_update':
|
|
73
|
+
return turnId && str(d.id)
|
|
74
|
+
? {
|
|
75
|
+
type: 'tool_use.updated',
|
|
76
|
+
sessionId,
|
|
77
|
+
turnId,
|
|
78
|
+
id: str(d.id),
|
|
79
|
+
status: str(d.status),
|
|
80
|
+
input: d.input,
|
|
81
|
+
locations: d.locations,
|
|
82
|
+
seq,
|
|
83
|
+
}
|
|
84
|
+
: null;
|
|
85
|
+
case 'chat.message.chunk.interaction':
|
|
86
|
+
return turnId && str(d.id)
|
|
87
|
+
? {
|
|
88
|
+
type: 'interaction.required',
|
|
89
|
+
sessionId,
|
|
90
|
+
turnId,
|
|
91
|
+
id: str(d.id),
|
|
92
|
+
kind: str(d.kind),
|
|
93
|
+
title: str(d.title),
|
|
94
|
+
schema: d.schema,
|
|
95
|
+
...(d.respond === 'message' || d.respond === 'endpoint' ? { respond: d.respond } : {}),
|
|
96
|
+
revision: num(d.revision, 1),
|
|
97
|
+
seq,
|
|
98
|
+
}
|
|
99
|
+
: null;
|
|
100
|
+
case 'chat.message.interaction.updated':
|
|
101
|
+
return str(d.interactionId)
|
|
102
|
+
? {
|
|
103
|
+
type: 'interaction.updated',
|
|
104
|
+
sessionId,
|
|
105
|
+
interactionId: str(d.interactionId),
|
|
106
|
+
status: d.status === 'cancelled' ? 'cancelled' : 'answered',
|
|
107
|
+
revision: num(d.revision, 1),
|
|
108
|
+
answer: d.answer,
|
|
109
|
+
seq,
|
|
110
|
+
}
|
|
111
|
+
: null;
|
|
112
|
+
case 'chat.message.complete':
|
|
113
|
+
return turnId && d.message
|
|
114
|
+
? { type: 'turn.completed', sessionId, turnId, message: d.message, seq }
|
|
115
|
+
: null;
|
|
116
|
+
case 'chat.resync.required':
|
|
117
|
+
return {
|
|
118
|
+
type: 'resync.required',
|
|
119
|
+
sessionId,
|
|
120
|
+
...(typeof d.reason === 'string' ? { reason: d.reason } : {}),
|
|
121
|
+
};
|
|
122
|
+
case 'chat.message.error':
|
|
123
|
+
return {
|
|
124
|
+
type: 'turn.failed',
|
|
125
|
+
sessionId,
|
|
126
|
+
...(turnId ? { turnId } : {}),
|
|
127
|
+
...(d.message ? { message: d.message } : {}),
|
|
128
|
+
seq,
|
|
129
|
+
};
|
|
130
|
+
default:
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/chat-protocol/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module chat-protocol/form
|
|
3
|
+
* @description **规范表单描述** `FormSpec` —— 交互块(`kind: 'form'`)的 schema 就是它。
|
|
4
|
+
*
|
|
5
|
+
* 为什么要有:此前同一个 `present_form`,claude 路发的是 fields 数组 DSL、openai 路发的是
|
|
6
|
+
* JSON Schema,于是每个产品要写**两个**表单渲染器;更糟的是生图模板
|
|
7
|
+
* (`IMAGE_FORM_SPEC`)被复制在引擎和 console 两处,靠注释提醒手工同步——再接两个平台
|
|
8
|
+
* 就是四份。规范化成一种语言之后,产品只写一个渲染器,且**完全不需要认识任何模板名**:
|
|
9
|
+
* 展开发生在引擎侧,事件里永远是完整字段表。
|
|
10
|
+
*
|
|
11
|
+
* 选 fields DSL 而不是 JSON Schema:它能表达 slider / multiselect / image-ref / 分组 /
|
|
12
|
+
* 折叠高级项 / 条件显隐,JSON Schema 表达这些是有损的。
|
|
13
|
+
*
|
|
14
|
+
* 零依赖规则见 `./types.ts` 头注释。
|
|
15
|
+
* @layer contract
|
|
16
|
+
* @boundedContext chat
|
|
17
|
+
*/
|
|
18
|
+
export type FormFieldType = 'text' | 'textarea' | 'number' | 'slider' | 'select' | 'radio' | 'multiselect' | 'checkbox' | 'toggle' | 'color' | 'image-ref' | 'file';
|
|
19
|
+
export interface FormFieldSpec {
|
|
20
|
+
/** 回流 JSON 的键。 */
|
|
21
|
+
id: string;
|
|
22
|
+
label: string;
|
|
23
|
+
/** 一次定死:渲染控件 + 返回值类型 + 校验。 */
|
|
24
|
+
type: FormFieldType;
|
|
25
|
+
default?: unknown;
|
|
26
|
+
required?: boolean;
|
|
27
|
+
/** 字段下方灰字说明。 */
|
|
28
|
+
hint?: string;
|
|
29
|
+
/** 分组名(同 group 归一栏)。 */
|
|
30
|
+
group?: string;
|
|
31
|
+
/** true = 默认折叠进「高级」。 */
|
|
32
|
+
advanced?: boolean;
|
|
33
|
+
options?: {
|
|
34
|
+
value: string;
|
|
35
|
+
label: string;
|
|
36
|
+
}[];
|
|
37
|
+
min?: number;
|
|
38
|
+
max?: number;
|
|
39
|
+
step?: number;
|
|
40
|
+
placeholder?: string;
|
|
41
|
+
/** file / image-ref:如 `image/*`。 */
|
|
42
|
+
accept?: string;
|
|
43
|
+
/** 条件显隐。 */
|
|
44
|
+
dependsOn?: {
|
|
45
|
+
field: string;
|
|
46
|
+
equals: unknown;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export interface FormSpec {
|
|
50
|
+
title: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
submitLabel?: string;
|
|
53
|
+
skipLabel?: string;
|
|
54
|
+
fields: FormFieldSpec[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 答案怎么送回去。**两条后端路径的往返语义本身不同**,与其让客户端去猜"这是哪个后端",
|
|
58
|
+
* 不如在块上显式说清楚:
|
|
59
|
+
* - `message` —— 作为一条**新的用户消息**发回(claude/MCP 路:工具立即返回,回合不挂起);
|
|
60
|
+
* - `endpoint` —— `POST /sessions/:id/interactions/:interactionId`(openai/broker 路:
|
|
61
|
+
* run 真的挂起,提交后恢复)。
|
|
62
|
+
*/
|
|
63
|
+
export type InteractionRespond = 'message' | 'endpoint';
|
|
64
|
+
/** 运行时判别:交互块的 schema 是不是规范 FormSpec(而非旧的 JSON Schema)。 */
|
|
65
|
+
export declare function isFormSpec(schema: unknown): schema is FormSpec;
|
|
66
|
+
//# sourceMappingURL=form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/chat-protocol/form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,aAAa,GACb,UAAU,GACV,QAAQ,GACR,OAAO,GACP,WAAW,GACX,MAAM,CAAC;AAEX,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY;IACZ,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;CAChD;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,UAAU,CAAC;AAExD,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,QAAQ,CAI9D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module chat-protocol/form
|
|
3
|
+
* @description **规范表单描述** `FormSpec` —— 交互块(`kind: 'form'`)的 schema 就是它。
|
|
4
|
+
*
|
|
5
|
+
* 为什么要有:此前同一个 `present_form`,claude 路发的是 fields 数组 DSL、openai 路发的是
|
|
6
|
+
* JSON Schema,于是每个产品要写**两个**表单渲染器;更糟的是生图模板
|
|
7
|
+
* (`IMAGE_FORM_SPEC`)被复制在引擎和 console 两处,靠注释提醒手工同步——再接两个平台
|
|
8
|
+
* 就是四份。规范化成一种语言之后,产品只写一个渲染器,且**完全不需要认识任何模板名**:
|
|
9
|
+
* 展开发生在引擎侧,事件里永远是完整字段表。
|
|
10
|
+
*
|
|
11
|
+
* 选 fields DSL 而不是 JSON Schema:它能表达 slider / multiselect / image-ref / 分组 /
|
|
12
|
+
* 折叠高级项 / 条件显隐,JSON Schema 表达这些是有损的。
|
|
13
|
+
*
|
|
14
|
+
* 零依赖规则见 `./types.ts` 头注释。
|
|
15
|
+
* @layer contract
|
|
16
|
+
* @boundedContext chat
|
|
17
|
+
*/
|
|
18
|
+
/** 运行时判别:交互块的 schema 是不是规范 FormSpec(而非旧的 JSON Schema)。 */
|
|
19
|
+
export function isFormSpec(schema) {
|
|
20
|
+
if (!schema || typeof schema !== 'object')
|
|
21
|
+
return false;
|
|
22
|
+
const s = schema;
|
|
23
|
+
return typeof s.title === 'string' && Array.isArray(s.fields);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/chat-protocol/form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA0DH,0DAA0D;AAC1D,MAAM,UAAU,UAAU,CAAC,MAAe;IACxC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,CAAC,GAAG,MAA+C,CAAC;IAC1D,OAAO,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module chat-protocol
|
|
3
|
+
* @description 对话流协议 + 共享状态机的**唯一入口**。三个前端都从这里进。
|
|
4
|
+
*
|
|
5
|
+
* 🔴 零依赖叶子模块:本目录不许 import 目录外任何东西(含 node 内置与 npm 包)。
|
|
6
|
+
* 规则由 `chat-protocol.deps.test.ts` 卡死。将来抽成独立包 `@coralai/chat-protocol`
|
|
7
|
+
* 时只是移文件 + 加一个 package.json,代码零改。
|
|
8
|
+
*
|
|
9
|
+
* @layer contract
|
|
10
|
+
* @boundedContext chat
|
|
11
|
+
*/
|
|
12
|
+
export { CHAT_PROTOCOL_VERSION, WIRE_EVENT_NAMES, fromWireEvent } from './events.js';
|
|
13
|
+
export type { ChatStreamEvent } from './events.js';
|
|
14
|
+
export { OPTIMISTIC_ID_PREFIX, initialChatStreamState } from './types.js';
|
|
15
|
+
export type { ChatBlock, ChatMessage, ChatStreamState, PendingTurn } from './types.js';
|
|
16
|
+
export { commitTurn, reduceChatEvent } from './reduce.js';
|
|
17
|
+
export { isFormSpec } from './form.js';
|
|
18
|
+
export type { FormFieldSpec, FormFieldType, FormSpec, InteractionRespond } from './form.js';
|
|
19
|
+
export { advanceTypewriter, isDrained, renderBlocks } from './typewriter.js';
|
|
20
|
+
export type { TypewriterProgress } from './typewriter.js';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat-protocol/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrF,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAC1E,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC5F,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC7E,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module chat-protocol
|
|
3
|
+
* @description 对话流协议 + 共享状态机的**唯一入口**。三个前端都从这里进。
|
|
4
|
+
*
|
|
5
|
+
* 🔴 零依赖叶子模块:本目录不许 import 目录外任何东西(含 node 内置与 npm 包)。
|
|
6
|
+
* 规则由 `chat-protocol.deps.test.ts` 卡死。将来抽成独立包 `@coralai/chat-protocol`
|
|
7
|
+
* 时只是移文件 + 加一个 package.json,代码零改。
|
|
8
|
+
*
|
|
9
|
+
* @layer contract
|
|
10
|
+
* @boundedContext chat
|
|
11
|
+
*/
|
|
12
|
+
export { CHAT_PROTOCOL_VERSION, WIRE_EVENT_NAMES, fromWireEvent } from './events.js';
|
|
13
|
+
export { OPTIMISTIC_ID_PREFIX, initialChatStreamState } from './types.js';
|
|
14
|
+
export { commitTurn, reduceChatEvent } from './reduce.js';
|
|
15
|
+
export { isFormSpec } from './form.js';
|
|
16
|
+
export { advanceTypewriter, isDrained, renderBlocks } from './typewriter.js';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat-protocol/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAErF,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAE1E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module chat-protocol/reduce
|
|
3
|
+
* @description **共享对话状态机**——三个前端(sps-console / coral-platform / gameforge)
|
|
4
|
+
* 喂同一串事件必须得到深度相等的状态。
|
|
5
|
+
*
|
|
6
|
+
* 本文件是从 `console/src/shared/hooks/useChatStream.ts` **忠实抽出**的纯函数,不是重写:
|
|
7
|
+
* 那里每条分支背后都有历史修复(丢首个 chunk、切会话误提交、断线补偿快照…),
|
|
8
|
+
* 重写等于把踩过的坑再踩一遍。
|
|
9
|
+
*
|
|
10
|
+
* 不在本文件的东西(**故意的**):
|
|
11
|
+
* - 打字机(displayed/target):那是**展示**,见 `./typewriter.ts`,产品可选可不选;
|
|
12
|
+
* - 传输(EventSource/fetch)、缓存(react-query)、定时器:各产品自己的事。
|
|
13
|
+
*
|
|
14
|
+
* 零依赖规则见 `./types.ts` 头注释。
|
|
15
|
+
* @layer contract
|
|
16
|
+
* @boundedContext chat
|
|
17
|
+
*/
|
|
18
|
+
import type { ChatStreamEvent } from './events.js';
|
|
19
|
+
import type { ChatStreamState } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* 唯一的状态归并入口。纯函数:同样的 (state, event) 永远得到同样的结果。
|
|
22
|
+
*
|
|
23
|
+
* 事件不属于本会话 → 原样返回(切会话时别的会话的事件不该污染当前状态)。
|
|
24
|
+
*/
|
|
25
|
+
export declare function reduceChatEvent(state: ChatStreamState, event: ChatStreamEvent): ChatStreamState;
|
|
26
|
+
/**
|
|
27
|
+
* 把已收尾的回合提交进消息列表并清空在途态。
|
|
28
|
+
*
|
|
29
|
+
* 由**产品**决定时机:带打字机的等追齐后调(见 `./typewriter.ts` 的 `isDrained`),
|
|
30
|
+
* 不带的收到 `pending.done` 就调。未收尾时调用是安全的空操作。
|
|
31
|
+
*/
|
|
32
|
+
export declare function commitTurn(state: ChatStreamState): ChatStreamState;
|
|
33
|
+
//# sourceMappingURL=reduce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reduce.d.ts","sourceRoot":"","sources":["../../src/chat-protocol/reduce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAA0B,eAAe,EAAe,MAAM,YAAY,CAAC;AAuDvF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,GAAG,eAAe,CAwJ/F;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,CAQlE"}
|