@arki-moe/agent-ts 5.2.0 → 5.3.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/README.md +5 -4
- package/dist/adapter/openai.d.ts +2 -2
- package/dist/adapter/openai.js +48 -22
- package/dist/adapter/openrouter.d.ts +2 -2
- package/dist/adapter/openrouter.js +48 -22
- package/dist/adapter/selfhost_chat_completions.d.ts +2 -2
- package/dist/adapter/selfhost_chat_completions.js +48 -22
- package/dist/index.d.ts +7 -3
- package/dist/index.js +24 -6
- package/dist/types.d.ts +15 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,9 +33,10 @@ const agent = new Agent("openai", {
|
|
|
33
33
|
});
|
|
34
34
|
agent.registerTool(getTimeTool);
|
|
35
35
|
|
|
36
|
-
// run: Executes tool chain automatically, returns new messages, context is maintained automatically
|
|
37
|
-
const
|
|
38
|
-
console.log(
|
|
36
|
+
// run: Executes tool chain automatically, returns new messages and usage, context is maintained automatically
|
|
37
|
+
const result = await agent.run("What time is it?");
|
|
38
|
+
console.log(result.messages);
|
|
39
|
+
console.log(result.usage, result.usageSum);
|
|
39
40
|
|
|
40
41
|
// context is a public property that can be read directly
|
|
41
42
|
console.log(agent.context);
|
|
@@ -56,7 +57,7 @@ When `apiKey` is not provided in config, adapters read from the corresponding en
|
|
|
56
57
|
- `Agent(adapterName, config)` - Create Agent
|
|
57
58
|
- `agent.context` - Public property, complete conversation history
|
|
58
59
|
- `agent.registerTool(tool)` - Register tool
|
|
59
|
-
- `agent.run(message)` - Execute tool chain automatically, returns
|
|
60
|
+
- `agent.run(message)` - Execute tool chain automatically, returns `{ messages, usage, usageSum }`
|
|
60
61
|
|
|
61
62
|
### Config
|
|
62
63
|
|
package/dist/adapter/openai.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type Message, type Tool } from "../types";
|
|
2
|
-
export declare function openaiAdapter(config: Record<string, unknown>, context: Message[], tools: Tool[]): Promise<
|
|
1
|
+
import { type AdapterResult, type Message, type Tool } from "../types";
|
|
2
|
+
export declare function openaiAdapter(config: Record<string, unknown>, context: Message[], tools: Tool[]): Promise<AdapterResult>;
|
package/dist/adapter/openai.js
CHANGED
|
@@ -27,6 +27,18 @@ function toOpenAIMessages(context) {
|
|
|
27
27
|
return out;
|
|
28
28
|
}, []);
|
|
29
29
|
}
|
|
30
|
+
function toUsage(usage) {
|
|
31
|
+
if (!usage)
|
|
32
|
+
return undefined;
|
|
33
|
+
const promptTokens = usage.prompt_tokens;
|
|
34
|
+
const completionTokens = usage.completion_tokens;
|
|
35
|
+
const totalTokens = usage.total_tokens;
|
|
36
|
+
if (typeof promptTokens !== "number"
|
|
37
|
+
|| typeof completionTokens !== "number"
|
|
38
|
+
|| typeof totalTokens !== "number")
|
|
39
|
+
return undefined;
|
|
40
|
+
return { promptTokens, completionTokens, totalTokens };
|
|
41
|
+
}
|
|
30
42
|
async function openaiAdapter(config, context, tools) {
|
|
31
43
|
const baseUrl = config.baseUrl ?? "https://api.openai.com";
|
|
32
44
|
const apiKey = config.apiKey || process.env.OPENAI_API_KEY || "";
|
|
@@ -47,9 +59,10 @@ async function openaiAdapter(config, context, tools) {
|
|
|
47
59
|
tools: tools.length ? tools.map((t) => ({ type: "function", function: { name: t.name, description: t.description, parameters: t.parameters ?? {} } })) : undefined,
|
|
48
60
|
tool_choice: tools.length ? (toolChoice ?? "auto") : undefined,
|
|
49
61
|
stream: onStream ? true : undefined,
|
|
62
|
+
stream_options: onStream ? { include_usage: true } : undefined,
|
|
50
63
|
};
|
|
51
64
|
if (await check())
|
|
52
|
-
return [];
|
|
65
|
+
return { messages: [] };
|
|
53
66
|
const res = await fetch(`${baseUrl.replace(/\/$/, "")}/v1/chat/completions`, {
|
|
54
67
|
method: "POST",
|
|
55
68
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
@@ -71,6 +84,7 @@ async function openaiAdapter(config, context, tools) {
|
|
|
71
84
|
}
|
|
72
85
|
if (onStream) {
|
|
73
86
|
let content = "";
|
|
87
|
+
let usage;
|
|
74
88
|
const toolCalls = new Map();
|
|
75
89
|
const upsertToolCall = (tc) => {
|
|
76
90
|
const index = typeof tc?.index === "number" ? tc.index : toolCalls.size;
|
|
@@ -99,6 +113,11 @@ async function openaiAdapter(config, context, tools) {
|
|
|
99
113
|
catch {
|
|
100
114
|
throw new Error(`OpenAI API returned invalid JSON: ${dataLine.slice(0, 200)}`);
|
|
101
115
|
}
|
|
116
|
+
if (parsed?.usage) {
|
|
117
|
+
const nextUsage = toUsage(parsed.usage);
|
|
118
|
+
if (nextUsage)
|
|
119
|
+
usage = nextUsage;
|
|
120
|
+
}
|
|
102
121
|
const delta = parsed?.choices?.[0]?.delta;
|
|
103
122
|
if (!delta)
|
|
104
123
|
return;
|
|
@@ -114,22 +133,25 @@ async function openaiAdapter(config, context, tools) {
|
|
|
114
133
|
await check();
|
|
115
134
|
}, check);
|
|
116
135
|
if (toolCalls.size > 0) {
|
|
117
|
-
return
|
|
118
|
-
.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
136
|
+
return {
|
|
137
|
+
messages: [...toolCalls.entries()]
|
|
138
|
+
.sort((a, b) => a[0] - b[0])
|
|
139
|
+
.map(([index, tc]) => {
|
|
140
|
+
if (!tc.name)
|
|
141
|
+
throw new Error(`OpenAI streaming tool call missing function name at index ${index}`);
|
|
142
|
+
return {
|
|
143
|
+
role: types_1.Role.ToolCall,
|
|
144
|
+
toolName: tc.name,
|
|
145
|
+
callId: tc.id ?? `call_${index}`,
|
|
146
|
+
argsText: tc.args.length ? tc.args : "{}",
|
|
147
|
+
};
|
|
148
|
+
}),
|
|
149
|
+
usage,
|
|
150
|
+
};
|
|
129
151
|
}
|
|
130
152
|
if (!content)
|
|
131
|
-
return [];
|
|
132
|
-
return [{ role: types_1.Role.Ai, content, isPartial: isAborted() ? true : undefined }];
|
|
153
|
+
return { messages: [], usage };
|
|
154
|
+
return { messages: [{ role: types_1.Role.Ai, content, isPartial: isAborted() ? true : undefined }], usage };
|
|
133
155
|
}
|
|
134
156
|
const text = await res.text();
|
|
135
157
|
let data;
|
|
@@ -141,16 +163,20 @@ async function openaiAdapter(config, context, tools) {
|
|
|
141
163
|
}
|
|
142
164
|
if (data.error)
|
|
143
165
|
throw new Error(`OpenAI API error: ${data.error.message}`);
|
|
166
|
+
const usage = toUsage(data.usage);
|
|
144
167
|
const msg = data.choices?.[0]?.message;
|
|
145
168
|
if (!msg)
|
|
146
169
|
throw new Error("OpenAI API returned empty response");
|
|
147
170
|
if (msg.tool_calls?.length) {
|
|
148
|
-
return
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
171
|
+
return {
|
|
172
|
+
messages: msg.tool_calls.map((tc) => ({
|
|
173
|
+
role: types_1.Role.ToolCall,
|
|
174
|
+
toolName: tc.function.name,
|
|
175
|
+
callId: tc.id,
|
|
176
|
+
argsText: tc.function.arguments ?? "{}",
|
|
177
|
+
})),
|
|
178
|
+
usage,
|
|
179
|
+
};
|
|
154
180
|
}
|
|
155
|
-
return [{ role: types_1.Role.Ai, content: msg.content ?? "" }];
|
|
181
|
+
return { messages: [{ role: types_1.Role.Ai, content: msg.content ?? "" }], usage };
|
|
156
182
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type Message, type Tool } from "../types";
|
|
2
|
-
export declare function openrouterAdapter(config: Record<string, unknown>, context: Message[], tools: Tool[]): Promise<
|
|
1
|
+
import { type AdapterResult, type Message, type Tool } from "../types";
|
|
2
|
+
export declare function openrouterAdapter(config: Record<string, unknown>, context: Message[], tools: Tool[]): Promise<AdapterResult>;
|
|
@@ -27,6 +27,18 @@ function toOpenRouterMessages(context) {
|
|
|
27
27
|
return out;
|
|
28
28
|
}, []);
|
|
29
29
|
}
|
|
30
|
+
function toUsage(usage) {
|
|
31
|
+
if (!usage)
|
|
32
|
+
return undefined;
|
|
33
|
+
const promptTokens = usage.prompt_tokens;
|
|
34
|
+
const completionTokens = usage.completion_tokens;
|
|
35
|
+
const totalTokens = usage.total_tokens;
|
|
36
|
+
if (typeof promptTokens !== "number"
|
|
37
|
+
|| typeof completionTokens !== "number"
|
|
38
|
+
|| typeof totalTokens !== "number")
|
|
39
|
+
return undefined;
|
|
40
|
+
return { promptTokens, completionTokens, totalTokens };
|
|
41
|
+
}
|
|
30
42
|
async function openrouterAdapter(config, context, tools) {
|
|
31
43
|
const baseUrl = config.baseUrl ?? "https://openrouter.ai/api/v1";
|
|
32
44
|
const apiKey = config.apiKey || process.env.OPENROUTER_API_KEY || "";
|
|
@@ -49,6 +61,7 @@ async function openrouterAdapter(config, context, tools) {
|
|
|
49
61
|
tools: tools.length ? tools.map((t) => ({ type: "function", function: { name: t.name, description: t.description, parameters: t.parameters ?? {} } })) : undefined,
|
|
50
62
|
tool_choice: tools.length ? (toolChoice ?? "auto") : undefined,
|
|
51
63
|
stream: onStream ? true : undefined,
|
|
64
|
+
stream_options: onStream ? { include_usage: true } : undefined,
|
|
52
65
|
};
|
|
53
66
|
const headers = {
|
|
54
67
|
"Content-Type": "application/json",
|
|
@@ -59,7 +72,7 @@ async function openrouterAdapter(config, context, tools) {
|
|
|
59
72
|
if (title)
|
|
60
73
|
headers["X-Title"] = title;
|
|
61
74
|
if (await check())
|
|
62
|
-
return [];
|
|
75
|
+
return { messages: [] };
|
|
63
76
|
const res = await fetch(`${baseUrl.replace(/\/$/, "")}/chat/completions`, {
|
|
64
77
|
method: "POST",
|
|
65
78
|
headers,
|
|
@@ -81,6 +94,7 @@ async function openrouterAdapter(config, context, tools) {
|
|
|
81
94
|
}
|
|
82
95
|
if (onStream) {
|
|
83
96
|
let content = "";
|
|
97
|
+
let usage;
|
|
84
98
|
const toolCalls = new Map();
|
|
85
99
|
const upsertToolCall = (tc) => {
|
|
86
100
|
const index = typeof tc?.index === "number" ? tc.index : toolCalls.size;
|
|
@@ -109,6 +123,11 @@ async function openrouterAdapter(config, context, tools) {
|
|
|
109
123
|
catch {
|
|
110
124
|
throw new Error(`OpenRouter API returned invalid JSON: ${dataLine.slice(0, 200)}`);
|
|
111
125
|
}
|
|
126
|
+
if (parsed?.usage) {
|
|
127
|
+
const nextUsage = toUsage(parsed.usage);
|
|
128
|
+
if (nextUsage)
|
|
129
|
+
usage = nextUsage;
|
|
130
|
+
}
|
|
112
131
|
const delta = parsed?.choices?.[0]?.delta;
|
|
113
132
|
if (!delta)
|
|
114
133
|
return;
|
|
@@ -124,22 +143,25 @@ async function openrouterAdapter(config, context, tools) {
|
|
|
124
143
|
await check();
|
|
125
144
|
}, check);
|
|
126
145
|
if (toolCalls.size > 0) {
|
|
127
|
-
return
|
|
128
|
-
.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
146
|
+
return {
|
|
147
|
+
messages: [...toolCalls.entries()]
|
|
148
|
+
.sort((a, b) => a[0] - b[0])
|
|
149
|
+
.map(([index, tc]) => {
|
|
150
|
+
if (!tc.name)
|
|
151
|
+
throw new Error(`OpenRouter streaming tool call missing function name at index ${index}`);
|
|
152
|
+
return {
|
|
153
|
+
role: types_1.Role.ToolCall,
|
|
154
|
+
toolName: tc.name,
|
|
155
|
+
callId: tc.id ?? `call_${index}`,
|
|
156
|
+
argsText: tc.args.length ? tc.args : "{}",
|
|
157
|
+
};
|
|
158
|
+
}),
|
|
159
|
+
usage,
|
|
160
|
+
};
|
|
139
161
|
}
|
|
140
162
|
if (!content)
|
|
141
|
-
return [];
|
|
142
|
-
return [{ role: types_1.Role.Ai, content, isPartial: isAborted() ? true : undefined }];
|
|
163
|
+
return { messages: [], usage };
|
|
164
|
+
return { messages: [{ role: types_1.Role.Ai, content, isPartial: isAborted() ? true : undefined }], usage };
|
|
143
165
|
}
|
|
144
166
|
const text = await res.text();
|
|
145
167
|
let data;
|
|
@@ -151,16 +173,20 @@ async function openrouterAdapter(config, context, tools) {
|
|
|
151
173
|
}
|
|
152
174
|
if (data.error)
|
|
153
175
|
throw new Error(`OpenRouter API error: ${data.error.message}`);
|
|
176
|
+
const usage = toUsage(data.usage);
|
|
154
177
|
const msg = data.choices?.[0]?.message;
|
|
155
178
|
if (!msg)
|
|
156
179
|
throw new Error("OpenRouter API returned empty response");
|
|
157
180
|
if (msg.tool_calls?.length) {
|
|
158
|
-
return
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
181
|
+
return {
|
|
182
|
+
messages: msg.tool_calls.map((tc) => ({
|
|
183
|
+
role: types_1.Role.ToolCall,
|
|
184
|
+
toolName: tc.function.name,
|
|
185
|
+
callId: tc.id,
|
|
186
|
+
argsText: tc.function.arguments ?? "{}",
|
|
187
|
+
})),
|
|
188
|
+
usage,
|
|
189
|
+
};
|
|
164
190
|
}
|
|
165
|
-
return [{ role: types_1.Role.Ai, content: msg.content ?? "" }];
|
|
191
|
+
return { messages: [{ role: types_1.Role.Ai, content: msg.content ?? "" }], usage };
|
|
166
192
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type Message, type Tool } from "../types";
|
|
2
|
-
export declare function selfhostChatCompletionsAdapter(config: Record<string, unknown>, context: Message[], tools: Tool[]): Promise<
|
|
1
|
+
import { type AdapterResult, type Message, type Tool } from "../types";
|
|
2
|
+
export declare function selfhostChatCompletionsAdapter(config: Record<string, unknown>, context: Message[], tools: Tool[]): Promise<AdapterResult>;
|
|
@@ -27,6 +27,18 @@ function toOpenAIMessages(context) {
|
|
|
27
27
|
return out;
|
|
28
28
|
}, []);
|
|
29
29
|
}
|
|
30
|
+
function toUsage(usage) {
|
|
31
|
+
if (!usage)
|
|
32
|
+
return undefined;
|
|
33
|
+
const promptTokens = usage.prompt_tokens;
|
|
34
|
+
const completionTokens = usage.completion_tokens;
|
|
35
|
+
const totalTokens = usage.total_tokens;
|
|
36
|
+
if (typeof promptTokens !== "number"
|
|
37
|
+
|| typeof completionTokens !== "number"
|
|
38
|
+
|| typeof totalTokens !== "number")
|
|
39
|
+
return undefined;
|
|
40
|
+
return { promptTokens, completionTokens, totalTokens };
|
|
41
|
+
}
|
|
30
42
|
async function selfhostChatCompletionsAdapter(config, context, tools) {
|
|
31
43
|
const baseUrl = config.baseUrl ?? "http://localhost:1234";
|
|
32
44
|
const apiKey = config.apiKey || process.env.SELFHOST_API_KEY || "";
|
|
@@ -47,9 +59,10 @@ async function selfhostChatCompletionsAdapter(config, context, tools) {
|
|
|
47
59
|
tools: tools.length ? tools.map((t) => ({ type: "function", function: { name: t.name, description: t.description, parameters: t.parameters ?? {} } })) : undefined,
|
|
48
60
|
tool_choice: tools.length ? (toolChoice ?? "auto") : undefined,
|
|
49
61
|
stream: onStream ? true : undefined,
|
|
62
|
+
stream_options: onStream ? { include_usage: true } : undefined,
|
|
50
63
|
};
|
|
51
64
|
if (await check())
|
|
52
|
-
return [];
|
|
65
|
+
return { messages: [] };
|
|
53
66
|
const res = await fetch(`${baseUrl.replace(/\/$/, "")}/v1/chat/completions`, {
|
|
54
67
|
method: "POST",
|
|
55
68
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
@@ -71,6 +84,7 @@ async function selfhostChatCompletionsAdapter(config, context, tools) {
|
|
|
71
84
|
}
|
|
72
85
|
if (onStream) {
|
|
73
86
|
let content = "";
|
|
87
|
+
let usage;
|
|
74
88
|
const toolCalls = new Map();
|
|
75
89
|
const upsertToolCall = (tc) => {
|
|
76
90
|
const index = typeof tc?.index === "number" ? tc.index : toolCalls.size;
|
|
@@ -99,6 +113,11 @@ async function selfhostChatCompletionsAdapter(config, context, tools) {
|
|
|
99
113
|
catch {
|
|
100
114
|
throw new Error(`Self-host chat completions API returned invalid JSON: ${dataLine.slice(0, 200)}`);
|
|
101
115
|
}
|
|
116
|
+
if (parsed?.usage) {
|
|
117
|
+
const nextUsage = toUsage(parsed.usage);
|
|
118
|
+
if (nextUsage)
|
|
119
|
+
usage = nextUsage;
|
|
120
|
+
}
|
|
102
121
|
const delta = parsed?.choices?.[0]?.delta;
|
|
103
122
|
if (!delta)
|
|
104
123
|
return;
|
|
@@ -114,22 +133,25 @@ async function selfhostChatCompletionsAdapter(config, context, tools) {
|
|
|
114
133
|
await check();
|
|
115
134
|
}, check);
|
|
116
135
|
if (toolCalls.size > 0) {
|
|
117
|
-
return
|
|
118
|
-
.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
136
|
+
return {
|
|
137
|
+
messages: [...toolCalls.entries()]
|
|
138
|
+
.sort((a, b) => a[0] - b[0])
|
|
139
|
+
.map(([index, tc]) => {
|
|
140
|
+
if (!tc.name)
|
|
141
|
+
throw new Error(`Self-host streaming tool call missing function name at index ${index}`);
|
|
142
|
+
return {
|
|
143
|
+
role: types_1.Role.ToolCall,
|
|
144
|
+
toolName: tc.name,
|
|
145
|
+
callId: tc.id ?? `call_${index}`,
|
|
146
|
+
argsText: tc.args.length ? tc.args : "{}",
|
|
147
|
+
};
|
|
148
|
+
}),
|
|
149
|
+
usage,
|
|
150
|
+
};
|
|
129
151
|
}
|
|
130
152
|
if (!content)
|
|
131
|
-
return [];
|
|
132
|
-
return [{ role: types_1.Role.Ai, content, isPartial: isAborted() ? true : undefined }];
|
|
153
|
+
return { messages: [], usage };
|
|
154
|
+
return { messages: [{ role: types_1.Role.Ai, content, isPartial: isAborted() ? true : undefined }], usage };
|
|
133
155
|
}
|
|
134
156
|
const text = await res.text();
|
|
135
157
|
let data;
|
|
@@ -141,16 +163,20 @@ async function selfhostChatCompletionsAdapter(config, context, tools) {
|
|
|
141
163
|
}
|
|
142
164
|
if (data.error)
|
|
143
165
|
throw new Error(`Self-host chat completions API error: ${data.error.message}`);
|
|
166
|
+
const usage = toUsage(data.usage);
|
|
144
167
|
const msg = data.choices?.[0]?.message;
|
|
145
168
|
if (!msg)
|
|
146
169
|
throw new Error("Self-host chat completions API returned empty response");
|
|
147
170
|
if (msg.tool_calls?.length) {
|
|
148
|
-
return
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
171
|
+
return {
|
|
172
|
+
messages: msg.tool_calls.map((tc) => ({
|
|
173
|
+
role: types_1.Role.ToolCall,
|
|
174
|
+
toolName: tc.function.name,
|
|
175
|
+
callId: tc.id,
|
|
176
|
+
argsText: tc.function.arguments ?? "{}",
|
|
177
|
+
})),
|
|
178
|
+
usage,
|
|
179
|
+
};
|
|
154
180
|
}
|
|
155
|
-
return [{ role: types_1.Role.Ai, content: msg.content ?? "" }];
|
|
181
|
+
return { messages: [{ role: types_1.Role.Ai, content: msg.content ?? "" }], usage };
|
|
156
182
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { AgentConfig, AgentLike, Context, Message, Tool } from "./types";
|
|
1
|
+
import type { AgentConfig, AgentLike, Context, Message, Tool, Usage } from "./types";
|
|
2
2
|
export { openaiAdapter } from "./adapter/openai";
|
|
3
3
|
export { openrouterAdapter } from "./adapter/openrouter";
|
|
4
4
|
export { selfhostChatCompletionsAdapter } from "./adapter/selfhost_chat_completions";
|
|
5
|
-
export type { Adapter, AgentConfig, AgentLike, Context, Message, Tool } from "./types";
|
|
5
|
+
export type { Adapter, AgentConfig, AgentLike, Context, Message, Tool, Usage, AdapterResult } from "./types";
|
|
6
6
|
export { Role } from "./types";
|
|
7
7
|
export declare class Agent implements AgentLike {
|
|
8
8
|
context: Context;
|
|
@@ -15,5 +15,9 @@ export declare class Agent implements AgentLike {
|
|
|
15
15
|
private onToolResult?;
|
|
16
16
|
constructor(adapterName: string, config: AgentConfig);
|
|
17
17
|
registerTool(tool: Tool): void;
|
|
18
|
-
run(message: string): Promise<
|
|
18
|
+
run(message: string): Promise<{
|
|
19
|
+
messages: Message[];
|
|
20
|
+
usage?: Usage;
|
|
21
|
+
usageSum?: Usage;
|
|
22
|
+
}>;
|
|
19
23
|
}
|
package/dist/index.js
CHANGED
|
@@ -35,9 +35,11 @@ class Agent {
|
|
|
35
35
|
}
|
|
36
36
|
async run(message) {
|
|
37
37
|
const all = [];
|
|
38
|
+
let usage;
|
|
39
|
+
let usageSum;
|
|
38
40
|
const { check } = (0, abort_1.createAbortChecker)(this.config.isAbort);
|
|
39
41
|
if (await check())
|
|
40
|
-
return
|
|
42
|
+
return { messages: [] };
|
|
41
43
|
const sessionContext = [...this.context];
|
|
42
44
|
const persistToContext = (msgs) => {
|
|
43
45
|
this.context.push(...msgs);
|
|
@@ -48,10 +50,26 @@ class Agent {
|
|
|
48
50
|
const userMessage = { role: types_1.Role.User, content: message };
|
|
49
51
|
pushToSession([userMessage]);
|
|
50
52
|
persistToContext([userMessage]);
|
|
53
|
+
const addUsage = (next) => {
|
|
54
|
+
if (!next)
|
|
55
|
+
return;
|
|
56
|
+
usage = next;
|
|
57
|
+
if (!usageSum) {
|
|
58
|
+
usageSum = { ...next };
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
usageSum = {
|
|
62
|
+
promptTokens: usageSum.promptTokens + next.promptTokens,
|
|
63
|
+
completionTokens: usageSum.completionTokens + next.completionTokens,
|
|
64
|
+
totalTokens: usageSum.totalTokens + next.totalTokens,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
51
67
|
const runAdapter = async () => {
|
|
52
68
|
if (await check())
|
|
53
69
|
return [];
|
|
54
|
-
const
|
|
70
|
+
const result = await this.adapter(this.config, sessionContext, this.tools);
|
|
71
|
+
addUsage(result.usage);
|
|
72
|
+
const msgs = result.messages;
|
|
55
73
|
pushToSession(msgs);
|
|
56
74
|
persistToContext(msgs);
|
|
57
75
|
all.push(...msgs);
|
|
@@ -59,16 +77,16 @@ class Agent {
|
|
|
59
77
|
};
|
|
60
78
|
let msgs = await runAdapter();
|
|
61
79
|
if (await check())
|
|
62
|
-
return all;
|
|
80
|
+
return { messages: all, usage, usageSum };
|
|
63
81
|
for (;;) {
|
|
64
82
|
if (await check())
|
|
65
|
-
return all;
|
|
83
|
+
return { messages: all, usage, usageSum };
|
|
66
84
|
const last = msgs[msgs.length - 1];
|
|
67
85
|
if (this.endCondition(sessionContext, last))
|
|
68
|
-
return all;
|
|
86
|
+
return { messages: all, usage, usageSum };
|
|
69
87
|
const toolCalls = msgs.filter((m) => m.role === types_1.Role.ToolCall);
|
|
70
88
|
if (toolCalls.length === 0)
|
|
71
|
-
return all;
|
|
89
|
+
return { messages: all, usage, usageSum };
|
|
72
90
|
const results = await Promise.all(toolCalls.map(async (m) => {
|
|
73
91
|
if (await check())
|
|
74
92
|
return null;
|
package/dist/types.d.ts
CHANGED
|
@@ -27,10 +27,19 @@ export type Message = {
|
|
|
27
27
|
isError?: boolean;
|
|
28
28
|
};
|
|
29
29
|
export type Context = Message[];
|
|
30
|
+
export type Usage = {
|
|
31
|
+
promptTokens: number;
|
|
32
|
+
completionTokens: number;
|
|
33
|
+
totalTokens: number;
|
|
34
|
+
};
|
|
30
35
|
export interface AgentLike {
|
|
31
36
|
context: Context;
|
|
32
37
|
registerTool: (tool: Tool) => void;
|
|
33
|
-
run: (message: string) => Promise<
|
|
38
|
+
run: (message: string) => Promise<{
|
|
39
|
+
messages: Message[];
|
|
40
|
+
usage?: Usage;
|
|
41
|
+
usageSum?: Usage;
|
|
42
|
+
}>;
|
|
34
43
|
}
|
|
35
44
|
export type Tool = {
|
|
36
45
|
name: string;
|
|
@@ -52,4 +61,8 @@ export type AgentConfig = {
|
|
|
52
61
|
}>, agent: AgentLike) => void | Promise<void>;
|
|
53
62
|
[key: string]: unknown;
|
|
54
63
|
};
|
|
55
|
-
export type
|
|
64
|
+
export type AdapterResult = {
|
|
65
|
+
messages: Message[];
|
|
66
|
+
usage?: Usage;
|
|
67
|
+
};
|
|
68
|
+
export type Adapter = (config: Record<string, unknown>, context: Message[], tools: Tool[]) => Promise<AdapterResult>;
|