@niadra/sdk 0.1.1 → 0.7.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.
Files changed (133) hide show
  1. package/CHANGELOG.md +160 -68
  2. package/README.md +451 -22
  3. package/dist/ai-sdk.cjs +1037 -0
  4. package/dist/ai-sdk.cjs.map +1 -0
  5. package/dist/ai-sdk.d.cts +118 -0
  6. package/dist/ai-sdk.d.ts +118 -0
  7. package/dist/ai-sdk.js +1030 -0
  8. package/dist/ai-sdk.js.map +1 -0
  9. package/dist/anthropic.cjs +528 -0
  10. package/dist/anthropic.cjs.map +1 -0
  11. package/dist/anthropic.d.cts +35 -0
  12. package/dist/anthropic.d.ts +35 -0
  13. package/dist/anthropic.js +523 -0
  14. package/dist/anthropic.js.map +1 -0
  15. package/dist/bedrock.cjs +392 -0
  16. package/dist/bedrock.cjs.map +1 -0
  17. package/dist/bedrock.d.cts +25 -0
  18. package/dist/bedrock.d.ts +25 -0
  19. package/dist/bedrock.js +388 -0
  20. package/dist/bedrock.js.map +1 -0
  21. package/dist/cli.js +11045 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/client-DsIxZxZk.d.cts +6905 -0
  24. package/dist/client-DsIxZxZk.d.ts +6905 -0
  25. package/dist/cloudflare-agents.cjs +626 -0
  26. package/dist/cloudflare-agents.cjs.map +1 -0
  27. package/dist/cloudflare-agents.d.cts +113 -0
  28. package/dist/cloudflare-agents.d.ts +113 -0
  29. package/dist/cloudflare-agents.js +622 -0
  30. package/dist/cloudflare-agents.js.map +1 -0
  31. package/dist/elevenlabs.cjs +738 -0
  32. package/dist/elevenlabs.cjs.map +1 -0
  33. package/dist/elevenlabs.d.cts +86 -0
  34. package/dist/elevenlabs.d.ts +86 -0
  35. package/dist/elevenlabs.js +733 -0
  36. package/dist/elevenlabs.js.map +1 -0
  37. package/dist/genkit.cjs +323 -0
  38. package/dist/genkit.cjs.map +1 -0
  39. package/dist/genkit.d.cts +67 -0
  40. package/dist/genkit.d.ts +67 -0
  41. package/dist/genkit.js +318 -0
  42. package/dist/genkit.js.map +1 -0
  43. package/dist/google-adk.cjs +705 -0
  44. package/dist/google-adk.cjs.map +1 -0
  45. package/dist/google-adk.d.cts +91 -0
  46. package/dist/google-adk.d.ts +91 -0
  47. package/dist/google-adk.js +701 -0
  48. package/dist/google-adk.js.map +1 -0
  49. package/dist/google-genai.cjs +422 -0
  50. package/dist/google-genai.cjs.map +1 -0
  51. package/dist/google-genai.d.cts +26 -0
  52. package/dist/google-genai.d.ts +26 -0
  53. package/dist/google-genai.js +418 -0
  54. package/dist/google-genai.js.map +1 -0
  55. package/dist/index.cjs +11421 -1895
  56. package/dist/index.cjs.map +1 -1
  57. package/dist/index.d.cts +959 -1294
  58. package/dist/index.d.ts +959 -1294
  59. package/dist/index.js +11368 -1896
  60. package/dist/index.js.map +1 -1
  61. package/dist/intercept-0_lJE6k1.d.cts +20 -0
  62. package/dist/intercept-D7qFCaRb.d.ts +20 -0
  63. package/dist/langchain.cjs +1077 -0
  64. package/dist/langchain.cjs.map +1 -0
  65. package/dist/langchain.d.cts +102 -0
  66. package/dist/langchain.d.ts +102 -0
  67. package/dist/langchain.js +1068 -0
  68. package/dist/langchain.js.map +1 -0
  69. package/dist/livekit.cjs +404 -0
  70. package/dist/livekit.cjs.map +1 -0
  71. package/dist/livekit.d.cts +113 -0
  72. package/dist/livekit.d.ts +113 -0
  73. package/dist/livekit.js +398 -0
  74. package/dist/livekit.js.map +1 -0
  75. package/dist/llamaindex.cjs +349 -0
  76. package/dist/llamaindex.cjs.map +1 -0
  77. package/dist/llamaindex.d.cts +92 -0
  78. package/dist/llamaindex.d.ts +92 -0
  79. package/dist/llamaindex.js +344 -0
  80. package/dist/llamaindex.js.map +1 -0
  81. package/dist/mastra.cjs +1082 -0
  82. package/dist/mastra.cjs.map +1 -0
  83. package/dist/mastra.d.cts +86 -0
  84. package/dist/mastra.d.ts +86 -0
  85. package/dist/mastra.js +1075 -0
  86. package/dist/mastra.js.map +1 -0
  87. package/dist/openai-agents.cjs +465 -0
  88. package/dist/openai-agents.cjs.map +1 -0
  89. package/dist/openai-agents.d.cts +75 -0
  90. package/dist/openai-agents.d.ts +75 -0
  91. package/dist/openai-agents.js +459 -0
  92. package/dist/openai-agents.js.map +1 -0
  93. package/dist/retell.cjs +846 -0
  94. package/dist/retell.cjs.map +1 -0
  95. package/dist/retell.d.cts +161 -0
  96. package/dist/retell.d.ts +161 -0
  97. package/dist/retell.js +841 -0
  98. package/dist/retell.js.map +1 -0
  99. package/dist/shared-Bb5B59Bu.d.ts +39 -0
  100. package/dist/shared-DTPWVlWm.d.cts +39 -0
  101. package/dist/strands.cjs +352 -0
  102. package/dist/strands.cjs.map +1 -0
  103. package/dist/strands.d.cts +72 -0
  104. package/dist/strands.d.ts +72 -0
  105. package/dist/strands.js +347 -0
  106. package/dist/strands.js.map +1 -0
  107. package/dist/twilio.cjs +174 -0
  108. package/dist/twilio.cjs.map +1 -0
  109. package/dist/twilio.d.cts +64 -0
  110. package/dist/twilio.d.ts +64 -0
  111. package/dist/twilio.js +167 -0
  112. package/dist/twilio.js.map +1 -0
  113. package/dist/vapi.cjs +661 -0
  114. package/dist/vapi.cjs.map +1 -0
  115. package/dist/vapi.d.cts +78 -0
  116. package/dist/vapi.d.ts +78 -0
  117. package/dist/vapi.js +656 -0
  118. package/dist/vapi.js.map +1 -0
  119. package/dist/voltagent.cjs +509 -0
  120. package/dist/voltagent.cjs.map +1 -0
  121. package/dist/voltagent.d.cts +70 -0
  122. package/dist/voltagent.d.ts +70 -0
  123. package/dist/voltagent.js +503 -0
  124. package/dist/voltagent.js.map +1 -0
  125. package/dist/webhook-1ozGyksG.d.ts +37 -0
  126. package/dist/webhook-CG4om_DK.d.cts +37 -0
  127. package/dist/whatsapp.cjs +214 -0
  128. package/dist/whatsapp.cjs.map +1 -0
  129. package/dist/whatsapp.d.cts +81 -0
  130. package/dist/whatsapp.d.ts +81 -0
  131. package/dist/whatsapp.js +207 -0
  132. package/dist/whatsapp.js.map +1 -0
  133. package/package.json +351 -6
