@framers/agentos 0.1.93 → 0.1.94

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.
@@ -8,7 +8,10 @@
8
8
  * model produces a plain-text reply or `maxSteps` is exhausted.
9
9
  */
10
10
  import { resolveModelOption, resolveProvider, createProviderManager } from './model.js';
11
+ import { attachUsageAttributes, toTurnMetricUsage } from './observability.js';
11
12
  import { adaptTools } from './toolAdapter.js';
13
+ import { recordAgentOSUsage } from './usageLedger.js';
14
+ import { recordAgentOSTurnMetrics, withAgentOSSpan } from '../core/observability/otel.js';
12
15
  /**
13
16
  * Stateless text generation with optional multi-step tool calling.
14
17
  *
@@ -30,113 +33,182 @@ import { adaptTools } from './toolAdapter.js';
30
33
  * ```
31
34
  */
32
35
  export async function generateText(opts) {
33
- const { providerId, modelId } = resolveModelOption(opts, 'text');
34
- const resolved = resolveProvider(providerId, modelId, { apiKey: opts.apiKey, baseUrl: opts.baseUrl });
35
- const manager = await createProviderManager(resolved);
36
- const provider = manager.getProvider(resolved.providerId);
37
- if (!provider)
38
- throw new Error(`Provider ${resolved.providerId} not available.`);
39
- // Build messages
40
- const messages = [];
41
- if (opts.system)
42
- messages.push({ role: 'system', content: opts.system });
43
- if (opts.messages) {
44
- for (const m of opts.messages)
45
- messages.push({ role: m.role, content: m.content });
46
- }
47
- if (opts.prompt)
48
- messages.push({ role: 'user', content: opts.prompt });
49
- const tools = adaptTools(opts.tools);
50
- const toolMap = new Map();
51
- for (const t of tools)
52
- toolMap.set(t.name, t);
53
- const toolSchemas = tools.length > 0
54
- ? tools.map(t => ({
55
- type: 'function',
56
- function: { name: t.name, description: t.description, parameters: t.inputSchema },
57
- }))
58
- : undefined;
59
- const allToolCalls = [];
60
- const totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
61
- const maxSteps = opts.maxSteps ?? 1;
62
- for (let step = 0; step < maxSteps; step++) {
63
- const response = await provider.generateCompletion(resolved.modelId, messages, {
64
- tools: toolSchemas,
65
- temperature: opts.temperature,
66
- maxTokens: opts.maxTokens,
67
- });
68
- // Accumulate usage
69
- if (response.usage) {
70
- totalUsage.promptTokens += response.usage.promptTokens ?? 0;
71
- totalUsage.completionTokens += response.usage.completionTokens ?? 0;
72
- totalUsage.totalTokens += response.usage.totalTokens ?? 0;
73
- }
74
- const choice = response.choices?.[0];
75
- if (!choice)
76
- break;
77
- const content = choice.message?.content;
78
- const textContent = typeof content === 'string' ? content : content?.text ?? '';
79
- const toolCallsInChoice = choice.message?.tool_calls ?? [];
80
- // If assistant returned text with no tool calls, we're done
81
- if (textContent && toolCallsInChoice.length === 0) {
36
+ const startedAt = Date.now();
37
+ let metricStatus = 'ok';
38
+ let metricUsage;
39
+ let metricProviderId;
40
+ let metricModelId;
41
+ try {
42
+ return await withAgentOSSpan('agentos.api.generate_text', async (span) => {
43
+ const { providerId, modelId } = resolveModelOption(opts, 'text');
44
+ const resolved = resolveProvider(providerId, modelId, { apiKey: opts.apiKey, baseUrl: opts.baseUrl });
45
+ const manager = await createProviderManager(resolved);
46
+ metricProviderId = resolved.providerId;
47
+ metricModelId = resolved.modelId;
48
+ const provider = manager.getProvider(resolved.providerId);
49
+ if (!provider)
50
+ throw new Error(`Provider ${resolved.providerId} not available.`);
51
+ span?.setAttribute('llm.provider', resolved.providerId);
52
+ span?.setAttribute('llm.model', resolved.modelId);
53
+ // Build messages
54
+ const messages = [];
55
+ if (opts.system)
56
+ messages.push({ role: 'system', content: opts.system });
57
+ if (opts.messages) {
58
+ for (const m of opts.messages)
59
+ messages.push({ role: m.role, content: m.content });
60
+ }
61
+ if (opts.prompt)
62
+ messages.push({ role: 'user', content: opts.prompt });
63
+ const tools = adaptTools(opts.tools);
64
+ const toolMap = new Map();
65
+ for (const t of tools)
66
+ toolMap.set(t.name, t);
67
+ span?.setAttribute('agentos.api.tool_count', tools.length);
68
+ const toolSchemas = tools.length > 0
69
+ ? tools.map(t => ({
70
+ type: 'function',
71
+ function: { name: t.name, description: t.description, parameters: t.inputSchema },
72
+ }))
73
+ : undefined;
74
+ const allToolCalls = [];
75
+ const totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
76
+ const maxSteps = opts.maxSteps ?? 1;
77
+ span?.setAttribute('agentos.api.max_steps', maxSteps);
78
+ for (let step = 0; step < maxSteps; step++) {
79
+ const response = await withAgentOSSpan('agentos.api.generate_text.step', async (stepSpan) => {
80
+ stepSpan?.setAttribute('llm.provider', resolved.providerId);
81
+ stepSpan?.setAttribute('llm.model', resolved.modelId);
82
+ stepSpan?.setAttribute('agentos.api.step', step + 1);
83
+ stepSpan?.setAttribute('agentos.api.tool_count', tools.length);
84
+ const stepResponse = await provider.generateCompletion(resolved.modelId, messages, {
85
+ tools: toolSchemas,
86
+ temperature: opts.temperature,
87
+ maxTokens: opts.maxTokens,
88
+ });
89
+ attachUsageAttributes(stepSpan, {
90
+ promptTokens: stepResponse.usage?.promptTokens,
91
+ completionTokens: stepResponse.usage?.completionTokens,
92
+ totalTokens: stepResponse.usage?.totalTokens,
93
+ costUSD: stepResponse.usage?.costUSD,
94
+ });
95
+ return stepResponse;
96
+ });
97
+ if (response.usage) {
98
+ totalUsage.promptTokens += response.usage.promptTokens ?? 0;
99
+ totalUsage.completionTokens += response.usage.completionTokens ?? 0;
100
+ totalUsage.totalTokens += response.usage.totalTokens ?? 0;
101
+ if (typeof response.usage.costUSD === 'number') {
102
+ totalUsage.costUSD = (totalUsage.costUSD ?? 0) + response.usage.costUSD;
103
+ }
104
+ }
105
+ const choice = response.choices?.[0];
106
+ if (!choice)
107
+ break;
108
+ const content = choice.message?.content;
109
+ const textContent = typeof content === 'string' ? content : content?.text ?? '';
110
+ const toolCallsInChoice = choice.message?.tool_calls ?? [];
111
+ if (textContent && toolCallsInChoice.length === 0) {
112
+ metricUsage = totalUsage;
113
+ span?.setAttribute('agentos.api.finish_reason', choice.finishReason ?? 'stop');
114
+ span?.setAttribute('agentos.api.tool_calls', allToolCalls.length);
115
+ attachUsageAttributes(span, totalUsage);
116
+ return {
117
+ provider: resolved.providerId,
118
+ model: resolved.modelId,
119
+ text: textContent,
120
+ usage: totalUsage,
121
+ toolCalls: allToolCalls,
122
+ finishReason: (choice.finishReason ?? 'stop'),
123
+ };
124
+ }
125
+ if (toolCallsInChoice.length > 0) {
126
+ messages.push({
127
+ role: 'assistant',
128
+ content: textContent || null,
129
+ tool_calls: toolCallsInChoice,
130
+ });
131
+ for (const tc of toolCallsInChoice) {
132
+ const fnName = tc.function?.name ?? tc.name ?? '';
133
+ const fnArgs = tc.function?.arguments ?? '{}';
134
+ const tcId = tc.id ?? '';
135
+ const tool = toolMap.get(fnName);
136
+ const record = {
137
+ name: fnName,
138
+ args: JSON.parse(typeof fnArgs === 'string' ? fnArgs : JSON.stringify(fnArgs)),
139
+ };
140
+ if (tool) {
141
+ try {
142
+ const result = await tool.execute(record.args, {});
143
+ record.result = result.output;
144
+ record.error = result.success ? undefined : result.error;
145
+ messages.push({
146
+ role: 'tool',
147
+ tool_call_id: tcId,
148
+ content: JSON.stringify(result.output ?? result.error ?? ''),
149
+ });
150
+ }
151
+ catch (err) {
152
+ record.error = err?.message;
153
+ messages.push({ role: 'tool', tool_call_id: tcId, content: JSON.stringify({ error: err?.message }) });
154
+ }
155
+ }
156
+ allToolCalls.push(record);
157
+ }
158
+ continue;
159
+ }
160
+ metricUsage = totalUsage;
161
+ span?.setAttribute('agentos.api.finish_reason', choice.finishReason ?? 'stop');
162
+ span?.setAttribute('agentos.api.tool_calls', allToolCalls.length);
163
+ attachUsageAttributes(span, totalUsage);
164
+ return {
165
+ provider: resolved.providerId,
166
+ model: resolved.modelId,
167
+ text: textContent,
168
+ usage: totalUsage,
169
+ toolCalls: allToolCalls,
170
+ finishReason: (choice.finishReason ?? 'stop'),
171
+ };
172
+ }
173
+ const lastAssistant = messages.filter(m => m.role === 'assistant').pop();
174
+ metricUsage = totalUsage;
175
+ span?.setAttribute('agentos.api.finish_reason', 'tool-calls');
176
+ span?.setAttribute('agentos.api.tool_calls', allToolCalls.length);
177
+ attachUsageAttributes(span, totalUsage);
82
178
  return {
83
- text: textContent,
179
+ provider: resolved.providerId,
180
+ model: resolved.modelId,
181
+ text: lastAssistant?.content ?? '',
84
182
  usage: totalUsage,
85
183
  toolCalls: allToolCalls,
86
- finishReason: (choice.finishReason ?? 'stop'),
184
+ finishReason: 'tool-calls',
87
185
  };
88
- }
89
- // Tool calls
90
- if (toolCallsInChoice.length > 0) {
91
- messages.push({
92
- role: 'assistant',
93
- content: textContent || null,
94
- tool_calls: toolCallsInChoice,
186
+ });
187
+ }
188
+ catch (error) {
189
+ metricStatus = 'error';
190
+ throw error;
191
+ }
192
+ finally {
193
+ try {
194
+ await recordAgentOSUsage({
195
+ providerId: metricProviderId,
196
+ modelId: metricModelId,
197
+ usage: metricUsage,
198
+ options: {
199
+ ...opts.usageLedger,
200
+ source: opts.usageLedger?.source ?? 'generateText',
201
+ },
95
202
  });
96
- for (const tc of toolCallsInChoice) {
97
- const fnName = tc.function?.name ?? tc.name ?? '';
98
- const fnArgs = tc.function?.arguments ?? '{}';
99
- const tcId = tc.id ?? '';
100
- const tool = toolMap.get(fnName);
101
- const record = {
102
- name: fnName,
103
- args: JSON.parse(typeof fnArgs === 'string' ? fnArgs : JSON.stringify(fnArgs)),
104
- };
105
- if (tool) {
106
- try {
107
- const result = await tool.execute(record.args, {});
108
- record.result = result.output;
109
- record.error = result.success ? undefined : result.error;
110
- messages.push({
111
- role: 'tool',
112
- tool_call_id: tcId,
113
- content: JSON.stringify(result.output ?? result.error ?? ''),
114
- });
115
- }
116
- catch (err) {
117
- record.error = err?.message;
118
- messages.push({ role: 'tool', tool_call_id: tcId, content: JSON.stringify({ error: err?.message }) });
119
- }
120
- }
121
- allToolCalls.push(record);
122
- }
123
- continue;
124
203
  }
125
- // No content and no tool calls — done
126
- return {
127
- text: textContent,
128
- usage: totalUsage,
129
- toolCalls: allToolCalls,
130
- finishReason: (choice.finishReason ?? 'stop'),
131
- };
204
+ catch {
205
+ // Helper-level usage persistence is best-effort and should not break generation.
206
+ }
207
+ recordAgentOSTurnMetrics({
208
+ durationMs: Date.now() - startedAt,
209
+ status: metricStatus,
210
+ usage: toTurnMetricUsage(metricUsage),
211
+ });
132
212
  }
133
- // Exhausted maxSteps — return last state
134
- const lastAssistant = messages.filter(m => m.role === 'assistant').pop();
135
- return {
136
- text: lastAssistant?.content ?? '',
137
- usage: totalUsage,
138
- toolCalls: allToolCalls,
139
- finishReason: 'tool-calls',
140
- };
141
213
  }
142
214
  //# sourceMappingURL=generateText.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateText.js","sourceRoot":"","sources":["../../src/api/generateText.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generateText.js","sourceRoot":"","sources":["../../src/api/generateText.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Span } from '@opentelemetry/api';
2
+ export interface ApiUsageLike {
3
+ promptTokens?: number;
4
+ completionTokens?: number;
5
+ totalTokens?: number;
6
+ costUSD?: number;
7
+ totalCostUSD?: number;
8
+ }
9
+ export declare function attachUsageAttributes(span: Span | null, usage?: ApiUsageLike | null): void;
10
+ export declare function toTurnMetricUsage(usage?: ApiUsageLike | null): {
11
+ totalTokens?: number;
12
+ promptTokens?: number;
13
+ completionTokens?: number;
14
+ totalCostUSD?: number;
15
+ } | undefined;
16
+ //# sourceMappingURL=observability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability.d.ts","sourceRoot":"","sources":["../../src/api/observability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAsB1F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,SAAS,CA4BZ"}
@@ -0,0 +1,46 @@
1
+ export function attachUsageAttributes(span, usage) {
2
+ if (!span || !usage)
3
+ return;
4
+ if (typeof usage.promptTokens === 'number') {
5
+ span.setAttribute('llm.usage.prompt_tokens', usage.promptTokens);
6
+ }
7
+ if (typeof usage.completionTokens === 'number') {
8
+ span.setAttribute('llm.usage.completion_tokens', usage.completionTokens);
9
+ }
10
+ if (typeof usage.totalTokens === 'number') {
11
+ span.setAttribute('llm.usage.total_tokens', usage.totalTokens);
12
+ }
13
+ const totalCostUSD = typeof usage.totalCostUSD === 'number'
14
+ ? usage.totalCostUSD
15
+ : typeof usage.costUSD === 'number'
16
+ ? usage.costUSD
17
+ : undefined;
18
+ if (typeof totalCostUSD === 'number') {
19
+ span.setAttribute('llm.usage.cost_usd', totalCostUSD);
20
+ }
21
+ }
22
+ export function toTurnMetricUsage(usage) {
23
+ if (!usage)
24
+ return undefined;
25
+ const totalTokens = typeof usage.totalTokens === 'number' ? usage.totalTokens : undefined;
26
+ const promptTokens = typeof usage.promptTokens === 'number' ? usage.promptTokens : undefined;
27
+ const completionTokens = typeof usage.completionTokens === 'number' ? usage.completionTokens : undefined;
28
+ const totalCostUSD = typeof usage.totalCostUSD === 'number'
29
+ ? usage.totalCostUSD
30
+ : typeof usage.costUSD === 'number'
31
+ ? usage.costUSD
32
+ : undefined;
33
+ if (totalTokens === undefined
34
+ && promptTokens === undefined
35
+ && completionTokens === undefined
36
+ && totalCostUSD === undefined) {
37
+ return undefined;
38
+ }
39
+ return {
40
+ totalTokens,
41
+ promptTokens,
42
+ completionTokens,
43
+ totalCostUSD,
44
+ };
45
+ }
46
+ //# sourceMappingURL=observability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability.js","sourceRoot":"","sources":["../../src/api/observability.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,qBAAqB,CAAC,IAAiB,EAAE,KAA2B;IAClF,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO;IAE5B,IAAI,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC3C,IAAI,CAAC,YAAY,CAAC,yBAAyB,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,gBAAgB,KAAK,QAAQ,EAAE,CAAC;QAC/C,IAAI,CAAC,YAAY,CAAC,6BAA6B,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QAC1C,IAAI,CAAC,YAAY,CAAC,wBAAwB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,YAAY,GAChB,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ;QACpC,CAAC,CAAC,KAAK,CAAC,YAAY;QACpB,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;YACjC,CAAC,CAAC,KAAK,CAAC,OAAO;YACf,CAAC,CAAC,SAAS,CAAC;IAClB,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,IAAI,CAAC,YAAY,CAAC,oBAAoB,EAAE,YAAY,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAA2B;IAM3D,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAE7B,MAAM,WAAW,GAAG,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1F,MAAM,YAAY,GAAG,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7F,MAAM,gBAAgB,GAAG,OAAO,KAAK,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;IACzG,MAAM,YAAY,GAChB,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ;QACpC,CAAC,CAAC,KAAK,CAAC,YAAY;QACpB,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;YACjC,CAAC,CAAC,KAAK,CAAC,OAAO;YACf,CAAC,CAAC,SAAS,CAAC;IAElB,IACE,WAAW,KAAK,SAAS;WACtB,YAAY,KAAK,SAAS;WAC1B,gBAAgB,KAAK,SAAS;WAC9B,YAAY,KAAK,SAAS,EAC7B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,WAAW;QACX,YAAY;QACZ,gBAAgB;QAChB,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"streamText.d.ts","sourceRoot":"","sources":["../../src/api/streamText.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAIzF;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpC;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2FAA2F;IAC3F,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,yEAAyE;IACzE,UAAU,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACtC,iFAAiF;IACjF,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,2EAA2E;IAC3E,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3B,yFAAyF;IACzF,SAAS,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,mBAAmB,GAAG,gBAAgB,CA2NtE"}
1
+ {"version":3,"file":"streamText.d.ts","sourceRoot":"","sources":["../../src/api/streamText.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMzF;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpC;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2FAA2F;IAC3F,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,yEAAyE;IACzE,UAAU,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACtC,iFAAiF;IACjF,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,2EAA2E;IAC3E,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3B,yFAAyF;IACzF,SAAS,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,mBAAmB,GAAG,gBAAgB,CA4RtE"}
@@ -8,8 +8,11 @@
8
8
  * yielded inline before the next LLM step begins.
9
9
  */
10
10
  import { resolveModelOption, resolveProvider, createProviderManager } from './model.js';
11
+ import { attachUsageAttributes, toTurnMetricUsage } from './observability.js';
11
12
  import { adaptTools } from './toolAdapter.js';
13
+ import { recordAgentOSUsage } from './usageLedger.js';
12
14
  import { StreamingReconstructor } from '../core/llm/streaming/StreamingReconstructor.js';
15
+ import { recordAgentOSTurnMetrics, startAgentOSSpan } from '../core/observability/otel.js';
13
16
  /**
14
17
  * Stateless streaming text generation with optional multi-step tool calling.
15
18
  *
@@ -38,15 +41,24 @@ export function streamText(opts) {
38
41
  const parts = [];
39
42
  const allToolCalls = [];
40
43
  async function* runStream() {
44
+ const startedAt = Date.now();
45
+ const rootSpan = startAgentOSSpan('agentos.api.stream_text');
41
46
  const usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
42
47
  let finalText = '';
48
+ let metricStatus = 'ok';
49
+ let recordedProviderId;
50
+ let recordedModelId;
43
51
  try {
44
52
  const { providerId, modelId } = resolveModelOption(opts, 'text');
45
53
  const resolved = resolveProvider(providerId, modelId, { apiKey: opts.apiKey, baseUrl: opts.baseUrl });
46
54
  const manager = await createProviderManager(resolved);
55
+ recordedProviderId = resolved.providerId;
56
+ recordedModelId = resolved.modelId;
47
57
  const provider = manager.getProvider(resolved.providerId);
48
58
  if (!provider)
49
59
  throw new Error(`Provider ${resolved.providerId} not available.`);
60
+ rootSpan?.setAttribute('llm.provider', resolved.providerId);
61
+ rootSpan?.setAttribute('llm.model', resolved.modelId);
50
62
  const messages = [];
51
63
  if (opts.system)
52
64
  messages.push({ role: 'system', content: opts.system });
@@ -59,6 +71,7 @@ export function streamText(opts) {
59
71
  const toolMap = new Map();
60
72
  for (const tool of tools)
61
73
  toolMap.set(tool.name, tool);
74
+ rootSpan?.setAttribute('agentos.api.tool_count', tools.length);
62
75
  const toolSchemas = tools.length > 0
63
76
  ? tools.map((tool) => ({
64
77
  type: 'function',
@@ -66,37 +79,61 @@ export function streamText(opts) {
66
79
  }))
67
80
  : undefined;
68
81
  const maxSteps = opts.maxSteps ?? 1;
82
+ rootSpan?.setAttribute('agentos.api.max_steps', maxSteps);
69
83
  for (let step = 0; step < maxSteps; step++) {
84
+ const stepSpan = startAgentOSSpan('agentos.api.stream_text.step', {
85
+ attributes: {
86
+ 'llm.provider': resolved.providerId,
87
+ 'llm.model': resolved.modelId,
88
+ 'agentos.api.step': step + 1,
89
+ 'agentos.api.tool_count': tools.length,
90
+ },
91
+ });
70
92
  const stream = provider.generateCompletionStream(resolved.modelId, messages, {
71
93
  tools: toolSchemas,
72
94
  temperature: opts.temperature,
73
95
  maxTokens: opts.maxTokens,
74
96
  });
75
97
  const reconstructor = new StreamingReconstructor();
76
- for await (const chunk of stream) {
77
- reconstructor.push(chunk);
78
- const textDelta = chunk.responseTextDelta ?? '';
79
- if (textDelta) {
80
- const part = { type: 'text', text: textDelta };
81
- parts.push(part);
82
- yield part;
83
- }
84
- if (chunk.error) {
85
- const error = new Error(chunk.error.message);
86
- const part = { type: 'error', error };
87
- parts.push(part);
88
- yield part;
89
- resolveText(finalText);
90
- resolveUsage(usage);
91
- resolveToolCalls(allToolCalls);
92
- return;
93
- }
94
- if (chunk.isFinal && chunk.usage) {
95
- usage.promptTokens += chunk.usage.promptTokens ?? 0;
96
- usage.completionTokens += chunk.usage.completionTokens ?? 0;
97
- usage.totalTokens += chunk.usage.totalTokens ?? 0;
98
+ try {
99
+ for await (const chunk of stream) {
100
+ reconstructor.push(chunk);
101
+ const textDelta = chunk.responseTextDelta ?? '';
102
+ if (textDelta) {
103
+ const part = { type: 'text', text: textDelta };
104
+ parts.push(part);
105
+ yield part;
106
+ }
107
+ if (chunk.error) {
108
+ const error = new Error(chunk.error.message);
109
+ const part = { type: 'error', error };
110
+ parts.push(part);
111
+ yield part;
112
+ metricStatus = 'error';
113
+ resolveText(finalText);
114
+ resolveUsage(usage);
115
+ resolveToolCalls(allToolCalls);
116
+ return;
117
+ }
118
+ if (chunk.isFinal && chunk.usage) {
119
+ usage.promptTokens += chunk.usage.promptTokens ?? 0;
120
+ usage.completionTokens += chunk.usage.completionTokens ?? 0;
121
+ usage.totalTokens += chunk.usage.totalTokens ?? 0;
122
+ if (typeof chunk.usage.costUSD === 'number') {
123
+ usage.costUSD = (usage.costUSD ?? 0) + chunk.usage.costUSD;
124
+ }
125
+ attachUsageAttributes(stepSpan, {
126
+ promptTokens: chunk.usage.promptTokens,
127
+ completionTokens: chunk.usage.completionTokens,
128
+ totalTokens: chunk.usage.totalTokens,
129
+ costUSD: chunk.usage.costUSD,
130
+ });
131
+ }
98
132
  }
99
133
  }
134
+ finally {
135
+ stepSpan?.end();
136
+ }
100
137
  const stepText = reconstructor.getFullText();
101
138
  const finalChunk = reconstructor.getFinalChunk();
102
139
  const streamedToolCalls = finalChunk?.choices?.[0]?.message?.tool_calls
@@ -112,6 +149,9 @@ export function streamText(opts) {
112
149
  }));
113
150
  if (!streamedToolCalls || streamedToolCalls.length === 0) {
114
151
  finalText = stepText;
152
+ rootSpan?.setAttribute('agentos.api.finish_reason', 'stop');
153
+ rootSpan?.setAttribute('agentos.api.tool_calls', allToolCalls.length);
154
+ attachUsageAttributes(rootSpan, usage);
115
155
  resolveText(finalText);
116
156
  resolveUsage(usage);
117
157
  resolveToolCalls(allToolCalls);
@@ -194,6 +234,7 @@ export function streamText(opts) {
194
234
  resolveToolCalls(allToolCalls);
195
235
  }
196
236
  catch (err) {
237
+ metricStatus = 'error';
197
238
  const error = err instanceof Error ? err : new Error(String(err));
198
239
  const part = { type: 'error', error };
199
240
  parts.push(part);
@@ -202,6 +243,36 @@ export function streamText(opts) {
202
243
  resolveUsage(usage);
203
244
  resolveToolCalls(allToolCalls);
204
245
  }
246
+ finally {
247
+ rootSpan?.setAttribute('agentos.api.tool_calls', allToolCalls.length);
248
+ if (metricStatus === 'error') {
249
+ rootSpan?.setAttribute('agentos.api.finish_reason', 'error');
250
+ }
251
+ else if (allToolCalls.length > 0 && !finalText) {
252
+ rootSpan?.setAttribute('agentos.api.finish_reason', 'tool-calls');
253
+ }
254
+ attachUsageAttributes(rootSpan, usage);
255
+ rootSpan?.end();
256
+ try {
257
+ await recordAgentOSUsage({
258
+ providerId: recordedProviderId,
259
+ modelId: recordedModelId,
260
+ usage,
261
+ options: {
262
+ ...opts.usageLedger,
263
+ source: opts.usageLedger?.source ?? 'streamText',
264
+ },
265
+ });
266
+ }
267
+ catch {
268
+ // Helper-level usage persistence is best-effort and should not break streaming.
269
+ }
270
+ recordAgentOSTurnMetrics({
271
+ durationMs: Date.now() - startedAt,
272
+ status: metricStatus,
273
+ usage: toTurnMetricUsage(usage),
274
+ });
275
+ }
205
276
  }
206
277
  const fullStreamIterable = runStream();
207
278
  const textStreamIterable = {