@aix-chat/core 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.
Files changed (41) hide show
  1. package/dist/bridge/ChatBridge.d.ts +111 -0
  2. package/dist/bridge/ChatBridge.js +273 -0
  3. package/dist/bridge/index.d.ts +16 -0
  4. package/dist/bridge/index.js +25 -0
  5. package/dist/domain/block.d.ts +7 -0
  6. package/dist/domain/block.js +1 -0
  7. package/dist/domain/chat.d.ts +77 -0
  8. package/dist/domain/chat.js +265 -0
  9. package/dist/domain/conversation.d.ts +17 -0
  10. package/dist/domain/conversation.js +1 -0
  11. package/dist/domain/index.d.ts +7 -0
  12. package/dist/domain/index.js +2 -0
  13. package/dist/domain/message.d.ts +38 -0
  14. package/dist/domain/message.js +1 -0
  15. package/dist/domain/status.d.ts +10 -0
  16. package/dist/domain/status.js +30 -0
  17. package/dist/index.d.ts +18 -0
  18. package/dist/index.js +31 -0
  19. package/dist/types/blocks.d.ts +78 -0
  20. package/dist/types/blocks.js +1 -0
  21. package/dist/types/context.d.ts +22 -0
  22. package/dist/types/context.js +1 -0
  23. package/dist/types/index.d.ts +6 -0
  24. package/dist/types/index.js +6 -0
  25. package/dist/types/interaction.d.ts +46 -0
  26. package/dist/types/interaction.js +1 -0
  27. package/dist/types/message.d.ts +39 -0
  28. package/dist/types/message.js +1 -0
  29. package/dist/types/openclaw-blocks.d.ts +77 -0
  30. package/dist/types/openclaw-blocks.js +1 -0
  31. package/dist/types/panel.d.ts +71 -0
  32. package/dist/types/panel.js +1 -0
  33. package/dist/types/protocol.d.ts +48 -0
  34. package/dist/types/protocol.js +1 -0
  35. package/dist/types/provider.d.ts +15 -0
  36. package/dist/types/provider.js +1 -0
  37. package/dist/utils/EventEmitter.d.ts +18 -0
  38. package/dist/utils/EventEmitter.js +65 -0
  39. package/dist/utils/InteractionBuffer.d.ts +17 -0
  40. package/dist/utils/InteractionBuffer.js +64 -0
  41. package/package.json +85 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * ChatBridge — 命令式聊天控制 API
