@digilogiclabs/platform-core 1.13.0 → 1.15.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/dist/{ConsoleEmail-CqXhZmFN.d.mts → ConsoleEmail-CO0OM4UT.d.ts} +2 -718
- package/dist/{ConsoleEmail-CqXhZmFN.d.ts → ConsoleEmail-DDB28vyS.d.mts} +2 -718
- package/dist/IAI-D8wA_i8N.d.mts +718 -0
- package/dist/IAI-D8wA_i8N.d.ts +718 -0
- package/dist/agents-Cd2eEX5M.d.mts +864 -0
- package/dist/agents-CntmA45w.d.ts +864 -0
- package/dist/agents.d.mts +2 -0
- package/dist/agents.d.ts +2 -0
- package/dist/agents.js +479 -0
- package/dist/agents.js.map +1 -0
- package/dist/agents.mjs +448 -0
- package/dist/agents.mjs.map +1 -0
- package/dist/auth.d.mts +186 -1
- package/dist/auth.d.ts +186 -1
- package/dist/auth.js +205 -0
- package/dist/auth.js.map +1 -1
- package/dist/auth.mjs +204 -0
- package/dist/auth.mjs.map +1 -1
- package/dist/index.d.mts +7 -563
- package/dist/index.d.ts +7 -563
- package/dist/index.js +436 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +431 -0
- package/dist/index.mjs.map +1 -1
- package/dist/testing.d.mts +3 -2
- package/dist/testing.d.ts +3 -2
- package/package.json +6 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { F as AgentBudget, p as AgentCumulativeUsage, r as AgentIterationCallback, q as AgentIterationEvent, t as AgentLoopOptions, u as AgentLoopResult, s as AgentStopReason, n as AgentTool, o as AgentToolResult, x as AgentTracer, w as AgentTracerOptions, E as AgentUsageRecordParams, G as AgentUsageTracker, z as AgentUsageTrackerOptions, D as DEFAULT_AGENT_LOOP_OPTIONS, T as ToolExecutor, J as TracedAIOptions, y as createAgentTracer, H as createAgentUsageTracker, K as createTracedAI, v as runAgentLoop } from './agents-Cd2eEX5M.mjs';
|
|
2
|
+
import './IAI-D8wA_i8N.mjs';
|
package/dist/agents.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { F as AgentBudget, p as AgentCumulativeUsage, r as AgentIterationCallback, q as AgentIterationEvent, t as AgentLoopOptions, u as AgentLoopResult, s as AgentStopReason, n as AgentTool, o as AgentToolResult, x as AgentTracer, w as AgentTracerOptions, E as AgentUsageRecordParams, G as AgentUsageTracker, z as AgentUsageTrackerOptions, D as DEFAULT_AGENT_LOOP_OPTIONS, T as ToolExecutor, J as TracedAIOptions, y as createAgentTracer, H as createAgentUsageTracker, K as createTracedAI, v as runAgentLoop } from './agents-CntmA45w.js';
|
|
2
|
+
import './IAI-D8wA_i8N.js';
|
package/dist/agents.js
ADDED
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/agents.ts
|
|
21
|
+
var agents_exports = {};
|
|
22
|
+
__export(agents_exports, {
|
|
23
|
+
DEFAULT_AGENT_LOOP_OPTIONS: () => DEFAULT_AGENT_LOOP_OPTIONS,
|
|
24
|
+
createAgentTracer: () => createAgentTracer,
|
|
25
|
+
createAgentUsageTracker: () => createAgentUsageTracker,
|
|
26
|
+
createTracedAI: () => createTracedAI,
|
|
27
|
+
runAgentLoop: () => runAgentLoop
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(agents_exports);
|
|
30
|
+
|
|
31
|
+
// src/interfaces/ILogger.ts
|
|
32
|
+
var NoopLogger = class {
|
|
33
|
+
debug() {
|
|
34
|
+
}
|
|
35
|
+
info() {
|
|
36
|
+
}
|
|
37
|
+
warn() {
|
|
38
|
+
}
|
|
39
|
+
error() {
|
|
40
|
+
}
|
|
41
|
+
child() {
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// src/agent/agent-loop.ts
|
|
47
|
+
var DEFAULT_AGENT_LOOP_OPTIONS = {
|
|
48
|
+
maxIterations: 10,
|
|
49
|
+
maxTokens: Infinity,
|
|
50
|
+
maxCostUsd: Infinity,
|
|
51
|
+
cacheTtlSeconds: 300,
|
|
52
|
+
cacheKeyPrefix: "agent:tool:"
|
|
53
|
+
};
|
|
54
|
+
function mapFinishReason(reason) {
|
|
55
|
+
switch (reason) {
|
|
56
|
+
case "stop":
|
|
57
|
+
return "stop";
|
|
58
|
+
case "length":
|
|
59
|
+
return "length";
|
|
60
|
+
case "content_filter":
|
|
61
|
+
return "content_filter";
|
|
62
|
+
case "tool_calls":
|
|
63
|
+
return "stop";
|
|
64
|
+
// shouldn't reach here in normal flow
|
|
65
|
+
case "error":
|
|
66
|
+
default:
|
|
67
|
+
return "error";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function executeToolCall(toolCall, executorMap, cache, cacheKeyPrefix, cacheTtlSeconds) {
|
|
71
|
+
const start = Date.now();
|
|
72
|
+
const executor = executorMap.get(toolCall.function.name);
|
|
73
|
+
if (!executor) {
|
|
74
|
+
return {
|
|
75
|
+
toolCall,
|
|
76
|
+
result: `Error: Unknown tool "${toolCall.function.name}"`,
|
|
77
|
+
success: false,
|
|
78
|
+
error: `Unknown tool: ${toolCall.function.name}`,
|
|
79
|
+
durationMs: Date.now() - start,
|
|
80
|
+
cached: false
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (cache) {
|
|
84
|
+
const cacheKey = cacheKeyPrefix + toolCall.function.name + ":" + toolCall.function.arguments;
|
|
85
|
+
try {
|
|
86
|
+
const cached = await cache.get(cacheKey);
|
|
87
|
+
if (cached !== null) {
|
|
88
|
+
return {
|
|
89
|
+
toolCall,
|
|
90
|
+
result: cached,
|
|
91
|
+
success: true,
|
|
92
|
+
durationMs: Date.now() - start,
|
|
93
|
+
cached: true
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
} catch {
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const parsed = JSON.parse(toolCall.function.arguments);
|
|
101
|
+
const result = await executor.execute(parsed, toolCall);
|
|
102
|
+
if (cache) {
|
|
103
|
+
const cacheKey = cacheKeyPrefix + toolCall.function.name + ":" + toolCall.function.arguments;
|
|
104
|
+
await cache.set(cacheKey, result, cacheTtlSeconds).catch(() => {
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
toolCall,
|
|
109
|
+
result,
|
|
110
|
+
success: true,
|
|
111
|
+
durationMs: Date.now() - start,
|
|
112
|
+
cached: false
|
|
113
|
+
};
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
116
|
+
return {
|
|
117
|
+
toolCall,
|
|
118
|
+
result: `Error: ${errorMsg}`,
|
|
119
|
+
success: false,
|
|
120
|
+
error: errorMsg,
|
|
121
|
+
durationMs: Date.now() - start,
|
|
122
|
+
cached: false
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function runAgentLoop(options) {
|
|
127
|
+
const opts = { ...DEFAULT_AGENT_LOOP_OPTIONS, ...options };
|
|
128
|
+
const logger = opts.logger ?? new NoopLogger();
|
|
129
|
+
const toolDefs = opts.tools.map((t) => t.definition);
|
|
130
|
+
const executorMap = /* @__PURE__ */ new Map();
|
|
131
|
+
for (const tool of opts.tools) {
|
|
132
|
+
executorMap.set(tool.definition.function.name, tool);
|
|
133
|
+
}
|
|
134
|
+
const messages = [...opts.messages];
|
|
135
|
+
const iterations = [];
|
|
136
|
+
const cumulative = {
|
|
137
|
+
promptTokens: 0,
|
|
138
|
+
completionTokens: 0,
|
|
139
|
+
totalTokens: 0,
|
|
140
|
+
estimatedCostUsd: 0,
|
|
141
|
+
iterations: 0,
|
|
142
|
+
toolCallCount: 0
|
|
143
|
+
};
|
|
144
|
+
let lastResponse;
|
|
145
|
+
let stopReason = "stop";
|
|
146
|
+
for (let i = 1; i <= opts.maxIterations; i++) {
|
|
147
|
+
if (opts.signal?.aborted) {
|
|
148
|
+
stopReason = "aborted";
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
if (cumulative.totalTokens >= opts.maxTokens) {
|
|
152
|
+
stopReason = "max_tokens";
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
if (cumulative.estimatedCostUsd >= opts.maxCostUsd) {
|
|
156
|
+
stopReason = "max_cost";
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
logger.debug("Agent loop iteration", { iteration: i });
|
|
160
|
+
const chatRequest = {
|
|
161
|
+
...opts.chatRequestOverrides,
|
|
162
|
+
messages,
|
|
163
|
+
tools: toolDefs.length > 0 ? toolDefs : void 0
|
|
164
|
+
};
|
|
165
|
+
const response = await opts.ai.chat(chatRequest);
|
|
166
|
+
lastResponse = response;
|
|
167
|
+
cumulative.promptTokens += response.usage.promptTokens;
|
|
168
|
+
cumulative.completionTokens += response.usage.completionTokens;
|
|
169
|
+
cumulative.totalTokens += response.usage.totalTokens;
|
|
170
|
+
cumulative.estimatedCostUsd += response.usage.estimatedCostUsd;
|
|
171
|
+
cumulative.iterations = i;
|
|
172
|
+
const assistantMessage = response.choices[0]?.message;
|
|
173
|
+
if (!assistantMessage) {
|
|
174
|
+
stopReason = "error";
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
messages.push(assistantMessage);
|
|
178
|
+
if (response.finishReason !== "tool_calls") {
|
|
179
|
+
stopReason = mapFinishReason(response.finishReason);
|
|
180
|
+
const event2 = {
|
|
181
|
+
iteration: i,
|
|
182
|
+
response,
|
|
183
|
+
toolCalls: [],
|
|
184
|
+
cumulativeUsage: { ...cumulative },
|
|
185
|
+
messages: [...messages]
|
|
186
|
+
};
|
|
187
|
+
iterations.push(event2);
|
|
188
|
+
await opts.onIteration?.(event2);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
const toolCalls = assistantMessage.toolCalls ?? [];
|
|
192
|
+
cumulative.toolCallCount += toolCalls.length;
|
|
193
|
+
const toolResults = await Promise.all(
|
|
194
|
+
toolCalls.map(
|
|
195
|
+
(tc) => executeToolCall(
|
|
196
|
+
tc,
|
|
197
|
+
executorMap,
|
|
198
|
+
opts.cache,
|
|
199
|
+
opts.cacheKeyPrefix,
|
|
200
|
+
opts.cacheTtlSeconds
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
);
|
|
204
|
+
for (const tr of toolResults) {
|
|
205
|
+
messages.push({
|
|
206
|
+
role: "tool",
|
|
207
|
+
content: tr.result,
|
|
208
|
+
toolCallId: tr.toolCall.id
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
const event = {
|
|
212
|
+
iteration: i,
|
|
213
|
+
response,
|
|
214
|
+
toolCalls: toolResults,
|
|
215
|
+
cumulativeUsage: { ...cumulative },
|
|
216
|
+
messages: [...messages]
|
|
217
|
+
};
|
|
218
|
+
iterations.push(event);
|
|
219
|
+
const callbackResult = await opts.onIteration?.(event);
|
|
220
|
+
if (callbackResult === false) {
|
|
221
|
+
stopReason = "callback_abort";
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
if (i === opts.maxIterations) {
|
|
225
|
+
stopReason = "max_iterations";
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
response: lastResponse,
|
|
230
|
+
messages,
|
|
231
|
+
stopReason,
|
|
232
|
+
iterations,
|
|
233
|
+
usage: cumulative
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// src/agent/agent-tracer.ts
|
|
238
|
+
function createAgentTracer(options) {
|
|
239
|
+
const { tracing, agentId } = options;
|
|
240
|
+
return {
|
|
241
|
+
async traceLoop(fn) {
|
|
242
|
+
return tracing.withSpanAsync(
|
|
243
|
+
"agent.loop",
|
|
244
|
+
async (span) => {
|
|
245
|
+
span.setAttribute("agent.id", agentId);
|
|
246
|
+
return fn(span);
|
|
247
|
+
},
|
|
248
|
+
{ kind: "internal" }
|
|
249
|
+
);
|
|
250
|
+
},
|
|
251
|
+
async traceIteration(iteration, fn) {
|
|
252
|
+
return tracing.withSpanAsync(
|
|
253
|
+
"agent.iteration",
|
|
254
|
+
async (span) => {
|
|
255
|
+
span.setAttributes({
|
|
256
|
+
"agent.id": agentId,
|
|
257
|
+
"agent.iteration": iteration
|
|
258
|
+
});
|
|
259
|
+
return fn(span);
|
|
260
|
+
},
|
|
261
|
+
{ kind: "internal" }
|
|
262
|
+
);
|
|
263
|
+
},
|
|
264
|
+
async traceToolCall(toolName, fn) {
|
|
265
|
+
return tracing.withSpanAsync(
|
|
266
|
+
`agent.tool.${toolName}`,
|
|
267
|
+
async (span) => {
|
|
268
|
+
span.setAttributes({
|
|
269
|
+
"agent.id": agentId,
|
|
270
|
+
"agent.tool.name": toolName
|
|
271
|
+
});
|
|
272
|
+
const result = await fn(span);
|
|
273
|
+
span.setAttributes({
|
|
274
|
+
"agent.tool.duration_ms": result.durationMs,
|
|
275
|
+
"agent.tool.success": result.success,
|
|
276
|
+
"agent.tool.cached": result.cached
|
|
277
|
+
});
|
|
278
|
+
if (result.error) {
|
|
279
|
+
span.setAttribute("agent.tool.error", result.error);
|
|
280
|
+
}
|
|
281
|
+
return result;
|
|
282
|
+
},
|
|
283
|
+
{ kind: "internal" }
|
|
284
|
+
);
|
|
285
|
+
},
|
|
286
|
+
traceDecision(span, attrs) {
|
|
287
|
+
span.setAttributes({
|
|
288
|
+
"agent.decision.finish_reason": attrs.finishReason,
|
|
289
|
+
"agent.decision.tool_count": attrs.toolCallCount,
|
|
290
|
+
"agent.decision.total_tokens": attrs.cumulativeUsage.totalTokens,
|
|
291
|
+
"agent.decision.cost_usd": attrs.cumulativeUsage.estimatedCostUsd,
|
|
292
|
+
"agent.decision.iterations": attrs.cumulativeUsage.iterations
|
|
293
|
+
});
|
|
294
|
+
span.addEvent("agent.decision", {
|
|
295
|
+
finish_reason: attrs.finishReason,
|
|
296
|
+
tool_count: attrs.toolCallCount
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// src/agent/agent-usage.ts
|
|
303
|
+
function createAgentUsageTracker(options) {
|
|
304
|
+
const { usage, agentId, tenantId, userId } = options;
|
|
305
|
+
return {
|
|
306
|
+
async recordIteration(params) {
|
|
307
|
+
return usage.record({
|
|
308
|
+
tenantId,
|
|
309
|
+
userId,
|
|
310
|
+
category: params.category ?? "chat",
|
|
311
|
+
provider: params.provider,
|
|
312
|
+
model: params.model,
|
|
313
|
+
inputTokens: params.usage.promptTokens,
|
|
314
|
+
outputTokens: params.usage.completionTokens,
|
|
315
|
+
totalTokens: params.usage.totalTokens,
|
|
316
|
+
costUsd: params.usage.estimatedCostUsd,
|
|
317
|
+
latencyMs: params.latencyMs ?? 0,
|
|
318
|
+
success: params.success ?? true,
|
|
319
|
+
error: params.error,
|
|
320
|
+
metadata: { agentId }
|
|
321
|
+
});
|
|
322
|
+
},
|
|
323
|
+
createBudgetCallback(budget) {
|
|
324
|
+
return async (event) => {
|
|
325
|
+
const response = event.response;
|
|
326
|
+
await usage.record({
|
|
327
|
+
tenantId,
|
|
328
|
+
userId,
|
|
329
|
+
category: "chat",
|
|
330
|
+
provider: response.provider,
|
|
331
|
+
model: response.model,
|
|
332
|
+
inputTokens: response.usage.promptTokens,
|
|
333
|
+
outputTokens: response.usage.completionTokens,
|
|
334
|
+
totalTokens: response.usage.totalTokens,
|
|
335
|
+
costUsd: response.usage.estimatedCostUsd,
|
|
336
|
+
latencyMs: 0,
|
|
337
|
+
success: true,
|
|
338
|
+
metadata: { agentId, iteration: event.iteration }
|
|
339
|
+
});
|
|
340
|
+
if (budget) {
|
|
341
|
+
if (budget.maxCostUsd !== void 0 && event.cumulativeUsage.estimatedCostUsd >= budget.maxCostUsd) {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
if (budget.maxTokens !== void 0 && event.cumulativeUsage.totalTokens >= budget.maxTokens) {
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/agent/traced-ai.ts
|
|
354
|
+
function createTracedAI(options) {
|
|
355
|
+
const { ai, tracing } = options;
|
|
356
|
+
return {
|
|
357
|
+
async chat(request) {
|
|
358
|
+
return tracing.withSpanAsync(
|
|
359
|
+
"ai.chat",
|
|
360
|
+
async (span) => {
|
|
361
|
+
const start = Date.now();
|
|
362
|
+
if (request.model) {
|
|
363
|
+
span.setAttribute("ai.model", request.model);
|
|
364
|
+
}
|
|
365
|
+
try {
|
|
366
|
+
const response = await ai.chat(request);
|
|
367
|
+
span.setAttributes({
|
|
368
|
+
"ai.provider": response.provider,
|
|
369
|
+
"ai.model": response.model,
|
|
370
|
+
"ai.input_tokens": response.usage.promptTokens,
|
|
371
|
+
"ai.output_tokens": response.usage.completionTokens,
|
|
372
|
+
"ai.total_tokens": response.usage.totalTokens,
|
|
373
|
+
"ai.cost_usd": response.usage.estimatedCostUsd,
|
|
374
|
+
"ai.finish_reason": response.finishReason,
|
|
375
|
+
"ai.latency_ms": Date.now() - start
|
|
376
|
+
});
|
|
377
|
+
span.setStatus({ code: "ok" });
|
|
378
|
+
return response;
|
|
379
|
+
} catch (err) {
|
|
380
|
+
span.setAttributes({
|
|
381
|
+
"ai.latency_ms": Date.now() - start
|
|
382
|
+
});
|
|
383
|
+
if (err instanceof Error) {
|
|
384
|
+
span.recordException(err);
|
|
385
|
+
}
|
|
386
|
+
span.setStatus({
|
|
387
|
+
code: "error",
|
|
388
|
+
message: err instanceof Error ? err.message : String(err)
|
|
389
|
+
});
|
|
390
|
+
throw err;
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
{ kind: "client" }
|
|
394
|
+
);
|
|
395
|
+
},
|
|
396
|
+
async *chatStream(request) {
|
|
397
|
+
yield* ai.chatStream(request);
|
|
398
|
+
},
|
|
399
|
+
async chatWithCallback(request, callback) {
|
|
400
|
+
return tracing.withSpanAsync(
|
|
401
|
+
"ai.chatWithCallback",
|
|
402
|
+
async (span) => {
|
|
403
|
+
const start = Date.now();
|
|
404
|
+
if (request.model) {
|
|
405
|
+
span.setAttribute("ai.model", request.model);
|
|
406
|
+
}
|
|
407
|
+
try {
|
|
408
|
+
const response = await ai.chatWithCallback(request, callback);
|
|
409
|
+
span.setAttributes({
|
|
410
|
+
"ai.provider": response.provider,
|
|
411
|
+
"ai.model": response.model,
|
|
412
|
+
"ai.input_tokens": response.usage.promptTokens,
|
|
413
|
+
"ai.output_tokens": response.usage.completionTokens,
|
|
414
|
+
"ai.total_tokens": response.usage.totalTokens,
|
|
415
|
+
"ai.cost_usd": response.usage.estimatedCostUsd,
|
|
416
|
+
"ai.finish_reason": response.finishReason,
|
|
417
|
+
"ai.latency_ms": Date.now() - start
|
|
418
|
+
});
|
|
419
|
+
span.setStatus({ code: "ok" });
|
|
420
|
+
return response;
|
|
421
|
+
} catch (err) {
|
|
422
|
+
span.setAttributes({
|
|
423
|
+
"ai.latency_ms": Date.now() - start
|
|
424
|
+
});
|
|
425
|
+
if (err instanceof Error) {
|
|
426
|
+
span.recordException(err);
|
|
427
|
+
}
|
|
428
|
+
span.setStatus({
|
|
429
|
+
code: "error",
|
|
430
|
+
message: err instanceof Error ? err.message : String(err)
|
|
431
|
+
});
|
|
432
|
+
throw err;
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
{ kind: "client" }
|
|
436
|
+
);
|
|
437
|
+
},
|
|
438
|
+
// Pass-through methods (no tracing needed for non-chat operations in v1)
|
|
439
|
+
async complete(request) {
|
|
440
|
+
return ai.complete(request);
|
|
441
|
+
},
|
|
442
|
+
async *completeStream(request) {
|
|
443
|
+
yield* ai.completeStream(request);
|
|
444
|
+
},
|
|
445
|
+
async embed(request) {
|
|
446
|
+
return ai.embed(request);
|
|
447
|
+
},
|
|
448
|
+
async similarity(text1, text2, model) {
|
|
449
|
+
return ai.similarity(text1, text2, model);
|
|
450
|
+
},
|
|
451
|
+
async listModels() {
|
|
452
|
+
return ai.listModels();
|
|
453
|
+
},
|
|
454
|
+
async getModel(modelId) {
|
|
455
|
+
return ai.getModel(modelId);
|
|
456
|
+
},
|
|
457
|
+
async supportsCapability(modelId, capability) {
|
|
458
|
+
return ai.supportsCapability(modelId, capability);
|
|
459
|
+
},
|
|
460
|
+
async estimateTokens(text, model) {
|
|
461
|
+
return ai.estimateTokens(text, model);
|
|
462
|
+
},
|
|
463
|
+
async estimateCost(request) {
|
|
464
|
+
return ai.estimateCost(request);
|
|
465
|
+
},
|
|
466
|
+
async healthCheck() {
|
|
467
|
+
return ai.healthCheck();
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
472
|
+
0 && (module.exports = {
|
|
473
|
+
DEFAULT_AGENT_LOOP_OPTIONS,
|
|
474
|
+
createAgentTracer,
|
|
475
|
+
createAgentUsageTracker,
|
|
476
|
+
createTracedAI,
|
|
477
|
+
runAgentLoop
|
|
478
|
+
});
|
|
479
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agents.ts","../src/interfaces/ILogger.ts","../src/agent/agent-loop.ts","../src/agent/agent-tracer.ts","../src/agent/agent-usage.ts","../src/agent/traced-ai.ts"],"sourcesContent":["/**\n * Agents Module\n *\n * Multi-turn tool-calling agent runtime with observability and cost tracking.\n *\n * This sub-path export (`@digilogiclabs/platform-core/agents`) is lightweight —\n * it only depends on IAI, ICache, ITracing, IAIUsage, and ILogger interfaces.\n * It does NOT pull in database, storage, email, payment, or AI provider adapters.\n *\n * @example\n * ```typescript\n * import { runAgentLoop, createTracedAI, createAgentTracer } from '@digilogiclabs/platform-core/agents';\n * ```\n */\n\n// Core agent loop\nexport {\n runAgentLoop,\n DEFAULT_AGENT_LOOP_OPTIONS,\n type AgentTool,\n type ToolExecutor,\n type AgentLoopOptions,\n type AgentLoopResult,\n type AgentStopReason,\n type AgentIterationEvent,\n type AgentIterationCallback,\n type AgentToolResult,\n type AgentCumulativeUsage,\n} from \"./agent/agent-loop\";\n\n// Agent tracing helpers\nexport {\n createAgentTracer,\n type AgentTracer,\n type AgentTracerOptions,\n} from \"./agent/agent-tracer\";\n\n// Agent usage tracking\nexport {\n createAgentUsageTracker,\n type AgentUsageTracker,\n type AgentUsageTrackerOptions,\n type AgentUsageRecordParams,\n type AgentBudget,\n} from \"./agent/agent-usage\";\n\n// Auto-instrumented AI wrapper\nexport {\n createTracedAI,\n type TracedAIOptions,\n} from \"./agent/traced-ai\";\n","/**\n * Logger Interface\n * Standardizes logging across the platform\n */\n\n/**\n * Log levels in order of severity\n */\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\n/**\n * Metadata that can be attached to log entries\n */\nexport interface LogMeta {\n /** Error object if logging an error */\n error?: Error;\n /** Duration in milliseconds (for timing operations) */\n duration?: number;\n /** Request ID for tracing */\n requestId?: string;\n /** User ID if applicable */\n userId?: string;\n /** Any additional key-value pairs */\n [key: string]: unknown;\n}\n\n/**\n * A structured log entry\n */\nexport interface LogEntry {\n /** Log level */\n level: LogLevel;\n /** Log message */\n message: string;\n /** When the log was created */\n timestamp: Date;\n /** Optional metadata */\n meta?: LogMeta;\n /** Logger context (e.g., service name) */\n context?: Record<string, unknown>;\n}\n\n/**\n * Logger interface for structured logging\n */\nexport interface ILogger {\n /**\n * Log a debug message (for development/troubleshooting)\n */\n debug(message: string, meta?: LogMeta): void;\n\n /**\n * Log an informational message\n */\n info(message: string, meta?: LogMeta): void;\n\n /**\n * Log a warning message\n */\n warn(message: string, meta?: LogMeta): void;\n\n /**\n * Log an error message\n */\n error(message: string, meta?: LogMeta): void;\n\n /**\n * Create a child logger with additional context\n * @param context Additional context to include in all logs from this child\n */\n child(context: Record<string, unknown>): ILogger;\n}\n\n/**\n * Configuration options for loggers\n */\nexport interface LoggerConfig {\n /** Minimum level to log */\n level?: LogLevel;\n /** Whether to pretty print (for development) */\n pretty?: boolean;\n /** Service name to include in logs */\n service?: string;\n /** Environment name */\n environment?: string;\n}\n\n/**\n * Console logger implementation (for development)\n */\nexport class ConsoleLogger implements ILogger {\n private context: Record<string, unknown>;\n private level: LogLevel;\n\n private static levelPriority: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n };\n\n constructor(config: LoggerConfig = {}) {\n this.context = {\n service: config.service,\n environment: config.environment,\n };\n this.level = config.level || \"info\";\n }\n\n private shouldLog(level: LogLevel): boolean {\n return (\n ConsoleLogger.levelPriority[level] >=\n ConsoleLogger.levelPriority[this.level]\n );\n }\n\n private log(level: LogLevel, message: string, meta?: LogMeta): void {\n if (!this.shouldLog(level)) return;\n\n const entry: LogEntry = {\n level,\n message,\n timestamp: new Date(),\n meta,\n context: this.context,\n };\n\n const prefix = `[${entry.timestamp.toISOString()}] [${level.toUpperCase()}]`;\n const contextStr =\n Object.keys(this.context).length > 0\n ? ` [${Object.entries(this.context)\n .map(([k, v]) => `${k}=${v}`)\n .join(\" \")}]`\n : \"\";\n\n switch (level) {\n case \"debug\":\n console.debug(`${prefix}${contextStr} ${message}`, meta || \"\");\n break;\n case \"info\":\n console.info(`${prefix}${contextStr} ${message}`, meta || \"\");\n break;\n case \"warn\":\n console.warn(`${prefix}${contextStr} ${message}`, meta || \"\");\n break;\n case \"error\":\n console.error(`${prefix}${contextStr} ${message}`, meta || \"\");\n if (meta?.error) {\n console.error(meta.error);\n }\n break;\n }\n }\n\n debug(message: string, meta?: LogMeta): void {\n this.log(\"debug\", message, meta);\n }\n\n info(message: string, meta?: LogMeta): void {\n this.log(\"info\", message, meta);\n }\n\n warn(message: string, meta?: LogMeta): void {\n this.log(\"warn\", message, meta);\n }\n\n error(message: string, meta?: LogMeta): void {\n this.log(\"error\", message, meta);\n }\n\n child(context: Record<string, unknown>): ILogger {\n const childLogger = new ConsoleLogger({ level: this.level });\n childLogger.context = { ...this.context, ...context };\n return childLogger;\n }\n}\n\n/**\n * No-op logger for testing or when logging is disabled\n */\nexport class NoopLogger implements ILogger {\n debug(): void {}\n info(): void {}\n warn(): void {}\n error(): void {}\n child(): ILogger {\n return this;\n }\n}\n","/**\n * Agent Loop — Multi-turn tool-calling orchestration\n *\n * Runs an IAI chat → tool execution → repeat loop until the AI stops,\n * a budget is hit, or the caller aborts.\n */\n\nimport type {\n IAI,\n AIMessage,\n AITool,\n AIToolCall,\n AIChatRequest,\n AIChatResponse,\n AIFinishReason,\n} from \"../interfaces/IAI\";\nimport type { ICache } from \"../interfaces/ICache\";\nimport type { ILogger } from \"../interfaces/ILogger\";\nimport { NoopLogger } from \"../interfaces/ILogger\";\n\n// ═══════════════════════════════════════════════════════════════\n// TYPES\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Function that executes a tool call and returns a string result.\n * Receives the parsed arguments (from JSON) and the raw tool call.\n */\nexport type ToolExecutor = (\n args: Record<string, unknown>,\n toolCall: AIToolCall,\n) => Promise<string>;\n\n/**\n * Tool definition paired with its executor.\n */\nexport interface AgentTool {\n /** The AI tool definition (JSON Schema for the function) */\n definition: AITool;\n /** The function that executes this tool */\n execute: ToolExecutor;\n}\n\n/**\n * Result of a single tool call execution.\n */\nexport interface AgentToolResult {\n /** The original tool call from the AI */\n toolCall: AIToolCall;\n /** The string result returned by the executor */\n result: string;\n /** Whether the tool execution succeeded */\n success: boolean;\n /** Error message if the tool failed */\n error?: string;\n /** Execution duration in ms */\n durationMs: number;\n /** Whether the result came from cache */\n cached: boolean;\n}\n\n/**\n * Cumulative usage across all iterations.\n */\nexport interface AgentCumulativeUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n estimatedCostUsd: number;\n iterations: number;\n toolCallCount: number;\n}\n\n/**\n * Event emitted after each iteration of the agent loop.\n */\nexport interface AgentIterationEvent {\n /** 1-based iteration number */\n iteration: number;\n /** The AI response for this iteration */\n response: AIChatResponse;\n /** Tool calls made in this iteration (empty if no tool calls) */\n toolCalls: AgentToolResult[];\n /** Cumulative usage across all iterations */\n cumulativeUsage: AgentCumulativeUsage;\n /** Full conversation so far */\n messages: AIMessage[];\n}\n\n/**\n * Callback invoked after each iteration.\n * Return `false` to abort the loop.\n */\nexport type AgentIterationCallback = (\n event: AgentIterationEvent,\n) => void | false | Promise<void | false>;\n\n/**\n * Why the agent loop stopped.\n */\nexport type AgentStopReason =\n | \"stop\"\n | \"max_iterations\"\n | \"max_tokens\"\n | \"max_cost\"\n | \"aborted\"\n | \"callback_abort\"\n | \"length\"\n | \"content_filter\"\n | \"error\";\n\n/**\n * Options for runAgentLoop.\n */\nexport interface AgentLoopOptions {\n /** The IAI instance to call */\n ai: IAI;\n /** Initial messages (system + user prompt) */\n messages: AIMessage[];\n /** Tool definitions with executors */\n tools: AgentTool[];\n /** Maximum iterations before forced stop @default 10 */\n maxIterations: number;\n /** Maximum cumulative total tokens @default Infinity */\n maxTokens: number;\n /** Maximum cumulative cost in USD @default Infinity */\n maxCostUsd: number;\n /** Optional cache for tool results */\n cache?: ICache;\n /** Cache TTL in seconds for tool results @default 300 */\n cacheTtlSeconds: number;\n /** Cache key prefix @default \"agent:tool:\" */\n cacheKeyPrefix: string;\n /** Callback after each iteration */\n onIteration?: AgentIterationCallback;\n /** AbortSignal for cancellation */\n signal?: AbortSignal;\n /** Logger for observability */\n logger?: ILogger;\n /** Additional fields for AIChatRequest (model, temperature, etc.) */\n chatRequestOverrides?: Partial<Omit<AIChatRequest, \"messages\" | \"tools\">>;\n}\n\n/**\n * Result of a completed agent loop.\n */\nexport interface AgentLoopResult {\n /** Final AI response */\n response: AIChatResponse;\n /** Complete conversation history including all tool messages */\n messages: AIMessage[];\n /** Why the loop stopped */\n stopReason: AgentStopReason;\n /** Per-iteration details */\n iterations: AgentIterationEvent[];\n /** Cumulative usage summary */\n usage: AgentCumulativeUsage;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// DEFAULTS\n// ═══════════════════════════════════════════════════════════════\n\nexport const DEFAULT_AGENT_LOOP_OPTIONS: Pick<\n AgentLoopOptions,\n | \"maxIterations\"\n | \"maxTokens\"\n | \"maxCostUsd\"\n | \"cacheTtlSeconds\"\n | \"cacheKeyPrefix\"\n> = {\n maxIterations: 10,\n maxTokens: Infinity,\n maxCostUsd: Infinity,\n cacheTtlSeconds: 300,\n cacheKeyPrefix: \"agent:tool:\",\n};\n\n// ═══════════════════════════════════════════════════════════════\n// HELPERS\n// ═══════════════════════════════════════════════════════════════\n\nfunction mapFinishReason(reason: AIFinishReason): AgentStopReason {\n switch (reason) {\n case \"stop\":\n return \"stop\";\n case \"length\":\n return \"length\";\n case \"content_filter\":\n return \"content_filter\";\n case \"tool_calls\":\n return \"stop\"; // shouldn't reach here in normal flow\n case \"error\":\n default:\n return \"error\";\n }\n}\n\nasync function executeToolCall(\n toolCall: AIToolCall,\n executorMap: Map<string, AgentTool>,\n cache: ICache | undefined,\n cacheKeyPrefix: string,\n cacheTtlSeconds: number,\n): Promise<AgentToolResult> {\n const start = Date.now();\n const executor = executorMap.get(toolCall.function.name);\n\n if (!executor) {\n return {\n toolCall,\n result: `Error: Unknown tool \"${toolCall.function.name}\"`,\n success: false,\n error: `Unknown tool: ${toolCall.function.name}`,\n durationMs: Date.now() - start,\n cached: false,\n };\n }\n\n // Check cache\n if (cache) {\n const cacheKey =\n cacheKeyPrefix + toolCall.function.name + \":\" + toolCall.function.arguments;\n try {\n const cached = await cache.get<string>(cacheKey);\n if (cached !== null) {\n return {\n toolCall,\n result: cached,\n success: true,\n durationMs: Date.now() - start,\n cached: true,\n };\n }\n } catch {\n // Cache read failure is non-fatal\n }\n }\n\n // Execute\n try {\n const parsed = JSON.parse(toolCall.function.arguments) as Record<\n string,\n unknown\n >;\n const result = await executor.execute(parsed, toolCall);\n\n // Store in cache\n if (cache) {\n const cacheKey =\n cacheKeyPrefix + toolCall.function.name + \":\" + toolCall.function.arguments;\n await cache.set(cacheKey, result, cacheTtlSeconds).catch(() => {});\n }\n\n return {\n toolCall,\n result,\n success: true,\n durationMs: Date.now() - start,\n cached: false,\n };\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n return {\n toolCall,\n result: `Error: ${errorMsg}`,\n success: false,\n error: errorMsg,\n durationMs: Date.now() - start,\n cached: false,\n };\n }\n}\n\n// ═══════════════════════════════════════════════════════════════\n// MAIN FUNCTION\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Run a multi-turn tool-calling agent loop.\n *\n * @example\n * ```typescript\n * const result = await runAgentLoop({\n * ai: platform.ai,\n * messages: [\n * { role: 'system', content: 'You are a helpful assistant.' },\n * { role: 'user', content: 'What is the weather in London?' },\n * ],\n * tools: [{\n * definition: {\n * type: 'function',\n * function: {\n * name: 'get_weather',\n * description: 'Get the weather for a city',\n * parameters: { type: 'object', properties: { city: { type: 'string' } } },\n * },\n * },\n * execute: async (args) => {\n * const weather = await fetchWeather(args.city as string);\n * return JSON.stringify(weather);\n * },\n * }],\n * });\n *\n * console.log(result.stopReason); // \"stop\"\n * console.log(result.usage.totalTokens); // cumulative tokens\n * ```\n */\nexport async function runAgentLoop(\n options: Partial<AgentLoopOptions> &\n Pick<AgentLoopOptions, \"ai\" | \"messages\" | \"tools\">,\n): Promise<AgentLoopResult> {\n const opts = { ...DEFAULT_AGENT_LOOP_OPTIONS, ...options };\n const logger = opts.logger ?? new NoopLogger();\n\n // Build tool definitions and executor map\n const toolDefs: AITool[] = opts.tools.map((t) => t.definition);\n const executorMap = new Map<string, AgentTool>();\n for (const tool of opts.tools) {\n executorMap.set(tool.definition.function.name, tool);\n }\n\n // Mutable state\n const messages: AIMessage[] = [...opts.messages];\n const iterations: AgentIterationEvent[] = [];\n const cumulative: AgentCumulativeUsage = {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n estimatedCostUsd: 0,\n iterations: 0,\n toolCallCount: 0,\n };\n\n let lastResponse: AIChatResponse | undefined;\n let stopReason: AgentStopReason = \"stop\";\n\n for (let i = 1; i <= opts.maxIterations; i++) {\n // Check abort signal\n if (opts.signal?.aborted) {\n stopReason = \"aborted\";\n break;\n }\n\n // Check budgets before calling AI\n if (cumulative.totalTokens >= opts.maxTokens) {\n stopReason = \"max_tokens\";\n break;\n }\n if (cumulative.estimatedCostUsd >= opts.maxCostUsd) {\n stopReason = \"max_cost\";\n break;\n }\n\n // Call ai.chat()\n logger.debug(\"Agent loop iteration\", { iteration: i });\n const chatRequest: AIChatRequest = {\n ...opts.chatRequestOverrides,\n messages,\n tools: toolDefs.length > 0 ? toolDefs : undefined,\n };\n\n const response = await opts.ai.chat(chatRequest);\n lastResponse = response;\n\n // Accumulate usage\n cumulative.promptTokens += response.usage.promptTokens;\n cumulative.completionTokens += response.usage.completionTokens;\n cumulative.totalTokens += response.usage.totalTokens;\n cumulative.estimatedCostUsd += response.usage.estimatedCostUsd;\n cumulative.iterations = i;\n\n // Get assistant message\n const assistantMessage = response.choices[0]?.message;\n if (!assistantMessage) {\n stopReason = \"error\";\n break;\n }\n messages.push(assistantMessage);\n\n // If not tool_calls, we're done\n if (response.finishReason !== \"tool_calls\") {\n stopReason = mapFinishReason(response.finishReason);\n\n const event: AgentIterationEvent = {\n iteration: i,\n response,\n toolCalls: [],\n cumulativeUsage: { ...cumulative },\n messages: [...messages],\n };\n iterations.push(event);\n await opts.onIteration?.(event);\n break;\n }\n\n // Execute tool calls in parallel\n const toolCalls = assistantMessage.toolCalls ?? [];\n cumulative.toolCallCount += toolCalls.length;\n\n const toolResults: AgentToolResult[] = await Promise.all(\n toolCalls.map((tc) =>\n executeToolCall(\n tc,\n executorMap,\n opts.cache,\n opts.cacheKeyPrefix,\n opts.cacheTtlSeconds,\n ),\n ),\n );\n\n // Append tool result messages\n for (const tr of toolResults) {\n messages.push({\n role: \"tool\",\n content: tr.result,\n toolCallId: tr.toolCall.id,\n });\n }\n\n // Build iteration event\n const event: AgentIterationEvent = {\n iteration: i,\n response,\n toolCalls: toolResults,\n cumulativeUsage: { ...cumulative },\n messages: [...messages],\n };\n iterations.push(event);\n\n // Fire callback\n const callbackResult = await opts.onIteration?.(event);\n if (callbackResult === false) {\n stopReason = \"callback_abort\";\n break;\n }\n\n // Last iteration check\n if (i === opts.maxIterations) {\n stopReason = \"max_iterations\";\n }\n }\n\n return {\n response: lastResponse!,\n messages,\n stopReason,\n iterations,\n usage: cumulative,\n };\n}\n","/**\n * Agent Tracer — OTEL span helpers for agent observability\n *\n * Wraps ITracing with standardized agent-specific span attributes\n * following OpenTelemetry semantic conventions.\n */\n\nimport type { ITracing, ISpan } from \"../interfaces/ITracing\";\nimport type { AgentToolResult, AgentCumulativeUsage } from \"./agent-loop\";\n\n// ═══════════════════════════════════════════════════════════════\n// TYPES\n// ═══════════════════════════════════════════════════════════════\n\nexport interface AgentTracerOptions {\n /** The ITracing instance */\n tracing: ITracing;\n /** Agent identifier for span attributes */\n agentId: string;\n}\n\nexport interface AgentTracer {\n /**\n * Wrap an entire agent loop execution in a span.\n * Sets `agent.id` on the span.\n */\n traceLoop<T>(fn: (span: ISpan) => Promise<T>): Promise<T>;\n\n /**\n * Wrap a single iteration in a span.\n * Sets `agent.iteration` on the span.\n */\n traceIteration(\n iteration: number,\n fn: (span: ISpan) => Promise<void>,\n ): Promise<void>;\n\n /**\n * Wrap a single tool call execution in a span.\n * Sets `agent.tool.name`, `agent.tool.duration_ms`, `agent.tool.success`, `agent.tool.cached`.\n */\n traceToolCall(\n toolName: string,\n fn: (span: ISpan) => Promise<AgentToolResult>,\n ): Promise<AgentToolResult>;\n\n /**\n * Record a decision event on the current span.\n */\n traceDecision(\n span: ISpan,\n attrs: {\n finishReason: string;\n toolCallCount: number;\n cumulativeUsage: AgentCumulativeUsage;\n },\n ): void;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// IMPLEMENTATION\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Create an agent tracer with standardized OTEL attributes.\n *\n * @example\n * ```typescript\n * const tracer = createAgentTracer({ tracing: platform.tracing, agentId: 'weather-agent' });\n *\n * const result = await tracer.traceLoop(async (span) => {\n * return await runAgentLoop({ ... });\n * });\n * ```\n */\nexport function createAgentTracer(options: AgentTracerOptions): AgentTracer {\n const { tracing, agentId } = options;\n\n return {\n async traceLoop<T>(fn: (span: ISpan) => Promise<T>): Promise<T> {\n return tracing.withSpanAsync(\n \"agent.loop\",\n async (span) => {\n span.setAttribute(\"agent.id\", agentId);\n return fn(span);\n },\n { kind: \"internal\" },\n );\n },\n\n async traceIteration(\n iteration: number,\n fn: (span: ISpan) => Promise<void>,\n ): Promise<void> {\n return tracing.withSpanAsync(\n \"agent.iteration\",\n async (span) => {\n span.setAttributes({\n \"agent.id\": agentId,\n \"agent.iteration\": iteration,\n });\n return fn(span);\n },\n { kind: \"internal\" },\n );\n },\n\n async traceToolCall(\n toolName: string,\n fn: (span: ISpan) => Promise<AgentToolResult>,\n ): Promise<AgentToolResult> {\n return tracing.withSpanAsync(\n `agent.tool.${toolName}`,\n async (span) => {\n span.setAttributes({\n \"agent.id\": agentId,\n \"agent.tool.name\": toolName,\n });\n const result = await fn(span);\n span.setAttributes({\n \"agent.tool.duration_ms\": result.durationMs,\n \"agent.tool.success\": result.success,\n \"agent.tool.cached\": result.cached,\n });\n if (result.error) {\n span.setAttribute(\"agent.tool.error\", result.error);\n }\n return result;\n },\n { kind: \"internal\" },\n );\n },\n\n traceDecision(\n span: ISpan,\n attrs: {\n finishReason: string;\n toolCallCount: number;\n cumulativeUsage: AgentCumulativeUsage;\n },\n ): void {\n span.setAttributes({\n \"agent.decision.finish_reason\": attrs.finishReason,\n \"agent.decision.tool_count\": attrs.toolCallCount,\n \"agent.decision.total_tokens\": attrs.cumulativeUsage.totalTokens,\n \"agent.decision.cost_usd\": attrs.cumulativeUsage.estimatedCostUsd,\n \"agent.decision.iterations\": attrs.cumulativeUsage.iterations,\n });\n span.addEvent(\"agent.decision\", {\n finish_reason: attrs.finishReason,\n tool_count: attrs.toolCallCount,\n });\n },\n };\n}\n","/**\n * Agent Usage Tracker — Per-agent cost tracking via IAIUsage\n *\n * Tags usage records with agentId in metadata for per-agent attribution.\n * No changes to IAIUsage interface required.\n */\n\nimport type { IAIUsage, UsageRecord, UsageCategory } from \"../interfaces/IAIUsage\";\nimport type { AIUsageInfo } from \"../interfaces/IAI\";\nimport type { AgentIterationCallback, AgentIterationEvent } from \"./agent-loop\";\n\n// ═══════════════════════════════════════════════════════════════\n// TYPES\n// ═══════════════════════════════════════════════════════════════\n\nexport interface AgentUsageTrackerOptions {\n /** The IAIUsage instance */\n usage: IAIUsage;\n /** Agent identifier to tag on all records */\n agentId: string;\n /** Tenant ID for usage records */\n tenantId: string;\n /** Optional user ID */\n userId?: string;\n}\n\nexport interface AgentUsageRecordParams {\n /** AI provider name */\n provider: string;\n /** Model used */\n model: string;\n /** Token usage info from the AI response */\n usage: AIUsageInfo;\n /** Usage category @default \"chat\" */\n category?: UsageCategory;\n /** Whether the request succeeded @default true */\n success?: boolean;\n /** Request latency in ms */\n latencyMs?: number;\n /** Error message if failed */\n error?: string;\n}\n\nexport interface AgentBudget {\n /** Maximum cumulative cost in USD */\n maxCostUsd?: number;\n /** Maximum cumulative tokens */\n maxTokens?: number;\n}\n\nexport interface AgentUsageTracker {\n /**\n * Record a single AI call's usage, tagged with agentId in metadata.\n */\n recordIteration(params: AgentUsageRecordParams): Promise<UsageRecord>;\n\n /**\n * Returns an AgentIterationCallback suitable for runAgentLoop's onIteration.\n * Records usage for each iteration and returns false when budget is exceeded.\n */\n createBudgetCallback(budget?: AgentBudget): AgentIterationCallback;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// IMPLEMENTATION\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Create a usage tracker that tags all records with an agent ID.\n *\n * @example\n * ```typescript\n * const tracker = createAgentUsageTracker({\n * usage: platform.aiUsage,\n * agentId: 'weather-agent',\n * tenantId: 'tenant_123',\n * });\n *\n * const result = await runAgentLoop({\n * ai, messages, tools,\n * onIteration: tracker.createBudgetCallback({ maxCostUsd: 0.50 }),\n * });\n * ```\n */\nexport function createAgentUsageTracker(\n options: AgentUsageTrackerOptions,\n): AgentUsageTracker {\n const { usage, agentId, tenantId, userId } = options;\n\n return {\n async recordIteration(params: AgentUsageRecordParams): Promise<UsageRecord> {\n return usage.record({\n tenantId,\n userId,\n category: params.category ?? \"chat\",\n provider: params.provider,\n model: params.model,\n inputTokens: params.usage.promptTokens,\n outputTokens: params.usage.completionTokens,\n totalTokens: params.usage.totalTokens,\n costUsd: params.usage.estimatedCostUsd,\n latencyMs: params.latencyMs ?? 0,\n success: params.success ?? true,\n error: params.error,\n metadata: { agentId },\n });\n },\n\n createBudgetCallback(budget?: AgentBudget): AgentIterationCallback {\n return async (event: AgentIterationEvent): Promise<void | false> => {\n // Record usage for this iteration\n const response = event.response;\n await usage.record({\n tenantId,\n userId,\n category: \"chat\",\n provider: response.provider,\n model: response.model,\n inputTokens: response.usage.promptTokens,\n outputTokens: response.usage.completionTokens,\n totalTokens: response.usage.totalTokens,\n costUsd: response.usage.estimatedCostUsd,\n latencyMs: 0,\n success: true,\n metadata: { agentId, iteration: event.iteration },\n });\n\n // Check budget\n if (budget) {\n if (\n budget.maxCostUsd !== undefined &&\n event.cumulativeUsage.estimatedCostUsd >= budget.maxCostUsd\n ) {\n return false;\n }\n if (\n budget.maxTokens !== undefined &&\n event.cumulativeUsage.totalTokens >= budget.maxTokens\n ) {\n return false;\n }\n }\n };\n },\n };\n}\n","/**\n * Traced AI — Auto-instrument any IAI with OTEL spans\n *\n * Wraps an IAI instance so that every chat() call is automatically\n * wrapped in an OTEL span capturing provider, model, tokens, cost,\n * latency, and finish reason.\n */\n\nimport type {\n IAI,\n AIChatRequest,\n AIChatResponse,\n AICompletionRequest,\n AICompletionResponse,\n AIEmbeddingRequest,\n AIEmbeddingResponse,\n AIStreamChunk,\n AIStreamCallback,\n AIModelConfig,\n AIModelType,\n AIProvider,\n} from \"../interfaces/IAI\";\nimport type { ITracing } from \"../interfaces/ITracing\";\n\n// ═══════════════════════════════════════════════════════════════\n// TYPES\n// ═══════════════════════════════════════════════════════════════\n\nexport interface TracedAIOptions {\n /** The IAI instance to wrap */\n ai: IAI;\n /** The ITracing instance */\n tracing: ITracing;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// IMPLEMENTATION\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Wraps an IAI instance with automatic OTEL tracing on chat operations.\n *\n * @example\n * ```typescript\n * const tracedAI = createTracedAI({ ai: platform.ai, tracing: platform.tracing });\n *\n * // Every chat() call now creates an OTEL span with ai.* attributes\n * const response = await tracedAI.chat({ messages: [...] });\n * ```\n */\nexport function createTracedAI(options: TracedAIOptions): IAI {\n const { ai, tracing } = options;\n\n return {\n async chat(request: AIChatRequest): Promise<AIChatResponse> {\n return tracing.withSpanAsync(\n \"ai.chat\",\n async (span) => {\n const start = Date.now();\n if (request.model) {\n span.setAttribute(\"ai.model\", request.model);\n }\n\n try {\n const response = await ai.chat(request);\n span.setAttributes({\n \"ai.provider\": response.provider,\n \"ai.model\": response.model,\n \"ai.input_tokens\": response.usage.promptTokens,\n \"ai.output_tokens\": response.usage.completionTokens,\n \"ai.total_tokens\": response.usage.totalTokens,\n \"ai.cost_usd\": response.usage.estimatedCostUsd,\n \"ai.finish_reason\": response.finishReason,\n \"ai.latency_ms\": Date.now() - start,\n });\n span.setStatus({ code: \"ok\" });\n return response;\n } catch (err) {\n span.setAttributes({\n \"ai.latency_ms\": Date.now() - start,\n });\n if (err instanceof Error) {\n span.recordException(err);\n }\n span.setStatus({\n code: \"error\",\n message: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n },\n { kind: \"client\" },\n );\n },\n\n async *chatStream(request: AIChatRequest): AsyncIterable<AIStreamChunk> {\n // Delegate directly — tracing streaming is complex and deferred to P4\n yield* ai.chatStream(request);\n },\n\n async chatWithCallback(\n request: AIChatRequest,\n callback: AIStreamCallback,\n ): Promise<AIChatResponse> {\n return tracing.withSpanAsync(\n \"ai.chatWithCallback\",\n async (span) => {\n const start = Date.now();\n if (request.model) {\n span.setAttribute(\"ai.model\", request.model);\n }\n\n try {\n const response = await ai.chatWithCallback(request, callback);\n span.setAttributes({\n \"ai.provider\": response.provider,\n \"ai.model\": response.model,\n \"ai.input_tokens\": response.usage.promptTokens,\n \"ai.output_tokens\": response.usage.completionTokens,\n \"ai.total_tokens\": response.usage.totalTokens,\n \"ai.cost_usd\": response.usage.estimatedCostUsd,\n \"ai.finish_reason\": response.finishReason,\n \"ai.latency_ms\": Date.now() - start,\n });\n span.setStatus({ code: \"ok\" });\n return response;\n } catch (err) {\n span.setAttributes({\n \"ai.latency_ms\": Date.now() - start,\n });\n if (err instanceof Error) {\n span.recordException(err);\n }\n span.setStatus({\n code: \"error\",\n message: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n },\n { kind: \"client\" },\n );\n },\n\n // Pass-through methods (no tracing needed for non-chat operations in v1)\n async complete(request: AICompletionRequest): Promise<AICompletionResponse> {\n return ai.complete(request);\n },\n\n async *completeStream(\n request: AICompletionRequest,\n ): AsyncIterable<AIStreamChunk> {\n yield* ai.completeStream(request);\n },\n\n async embed(request: AIEmbeddingRequest): Promise<AIEmbeddingResponse> {\n return ai.embed(request);\n },\n\n async similarity(\n text1: string,\n text2: string,\n model?: string,\n ): Promise<number> {\n return ai.similarity(text1, text2, model);\n },\n\n async listModels(): Promise<AIModelConfig[]> {\n return ai.listModels();\n },\n\n async getModel(modelId: string): Promise<AIModelConfig | null> {\n return ai.getModel(modelId);\n },\n\n async supportsCapability(\n modelId: string,\n capability: AIModelType,\n ): Promise<boolean> {\n return ai.supportsCapability(modelId, capability);\n },\n\n async estimateTokens(text: string, model?: string): Promise<number> {\n return ai.estimateTokens(text, model);\n },\n\n async estimateCost(request: AIChatRequest | AICompletionRequest | AIEmbeddingRequest): Promise<number> {\n return ai.estimateCost(request);\n },\n\n async healthCheck(): Promise<{\n healthy: boolean;\n providers: Record<\n AIProvider,\n { available: boolean; latencyMs?: number; error?: string }\n >;\n }> {\n return ai.healthCheck();\n },\n };\n}\n"],"mappings":"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","names":["event"]}
|