@@ -0,0 +1,503 @@
1
+ import { createTool } from '@voltagent/core';
2
+ import { jsonSchema } from 'ai';
3
+
4
+ // src/integrations/voltagent.ts
5
+
6
+ // src/usage.ts
7
+ function get(value, name) {
8
+ return (typeof value === "object" || typeof value === "function") && value !== null ? value[name] : void 0;
9
+ }
10
+ function providerOf(model, usage) {
11
+ const slash = model.indexOf("/");
12
+ if (slash > 0) return model.slice(0, slash).trim().toLowerCase();
13
+ const name = model.trim().toLowerCase();
14
+ if (name.startsWith("claude") || `.${name}`.includes(".anthropic.")) return "anthropic";
15
+ if (name.startsWith("gemini")) return "google";
16
+ if (get(usage, "prompt_tokens") === void 0 && get(usage, "cache_read_input_tokens") !== void 0) {
17
+ return "anthropic";
18
+ }
19
+ return "openai";
20
+ }
21
+
22
+ // src/capture/tool.ts
23
+ var RECORDED = /* @__PURE__ */ Symbol.for("niadra.tool");
24
+ function recordedTool(fn) {
25
+ return typeof fn === "function" ? fn[RECORDED] ?? null : null;
26
+ }
27
+
28
+ // src/context.ts
29
+ function emptyResult(error) {
30
+ return { text: "", suffix: "", variables: {}, pack: null, source: "none", response: null, error, constraints: null, state: null, coordination: null };
31
+ }
32
+
33
+ // src/integrations/shared.ts
34
+ var ATTESTED = { A: "V2", B: "V1", C: "V1" };
35
+ function attestationProof(attestation) {
36
+ if (!attestation) return null;
37
+ const value = attestation.trim().toUpperCase();
38
+ if (value.includes("FAILED") || value.startsWith("NO-")) return null;
39
+ const letter = value.length === 1 ? value : /PASSED-([ABC])$/.exec(value)?.[1];
40
+ const level = letter ? ATTESTED[letter] : void 0;
41
+ return level ? { method: "network_attestation", level } : null;
42
+ }
43
+ function resolveSession(source) {
44
+ if (typeof source !== "function") return source;
45
+ try {
46
+ return source() ?? null;
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+ function isConversation(session) {
52
+ return "customer" in session && typeof session.customer === "function";
53
+ }
54
+ function errorName(error) {
55
+ return error instanceof Error ? error.name : typeof error;
56
+ }
57
+ var Bridge = class {
58
+ constructor(session, proof, memory = false) {
59
+ this.session = session;
60
+ this.proof = proof;
61
+ this.memory = memory;
62
+ }
63
+ session;
64
+ proof;
65
+ memory;
66
+ proving = null;
67
+ /** `begin()` started the first read of a call: the first `context()` waits for it with `ready()`. */
68
+ begun = false;
69
+ opened = false;
70
+ /**
71
+ * The context and, when enabled, the agent's notes, read side by side within the same budget.
72
+ * Never rejects.
73
+ */
74
+ async read(options = {}) {
75
+ const memoryParams = this.memory === false ? null : this.memory === true ? {} : withoutWrite(this.memory);
76
+ const [context, memory] = await Promise.all([
77
+ this.context(options),
78
+ memoryParams ? this.agentMemory(memoryParams, options) : Promise.resolve("")
79
+ ]);
80
+ return { context, memory, prefix: [memory, context.text].filter(Boolean).join("\n\n"), suffix: context.suffix };
81
+ }
82
+ get logger() {
83
+ return this.session.logger;
84
+ }
85
+ /**
86
+ * Starts the first read of a call now, in the background, after the proof when one was given (the
87
+ * pack depends on the level it proves): at call start, so the read runs while the call is set up.
88
+ * The first `context()` then waits for it within `timeouts.contextVoiceStart`. Never throws.
89
+ */
90
+ begin() {
91
+ const session = this.session;
92
+ if (!isConversation(session)) return;
93
+ const start = () => {
94
+ this.safe("start the first read", () => {
95
+ this.begun = session.begin();
96
+ });
97
+ };
98
+ if (this.proof === void 0 || this.proof === null) start();
99
+ else void this.verifyOnce().then(start);
100
+ }
101
+ /** Verifies once (when a proof was given), then reads the context. Never rejects. */
102
+ async context(options = {}) {
103
+ await this.verifyOnce();
104
+ try {
105
+ const session = this.session;
106
+ if (this.begun && !this.opened && isConversation(session)) {
107
+ this.opened = true;
108
+ await session.ready(options.timeout === void 0 ? {} : { timeout: options.timeout });
109
+ }
110
+ return await this.session.context(options);
111
+ } catch (error) {
112
+ this.logger.warn(`could not read context (${errorName(error)})`);
113
+ return emptyResult(null);
114
+ }
115
+ }
116
+ /** Records that `context` went into the prompt, unless it was empty for a reason other than the holdout. */
117
+ injected(context) {
118
+ if (!context.text && !context.suffix && context.response?.path !== "holdout") return;
119
+ this.safe("mark the injection", () => {
120
+ this.session.markInjected(context);
121
+ });
122
+ }
123
+ customer(text, options = {}) {
124
+ const session = this.session;
125
+ if (!text.trim() || !isConversation(session)) return;
126
+ this.safe("record the customer's turn", () => session.customer(text, options));
127
+ }
128
+ /** Sends the customer's turn so far, while they speak. In the background; never throws. */
129
+ prefetch(text) {
130
+ const session = this.session;
131
+ if (!text.trim() || !isConversation(session)) return;
132
+ this.safe("prefetch the turn", () => session.prefetch(text));
133
+ }
134
+ agent(text, options = {}) {
135
+ if (!text.trim()) return;
136
+ this.safe("record the agent's turn", () => this.session.agent(text, options));
137
+ }
138
+ /** Records a transfer. Tasks have no transfer; the call is ignored for them. */
139
+ async handoff(target, reason) {
140
+ const session = this.session;
141
+ if (!isConversation(session)) return;
142
+ try {
143
+ await session.handoff(reason ? { target, reason } : { target });
144
+ } catch (error) {
145
+ this.logger.warn(`could not record the handoff (${errorName(error)})`);
146
+ }
147
+ }
148
+ async end() {
149
+ try {
150
+ await this.session.end();
151
+ } catch (error) {
152
+ this.logger.warn(`could not end the session (${errorName(error)})`);
153
+ }
154
+ }
155
+ /** The navigation kit as plain specs (with the agent's memory tools when enabled), or none for a task about an object only. */
156
+ tools() {
157
+ let bound;
158
+ try {
159
+ const memory = this.memory;
160
+ bound = this.session.tools(memory === false ? {} : { agentMemory: true, writeAgentMemory: memory !== true && memory.write === true });
161
+ } catch (error) {
162
+ this.logger.warn(`could not build the tools (${errorName(error)})`);
163
+ return [];
164
+ }
165
+ return bound ? toolSpecs(bound) : [];
166
+ }
167
+ async agentMemory(params, options) {
168
+ try {
169
+ const result = await this.session.agentMemory(params, options.timeout === void 0 ? {} : { timeout: options.timeout });
170
+ return result.text;
171
+ } catch (error) {
172
+ this.logger.warn(`could not read the agent's memory (${errorName(error)})`);
173
+ return "";
174
+ }
175
+ }
176
+ async verifyOnce() {
177
+ if (this.proof === void 0 || this.proof === null) return;
178
+ this.proving ??= this.runVerify();
179
+ await this.proving;
180
+ }
181
+ async runVerify() {
182
+ try {
183
+ const source = this.proof;
184
+ const proof = typeof source === "function" ? await source() : source;
185
+ if (!proof) return;
186
+ await this.session.verify(proof);
187
+ } catch (error) {
188
+ this.logger.warn(`could not record the verification (${errorName(error)})`);
189
+ }
190
+ }
191
+ safe(what, run) {
192
+ try {
193
+ run();
194
+ } catch (error) {
195
+ this.logger.warn(`could not ${what} (${errorName(error)})`);
196
+ }
197
+ }
198
+ };
199
+ function withoutWrite(option) {
200
+ const { write: _, ...params } = option;
201
+ return params;
202
+ }
203
+ function toolSpecs(bound) {
204
+ return bound.definitions.map(({ function: definition }) => ({
205
+ name: definition.name,
206
+ description: definition.description,
207
+ parameters: definition.parameters,
208
+ execute: (args) => bound.call(definition.name, args)
209
+ }));
210
+ }
211
+ function textOf(content) {
212
+ if (typeof content === "string") return content;
213
+ if (!Array.isArray(content)) return "";
214
+ const parts = [];
215
+ for (const part of content) {
216
+ if (typeof part === "string") parts.push(part);
217
+ else if (isRecord(part) && typeof part.text === "string" && (part.type === void 0 || part.type === "text")) {
218
+ parts.push(part.text);
219
+ }
220
+ }
221
+ return parts.join("");
222
+ }
223
+ function isRecord(value) {
224
+ return typeof value === "object" && value !== null;
225
+ }
226
+ function count(value) {
227
+ return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : null;
228
+ }
229
+ var TurnHooks = class _TurnHooks {
230
+ constructor(adapter, enabled) {
231
+ this.adapter = adapter;
232
+ this.enabled = enabled;
233
+ }
234
+ adapter;
235
+ enabled;
236
+ /** Runs held open at most; past it the oldest run's turn closes, incomplete (a run whose end never came). */
237
+ static MAX_OPEN = 100;
238
+ frames = /* @__PURE__ */ new Map();
239
+ calls = /* @__PURE__ */ new Map();
240
+ /** The turn of the run `key`: the session's turn in progress, or a new one of its own. */
241
+ open(session, key, params = {}) {
242
+ if (!this.enabled) return void 0;
243
+ const held = this.frames.get(key);
244
+ if (held !== void 0) return held.frame;
245
+ try {
246
+ const active = session.activeTurn();
247
+ if (active !== void 0 && !this.owns(active)) {
248
+ this.frames.set(key, { frame: active, own: false });
249
+ return active;
250
+ }
251
+ const frame = session.openTurn({ ...params, adapter: this.adapter });
252
+ this.frames.set(key, { frame, own: true });
253
+ if (this.frames.size > _TurnHooks.MAX_OPEN) {
254
+ const [oldest] = this.frames.keys();
255
+ if (oldest !== void 0) {
256
+ this.frames.get(oldest)?.frame.incomplete();
257
+ this.close(oldest);
258
+ }
259
+ }
260
+ return frame;
261
+ } catch (error) {
262
+ session.logger.warn(`could not open the turn (${errorName(error)})`);
263
+ return void 0;
264
+ }
265
+ }
266
+ /** The turn of `key`, else the session's turn in progress. */
267
+ frame(session, key) {
268
+ if (!this.enabled) return void 0;
269
+ const held = key === void 0 ? void 0 : this.frames.get(key);
270
+ const frame = held?.frame ?? session.activeTurn();
271
+ return frame === void 0 || frame.closed ? void 0 : frame;
272
+ }
273
+ has(key) {
274
+ return this.frames.has(key);
275
+ }
276
+ owns(frame) {
277
+ for (const held of this.frames.values()) if (held.own && held.frame === frame) return true;
278
+ return false;
279
+ }
280
+ /** Ends the run `key`: a turn the adapter opened closes; the calls it left open failed. */
281
+ close(key, error) {
282
+ const held = this.frames.get(key);
283
+ if (held === void 0) return;
284
+ this.frames.delete(key);
285
+ for (const [callKey, call] of this.calls) {
286
+ if (call.frame !== held.frame) continue;
287
+ this.calls.delete(callKey);
288
+ if (held.own) call.failed(error ?? "error");
289
+ }
290
+ if (held.own) held.frame.close(error);
291
+ }
292
+ /** A tool call starting, keyed by `callKey`; `callId` is the provider's id of the call, when there is one. */
293
+ toolStart(session, callKey, name, args, options = {}) {
294
+ const frame = this.frame(session, options.frameKey);
295
+ if (frame === void 0) return;
296
+ try {
297
+ this.calls.set(callKey, frame.toolCall(name, args, { callId: options.callId ?? null, adoptable: true }));
298
+ } catch {
299
+ frame.incomplete();
300
+ }
301
+ }
302
+ /**
303
+ * In a replay, how a framework tool the adapter stands in for answers: the recorded result of a call with the
304
+ * same arguments, or empty (a divergence), never the live tool. `null` outside a replay, and for a function
305
+ * wrapped with `tool()`, which answers itself.
306
+ */
307
+ replayed(session, name, args, fn, frameKey) {
308
+ const frame = this.enabled ? this.frame(session, frameKey) : session.activeTurn();
309
+ if (frame?.playback == null || fn !== void 0 && recordedTool(fn) !== null) return null;
310
+ return frame.playback.answer(name, args, false);
311
+ }
312
+ toolEnd(callKey, result, error) {
313
+ const call = this.calls.get(callKey);
314
+ if (call === void 0) return;
315
+ this.calls.delete(callKey);
316
+ try {
317
+ if (error !== void 0) call.failed(error);
318
+ else call.result(result);
319
+ } catch {
320
+ call.frame.incomplete();
321
+ }
322
+ }
323
+ /** A model call that ended, with its tokens when the framework reported them. */
324
+ model(session, model, tokens = {}, frameKey) {
325
+ const frame = this.frame(session, frameKey);
326
+ if (frame === void 0) return;
327
+ try {
328
+ frame.modelCall(model, { tokensIn: tokens.in ?? null, tokensOut: tokens.out ?? null, tokensCached: tokens.cached ?? 0 });
329
+ } catch {
330
+ frame.incomplete();
331
+ }
332
+ }
333
+ };
334
+
335
+ // src/integrations/voltagent.ts
336
+ var NIADRA_CONTEXT_KEY = "niadra";
337
+ function niadraHooks(options = {}) {
338
+ const states = /* @__PURE__ */ new WeakMap();
339
+ const hooks = new TurnHooks("voltagent", options.turns ?? false);
340
+ const stateOf = (context) => {
341
+ const choice = options.session;
342
+ const session = typeof choice === "function" ? context ? resolveSession(() => choice(context)) : null : choice ?? asSession(context?.context.get(NIADRA_CONTEXT_KEY));
343
+ if (!session) return null;
344
+ let state = states.get(session);
345
+ if (!state) {
346
+ state = { bridge: new Bridge(session, options.verify, options.agentMemory), seen: /* @__PURE__ */ new Set() };
347
+ states.set(session, state);
348
+ }
349
+ return state;
350
+ };
351
+ const callId = (call) => call?.toolContext?.callId ?? null;
352
+ const callKey = (context, tool, call) => callId(call) ?? `${context.operationId}:${tool}`;
353
+ const recordAnswer = ({ output, agent, context }) => {
354
+ if (!(options.recordAgent ?? true) || !output || !("text" in output)) return;
355
+ const state = stateOf(context);
356
+ if (!state) return;
357
+ try {
358
+ const steps = Array.isArray(output.steps) ? output.steps : [];
359
+ const last = steps.at(-1);
360
+ const response = isRecord(last) && isRecord(last.response) ? last.response : {};
361
+ const model = typeof response.modelId === "string" ? response.modelId : modelName(agent);
362
+ const usage = model ? voltAgentUsage(output.totalUsage ?? output.usage, model, options.provider) : null;
363
+ state.bridge.agent(output.text, usage ? { usage } : {});
364
+ } catch (error) {
365
+ state.bridge.logger.warn(`could not record the agent's answer (${errorName(error)})`);
366
+ }
367
+ };
368
+ return {
369
+ async onPrepareModelMessages({ modelMessages, context }) {
370
+ const state = stateOf(context);
371
+ if (!state) return {};
372
+ try {
373
+ if (options.recordCustomer ?? true) recordNewest(state, modelMessages);
374
+ const read = await state.bridge.read();
375
+ state.bridge.injected(read.context);
376
+ return { modelMessages: inject(modelMessages, read.prefix, read.suffix) };
377
+ } catch (error) {
378
+ state.bridge.logger.warn(`could not inject context (${errorName(error)})`);
379
+ return {};
380
+ }
381
+ },
382
+ onStart({ agent, context }) {
383
+ const state = hooks.enabled ? stateOf(context) : null;
384
+ if (state) hooks.open(state.bridge.session, context.operationId, { agent: agent.name });
385
+ },
386
+ onToolStart({ tool, args, context, options: call }) {
387
+ const state = hooks.enabled ? stateOf(context) : null;
388
+ if (!state) return;
389
+ hooks.toolStart(state.bridge.session, callKey(context, tool.name, call), tool.name, args, { frameKey: context.operationId, callId: callId(call) });
390
+ },
391
+ onToolEnd({ tool, output, error, context, options: call }) {
392
+ hooks.toolEnd(callKey(context, tool.name, call), output, error);
393
+ return void 0;
394
+ },
395
+ onStepFinish({ agent, step, context }) {
396
+ const state = hooks.enabled ? stateOf(context) : null;
397
+ if (!state || !isRecord(step)) return;
398
+ const response = isRecord(step.response) ? step.response : {};
399
+ const usage = isRecord(step.usage) ? step.usage : {};
400
+ const input = isRecord(usage.inputTokens) ? usage.inputTokens : null;
401
+ hooks.model(
402
+ state.bridge.session,
403
+ typeof response.modelId === "string" ? response.modelId : modelName(agent),
404
+ {
405
+ in: input ? count(input.total) : count(usage.inputTokens),
406
+ out: isRecord(usage.outputTokens) ? count(usage.outputTokens.total) : count(usage.outputTokens),
407
+ cached: (input ? count(input.cacheRead) : count(usage.cachedInputTokens)) ?? 0
408
+ },
409
+ context.operationId
410
+ );
411
+ },
412
+ onEnd(args) {
413
+ try {
414
+ recordAnswer(args);
415
+ } finally {
416
+ hooks.close(args.context.operationId);
417
+ }
418
+ },
419
+ async onHandoff({ agent, sourceAgent }) {
420
+ const state = typeof options.session === "object" ? stateOf(void 0) : null;
421
+ if (state) await state.bridge.handoff("agent", `${sourceAgent.name} to ${agent.name}`);
422
+ }
423
+ };
424
+ }
425
+ function niadraTools(session, options = {}) {
426
+ return new Bridge(session, void 0, options.agentMemory).tools().map(
427
+ (spec) => createTool({
428
+ name: spec.name,
429
+ description: spec.description,
430
+ // VoltAgent hands the schema to the AI SDK, which takes a JSON Schema as it takes Zod.
431
+ parameters: jsonSchema(spec.parameters),
432
+ execute: async (input) => parsed(await spec.execute(isRecord(input) ? input : {}))
433
+ })
434
+ );
435
+ }
436
+ function voltAgentUsage(usage, model, provider) {
437
+ if (!isRecord(usage)) return null;
438
+ const prompt = count(usage.inputTokens);
439
+ if (prompt === null) return null;
440
+ const details = isRecord(usage.inputTokenDetails) ? usage.inputTokenDetails : {};
441
+ const cached = count(details.cacheReadTokens) ?? count(usage.cachedInputTokens) ?? 0;
442
+ const written = count(details.cacheWriteTokens) ?? 0;
443
+ return {
444
+ provider: (provider ?? providerOf(model, usage)).toLowerCase(),
445
+ model,
446
+ prompt_tokens: Math.max(prompt, cached + written),
447
+ cached_tokens: cached,
448
+ cache_write_tokens: written
449
+ };
450
+ }
451
+ function recordNewest(state, messages) {
452
+ const index = lastUser(messages);
453
+ if (index < 0) return;
454
+ const text = textOf(messages[index]?.content);
455
+ const key = `${String(index)}:${text}`;
456
+ if (!text || state.seen.has(key)) return;
457
+ state.seen.add(key);
458
+ state.bridge.customer(text);
459
+ }
460
+ function inject(messages, prefix, suffix) {
461
+ const result = [...messages];
462
+ const index = lastUser(result);
463
+ const last = result[index];
464
+ if (suffix && last?.role === "user") {
465
+ const content = typeof last.content === "string" ? `${last.content}
466
+
467
+ ${suffix}` : [...last.content, { type: "text", text: suffix }];
468
+ result[index] = { ...last, content };
469
+ }
470
+ if (prefix) {
471
+ let position = 0;
472
+ while (position < result.length && result[position]?.role === "system") position++;
473
+ result.splice(position, 0, { role: "system", content: prefix });
474
+ }
475
+ return result;
476
+ }
477
+ function lastUser(messages) {
478
+ for (let index = messages.length - 1; index >= 0; index--) if (messages[index]?.role === "user") return index;
479
+ return -1;
480
+ }
481
+ function modelName(agent) {
482
+ if (!isRecord(agent) || typeof agent.getModelName !== "function") return void 0;
483
+ try {
484
+ const name = agent.getModelName.call(agent);
485
+ return typeof name === "string" && name ? name : void 0;
486
+ } catch {
487
+ return void 0;
488
+ }
489
+ }
490
+ function asSession(value) {
491
+ return isRecord(value) && typeof value.context === "function" && typeof value.agent === "function" ? value : null;
492
+ }
493
+ function parsed(text) {
494
+ try {
495
+ return JSON.parse(text);
496
+ } catch {
497
+ return text;
498
+ }
499
+ }
500
+
501
+ export { NIADRA_CONTEXT_KEY, attestationProof, niadraHooks, niadraTools, voltAgentUsage };
502
+ //# sourceMappingURL=voltagent.js.map
503
+ //# sourceMappingURL=voltagent.js.map