@agentscope-ai/agentscope 0.0.2 → 0.0.4
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 +202 -0
- package/dist/agent/index.d.mts +10 -10
- package/dist/agent/index.d.ts +10 -10
- package/dist/agent/index.js +104 -93
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +104 -93
- package/dist/agent/index.mjs.map +1 -1
- package/dist/{base-BOx3UzOl.d.mts → base-1YVBgB4n.d.mts} +2 -2
- package/dist/{base-DYlBMCy_.d.mts → base-B_MQMHWr.d.mts} +3 -3
- package/dist/{base-Cwi4bjze.d.ts → base-BherSLRs.d.ts} +3 -3
- package/dist/{base-NX-knWOv.d.ts → base-CY4DMBH1.d.ts} +1 -1
- package/dist/{base-BoIps2RL.d.ts → base-ChWjyzPL.d.ts} +2 -2
- package/dist/{base-C7jwyH4Z.d.mts → base-ClilytRZ.d.mts} +1 -1
- package/dist/{block-VsnHrllL.d.mts → block-B72uPF1H.d.mts} +7 -5
- package/dist/{block-VsnHrllL.d.ts → block-B72uPF1H.d.ts} +7 -5
- package/dist/event/index.d.mts +105 -89
- package/dist/event/index.d.ts +105 -89
- package/dist/event/index.js +8 -8
- package/dist/event/index.js.map +1 -1
- package/dist/event/index.mjs +8 -8
- package/dist/event/index.mjs.map +1 -1
- package/dist/formatter/index.d.mts +4 -3
- package/dist/formatter/index.d.ts +4 -3
- package/dist/formatter/index.js +17 -17
- package/dist/formatter/index.js.map +1 -1
- package/dist/formatter/index.mjs +17 -17
- package/dist/formatter/index.mjs.map +1 -1
- package/dist/{index-BcatlwXQ.d.ts → index-BNfyKbQN.d.ts} +1 -1
- package/dist/{index-BTJDlKvQ.d.mts → index-UQCwdfet.d.mts} +1 -1
- package/dist/mcp/index.d.mts +2 -2
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/index.mjs +1 -1
- package/dist/mcp/index.mjs.map +1 -1
- package/dist/message/index.d.mts +3 -2
- package/dist/message/index.d.ts +3 -2
- package/dist/message/index.js +204 -5
- package/dist/message/index.js.map +1 -1
- package/dist/message/index.mjs +200 -5
- package/dist/message/index.mjs.map +1 -1
- package/dist/message-CPZd0NIc.d.ts +133 -0
- package/dist/message-DgpfAaHK.d.mts +133 -0
- package/dist/model/index.d.mts +6 -5
- package/dist/model/index.d.ts +6 -5
- package/dist/model/index.js +39 -28
- package/dist/model/index.js.map +1 -1
- package/dist/model/index.mjs +39 -28
- package/dist/model/index.mjs.map +1 -1
- package/dist/storage/index.d.mts +4 -3
- package/dist/storage/index.d.ts +4 -3
- package/dist/storage/index.js +4 -4
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +4 -4
- package/dist/storage/index.mjs.map +1 -1
- package/dist/tool/index.d.mts +4 -4
- package/dist/tool/index.d.ts +4 -4
- package/dist/{toolkit-CEpulFi0.d.ts → toolkit-DeOlul5Y.d.ts} +2 -2
- package/dist/{toolkit-CGEZSZPa.d.mts → toolkit-jwe7NmVJ.d.mts} +2 -2
- package/package.json +87 -87
- package/src/agent/agent.test.ts +104 -71
- package/src/agent/agent.ts +112 -104
- package/src/agent/test-compression.ts +1 -1
- package/src/event/index.ts +96 -98
- package/src/formatter/base.ts +3 -3
- package/src/formatter/dashscope-chat-formatter.test.ts +11 -8
- package/src/formatter/dashscope-chat-formatter.ts +3 -3
- package/src/formatter/openai-chat-formatter.test.ts +13 -5
- package/src/formatter/openai-chat-formatter.ts +6 -6
- package/src/mcp/base.ts +1 -1
- package/src/mcp/http.test.ts +2 -0
- package/src/mcp/stdio.test.ts +1 -0
- package/src/message/append-event.test.ts +783 -0
- package/src/message/block.ts +8 -4
- package/src/message/index.ts +12 -1
- package/src/message/message.test.ts +3 -1
- package/src/message/message.ts +310 -47
- package/src/model/dashscope-model.test.ts +4 -0
- package/src/model/dashscope-model.ts +3 -0
- package/src/model/deepseek-model.test.ts +2 -0
- package/src/model/deepseek-model.ts +3 -0
- package/src/model/ollama-model.test.ts +1 -0
- package/src/model/ollama-model.ts +2 -0
- package/src/model/openai-model.ts +3 -0
- package/src/permission/index.ts +13 -0
- package/src/storage/file-system.test.ts +4 -3
- package/src/storage/file-system.ts +4 -4
- package/src/tool/toolkit.test.ts +12 -0
- package/dist/message-CkN21KaY.d.mts +0 -99
- package/dist/message-CzLeTlua.d.ts +0 -99
package/src/message/block.ts
CHANGED
|
@@ -16,32 +16,36 @@ export interface HintBlock {
|
|
|
16
16
|
id: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export type ToolCallState = 'pending' | 'asking' | 'allowed' | 'submitted' | 'finished';
|
|
20
|
+
|
|
19
21
|
export interface ToolCallBlock {
|
|
20
22
|
type: 'tool_call';
|
|
21
23
|
name: string;
|
|
22
24
|
id: string;
|
|
23
25
|
input: string;
|
|
24
|
-
|
|
26
|
+
state: ToolCallState;
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
export type ToolResultState = 'success' | 'error' | 'interrupted' | 'denied' | 'running';
|
|
30
|
+
|
|
27
31
|
export interface ToolResultBlock {
|
|
28
32
|
type: 'tool_result';
|
|
29
33
|
id: string;
|
|
30
34
|
name: string;
|
|
31
35
|
output: string | (TextBlock | DataBlock)[];
|
|
32
|
-
state:
|
|
36
|
+
state: ToolResultState;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export interface Base64Source {
|
|
36
40
|
type: 'base64';
|
|
37
41
|
data: string;
|
|
38
|
-
|
|
42
|
+
media_type: string;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
export interface URLSource {
|
|
42
46
|
type: 'url';
|
|
43
47
|
url: string;
|
|
44
|
-
|
|
48
|
+
media_type: string;
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
export interface DataBlock {
|
package/src/message/index.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
Msg,
|
|
3
|
+
createMsg,
|
|
4
|
+
UserMsg,
|
|
5
|
+
AssistantMsg,
|
|
6
|
+
SystemMsg,
|
|
7
|
+
getTextContent,
|
|
8
|
+
getContentBlocks,
|
|
9
|
+
appendEvent,
|
|
10
|
+
} from './message';
|
|
2
11
|
export {
|
|
3
12
|
TextBlock,
|
|
4
13
|
ThinkingBlock,
|
|
5
14
|
ToolCallBlock,
|
|
15
|
+
ToolCallState,
|
|
6
16
|
ToolResultBlock,
|
|
17
|
+
ToolResultState,
|
|
7
18
|
ContentBlock,
|
|
8
19
|
Base64Source,
|
|
9
20
|
URLSource,
|
|
@@ -13,7 +13,7 @@ describe('Message', () => {
|
|
|
13
13
|
]);
|
|
14
14
|
expect(msg.role).toBe('user');
|
|
15
15
|
expect(msg.metadata).toEqual({});
|
|
16
|
-
expect(msg.
|
|
16
|
+
expect(msg.created_at).toBeDefined();
|
|
17
17
|
expect(msg.id).toBeDefined();
|
|
18
18
|
expect(getTextContent(msg)).toBe('Hello, world!');
|
|
19
19
|
|
|
@@ -38,6 +38,7 @@ describe('Message', () => {
|
|
|
38
38
|
id: '1',
|
|
39
39
|
name: 'test',
|
|
40
40
|
input: "{ query: 'What is AI?' }",
|
|
41
|
+
state: 'pending',
|
|
41
42
|
},
|
|
42
43
|
{
|
|
43
44
|
type: 'tool_result',
|
|
@@ -64,6 +65,7 @@ describe('Message', () => {
|
|
|
64
65
|
id: '1',
|
|
65
66
|
name: 'test',
|
|
66
67
|
input: "{ query: 'What is AI?' }",
|
|
68
|
+
state: 'pending',
|
|
67
69
|
},
|
|
68
70
|
]);
|
|
69
71
|
expect(getContentBlocks(msg, 'tool_result')).toStrictEqual([
|
package/src/message/message.ts
CHANGED
|
@@ -6,7 +6,10 @@ import {
|
|
|
6
6
|
ToolResultBlock,
|
|
7
7
|
ToolCallBlock,
|
|
8
8
|
DataBlock,
|
|
9
|
+
Base64Source,
|
|
10
|
+
URLSource,
|
|
9
11
|
} from './block';
|
|
12
|
+
import { AgentEvent, EventType } from '../event';
|
|
10
13
|
|
|
11
14
|
/** A chat message exchanged between agents or between an agent and a model. */
|
|
12
15
|
export interface Msg {
|
|
@@ -21,7 +24,9 @@ export interface Msg {
|
|
|
21
24
|
/** Arbitrary key-value metadata attached to the message. */
|
|
22
25
|
metadata: Record<string, JSONSerializableObject>;
|
|
23
26
|
/** ISO-8601 creation timestamp. */
|
|
24
|
-
|
|
27
|
+
created_at: string;
|
|
28
|
+
/** ISO-8601 finished timestamp. */
|
|
29
|
+
finished_at?: string | null;
|
|
25
30
|
/** Usage information for the message, such as token counts. */
|
|
26
31
|
usage?: {
|
|
27
32
|
inputTokens: number;
|
|
@@ -30,17 +35,18 @@ export interface Msg {
|
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
/**
|
|
33
|
-
* Create a new {@link Msg} object, filling in `id` and `
|
|
34
|
-
*
|
|
38
|
+
* Create a new {@link Msg} object, filling in `id` and `created_at` when omitted.
|
|
39
|
+
* A plain string `content` is automatically wrapped in a single {@link TextBlock}.
|
|
35
40
|
* @param root0
|
|
36
41
|
* @param root0.name
|
|
37
42
|
* @param root0.content
|
|
38
43
|
* @param root0.role
|
|
39
44
|
* @param root0.metadata
|
|
40
45
|
* @param root0.id
|
|
41
|
-
* @param root0.
|
|
46
|
+
* @param root0.created_at
|
|
47
|
+
* @param root0.finished_at
|
|
42
48
|
* @param root0.usage
|
|
43
|
-
* @returns A
|
|
49
|
+
* @returns A Msg object.
|
|
44
50
|
*/
|
|
45
51
|
export function createMsg({
|
|
46
52
|
name,
|
|
@@ -48,11 +54,99 @@ export function createMsg({
|
|
|
48
54
|
role,
|
|
49
55
|
metadata = {},
|
|
50
56
|
id = crypto.randomUUID(),
|
|
51
|
-
|
|
57
|
+
created_at = new Date().toISOString(),
|
|
58
|
+
finished_at,
|
|
59
|
+
usage,
|
|
60
|
+
}: Omit<Msg, 'id' | 'created_at' | 'metadata' | 'content'> &
|
|
61
|
+
Partial<Pick<Msg, 'id' | 'created_at' | 'metadata'>> & {
|
|
62
|
+
content: string | ContentBlock[];
|
|
63
|
+
}): Msg {
|
|
64
|
+
const contentBlocks: ContentBlock[] =
|
|
65
|
+
typeof content === 'string'
|
|
66
|
+
? [{ id: crypto.randomUUID(), type: 'text', text: content } as TextBlock]
|
|
67
|
+
: content;
|
|
68
|
+
return { id, name, role, content: contentBlocks, metadata, created_at, finished_at, usage };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create a user {@link Msg}.
|
|
73
|
+
* @param root0
|
|
74
|
+
* @param root0.name
|
|
75
|
+
* @param root0.content
|
|
76
|
+
* @param root0.metadata
|
|
77
|
+
* @param root0.id
|
|
78
|
+
* @param root0.created_at
|
|
79
|
+
* @returns A Msg object with role 'user'.
|
|
80
|
+
*/
|
|
81
|
+
export function UserMsg({
|
|
82
|
+
name,
|
|
83
|
+
content,
|
|
84
|
+
metadata = {},
|
|
85
|
+
id = crypto.randomUUID(),
|
|
86
|
+
created_at = new Date().toISOString(),
|
|
87
|
+
}: {
|
|
88
|
+
name: string;
|
|
89
|
+
content: string | ContentBlock[];
|
|
90
|
+
metadata?: Record<string, JSONSerializableObject>;
|
|
91
|
+
id?: string;
|
|
92
|
+
created_at?: string;
|
|
93
|
+
}): Msg {
|
|
94
|
+
return createMsg({ name, content, role: 'user', metadata, id, created_at });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Create an assistant {@link Msg}.
|
|
99
|
+
* @param root0
|
|
100
|
+
* @param root0.name
|
|
101
|
+
* @param root0.content
|
|
102
|
+
* @param root0.metadata
|
|
103
|
+
* @param root0.id
|
|
104
|
+
* @param root0.created_at
|
|
105
|
+
* @param root0.usage
|
|
106
|
+
* @returns A Msg object with role 'assistant'.
|
|
107
|
+
*/
|
|
108
|
+
export function AssistantMsg({
|
|
109
|
+
name,
|
|
110
|
+
content,
|
|
111
|
+
metadata = {},
|
|
112
|
+
id = crypto.randomUUID(),
|
|
113
|
+
created_at = new Date().toISOString(),
|
|
52
114
|
usage,
|
|
53
|
-
}:
|
|
54
|
-
|
|
55
|
-
|
|
115
|
+
}: {
|
|
116
|
+
name: string;
|
|
117
|
+
content: string | ContentBlock[];
|
|
118
|
+
metadata?: Record<string, JSONSerializableObject>;
|
|
119
|
+
id?: string;
|
|
120
|
+
created_at?: string;
|
|
121
|
+
usage?: Msg['usage'];
|
|
122
|
+
}): Msg {
|
|
123
|
+
return createMsg({ name, content, role: 'assistant', metadata, id, created_at, usage });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Create a system {@link Msg}.
|
|
128
|
+
* @param root0
|
|
129
|
+
* @param root0.name
|
|
130
|
+
* @param root0.content
|
|
131
|
+
* @param root0.metadata
|
|
132
|
+
* @param root0.id
|
|
133
|
+
* @param root0.created_at
|
|
134
|
+
* @returns A Msg object with role 'system'.
|
|
135
|
+
*/
|
|
136
|
+
export function SystemMsg({
|
|
137
|
+
name,
|
|
138
|
+
content,
|
|
139
|
+
metadata = {},
|
|
140
|
+
id = crypto.randomUUID(),
|
|
141
|
+
created_at = new Date().toISOString(),
|
|
142
|
+
}: {
|
|
143
|
+
name: string;
|
|
144
|
+
content: string | ContentBlock[];
|
|
145
|
+
metadata?: Record<string, JSONSerializableObject>;
|
|
146
|
+
id?: string;
|
|
147
|
+
created_at?: string;
|
|
148
|
+
}): Msg {
|
|
149
|
+
return createMsg({ name, content, role: 'system', metadata, id, created_at });
|
|
56
150
|
}
|
|
57
151
|
|
|
58
152
|
/**
|
|
@@ -67,9 +161,7 @@ export function createMsg({
|
|
|
67
161
|
*/
|
|
68
162
|
export function getTextContent(msg: Msg, separator: string = '\n'): string | null {
|
|
69
163
|
const textBlocks = msg.content.filter(block => block.type === 'text');
|
|
70
|
-
if (textBlocks.length === 0)
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
164
|
+
if (textBlocks.length === 0) return null;
|
|
73
165
|
return textBlocks.map(block => (block as TextBlock).text).join(separator);
|
|
74
166
|
}
|
|
75
167
|
|
|
@@ -82,45 +174,10 @@ export function getTextContent(msg: Msg, separator: string = '\n'): string | nul
|
|
|
82
174
|
* @returns An array of all {@link ContentBlock} objects.
|
|
83
175
|
*/
|
|
84
176
|
export function getContentBlocks(msg: Msg): ContentBlock[];
|
|
85
|
-
/**
|
|
86
|
-
* Return all {@link TextBlock} objects from a message.
|
|
87
|
-
*
|
|
88
|
-
* @param msg - The message to read.
|
|
89
|
-
* @param blockType - `'text'`
|
|
90
|
-
* @returns An array of {@link TextBlock} objects.
|
|
91
|
-
*/
|
|
92
177
|
export function getContentBlocks(msg: Msg, blockType: 'text'): TextBlock[];
|
|
93
|
-
/**
|
|
94
|
-
* Return all {@link ThinkingBlock} objects from a message.
|
|
95
|
-
*
|
|
96
|
-
* @param msg - The message to read.
|
|
97
|
-
* @param blockType - `'thinking'`
|
|
98
|
-
* @returns An array of {@link ThinkingBlock} objects.
|
|
99
|
-
*/
|
|
100
178
|
export function getContentBlocks(msg: Msg, blockType: 'thinking'): ThinkingBlock[];
|
|
101
|
-
/**
|
|
102
|
-
* Return all {@link DataBlock} objects from a message.
|
|
103
|
-
*
|
|
104
|
-
* @param msg - The message to read.
|
|
105
|
-
* @param blockType - `'video'`
|
|
106
|
-
* @returns An array of {@link DataBlock} objects.
|
|
107
|
-
*/
|
|
108
179
|
export function getContentBlocks(msg: Msg, blockType: 'data'): DataBlock[];
|
|
109
|
-
/**
|
|
110
|
-
* Return all {@link ToolCallBlock} objects from a message.
|
|
111
|
-
*
|
|
112
|
-
* @param msg - The message to read.
|
|
113
|
-
* @param blockType - `'tool_call'`
|
|
114
|
-
* @returns An array of {@link ToolCallBlock} objects.
|
|
115
|
-
*/
|
|
116
180
|
export function getContentBlocks(msg: Msg, blockType: 'tool_call'): ToolCallBlock[];
|
|
117
|
-
/**
|
|
118
|
-
* Return all {@link ToolResultBlock} objects from a message.
|
|
119
|
-
*
|
|
120
|
-
* @param msg - The message to read.
|
|
121
|
-
* @param blockType - `'tool_result'`
|
|
122
|
-
* @returns An array of {@link ToolResultBlock} objects.
|
|
123
|
-
*/
|
|
124
181
|
export function getContentBlocks(msg: Msg, blockType: 'tool_result'): ToolResultBlock[];
|
|
125
182
|
export function getContentBlocks(
|
|
126
183
|
msg: Msg,
|
|
@@ -129,3 +186,209 @@ export function getContentBlocks(
|
|
|
129
186
|
if (!blockType) return msg.content;
|
|
130
187
|
return msg.content.filter(block => block.type === blockType);
|
|
131
188
|
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Find a content block by type and id within a message.
|
|
192
|
+
* @param msg
|
|
193
|
+
* @param blockType
|
|
194
|
+
* @param blockId
|
|
195
|
+
* @returns The matching {@link ContentBlock}, or `undefined` if not found.
|
|
196
|
+
*/
|
|
197
|
+
function findBlock(msg: Msg, blockType: string, blockId: string): ContentBlock | undefined {
|
|
198
|
+
return msg.content.find(block => block.type === blockType && block.id === blockId);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Apply a streaming {@link AgentEvent} to a {@link Msg}, mutating it in place.
|
|
203
|
+
*
|
|
204
|
+
* Only `content` and `finished_at` are ever modified. Events whose
|
|
205
|
+
* `reply_id` does not match `msg.id` are skipped with a warning.
|
|
206
|
+
* @param msg
|
|
207
|
+
* @param event
|
|
208
|
+
* @returns The mutated {@link Msg} object.
|
|
209
|
+
*/
|
|
210
|
+
export function appendEvent(msg: Msg, event: AgentEvent): Msg {
|
|
211
|
+
if (!('reply_id' in event)) return msg;
|
|
212
|
+
if (event.reply_id !== msg.id) {
|
|
213
|
+
console.warn(
|
|
214
|
+
`Event reply_id "${event.reply_id}" does not match message id "${msg.id}", skipping.`
|
|
215
|
+
);
|
|
216
|
+
return msg;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
switch (event.type) {
|
|
220
|
+
case EventType.REPLY_END:
|
|
221
|
+
msg.finished_at = event.created_at;
|
|
222
|
+
break;
|
|
223
|
+
|
|
224
|
+
case EventType.TEXT_BLOCK_START:
|
|
225
|
+
msg.content.push({ type: 'text', id: event.block_id, text: '' });
|
|
226
|
+
break;
|
|
227
|
+
|
|
228
|
+
case EventType.TEXT_BLOCK_DELTA: {
|
|
229
|
+
const block = findBlock(msg, 'text', event.block_id);
|
|
230
|
+
if (!block) {
|
|
231
|
+
console.warn(`TextBlock "${event.block_id}" not found, skipping.`);
|
|
232
|
+
} else {
|
|
233
|
+
(block as TextBlock).text += event.delta;
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
case EventType.TEXT_BLOCK_END:
|
|
239
|
+
break;
|
|
240
|
+
|
|
241
|
+
case EventType.THINKING_BLOCK_START:
|
|
242
|
+
msg.content.push({ type: 'thinking', id: event.block_id, thinking: '' });
|
|
243
|
+
break;
|
|
244
|
+
|
|
245
|
+
case EventType.THINKING_BLOCK_DELTA: {
|
|
246
|
+
const block = findBlock(msg, 'thinking', event.block_id);
|
|
247
|
+
if (!block) {
|
|
248
|
+
console.warn(`ThinkingBlock "${event.block_id}" not found, skipping.`);
|
|
249
|
+
} else {
|
|
250
|
+
(block as ThinkingBlock).thinking += event.delta;
|
|
251
|
+
}
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
case EventType.THINKING_BLOCK_END:
|
|
256
|
+
break;
|
|
257
|
+
|
|
258
|
+
case EventType.DATA_BLOCK_START:
|
|
259
|
+
msg.content.push({
|
|
260
|
+
type: 'data',
|
|
261
|
+
id: event.block_id,
|
|
262
|
+
source: { type: 'base64', data: '', media_type: event.media_type },
|
|
263
|
+
});
|
|
264
|
+
break;
|
|
265
|
+
|
|
266
|
+
case EventType.DATA_BLOCK_DELTA: {
|
|
267
|
+
const block = findBlock(msg, 'data', event.block_id);
|
|
268
|
+
if (!block) {
|
|
269
|
+
console.warn(`DataBlock "${event.block_id}" not found, skipping.`);
|
|
270
|
+
} else {
|
|
271
|
+
((block as DataBlock).source as Base64Source).data += event.data;
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
case EventType.DATA_BLOCK_END:
|
|
277
|
+
break;
|
|
278
|
+
|
|
279
|
+
case EventType.TOOL_CALL_START:
|
|
280
|
+
msg.content.push({
|
|
281
|
+
type: 'tool_call',
|
|
282
|
+
id: event.tool_call_id,
|
|
283
|
+
name: event.tool_call_name,
|
|
284
|
+
input: '',
|
|
285
|
+
state: 'pending',
|
|
286
|
+
});
|
|
287
|
+
break;
|
|
288
|
+
|
|
289
|
+
case EventType.TOOL_CALL_DELTA: {
|
|
290
|
+
const block = findBlock(msg, 'tool_call', event.tool_call_id);
|
|
291
|
+
if (!block) {
|
|
292
|
+
console.warn(`ToolCallBlock "${event.tool_call_id}" not found, skipping.`);
|
|
293
|
+
} else {
|
|
294
|
+
(block as ToolCallBlock).input += event.delta;
|
|
295
|
+
}
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
case EventType.TOOL_CALL_END:
|
|
300
|
+
break;
|
|
301
|
+
|
|
302
|
+
case EventType.TOOL_RESULT_START:
|
|
303
|
+
msg.content.push({
|
|
304
|
+
type: 'tool_result',
|
|
305
|
+
id: event.tool_call_id,
|
|
306
|
+
name: event.tool_call_name,
|
|
307
|
+
output: [],
|
|
308
|
+
state: 'running',
|
|
309
|
+
});
|
|
310
|
+
break;
|
|
311
|
+
|
|
312
|
+
case EventType.TOOL_RESULT_TEXT_DELTA: {
|
|
313
|
+
const block = findBlock(msg, 'tool_result', event.tool_call_id);
|
|
314
|
+
if (!block) {
|
|
315
|
+
console.warn(`ToolResultBlock "${event.tool_call_id}" not found, skipping.`);
|
|
316
|
+
} else {
|
|
317
|
+
const trb = block as ToolResultBlock;
|
|
318
|
+
if (typeof trb.output === 'string') {
|
|
319
|
+
trb.output = [{ type: 'text', id: crypto.randomUUID(), text: trb.output }];
|
|
320
|
+
}
|
|
321
|
+
const last = trb.output[trb.output.length - 1];
|
|
322
|
+
if (!last || last.type !== 'text') {
|
|
323
|
+
trb.output.push({
|
|
324
|
+
type: 'text',
|
|
325
|
+
id: event.block_id ?? crypto.randomUUID(),
|
|
326
|
+
text: event.delta,
|
|
327
|
+
});
|
|
328
|
+
} else {
|
|
329
|
+
(last as TextBlock).text += event.delta;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
case EventType.TOOL_RESULT_DATA_DELTA: {
|
|
336
|
+
const block = findBlock(msg, 'tool_result', event.tool_call_id);
|
|
337
|
+
if (!block) {
|
|
338
|
+
console.warn(`ToolResultBlock "${event.tool_call_id}" not found, skipping.`);
|
|
339
|
+
} else {
|
|
340
|
+
const trb = block as ToolResultBlock;
|
|
341
|
+
if (typeof trb.output === 'string') {
|
|
342
|
+
trb.output = [{ type: 'text', id: crypto.randomUUID(), text: trb.output }];
|
|
343
|
+
}
|
|
344
|
+
const source: Base64Source | URLSource =
|
|
345
|
+
event.data != null
|
|
346
|
+
? { type: 'base64', data: event.data, media_type: event.media_type }
|
|
347
|
+
: { type: 'url', url: event.url!, media_type: event.media_type };
|
|
348
|
+
trb.output.push({ type: 'data', id: event.block_id, source });
|
|
349
|
+
}
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
case EventType.TOOL_RESULT_END: {
|
|
354
|
+
const block = findBlock(msg, 'tool_result', event.tool_call_id);
|
|
355
|
+
if (!block) {
|
|
356
|
+
console.warn(`ToolResultBlock "${event.tool_call_id}" not found, skipping.`);
|
|
357
|
+
} else {
|
|
358
|
+
(block as ToolResultBlock).state = event.state;
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
case EventType.REQUIRE_USER_CONFIRM:
|
|
364
|
+
for (const tc of event.tool_calls) {
|
|
365
|
+
const b = findBlock(msg, 'tool_call', tc.id);
|
|
366
|
+
if (b) (b as ToolCallBlock).state = 'asking';
|
|
367
|
+
}
|
|
368
|
+
break;
|
|
369
|
+
|
|
370
|
+
case EventType.USER_CONFIRM_RESULT:
|
|
371
|
+
for (const result of event.confirm_results) {
|
|
372
|
+
const b = findBlock(msg, 'tool_call', result.tool_call.id);
|
|
373
|
+
if (b) {
|
|
374
|
+
(b as ToolCallBlock).state = result.confirmed ? 'allowed' : 'finished';
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
break;
|
|
378
|
+
|
|
379
|
+
case EventType.REQUIRE_EXTERNAL_EXECUTION:
|
|
380
|
+
for (const tc of event.tool_calls) {
|
|
381
|
+
const b = findBlock(msg, 'tool_call', tc.id);
|
|
382
|
+
if (b) (b as ToolCallBlock).state = 'submitted';
|
|
383
|
+
}
|
|
384
|
+
break;
|
|
385
|
+
|
|
386
|
+
case EventType.EXTERNAL_EXECUTION_RESULT:
|
|
387
|
+
for (const result of event.execution_results) {
|
|
388
|
+
msg.content.push(result);
|
|
389
|
+
}
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return msg;
|
|
394
|
+
}
|
|
@@ -122,6 +122,7 @@ describe('DashScopeChatModel', () => {
|
|
|
122
122
|
name: 'get_current_weather',
|
|
123
123
|
id: 'call-123',
|
|
124
124
|
input: '{"location"',
|
|
125
|
+
state: 'pending',
|
|
125
126
|
});
|
|
126
127
|
|
|
127
128
|
// Chunk 4: Tool call with second part of arguments (delta)
|
|
@@ -131,6 +132,7 @@ describe('DashScopeChatModel', () => {
|
|
|
131
132
|
name: 'get_current_weather',
|
|
132
133
|
id: 'call-123',
|
|
133
134
|
input: ':"Beijing"}',
|
|
135
|
+
state: 'pending',
|
|
134
136
|
});
|
|
135
137
|
|
|
136
138
|
// Chunk 5: Empty content with usage info
|
|
@@ -158,6 +160,7 @@ describe('DashScopeChatModel', () => {
|
|
|
158
160
|
name: 'get_current_weather',
|
|
159
161
|
id: 'call-123',
|
|
160
162
|
input: '{"location":"Beijing"}',
|
|
163
|
+
state: 'pending',
|
|
161
164
|
});
|
|
162
165
|
|
|
163
166
|
// Verify usage
|
|
@@ -266,6 +269,7 @@ describe('DashScopeChatModel', () => {
|
|
|
266
269
|
name: 'get_current_weather',
|
|
267
270
|
id: 'call-123',
|
|
268
271
|
input: '{"location":"Beijing"}',
|
|
272
|
+
state: 'pending',
|
|
269
273
|
});
|
|
270
274
|
|
|
271
275
|
// Verify usage
|
|
@@ -231,6 +231,7 @@ export class DashScopeChatModel extends ChatModelBase {
|
|
|
231
231
|
id: String(toolCall.id),
|
|
232
232
|
name: String(toolCall.function.name),
|
|
233
233
|
input: inputString,
|
|
234
|
+
state: 'pending',
|
|
234
235
|
});
|
|
235
236
|
}
|
|
236
237
|
});
|
|
@@ -354,6 +355,7 @@ export class DashScopeChatModel extends ChatModelBase {
|
|
|
354
355
|
id: meta.id,
|
|
355
356
|
name: meta.name,
|
|
356
357
|
input: deltaArgs,
|
|
358
|
+
state: 'pending',
|
|
357
359
|
});
|
|
358
360
|
}
|
|
359
361
|
});
|
|
@@ -387,6 +389,7 @@ export class DashScopeChatModel extends ChatModelBase {
|
|
|
387
389
|
id: meta.id,
|
|
388
390
|
name: meta.name,
|
|
389
391
|
input: accToolInputs.get(index) || '{}',
|
|
392
|
+
state: 'pending',
|
|
390
393
|
});
|
|
391
394
|
});
|
|
392
395
|
|
|
@@ -106,6 +106,7 @@ describe('DeepSeekChatModel', () => {
|
|
|
106
106
|
name: 'get_current_weather',
|
|
107
107
|
id: 'call-123',
|
|
108
108
|
input: '{"location":"Beijing"}',
|
|
109
|
+
state: 'pending',
|
|
109
110
|
});
|
|
110
111
|
|
|
111
112
|
// Verify usage
|
|
@@ -209,6 +210,7 @@ describe('DeepSeekChatModel', () => {
|
|
|
209
210
|
name: 'get_current_weather',
|
|
210
211
|
id: 'call-123',
|
|
211
212
|
input: '{"location":"Beijing"}',
|
|
213
|
+
state: 'pending',
|
|
212
214
|
});
|
|
213
215
|
|
|
214
216
|
// Verify usage
|
|
@@ -191,6 +191,7 @@ export class DeepSeekChatModel extends ChatModelBase {
|
|
|
191
191
|
id: String(toolCall.id),
|
|
192
192
|
name: String(toolCall.function.name),
|
|
193
193
|
input: inputString,
|
|
194
|
+
state: 'pending',
|
|
194
195
|
});
|
|
195
196
|
}
|
|
196
197
|
});
|
|
@@ -314,6 +315,7 @@ export class DeepSeekChatModel extends ChatModelBase {
|
|
|
314
315
|
id: meta.id,
|
|
315
316
|
name: meta.name,
|
|
316
317
|
input: deltaArgs,
|
|
318
|
+
state: 'pending',
|
|
317
319
|
});
|
|
318
320
|
}
|
|
319
321
|
});
|
|
@@ -347,6 +349,7 @@ export class DeepSeekChatModel extends ChatModelBase {
|
|
|
347
349
|
id: meta.id,
|
|
348
350
|
name: meta.name,
|
|
349
351
|
input: accToolInputs.get(index) || '{}',
|
|
352
|
+
state: 'pending',
|
|
350
353
|
});
|
|
351
354
|
});
|
|
352
355
|
|
|
@@ -212,6 +212,7 @@ export class OllamaChatModel extends ChatModelBase {
|
|
|
212
212
|
id: toolId,
|
|
213
213
|
name: func.name,
|
|
214
214
|
input: JSON.stringify(func.arguments),
|
|
215
|
+
state: 'pending' as const,
|
|
215
216
|
};
|
|
216
217
|
|
|
217
218
|
toolCalls.set(toolId, toolCallBlock);
|
|
@@ -284,6 +285,7 @@ export class OllamaChatModel extends ChatModelBase {
|
|
|
284
285
|
id: `${idx}_${toolCall.function.name}`,
|
|
285
286
|
name: toolCall.function.name,
|
|
286
287
|
input: JSON.stringify(toolCall.function.arguments),
|
|
288
|
+
state: 'pending',
|
|
287
289
|
});
|
|
288
290
|
}
|
|
289
291
|
}
|
|
@@ -117,6 +117,7 @@ export class OpenAIChatModel extends ChatModelBase {
|
|
|
117
117
|
id: toolCall.id,
|
|
118
118
|
name: toolCall.function.name,
|
|
119
119
|
input: toolCall.function.arguments,
|
|
120
|
+
state: 'pending',
|
|
120
121
|
});
|
|
121
122
|
}
|
|
122
123
|
});
|
|
@@ -238,6 +239,7 @@ export class OpenAIChatModel extends ChatModelBase {
|
|
|
238
239
|
id: meta.id,
|
|
239
240
|
name: meta.name,
|
|
240
241
|
input: deltaArgs,
|
|
242
|
+
state: 'pending',
|
|
241
243
|
});
|
|
242
244
|
}
|
|
243
245
|
});
|
|
@@ -276,6 +278,7 @@ export class OpenAIChatModel extends ChatModelBase {
|
|
|
276
278
|
id: meta.id,
|
|
277
279
|
name: meta.name,
|
|
278
280
|
input: accToolInputs.get(index) || '{}',
|
|
281
|
+
state: 'pending',
|
|
279
282
|
});
|
|
280
283
|
});
|
|
281
284
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export enum PermissionBehavior {
|
|
2
|
+
ALLOW = 'allow',
|
|
3
|
+
DENY = 'deny',
|
|
4
|
+
ASK = 'ask',
|
|
5
|
+
PASSTHROUGH = 'passthrough',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface PermissionRule {
|
|
9
|
+
tool_name: string;
|
|
10
|
+
rule_content: string | null;
|
|
11
|
+
behavior: PermissionBehavior;
|
|
12
|
+
source: string;
|
|
13
|
+
}
|