@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
package/dist/ai-sdk.js
ADDED
|
@@ -0,0 +1,1030 @@
|
|
|
1
|
+
import { tool as tool$1, jsonSchema } from 'ai';
|
|
2
|
+
|
|
3
|
+
// src/integrations/ai-sdk.ts
|
|
4
|
+
|
|
5
|
+
// src/constraints/binding.ts
|
|
6
|
+
function parseBinding(raw, families = {}) {
|
|
7
|
+
return {
|
|
8
|
+
tool: raw.tool,
|
|
9
|
+
args: (raw.args ?? []).map((a) => ({
|
|
10
|
+
attr: a.attr,
|
|
11
|
+
param: a.param,
|
|
12
|
+
transform: a.transform ?? null,
|
|
13
|
+
negation: a.negation?.param ?? null,
|
|
14
|
+
ops: [...a.ops ?? []],
|
|
15
|
+
family: families[a.attr] ?? null
|
|
16
|
+
})),
|
|
17
|
+
overfetch: raw.overfetch ?? raw.capabilities?.overfetch ?? false
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function resultItems(raw, result) {
|
|
21
|
+
const out = [];
|
|
22
|
+
for (const spec of raw.results ?? []) {
|
|
23
|
+
for (const found2 of readPath(result, spec.path ?? "$")) {
|
|
24
|
+
if (typeof found2 !== "object" || found2 === null || Array.isArray(found2)) continue;
|
|
25
|
+
const entry = found2;
|
|
26
|
+
const item = {};
|
|
27
|
+
for (const [field, key] of Object.entries(spec.fields ?? {})) if (key in entry) item[`${String(spec.type)}.${field}`] = entry[key];
|
|
28
|
+
const ident = entry[spec.id ?? "id"];
|
|
29
|
+
if (typeof ident === "string" || typeof ident === "number") item.ref = `${String(spec.type)}:${spec.namespace ?? "default"}:${String(ident)}`;
|
|
30
|
+
out.push(item);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
function relaxed(raw, result) {
|
|
36
|
+
const path = raw.capabilities?.relax_flag;
|
|
37
|
+
return typeof path === "string" && readPath(result, path).some((v) => v === true);
|
|
38
|
+
}
|
|
39
|
+
function readPath(value, path) {
|
|
40
|
+
let found2 = [value];
|
|
41
|
+
const trimmed = path.replace(/^\$/, "").replace(/^\.+|\.+$/g, "");
|
|
42
|
+
if (!trimmed) return found2;
|
|
43
|
+
for (const part of trimmed.split(".")) {
|
|
44
|
+
const many = part.endsWith("[*]");
|
|
45
|
+
const key = many ? part.slice(0, -3) : part;
|
|
46
|
+
const step = [];
|
|
47
|
+
for (const current of found2) {
|
|
48
|
+
const got = key ? typeof current === "object" && current !== null ? current[key] : void 0 : current;
|
|
49
|
+
if (many) {
|
|
50
|
+
if (Array.isArray(got)) step.push(...got);
|
|
51
|
+
} else if (got !== void 0 && got !== null) step.push(got);
|
|
52
|
+
}
|
|
53
|
+
found2 = step;
|
|
54
|
+
}
|
|
55
|
+
return found2;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/claims/text.ts
|
|
59
|
+
var WORD_CHARS = String.raw`\p{L}\p{N}_`;
|
|
60
|
+
var SPACE_CHARS = String.raw`\t-\r\x1c-\x20\x85\xa0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000`;
|
|
61
|
+
var CLASSES = { w: WORD_CHARS, d: String.raw`\p{Nd}`, s: SPACE_CHARS };
|
|
62
|
+
var BOUNDARY = `(?:(?<=[${WORD_CHARS}])(?![${WORD_CHARS}])|(?<![${WORD_CHARS}])(?=[${WORD_CHARS}]))`;
|
|
63
|
+
function pattern(source, flags = "") {
|
|
64
|
+
let out = "";
|
|
65
|
+
let inClass = false;
|
|
66
|
+
for (let i = 0; i < source.length; i++) {
|
|
67
|
+
const ch = source.charAt(i);
|
|
68
|
+
if (ch === "\\") {
|
|
69
|
+
const next = source.charAt(++i);
|
|
70
|
+
const chars = CLASSES[next];
|
|
71
|
+
if (chars !== void 0) out += inClass ? chars : `[${chars}]`;
|
|
72
|
+
else if (next === "b" && !inClass) out += BOUNDARY;
|
|
73
|
+
else out += next === "Z" && !inClass ? "$" : `\\${next}`;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (ch === "[") inClass = true;
|
|
77
|
+
else if (ch === "]") inClass = false;
|
|
78
|
+
out += ch === "$" && !inClass ? String.raw`(?=\n?$)` : ch;
|
|
79
|
+
}
|
|
80
|
+
return new RegExp(out, `${flags}u`);
|
|
81
|
+
}
|
|
82
|
+
function memo(compute, size = 256) {
|
|
83
|
+
const cache = /* @__PURE__ */ new Map();
|
|
84
|
+
return (text) => {
|
|
85
|
+
const hit = cache.get(text);
|
|
86
|
+
if (hit !== void 0) return hit;
|
|
87
|
+
const value = compute(text);
|
|
88
|
+
const oldest = cache.keys().next();
|
|
89
|
+
if (cache.size >= size && !oldest.done) cache.delete(oldest.value);
|
|
90
|
+
cache.set(text, value);
|
|
91
|
+
return value;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
var ASCII = /^\p{ASCII}*$/u;
|
|
95
|
+
var MARK = /^[\p{Mn}\p{Mc}]$/u;
|
|
96
|
+
function combining(c) {
|
|
97
|
+
if (!MARK.test(c)) return false;
|
|
98
|
+
const run = `\u0301${c}\u0316`;
|
|
99
|
+
return run.normalize("NFD") !== run;
|
|
100
|
+
}
|
|
101
|
+
function plain(text) {
|
|
102
|
+
let out = "";
|
|
103
|
+
for (const c of text.normalize("NFKD")) if (!combining(c)) out += c;
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
var fold = memo((text) => {
|
|
107
|
+
if (ASCII.test(text)) return text.toLowerCase();
|
|
108
|
+
let out = "";
|
|
109
|
+
for (const ch of text) {
|
|
110
|
+
const folded2 = plain(ch).toLowerCase();
|
|
111
|
+
out += Array.from(folded2).length === 1 ? folded2 : "?";
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
});
|
|
115
|
+
pattern(String.raw`[!?;](?=\s|$)|\.(?=\s+[A-ZÀ-Ý]|\s*$)|\n`, "g");
|
|
116
|
+
|
|
117
|
+
// src/constraints/render.ts
|
|
118
|
+
var SAID = /* @__PURE__ */ new Set(["stated", "tool_args", "correction"]);
|
|
119
|
+
var NEGATED = /* @__PURE__ */ new Set(["not_in", "ne"]);
|
|
120
|
+
var POSITIVE = /* @__PURE__ */ new Set(["in", "eq"]);
|
|
121
|
+
function render(block, binding, call, mode = "advisory") {
|
|
122
|
+
if ((block.subject?.for ?? "self") !== (call.for ?? "self")) {
|
|
123
|
+
const args2 = { ...call.args };
|
|
124
|
+
return { applies: false, args: args2, suggested: {}, injected: [], hardSent: [], residual: [], postFilter: [], conflicts: [] };
|
|
125
|
+
}
|
|
126
|
+
const hard = block.hard ?? [];
|
|
127
|
+
const attributes = block.attributes ?? [];
|
|
128
|
+
const lost = new Set((block.conflicts ?? []).flatMap((c) => c.ids.filter((id) => id !== c.kept)));
|
|
129
|
+
const category = call.category ?? null;
|
|
130
|
+
const suggested = /* @__PURE__ */ new Map();
|
|
131
|
+
const sources = /* @__PURE__ */ new Map();
|
|
132
|
+
const residual = [];
|
|
133
|
+
const conflicts = [];
|
|
134
|
+
const routed = [];
|
|
135
|
+
for (const h of hard) {
|
|
136
|
+
if (lost.has(h.id) || h.category != null && h.category !== category) continue;
|
|
137
|
+
const route = routeOf(h, binding);
|
|
138
|
+
if (!route) {
|
|
139
|
+
residual.push(h.id);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const [arg, param] = route;
|
|
143
|
+
let value = shape(h.values, arg.transform);
|
|
144
|
+
if (suggested.has(param)) {
|
|
145
|
+
if (!POSITIVE.has(h.op) && !NEGATED.has(h.op)) {
|
|
146
|
+
residual.push(h.id);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const before = asList(suggested.get(param));
|
|
150
|
+
const merged = [...before, ...asList(value).filter((v) => !before.includes(v))];
|
|
151
|
+
value = merged.length === 1 ? merged[0] : merged;
|
|
152
|
+
}
|
|
153
|
+
suggested.set(param, value);
|
|
154
|
+
sources.set(param, [...sources.get(param) ?? [], h.id]);
|
|
155
|
+
routed.push([h, param]);
|
|
156
|
+
if (against(h, arg, call.args)) conflicts.push({ id: h.id, param: arg.param });
|
|
157
|
+
}
|
|
158
|
+
const asked = new Set(call.asked ?? []);
|
|
159
|
+
for (const a of attributes) {
|
|
160
|
+
const family = a.name.split(".")[0] ?? a.name;
|
|
161
|
+
if (a.category != null && a.category !== category) continue;
|
|
162
|
+
if (a.apply !== "always" && !asked.has(family) && !asked.has(a.name)) continue;
|
|
163
|
+
const carrier = binding.args.find((b) => b.family === family);
|
|
164
|
+
if (carrier && !suggested.has(carrier.param)) {
|
|
165
|
+
suggested.set(carrier.param, shape([a.value], carrier.transform));
|
|
166
|
+
sources.set(carrier.param, [a.id]);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if ((block.exclude ?? []).length > 0) residual.push("exclude");
|
|
170
|
+
const args = new Map(Object.entries(call.args));
|
|
171
|
+
const injected = [];
|
|
172
|
+
if (mode === "apply") {
|
|
173
|
+
const disputed = new Set(conflicts.map((c) => c.id));
|
|
174
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
175
|
+
...hard.filter((h) => SAID.has(h.source) && (h.scope === "turn" || h.scope === "session") && !disputed.has(h.id)).map((h) => h.id),
|
|
176
|
+
...attributes.filter((a) => a.source === "stated" || a.source === "correction").map((a) => a.id)
|
|
177
|
+
]);
|
|
178
|
+
for (const [param, value] of suggested) {
|
|
179
|
+
const ids = sources.get(param) ?? [];
|
|
180
|
+
if (!args.has(param) && ids.every((id) => allowed.has(id))) {
|
|
181
|
+
args.set(param, value);
|
|
182
|
+
injected.push(...ids);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const hardSent = routed.filter(([h, param]) => sent(h, param, args)).map(([h]) => h.id);
|
|
187
|
+
return {
|
|
188
|
+
applies: true,
|
|
189
|
+
args: Object.fromEntries(args),
|
|
190
|
+
suggested: Object.fromEntries(suggested),
|
|
191
|
+
injected,
|
|
192
|
+
hardSent,
|
|
193
|
+
residual,
|
|
194
|
+
postFilter: binding.overfetch ? [...residual] : [],
|
|
195
|
+
conflicts
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function honored(block, sentIds, results) {
|
|
199
|
+
const checks = (block.hard ?? []).filter((h) => sentIds.includes(h.id));
|
|
200
|
+
let violations = 0;
|
|
201
|
+
let unverifiable = 0;
|
|
202
|
+
for (const item of results) {
|
|
203
|
+
if (checks.some((h) => item[h.attr] != null && !satisfies(h.op, h.values, item[h.attr]))) violations++;
|
|
204
|
+
else if (checks.some((h) => item[h.attr] == null)) unverifiable++;
|
|
205
|
+
}
|
|
206
|
+
return { resultsChecked: results.length, violations, unverifiable };
|
|
207
|
+
}
|
|
208
|
+
function satisfies(op, values, value) {
|
|
209
|
+
const got = keyOf(value);
|
|
210
|
+
const want = values.map(keyOf);
|
|
211
|
+
const first = want[0];
|
|
212
|
+
switch (op) {
|
|
213
|
+
case "in":
|
|
214
|
+
case "eq":
|
|
215
|
+
return want.some((w) => same(got, w));
|
|
216
|
+
case "not_in":
|
|
217
|
+
case "ne":
|
|
218
|
+
return !want.some((w) => same(got, w));
|
|
219
|
+
case "lt":
|
|
220
|
+
return holds(compare(got, first), (c) => c < 0);
|
|
221
|
+
case "lte":
|
|
222
|
+
return holds(compare(got, first), (c) => c <= 0);
|
|
223
|
+
case "gt":
|
|
224
|
+
return holds(compare(got, first), (c) => c > 0);
|
|
225
|
+
case "gte":
|
|
226
|
+
return holds(compare(got, first), (c) => c >= 0);
|
|
227
|
+
case "between":
|
|
228
|
+
return holds(compare(first, got), (c) => c <= 0) && holds(compare(got, want[1]), (c) => c <= 0);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function shape(values, transform) {
|
|
232
|
+
const out = values.map((v) => {
|
|
233
|
+
if (typeof v !== "string") return v;
|
|
234
|
+
return transform === "lower" ? v.toLowerCase() : transform === "upper" ? v.toUpperCase() : v;
|
|
235
|
+
});
|
|
236
|
+
return out.length === 1 ? out[0] : out;
|
|
237
|
+
}
|
|
238
|
+
function asList(value) {
|
|
239
|
+
return Array.isArray(value) ? [...value] : [value];
|
|
240
|
+
}
|
|
241
|
+
function routeOf(h, binding) {
|
|
242
|
+
for (const arg of binding.args) {
|
|
243
|
+
if (arg.attr !== h.attr) continue;
|
|
244
|
+
const ops = arg.ops ?? [];
|
|
245
|
+
if (POSITIVE.has(h.op) && (ops.length === 0 || ops.includes(h.op) || ops.includes("in"))) return [arg, arg.param];
|
|
246
|
+
if (NEGATED.has(h.op) && arg.negation != null) return [arg, arg.negation];
|
|
247
|
+
if (!POSITIVE.has(h.op) && !NEGATED.has(h.op) && ops.includes(h.op)) return [arg, arg.param];
|
|
248
|
+
}
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
function sent(h, param, args) {
|
|
252
|
+
if (!args.has(param)) return false;
|
|
253
|
+
const given = asList(args.get(param));
|
|
254
|
+
if (NEGATED.has(h.op)) return h.values.every((v) => satisfies("in", given, v));
|
|
255
|
+
if (POSITIVE.has(h.op)) return given.every((v) => satisfies("in", h.values, v));
|
|
256
|
+
return given.every((v) => satisfies(h.op, h.values, v));
|
|
257
|
+
}
|
|
258
|
+
function against(h, arg, args) {
|
|
259
|
+
if (!Object.hasOwn(args, arg.param)) return false;
|
|
260
|
+
return asList(args[arg.param]).some((v) => !satisfies(h.op, h.values, v));
|
|
261
|
+
}
|
|
262
|
+
var DECIMAL = /^([+-]?)(?:(\d+)(?:\.(\d*))?|\.(\d+))(?:e([+-]?\d+))?$/i;
|
|
263
|
+
var OTHER = { kind: "other" };
|
|
264
|
+
function keyOf(value) {
|
|
265
|
+
if (typeof value === "string") {
|
|
266
|
+
return decimal(value.trim().replace(/_/g, "")) ?? { kind: "text", text: fold(value).trim() };
|
|
267
|
+
}
|
|
268
|
+
const number = typeof value === "boolean" ? Number(value) : value;
|
|
269
|
+
return typeof number === "number" && Number.isFinite(number) ? decimal(String(number)) ?? OTHER : OTHER;
|
|
270
|
+
}
|
|
271
|
+
function decimal(text) {
|
|
272
|
+
const m = DECIMAL.exec(text);
|
|
273
|
+
if (!m) return null;
|
|
274
|
+
const fraction = m[3] ?? m[4] ?? "";
|
|
275
|
+
const all = `${m[2] ?? ""}${fraction}`.replace(/^0+/, "");
|
|
276
|
+
const digits = all.replace(/0+$/, "");
|
|
277
|
+
if (!digits) return { kind: "number", sign: 0, digits: "", exponent: 0 };
|
|
278
|
+
const exponent = Number(m[5] ?? 0) - fraction.length + (all.length - digits.length);
|
|
279
|
+
return { kind: "number", sign: m[1] === "-" ? -1 : 1, digits, exponent };
|
|
280
|
+
}
|
|
281
|
+
function same(a, b) {
|
|
282
|
+
if (a.kind === "number" && b?.kind === "number") {
|
|
283
|
+
return a.sign === b.sign && a.digits === b.digits && a.exponent === b.exponent;
|
|
284
|
+
}
|
|
285
|
+
return a.kind === "text" && b?.kind === "text" && a.text === b.text;
|
|
286
|
+
}
|
|
287
|
+
function compare(a, b) {
|
|
288
|
+
if (a?.kind === "text" && b?.kind === "text") return a.text < b.text ? -1 : a.text > b.text ? 1 : 0;
|
|
289
|
+
if (a?.kind !== "number" || b?.kind !== "number") return null;
|
|
290
|
+
if (a.sign !== b.sign) return a.sign < b.sign ? -1 : 1;
|
|
291
|
+
if (a.sign === 0) return 0;
|
|
292
|
+
const lead = a.digits.length + a.exponent - (b.digits.length + b.exponent);
|
|
293
|
+
if (lead !== 0) return lead * a.sign < 0 ? -1 : 1;
|
|
294
|
+
const width = Math.max(a.digits.length, b.digits.length);
|
|
295
|
+
const left = a.digits.padEnd(width, "0");
|
|
296
|
+
const right = b.digits.padEnd(width, "0");
|
|
297
|
+
return left === right ? 0 : (left < right ? -1 : 1) * a.sign;
|
|
298
|
+
}
|
|
299
|
+
function holds(order, test) {
|
|
300
|
+
return order !== null && test(order);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// src/capture/context.ts
|
|
304
|
+
var chosen;
|
|
305
|
+
var stores = /* @__PURE__ */ new Map();
|
|
306
|
+
function storeClass() {
|
|
307
|
+
if (chosen !== void 0) return chosen;
|
|
308
|
+
try {
|
|
309
|
+
const proc = globalThis.process;
|
|
310
|
+
const hooks = proc?.getBuiltinModule?.("node:async_hooks");
|
|
311
|
+
chosen = hooks?.AsyncLocalStorage ?? null;
|
|
312
|
+
} catch {
|
|
313
|
+
chosen = null;
|
|
314
|
+
}
|
|
315
|
+
return chosen;
|
|
316
|
+
}
|
|
317
|
+
function store(name) {
|
|
318
|
+
const existing = stores.get(name);
|
|
319
|
+
if (existing) return existing;
|
|
320
|
+
const Class = storeClass();
|
|
321
|
+
if (!Class) return null;
|
|
322
|
+
const created = new Class();
|
|
323
|
+
stores.set(name, created);
|
|
324
|
+
return created;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/capture/frame.ts
|
|
328
|
+
var turns = () => store("niadra_turn");
|
|
329
|
+
function currentTurn() {
|
|
330
|
+
return turns()?.getStore();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/capture/mask.ts
|
|
334
|
+
var MASKED = "[masked]";
|
|
335
|
+
var WITHHELD = "[withheld: the fields this agent may read are not known yet]";
|
|
336
|
+
function protect(result, access, types, onUnknown) {
|
|
337
|
+
if (access === null) return onUnknown === "block" ? WITHHELD : result;
|
|
338
|
+
const rules = /* @__PURE__ */ new Map();
|
|
339
|
+
for (const name of types ?? Object.keys(access)) {
|
|
340
|
+
for (const [field, effect] of Object.entries(access[name] ?? {})) rules.set(field, effect === "deny" || rules.get(field) === "deny" ? "deny" : effect);
|
|
341
|
+
}
|
|
342
|
+
if (rules.size === 0) return result;
|
|
343
|
+
if (typeof result === "string" && /^\s*[[{]/.test(result)) {
|
|
344
|
+
try {
|
|
345
|
+
return JSON.stringify(walk(JSON.parse(result), rules));
|
|
346
|
+
} catch {
|
|
347
|
+
return result;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return walk(result, rules);
|
|
351
|
+
}
|
|
352
|
+
function walk(value, rules) {
|
|
353
|
+
if (Array.isArray(value)) return value.map((v) => walk(v, rules));
|
|
354
|
+
if (typeof value !== "object" || value === null) return value;
|
|
355
|
+
const out = {};
|
|
356
|
+
for (const [key, v] of Object.entries(value)) {
|
|
357
|
+
const effect = rules.get(key);
|
|
358
|
+
if (effect === "deny") continue;
|
|
359
|
+
out[key] = effect === "mask" ? MASKED : walk(v, rules);
|
|
360
|
+
}
|
|
361
|
+
return out;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// src/capture/tool.ts
|
|
365
|
+
var RECORDED = /* @__PURE__ */ Symbol.for("niadra.tool");
|
|
366
|
+
function recordedTool(fn) {
|
|
367
|
+
return typeof fn === "function" ? fn[RECORDED] ?? null : null;
|
|
368
|
+
}
|
|
369
|
+
var isAsyncFunction = (fn) => Object.prototype.toString.call(fn) === "[object AsyncFunction]";
|
|
370
|
+
function isAsyncIterator(value) {
|
|
371
|
+
return typeof value === "object" && value !== null && typeof value.next === "function" && Symbol.asyncIterator in value;
|
|
372
|
+
}
|
|
373
|
+
function found(frame) {
|
|
374
|
+
try {
|
|
375
|
+
return frame?.() ?? void 0;
|
|
376
|
+
} catch {
|
|
377
|
+
return void 0;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
function thenable(value) {
|
|
381
|
+
return typeof value === "object" && value !== null && typeof value.then === "function";
|
|
382
|
+
}
|
|
383
|
+
function tool(name, fn, options = {}) {
|
|
384
|
+
const isAsync = isAsyncFunction(fn);
|
|
385
|
+
function bindingOf(frame) {
|
|
386
|
+
return options.binding ?? (options.served ?? frame?.profile.bindings)?.(name) ?? null;
|
|
387
|
+
}
|
|
388
|
+
function masks(frame) {
|
|
389
|
+
return options.maskOutput ?? bindingOf(frame)?.capabilities?.mask_output ?? false;
|
|
390
|
+
}
|
|
391
|
+
function shield(result, frame) {
|
|
392
|
+
if (!masks(frame)) return result;
|
|
393
|
+
const access = options.access ?? frame?.profile.fieldAccess ?? (() => null);
|
|
394
|
+
return protect(result, access(), typesOf(result), options.onUnknown ?? "pass");
|
|
395
|
+
}
|
|
396
|
+
function typesOf(result) {
|
|
397
|
+
if (!options.provenance) return null;
|
|
398
|
+
try {
|
|
399
|
+
const found2 = options.provenance(result);
|
|
400
|
+
const items = found2 == null ? [] : Array.isArray(found2) ? found2 : [found2];
|
|
401
|
+
return items.map((o) => o.ref.split(":")[0] ?? "");
|
|
402
|
+
} catch {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
function end(call, result, model = result) {
|
|
407
|
+
const observations = observed(call, result);
|
|
408
|
+
let shown;
|
|
409
|
+
if (options.ui) {
|
|
410
|
+
try {
|
|
411
|
+
shown = options.ui(result);
|
|
412
|
+
} catch {
|
|
413
|
+
call.frame.incomplete();
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
call.result(model, { ui: shown, observations });
|
|
417
|
+
}
|
|
418
|
+
function observed(call, result) {
|
|
419
|
+
if (!options.provenance) return [];
|
|
420
|
+
try {
|
|
421
|
+
const found2 = options.provenance(result);
|
|
422
|
+
if (found2 == null) return [];
|
|
423
|
+
const items = Array.isArray(found2) ? found2 : [found2];
|
|
424
|
+
return items.filter((o) => typeof o.ref === "string" && typeof o.fields === "object");
|
|
425
|
+
} catch {
|
|
426
|
+
call.frame.incomplete();
|
|
427
|
+
return [];
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
async function* pieces(call, source) {
|
|
431
|
+
const kept = [];
|
|
432
|
+
try {
|
|
433
|
+
for await (const piece of source) {
|
|
434
|
+
const shown = shield(piece, call.frame);
|
|
435
|
+
kept.push(shown);
|
|
436
|
+
yield shown;
|
|
437
|
+
}
|
|
438
|
+
} catch (error) {
|
|
439
|
+
call.failed(error);
|
|
440
|
+
throw error;
|
|
441
|
+
}
|
|
442
|
+
end(call, kept);
|
|
443
|
+
}
|
|
444
|
+
const wrapped = function(...args) {
|
|
445
|
+
const frame = currentTurn() ?? found(options.frame);
|
|
446
|
+
if (frame === void 0 || frame.closed) {
|
|
447
|
+
if (!masks(frame)) return fn.apply(this, args);
|
|
448
|
+
const out = fn.apply(this, args);
|
|
449
|
+
if (isAsyncIterator(out)) return maskedPieces(out, frame);
|
|
450
|
+
return thenable(out) ? Promise.resolve(out).then((v) => shield(v, frame)) : shield(out, frame);
|
|
451
|
+
}
|
|
452
|
+
let recorded;
|
|
453
|
+
let callId;
|
|
454
|
+
try {
|
|
455
|
+
recorded = options.args ? options.args(...args) : args.length === 1 ? args[0] : args;
|
|
456
|
+
callId = options.callId?.(...args);
|
|
457
|
+
} catch {
|
|
458
|
+
recorded = args;
|
|
459
|
+
}
|
|
460
|
+
const call = frame.adopt(name, recorded) ?? frame.toolCall(name, recorded, typeof callId === "string" && callId ? { callId } : {});
|
|
461
|
+
const binding = bindingOf(frame);
|
|
462
|
+
if (binding !== null && frame.constraints !== null) call.measure = measure(frame, binding, recorded);
|
|
463
|
+
if (frame.playback !== null) call.played = frame.playback.answer(name, recorded, options.dryRun ?? false);
|
|
464
|
+
if (call.played !== null && !call.played.live) {
|
|
465
|
+
const value = call.played.value;
|
|
466
|
+
end(call, value);
|
|
467
|
+
return isAsync ? Promise.resolve(value) : value;
|
|
468
|
+
}
|
|
469
|
+
let result;
|
|
470
|
+
try {
|
|
471
|
+
result = call.run(() => fn.apply(this, args));
|
|
472
|
+
} catch (error) {
|
|
473
|
+
call.failed(error);
|
|
474
|
+
throw error;
|
|
475
|
+
}
|
|
476
|
+
if (isAsyncIterator(result)) return pieces(call, result);
|
|
477
|
+
if (thenable(result)) {
|
|
478
|
+
return Promise.resolve(result).then(
|
|
479
|
+
(value) => {
|
|
480
|
+
const shown2 = shield(value, frame);
|
|
481
|
+
end(call, value, shown2);
|
|
482
|
+
return shown2;
|
|
483
|
+
},
|
|
484
|
+
(error) => {
|
|
485
|
+
call.failed(error);
|
|
486
|
+
throw error;
|
|
487
|
+
}
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
const shown = shield(result, frame);
|
|
491
|
+
end(call, result, shown);
|
|
492
|
+
return shown;
|
|
493
|
+
};
|
|
494
|
+
async function* maskedPieces(source, frame) {
|
|
495
|
+
for await (const piece of source) yield shield(piece, frame);
|
|
496
|
+
}
|
|
497
|
+
Object.defineProperty(wrapped, "name", { value: fn.name || name });
|
|
498
|
+
const marker = {
|
|
499
|
+
name,
|
|
500
|
+
dryRun: options.dryRun ?? false,
|
|
501
|
+
provenance: options.provenance ?? null,
|
|
502
|
+
binding: options.binding ?? null
|
|
503
|
+
};
|
|
504
|
+
Object.defineProperty(wrapped, RECORDED, { value: marker });
|
|
505
|
+
return wrapped;
|
|
506
|
+
}
|
|
507
|
+
function measure(frame, raw, args) {
|
|
508
|
+
const block = frame.constraints;
|
|
509
|
+
if (block === null) return null;
|
|
510
|
+
const given = typeof args === "object" && args !== null && !Array.isArray(args) ? args : {};
|
|
511
|
+
const rendering = render(block, parseBinding(raw, frame.profile.families?.() ?? {}), { args: given });
|
|
512
|
+
if (!rendering.applies) return null;
|
|
513
|
+
return (result) => {
|
|
514
|
+
const seen = honored(block, rendering.hardSent, resultItems(raw, result));
|
|
515
|
+
return {
|
|
516
|
+
constraints: block.version,
|
|
517
|
+
hard_sent: [...rendering.hardSent],
|
|
518
|
+
results_checked: seen.resultsChecked,
|
|
519
|
+
violations: seen.violations,
|
|
520
|
+
unverifiable: seen.unverifiable,
|
|
521
|
+
...relaxed(raw, result) ? { relaxed: "declared" } : {}
|
|
522
|
+
};
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// src/context.ts
|
|
527
|
+
function emptyResult(error) {
|
|
528
|
+
return { text: "", suffix: "", variables: {}, pack: null, source: "none", response: null, error, constraints: null, state: null, coordination: null };
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// src/integrations/shared.ts
|
|
532
|
+
var ATTESTED = { A: "V2", B: "V1", C: "V1" };
|
|
533
|
+
function attestationProof(attestation) {
|
|
534
|
+
if (!attestation) return null;
|
|
535
|
+
const value = attestation.trim().toUpperCase();
|
|
536
|
+
if (value.includes("FAILED") || value.startsWith("NO-")) return null;
|
|
537
|
+
const letter = value.length === 1 ? value : /PASSED-([ABC])$/.exec(value)?.[1];
|
|
538
|
+
const level = letter ? ATTESTED[letter] : void 0;
|
|
539
|
+
return level ? { method: "network_attestation", level } : null;
|
|
540
|
+
}
|
|
541
|
+
function resolveSession(source) {
|
|
542
|
+
if (typeof source !== "function") return source;
|
|
543
|
+
try {
|
|
544
|
+
return source() ?? null;
|
|
545
|
+
} catch {
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
function isConversation(session) {
|
|
550
|
+
return "customer" in session && typeof session.customer === "function";
|
|
551
|
+
}
|
|
552
|
+
function errorName(error) {
|
|
553
|
+
return error instanceof Error ? error.name : typeof error;
|
|
554
|
+
}
|
|
555
|
+
var Bridge = class {
|
|
556
|
+
constructor(session, proof, memory = false) {
|
|
557
|
+
this.session = session;
|
|
558
|
+
this.proof = proof;
|
|
559
|
+
this.memory = memory;
|
|
560
|
+
}
|
|
561
|
+
session;
|
|
562
|
+
proof;
|
|
563
|
+
memory;
|
|
564
|
+
proving = null;
|
|
565
|
+
/** `begin()` started the first read of a call: the first `context()` waits for it with `ready()`. */
|
|
566
|
+
begun = false;
|
|
567
|
+
opened = false;
|
|
568
|
+
/**
|
|
569
|
+
* The context and, when enabled, the agent's notes, read side by side within the same budget.
|
|
570
|
+
* Never rejects.
|
|
571
|
+
*/
|
|
572
|
+
async read(options = {}) {
|
|
573
|
+
const memoryParams = this.memory === false ? null : this.memory === true ? {} : withoutWrite(this.memory);
|
|
574
|
+
const [context, memory] = await Promise.all([
|
|
575
|
+
this.context(options),
|
|
576
|
+
memoryParams ? this.agentMemory(memoryParams, options) : Promise.resolve("")
|
|
577
|
+
]);
|
|
578
|
+
return { context, memory, prefix: [memory, context.text].filter(Boolean).join("\n\n"), suffix: context.suffix };
|
|
579
|
+
}
|
|
580
|
+
get logger() {
|
|
581
|
+
return this.session.logger;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Starts the first read of a call now, in the background, after the proof when one was given (the
|
|
585
|
+
* pack depends on the level it proves): at call start, so the read runs while the call is set up.
|
|
586
|
+
* The first `context()` then waits for it within `timeouts.contextVoiceStart`. Never throws.
|
|
587
|
+
*/
|
|
588
|
+
begin() {
|
|
589
|
+
const session = this.session;
|
|
590
|
+
if (!isConversation(session)) return;
|
|
591
|
+
const start = () => {
|
|
592
|
+
this.safe("start the first read", () => {
|
|
593
|
+
this.begun = session.begin();
|
|
594
|
+
});
|
|
595
|
+
};
|
|
596
|
+
if (this.proof === void 0 || this.proof === null) start();
|
|
597
|
+
else void this.verifyOnce().then(start);
|
|
598
|
+
}
|
|
599
|
+
/** Verifies once (when a proof was given), then reads the context. Never rejects. */
|
|
600
|
+
async context(options = {}) {
|
|
601
|
+
await this.verifyOnce();
|
|
602
|
+
try {
|
|
603
|
+
const session = this.session;
|
|
604
|
+
if (this.begun && !this.opened && isConversation(session)) {
|
|
605
|
+
this.opened = true;
|
|
606
|
+
await session.ready(options.timeout === void 0 ? {} : { timeout: options.timeout });
|
|
607
|
+
}
|
|
608
|
+
return await this.session.context(options);
|
|
609
|
+
} catch (error) {
|
|
610
|
+
this.logger.warn(`could not read context (${errorName(error)})`);
|
|
611
|
+
return emptyResult(null);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
/** Records that `context` went into the prompt, unless it was empty for a reason other than the holdout. */
|
|
615
|
+
injected(context) {
|
|
616
|
+
if (!context.text && !context.suffix && context.response?.path !== "holdout") return;
|
|
617
|
+
this.safe("mark the injection", () => {
|
|
618
|
+
this.session.markInjected(context);
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
customer(text, options = {}) {
|
|
622
|
+
const session = this.session;
|
|
623
|
+
if (!text.trim() || !isConversation(session)) return;
|
|
624
|
+
this.safe("record the customer's turn", () => session.customer(text, options));
|
|
625
|
+
}
|
|
626
|
+
/** Sends the customer's turn so far, while they speak. In the background; never throws. */
|
|
627
|
+
prefetch(text) {
|
|
628
|
+
const session = this.session;
|
|
629
|
+
if (!text.trim() || !isConversation(session)) return;
|
|
630
|
+
this.safe("prefetch the turn", () => session.prefetch(text));
|
|
631
|
+
}
|
|
632
|
+
agent(text, options = {}) {
|
|
633
|
+
if (!text.trim()) return;
|
|
634
|
+
this.safe("record the agent's turn", () => this.session.agent(text, options));
|
|
635
|
+
}
|
|
636
|
+
/** Records a transfer. Tasks have no transfer; the call is ignored for them. */
|
|
637
|
+
async handoff(target, reason) {
|
|
638
|
+
const session = this.session;
|
|
639
|
+
if (!isConversation(session)) return;
|
|
640
|
+
try {
|
|
641
|
+
await session.handoff(reason ? { target, reason } : { target });
|
|
642
|
+
} catch (error) {
|
|
643
|
+
this.logger.warn(`could not record the handoff (${errorName(error)})`);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
async end() {
|
|
647
|
+
try {
|
|
648
|
+
await this.session.end();
|
|
649
|
+
} catch (error) {
|
|
650
|
+
this.logger.warn(`could not end the session (${errorName(error)})`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
/** The navigation kit as plain specs (with the agent's memory tools when enabled), or none for a task about an object only. */
|
|
654
|
+
tools() {
|
|
655
|
+
let bound;
|
|
656
|
+
try {
|
|
657
|
+
const memory = this.memory;
|
|
658
|
+
bound = this.session.tools(memory === false ? {} : { agentMemory: true, writeAgentMemory: memory !== true && memory.write === true });
|
|
659
|
+
} catch (error) {
|
|
660
|
+
this.logger.warn(`could not build the tools (${errorName(error)})`);
|
|
661
|
+
return [];
|
|
662
|
+
}
|
|
663
|
+
return bound ? toolSpecs(bound) : [];
|
|
664
|
+
}
|
|
665
|
+
async agentMemory(params, options) {
|
|
666
|
+
try {
|
|
667
|
+
const result = await this.session.agentMemory(params, options.timeout === void 0 ? {} : { timeout: options.timeout });
|
|
668
|
+
return result.text;
|
|
669
|
+
} catch (error) {
|
|
670
|
+
this.logger.warn(`could not read the agent's memory (${errorName(error)})`);
|
|
671
|
+
return "";
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
async verifyOnce() {
|
|
675
|
+
if (this.proof === void 0 || this.proof === null) return;
|
|
676
|
+
this.proving ??= this.runVerify();
|
|
677
|
+
await this.proving;
|
|
678
|
+
}
|
|
679
|
+
async runVerify() {
|
|
680
|
+
try {
|
|
681
|
+
const source = this.proof;
|
|
682
|
+
const proof = typeof source === "function" ? await source() : source;
|
|
683
|
+
if (!proof) return;
|
|
684
|
+
await this.session.verify(proof);
|
|
685
|
+
} catch (error) {
|
|
686
|
+
this.logger.warn(`could not record the verification (${errorName(error)})`);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
safe(what, run) {
|
|
690
|
+
try {
|
|
691
|
+
run();
|
|
692
|
+
} catch (error) {
|
|
693
|
+
this.logger.warn(`could not ${what} (${errorName(error)})`);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
function withoutWrite(option) {
|
|
698
|
+
const { write: _, ...params } = option;
|
|
699
|
+
return params;
|
|
700
|
+
}
|
|
701
|
+
function toolSpecs(bound) {
|
|
702
|
+
return bound.definitions.map(({ function: definition }) => ({
|
|
703
|
+
name: definition.name,
|
|
704
|
+
description: definition.description,
|
|
705
|
+
parameters: definition.parameters,
|
|
706
|
+
execute: (args) => bound.call(definition.name, args)
|
|
707
|
+
}));
|
|
708
|
+
}
|
|
709
|
+
function isRecord(value) {
|
|
710
|
+
return typeof value === "object" && value !== null;
|
|
711
|
+
}
|
|
712
|
+
function count(value) {
|
|
713
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : null;
|
|
714
|
+
}
|
|
715
|
+
var TurnHooks = class _TurnHooks {
|
|
716
|
+
constructor(adapter, enabled) {
|
|
717
|
+
this.adapter = adapter;
|
|
718
|
+
this.enabled = enabled;
|
|
719
|
+
}
|
|
720
|
+
adapter;
|
|
721
|
+
enabled;
|
|
722
|
+
/** Runs held open at most; past it the oldest run's turn closes, incomplete (a run whose end never came). */
|
|
723
|
+
static MAX_OPEN = 100;
|
|
724
|
+
frames = /* @__PURE__ */ new Map();
|
|
725
|
+
calls = /* @__PURE__ */ new Map();
|
|
726
|
+
/** The turn of the run `key`: the session's turn in progress, or a new one of its own. */
|
|
727
|
+
open(session, key, params = {}) {
|
|
728
|
+
if (!this.enabled) return void 0;
|
|
729
|
+
const held = this.frames.get(key);
|
|
730
|
+
if (held !== void 0) return held.frame;
|
|
731
|
+
try {
|
|
732
|
+
const active = session.activeTurn();
|
|
733
|
+
if (active !== void 0 && !this.owns(active)) {
|
|
734
|
+
this.frames.set(key, { frame: active, own: false });
|
|
735
|
+
return active;
|
|
736
|
+
}
|
|
737
|
+
const frame = session.openTurn({ ...params, adapter: this.adapter });
|
|
738
|
+
this.frames.set(key, { frame, own: true });
|
|
739
|
+
if (this.frames.size > _TurnHooks.MAX_OPEN) {
|
|
740
|
+
const [oldest] = this.frames.keys();
|
|
741
|
+
if (oldest !== void 0) {
|
|
742
|
+
this.frames.get(oldest)?.frame.incomplete();
|
|
743
|
+
this.close(oldest);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
return frame;
|
|
747
|
+
} catch (error) {
|
|
748
|
+
session.logger.warn(`could not open the turn (${errorName(error)})`);
|
|
749
|
+
return void 0;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
/** The turn of `key`, else the session's turn in progress. */
|
|
753
|
+
frame(session, key) {
|
|
754
|
+
if (!this.enabled) return void 0;
|
|
755
|
+
const held = key === void 0 ? void 0 : this.frames.get(key);
|
|
756
|
+
const frame = held?.frame ?? session.activeTurn();
|
|
757
|
+
return frame === void 0 || frame.closed ? void 0 : frame;
|
|
758
|
+
}
|
|
759
|
+
has(key) {
|
|
760
|
+
return this.frames.has(key);
|
|
761
|
+
}
|
|
762
|
+
owns(frame) {
|
|
763
|
+
for (const held of this.frames.values()) if (held.own && held.frame === frame) return true;
|
|
764
|
+
return false;
|
|
765
|
+
}
|
|
766
|
+
/** Ends the run `key`: a turn the adapter opened closes; the calls it left open failed. */
|
|
767
|
+
close(key, error) {
|
|
768
|
+
const held = this.frames.get(key);
|
|
769
|
+
if (held === void 0) return;
|
|
770
|
+
this.frames.delete(key);
|
|
771
|
+
for (const [callKey, call] of this.calls) {
|
|
772
|
+
if (call.frame !== held.frame) continue;
|
|
773
|
+
this.calls.delete(callKey);
|
|
774
|
+
if (held.own) call.failed(error ?? "error");
|
|
775
|
+
}
|
|
776
|
+
if (held.own) held.frame.close(error);
|
|
777
|
+
}
|
|
778
|
+
/** A tool call starting, keyed by `callKey`; `callId` is the provider's id of the call, when there is one. */
|
|
779
|
+
toolStart(session, callKey, name, args, options = {}) {
|
|
780
|
+
const frame = this.frame(session, options.frameKey);
|
|
781
|
+
if (frame === void 0) return;
|
|
782
|
+
try {
|
|
783
|
+
this.calls.set(callKey, frame.toolCall(name, args, { callId: options.callId ?? null, adoptable: true }));
|
|
784
|
+
} catch {
|
|
785
|
+
frame.incomplete();
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* In a replay, how a framework tool the adapter stands in for answers: the recorded result of a call with the
|
|
790
|
+
* same arguments, or empty (a divergence), never the live tool. `null` outside a replay, and for a function
|
|
791
|
+
* wrapped with `tool()`, which answers itself.
|
|
792
|
+
*/
|
|
793
|
+
replayed(session, name, args, fn, frameKey) {
|
|
794
|
+
const frame = this.enabled ? this.frame(session, frameKey) : session.activeTurn();
|
|
795
|
+
if (frame?.playback == null || fn !== void 0 && recordedTool(fn) !== null) return null;
|
|
796
|
+
return frame.playback.answer(name, args, false);
|
|
797
|
+
}
|
|
798
|
+
toolEnd(callKey, result, error) {
|
|
799
|
+
const call = this.calls.get(callKey);
|
|
800
|
+
if (call === void 0) return;
|
|
801
|
+
this.calls.delete(callKey);
|
|
802
|
+
try {
|
|
803
|
+
if (error !== void 0) call.failed(error);
|
|
804
|
+
else call.result(result);
|
|
805
|
+
} catch {
|
|
806
|
+
call.frame.incomplete();
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
/** A model call that ended, with its tokens when the framework reported them. */
|
|
810
|
+
model(session, model, tokens = {}, frameKey) {
|
|
811
|
+
const frame = this.frame(session, frameKey);
|
|
812
|
+
if (frame === void 0) return;
|
|
813
|
+
try {
|
|
814
|
+
frame.modelCall(model, { tokensIn: tokens.in ?? null, tokensOut: tokens.out ?? null, tokensCached: tokens.cached ?? 0 });
|
|
815
|
+
} catch {
|
|
816
|
+
frame.incomplete();
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
|
|
821
|
+
// src/integrations/prompt.ts
|
|
822
|
+
function injectPrompt(prompt, read) {
|
|
823
|
+
const injected = [...prompt];
|
|
824
|
+
if (read.suffix) {
|
|
825
|
+
const last = lastUserIndex(injected);
|
|
826
|
+
const message = injected[last];
|
|
827
|
+
if (isRecord(message) && Array.isArray(message.content)) {
|
|
828
|
+
injected[last] = { ...message, content: [...message.content, { type: "text", text: read.suffix }] };
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
if (read.prefix) {
|
|
832
|
+
let position = 0;
|
|
833
|
+
while (position < injected.length && roleOf(injected[position]) === "system") position++;
|
|
834
|
+
injected.splice(position, 0, { role: "system", content: read.prefix });
|
|
835
|
+
}
|
|
836
|
+
return injected;
|
|
837
|
+
}
|
|
838
|
+
function recordNewest(bridge, seen, prompt) {
|
|
839
|
+
const index = lastUserIndex(prompt);
|
|
840
|
+
if (index < 0) return;
|
|
841
|
+
const message = prompt[index];
|
|
842
|
+
const text = isRecord(message) ? textParts(message.content) : "";
|
|
843
|
+
const key = `${String(index)}:${text}`;
|
|
844
|
+
if (!text || seen.has(key)) return;
|
|
845
|
+
seen.add(key);
|
|
846
|
+
bridge.customer(text);
|
|
847
|
+
}
|
|
848
|
+
function textParts(content) {
|
|
849
|
+
if (typeof content === "string") return content;
|
|
850
|
+
if (!Array.isArray(content)) return "";
|
|
851
|
+
return content.map((part) => isRecord(part) && part.type === "text" && typeof part.text === "string" ? part.text : "").filter(Boolean).join("\n");
|
|
852
|
+
}
|
|
853
|
+
function lastUserIndex(prompt) {
|
|
854
|
+
for (let index = prompt.length - 1; index >= 0; index--) if (roleOf(prompt[index]) === "user") return index;
|
|
855
|
+
return -1;
|
|
856
|
+
}
|
|
857
|
+
function roleOf(message) {
|
|
858
|
+
return isRecord(message) && typeof message.role === "string" ? message.role : "";
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// src/integrations/ai-sdk.ts
|
|
862
|
+
function niadraMiddleware(session, options = {}) {
|
|
863
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
864
|
+
const hooks = new TurnHooks("ai-sdk", true);
|
|
865
|
+
const modelCall = (usage, model, modelId) => {
|
|
866
|
+
const current = resolveSession(session);
|
|
867
|
+
if (!current) return;
|
|
868
|
+
const name = typeof modelId === "string" && modelId ? modelId : model.modelId;
|
|
869
|
+
const reported = aiSdkUsage(usage, model, modelId);
|
|
870
|
+
const out = isRecord(usage) ? count(usage.outputTokens) ?? (isRecord(usage.outputTokens) ? count(usage.outputTokens.total) : null) : null;
|
|
871
|
+
hooks.model(current, name, reported ? { in: reported.prompt_tokens, out, cached: reported.cached_tokens ?? 0 } : {});
|
|
872
|
+
};
|
|
873
|
+
const stateOf = () => {
|
|
874
|
+
const current = resolveSession(session);
|
|
875
|
+
if (!current) return null;
|
|
876
|
+
let state = states.get(current);
|
|
877
|
+
if (!state) {
|
|
878
|
+
state = { bridge: new Bridge(current, options.verify, options.agentMemory), seen: /* @__PURE__ */ new Set() };
|
|
879
|
+
states.set(current, state);
|
|
880
|
+
}
|
|
881
|
+
return state;
|
|
882
|
+
};
|
|
883
|
+
return {
|
|
884
|
+
specificationVersion: "v3",
|
|
885
|
+
async transformParams({ params }) {
|
|
886
|
+
const state = stateOf();
|
|
887
|
+
if (!state || !Array.isArray(params.prompt)) return params;
|
|
888
|
+
try {
|
|
889
|
+
const prompt = params.prompt;
|
|
890
|
+
if (options.recordCustomer ?? true) recordNewest(state.bridge, state.seen, prompt);
|
|
891
|
+
const read = await state.bridge.read();
|
|
892
|
+
state.bridge.injected(read.context);
|
|
893
|
+
return { ...params, prompt: injectPrompt(prompt, read) };
|
|
894
|
+
} catch (error) {
|
|
895
|
+
state.bridge.logger.warn(`could not inject context (${errorName(error)})`);
|
|
896
|
+
return params;
|
|
897
|
+
}
|
|
898
|
+
},
|
|
899
|
+
async wrapGenerate({ doGenerate, model }) {
|
|
900
|
+
const result = await doGenerate();
|
|
901
|
+
if (isRecord(result)) modelCall(result.usage, model, isRecord(result.response) ? result.response.modelId : void 0);
|
|
902
|
+
if (options.recordAgent ?? true) {
|
|
903
|
+
const state = stateOf();
|
|
904
|
+
if (state) {
|
|
905
|
+
try {
|
|
906
|
+
const content = isRecord(result) && Array.isArray(result.content) ? result.content : [];
|
|
907
|
+
const text = content.map((part) => isRecord(part) && part.type === "text" && typeof part.text === "string" ? part.text : "").join("");
|
|
908
|
+
const response = isRecord(result) && isRecord(result.response) ? result.response : {};
|
|
909
|
+
record(state, text, isRecord(result) ? result.usage : void 0, model, response.modelId);
|
|
910
|
+
} catch (error) {
|
|
911
|
+
state.bridge.logger.warn(`could not capture the model's answer (${errorName(error)})`);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
return result;
|
|
916
|
+
},
|
|
917
|
+
async wrapStream({ doStream, model }) {
|
|
918
|
+
const result = await doStream();
|
|
919
|
+
const state = options.recordAgent ?? true ? stateOf() : null;
|
|
920
|
+
if (!state || !isRecord(result) || !(result.stream instanceof ReadableStream)) return result;
|
|
921
|
+
const parts = [];
|
|
922
|
+
let usage;
|
|
923
|
+
let modelId;
|
|
924
|
+
const capture = new TransformStream({
|
|
925
|
+
transform(chunk, controller) {
|
|
926
|
+
if (isRecord(chunk)) {
|
|
927
|
+
if (chunk.type === "text-delta") parts.push(typeof chunk.delta === "string" ? chunk.delta : typeof chunk.textDelta === "string" ? chunk.textDelta : "");
|
|
928
|
+
else if (chunk.type === "finish") usage = chunk.usage;
|
|
929
|
+
else if (chunk.type === "response-metadata") modelId = chunk.modelId;
|
|
930
|
+
}
|
|
931
|
+
controller.enqueue(chunk);
|
|
932
|
+
},
|
|
933
|
+
flush() {
|
|
934
|
+
try {
|
|
935
|
+
modelCall(usage, model, modelId);
|
|
936
|
+
record(state, parts.join(""), usage, model, modelId);
|
|
937
|
+
} catch (error) {
|
|
938
|
+
state.bridge.logger.warn(`could not capture the model's answer (${errorName(error)})`);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
});
|
|
942
|
+
return { ...result, stream: result.stream.pipeThrough(capture) };
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
function niadraTools(session, options = {}) {
|
|
947
|
+
const tools = {};
|
|
948
|
+
for (const spec of new Bridge(session, void 0, options.agentMemory).tools()) {
|
|
949
|
+
tools[spec.name] = tool$1({
|
|
950
|
+
description: spec.description,
|
|
951
|
+
inputSchema: jsonSchema(spec.parameters),
|
|
952
|
+
execute: async (input) => parsed(await spec.execute(input))
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
return tools;
|
|
956
|
+
}
|
|
957
|
+
function niadraTurn(session, params = {}) {
|
|
958
|
+
const frame = session.openTurn({ ...params, adapter: "ai-sdk" });
|
|
959
|
+
return {
|
|
960
|
+
frame,
|
|
961
|
+
run: (fn) => frame.run(fn),
|
|
962
|
+
onFinish: () => {
|
|
963
|
+
frame.close();
|
|
964
|
+
},
|
|
965
|
+
onError: (event) => {
|
|
966
|
+
frame.close(event.error);
|
|
967
|
+
},
|
|
968
|
+
onAbort: () => {
|
|
969
|
+
frame.close();
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
function recordTools(tools, options = {}) {
|
|
974
|
+
const out = {};
|
|
975
|
+
for (const [name, spec] of Object.entries(tools)) {
|
|
976
|
+
const execute = isRecord(spec) ? spec.execute : void 0;
|
|
977
|
+
if (typeof execute !== "function") {
|
|
978
|
+
out[name] = spec;
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
981
|
+
const dryRun = Array.isArray(options.dryRun) ? options.dryRun.includes(name) : options.dryRun === true;
|
|
982
|
+
const session = options.session;
|
|
983
|
+
out[name] = {
|
|
984
|
+
...spec,
|
|
985
|
+
execute: tool(name, execute, {
|
|
986
|
+
args: (input) => input,
|
|
987
|
+
callId: (_input, context) => isRecord(context) && typeof context.toolCallId === "string" ? context.toolCallId : null,
|
|
988
|
+
...session ? { frame: () => session.activeTurn() } : {},
|
|
989
|
+
dryRun
|
|
990
|
+
})
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
return out;
|
|
994
|
+
}
|
|
995
|
+
function aiSdkUsage(usage, model, modelId) {
|
|
996
|
+
if (!isRecord(usage)) return null;
|
|
997
|
+
const name = typeof modelId === "string" && modelId ? modelId : model.modelId;
|
|
998
|
+
const provider = model.provider?.split(".")[0]?.toLowerCase();
|
|
999
|
+
if (!name || !provider) return null;
|
|
1000
|
+
let prompt;
|
|
1001
|
+
let cached;
|
|
1002
|
+
let written;
|
|
1003
|
+
if (isRecord(usage.inputTokens)) {
|
|
1004
|
+
const input = usage.inputTokens;
|
|
1005
|
+
cached = count(input.cacheRead) ?? 0;
|
|
1006
|
+
written = count(input.cacheWrite) ?? 0;
|
|
1007
|
+
prompt = count(input.total) ?? (count(input.noCache) === null ? null : (count(input.noCache) ?? 0) + cached + written);
|
|
1008
|
+
} else {
|
|
1009
|
+
prompt = count(usage.inputTokens);
|
|
1010
|
+
cached = count(usage.cachedInputTokens) ?? 0;
|
|
1011
|
+
written = 0;
|
|
1012
|
+
}
|
|
1013
|
+
if (prompt === null) return null;
|
|
1014
|
+
return { provider, model: name, prompt_tokens: Math.max(prompt, cached + written), cached_tokens: cached, cache_write_tokens: written };
|
|
1015
|
+
}
|
|
1016
|
+
function record(state, text, usage, model, modelId) {
|
|
1017
|
+
const reported = aiSdkUsage(usage, model, modelId);
|
|
1018
|
+
state.bridge.agent(text, reported ? { usage: reported } : {});
|
|
1019
|
+
}
|
|
1020
|
+
function parsed(text) {
|
|
1021
|
+
try {
|
|
1022
|
+
return JSON.parse(text);
|
|
1023
|
+
} catch {
|
|
1024
|
+
return text;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
export { aiSdkUsage, attestationProof, niadraMiddleware, niadraTools, niadraTurn, recordTools };
|
|
1029
|
+
//# sourceMappingURL=ai-sdk.js.map
|
|
1030
|
+
//# sourceMappingURL=ai-sdk.js.map
|