3
+ *
4
+ * 纯 JS 实现,零 React 依赖。通过 handler 注册模式与 React 层解耦:
5
+ * - adapters 的 useChatBridge hook 注册 submit/abort/getMessages 等 handler
6
+ * - 外部代码(ReactRender sandbox、action 按钮、父页面)调用公共 API
7
+ */
8
+ import { EventEmitter } from '../utils/EventEmitter';
9
+ export { EventEmitter };
10
+ export interface ChatBridgeConfig {
11
+ /** 是否挂载到 window.aixBridge(默认 false) */
12
+ installGlobal?: boolean;
13
+ }
14
+ /**
15
+ * 输入框控制接口
16
+ * 与 ui 包的 ChatInputRef 结构兼容,但不依赖 ui 包
17
+ */
18
+ export interface BridgeInputRef {
19
+ focus(): void;
20
+ blur(): void;
21
+ clear(): void;
22
+ getValue(): string;
23
+ insert(text: string, position?: 'start' | 'end' | number): void;
24
+ }
25
+ export type BridgeHandler = (...args: any[]) => any;
26
+ export declare class ChatBridge {
27
+ private handlers;
28
+ private inputRef;
29
+ private config;
30
+ /** 存储 tabId 到 eventEmitter 的映射 */
31
+ private panelEmitters;
32
+ constructor(config?: ChatBridgeConfig);
33
+ /**
34
+ * 注册一个命令处理器
35
+ */
36
+ registerHandler(name: string, handler: BridgeHandler): void;
37
+ /**
38
+ * 注销一个命令处理器
39
+ */
40
+ unregisterHandler(name: string): void;
41
+ /**
42
+ * 发送消息(触发聊天 submit)
43
+ */
44
+ submit(content: string, extra?: Record<string, any>): any;
45
+ /**
46
+ * 发送消息(submit 的别名,与 Panel 代码保持兼容)
47
+ * 支持 isInject 参数标记为注入消息
48
+ */
49
+ sendMessage(content: string, extra?: Record<string, any>): any;
50
+ /**
51
+ * 中止当前请求
52
+ */
53
+ abort(): void;
54
+ /**
55
+ * 获取当前消息列表
56
+ */
57
+ getMessages(): any[];
58
+ /**
59
+ * 是否正在请求中
60
+ */
61
+ getIsRequesting(): boolean;
62
+ /**
63
+ * 设置输入框 ref(由 useChatBridge 调用)
64
+ */
65
+ setInputRef(ref: BridgeInputRef | null): void;
66
+ /**
67
+ * 获取输入框 ref(外部可调用 focus/clear/insert 等)
68
+ */
69
+ getInputRef(): BridgeInputRef | null;
70
+ /**
71
+ * 打开(或激活)副屏中的指定 tab。
72
+ * tab 不存在时新建,已存在时更新 payload 并切换到该 tab。
73
+ * 自动为每个 tab 创建一个 EventEmitter,供事件通信使用。
74
+ */
75
+ openPanelTab(tab: import('../types/panel').PanelTab): void;
76
+ /**
77
+ * 关闭副屏中的指定 tab。
78
+ * 同时清理存储的 eventEmitter(如果有)。
79
+ */
80
+ closePanelTab(id: string): void;
81
+ /**
82
+ * 展开副屏面板容器(不影响 tab 内容)。
83
+ */
84
+ openPanel(): void;
85
+ /**
86
+ * 收起副屏面板容器(tab 仍保留,只是不可见)。
87
+ */
88
+ closePanel(): void;
89
+ /**
90
+ * 强制关闭副屏面板并清空所有 tabs。
91
+ */
92
+ closePanelForce(): void;
93
+ /**
94
+ * 更新副屏中的指定 tab。
95
+ * 如果 tab 不存在,此方法无效果。
96
+ */
97
+ updatePanelTab(id: string, update: Partial<Omit<import('../types/panel').PanelTab, 'id'>>): void;
98
+ /**
99
+ * 向副屏中的指定 tab 发送事件。
100
+ * 事件由副屏组件订阅和消费,通过 EventEmitter 实现。
101
+ */
102
+ emitPanelEvent(id: string, event: import('../types/panel').PanelEvent): void;
103
+ /**
104
+ * 获取指定 tab 的 EventEmitter(供 SidePanelContent 注入到 payload)
105
+ */
106
+ getPanelEventEmitter(id: string): EventEmitter | undefined;
107
+ /**
108
+ * 销毁 bridge,清理所有 handler 和全局引用
109
+ */
110
+ destroy(): void;
111
+ }
@@ -0,0 +1,273 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
4
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
5
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
7
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
8
+ /**
9
+ * ChatBridge — 命令式聊天控制 API
10
+ *
11
+ * 纯 JS 实现,零 React 依赖。通过 handler 注册模式与 React 层解耦:
12
+ * - adapters 的 useChatBridge hook 注册 submit/abort/getMessages 等 handler
13
+ * - 外部代码(ReactRender sandbox、action 按钮、父页面)调用公共 API
14
+ */
15
+
16
+ import { EventEmitter } from "../utils/EventEmitter";
17
+
18
+ // 导出 EventEmitter,方便业务组件直接使用
19
+ export { EventEmitter };
20
+
21
+ // ======================== 类型定义 ========================
22
+
23
+ /**
24
+ * 输入框控制接口
25
+ * 与 ui 包的 ChatInputRef 结构兼容,但不依赖 ui 包
26
+ */
27
+
28
+ // ======================== ChatBridge ========================
29
+
30
+ export var ChatBridge = /*#__PURE__*/function () {
31
+ function ChatBridge(config) {
32
+ _classCallCheck(this, ChatBridge);
33
+ _defineProperty(this, "handlers", new Map());
34
+ _defineProperty(this, "inputRef", null);
35
+ _defineProperty(this, "config", void 0);
36
+ /** 存储 tabId 到 eventEmitter 的映射 */
37
+ _defineProperty(this, "panelEmitters", new Map());
38
+ this.config = config || {};
39
+ if (this.config.installGlobal && typeof window !== 'undefined') {
40
+ window.aixBridge = this;
41
+ }
42
+ }
43
+
44
+ // -------------------- Handler 注册(由 adapters 调用) --------------------
45
+
46
+ /**
47
+ * 注册一个命令处理器
48
+ */
49
+ _createClass(ChatBridge, [{
50
+ key: "registerHandler",
51
+ value: function registerHandler(name, handler) {
52
+ this.handlers.set(name, handler);
53
+ }
54
+
55
+ /**
56
+ * 注销一个命令处理器
57
+ */
58
+ }, {
59
+ key: "unregisterHandler",
60
+ value: function unregisterHandler(name) {
61
+ this.handlers.delete(name);
62
+ }
63
+
64
+ // -------------------- 公共 API(由外部代码调用) --------------------
65
+
66
+ /**
67
+ * 发送消息(触发聊天 submit)
68
+ */
69
+ }, {
70
+ key: "submit",
71
+ value: function submit(content, extra) {
72
+ var handler = this.handlers.get('submit');
73
+ if (!handler) {
74
+ console.warn('[ChatBridge] No "submit" handler registered. Ensure useChatBridge is mounted.');
75
+ return;
76
+ }
77
+ return handler(content, extra);
78
+ }
79
+
80
+ /**
81
+ * 发送消息(submit 的别名,与 Panel 代码保持兼容)
82
+ * 支持 isInject 参数标记为注入消息
83
+ */
84
+ }, {
85
+ key: "sendMessage",
86
+ value: function sendMessage(content, extra) {
87
+ return this.submit(content, extra);
88
+ }
89
+
90
+ /**
91
+ * 中止当前请求
92
+ */
93
+ }, {
94
+ key: "abort",
95
+ value: function abort() {
96
+ var _this$handlers$get;
97
+ (_this$handlers$get = this.handlers.get('abort')) === null || _this$handlers$get === void 0 || _this$handlers$get();
98
+ }
99
+
100
+ /**
101
+ * 获取当前消息列表
102
+ */
103
+ }, {
104
+ key: "getMessages",
105
+ value: function getMessages() {
106
+ var _this$handlers$get2, _this$handlers$get3;
107
+ return (_this$handlers$get2 = (_this$handlers$get3 = this.handlers.get('getMessages')) === null || _this$handlers$get3 === void 0 ? void 0 : _this$handlers$get3()) !== null && _this$handlers$get2 !== void 0 ? _this$handlers$get2 : [];
108
+ }
109
+
110
+ /**
111
+ * 是否正在请求中
112
+ */
113
+ }, {
114
+ key: "getIsRequesting",
115
+ value: function getIsRequesting() {
116
+ var _this$handlers$get4, _this$handlers$get5;
117
+ return (_this$handlers$get4 = (_this$handlers$get5 = this.handlers.get('getIsRequesting')) === null || _this$handlers$get5 === void 0 ? void 0 : _this$handlers$get5()) !== null && _this$handlers$get4 !== void 0 ? _this$handlers$get4 : false;
118
+ }
119
+
120
+ // -------------------- Input 控制 --------------------
121
+
122
+ /**
123
+ * 设置输入框 ref(由 useChatBridge 调用)
124
+ */
125
+ }, {
126
+ key: "setInputRef",
127
+ value: function setInputRef(ref) {
128
+ this.inputRef = ref;
129
+ }
130
+
131
+ /**
132
+ * 获取输入框 ref(外部可调用 focus/clear/insert 等)
133
+ */
134
+ }, {
135
+ key: "getInputRef",
136
+ value: function getInputRef() {
137
+ return this.inputRef;
138
+ }
139
+
140
+ // -------------------- Panel 控制 --------------------
141
+ // 与 ChatLayout.Panel 配合:Panel mount 时注册 handler,unmount 时注销。
142
+ // 业务卡片(任意位置)通过这组方法命令式唤起副屏。
143
+
144
+ /**
145
+ * 打开(或激活)副屏中的指定 tab。
146
+ * tab 不存在时新建,已存在时更新 payload 并切换到该 tab。
147
+ * 自动为每个 tab 创建一个 EventEmitter,供事件通信使用。
148
+ */
149
+ }, {
150
+ key: "openPanelTab",
151
+ value: function openPanelTab(tab) {
152
+ var handler = this.handlers.get('openPanelTab');
153
+ if (!handler) {
154
+ console.warn('[ChatBridge] No "openPanelTab" handler registered. Ensure ChatLayout.Panel is mounted.');
155
+ return;
156
+ }
157
+
158
+ // 自动为每个 tab 创建 EventEmitter(如果不存在)
159
+ if (!this.panelEmitters.has(tab.id)) {
160
+ this.panelEmitters.set(tab.id, new EventEmitter());
161
+ }
162
+ handler(tab);
163
+ }
164
+
165
+ /**
166
+ * 关闭副屏中的指定 tab。
167
+ * 同时清理存储的 eventEmitter(如果有)。
168
+ */
169
+ }, {
170
+ key: "closePanelTab",
171
+ value: function closePanelTab(id) {
172
+ var _this$handlers$get6;
173
+ // 清理存储的 eventEmitter
174
+ var emitter = this.panelEmitters.get(id);
175
+ if (emitter) {
176
+ emitter.removeAllListeners();
177
+ this.panelEmitters.delete(id);
178
+ }
179
+ (_this$handlers$get6 = this.handlers.get('closePanelTab')) === null || _this$handlers$get6 === void 0 || _this$handlers$get6(id);
180
+ }
181
+
182
+ /**
183
+ * 展开副屏面板容器(不影响 tab 内容)。
184
+ */
185
+ }, {
186
+ key: "openPanel",
187
+ value: function openPanel() {
188
+ var _this$handlers$get7;
189
+ (_this$handlers$get7 = this.handlers.get('openPanel')) === null || _this$handlers$get7 === void 0 || _this$handlers$get7();
190
+ }
191
+
192
+ /**
193
+ * 收起副屏面板容器(tab 仍保留,只是不可见)。
194
+ */
195
+ }, {
196
+ key: "closePanel",
197
+ value: function closePanel() {
198
+ var _this$handlers$get8;
199
+ (_this$handlers$get8 = this.handlers.get('closePanel')) === null || _this$handlers$get8 === void 0 || _this$handlers$get8();
200
+ }
201
+
202
+ /**
203
+ * 强制关闭副屏面板并清空所有 tabs。
204
+ */
205
+ }, {
206
+ key: "closePanelForce",
207
+ value: function closePanelForce() {
208
+ var _this$handlers$get9;
209
+ (_this$handlers$get9 = this.handlers.get('closePanelForce')) === null || _this$handlers$get9 === void 0 || _this$handlers$get9();
210
+ }
211
+
212
+ /**
213
+ * 更新副屏中的指定 tab。
214
+ * 如果 tab 不存在,此方法无效果。
215
+ */
216
+ }, {
217
+ key: "updatePanelTab",
218
+ value: function updatePanelTab(id, update) {
219
+ var handler = this.handlers.get('updatePanelTab');
220
+ if (!handler) {
221
+ console.warn('[ChatBridge] No "updatePanelTab" handler registered. Ensure ChatLayout.Panel is mounted.');
222
+ return;
223
+ }
224
+ handler(id, update);
225
+ }
226
+
227
+ /**
228
+ * 向副屏中的指定 tab 发送事件。
229
+ * 事件由副屏组件订阅和消费,通过 EventEmitter 实现。
230
+ */
231
+ }, {
232
+ key: "emitPanelEvent",
233
+ value: function emitPanelEvent(id, event) {
234
+ var emitter = this.panelEmitters.get(id);
235
+ if (!emitter) {
236
+ console.warn("[ChatBridge] No EventEmitter found for tab \"".concat(id, "\". Ensure openPanelTab was called."));
237
+ return;
238
+ }
239
+ emitter.emit(event.type, event.payload);
240
+ }
241
+
242
+ /**
243
+ * 获取指定 tab 的 EventEmitter(供 SidePanelContent 注入到 payload)
244
+ */
245
+ }, {
246
+ key: "getPanelEventEmitter",
247
+ value: function getPanelEventEmitter(id) {
248
+ return this.panelEmitters.get(id);
249
+ }
250
+
251
+ // -------------------- 生命周期 --------------------
252
+
253
+ /**
254
+ * 销毁 bridge,清理所有 handler 和全局引用
255
+ */
256
+ }, {
257
+ key: "destroy",
258
+ value: function destroy() {
259
+ this.handlers.clear();
260
+ this.inputRef = null;
261
+
262
+ // 清理所有 EventEmitter
263
+ this.panelEmitters.forEach(function (emitter) {
264
+ return emitter.removeAllListeners();
265
+ });
266
+ this.panelEmitters.clear();
267
+ if (this.config.installGlobal && typeof window !== 'undefined' && window.aixBridge === this) {
268
+ delete window.aixBridge;
269
+ }
270
+ }
271
+ }]);
272
+ return ChatBridge;
273
+ }();
@@ -0,0 +1,16 @@
1
+ import { ChatBridge, EventEmitter } from './ChatBridge';
2
+ export { ChatBridge, EventEmitter };
3
+ export type { ChatBridgeConfig, BridgeInputRef, BridgeHandler } from './ChatBridge';
4
+ type BridgeKey = string | number | symbol;
5
+ /**
6
+ * ChatBridge 全局注册表
7
+ * 类比 chatMessagesStoreHelper,支持多实例管理
8
+ */
9
+ export declare const chatBridgeHelper: {
10
+ _bridges: Map<BridgeKey, ChatBridge>;
11
+ get(key: BridgeKey): ChatBridge | undefined;
12
+ set(key: BridgeKey, bridge: ChatBridge): void;
13
+ delete(key: BridgeKey): void;
14
+ /** 获取第一个注册的 bridge(单实例场景的快捷方式) */
15
+ getDefault(): ChatBridge | undefined;
16
+ };
@@ -0,0 +1,25 @@
1
+ import { ChatBridge, EventEmitter } from "./ChatBridge";
2
+ export { ChatBridge, EventEmitter };
3
+
4
+ // ======================== 全局注册表 ========================
5
+
6
+ /**
7
+ * ChatBridge 全局注册表
8
+ * 类比 chatMessagesStoreHelper,支持多实例管理
9
+ */
10
+ export var chatBridgeHelper = {
11
+ _bridges: new Map(),
12
+ get: function get(key) {
13
+ return chatBridgeHelper._bridges.get(key);
14
+ },
15
+ set: function set(key, bridge) {
16
+ chatBridgeHelper._bridges.set(key, bridge);
17
+ },
18
+ delete: function _delete(key) {
19
+ chatBridgeHelper._bridges.delete(key);
20
+ },
21
+ /** 获取第一个注册的 bridge(单实例场景的快捷方式) */getDefault: function getDefault() {
22
+ var first = chatBridgeHelper._bridges.values().next();
23
+ return first.done ? undefined : first.value;
24
+ }
25
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Block — 协议无关的最小基类
3
+ * 所有 Parser 输出的 block 均实现此接口
4
+ */
5
+ export interface Block {
6
+ type: string;
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,77 @@
1
+ import type { ChatProvider } from '../types/provider';
2
+ import type { ChatMessage } from './message';
3
+ export interface ChatSnapshot {
4
+ messages: ChatMessage[];
5
+ isRequesting: boolean;
6
+ error?: Error;
7
+ /** 是否可以重试(最后一个 Turn 处于 error / aborted 状态) */
8
+ canRetry: boolean;
9
+ }
10
+ /**
11
+ * Chat — 核心交互实体
12
+ *
13
+ * 职责:
14
+ * - 接管 Provider 的 onMessage / onComplete / onError 回调
15
+ * - 维护消息列表与请求状态
16
+ * - 提供 subscribe / getSnapshot 供 React hooks 订阅
17
+ * - 支持 Turn 级重试(retry)
18
+ * - 通过 onComplete / onError 向外透传会话级事件
19
+ *
20
+ * 不负责:
21
+ * - WebSocket 连接管理(ConnectionStatus 由 hooks 层管理)
22
+ * - 历史分页加载
23
+ * - Provider 的创建与生命周期
24
+ */
25
+ export declare class Chat<TInput = any> {
26
+ readonly provider: ChatProvider<TInput>;
27
+ /** 会话完成后的外部回调(由 useSessions 等注入) */
28
+ onComplete?: (messages: ChatMessage[]) => void;
29
+ /** 会话出错后的外部回调 */
30
+ onError?: (error: Error) => void;
31
+ onMessage?: (message: ChatMessage) => void;
32
+ private _messages;
33
+ private _isRequesting;
34
+ private _error?;
35
+ private _lastInput?;
36
+ private _listeners;
37
+ constructor(provider: ChatProvider<TInput>);
38
+ private _wireCallbacks;
39
+ /**
40
+ * 发起请求
41
+ * 调用后 isRequesting = true,Provider 回调驱动后续状态转换
42
+ */
43
+ send(input: TInput, assistantMessageId?: string): void;
44
+ /** 中止当前请求 */
45
+ abort(): void;
46
+ /**
47
+ * Turn 级重试
48
+ *
49
+ * 找到最后一个 Turn,如果其 assistant message 处于 error / aborted 状态,
50
+ * 则删除该 assistant message,使用相同的 input 重新发送。
51
+ *
52
+ * Turn 从 messages 数组中派生,不额外存储。
53
+ */
54
+ retry(): void;
55
+ /** 是否可以重试(最后一个 Turn 有失败的 assistant message) */
56
+ canRetry(): boolean;
57
+ /** 手动添加一条消息(如用户消息、历史消息) */
58
+ addMessage(message: ChatMessage): void;
59
+ /** 批量设置消息列表(如加载历史、清空) */
60
+ setMessages(messages: ChatMessage[]): void;
61
+ getMessages(): ChatMessage[];
62
+ getIsRequesting(): boolean;
63
+ getSnapshot(): ChatSnapshot;
64
+ /**
65
+ * 订阅状态变更,返回取消订阅函数
66
+ * 适用于 useSyncExternalStore / useEffect 场景
67
+ */
68
+ subscribe(listener: () => void): () => void;
69
+ /** 清理所有订阅和 Provider 回调,防止内存泄漏 */
70
+ destroy(): void;
71
+ /**
72
+ * 从消息列表中派生最后一个 Turn
73
+ * Turn = 最后一条 user 消息 + 其后的 assistant 消息(若有)
74
+ */
75
+ private _getLastTurn;
76
+ private _notify;
77
+ }