@niadra/sdk 0.1.0 → 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.
- package/CHANGELOG.md +161 -20
- package/README.md +484 -38
- package/dist/ai-sdk.cjs +1037 -0
- package/dist/ai-sdk.cjs.map +1 -0
- package/dist/ai-sdk.d.cts +118 -0
- package/dist/ai-sdk.d.ts +118 -0
- package/dist/ai-sdk.js +1030 -0
- package/dist/ai-sdk.js.map +1 -0
- package/dist/anthropic.cjs +528 -0
- package/dist/anthropic.cjs.map +1 -0
- package/dist/anthropic.d.cts +35 -0
- package/dist/anthropic.d.ts +35 -0
- package/dist/anthropic.js +523 -0
- package/dist/anthropic.js.map +1 -0
- package/dist/bedrock.cjs +392 -0
- package/dist/bedrock.cjs.map +1 -0
- package/dist/bedrock.d.cts +25 -0
- package/dist/bedrock.d.ts +25 -0
- package/dist/bedrock.js +388 -0
- package/dist/bedrock.js.map +1 -0
- package/dist/cli.js +11045 -0
- package/dist/cli.js.map +1 -0
- package/dist/client-DsIxZxZk.d.cts +6905 -0
- package/dist/client-DsIxZxZk.d.ts +6905 -0
- package/dist/cloudflare-agents.cjs +626 -0
- package/dist/cloudflare-agents.cjs.map +1 -0
- package/dist/cloudflare-agents.d.cts +113 -0
- package/dist/cloudflare-agents.d.ts +113 -0
- package/dist/cloudflare-agents.js +622 -0
- package/dist/cloudflare-agents.js.map +1 -0
- package/dist/elevenlabs.cjs +738 -0
- package/dist/elevenlabs.cjs.map +1 -0
- package/dist/elevenlabs.d.cts +86 -0
- package/dist/elevenlabs.d.ts +86 -0
- package/dist/elevenlabs.js +733 -0
- package/dist/elevenlabs.js.map +1 -0
- package/dist/genkit.cjs +323 -0
- package/dist/genkit.cjs.map +1 -0
- package/dist/genkit.d.cts +67 -0
- package/dist/genkit.d.ts +67 -0
- package/dist/genkit.js +318 -0
- package/dist/genkit.js.map +1 -0
- package/dist/google-adk.cjs +705 -0
- package/dist/google-adk.cjs.map +1 -0
- package/dist/google-adk.d.cts +91 -0
- package/dist/google-adk.d.ts +91 -0
- package/dist/google-adk.js +701 -0
- package/dist/google-adk.js.map +1 -0
- package/dist/google-genai.cjs +422 -0
- package/dist/google-genai.cjs.map +1 -0
- package/dist/google-genai.d.cts +26 -0
- package/dist/google-genai.d.ts +26 -0
- package/dist/google-genai.js +418 -0
- package/dist/google-genai.js.map +1 -0
- package/dist/index.cjs +11449 -1796
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1006 -1247
- package/dist/index.d.ts +1006 -1247
- package/dist/index.js +11393 -1797
- package/dist/index.js.map +1 -1
- package/dist/intercept-0_lJE6k1.d.cts +20 -0
- package/dist/intercept-D7qFCaRb.d.ts +20 -0
- package/dist/langchain.cjs +1077 -0
- package/dist/langchain.cjs.map +1 -0
- package/dist/langchain.d.cts +102 -0
- package/dist/langchain.d.ts +102 -0
- package/dist/langchain.js +1068 -0
- package/dist/langchain.js.map +1 -0
- package/dist/livekit.cjs +404 -0
- package/dist/livekit.cjs.map +1 -0
- package/dist/livekit.d.cts +113 -0
- package/dist/livekit.d.ts +113 -0
- package/dist/livekit.js +398 -0
- package/dist/livekit.js.map +1 -0
- package/dist/llamaindex.cjs +349 -0
- package/dist/llamaindex.cjs.map +1 -0
- package/dist/llamaindex.d.cts +92 -0
- package/dist/llamaindex.d.ts +92 -0
- package/dist/llamaindex.js +344 -0
- package/dist/llamaindex.js.map +1 -0
- package/dist/mastra.cjs +1082 -0
- package/dist/mastra.cjs.map +1 -0
- package/dist/mastra.d.cts +86 -0
- package/dist/mastra.d.ts +86 -0
- package/dist/mastra.js +1075 -0
- package/dist/mastra.js.map +1 -0
- package/dist/openai-agents.cjs +465 -0
- package/dist/openai-agents.cjs.map +1 -0
- package/dist/openai-agents.d.cts +75 -0
- package/dist/openai-agents.d.ts +75 -0
- package/dist/openai-agents.js +459 -0
- package/dist/openai-agents.js.map +1 -0
- package/dist/retell.cjs +846 -0
- package/dist/retell.cjs.map +1 -0
- package/dist/retell.d.cts +161 -0
- package/dist/retell.d.ts +161 -0
- package/dist/retell.js +841 -0
- package/dist/retell.js.map +1 -0
- package/dist/shared-Bb5B59Bu.d.ts +39 -0
- package/dist/shared-DTPWVlWm.d.cts +39 -0
- package/dist/strands.cjs +352 -0
- package/dist/strands.cjs.map +1 -0
- package/dist/strands.d.cts +72 -0
- package/dist/strands.d.ts +72 -0
- package/dist/strands.js +347 -0
- package/dist/strands.js.map +1 -0
- package/dist/twilio.cjs +174 -0
- package/dist/twilio.cjs.map +1 -0
- package/dist/twilio.d.cts +64 -0
- package/dist/twilio.d.ts +64 -0
- package/dist/twilio.js +167 -0
- package/dist/twilio.js.map +1 -0
- package/dist/vapi.cjs +661 -0
- package/dist/vapi.cjs.map +1 -0
- package/dist/vapi.d.cts +78 -0
- package/dist/vapi.d.ts +78 -0
- package/dist/vapi.js +656 -0
- package/dist/vapi.js.map +1 -0
- package/dist/voltagent.cjs +509 -0
- package/dist/voltagent.cjs.map +1 -0
- package/dist/voltagent.d.cts +70 -0
- package/dist/voltagent.d.ts +70 -0
- package/dist/voltagent.js +503 -0
- package/dist/voltagent.js.map +1 -0
- package/dist/webhook-1ozGyksG.d.ts +37 -0
- package/dist/webhook-CG4om_DK.d.cts +37 -0
- package/dist/whatsapp.cjs +214 -0
- package/dist/whatsapp.cjs.map +1 -0
- package/dist/whatsapp.d.cts +81 -0
- package/dist/whatsapp.d.ts +81 -0
- package/dist/whatsapp.js +207 -0
- package/dist/whatsapp.js.map +1 -0
- package/package.json +355 -7
|
@@ -0,0 +1,701 @@
|
|
|
1
|
+
import { BaseTool } from '@google/adk';
|
|
2
|
+
|
|
3
|
+
// src/integrations/google-adk.ts
|
|
4
|
+
|
|
5
|
+
// src/tools.ts
|
|
6
|
+
var TOOL_DEFINITIONS = [
|
|
7
|
+
{
|
|
8
|
+
"type": "function",
|
|
9
|
+
"function": {
|
|
10
|
+
"name": "search_customer_history",
|
|
11
|
+
"description": "Search everything that already happened with this customer: past conversations, promises, agent actions, orders and invoices. Use it when the customer refers to something earlier or asks whether a problem happened before. Do not call it when the answer is already in the context block, including its 'Do hist\xF3rico' line, which already counts recurrences. Returns short items with date, channel and outcome, plus a recurrence count. Open one with open_history_item.",
|
|
12
|
+
"parameters": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"query": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "What to look for, in the customer's words."
|
|
18
|
+
},
|
|
19
|
+
"filters": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"properties": {
|
|
22
|
+
"since": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"format": "date-time"
|
|
25
|
+
},
|
|
26
|
+
"until": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"format": "date-time"
|
|
29
|
+
},
|
|
30
|
+
"when": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "The period in the customer's own words, as they said it: 'last week', 'semana passada', 'en marzo'."
|
|
33
|
+
},
|
|
34
|
+
"channels": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"items": {
|
|
37
|
+
"type": "string"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"categories": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"items": {
|
|
43
|
+
"type": "string"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"item_kinds": {
|
|
47
|
+
"type": "array",
|
|
48
|
+
"items": {
|
|
49
|
+
"enum": [
|
|
50
|
+
"episode",
|
|
51
|
+
"fact",
|
|
52
|
+
"open_item",
|
|
53
|
+
"action",
|
|
54
|
+
"object",
|
|
55
|
+
"trait"
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"outcome": {
|
|
60
|
+
"type": "string"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"additionalProperties": false
|
|
64
|
+
},
|
|
65
|
+
"max_tokens": {
|
|
66
|
+
"type": "integer",
|
|
67
|
+
"minimum": 50,
|
|
68
|
+
"maximum": 4e3
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"required": [
|
|
72
|
+
"query"
|
|
73
|
+
],
|
|
74
|
+
"additionalProperties": false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"type": "function",
|
|
80
|
+
"function": {
|
|
81
|
+
"name": "get_customer_timeline",
|
|
82
|
+
"description": "List this customer's conversations and agent actions in order, newest first, one line each. Use it to leaf through the history when you do not know what to search for. Pass next_cursor to continue. Prefer search_customer_history for a specific question.",
|
|
83
|
+
"parameters": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"properties": {
|
|
86
|
+
"cursor": {
|
|
87
|
+
"type": "string"
|
|
88
|
+
},
|
|
89
|
+
"limit": {
|
|
90
|
+
"type": "integer",
|
|
91
|
+
"minimum": 1,
|
|
92
|
+
"maximum": 100
|
|
93
|
+
},
|
|
94
|
+
"filters": {
|
|
95
|
+
"type": "object",
|
|
96
|
+
"properties": {
|
|
97
|
+
"since": {
|
|
98
|
+
"type": "string",
|
|
99
|
+
"format": "date-time"
|
|
100
|
+
},
|
|
101
|
+
"until": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"format": "date-time"
|
|
104
|
+
},
|
|
105
|
+
"when": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"description": "The period in the customer's own words, as they said it: 'last week', 'semana passada', 'en marzo'."
|
|
108
|
+
},
|
|
109
|
+
"channels": {
|
|
110
|
+
"type": "array",
|
|
111
|
+
"items": {
|
|
112
|
+
"type": "string"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"categories": {
|
|
116
|
+
"type": "array",
|
|
117
|
+
"items": {
|
|
118
|
+
"type": "string"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"item_kinds": {
|
|
122
|
+
"type": "array",
|
|
123
|
+
"items": {
|
|
124
|
+
"enum": [
|
|
125
|
+
"episode",
|
|
126
|
+
"fact",
|
|
127
|
+
"open_item",
|
|
128
|
+
"action",
|
|
129
|
+
"object",
|
|
130
|
+
"trait"
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"outcome": {
|
|
135
|
+
"type": "string"
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"additionalProperties": false
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"additionalProperties": false
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"type": "function",
|
|
147
|
+
"function": {
|
|
148
|
+
"name": "open_history_item",
|
|
149
|
+
"description": "Open one conversation or business object returned by search_customer_history or get_customer_timeline: what was asked, what was promised and by whom, the outcome and what memory came from it. Use it only after a search or timeline pointed to the item.",
|
|
150
|
+
"parameters": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"properties": {
|
|
153
|
+
"id": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"description": "The item id, e.g. `episode:...`."
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"required": [
|
|
159
|
+
"id"
|
|
160
|
+
],
|
|
161
|
+
"additionalProperties": false
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
];
|
|
166
|
+
var AGENT_MEMORY_TOOL_DEFINITIONS = [
|
|
167
|
+
{
|
|
168
|
+
"type": "function",
|
|
169
|
+
"function": {
|
|
170
|
+
"name": "search_agent_memory",
|
|
171
|
+
"description": "Search your own working notes: procedures, how the company's tools and processes behave, and known pitfalls. Use it before a task or a tool call you are unsure how to do. It holds nothing about customers; for the customer's history use search_customer_history.",
|
|
172
|
+
"parameters": {
|
|
173
|
+
"type": "object",
|
|
174
|
+
"properties": {
|
|
175
|
+
"query": {
|
|
176
|
+
"type": "string",
|
|
177
|
+
"description": "What you need to know how to do."
|
|
178
|
+
},
|
|
179
|
+
"tags": {
|
|
180
|
+
"type": "array",
|
|
181
|
+
"maxItems": 8,
|
|
182
|
+
"items": {
|
|
183
|
+
"type": "string",
|
|
184
|
+
"pattern": "^[a-z0-9][a-z0-9_.:-]{0,63}$"
|
|
185
|
+
},
|
|
186
|
+
"description": "Object types, operations or systems, e.g. `invoice`, `credit`, `erp`."
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"required": [
|
|
190
|
+
"query"
|
|
191
|
+
],
|
|
192
|
+
"additionalProperties": false
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"type": "function",
|
|
198
|
+
"function": {
|
|
199
|
+
"name": "remember",
|
|
200
|
+
"description": "Save a working note for yourself and future runs: a procedure that worked, how a tool or process behaves, or a pitfall to avoid. Never write anything about a customer here: no names, phones, e-mails, documents, ids or words from the conversation. A note with personal data is refused. Write it so it helps with any customer.",
|
|
201
|
+
"parameters": {
|
|
202
|
+
"type": "object",
|
|
203
|
+
"properties": {
|
|
204
|
+
"kind": {
|
|
205
|
+
"enum": [
|
|
206
|
+
"procedure",
|
|
207
|
+
"tool_note",
|
|
208
|
+
"process_note",
|
|
209
|
+
"pitfall"
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
"title": {
|
|
213
|
+
"type": "string",
|
|
214
|
+
"maxLength": 120
|
|
215
|
+
},
|
|
216
|
+
"body": {
|
|
217
|
+
"type": "string",
|
|
218
|
+
"maxLength": 2e3
|
|
219
|
+
},
|
|
220
|
+
"tags": {
|
|
221
|
+
"type": "array",
|
|
222
|
+
"maxItems": 8,
|
|
223
|
+
"items": {
|
|
224
|
+
"type": "string",
|
|
225
|
+
"pattern": "^[a-z0-9][a-z0-9_.:-]{0,63}$"
|
|
226
|
+
},
|
|
227
|
+
"description": "Object types, operations or systems, e.g. `invoice`, `credit`, `erp`."
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
"required": [
|
|
231
|
+
"kind",
|
|
232
|
+
"title",
|
|
233
|
+
"body"
|
|
234
|
+
],
|
|
235
|
+
"additionalProperties": false
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
];
|
|
240
|
+
function providerOf(model, usage) {
|
|
241
|
+
const slash = model.indexOf("/");
|
|
242
|
+
if (slash > 0) return model.slice(0, slash).trim().toLowerCase();
|
|
243
|
+
const name = model.trim().toLowerCase();
|
|
244
|
+
if (name.startsWith("claude") || `.${name}`.includes(".anthropic.")) return "anthropic";
|
|
245
|
+
if (name.startsWith("gemini")) return "google";
|
|
246
|
+
return "openai";
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/capture/tool.ts
|
|
250
|
+
var RECORDED = /* @__PURE__ */ Symbol.for("niadra.tool");
|
|
251
|
+
function recordedTool(fn) {
|
|
252
|
+
return typeof fn === "function" ? fn[RECORDED] ?? null : null;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// src/context.ts
|
|
256
|
+
function emptyResult(error) {
|
|
257
|
+
return { text: "", suffix: "", variables: {}, pack: null, source: "none", response: null, error, constraints: null, state: null, coordination: null };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/integrations/shared.ts
|
|
261
|
+
var ATTESTED = { A: "V2", B: "V1", C: "V1" };
|
|
262
|
+
function attestationProof(attestation) {
|
|
263
|
+
if (!attestation) return null;
|
|
264
|
+
const value = attestation.trim().toUpperCase();
|
|
265
|
+
if (value.includes("FAILED") || value.startsWith("NO-")) return null;
|
|
266
|
+
const letter = value.length === 1 ? value : /PASSED-([ABC])$/.exec(value)?.[1];
|
|
267
|
+
const level = letter ? ATTESTED[letter] : void 0;
|
|
268
|
+
return level ? { method: "network_attestation", level } : null;
|
|
269
|
+
}
|
|
270
|
+
function isConversation(session) {
|
|
271
|
+
return "customer" in session && typeof session.customer === "function";
|
|
272
|
+
}
|
|
273
|
+
function errorName(error) {
|
|
274
|
+
return error instanceof Error ? error.name : typeof error;
|
|
275
|
+
}
|
|
276
|
+
var Bridge = class {
|
|
277
|
+
constructor(session, proof, memory = false) {
|
|
278
|
+
this.session = session;
|
|
279
|
+
this.proof = proof;
|
|
280
|
+
this.memory = memory;
|
|
281
|
+
}
|
|
282
|
+
session;
|
|
283
|
+
proof;
|
|
284
|
+
memory;
|
|
285
|
+
proving = null;
|
|
286
|
+
/** `begin()` started the first read of a call: the first `context()` waits for it with `ready()`. */
|
|
287
|
+
begun = false;
|
|
288
|
+
opened = false;
|
|
289
|
+
/**
|
|
290
|
+
* The context and, when enabled, the agent's notes, read side by side within the same budget.
|
|
291
|
+
* Never rejects.
|
|
292
|
+
*/
|
|
293
|
+
async read(options = {}) {
|
|
294
|
+
const memoryParams = this.memory === false ? null : this.memory === true ? {} : withoutWrite(this.memory);
|
|
295
|
+
const [context, memory] = await Promise.all([
|
|
296
|
+
this.context(options),
|
|
297
|
+
memoryParams ? this.agentMemory(memoryParams, options) : Promise.resolve("")
|
|
298
|
+
]);
|
|
299
|
+
return { context, memory, prefix: [memory, context.text].filter(Boolean).join("\n\n"), suffix: context.suffix };
|
|
300
|
+
}
|
|
301
|
+
get logger() {
|
|
302
|
+
return this.session.logger;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Starts the first read of a call now, in the background, after the proof when one was given (the
|
|
306
|
+
* pack depends on the level it proves): at call start, so the read runs while the call is set up.
|
|
307
|
+
* The first `context()` then waits for it within `timeouts.contextVoiceStart`. Never throws.
|
|
308
|
+
*/
|
|
309
|
+
begin() {
|
|
310
|
+
const session = this.session;
|
|
311
|
+
if (!isConversation(session)) return;
|
|
312
|
+
const start = () => {
|
|
313
|
+
this.safe("start the first read", () => {
|
|
314
|
+
this.begun = session.begin();
|
|
315
|
+
});
|
|
316
|
+
};
|
|
317
|
+
if (this.proof === void 0 || this.proof === null) start();
|
|
318
|
+
else void this.verifyOnce().then(start);
|
|
319
|
+
}
|
|
320
|
+
/** Verifies once (when a proof was given), then reads the context. Never rejects. */
|
|
321
|
+
async context(options = {}) {
|
|
322
|
+
await this.verifyOnce();
|
|
323
|
+
try {
|
|
324
|
+
const session = this.session;
|
|
325
|
+
if (this.begun && !this.opened && isConversation(session)) {
|
|
326
|
+
this.opened = true;
|
|
327
|
+
await session.ready(options.timeout === void 0 ? {} : { timeout: options.timeout });
|
|
328
|
+
}
|
|
329
|
+
return await this.session.context(options);
|
|
330
|
+
} catch (error) {
|
|
331
|
+
this.logger.warn(`could not read context (${errorName(error)})`);
|
|
332
|
+
return emptyResult(null);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/** Records that `context` went into the prompt, unless it was empty for a reason other than the holdout. */
|
|
336
|
+
injected(context) {
|
|
337
|
+
if (!context.text && !context.suffix && context.response?.path !== "holdout") return;
|
|
338
|
+
this.safe("mark the injection", () => {
|
|
339
|
+
this.session.markInjected(context);
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
customer(text, options = {}) {
|
|
343
|
+
const session = this.session;
|
|
344
|
+
if (!text.trim() || !isConversation(session)) return;
|
|
345
|
+
this.safe("record the customer's turn", () => session.customer(text, options));
|
|
346
|
+
}
|
|
347
|
+
/** Sends the customer's turn so far, while they speak. In the background; never throws. */
|
|
348
|
+
prefetch(text) {
|
|
349
|
+
const session = this.session;
|
|
350
|
+
if (!text.trim() || !isConversation(session)) return;
|
|
351
|
+
this.safe("prefetch the turn", () => session.prefetch(text));
|
|
352
|
+
}
|
|
353
|
+
agent(text, options = {}) {
|
|
354
|
+
if (!text.trim()) return;
|
|
355
|
+
this.safe("record the agent's turn", () => this.session.agent(text, options));
|
|
356
|
+
}
|
|
357
|
+
/** Records a transfer. Tasks have no transfer; the call is ignored for them. */
|
|
358
|
+
async handoff(target, reason) {
|
|
359
|
+
const session = this.session;
|
|
360
|
+
if (!isConversation(session)) return;
|
|
361
|
+
try {
|
|
362
|
+
await session.handoff(reason ? { target, reason } : { target });
|
|
363
|
+
} catch (error) {
|
|
364
|
+
this.logger.warn(`could not record the handoff (${errorName(error)})`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
async end() {
|
|
368
|
+
try {
|
|
369
|
+
await this.session.end();
|
|
370
|
+
} catch (error) {
|
|
371
|
+
this.logger.warn(`could not end the session (${errorName(error)})`);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
/** The navigation kit as plain specs (with the agent's memory tools when enabled), or none for a task about an object only. */
|
|
375
|
+
tools() {
|
|
376
|
+
let bound;
|
|
377
|
+
try {
|
|
378
|
+
const memory = this.memory;
|
|
379
|
+
bound = this.session.tools(memory === false ? {} : { agentMemory: true, writeAgentMemory: memory !== true && memory.write === true });
|
|
380
|
+
} catch (error) {
|
|
381
|
+
this.logger.warn(`could not build the tools (${errorName(error)})`);
|
|
382
|
+
return [];
|
|
383
|
+
}
|
|
384
|
+
return bound ? toolSpecs(bound) : [];
|
|
385
|
+
}
|
|
386
|
+
async agentMemory(params, options) {
|
|
387
|
+
try {
|
|
388
|
+
const result = await this.session.agentMemory(params, options.timeout === void 0 ? {} : { timeout: options.timeout });
|
|
389
|
+
return result.text;
|
|
390
|
+
} catch (error) {
|
|
391
|
+
this.logger.warn(`could not read the agent's memory (${errorName(error)})`);
|
|
392
|
+
return "";
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
async verifyOnce() {
|
|
396
|
+
if (this.proof === void 0 || this.proof === null) return;
|
|
397
|
+
this.proving ??= this.runVerify();
|
|
398
|
+
await this.proving;
|
|
399
|
+
}
|
|
400
|
+
async runVerify() {
|
|
401
|
+
try {
|
|
402
|
+
const source = this.proof;
|
|
403
|
+
const proof = typeof source === "function" ? await source() : source;
|
|
404
|
+
if (!proof) return;
|
|
405
|
+
await this.session.verify(proof);
|
|
406
|
+
} catch (error) {
|
|
407
|
+
this.logger.warn(`could not record the verification (${errorName(error)})`);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
safe(what, run) {
|
|
411
|
+
try {
|
|
412
|
+
run();
|
|
413
|
+
} catch (error) {
|
|
414
|
+
this.logger.warn(`could not ${what} (${errorName(error)})`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
function withoutWrite(option) {
|
|
419
|
+
const { write: _, ...params } = option;
|
|
420
|
+
return params;
|
|
421
|
+
}
|
|
422
|
+
function toolSpecs(bound) {
|
|
423
|
+
return bound.definitions.map(({ function: definition }) => ({
|
|
424
|
+
name: definition.name,
|
|
425
|
+
description: definition.description,
|
|
426
|
+
parameters: definition.parameters,
|
|
427
|
+
execute: (args) => bound.call(definition.name, args)
|
|
428
|
+
}));
|
|
429
|
+
}
|
|
430
|
+
function isRecord(value) {
|
|
431
|
+
return typeof value === "object" && value !== null;
|
|
432
|
+
}
|
|
433
|
+
function count(value) {
|
|
434
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : null;
|
|
435
|
+
}
|
|
436
|
+
var TurnHooks = class _TurnHooks {
|
|
437
|
+
constructor(adapter, enabled) {
|
|
438
|
+
this.adapter = adapter;
|
|
439
|
+
this.enabled = enabled;
|
|
440
|
+
}
|
|
441
|
+
adapter;
|
|
442
|
+
enabled;
|
|
443
|
+
/** Runs held open at most; past it the oldest run's turn closes, incomplete (a run whose end never came). */
|
|
444
|
+
static MAX_OPEN = 100;
|
|
445
|
+
frames = /* @__PURE__ */ new Map();
|
|
446
|
+
calls = /* @__PURE__ */ new Map();
|
|
447
|
+
/** The turn of the run `key`: the session's turn in progress, or a new one of its own. */
|
|
448
|
+
open(session, key, params = {}) {
|
|
449
|
+
if (!this.enabled) return void 0;
|
|
450
|
+
const held = this.frames.get(key);
|
|
451
|
+
if (held !== void 0) return held.frame;
|
|
452
|
+
try {
|
|
453
|
+
const active = session.activeTurn();
|
|
454
|
+
if (active !== void 0 && !this.owns(active)) {
|
|
455
|
+
this.frames.set(key, { frame: active, own: false });
|
|
456
|
+
return active;
|
|
457
|
+
}
|
|
458
|
+
const frame = session.openTurn({ ...params, adapter: this.adapter });
|
|
459
|
+
this.frames.set(key, { frame, own: true });
|
|
460
|
+
if (this.frames.size > _TurnHooks.MAX_OPEN) {
|
|
461
|
+
const [oldest] = this.frames.keys();
|
|
462
|
+
if (oldest !== void 0) {
|
|
463
|
+
this.frames.get(oldest)?.frame.incomplete();
|
|
464
|
+
this.close(oldest);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return frame;
|
|
468
|
+
} catch (error) {
|
|
469
|
+
session.logger.warn(`could not open the turn (${errorName(error)})`);
|
|
470
|
+
return void 0;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
/** The turn of `key`, else the session's turn in progress. */
|
|
474
|
+
frame(session, key) {
|
|
475
|
+
if (!this.enabled) return void 0;
|
|
476
|
+
const held = key === void 0 ? void 0 : this.frames.get(key);
|
|
477
|
+
const frame = held?.frame ?? session.activeTurn();
|
|
478
|
+
return frame === void 0 || frame.closed ? void 0 : frame;
|
|
479
|
+
}
|
|
480
|
+
has(key) {
|
|
481
|
+
return this.frames.has(key);
|
|
482
|
+
}
|
|
483
|
+
owns(frame) {
|
|
484
|
+
for (const held of this.frames.values()) if (held.own && held.frame === frame) return true;
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
/** Ends the run `key`: a turn the adapter opened closes; the calls it left open failed. */
|
|
488
|
+
close(key, error) {
|
|
489
|
+
const held = this.frames.get(key);
|
|
490
|
+
if (held === void 0) return;
|
|
491
|
+
this.frames.delete(key);
|
|
492
|
+
for (const [callKey, call] of this.calls) {
|
|
493
|
+
if (call.frame !== held.frame) continue;
|
|
494
|
+
this.calls.delete(callKey);
|
|
495
|
+
if (held.own) call.failed(error ?? "error");
|
|
496
|
+
}
|
|
497
|
+
if (held.own) held.frame.close(error);
|
|
498
|
+
}
|
|
499
|
+
/** A tool call starting, keyed by `callKey`; `callId` is the provider's id of the call, when there is one. */
|
|
500
|
+
toolStart(session, callKey, name, args, options = {}) {
|
|
501
|
+
const frame = this.frame(session, options.frameKey);
|
|
502
|
+
if (frame === void 0) return;
|
|
503
|
+
try {
|
|
504
|
+
this.calls.set(callKey, frame.toolCall(name, args, { callId: options.callId ?? null, adoptable: true }));
|
|
505
|
+
} catch {
|
|
506
|
+
frame.incomplete();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* In a replay, how a framework tool the adapter stands in for answers: the recorded result of a call with the
|
|
511
|
+
* same arguments, or empty (a divergence), never the live tool. `null` outside a replay, and for a function
|
|
512
|
+
* wrapped with `tool()`, which answers itself.
|
|
513
|
+
*/
|
|
514
|
+
replayed(session, name, args, fn, frameKey) {
|
|
515
|
+
const frame = this.enabled ? this.frame(session, frameKey) : session.activeTurn();
|
|
516
|
+
if (frame?.playback == null || fn !== void 0 && recordedTool(fn) !== null) return null;
|
|
517
|
+
return frame.playback.answer(name, args, false);
|
|
518
|
+
}
|
|
519
|
+
toolEnd(callKey, result, error) {
|
|
520
|
+
const call = this.calls.get(callKey);
|
|
521
|
+
if (call === void 0) return;
|
|
522
|
+
this.calls.delete(callKey);
|
|
523
|
+
try {
|
|
524
|
+
if (error !== void 0) call.failed(error);
|
|
525
|
+
else call.result(result);
|
|
526
|
+
} catch {
|
|
527
|
+
call.frame.incomplete();
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
/** A model call that ended, with its tokens when the framework reported them. */
|
|
531
|
+
model(session, model, tokens = {}, frameKey) {
|
|
532
|
+
const frame = this.frame(session, frameKey);
|
|
533
|
+
if (frame === void 0) return;
|
|
534
|
+
try {
|
|
535
|
+
frame.modelCall(model, { tokensIn: tokens.in ?? null, tokensOut: tokens.out ?? null, tokensCached: tokens.cached ?? 0 });
|
|
536
|
+
} catch {
|
|
537
|
+
frame.incomplete();
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
// src/integrations/google-adk.ts
|
|
543
|
+
var MAX_SESSIONS = 1e4;
|
|
544
|
+
function niadraAdk(options) {
|
|
545
|
+
const bySession = /* @__PURE__ */ new Map();
|
|
546
|
+
const hooks = new TurnHooks("google-adk", options.turns ?? false);
|
|
547
|
+
const runKey = (context) => `${context.invocationId}:${context.agentName}`;
|
|
548
|
+
const fixed = typeof options.session === "function" ? null : newState(options.session, options);
|
|
549
|
+
const stateOf = (context) => {
|
|
550
|
+
if (fixed) return fixed;
|
|
551
|
+
const resolve = options.session;
|
|
552
|
+
const key = context.sessionId;
|
|
553
|
+
if (bySession.has(key)) return bySession.get(key) ?? null;
|
|
554
|
+
let state;
|
|
555
|
+
try {
|
|
556
|
+
const session = resolve(context);
|
|
557
|
+
state = session ? newState(session, options) : null;
|
|
558
|
+
} catch {
|
|
559
|
+
state = null;
|
|
560
|
+
}
|
|
561
|
+
bySession.set(key, state);
|
|
562
|
+
if (bySession.size > MAX_SESSIONS) {
|
|
563
|
+
const oldest = bySession.keys().next().value;
|
|
564
|
+
if (oldest !== void 0) bySession.delete(oldest);
|
|
565
|
+
}
|
|
566
|
+
return state;
|
|
567
|
+
};
|
|
568
|
+
const beforeModelCallback = async ({ context, request }) => {
|
|
569
|
+
const state = stateOf(context);
|
|
570
|
+
if (!state) return void 0;
|
|
571
|
+
state.model = request.model ?? state.model;
|
|
572
|
+
try {
|
|
573
|
+
const contents = request.contents;
|
|
574
|
+
const said = textOfParts(context.userContent?.parts);
|
|
575
|
+
if ((options.recordCustomer ?? true) && said && !state.seen.has(context.invocationId)) {
|
|
576
|
+
state.seen.add(context.invocationId);
|
|
577
|
+
if (state.seen.size > MAX_SESSIONS) state.seen.clear();
|
|
578
|
+
state.bridge.customer(said);
|
|
579
|
+
}
|
|
580
|
+
const read = await state.bridge.read();
|
|
581
|
+
state.bridge.injected(read.context);
|
|
582
|
+
if (read.prefix) {
|
|
583
|
+
const config = request.config ??= {};
|
|
584
|
+
const system = config.systemInstruction;
|
|
585
|
+
if (system === void 0 || system === "") config.systemInstruction = read.prefix;
|
|
586
|
+
else if (typeof system === "string") config.systemInstruction = `${system}
|
|
587
|
+
|
|
588
|
+
${read.prefix}`;
|
|
589
|
+
else if (isRecord(system) && Array.isArray(system.parts)) config.systemInstruction = { ...system, parts: [...system.parts, { text: read.prefix }] };
|
|
590
|
+
else if (Array.isArray(system)) config.systemInstruction = [...system, { text: read.prefix }];
|
|
591
|
+
}
|
|
592
|
+
if (read.suffix) {
|
|
593
|
+
for (let index = contents.length - 1; index >= 0; index--) {
|
|
594
|
+
const content = contents[index];
|
|
595
|
+
if (!content || (content.role ?? "user") !== "user" || !textOfParts(content.parts)) continue;
|
|
596
|
+
contents[index] = { ...content, parts: [...content.parts ?? [], { text: read.suffix }] };
|
|
597
|
+
break;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
} catch (error) {
|
|
601
|
+
state.bridge.logger.warn(`could not inject context (${errorName(error)})`);
|
|
602
|
+
}
|
|
603
|
+
return void 0;
|
|
604
|
+
};
|
|
605
|
+
const afterModelCallback = async ({ context, response }) => {
|
|
606
|
+
const state = stateOf(context);
|
|
607
|
+
if (!state || response.partial === true) return void 0;
|
|
608
|
+
const tokens = response.usageMetadata;
|
|
609
|
+
hooks.model(state.bridge.session, state.model || null, { in: count(tokens?.promptTokenCount), out: count(tokens?.candidatesTokenCount), cached: count(tokens?.cachedContentTokenCount) ?? 0 }, runKey(context));
|
|
610
|
+
try {
|
|
611
|
+
const parts = response.content?.parts ?? [];
|
|
612
|
+
const transfer = parts.find((part) => part.functionCall?.name === "transfer_to_agent")?.functionCall;
|
|
613
|
+
if (transfer) {
|
|
614
|
+
const target = isRecord(transfer.args) && typeof transfer.args.agent_name === "string" ? transfer.args.agent_name : void 0;
|
|
615
|
+
await state.bridge.handoff("agent", target ? `${context.agentName} to ${target}` : void 0);
|
|
616
|
+
return void 0;
|
|
617
|
+
}
|
|
618
|
+
if (!(options.recordAgent ?? true) || parts.some((part) => part.functionCall)) return void 0;
|
|
619
|
+
const text = textOfParts(parts, "");
|
|
620
|
+
if (!text) return void 0;
|
|
621
|
+
const usage = adkUsage(response, state.model);
|
|
622
|
+
state.bridge.agent(text, usage ? { usage } : {});
|
|
623
|
+
} catch (error) {
|
|
624
|
+
state.bridge.logger.warn(`could not record the agent's answer (${errorName(error)})`);
|
|
625
|
+
}
|
|
626
|
+
return void 0;
|
|
627
|
+
};
|
|
628
|
+
const memory = options.agentMemory;
|
|
629
|
+
const definitions = [
|
|
630
|
+
...TOOL_DEFINITIONS,
|
|
631
|
+
...memory ? AGENT_MEMORY_TOOL_DEFINITIONS.slice(0, memory !== true && memory.write ? 2 : 1) : []
|
|
632
|
+
];
|
|
633
|
+
const tools = definitions.map(({ function: definition }) => new NiadraTool(definition, (context) => stateOf(context)));
|
|
634
|
+
const beforeAgentCallback = (context) => {
|
|
635
|
+
const state = stateOf(context);
|
|
636
|
+
if (state) hooks.open(state.bridge.session, runKey(context), { agent: context.agentName });
|
|
637
|
+
return void 0;
|
|
638
|
+
};
|
|
639
|
+
const afterAgentCallback = (context) => {
|
|
640
|
+
hooks.close(runKey(context));
|
|
641
|
+
return void 0;
|
|
642
|
+
};
|
|
643
|
+
const beforeToolCallback = ({ tool, args, context }) => {
|
|
644
|
+
const state = stateOf(context);
|
|
645
|
+
if (!state) return void 0;
|
|
646
|
+
const key = context.functionCallId ?? `${tool.name}:${context.invocationId}`;
|
|
647
|
+
hooks.toolStart(state.bridge.session, key, tool.name, args, { frameKey: runKey(context), callId: context.functionCallId ?? null });
|
|
648
|
+
const played = hooks.replayed(state.bridge.session, tool.name, args, tool.execute, runKey(context));
|
|
649
|
+
if (played === null) return void 0;
|
|
650
|
+
const answer = played.recorded && isRecord(played.value) ? played.value : {};
|
|
651
|
+
hooks.toolEnd(key, answer);
|
|
652
|
+
return answer;
|
|
653
|
+
};
|
|
654
|
+
const afterToolCallback = ({ tool, context, response }) => {
|
|
655
|
+
hooks.toolEnd(context.functionCallId ?? `${tool.name}:${context.invocationId}`, response);
|
|
656
|
+
return void 0;
|
|
657
|
+
};
|
|
658
|
+
return { beforeModelCallback, afterModelCallback, beforeAgentCallback, afterAgentCallback, beforeToolCallback, afterToolCallback, tools };
|
|
659
|
+
}
|
|
660
|
+
function adkUsage(response, model) {
|
|
661
|
+
const usage = response.usageMetadata;
|
|
662
|
+
const prompt = count(usage?.promptTokenCount);
|
|
663
|
+
const name = (response.modelVersion ?? model).replace(/^models\//, "");
|
|
664
|
+
if (prompt === null || !name) return null;
|
|
665
|
+
const cached = count(usage?.cachedContentTokenCount) ?? 0;
|
|
666
|
+
return { provider: providerOf(name), model: name, prompt_tokens: Math.max(prompt, cached), cached_tokens: cached, cache_write_tokens: 0 };
|
|
667
|
+
}
|
|
668
|
+
var NiadraTool = class extends BaseTool {
|
|
669
|
+
constructor(definition, stateOf) {
|
|
670
|
+
super({ name: definition.name, description: definition.description });
|
|
671
|
+
this.definition = definition;
|
|
672
|
+
this.stateOf = stateOf;
|
|
673
|
+
}
|
|
674
|
+
definition;
|
|
675
|
+
stateOf;
|
|
676
|
+
_getDeclaration() {
|
|
677
|
+
return { name: this.definition.name, description: this.definition.description, parametersJsonSchema: this.definition.parameters };
|
|
678
|
+
}
|
|
679
|
+
async runAsync({ args, toolContext }) {
|
|
680
|
+
const state = this.stateOf(toolContext);
|
|
681
|
+
const spec = state?.bridge.tools().find((candidate) => candidate.name === this.name);
|
|
682
|
+
if (!spec) return { error: "unavailable", detail: "customer history is unavailable right now" };
|
|
683
|
+
const text = await spec.execute(args);
|
|
684
|
+
try {
|
|
685
|
+
return JSON.parse(text);
|
|
686
|
+
} catch {
|
|
687
|
+
return { result: text };
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
function newState(session, options) {
|
|
692
|
+
return { bridge: new Bridge(session, options.verify, options.agentMemory), seen: /* @__PURE__ */ new Set(), model: "" };
|
|
693
|
+
}
|
|
694
|
+
function textOfParts(parts, separator = "\n") {
|
|
695
|
+
if (!Array.isArray(parts)) return "";
|
|
696
|
+
return parts.map((part) => isRecord(part) && typeof part.text === "string" && part.thought !== true ? part.text : "").filter(Boolean).join(separator);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
export { adkUsage, attestationProof, niadraAdk };
|
|
700
|
+
//# sourceMappingURL=google-adk.js.map
|
|
701
|
+
//# sourceMappingURL=google-adk.js.map
|