@arki-moe/agent-ts 5.2.0 → 5.4.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 CHANGED
@@ -33,9 +33,14 @@ 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 msgs = await agent.run("What time is it?");
38
- console.log(msgs);
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);
40
+
41
+ // run also accepts multiple user messages or Message objects
42
+ await agent.run(["Hello", "What's next?"]);
43
+ await agent.run({ role: Role.System, content: "You are brief." });
39
44
 
40
45
  // context is a public property that can be read directly
41
46
  console.log(agent.context);
@@ -56,7 +61,8 @@ When `apiKey` is not provided in config, adapters read from the corresponding en
56
61
  - `Agent(adapterName, config)` - Create Agent
57
62
  - `agent.context` - Public property, complete conversation history
58
63
  - `agent.registerTool(tool)` - Register tool
59
- - `agent.run(message)` - Execute tool chain automatically, returns all new `Message[]`
64
+ - `agent.run(message)` - Execute tool chain automatically, returns `{ messages, usage, usageSum }`
65
+ - `message` can be `string | string[] | Message | Message[]`
60
66
 
61
67
  ### Config
62
68
 
@@ -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<Message[]>;
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>;
@@ -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 [...toolCalls.entries()]
118
- .sort((a, b) => a[0] - b[0])
119
- .map(([index, tc]) => {
120
- if (!tc.name)
121
- throw new Error(`OpenAI streaming tool call missing function name at index ${index}`);
122
- return {
123
- role: types_1.Role.ToolCall,
124
- toolName: tc.name,
125
- callId: tc.id ?? `call_${index}`,
126
- argsText: tc.args.length ? tc.args : "{}",
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 msg.tool_calls.map((tc) => ({
149
- role: types_1.Role.ToolCall,
150
- toolName: tc.function.name,
151
- callId: tc.id,
152
- argsText: tc.function.arguments ?? "{}",
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<Message[]>;
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 [...toolCalls.entries()]
128
- .sort((a, b) => a[0] - b[0])
129
- .map(([index, tc]) => {
130
- if (!tc.name)
131
- throw new Error(`OpenRouter streaming tool call missing function name at index ${index}`);
132
- return {
133
- role: types_1.Role.ToolCall,
134
- toolName: tc.name,
135
- callId: tc.id ?? `call_${index}`,
136
- argsText: tc.args.length ? tc.args : "{}",
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 msg.tool_calls.map((tc) => ({
159
- role: types_1.Role.ToolCall,
160
- toolName: tc.function.name,
161
- callId: tc.id,
162
- argsText: tc.function.arguments ?? "{}",
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<Message[]>;
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 [...toolCalls.entries()]
118
- .sort((a, b) => a[0] - b[0])
119
- .map(([index, tc]) => {
120
- if (!tc.name)
121
- throw new Error(`Self-host streaming tool call missing function name at index ${index}`);
122
- return {
123
- role: types_1.Role.ToolCall,
124
- toolName: tc.name,
125
- callId: tc.id ?? `call_${index}`,
126
- argsText: tc.args.length ? tc.args : "{}",
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 msg.tool_calls.map((tc) => ({
149
- role: types_1.Role.ToolCall,
150
- toolName: tc.function.name,
151
- callId: tc.id,
152
- argsText: tc.function.arguments ?? "{}",
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, RunInput, 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, RunInput, 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,29 @@ 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<Message[]>;
18
+ run(message: RunInput): Promise<{
19
+ messages: Message[];
20
+ usage?: Usage;
21
+ usageSum?: Usage;
22
+ }>;
23
+ run(message: string): Promise<{
24
+ messages: Message[];
25
+ usage?: Usage;
26
+ usageSum?: Usage;
27
+ }>;
28
+ run(message: string[]): Promise<{
29
+ messages: Message[];
30
+ usage?: Usage;
31
+ usageSum?: Usage;
32
+ }>;
33
+ run(message: Message): Promise<{
34
+ messages: Message[];
35
+ usage?: Usage;
36
+ usageSum?: Usage;
37
+ }>;
38
+ run(message: Message[]): Promise<{
39
+ messages: Message[];
40
+ usage?: Usage;
41
+ usageSum?: Usage;
42
+ }>;
19
43
  }
package/dist/index.js CHANGED
@@ -19,6 +19,19 @@ const adapters = {
19
19
  openrouter: openrouter_1.openrouterAdapter,
20
20
  selfhost_chat_completions: selfhost_chat_completions_1.selfhostChatCompletionsAdapter,
21
21
  };
22
+ const normalizeRunInput = (input) => {
23
+ if (typeof input === "string")
24
+ return [{ role: types_1.Role.User, content: input }];
25
+ if (Array.isArray(input)) {
26
+ if (input.length === 0)
27
+ return [];
28
+ if (typeof input[0] === "string") {
29
+ return input.map((content) => ({ role: types_1.Role.User, content }));
30
+ }
31
+ return input;
32
+ }
33
+ return [input];
34
+ };
22
35
  class Agent {
23
36
  constructor(adapterName, config) {
24
37
  this.context = [];
@@ -35,9 +48,11 @@ class Agent {
35
48
  }
36
49
  async run(message) {
37
50
  const all = [];
51
+ let usage;
52
+ let usageSum;
38
53
  const { check } = (0, abort_1.createAbortChecker)(this.config.isAbort);
39
54
  if (await check())
40
- return all;
55
+ return { messages: [] };
41
56
  const sessionContext = [...this.context];
42
57
  const persistToContext = (msgs) => {
43
58
  this.context.push(...msgs);
@@ -45,13 +60,31 @@ class Agent {
45
60
  const pushToSession = (msgs) => {
46
61
  sessionContext.push(...msgs);
47
62
  };
48
- const userMessage = { role: types_1.Role.User, content: message };
49
- pushToSession([userMessage]);
50
- persistToContext([userMessage]);
63
+ const inputMessages = normalizeRunInput(message);
64
+ if (inputMessages.length === 0)
65
+ return { messages: [] };
66
+ pushToSession(inputMessages);
67
+ persistToContext(inputMessages);
68
+ const addUsage = (next) => {
69
+ if (!next)
70
+ return;
71
+ usage = next;
72
+ if (!usageSum) {
73
+ usageSum = { ...next };
74
+ return;
75
+ }
76
+ usageSum = {
77
+ promptTokens: usageSum.promptTokens + next.promptTokens,
78
+ completionTokens: usageSum.completionTokens + next.completionTokens,
79
+ totalTokens: usageSum.totalTokens + next.totalTokens,
80
+ };
81
+ };
51
82
  const runAdapter = async () => {
52
83
  if (await check())
53
84
  return [];
54
- const msgs = await this.adapter(this.config, sessionContext, this.tools);
85
+ const result = await this.adapter(this.config, sessionContext, this.tools);
86
+ addUsage(result.usage);
87
+ const msgs = result.messages;
55
88
  pushToSession(msgs);
56
89
  persistToContext(msgs);
57
90
  all.push(...msgs);
@@ -59,16 +92,16 @@ class Agent {
59
92
  };
60
93
  let msgs = await runAdapter();
61
94
  if (await check())
62
- return all;
95
+ return { messages: all, usage, usageSum };
63
96
  for (;;) {
64
97
  if (await check())
65
- return all;
98
+ return { messages: all, usage, usageSum };
66
99
  const last = msgs[msgs.length - 1];
67
100
  if (this.endCondition(sessionContext, last))
68
- return all;
101
+ return { messages: all, usage, usageSum };
69
102
  const toolCalls = msgs.filter((m) => m.role === types_1.Role.ToolCall);
70
103
  if (toolCalls.length === 0)
71
- return all;
104
+ return { messages: all, usage, usageSum };
72
105
  const results = await Promise.all(toolCalls.map(async (m) => {
73
106
  if (await check())
74
107
  return null;
package/dist/types.d.ts CHANGED
@@ -27,10 +27,20 @@ export type Message = {
27
27
  isError?: boolean;
28
28
  };
29
29
  export type Context = Message[];
30
+ export type RunInput = string | string[] | Message | Message[];
31
+ export type Usage = {
32
+ promptTokens: number;
33
+ completionTokens: number;
34
+ totalTokens: number;
35
+ };
30
36
  export interface AgentLike {
31
37
  context: Context;
32
38
  registerTool: (tool: Tool) => void;
33
- run: (message: string) => Promise<Message[]>;
39
+ run: (message: RunInput) => Promise<{
40
+ messages: Message[];
41
+ usage?: Usage;
42
+ usageSum?: Usage;
43
+ }>;
34
44
  }
35
45
  export type Tool = {
36
46
  name: string;
@@ -52,4 +62,8 @@ export type AgentConfig = {
52
62
  }>, agent: AgentLike) => void | Promise<void>;
53
63
  [key: string]: unknown;
54
64
  };
55
- export type Adapter = (config: Record<string, unknown>, context: Message[], tools: Tool[]) => Promise<Message[]>;
65
+ export type AdapterResult = {
66
+ messages: Message[];
67
+ usage?: Usage;
68
+ };
69
+ export type Adapter = (config: Record<string, unknown>, context: Message[], tools: Tool[]) => Promise<AdapterResult>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arki-moe/agent-ts",
3
- "version": "5.2.0",
3
+ "version": "5.4.0",
4
4
  "description": "Minimal Agent library, zero dependencies",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",