wtfai 1.5.1 → 1.5.3
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/README.md +96 -24
- package/dist/client.d.ts +0 -5
- package/dist/session.d.ts +15 -4
- package/dist/session.js +75 -5
- package/dist/types.d.ts +3 -2
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -33,13 +33,7 @@ const client = new Wtfai({
|
|
|
33
33
|
// 2. 创建会话
|
|
34
34
|
const session = client.createSession('workflow-id')
|
|
35
35
|
|
|
36
|
-
// 3.
|
|
37
|
-
session.on('stateChange', (state) => {
|
|
38
|
-
console.log('消息列表:', state.messages)
|
|
39
|
-
console.log('是否执行中:', state.isExecuting)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
// 4. 发送消息
|
|
36
|
+
// 3. 发送消息
|
|
43
37
|
await session.send({ content: '你好' })
|
|
44
38
|
```
|
|
45
39
|
|
|
@@ -105,12 +99,33 @@ const session = client.createSession('workflow-id', {
|
|
|
105
99
|
|
|
106
100
|
##### `on(event, listener)`
|
|
107
101
|
|
|
108
|
-
|
|
102
|
+
监听事件。事件语义与后端 SSE 推送保持一致(见 `docs/sse-event-protocol.md`)。
|
|
103
|
+
|
|
104
|
+
**事件说明与常见用法**
|
|
105
|
+
|
|
106
|
+
- `start`:工作流开始执行。会返回后端确认的 `threadId`;`title` 仅在新会话时返回(默认为工作流名)。
|
|
107
|
+
- 常见用法:首次拿到 `threadId` 后持久化,便于恢复会话。
|
|
108
|
+
- `nodeStart`:某个节点开始执行(排除了 LangGraph 内置的 `__start__/__end__`)。
|
|
109
|
+
- 常见用法:在 UI 上标记「当前节点」,或显示步骤进度。
|
|
110
|
+
- `nodeEnd`:某个节点执行结束,可能包含 `variables` 和/或 `messages`。
|
|
111
|
+
- 常见用法:更新节点级结果或收集中间产物。
|
|
112
|
+
- 注意:后端当前只透传 billing 相关变量;`brain/loop` 节点的消息已在流式 token 中渲染,这里会省略以避免重复。
|
|
113
|
+
- `token`:LLM 流式 token。`isReasoning` 表示推理内容(例如 DeepSeek 的 reasoning_content)。
|
|
114
|
+
- 常见用法:实现打字机效果;区分显示「推理」与「最终输出」。
|
|
115
|
+
- `loading`:仅在 Loading 节点触发,`message` 为配置的提示语(纯字符串)。
|
|
116
|
+
- 常见用法:展示阶段性加载提示。
|
|
117
|
+
- `title`:异步生成的会话标题(仅新会话)。通常在 `start` 之后稍晚到达。
|
|
118
|
+
- 常见用法:更新会话列表标题/面包屑。
|
|
119
|
+
- `complete`:本次执行成功结束。
|
|
120
|
+
- 常见用法:停止输入框 loading、允许再次发送。
|
|
121
|
+
- `error`:执行出错时触发(错误时不会再触发 `complete`)。
|
|
122
|
+
- 常见用法:toast 提示、错误上报、兜底 UI。
|
|
109
123
|
|
|
110
124
|
```typescript
|
|
111
125
|
session.on('start', ({ threadId, title }) => {
|
|
112
|
-
//
|
|
113
|
-
// title
|
|
126
|
+
// 工作流开始执行,获取到后端确认的 threadId
|
|
127
|
+
// title 只有新会话才会有(默认为工作流名称)
|
|
128
|
+
// 建议持久化 threadId,便于恢复会话
|
|
114
129
|
})
|
|
115
130
|
|
|
116
131
|
session.on('nodeStart', ({ nodeId }) => {
|
|
@@ -119,14 +134,17 @@ session.on('nodeStart', ({ nodeId }) => {
|
|
|
119
134
|
|
|
120
135
|
session.on('nodeEnd', ({ nodeId, variables, messages }) => {
|
|
121
136
|
// 节点执行结束
|
|
137
|
+
// variables: 目前只包含 billing 相关变量
|
|
138
|
+
// messages: brain/loop 节点通常已在 token 中渲染,可能为空
|
|
122
139
|
})
|
|
123
140
|
|
|
124
141
|
session.on('token', ({ nodeId, content, isReasoning }) => {
|
|
125
142
|
// 收到流式 token(用于打字机效果)
|
|
143
|
+
// isReasoning 为 true 时表示推理内容
|
|
126
144
|
})
|
|
127
145
|
|
|
128
146
|
session.on('loading', ({ nodeId, message }) => {
|
|
129
|
-
//
|
|
147
|
+
// Loading 节点的提示语(纯字符串)
|
|
130
148
|
console.log('Loading:', message)
|
|
131
149
|
})
|
|
132
150
|
|
|
@@ -136,22 +154,22 @@ session.on('title', ({ title }) => {
|
|
|
136
154
|
})
|
|
137
155
|
|
|
138
156
|
session.on('complete', () => {
|
|
139
|
-
//
|
|
157
|
+
// 工作流执行完成(成功)
|
|
140
158
|
})
|
|
141
159
|
|
|
142
160
|
session.on('error', ({ message }) => {
|
|
143
161
|
// 发生错误
|
|
144
162
|
})
|
|
145
163
|
|
|
146
|
-
session.on('stateChange', (state) => {
|
|
147
|
-
// 状态变化(推荐使用此事件更新 UI)
|
|
148
|
-
// state.messages: SimpleMessage[]
|
|
149
|
-
// state.isExecuting: boolean
|
|
150
|
-
// state.threadId?: string
|
|
151
|
-
// state.currentNodeId?: string
|
|
152
|
-
})
|
|
153
164
|
```
|
|
154
165
|
|
|
166
|
+
**最佳实践(推荐组合)**
|
|
167
|
+
|
|
168
|
+
1. **打字机效果**:使用 `token` 拼接流式内容。
|
|
169
|
+
2. **消息列表**:优先由 `token` 推进 AI 回复;`nodeEnd` 仅用于补齐非 brain/loop 节点的消息。
|
|
170
|
+
3. **加载状态**:`loading` 展示阶段性提示,`complete/error` 关闭 loading 并解锁输入。
|
|
171
|
+
4. **会话管理**:在 `start` 保存 `threadId`,`title` 更新会话标题。
|
|
172
|
+
|
|
155
173
|
##### `off(event, listener)`
|
|
156
174
|
|
|
157
175
|
移除事件监听。
|
|
@@ -235,7 +253,16 @@ const session = client.createSession('workflow-id', {
|
|
|
235
253
|
threadId: 'existing-thread-id',
|
|
236
254
|
})
|
|
237
255
|
await session.restore()
|
|
238
|
-
//
|
|
256
|
+
// 会将历史消息写入 state,可通过 getState 获取
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
##### `updateSessionTitle(title: string)`
|
|
260
|
+
|
|
261
|
+
更新会话标题(手动修改)。
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
await session.updateSessionTitle('新的会话标题')
|
|
265
|
+
// 会更新服务端变量,并触发 title 事件
|
|
239
266
|
```
|
|
240
267
|
|
|
241
268
|
##### `getState()`
|
|
@@ -256,6 +283,18 @@ console.log(state.isExecuting)
|
|
|
256
283
|
session.abort()
|
|
257
284
|
```
|
|
258
285
|
|
|
286
|
+
##### `dispose()`
|
|
287
|
+
|
|
288
|
+
释放会话资源:移除所有事件监听并中止执行,同时清空会话内部状态。被释放的 session 不可再使用。
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
session.dispose()
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**说明**:
|
|
295
|
+
- `abort()` 仅用于中断当前执行(比如用户点击停止生成)
|
|
296
|
+
- `dispose()` 用于彻底清理会话(组件卸载、切换会话时),调用后不可再复用该 session
|
|
297
|
+
|
|
259
298
|
##### `setWorkflowVariables(values)`
|
|
260
299
|
|
|
261
300
|
更新服务端会话变量。
|
|
@@ -511,6 +550,7 @@ function ChatComponent({ workflowId }: { workflowId: string }) {
|
|
|
511
550
|
const [isExecuting, setIsExecuting] = useState(false)
|
|
512
551
|
const [input, setInput] = useState('')
|
|
513
552
|
const sessionRef = useRef<WorkflowSession | null>(null)
|
|
553
|
+
const streamingIndexRef = useRef<number | null>(null)
|
|
514
554
|
|
|
515
555
|
useEffect(() => {
|
|
516
556
|
return () => {
|
|
@@ -524,22 +564,54 @@ function ChatComponent({ workflowId }: { workflowId: string }) {
|
|
|
524
564
|
const session = client.createSession(workflowId)
|
|
525
565
|
sessionRef.current = session
|
|
526
566
|
|
|
527
|
-
session.on('
|
|
528
|
-
setMessages(
|
|
529
|
-
|
|
567
|
+
session.on('token', ({ content }) => {
|
|
568
|
+
setMessages((prev) => {
|
|
569
|
+
const next = [...prev]
|
|
570
|
+
if (streamingIndexRef.current === null) {
|
|
571
|
+
streamingIndexRef.current = next.length
|
|
572
|
+
next.push({
|
|
573
|
+
type: 'ai',
|
|
574
|
+
parts: [{ type: 'text', text: content }],
|
|
575
|
+
})
|
|
576
|
+
return next
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
const index = streamingIndexRef.current
|
|
580
|
+
const msg = next[index]
|
|
581
|
+
const firstPart = msg?.parts?.[0]
|
|
582
|
+
if (msg && firstPart?.type === 'text') {
|
|
583
|
+
const updatedParts = [...msg.parts]
|
|
584
|
+
updatedParts[0] = {
|
|
585
|
+
...firstPart,
|
|
586
|
+
text: firstPart.text + content,
|
|
587
|
+
}
|
|
588
|
+
next[index] = { ...msg, parts: updatedParts }
|
|
589
|
+
}
|
|
590
|
+
return next
|
|
591
|
+
})
|
|
592
|
+
})
|
|
593
|
+
|
|
594
|
+
session.on('complete', () => {
|
|
595
|
+
setIsExecuting(false)
|
|
596
|
+
streamingIndexRef.current = null
|
|
530
597
|
})
|
|
531
598
|
|
|
532
599
|
session.on('error', ({ message }) => {
|
|
533
600
|
alert(`错误: ${message}`)
|
|
601
|
+
setIsExecuting(false)
|
|
602
|
+
streamingIndexRef.current = null
|
|
534
603
|
})
|
|
535
604
|
|
|
536
605
|
try {
|
|
606
|
+
setIsExecuting(true)
|
|
537
607
|
await session.send({
|
|
538
608
|
parts: [{ type: 'text', text: input }]
|
|
539
609
|
})
|
|
540
610
|
setInput('')
|
|
541
611
|
} catch (error) {
|
|
542
612
|
console.error(error)
|
|
613
|
+
setIsExecuting(false)
|
|
614
|
+
streamingIndexRef.current = null
|
|
543
615
|
}
|
|
544
616
|
}
|
|
545
617
|
|
|
@@ -548,7 +620,7 @@ function ChatComponent({ workflowId }: { workflowId: string }) {
|
|
|
548
620
|
<div className="messages">
|
|
549
621
|
{messages.map((msg, i) => (
|
|
550
622
|
<div key={i} className={msg.type}>
|
|
551
|
-
{
|
|
623
|
+
{msg.parts.find((part) => part.type === 'text')?.text || '...'}
|
|
552
624
|
</div>
|
|
553
625
|
))}
|
|
554
626
|
{isExecuting && <div>思考中...</div>}
|
package/dist/client.d.ts
CHANGED
|
@@ -22,11 +22,6 @@ import { UploadService } from './upload';
|
|
|
22
22
|
* // 创建会话
|
|
23
23
|
* const session = client.createSession('workflow-id')
|
|
24
24
|
*
|
|
25
|
-
* // 监听状态变化
|
|
26
|
-
* session.on('stateChange', (state) => {
|
|
27
|
-
* console.log('Messages:', state.messages)
|
|
28
|
-
* })
|
|
29
|
-
*
|
|
30
25
|
* // 发送消息
|
|
31
26
|
* await session.send({ parts: [{ type: 'text', text: '你好' }] })
|
|
32
27
|
* ```
|
package/dist/session.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare class WorkflowSession {
|
|
|
13
13
|
private state;
|
|
14
14
|
private listeners;
|
|
15
15
|
private abortController?;
|
|
16
|
+
private disposed;
|
|
16
17
|
constructor(workflowId: string, baseUrl: string, uploadService: UploadService, headers?: Record<string, string>, options?: SessionOptions);
|
|
17
18
|
private iframeMethods;
|
|
18
19
|
/**
|
|
@@ -47,7 +48,7 @@ export declare class WorkflowSession {
|
|
|
47
48
|
*/
|
|
48
49
|
private emit;
|
|
49
50
|
/**
|
|
50
|
-
*
|
|
51
|
+
* 更新会话状态
|
|
51
52
|
*/
|
|
52
53
|
private updateState;
|
|
53
54
|
/**
|
|
@@ -58,15 +59,17 @@ export declare class WorkflowSession {
|
|
|
58
59
|
* 恢复历史会话
|
|
59
60
|
*/
|
|
60
61
|
restore(): Promise<void>;
|
|
61
|
-
/**
|
|
62
|
-
* 获取工作流变量
|
|
63
|
-
*/
|
|
64
62
|
getWorkflowVariables(): Promise<Record<string, any>>;
|
|
65
63
|
/**
|
|
66
64
|
* 更新会话状态(服务端变量)
|
|
67
65
|
* @param values 需要更新的变量键值对
|
|
68
66
|
*/
|
|
69
67
|
setWorkflowVariables(values: Record<string, unknown>): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* 更新会话标题
|
|
70
|
+
* @param title 新的标题
|
|
71
|
+
*/
|
|
72
|
+
updateSessionTitle(title: string): Promise<void>;
|
|
70
73
|
/**
|
|
71
74
|
* 执行指定的工作流(临时/嵌套执行)
|
|
72
75
|
* 不会影响当前会话的状态(messages 等)
|
|
@@ -98,4 +101,12 @@ export declare class WorkflowSession {
|
|
|
98
101
|
* 中止执行
|
|
99
102
|
*/
|
|
100
103
|
abort(): void;
|
|
104
|
+
/**
|
|
105
|
+
* 释放会话资源(移除监听并中止执行)
|
|
106
|
+
*/
|
|
107
|
+
dispose(): void;
|
|
108
|
+
/**
|
|
109
|
+
* 确保会话未被释放
|
|
110
|
+
*/
|
|
111
|
+
private assertNotDisposed;
|
|
101
112
|
}
|
package/dist/session.js
CHANGED
|
@@ -12,6 +12,7 @@ function _define_property(obj, key, value) {
|
|
|
12
12
|
}
|
|
13
13
|
class WorkflowSession {
|
|
14
14
|
registerIframeMethods(methods) {
|
|
15
|
+
this.assertNotDisposed();
|
|
15
16
|
this.iframeMethods = {
|
|
16
17
|
...this.iframeMethods,
|
|
17
18
|
...methods
|
|
@@ -19,9 +20,11 @@ class WorkflowSession {
|
|
|
19
20
|
return this;
|
|
20
21
|
}
|
|
21
22
|
getIframeMethods() {
|
|
23
|
+
this.assertNotDisposed();
|
|
22
24
|
return this.iframeMethods;
|
|
23
25
|
}
|
|
24
26
|
async uploadFileFromIframe(options) {
|
|
27
|
+
this.assertNotDisposed();
|
|
25
28
|
const { base64, filename, mimeType, resourceType = 'conversation' } = options;
|
|
26
29
|
const byteString = atob(base64);
|
|
27
30
|
const arrayBuffer = new ArrayBuffer(byteString.length);
|
|
@@ -47,16 +50,19 @@ class WorkflowSession {
|
|
|
47
50
|
});
|
|
48
51
|
}
|
|
49
52
|
on(event, listener) {
|
|
53
|
+
this.assertNotDisposed();
|
|
50
54
|
if (!this.listeners.has(event)) this.listeners.set(event, new Set());
|
|
51
55
|
this.listeners.get(event).add(listener);
|
|
52
56
|
return this;
|
|
53
57
|
}
|
|
54
58
|
off(event, listener) {
|
|
55
59
|
var _this_listeners_get;
|
|
60
|
+
this.assertNotDisposed();
|
|
56
61
|
null == (_this_listeners_get = this.listeners.get(event)) || _this_listeners_get.delete(listener);
|
|
57
62
|
return this;
|
|
58
63
|
}
|
|
59
64
|
emit(event, ...args) {
|
|
65
|
+
if (this.disposed) return;
|
|
60
66
|
const listeners = this.listeners.get(event);
|
|
61
67
|
if (listeners) Array.from(listeners).forEach((listener)=>{
|
|
62
68
|
listener(...args);
|
|
@@ -67,27 +73,29 @@ class WorkflowSession {
|
|
|
67
73
|
...this.state,
|
|
68
74
|
...updates
|
|
69
75
|
};
|
|
70
|
-
this.emit('stateChange', {
|
|
71
|
-
...this.state
|
|
72
|
-
});
|
|
73
76
|
}
|
|
74
77
|
getState() {
|
|
78
|
+
this.assertNotDisposed();
|
|
75
79
|
return {
|
|
76
80
|
...this.state
|
|
77
81
|
};
|
|
78
82
|
}
|
|
79
83
|
async restore() {
|
|
84
|
+
this.assertNotDisposed();
|
|
80
85
|
if (!this.state.threadId) throw new Error('无法恢复会话:未提供 threadId');
|
|
81
86
|
const response = await fetch(`${this.baseUrl}/workflows/${this.workflowId}/state?threadId=${this.state.threadId}`, {
|
|
82
87
|
headers: this.headers
|
|
83
88
|
});
|
|
84
89
|
if (!response.ok) throw new Error('获取工作流状态失败');
|
|
85
90
|
const data = await response.json();
|
|
91
|
+
const variables = data.variables || {};
|
|
86
92
|
this.updateState({
|
|
87
|
-
messages: data.messages
|
|
93
|
+
messages: data.messages,
|
|
94
|
+
title: variables.conversationTitle
|
|
88
95
|
});
|
|
89
96
|
}
|
|
90
97
|
async getWorkflowVariables() {
|
|
98
|
+
this.assertNotDisposed();
|
|
91
99
|
if (!this.state.threadId) throw new Error('No active session (missing threadId)');
|
|
92
100
|
const response = await fetch(`${this.baseUrl}/workflows/${this.workflowId}/state?threadId=${this.state.threadId}`, {
|
|
93
101
|
headers: this.headers
|
|
@@ -97,7 +105,8 @@ class WorkflowSession {
|
|
|
97
105
|
return data.variables || {};
|
|
98
106
|
}
|
|
99
107
|
async setWorkflowVariables(values) {
|
|
100
|
-
|
|
108
|
+
this.assertNotDisposed();
|
|
109
|
+
if (!this.state.threadId) throw new Error('No active session (missing valid threadId)');
|
|
101
110
|
const response = await fetch(`${this.baseUrl}/workflows/${this.workflowId}/variables`, {
|
|
102
111
|
method: 'POST',
|
|
103
112
|
headers: {
|
|
@@ -111,7 +120,43 @@ class WorkflowSession {
|
|
|
111
120
|
});
|
|
112
121
|
if (!response.ok) throw new Error('Failed to update state');
|
|
113
122
|
}
|
|
123
|
+
async updateSessionTitle(title) {
|
|
124
|
+
this.assertNotDisposed();
|
|
125
|
+
if (!this.state.threadId) throw new Error('No active session (missing valid threadId)');
|
|
126
|
+
const executionInput = {
|
|
127
|
+
messages: [],
|
|
128
|
+
variables: {
|
|
129
|
+
conversationTitle: title
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
return new Promise((resolve, reject)=>{
|
|
133
|
+
executeWorkflowSSE(`${this.baseUrl}/workflows/${this.workflowId}/execute`, {
|
|
134
|
+
input: executionInput,
|
|
135
|
+
threadId: this.state.threadId,
|
|
136
|
+
mode: 'title_update'
|
|
137
|
+
}, {
|
|
138
|
+
onTitle: (data)=>{
|
|
139
|
+
this.updateState({
|
|
140
|
+
title: data.ti
|
|
141
|
+
});
|
|
142
|
+
this.emit('title', {
|
|
143
|
+
title: data.ti
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
onComplete: ()=>{
|
|
147
|
+
this.updateState({
|
|
148
|
+
title
|
|
149
|
+
});
|
|
150
|
+
resolve();
|
|
151
|
+
},
|
|
152
|
+
onError: (err)=>{
|
|
153
|
+
reject(new Error(err.message));
|
|
154
|
+
}
|
|
155
|
+
}, this.headers).catch(reject);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
114
158
|
async executeWorkflow(workflowId, input) {
|
|
159
|
+
this.assertNotDisposed();
|
|
115
160
|
const { parts: inputParts, ...rest } = input;
|
|
116
161
|
const parts = [];
|
|
117
162
|
for (const part of inputParts)switch(part.type){
|
|
@@ -190,6 +235,7 @@ class WorkflowSession {
|
|
|
190
235
|
});
|
|
191
236
|
}
|
|
192
237
|
async send({ parts: inputParts, ...rest }) {
|
|
238
|
+
this.assertNotDisposed();
|
|
193
239
|
if (this.state.isExecuting) throw new Error('工作流正在执行中');
|
|
194
240
|
this.updateState({
|
|
195
241
|
isExecuting: true,
|
|
@@ -271,6 +317,9 @@ class WorkflowSession {
|
|
|
271
317
|
this.updateState({
|
|
272
318
|
threadId: data.t
|
|
273
319
|
});
|
|
320
|
+
if (data.ti) this.updateState({
|
|
321
|
+
title: data.ti
|
|
322
|
+
});
|
|
274
323
|
this.emit('start', {
|
|
275
324
|
threadId: data.t,
|
|
276
325
|
...data.ti && {
|
|
@@ -346,6 +395,9 @@ class WorkflowSession {
|
|
|
346
395
|
});
|
|
347
396
|
},
|
|
348
397
|
onTitle: (data)=>{
|
|
398
|
+
this.updateState({
|
|
399
|
+
title: data.ti
|
|
400
|
+
});
|
|
349
401
|
this.emit('title', {
|
|
350
402
|
title: data.ti
|
|
351
403
|
});
|
|
@@ -431,6 +483,7 @@ class WorkflowSession {
|
|
|
431
483
|
throw new Error('Document part must have either file or url');
|
|
432
484
|
}
|
|
433
485
|
abort() {
|
|
486
|
+
if (this.disposed) return;
|
|
434
487
|
if (this.abortController) {
|
|
435
488
|
this.abortController.abort();
|
|
436
489
|
this.updateState({
|
|
@@ -439,6 +492,21 @@ class WorkflowSession {
|
|
|
439
492
|
});
|
|
440
493
|
}
|
|
441
494
|
}
|
|
495
|
+
dispose() {
|
|
496
|
+
if (this.disposed) return;
|
|
497
|
+
this.disposed = true;
|
|
498
|
+
this.abort();
|
|
499
|
+
this.listeners.clear();
|
|
500
|
+
this.iframeMethods = {};
|
|
501
|
+
this.abortController = void 0;
|
|
502
|
+
this.state = {
|
|
503
|
+
messages: [],
|
|
504
|
+
isExecuting: false
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
assertNotDisposed() {
|
|
508
|
+
if (this.disposed) throw new Error('Session has been disposed');
|
|
509
|
+
}
|
|
442
510
|
constructor(workflowId, baseUrl, uploadService, headers = {}, options = {}){
|
|
443
511
|
_define_property(this, "workflowId", void 0);
|
|
444
512
|
_define_property(this, "baseUrl", void 0);
|
|
@@ -447,6 +515,7 @@ class WorkflowSession {
|
|
|
447
515
|
_define_property(this, "state", void 0);
|
|
448
516
|
_define_property(this, "listeners", void 0);
|
|
449
517
|
_define_property(this, "abortController", void 0);
|
|
518
|
+
_define_property(this, "disposed", void 0);
|
|
450
519
|
_define_property(this, "iframeMethods", void 0);
|
|
451
520
|
this.workflowId = workflowId;
|
|
452
521
|
this.baseUrl = baseUrl;
|
|
@@ -457,6 +526,7 @@ class WorkflowSession {
|
|
|
457
526
|
isExecuting: false
|
|
458
527
|
};
|
|
459
528
|
this.listeners = new Map();
|
|
529
|
+
this.disposed = false;
|
|
460
530
|
this.iframeMethods = {};
|
|
461
531
|
if (options.threadId) this.state.threadId = options.threadId;
|
|
462
532
|
else this.state.threadId = v7();
|
package/dist/types.d.ts
CHANGED
|
@@ -122,7 +122,7 @@ export interface UploadCredentials {
|
|
|
122
122
|
/**
|
|
123
123
|
* 会话事件类型
|
|
124
124
|
*/
|
|
125
|
-
export type SessionEventType = 'start' | 'nodeStart' | 'nodeEnd' | 'token' | 'loading' | 'complete' | 'error'
|
|
125
|
+
export type SessionEventType = 'start' | 'nodeStart' | 'nodeEnd' | 'token' | 'loading' | 'complete' | 'error';
|
|
126
126
|
/**
|
|
127
127
|
* 会话事件监听器类型映射
|
|
128
128
|
*/
|
|
@@ -155,7 +155,6 @@ export interface SessionEventListeners {
|
|
|
155
155
|
error: (error: {
|
|
156
156
|
message: string;
|
|
157
157
|
}) => void;
|
|
158
|
-
stateChange: (state: SessionState) => void;
|
|
159
158
|
}
|
|
160
159
|
/**
|
|
161
160
|
* 会话状态
|
|
@@ -169,6 +168,8 @@ export interface SessionState {
|
|
|
169
168
|
isExecuting: boolean;
|
|
170
169
|
/** 当前执行节点 ID */
|
|
171
170
|
currentNodeId?: string;
|
|
171
|
+
/** 会话标题 */
|
|
172
|
+
title?: string;
|
|
172
173
|
}
|
|
173
174
|
/**
|
|
174
175
|
* 工作流基本信息
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wtfai",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -16,23 +16,23 @@
|
|
|
16
16
|
"@eslint/js": "^9.39.2",
|
|
17
17
|
"@rsbuild/plugin-react": "^1.4.3",
|
|
18
18
|
"@rslib/core": "^0.19.3",
|
|
19
|
-
"@types/react": "^19.2.
|
|
19
|
+
"@types/react": "^19.2.10",
|
|
20
20
|
"eslint": "^9.39.2",
|
|
21
21
|
"eslint-config-prettier": "^10.1.8",
|
|
22
22
|
"eslint-plugin-prettier": "^5.5.5",
|
|
23
|
-
"globals": "^17.
|
|
23
|
+
"globals": "^17.2.0",
|
|
24
24
|
"prettier": "^3.8.1",
|
|
25
|
-
"react": "^19.2.
|
|
25
|
+
"react": "^19.2.4",
|
|
26
26
|
"typescript": "^5.9.3",
|
|
27
|
-
"typescript-eslint": "^8.
|
|
27
|
+
"typescript-eslint": "^8.54.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"react": ">=16.9.0",
|
|
31
31
|
"react-dom": ">=16.9.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ant-design/x": "^2.
|
|
35
|
-
"@ant-design/x-markdown": "^2.
|
|
34
|
+
"@ant-design/x": "^2.2.0",
|
|
35
|
+
"@ant-design/x-markdown": "^2.2.0",
|
|
36
36
|
"@microsoft/fetch-event-source": "^2.0.1",
|
|
37
37
|
"clsx": "^2.1.1",
|
|
38
38
|
"compressorjs": "^1.2.1",
|