@niadra/sdk 0.7.0 → 0.9.1
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 +58 -0
- package/README.md +55 -7
- package/dist/ai-sdk.cjs +3 -4
- package/dist/ai-sdk.cjs.map +1 -1
- package/dist/ai-sdk.d.cts +3 -3
- package/dist/ai-sdk.d.ts +3 -3
- package/dist/ai-sdk.js +3 -4
- package/dist/ai-sdk.js.map +1 -1
- package/dist/anthropic.cjs +1 -1
- package/dist/anthropic.cjs.map +1 -1
- package/dist/anthropic.d.cts +4 -4
- package/dist/anthropic.d.ts +4 -4
- package/dist/anthropic.js +1 -1
- package/dist/anthropic.js.map +1 -1
- package/dist/bedrock.cjs +1 -1
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.d.cts +4 -4
- package/dist/bedrock.d.ts +4 -4
- package/dist/bedrock.js +1 -1
- package/dist/bedrock.js.map +1 -1
- package/dist/cli.js +157 -60
- package/dist/cli.js.map +1 -1
- package/dist/{client-DsIxZxZk.d.cts → client-CWMxmJHs.d.cts} +91 -28
- package/dist/{client-DsIxZxZk.d.ts → client-CWMxmJHs.d.ts} +91 -28
- package/dist/cloudflare-agents.cjs +1 -1
- package/dist/cloudflare-agents.cjs.map +1 -1
- package/dist/cloudflare-agents.d.cts +3 -3
- package/dist/cloudflare-agents.d.ts +3 -3
- package/dist/cloudflare-agents.js +1 -1
- package/dist/cloudflare-agents.js.map +1 -1
- package/dist/elevenlabs.cjs +1 -1
- package/dist/elevenlabs.cjs.map +1 -1
- package/dist/elevenlabs.d.cts +5 -5
- package/dist/elevenlabs.d.ts +5 -5
- package/dist/elevenlabs.js +1 -1
- package/dist/elevenlabs.js.map +1 -1
- package/dist/genkit.cjs +1 -1
- package/dist/genkit.cjs.map +1 -1
- package/dist/genkit.d.cts +3 -3
- package/dist/genkit.d.ts +3 -3
- package/dist/genkit.js +1 -1
- package/dist/genkit.js.map +1 -1
- package/dist/google-adk.cjs +1 -1
- package/dist/google-adk.cjs.map +1 -1
- package/dist/google-adk.d.cts +3 -3
- package/dist/google-adk.d.ts +3 -3
- package/dist/google-adk.js +1 -1
- package/dist/google-adk.js.map +1 -1
- package/dist/google-genai.cjs +1 -1
- package/dist/google-genai.cjs.map +1 -1
- package/dist/google-genai.d.cts +4 -4
- package/dist/google-genai.d.ts +4 -4
- package/dist/google-genai.js +1 -1
- package/dist/google-genai.js.map +1 -1
- package/dist/index.cjs +156 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -8
- package/dist/index.d.ts +6 -8
- package/dist/index.js +156 -57
- package/dist/index.js.map +1 -1
- package/dist/{intercept-D7qFCaRb.d.ts → intercept-Bv0nLpSw.d.ts} +1 -1
- package/dist/{intercept-0_lJE6k1.d.cts → intercept-CGngQI8B.d.cts} +1 -1
- package/dist/langchain.cjs +3 -4
- package/dist/langchain.cjs.map +1 -1
- package/dist/langchain.d.cts +3 -3
- package/dist/langchain.d.ts +3 -3
- package/dist/langchain.js +3 -4
- package/dist/langchain.js.map +1 -1
- package/dist/livekit.cjs +1 -1
- package/dist/livekit.cjs.map +1 -1
- package/dist/livekit.d.cts +3 -3
- package/dist/livekit.d.ts +3 -3
- package/dist/livekit.js +1 -1
- package/dist/livekit.js.map +1 -1
- package/dist/llamaindex.cjs +1 -1
- package/dist/llamaindex.cjs.map +1 -1
- package/dist/llamaindex.d.cts +3 -3
- package/dist/llamaindex.d.ts +3 -3
- package/dist/llamaindex.js +1 -1
- package/dist/llamaindex.js.map +1 -1
- package/dist/mastra.cjs +3 -4
- package/dist/mastra.cjs.map +1 -1
- package/dist/mastra.d.cts +3 -3
- package/dist/mastra.d.ts +3 -3
- package/dist/mastra.js +3 -4
- package/dist/mastra.js.map +1 -1
- package/dist/openai-agents.cjs +1 -1
- package/dist/openai-agents.cjs.map +1 -1
- package/dist/openai-agents.d.cts +3 -3
- package/dist/openai-agents.d.ts +3 -3
- package/dist/openai-agents.js +1 -1
- package/dist/openai-agents.js.map +1 -1
- package/dist/retell.cjs +1 -1
- package/dist/retell.cjs.map +1 -1
- package/dist/retell.d.cts +5 -5
- package/dist/retell.d.ts +5 -5
- package/dist/retell.js +1 -1
- package/dist/retell.js.map +1 -1
- package/dist/{shared-Bb5B59Bu.d.ts → shared-B4Ef2Wpg.d.ts} +1 -1
- package/dist/{shared-DTPWVlWm.d.cts → shared-Cq8mz-7m.d.cts} +1 -1
- package/dist/strands.cjs +1 -1
- package/dist/strands.cjs.map +1 -1
- package/dist/strands.d.cts +3 -3
- package/dist/strands.d.ts +3 -3
- package/dist/strands.js +1 -1
- package/dist/strands.js.map +1 -1
- package/dist/twilio.d.cts +4 -4
- package/dist/twilio.d.ts +4 -4
- package/dist/vapi.cjs +1 -1
- package/dist/vapi.cjs.map +1 -1
- package/dist/vapi.d.cts +5 -5
- package/dist/vapi.d.ts +5 -5
- package/dist/vapi.js +1 -1
- package/dist/vapi.js.map +1 -1
- package/dist/voltagent.cjs +1 -1
- package/dist/voltagent.cjs.map +1 -1
- package/dist/voltagent.d.cts +3 -3
- package/dist/voltagent.d.ts +3 -3
- package/dist/voltagent.js +1 -1
- package/dist/voltagent.js.map +1 -1
- package/dist/{webhook-CG4om_DK.d.cts → webhook-jTx_SegV.d.cts} +1 -1
- package/dist/{webhook-1ozGyksG.d.ts → webhook-z2TjUzjv.d.ts} +1 -1
- package/dist/whatsapp.d.cts +2 -2
- package/dist/whatsapp.d.ts +2 -2
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -518,7 +518,7 @@ function internalRecord(span, ref, act) {
|
|
|
518
518
|
}
|
|
519
519
|
|
|
520
520
|
// src/version.ts
|
|
521
|
-
var VERSION = "0.
|
|
521
|
+
var VERSION = "0.9.1";
|
|
522
522
|
|
|
523
523
|
// src/transport.ts
|
|
524
524
|
var RETRYABLE_WRITE_STATUS = /* @__PURE__ */ new Set([408, 421, 429, 500, 502, 503, 504]);
|
|
@@ -612,6 +612,7 @@ var Transport = class {
|
|
|
612
612
|
} catch (error) {
|
|
613
613
|
throw deadline.explain(error);
|
|
614
614
|
}
|
|
615
|
+
warnIfDeprecated(this.config.logger, init.method ?? "GET", url, response.headers);
|
|
615
616
|
const requestId = response.headers.get("x-request-id");
|
|
616
617
|
let payload;
|
|
617
618
|
try {
|
|
@@ -681,6 +682,29 @@ var Deadline = class {
|
|
|
681
682
|
return new NiadraConnectionError(`connection failed: ${message}`, { cause: error });
|
|
682
683
|
}
|
|
683
684
|
};
|
|
685
|
+
var VERSIONING_DOCS = "https://docs.niadra.com/en/security/api-versioning";
|
|
686
|
+
var DEPRECATION_LINK = /<([^>]*)>[^,]*;\s*rel="?deprecation"?/gi;
|
|
687
|
+
var deprecationsSeen = /* @__PURE__ */ new Set();
|
|
688
|
+
function warnIfDeprecated(logger, method, url, headers) {
|
|
689
|
+
const since = headers.get("deprecation");
|
|
690
|
+
if (since === null) return;
|
|
691
|
+
const links = [...(headers.get("link") ?? "").matchAll(DEPRECATION_LINK)].map((match) => match[1] ?? "");
|
|
692
|
+
const key2 = `${method} ${links.join(" ") || (url.split("?")[0] ?? url)}`;
|
|
693
|
+
if (deprecationsSeen.has(key2)) return;
|
|
694
|
+
deprecationsSeen.add(key2);
|
|
695
|
+
const sunset = headers.get("sunset");
|
|
696
|
+
logger.warn(
|
|
697
|
+
`the API deprecated a ${method} route this client calls, since ${deprecatedSince(since)}; it stops answering on ${sunset === null ? "a date not announced yet" : sunsetDay(sunset)}. See ${links.join(", ") || VERSIONING_DOCS}`
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
function deprecatedSince(value) {
|
|
701
|
+
const seconds = Number(value.trim().replace(/^@/, ""));
|
|
702
|
+
return Number.isInteger(seconds) ? new Date(seconds * 1e3).toISOString().slice(0, 10) : value;
|
|
703
|
+
}
|
|
704
|
+
function sunsetDay(value) {
|
|
705
|
+
const time = Date.parse(value);
|
|
706
|
+
return Number.isNaN(time) ? value : new Date(time).toISOString().slice(0, 10);
|
|
707
|
+
}
|
|
684
708
|
async function readBody(response) {
|
|
685
709
|
const text2 = await response.text();
|
|
686
710
|
if (text2.length === 0) return null;
|
|
@@ -2904,6 +2928,11 @@ ${change.field}`)) out.push({ ref, field: change.field, value: change.now, claim
|
|
|
2904
2928
|
for (const s of constraints.soft ?? []) said.push([s.attr, s.value]);
|
|
2905
2929
|
for (const a of constraints.attributes ?? []) said.push([a.name, a.value]);
|
|
2906
2930
|
for (const [attr, value] of said) out.push({ ref: null, field: attr.split(".").pop() ?? attr, value, claimSafe: true });
|
|
2931
|
+
for (const shown of constraints.already_presented ?? []) {
|
|
2932
|
+
for (const [field, n] of Object.entries(shown.values ?? {})) {
|
|
2933
|
+
out.push({ ref: shown.ref, field, value: n.v, claimSafe: n.claim_safe, role: n.role ?? null });
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2907
2936
|
}
|
|
2908
2937
|
return out;
|
|
2909
2938
|
}
|
|
@@ -3270,7 +3299,7 @@ function thenable(value) {
|
|
|
3270
3299
|
function tool(name, fn, options = {}) {
|
|
3271
3300
|
const isAsync = isAsyncFunction(fn);
|
|
3272
3301
|
function bindingOf(frame) {
|
|
3273
|
-
return
|
|
3302
|
+
return (options.served ?? frame?.profile.bindings)?.(name) ?? null;
|
|
3274
3303
|
}
|
|
3275
3304
|
function masks(frame) {
|
|
3276
3305
|
return options.maskOutput ?? bindingOf(frame)?.capabilities?.mask_output ?? false;
|
|
@@ -3385,8 +3414,7 @@ function tool(name, fn, options = {}) {
|
|
|
3385
3414
|
const marker = {
|
|
3386
3415
|
name,
|
|
3387
3416
|
dryRun: options.dryRun ?? false,
|
|
3388
|
-
provenance: options.provenance ?? null
|
|
3389
|
-
binding: options.binding ?? null
|
|
3417
|
+
provenance: options.provenance ?? null
|
|
3390
3418
|
};
|
|
3391
3419
|
Object.defineProperty(wrapped, RECORDED, { value: marker });
|
|
3392
3420
|
return wrapped;
|
|
@@ -3648,6 +3676,7 @@ function claimsOf(frame, claims, logger) {
|
|
|
3648
3676
|
|
|
3649
3677
|
// src/queue.ts
|
|
3650
3678
|
var HEARTBEAT_WINDOW_MS = 6e4;
|
|
3679
|
+
var MAX_PAUSE_MS = 6e4;
|
|
3651
3680
|
var EventQueue = class {
|
|
3652
3681
|
constructor(send, options, logger, now = Date.now) {
|
|
3653
3682
|
this.send = send;
|
|
@@ -3668,6 +3697,8 @@ var EventQueue = class {
|
|
|
3668
3697
|
droppedSinceWarning = 0;
|
|
3669
3698
|
windowStart;
|
|
3670
3699
|
sentInWindow = 0;
|
|
3700
|
+
pauseMs = 0;
|
|
3701
|
+
resumeAt = 0;
|
|
3671
3702
|
/** Items waiting to be sent, not counting a batch already in flight. */
|
|
3672
3703
|
get size() {
|
|
3673
3704
|
return this.items.length;
|
|
@@ -3703,10 +3734,16 @@ var EventQueue = class {
|
|
|
3703
3734
|
return run;
|
|
3704
3735
|
}
|
|
3705
3736
|
/**
|
|
3706
|
-
* Starts a flush without waiting for it
|
|
3707
|
-
*
|
|
3737
|
+
* Starts a flush without waiting for it: once the pause after a failed batch ends, or at once with
|
|
3738
|
+
* `now` (a caller waits for an item). Item failures are logged and settled inside the drain, so only
|
|
3739
|
+
* an unexpected error reaches this catch.
|
|
3708
3740
|
*/
|
|
3709
|
-
flushInBackground() {
|
|
3741
|
+
flushInBackground(now = false) {
|
|
3742
|
+
const paused = this.resumeAt - this.now();
|
|
3743
|
+
if (!now && paused > 0) {
|
|
3744
|
+
this.schedule(paused);
|
|
3745
|
+
return;
|
|
3746
|
+
}
|
|
3710
3747
|
this.flush().catch((error) => {
|
|
3711
3748
|
this.logger.error(`event flush failed: ${toNiadraError(error).message}`);
|
|
3712
3749
|
});
|
|
@@ -3723,24 +3760,36 @@ var EventQueue = class {
|
|
|
3723
3760
|
while (this.items.length > 0) {
|
|
3724
3761
|
const batch = this.items.splice(0, this.options.maxBatchSize);
|
|
3725
3762
|
const heartbeat = this.heartbeat();
|
|
3726
|
-
|
|
3727
|
-
if (
|
|
3728
|
-
await this.sendBatch(batch, wire, report);
|
|
3763
|
+
if (heartbeat) batch.push({ item: heartbeat });
|
|
3764
|
+
if (!await this.sendBatch(batch, report)) break;
|
|
3729
3765
|
}
|
|
3730
3766
|
return report;
|
|
3731
3767
|
}
|
|
3732
|
-
|
|
3768
|
+
/** Sends one batch; `false` when it went back to the queue and the queue pauses. */
|
|
3769
|
+
async sendBatch(batch, report) {
|
|
3770
|
+
const wire = batch.map((pending) => pending.item);
|
|
3733
3771
|
let response;
|
|
3734
3772
|
try {
|
|
3735
3773
|
response = await this.send(wire);
|
|
3736
3774
|
} catch (error) {
|
|
3737
3775
|
const failure = toNiadraError(error);
|
|
3738
|
-
report.failed += batch.length;
|
|
3739
3776
|
report.errors.push(failure);
|
|
3740
|
-
|
|
3777
|
+
if (isTransient(failure)) {
|
|
3778
|
+
for (const pending of batch) pending.settle?.(failure);
|
|
3779
|
+
this.requeue(batch);
|
|
3780
|
+
this.pauseMs = Math.min(MAX_PAUSE_MS, Math.max(this.options.flushIntervalMs, this.pauseMs * 2));
|
|
3781
|
+
this.resumeAt = this.now() + this.pauseMs;
|
|
3782
|
+
this.logger.warn(`could not deliver ${batch.length} events, will retry: ${failure.message}`);
|
|
3783
|
+
this.schedule(this.pauseMs);
|
|
3784
|
+
return false;
|
|
3785
|
+
}
|
|
3786
|
+
report.failed += batch.length;
|
|
3787
|
+
this.logger.warn(`dropped ${batch.length} events refused by the API: ${failure.message}`);
|
|
3741
3788
|
for (const pending of batch) pending.settle?.(failure);
|
|
3742
|
-
return;
|
|
3789
|
+
return true;
|
|
3743
3790
|
}
|
|
3791
|
+
this.pauseMs = 0;
|
|
3792
|
+
this.resumeAt = 0;
|
|
3744
3793
|
const rejected = /* @__PURE__ */ new Map();
|
|
3745
3794
|
for (const itemError of response.errors) {
|
|
3746
3795
|
const detail = itemError.detail ? `: ${itemError.detail}` : "";
|
|
@@ -3751,6 +3800,7 @@ var EventQueue = class {
|
|
|
3751
3800
|
this.logger.warn(`server rejected ${rejected.size} of ${wire.length} items (${codes2})`);
|
|
3752
3801
|
}
|
|
3753
3802
|
batch.forEach((pending, index) => {
|
|
3803
|
+
if (pending.item.type === "heartbeat") return;
|
|
3754
3804
|
const error = rejected.get(index) ?? null;
|
|
3755
3805
|
if (error) {
|
|
3756
3806
|
report.failed++;
|
|
@@ -3761,6 +3811,17 @@ var EventQueue = class {
|
|
|
3761
3811
|
}
|
|
3762
3812
|
pending.settle?.(error);
|
|
3763
3813
|
});
|
|
3814
|
+
return true;
|
|
3815
|
+
}
|
|
3816
|
+
/** Puts a batch back at the front, keeping only what still fits; what does not is dropped. */
|
|
3817
|
+
requeue(batch) {
|
|
3818
|
+
const room = Math.max(0, this.options.maxQueueSize - this.items.length);
|
|
3819
|
+
const lost = batch.slice(room);
|
|
3820
|
+
this.items.unshift(...batch.slice(0, room));
|
|
3821
|
+
if (lost.length > 0) {
|
|
3822
|
+
this.logger.warn(`event queue is full; dropped ${lost.length} events`);
|
|
3823
|
+
for (const pending of lost) pending.settle?.(new NiadraError("event queue is full"));
|
|
3824
|
+
}
|
|
3764
3825
|
}
|
|
3765
3826
|
/**
|
|
3766
3827
|
* Once a minute, the next batch carries the number of items sent in the previous window.
|
|
@@ -3811,7 +3872,7 @@ function unref(timer) {
|
|
|
3811
3872
|
var MAX_TURNS = 50;
|
|
3812
3873
|
var COMPRESSED_ROOM = 4 * 1024 * 1024 - 64 * 1024;
|
|
3813
3874
|
var DECODED_ROOM = 16 * 1024 * 1024 - 256 * 1024;
|
|
3814
|
-
var
|
|
3875
|
+
var MAX_PAUSE_MS2 = 6e4;
|
|
3815
3876
|
var encoder2 = new TextEncoder();
|
|
3816
3877
|
async function encode(records) {
|
|
3817
3878
|
const raw = encoder2.encode(JSON.stringify({ turns: records }));
|
|
@@ -3970,7 +4031,7 @@ var TurnSender = class {
|
|
|
3970
4031
|
}
|
|
3971
4032
|
if (isTransient(error)) {
|
|
3972
4033
|
this.queue.requeue(batch.frames);
|
|
3973
|
-
this.pause = Math.min(
|
|
4034
|
+
this.pause = Math.min(MAX_PAUSE_MS2, Math.max(this.intervalMs, this.pause * 2));
|
|
3974
4035
|
this.resumeAt = this.now() + this.pause;
|
|
3975
4036
|
this.logger.warn(`could not deliver ${batch.frames.length} turns, will retry (${toNiadraError(error).name})`);
|
|
3976
4037
|
return false;
|
|
@@ -4358,26 +4419,42 @@ async function suppressionKey(salt, canonical2) {
|
|
|
4358
4419
|
const key2 = await subtle.importKey("raw", saltBytes(salt), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
4359
4420
|
return toBase64url(new Uint8Array(await subtle.sign("HMAC", key2, new TextEncoder().encode(canonical2))));
|
|
4360
4421
|
}
|
|
4422
|
+
var AREA_CODES = new Set(
|
|
4423
|
+
"11 12 13 14 15 16 17 18 19 21 22 24 27 28 31 32 33 34 35 37 38 41 42 43 44 45 46 47 48 49 51 53 54 55 61 62 63 64 65 66 67 68 69 71 73 74 75 77 79 81 82 83 84 85 86 87 88 89 91 92 93 94 95 96 97 98 99".split(" ")
|
|
4424
|
+
);
|
|
4425
|
+
var FORMAT_CHARACTERS = /\p{Cf}/gu;
|
|
4361
4426
|
function phone(value) {
|
|
4362
|
-
|
|
4363
|
-
|
|
4427
|
+
let text2 = value.normalize("NFKC").replace(FORMAT_CHARACTERS, "").trim();
|
|
4428
|
+
if (text2.slice(0, 4).toLowerCase() === "tel:") text2 = text2.slice(4);
|
|
4429
|
+
const international = text2.startsWith("+") || text2.startsWith("00");
|
|
4430
|
+
if (international) text2 = text2.replaceAll("(0)", "");
|
|
4431
|
+
const raw = text2.replace(SEPARATORS2, "");
|
|
4364
4432
|
let digits = raw.startsWith("+") ? raw.slice(1) : international ? raw.slice(2) : raw;
|
|
4365
4433
|
if (!DIGITS2.test(digits)) throw new NiadraDestinationError("invalid_handle");
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4434
|
+
if (!international) {
|
|
4435
|
+
const national = digits.replace(/^0+/, "");
|
|
4436
|
+
if (isBrazilianNational(national)) {
|
|
4437
|
+
digits = `55${national}`;
|
|
4438
|
+
} else if (digits.startsWith("0") && (national.length === 12 || national.length === 13)) {
|
|
4439
|
+
if (isBrazilianNational(national.slice(2))) digits = `55${national.slice(2)}`;
|
|
4440
|
+
}
|
|
4369
4441
|
}
|
|
4370
4442
|
if (digits.length < 8 || digits.length > 15 || digits.startsWith("0")) {
|
|
4371
4443
|
throw new NiadraDestinationError("invalid_handle");
|
|
4372
4444
|
}
|
|
4373
4445
|
const rest = digits.slice(2);
|
|
4374
|
-
if (digits.startsWith("55") && rest.length === 10 &&
|
|
4446
|
+
if (digits.startsWith("55") && rest.length === 10 && AREA_CODES.has(rest.slice(0, 2)) && "6789".includes(rest.charAt(2))) {
|
|
4375
4447
|
digits = `55${rest.slice(0, 2)}9${rest.slice(2)}`;
|
|
4376
4448
|
}
|
|
4449
|
+
if (digits.length === 13 && (digits.startsWith("521") || digits.startsWith("549"))) {
|
|
4450
|
+
digits = digits.slice(0, 2) + digits.slice(3);
|
|
4451
|
+
}
|
|
4377
4452
|
return `phone:+${digits}`;
|
|
4378
4453
|
}
|
|
4379
|
-
function
|
|
4380
|
-
|
|
4454
|
+
function isBrazilianNational(national) {
|
|
4455
|
+
if (!AREA_CODES.has(national.slice(0, 2))) return false;
|
|
4456
|
+
if (national.length === 10) return "23456789".includes(national.charAt(2));
|
|
4457
|
+
return national.length === 11 && national.charAt(2) === "9";
|
|
4381
4458
|
}
|
|
4382
4459
|
function saltBytes(salt) {
|
|
4383
4460
|
const bytes = fromBase64url(salt);
|
|
@@ -4436,7 +4513,10 @@ var SuppressionCopy = class {
|
|
|
4436
4513
|
}
|
|
4437
4514
|
this.saltValue = salt;
|
|
4438
4515
|
}
|
|
4439
|
-
/**
|
|
4516
|
+
/**
|
|
4517
|
+
* Applies one page, in order. `true` when more pages follow: a full page. Every page carries the cursor to
|
|
4518
|
+
* read from next, the last one too, which the next read starts from.
|
|
4519
|
+
*/
|
|
4440
4520
|
apply(page) {
|
|
4441
4521
|
if (page.salt_id !== this.saltValue?.salt_id) {
|
|
4442
4522
|
this.saltValue = null;
|
|
@@ -4451,8 +4531,9 @@ var SuppressionCopy = class {
|
|
|
4451
4531
|
}
|
|
4452
4532
|
this.cursor = page.next_cursor ?? this.cursor;
|
|
4453
4533
|
this.absent = false;
|
|
4454
|
-
|
|
4455
|
-
|
|
4534
|
+
const more = Boolean(page.next_cursor) && page.items.length >= PAGE;
|
|
4535
|
+
if (!more) this.readAt = this.now();
|
|
4536
|
+
return more;
|
|
4456
4537
|
}
|
|
4457
4538
|
/** A 404: the space keeps no list. Anything else: the copy stays as it is. */
|
|
4458
4539
|
failed(error) {
|
|
@@ -4677,7 +4758,7 @@ var ContactGateway = class {
|
|
|
4677
4758
|
|
|
4678
4759
|
// src/outbox.ts
|
|
4679
4760
|
var CAPACITY = 1e3;
|
|
4680
|
-
var
|
|
4761
|
+
var MAX_PAUSE_MS3 = 6e4;
|
|
4681
4762
|
var Outbox = class {
|
|
4682
4763
|
constructor(logger, intervalMs = 1e3, now = Date.now) {
|
|
4683
4764
|
this.logger = logger;
|
|
@@ -4745,7 +4826,7 @@ var Outbox = class {
|
|
|
4745
4826
|
answer = await write.send();
|
|
4746
4827
|
} catch (error) {
|
|
4747
4828
|
if (isTransient(error)) {
|
|
4748
|
-
this.pause = Math.min(
|
|
4829
|
+
this.pause = Math.min(MAX_PAUSE_MS3, Math.max(this.intervalMs, this.pause * 2));
|
|
4749
4830
|
this.resumeAt = this.now() + this.pause;
|
|
4750
4831
|
return false;
|
|
4751
4832
|
}
|
|
@@ -5528,6 +5609,11 @@ var ContextCache = class {
|
|
|
5528
5609
|
}
|
|
5529
5610
|
return true;
|
|
5530
5611
|
}
|
|
5612
|
+
/** Milliseconds since the server last sent or confirmed the pack held for `key`; `null` when none is held. */
|
|
5613
|
+
age(key2) {
|
|
5614
|
+
const entry = this.entries.get(key2);
|
|
5615
|
+
return entry ? this.now() - entry.confirmedAt : null;
|
|
5616
|
+
}
|
|
5531
5617
|
/** The cached pack's ETag, without touching the order of eviction. */
|
|
5532
5618
|
etag(key2) {
|
|
5533
5619
|
return this.entries.get(key2)?.response.etag ?? null;
|
|
@@ -5750,7 +5836,7 @@ function mergeNotModified(cached, fresh) {
|
|
|
5750
5836
|
coordination: fresh.coordination ?? cached.coordination ?? null
|
|
5751
5837
|
};
|
|
5752
5838
|
}
|
|
5753
|
-
function resultFrom(response, source, error = null) {
|
|
5839
|
+
function resultFrom(response, source, error = null, ageMs = 0) {
|
|
5754
5840
|
const holdout = response.path === "holdout";
|
|
5755
5841
|
const text2 = holdout ? "" : response.text ?? "";
|
|
5756
5842
|
const pack = holdout ? null : response.pack ?? null;
|
|
@@ -5759,10 +5845,10 @@ function resultFrom(response, source, error = null) {
|
|
|
5759
5845
|
state: response.state ?? null,
|
|
5760
5846
|
coordination: response.coordination ?? null
|
|
5761
5847
|
};
|
|
5762
|
-
return { text: text2, suffix: renderSuffix(response), variables: response.variables, pack, source, response, error, ...blocks2 };
|
|
5848
|
+
return { text: text2, suffix: renderSuffix(response), variables: response.variables, pack, source, ageMs, response, error, ...blocks2 };
|
|
5763
5849
|
}
|
|
5764
5850
|
function emptyResult(error) {
|
|
5765
|
-
return { text: "", suffix: "", variables: {}, pack: null, source: "none", response: null, error, constraints: null, state: null, coordination: null };
|
|
5851
|
+
return { text: "", suffix: "", variables: {}, pack: null, source: "none", ageMs: null, response: null, error, constraints: null, state: null, coordination: null };
|
|
5766
5852
|
}
|
|
5767
5853
|
function renderSuffix(response) {
|
|
5768
5854
|
if (response.path === "holdout") return "";
|
|
@@ -8459,7 +8545,8 @@ var Niadra = class _Niadra {
|
|
|
8459
8545
|
baseURL,
|
|
8460
8546
|
apiKey,
|
|
8461
8547
|
fetch: fetchImpl,
|
|
8462
|
-
defaultHeaders: options.defaultHeaders ?? {}
|
|
8548
|
+
defaultHeaders: options.defaultHeaders ?? {},
|
|
8549
|
+
logger: this.logger
|
|
8463
8550
|
});
|
|
8464
8551
|
const queueOptions = { ...DEFAULT_QUEUE, ...options.queue };
|
|
8465
8552
|
queueOptions.maxBatchSize = Math.min(queueOptions.maxBatchSize, 499);
|
|
@@ -8556,19 +8643,29 @@ var Niadra = class _Niadra {
|
|
|
8556
8643
|
*/
|
|
8557
8644
|
async mayContact(handle, purpose, options = {}) {
|
|
8558
8645
|
if (this.core && this.suppressions.due()) {
|
|
8559
|
-
const read = this.suppressions.
|
|
8560
|
-
{
|
|
8561
|
-
salt: () => this.api.suppressionSalt({ timeout: this.timeouts.navigation }),
|
|
8562
|
-
page: (cursor, limit3) => this.api.suppressions({ cursor, limit: limit3 }, { timeout: this.timeouts.navigation })
|
|
8563
|
-
},
|
|
8564
|
-
this.suppressions.held ? this.timeouts.write : this.timeouts.navigation
|
|
8565
|
-
);
|
|
8646
|
+
const read = this.readSuppressions(this.suppressions.held ? this.timeouts.write : this.timeouts.navigation);
|
|
8566
8647
|
if (!this.suppressions.held) await read;
|
|
8567
8648
|
}
|
|
8568
8649
|
const checkOptions = { channel: options.channel ?? null };
|
|
8569
8650
|
if (options.failOpen !== void 0) checkOptions.failOpen = options.failOpen;
|
|
8570
8651
|
return this.suppressions.mayContact(handle, purpose, checkOptions);
|
|
8571
8652
|
}
|
|
8653
|
+
readSuppressions(budgetMs) {
|
|
8654
|
+
return this.suppressions.read(
|
|
8655
|
+
{
|
|
8656
|
+
salt: () => this.api.suppressionSalt({ timeout: this.timeouts.navigation }),
|
|
8657
|
+
page: (cursor, limit3) => this.api.suppressions({ cursor, limit: limit3 }, { timeout: this.timeouts.navigation })
|
|
8658
|
+
},
|
|
8659
|
+
budgetMs
|
|
8660
|
+
);
|
|
8661
|
+
}
|
|
8662
|
+
/**
|
|
8663
|
+
* Reads the local copy of the suppression list in the background when it is due: a check that Niadra does not
|
|
8664
|
+
* answer falls back on it, so an opt-out holds through an outage.
|
|
8665
|
+
*/
|
|
8666
|
+
keepSuppressions() {
|
|
8667
|
+
if (this.core && this.suppressions.due()) void this.readSuppressions(this.timeouts.write);
|
|
8668
|
+
}
|
|
8572
8669
|
/**
|
|
8573
8670
|
* The build a turn runs on, for `conversation.turn({ build })`: each prompt's version, the digest of the
|
|
8574
8671
|
* corpus the agent consults (computed by you, never the files), the model, your context assembler's version
|
|
@@ -8642,7 +8739,10 @@ var Niadra = class _Niadra {
|
|
|
8642
8739
|
states: this.states,
|
|
8643
8740
|
contract: () => this.currentContract(),
|
|
8644
8741
|
internalText: this.internalText,
|
|
8645
|
-
check: (request, timeoutMs) =>
|
|
8742
|
+
check: (request, timeoutMs) => {
|
|
8743
|
+
if (request.direction === "outbound") this.keepSuppressions();
|
|
8744
|
+
return this.api.check(request, { timeout: timeoutMs });
|
|
8745
|
+
},
|
|
8646
8746
|
claim: (request, timeoutMs) => this.api.claim(request, {}, { timeout: timeoutMs }),
|
|
8647
8747
|
verifyClaim: (ref, field, value, options) => this.verifyClaim(ref, field, value, options),
|
|
8648
8748
|
enabled: this.enabled,
|
|
@@ -8756,21 +8856,21 @@ var Niadra = class _Niadra {
|
|
|
8756
8856
|
}
|
|
8757
8857
|
const key2 = cacheKey(request);
|
|
8758
8858
|
const hit = cache.lookup(key2);
|
|
8759
|
-
if (hit?.freshness === "fresh") return resultFrom(delivered(hit.response, cache.take(key2)), "cache");
|
|
8859
|
+
if (hit?.freshness === "fresh") return resultFrom(delivered(hit.response, cache.take(key2)), "cache", null, cache.age(key2));
|
|
8760
8860
|
if (hit?.freshness === "stale") {
|
|
8761
8861
|
this.revalidate(core, cache, key2, scope, request, timeout, options.headers).catch((error) => {
|
|
8762
8862
|
this.logger.debug(`background context refresh failed: ${describe(toNiadraError(error))}`);
|
|
8763
8863
|
});
|
|
8764
|
-
return resultFrom(delivered(hit.response, cache.take(key2)), "stale");
|
|
8864
|
+
return resultFrom(delivered(hit.response, cache.take(key2)), "stale", null, cache.age(key2));
|
|
8765
8865
|
}
|
|
8766
8866
|
try {
|
|
8767
8867
|
const pending = this.revalidate(core, cache, key2, scope, request, timeout, options.headers);
|
|
8768
8868
|
const { response, source } = await abortable(pending, options.signal);
|
|
8769
|
-
return resultFrom(delivered(response, cache.take(key2)), source);
|
|
8869
|
+
return resultFrom(delivered(response, cache.take(key2)), source, null, source === "network" ? 0 : cache.age(key2));
|
|
8770
8870
|
} catch (error) {
|
|
8771
8871
|
const failure = toNiadraError(error);
|
|
8772
8872
|
const fallback2 = cache.lookup(key2);
|
|
8773
|
-
return this.contextFailure(failure, fallback2 ? delivered(fallback2.response, cache.take(key2)) : null);
|
|
8873
|
+
return this.contextFailure(failure, fallback2 ? delivered(fallback2.response, cache.take(key2)) : null, cache.age(key2));
|
|
8774
8874
|
}
|
|
8775
8875
|
}
|
|
8776
8876
|
/**
|
|
@@ -8792,11 +8892,11 @@ var Niadra = class _Niadra {
|
|
|
8792
8892
|
const failure = toNiadraError(error);
|
|
8793
8893
|
this.observeAuth(failure, key2);
|
|
8794
8894
|
const fallback2 = cache && key2 ? cache.lookup(key2) : null;
|
|
8795
|
-
return this.contextFailure(failure, cache && key2 && fallback2 ? delivered(fallback2.response, cache.take(key2)) : null);
|
|
8895
|
+
return this.contextFailure(failure, cache && key2 && fallback2 ? delivered(fallback2.response, cache.take(key2)) : null, key2 ? cache?.age(key2) ?? null : null);
|
|
8796
8896
|
}
|
|
8797
8897
|
if (!cache || !key2 || !scope) return resultFrom(response, "network");
|
|
8798
8898
|
if (response.degraded && !response.not_modified && cached) {
|
|
8799
|
-
return resultFrom(delivered({ ...cached.response, slots: response.slots ?? null }, cache.take(key2)), "fallback");
|
|
8899
|
+
return resultFrom(delivered({ ...cached.response, slots: response.slots ?? null }, cache.take(key2)), "fallback", null, cache.age(key2));
|
|
8800
8900
|
}
|
|
8801
8901
|
const merged = response.not_modified && cached ? mergeNotModified(cached.response, response) : response;
|
|
8802
8902
|
cache.store(key2, scope, withoutSlots(merged), generation);
|
|
@@ -9298,11 +9398,11 @@ var Niadra = class _Niadra {
|
|
|
9298
9398
|
}
|
|
9299
9399
|
});
|
|
9300
9400
|
}
|
|
9301
|
-
contextFailure(error, fallback2) {
|
|
9401
|
+
contextFailure(error, fallback2, ageMs = null) {
|
|
9302
9402
|
if (this.strict) throw error;
|
|
9303
9403
|
if (fallback2) {
|
|
9304
9404
|
this.logger.warn(`context request failed, serving the last good pack: ${describe(error)}`);
|
|
9305
|
-
return resultFrom(fallback2, "fallback", error);
|
|
9405
|
+
return resultFrom(fallback2, "fallback", error, ageMs);
|
|
9306
9406
|
}
|
|
9307
9407
|
this.logger.warn(`context unavailable: ${describe(error)}`);
|
|
9308
9408
|
return emptyResult(error);
|
|
@@ -9403,11 +9503,11 @@ var Niadra = class _Niadra {
|
|
|
9403
9503
|
});
|
|
9404
9504
|
}
|
|
9405
9505
|
const response = compose(delivered(hit.response, cache.take(key2)), chosen2);
|
|
9406
|
-
return resultFrom(response, opening.length > 0 ? "network" : hit.freshness === "fresh" ? "cache" : "stale");
|
|
9506
|
+
return resultFrom(response, opening.length > 0 ? "network" : hit.freshness === "fresh" ? "cache" : "stale", null, cache.age(key2));
|
|
9407
9507
|
} catch (error) {
|
|
9408
9508
|
const failure = toNiadraError(error);
|
|
9409
9509
|
const fallback2 = cache.lookup(key2);
|
|
9410
|
-
return this.contextFailure(failure, fallback2 ? delivered(fallback2.response, cache.take(key2)) : null);
|
|
9510
|
+
return this.contextFailure(failure, fallback2 ? delivered(fallback2.response, cache.take(key2)) : null, cache.age(key2));
|
|
9411
9511
|
}
|
|
9412
9512
|
}
|
|
9413
9513
|
/** Starts one read of a line in the background. */
|
|
@@ -9550,7 +9650,7 @@ var Niadra = class _Niadra {
|
|
|
9550
9650
|
else resolve({ ok: false, idempotency_key: key2, error });
|
|
9551
9651
|
};
|
|
9552
9652
|
core.queue.push(item, settle2);
|
|
9553
|
-
core.queue.flushInBackground();
|
|
9653
|
+
core.queue.flushInBackground(true);
|
|
9554
9654
|
});
|
|
9555
9655
|
}
|
|
9556
9656
|
async endScope(item, scope) {
|
|
@@ -11570,7 +11670,8 @@ var Counterfactual = class {
|
|
|
11570
11670
|
const fn = this.tools[tool2];
|
|
11571
11671
|
if (fn === void 0) throw new NiadraError(`no function for the tool ${tool2}: pass it in tools`);
|
|
11572
11672
|
if (!Number.isInteger(k) || k < 1 || k > MAX_K) throw new RangeError(`k must be 1 to ${String(MAX_K)}`);
|
|
11573
|
-
await this.
|
|
11673
|
+
const raw = await this.served(tool2);
|
|
11674
|
+
if (raw === null) throw new NiadraError(`the space binds no tool ${tool2} for this key's source: see its tool-bindings`);
|
|
11574
11675
|
const ids = [...turnIds];
|
|
11575
11676
|
if ((options.scenarioIds ?? []).length > 0) {
|
|
11576
11677
|
const found2 = await this.niadra.callRoute({ method: "GET", path: "/v1/scenarios", query: { ids: (options.scenarioIds ?? []).join(","), limit: 50 } });
|
|
@@ -11588,7 +11689,7 @@ var Counterfactual = class {
|
|
|
11588
11689
|
continue;
|
|
11589
11690
|
}
|
|
11590
11691
|
for (const call of calls(record, tool2)) {
|
|
11591
|
-
const found2 = await this.case(record, call, fn, element, k);
|
|
11692
|
+
const found2 = await this.case(record, call, fn, raw, element, k);
|
|
11592
11693
|
if (found2 === null) run.untouched++;
|
|
11593
11694
|
else run.cases.push(found2);
|
|
11594
11695
|
}
|
|
@@ -11598,17 +11699,15 @@ var Counterfactual = class {
|
|
|
11598
11699
|
run.report = await this.niadra.callRoute({ method: "POST", path: "/v1/measure/counterfactual-runs", body: report });
|
|
11599
11700
|
return run;
|
|
11600
11701
|
}
|
|
11601
|
-
async case(record, call, fn, element, k) {
|
|
11702
|
+
async case(record, call, fn, raw, element, k) {
|
|
11602
11703
|
const base = { turn_id: record.turn_id, call_id: call.call_id };
|
|
11603
11704
|
const tool2 = String(call.name);
|
|
11604
11705
|
const wrapped = recordedTool(fn);
|
|
11605
|
-
const raw = this.options.bindings?.[tool2] ?? wrapped?.binding ?? await this.served(tool2);
|
|
11606
11706
|
let block;
|
|
11607
11707
|
let args;
|
|
11608
11708
|
try {
|
|
11609
11709
|
block = await this.value(record, blockBlob(record, call));
|
|
11610
11710
|
args = { ...await this.value(record, call.args) };
|
|
11611
|
-
if (raw === null) throw new BlobError("the tool has no binding");
|
|
11612
11711
|
} catch {
|
|
11613
11712
|
return { ...base, status: "infrastructure_error", dry_run: false };
|
|
11614
11713
|
}
|