@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.js
CHANGED
|
@@ -516,7 +516,7 @@ function internalRecord(span, ref, act) {
|
|
|
516
516
|
}
|
|
517
517
|
|
|
518
518
|
// src/version.ts
|
|
519
|
-
var VERSION = "0.
|
|
519
|
+
var VERSION = "0.9.1";
|
|
520
520
|
|
|
521
521
|
// src/transport.ts
|
|
522
522
|
var RETRYABLE_WRITE_STATUS = /* @__PURE__ */ new Set([408, 421, 429, 500, 502, 503, 504]);
|
|
@@ -610,6 +610,7 @@ var Transport = class {
|
|
|
610
610
|
} catch (error) {
|
|
611
611
|
throw deadline.explain(error);
|
|
612
612
|
}
|
|
613
|
+
warnIfDeprecated(this.config.logger, init.method ?? "GET", url, response.headers);
|
|
613
614
|
const requestId = response.headers.get("x-request-id");
|
|
614
615
|
let payload;
|
|
615
616
|
try {
|
|
@@ -679,6 +680,29 @@ var Deadline = class {
|
|
|
679
680
|
return new NiadraConnectionError(`connection failed: ${message}`, { cause: error });
|
|
680
681
|
}
|
|
681
682
|
};
|
|
683
|
+
var VERSIONING_DOCS = "https://docs.niadra.com/en/security/api-versioning";
|
|
684
|
+
var DEPRECATION_LINK = /<([^>]*)>[^,]*;\s*rel="?deprecation"?/gi;
|
|
685
|
+
var deprecationsSeen = /* @__PURE__ */ new Set();
|
|
686
|
+
function warnIfDeprecated(logger, method, url, headers) {
|
|
687
|
+
const since = headers.get("deprecation");
|
|
688
|
+
if (since === null) return;
|
|
689
|
+
const links = [...(headers.get("link") ?? "").matchAll(DEPRECATION_LINK)].map((match) => match[1] ?? "");
|
|
690
|
+
const key2 = `${method} ${links.join(" ") || (url.split("?")[0] ?? url)}`;
|
|
691
|
+
if (deprecationsSeen.has(key2)) return;
|
|
692
|
+
deprecationsSeen.add(key2);
|
|
693
|
+
const sunset = headers.get("sunset");
|
|
694
|
+
logger.warn(
|
|
695
|
+
`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}`
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
function deprecatedSince(value) {
|
|
699
|
+
const seconds = Number(value.trim().replace(/^@/, ""));
|
|
700
|
+
return Number.isInteger(seconds) ? new Date(seconds * 1e3).toISOString().slice(0, 10) : value;
|
|
701
|
+
}
|
|
702
|
+
function sunsetDay(value) {
|
|
703
|
+
const time = Date.parse(value);
|
|
704
|
+
return Number.isNaN(time) ? value : new Date(time).toISOString().slice(0, 10);
|
|
705
|
+
}
|
|
682
706
|
async function readBody(response) {
|
|
683
707
|
const text2 = await response.text();
|
|
684
708
|
if (text2.length === 0) return null;
|
|
@@ -2902,6 +2926,11 @@ ${change.field}`)) out.push({ ref, field: change.field, value: change.now, claim
|
|
|
2902
2926
|
for (const s of constraints.soft ?? []) said.push([s.attr, s.value]);
|
|
2903
2927
|
for (const a of constraints.attributes ?? []) said.push([a.name, a.value]);
|
|
2904
2928
|
for (const [attr, value] of said) out.push({ ref: null, field: attr.split(".").pop() ?? attr, value, claimSafe: true });
|
|
2929
|
+
for (const shown of constraints.already_presented ?? []) {
|
|
2930
|
+
for (const [field, n] of Object.entries(shown.values ?? {})) {
|
|
2931
|
+
out.push({ ref: shown.ref, field, value: n.v, claimSafe: n.claim_safe, role: n.role ?? null });
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2905
2934
|
}
|
|
2906
2935
|
return out;
|
|
2907
2936
|
}
|
|
@@ -3268,7 +3297,7 @@ function thenable(value) {
|
|
|
3268
3297
|
function tool(name, fn, options = {}) {
|
|
3269
3298
|
const isAsync = isAsyncFunction(fn);
|
|
3270
3299
|
function bindingOf(frame) {
|
|
3271
|
-
return
|
|
3300
|
+
return (options.served ?? frame?.profile.bindings)?.(name) ?? null;
|
|
3272
3301
|
}
|
|
3273
3302
|
function masks(frame) {
|
|
3274
3303
|
return options.maskOutput ?? bindingOf(frame)?.capabilities?.mask_output ?? false;
|
|
@@ -3383,8 +3412,7 @@ function tool(name, fn, options = {}) {
|
|
|
3383
3412
|
const marker = {
|
|
3384
3413
|
name,
|
|
3385
3414
|
dryRun: options.dryRun ?? false,
|
|
3386
|
-
provenance: options.provenance ?? null
|
|
3387
|
-
binding: options.binding ?? null
|
|
3415
|
+
provenance: options.provenance ?? null
|
|
3388
3416
|
};
|
|
3389
3417
|
Object.defineProperty(wrapped, RECORDED, { value: marker });
|
|
3390
3418
|
return wrapped;
|
|
@@ -3646,6 +3674,7 @@ function claimsOf(frame, claims, logger) {
|
|
|
3646
3674
|
|
|
3647
3675
|
// src/queue.ts
|
|
3648
3676
|
var HEARTBEAT_WINDOW_MS = 6e4;
|
|
3677
|
+
var MAX_PAUSE_MS = 6e4;
|
|
3649
3678
|
var EventQueue = class {
|
|
3650
3679
|
constructor(send, options, logger, now = Date.now) {
|
|
3651
3680
|
this.send = send;
|
|
@@ -3666,6 +3695,8 @@ var EventQueue = class {
|
|
|
3666
3695
|
droppedSinceWarning = 0;
|
|
3667
3696
|
windowStart;
|
|
3668
3697
|
sentInWindow = 0;
|
|
3698
|
+
pauseMs = 0;
|
|
3699
|
+
resumeAt = 0;
|
|
3669
3700
|
/** Items waiting to be sent, not counting a batch already in flight. */
|
|
3670
3701
|
get size() {
|
|
3671
3702
|
return this.items.length;
|
|
@@ -3701,10 +3732,16 @@ var EventQueue = class {
|
|
|
3701
3732
|
return run;
|
|
3702
3733
|
}
|
|
3703
3734
|
/**
|
|
3704
|
-
* Starts a flush without waiting for it
|
|
3705
|
-
*
|
|
3735
|
+
* Starts a flush without waiting for it: once the pause after a failed batch ends, or at once with
|
|
3736
|
+
* `now` (a caller waits for an item). Item failures are logged and settled inside the drain, so only
|
|
3737
|
+
* an unexpected error reaches this catch.
|
|
3706
3738
|
*/
|
|
3707
|
-
flushInBackground() {
|
|
3739
|
+
flushInBackground(now = false) {
|
|
3740
|
+
const paused = this.resumeAt - this.now();
|
|
3741
|
+
if (!now && paused > 0) {
|
|
3742
|
+
this.schedule(paused);
|
|
3743
|
+
return;
|
|
3744
|
+
}
|
|
3708
3745
|
this.flush().catch((error) => {
|
|
3709
3746
|
this.logger.error(`event flush failed: ${toNiadraError(error).message}`);
|
|
3710
3747
|
});
|
|
@@ -3721,24 +3758,36 @@ var EventQueue = class {
|
|
|
3721
3758
|
while (this.items.length > 0) {
|
|
3722
3759
|
const batch = this.items.splice(0, this.options.maxBatchSize);
|
|
3723
3760
|
const heartbeat = this.heartbeat();
|
|
3724
|
-
|
|
3725
|
-
if (
|
|
3726
|
-
await this.sendBatch(batch, wire, report);
|
|
3761
|
+
if (heartbeat) batch.push({ item: heartbeat });
|
|
3762
|
+
if (!await this.sendBatch(batch, report)) break;
|
|
3727
3763
|
}
|
|
3728
3764
|
return report;
|
|
3729
3765
|
}
|
|
3730
|
-
|
|
3766
|
+
/** Sends one batch; `false` when it went back to the queue and the queue pauses. */
|
|
3767
|
+
async sendBatch(batch, report) {
|
|
3768
|
+
const wire = batch.map((pending) => pending.item);
|
|
3731
3769
|
let response;
|
|
3732
3770
|
try {
|
|
3733
3771
|
response = await this.send(wire);
|
|
3734
3772
|
} catch (error) {
|
|
3735
3773
|
const failure = toNiadraError(error);
|
|
3736
|
-
report.failed += batch.length;
|
|
3737
3774
|
report.errors.push(failure);
|
|
3738
|
-
|
|
3775
|
+
if (isTransient(failure)) {
|
|
3776
|
+
for (const pending of batch) pending.settle?.(failure);
|
|
3777
|
+
this.requeue(batch);
|
|
3778
|
+
this.pauseMs = Math.min(MAX_PAUSE_MS, Math.max(this.options.flushIntervalMs, this.pauseMs * 2));
|
|
3779
|
+
this.resumeAt = this.now() + this.pauseMs;
|
|
3780
|
+
this.logger.warn(`could not deliver ${batch.length} events, will retry: ${failure.message}`);
|
|
3781
|
+
this.schedule(this.pauseMs);
|
|
3782
|
+
return false;
|
|
3783
|
+
}
|
|
3784
|
+
report.failed += batch.length;
|
|
3785
|
+
this.logger.warn(`dropped ${batch.length} events refused by the API: ${failure.message}`);
|
|
3739
3786
|
for (const pending of batch) pending.settle?.(failure);
|
|
3740
|
-
return;
|
|
3787
|
+
return true;
|
|
3741
3788
|
}
|
|
3789
|
+
this.pauseMs = 0;
|
|
3790
|
+
this.resumeAt = 0;
|
|
3742
3791
|
const rejected = /* @__PURE__ */ new Map();
|
|
3743
3792
|
for (const itemError of response.errors) {
|
|
3744
3793
|
const detail = itemError.detail ? `: ${itemError.detail}` : "";
|
|
@@ -3749,6 +3798,7 @@ var EventQueue = class {
|
|
|
3749
3798
|
this.logger.warn(`server rejected ${rejected.size} of ${wire.length} items (${codes2})`);
|
|
3750
3799
|
}
|
|
3751
3800
|
batch.forEach((pending, index) => {
|
|
3801
|
+
if (pending.item.type === "heartbeat") return;
|
|
3752
3802
|
const error = rejected.get(index) ?? null;
|
|
3753
3803
|
if (error) {
|
|
3754
3804
|
report.failed++;
|
|
@@ -3759,6 +3809,17 @@ var EventQueue = class {
|
|
|
3759
3809
|
}
|
|
3760
3810
|
pending.settle?.(error);
|
|
3761
3811
|
});
|
|
3812
|
+
return true;
|
|
3813
|
+
}
|
|
3814
|
+
/** Puts a batch back at the front, keeping only what still fits; what does not is dropped. */
|
|
3815
|
+
requeue(batch) {
|
|
3816
|
+
const room = Math.max(0, this.options.maxQueueSize - this.items.length);
|
|
3817
|
+
const lost = batch.slice(room);
|
|
3818
|
+
this.items.unshift(...batch.slice(0, room));
|
|
3819
|
+
if (lost.length > 0) {
|
|
3820
|
+
this.logger.warn(`event queue is full; dropped ${lost.length} events`);
|
|
3821
|
+
for (const pending of lost) pending.settle?.(new NiadraError("event queue is full"));
|
|
3822
|
+
}
|
|
3762
3823
|
}
|
|
3763
3824
|
/**
|
|
3764
3825
|
* Once a minute, the next batch carries the number of items sent in the previous window.
|
|
@@ -3809,7 +3870,7 @@ function unref(timer) {
|
|
|
3809
3870
|
var MAX_TURNS = 50;
|
|
3810
3871
|
var COMPRESSED_ROOM = 4 * 1024 * 1024 - 64 * 1024;
|
|
3811
3872
|
var DECODED_ROOM = 16 * 1024 * 1024 - 256 * 1024;
|
|
3812
|
-
var
|
|
3873
|
+
var MAX_PAUSE_MS2 = 6e4;
|
|
3813
3874
|
var encoder2 = new TextEncoder();
|
|
3814
3875
|
async function encode(records) {
|
|
3815
3876
|
const raw = encoder2.encode(JSON.stringify({ turns: records }));
|
|
@@ -3968,7 +4029,7 @@ var TurnSender = class {
|
|
|
3968
4029
|
}
|
|
3969
4030
|
if (isTransient(error)) {
|
|
3970
4031
|
this.queue.requeue(batch.frames);
|
|
3971
|
-
this.pause = Math.min(
|
|
4032
|
+
this.pause = Math.min(MAX_PAUSE_MS2, Math.max(this.intervalMs, this.pause * 2));
|
|
3972
4033
|
this.resumeAt = this.now() + this.pause;
|
|
3973
4034
|
this.logger.warn(`could not deliver ${batch.frames.length} turns, will retry (${toNiadraError(error).name})`);
|
|
3974
4035
|
return false;
|
|
@@ -4356,26 +4417,42 @@ async function suppressionKey(salt, canonical2) {
|
|
|
4356
4417
|
const key2 = await subtle.importKey("raw", saltBytes(salt), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
4357
4418
|
return toBase64url(new Uint8Array(await subtle.sign("HMAC", key2, new TextEncoder().encode(canonical2))));
|
|
4358
4419
|
}
|
|
4420
|
+
var AREA_CODES = new Set(
|
|
4421
|
+
"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(" ")
|
|
4422
|
+
);
|
|
4423
|
+
var FORMAT_CHARACTERS = /\p{Cf}/gu;
|
|
4359
4424
|
function phone(value) {
|
|
4360
|
-
|
|
4361
|
-
|
|
4425
|
+
let text2 = value.normalize("NFKC").replace(FORMAT_CHARACTERS, "").trim();
|
|
4426
|
+
if (text2.slice(0, 4).toLowerCase() === "tel:") text2 = text2.slice(4);
|
|
4427
|
+
const international = text2.startsWith("+") || text2.startsWith("00");
|
|
4428
|
+
if (international) text2 = text2.replaceAll("(0)", "");
|
|
4429
|
+
const raw = text2.replace(SEPARATORS2, "");
|
|
4362
4430
|
let digits = raw.startsWith("+") ? raw.slice(1) : international ? raw.slice(2) : raw;
|
|
4363
4431
|
if (!DIGITS2.test(digits)) throw new NiadraDestinationError("invalid_handle");
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4432
|
+
if (!international) {
|
|
4433
|
+
const national = digits.replace(/^0+/, "");
|
|
4434
|
+
if (isBrazilianNational(national)) {
|
|
4435
|
+
digits = `55${national}`;
|
|
4436
|
+
} else if (digits.startsWith("0") && (national.length === 12 || national.length === 13)) {
|
|
4437
|
+
if (isBrazilianNational(national.slice(2))) digits = `55${national.slice(2)}`;
|
|
4438
|
+
}
|
|
4367
4439
|
}
|
|
4368
4440
|
if (digits.length < 8 || digits.length > 15 || digits.startsWith("0")) {
|
|
4369
4441
|
throw new NiadraDestinationError("invalid_handle");
|
|
4370
4442
|
}
|
|
4371
4443
|
const rest = digits.slice(2);
|
|
4372
|
-
if (digits.startsWith("55") && rest.length === 10 &&
|
|
4444
|
+
if (digits.startsWith("55") && rest.length === 10 && AREA_CODES.has(rest.slice(0, 2)) && "6789".includes(rest.charAt(2))) {
|
|
4373
4445
|
digits = `55${rest.slice(0, 2)}9${rest.slice(2)}`;
|
|
4374
4446
|
}
|
|
4447
|
+
if (digits.length === 13 && (digits.startsWith("521") || digits.startsWith("549"))) {
|
|
4448
|
+
digits = digits.slice(0, 2) + digits.slice(3);
|
|
4449
|
+
}
|
|
4375
4450
|
return `phone:+${digits}`;
|
|
4376
4451
|
}
|
|
4377
|
-
function
|
|
4378
|
-
|
|
4452
|
+
function isBrazilianNational(national) {
|
|
4453
|
+
if (!AREA_CODES.has(national.slice(0, 2))) return false;
|
|
4454
|
+
if (national.length === 10) return "23456789".includes(national.charAt(2));
|
|
4455
|
+
return national.length === 11 && national.charAt(2) === "9";
|
|
4379
4456
|
}
|
|
4380
4457
|
function saltBytes(salt) {
|
|
4381
4458
|
const bytes = fromBase64url(salt);
|
|
@@ -4434,7 +4511,10 @@ var SuppressionCopy = class {
|
|
|
4434
4511
|
}
|
|
4435
4512
|
this.saltValue = salt;
|
|
4436
4513
|
}
|
|
4437
|
-
/**
|
|
4514
|
+
/**
|
|
4515
|
+
* Applies one page, in order. `true` when more pages follow: a full page. Every page carries the cursor to
|
|
4516
|
+
* read from next, the last one too, which the next read starts from.
|
|
4517
|
+
*/
|
|
4438
4518
|
apply(page) {
|
|
4439
4519
|
if (page.salt_id !== this.saltValue?.salt_id) {
|
|
4440
4520
|
this.saltValue = null;
|
|
@@ -4449,8 +4529,9 @@ var SuppressionCopy = class {
|
|
|
4449
4529
|
}
|
|
4450
4530
|
this.cursor = page.next_cursor ?? this.cursor;
|
|
4451
4531
|
this.absent = false;
|
|
4452
|
-
|
|
4453
|
-
|
|
4532
|
+
const more = Boolean(page.next_cursor) && page.items.length >= PAGE;
|
|
4533
|
+
if (!more) this.readAt = this.now();
|
|
4534
|
+
return more;
|
|
4454
4535
|
}
|
|
4455
4536
|
/** A 404: the space keeps no list. Anything else: the copy stays as it is. */
|
|
4456
4537
|
failed(error) {
|
|
@@ -4675,7 +4756,7 @@ var ContactGateway = class {
|
|
|
4675
4756
|
|
|
4676
4757
|
// src/outbox.ts
|
|
4677
4758
|
var CAPACITY = 1e3;
|
|
4678
|
-
var
|
|
4759
|
+
var MAX_PAUSE_MS3 = 6e4;
|
|
4679
4760
|
var Outbox = class {
|
|
4680
4761
|
constructor(logger, intervalMs = 1e3, now = Date.now) {
|
|
4681
4762
|
this.logger = logger;
|
|
@@ -4743,7 +4824,7 @@ var Outbox = class {
|
|
|
4743
4824
|
answer = await write.send();
|
|
4744
4825
|
} catch (error) {
|
|
4745
4826
|
if (isTransient(error)) {
|
|
4746
|
-
this.pause = Math.min(
|
|
4827
|
+
this.pause = Math.min(MAX_PAUSE_MS3, Math.max(this.intervalMs, this.pause * 2));
|
|
4747
4828
|
this.resumeAt = this.now() + this.pause;
|
|
4748
4829
|
return false;
|
|
4749
4830
|
}
|
|
@@ -5526,6 +5607,11 @@ var ContextCache = class {
|
|
|
5526
5607
|
}
|
|
5527
5608
|
return true;
|
|
5528
5609
|
}
|
|
5610
|
+
/** Milliseconds since the server last sent or confirmed the pack held for `key`; `null` when none is held. */
|
|
5611
|
+
age(key2) {
|
|
5612
|
+
const entry = this.entries.get(key2);
|
|
5613
|
+
return entry ? this.now() - entry.confirmedAt : null;
|
|
5614
|
+
}
|
|
5529
5615
|
/** The cached pack's ETag, without touching the order of eviction. */
|
|
5530
5616
|
etag(key2) {
|
|
5531
5617
|
return this.entries.get(key2)?.response.etag ?? null;
|
|
@@ -5748,7 +5834,7 @@ function mergeNotModified(cached, fresh) {
|
|
|
5748
5834
|
coordination: fresh.coordination ?? cached.coordination ?? null
|
|
5749
5835
|
};
|
|
5750
5836
|
}
|
|
5751
|
-
function resultFrom(response, source, error = null) {
|
|
5837
|
+
function resultFrom(response, source, error = null, ageMs = 0) {
|
|
5752
5838
|
const holdout = response.path === "holdout";
|
|
5753
5839
|
const text2 = holdout ? "" : response.text ?? "";
|
|
5754
5840
|
const pack = holdout ? null : response.pack ?? null;
|
|
@@ -5757,10 +5843,10 @@ function resultFrom(response, source, error = null) {
|
|
|
5757
5843
|
state: response.state ?? null,
|
|
5758
5844
|
coordination: response.coordination ?? null
|
|
5759
5845
|
};
|
|
5760
|
-
return { text: text2, suffix: renderSuffix(response), variables: response.variables, pack, source, response, error, ...blocks2 };
|
|
5846
|
+
return { text: text2, suffix: renderSuffix(response), variables: response.variables, pack, source, ageMs, response, error, ...blocks2 };
|
|
5761
5847
|
}
|
|
5762
5848
|
function emptyResult(error) {
|
|
5763
|
-
return { text: "", suffix: "", variables: {}, pack: null, source: "none", response: null, error, constraints: null, state: null, coordination: null };
|
|
5849
|
+
return { text: "", suffix: "", variables: {}, pack: null, source: "none", ageMs: null, response: null, error, constraints: null, state: null, coordination: null };
|
|
5764
5850
|
}
|
|
5765
5851
|
function renderSuffix(response) {
|
|
5766
5852
|
if (response.path === "holdout") return "";
|
|
@@ -8457,7 +8543,8 @@ var Niadra = class _Niadra {
|
|
|
8457
8543
|
baseURL,
|
|
8458
8544
|
apiKey,
|
|
8459
8545
|
fetch: fetchImpl,
|
|
8460
|
-
defaultHeaders: options.defaultHeaders ?? {}
|
|
8546
|
+
defaultHeaders: options.defaultHeaders ?? {},
|
|
8547
|
+
logger: this.logger
|
|
8461
8548
|
});
|
|
8462
8549
|
const queueOptions = { ...DEFAULT_QUEUE, ...options.queue };
|
|
8463
8550
|
queueOptions.maxBatchSize = Math.min(queueOptions.maxBatchSize, 499);
|
|
@@ -8554,19 +8641,29 @@ var Niadra = class _Niadra {
|
|
|
8554
8641
|
*/
|
|
8555
8642
|
async mayContact(handle, purpose, options = {}) {
|
|
8556
8643
|
if (this.core && this.suppressions.due()) {
|
|
8557
|
-
const read = this.suppressions.
|
|
8558
|
-
{
|
|
8559
|
-
salt: () => this.api.suppressionSalt({ timeout: this.timeouts.navigation }),
|
|
8560
|
-
page: (cursor, limit3) => this.api.suppressions({ cursor, limit: limit3 }, { timeout: this.timeouts.navigation })
|
|
8561
|
-
},
|
|
8562
|
-
this.suppressions.held ? this.timeouts.write : this.timeouts.navigation
|
|
8563
|
-
);
|
|
8644
|
+
const read = this.readSuppressions(this.suppressions.held ? this.timeouts.write : this.timeouts.navigation);
|
|
8564
8645
|
if (!this.suppressions.held) await read;
|
|
8565
8646
|
}
|
|
8566
8647
|
const checkOptions = { channel: options.channel ?? null };
|
|
8567
8648
|
if (options.failOpen !== void 0) checkOptions.failOpen = options.failOpen;
|
|
8568
8649
|
return this.suppressions.mayContact(handle, purpose, checkOptions);
|
|
8569
8650
|
}
|
|
8651
|
+
readSuppressions(budgetMs) {
|
|
8652
|
+
return this.suppressions.read(
|
|
8653
|
+
{
|
|
8654
|
+
salt: () => this.api.suppressionSalt({ timeout: this.timeouts.navigation }),
|
|
8655
|
+
page: (cursor, limit3) => this.api.suppressions({ cursor, limit: limit3 }, { timeout: this.timeouts.navigation })
|
|
8656
|
+
},
|
|
8657
|
+
budgetMs
|
|
8658
|
+
);
|
|
8659
|
+
}
|
|
8660
|
+
/**
|
|
8661
|
+
* Reads the local copy of the suppression list in the background when it is due: a check that Niadra does not
|
|
8662
|
+
* answer falls back on it, so an opt-out holds through an outage.
|
|
8663
|
+
*/
|
|
8664
|
+
keepSuppressions() {
|
|
8665
|
+
if (this.core && this.suppressions.due()) void this.readSuppressions(this.timeouts.write);
|
|
8666
|
+
}
|
|
8570
8667
|
/**
|
|
8571
8668
|
* The build a turn runs on, for `conversation.turn({ build })`: each prompt's version, the digest of the
|
|
8572
8669
|
* corpus the agent consults (computed by you, never the files), the model, your context assembler's version
|
|
@@ -8640,7 +8737,10 @@ var Niadra = class _Niadra {
|
|
|
8640
8737
|
states: this.states,
|
|
8641
8738
|
contract: () => this.currentContract(),
|
|
8642
8739
|
internalText: this.internalText,
|
|
8643
|
-
check: (request, timeoutMs) =>
|
|
8740
|
+
check: (request, timeoutMs) => {
|
|
8741
|
+
if (request.direction === "outbound") this.keepSuppressions();
|
|
8742
|
+
return this.api.check(request, { timeout: timeoutMs });
|
|
8743
|
+
},
|
|
8644
8744
|
claim: (request, timeoutMs) => this.api.claim(request, {}, { timeout: timeoutMs }),
|
|
8645
8745
|
verifyClaim: (ref, field, value, options) => this.verifyClaim(ref, field, value, options),
|
|
8646
8746
|
enabled: this.enabled,
|
|
@@ -8754,21 +8854,21 @@ var Niadra = class _Niadra {
|
|
|
8754
8854
|
}
|
|
8755
8855
|
const key2 = cacheKey(request);
|
|
8756
8856
|
const hit = cache.lookup(key2);
|
|
8757
|
-
if (hit?.freshness === "fresh") return resultFrom(delivered(hit.response, cache.take(key2)), "cache");
|
|
8857
|
+
if (hit?.freshness === "fresh") return resultFrom(delivered(hit.response, cache.take(key2)), "cache", null, cache.age(key2));
|
|
8758
8858
|
if (hit?.freshness === "stale") {
|
|
8759
8859
|
this.revalidate(core, cache, key2, scope, request, timeout, options.headers).catch((error) => {
|
|
8760
8860
|
this.logger.debug(`background context refresh failed: ${describe(toNiadraError(error))}`);
|
|
8761
8861
|
});
|
|
8762
|
-
return resultFrom(delivered(hit.response, cache.take(key2)), "stale");
|
|
8862
|
+
return resultFrom(delivered(hit.response, cache.take(key2)), "stale", null, cache.age(key2));
|
|
8763
8863
|
}
|
|
8764
8864
|
try {
|
|
8765
8865
|
const pending = this.revalidate(core, cache, key2, scope, request, timeout, options.headers);
|
|
8766
8866
|
const { response, source } = await abortable(pending, options.signal);
|
|
8767
|
-
return resultFrom(delivered(response, cache.take(key2)), source);
|
|
8867
|
+
return resultFrom(delivered(response, cache.take(key2)), source, null, source === "network" ? 0 : cache.age(key2));
|
|
8768
8868
|
} catch (error) {
|
|
8769
8869
|
const failure = toNiadraError(error);
|
|
8770
8870
|
const fallback2 = cache.lookup(key2);
|
|
8771
|
-
return this.contextFailure(failure, fallback2 ? delivered(fallback2.response, cache.take(key2)) : null);
|
|
8871
|
+
return this.contextFailure(failure, fallback2 ? delivered(fallback2.response, cache.take(key2)) : null, cache.age(key2));
|
|
8772
8872
|
}
|
|
8773
8873
|
}
|
|
8774
8874
|
/**
|
|
@@ -8790,11 +8890,11 @@ var Niadra = class _Niadra {
|
|
|
8790
8890
|
const failure = toNiadraError(error);
|
|
8791
8891
|
this.observeAuth(failure, key2);
|
|
8792
8892
|
const fallback2 = cache && key2 ? cache.lookup(key2) : null;
|
|
8793
|
-
return this.contextFailure(failure, cache && key2 && fallback2 ? delivered(fallback2.response, cache.take(key2)) : null);
|
|
8893
|
+
return this.contextFailure(failure, cache && key2 && fallback2 ? delivered(fallback2.response, cache.take(key2)) : null, key2 ? cache?.age(key2) ?? null : null);
|
|
8794
8894
|
}
|
|
8795
8895
|
if (!cache || !key2 || !scope) return resultFrom(response, "network");
|
|
8796
8896
|
if (response.degraded && !response.not_modified && cached) {
|
|
8797
|
-
return resultFrom(delivered({ ...cached.response, slots: response.slots ?? null }, cache.take(key2)), "fallback");
|
|
8897
|
+
return resultFrom(delivered({ ...cached.response, slots: response.slots ?? null }, cache.take(key2)), "fallback", null, cache.age(key2));
|
|
8798
8898
|
}
|
|
8799
8899
|
const merged = response.not_modified && cached ? mergeNotModified(cached.response, response) : response;
|
|
8800
8900
|
cache.store(key2, scope, withoutSlots(merged), generation);
|
|
@@ -9296,11 +9396,11 @@ var Niadra = class _Niadra {
|
|
|
9296
9396
|
}
|
|
9297
9397
|
});
|
|
9298
9398
|
}
|
|
9299
|
-
contextFailure(error, fallback2) {
|
|
9399
|
+
contextFailure(error, fallback2, ageMs = null) {
|
|
9300
9400
|
if (this.strict) throw error;
|
|
9301
9401
|
if (fallback2) {
|
|
9302
9402
|
this.logger.warn(`context request failed, serving the last good pack: ${describe(error)}`);
|
|
9303
|
-
return resultFrom(fallback2, "fallback", error);
|
|
9403
|
+
return resultFrom(fallback2, "fallback", error, ageMs);
|
|
9304
9404
|
}
|
|
9305
9405
|
this.logger.warn(`context unavailable: ${describe(error)}`);
|
|
9306
9406
|
return emptyResult(error);
|
|
@@ -9401,11 +9501,11 @@ var Niadra = class _Niadra {
|
|
|
9401
9501
|
});
|
|
9402
9502
|
}
|
|
9403
9503
|
const response = compose(delivered(hit.response, cache.take(key2)), chosen2);
|
|
9404
|
-
return resultFrom(response, opening.length > 0 ? "network" : hit.freshness === "fresh" ? "cache" : "stale");
|
|
9504
|
+
return resultFrom(response, opening.length > 0 ? "network" : hit.freshness === "fresh" ? "cache" : "stale", null, cache.age(key2));
|
|
9405
9505
|
} catch (error) {
|
|
9406
9506
|
const failure = toNiadraError(error);
|
|
9407
9507
|
const fallback2 = cache.lookup(key2);
|
|
9408
|
-
return this.contextFailure(failure, fallback2 ? delivered(fallback2.response, cache.take(key2)) : null);
|
|
9508
|
+
return this.contextFailure(failure, fallback2 ? delivered(fallback2.response, cache.take(key2)) : null, cache.age(key2));
|
|
9409
9509
|
}
|
|
9410
9510
|
}
|
|
9411
9511
|
/** Starts one read of a line in the background. */
|
|
@@ -9548,7 +9648,7 @@ var Niadra = class _Niadra {
|
|
|
9548
9648
|
else resolve({ ok: false, idempotency_key: key2, error });
|
|
9549
9649
|
};
|
|
9550
9650
|
core.queue.push(item, settle2);
|
|
9551
|
-
core.queue.flushInBackground();
|
|
9651
|
+
core.queue.flushInBackground(true);
|
|
9552
9652
|
});
|
|
9553
9653
|
}
|
|
9554
9654
|
async endScope(item, scope) {
|
|
@@ -11568,7 +11668,8 @@ var Counterfactual = class {
|
|
|
11568
11668
|
const fn = this.tools[tool2];
|
|
11569
11669
|
if (fn === void 0) throw new NiadraError(`no function for the tool ${tool2}: pass it in tools`);
|
|
11570
11670
|
if (!Number.isInteger(k) || k < 1 || k > MAX_K) throw new RangeError(`k must be 1 to ${String(MAX_K)}`);
|
|
11571
|
-
await this.
|
|
11671
|
+
const raw = await this.served(tool2);
|
|
11672
|
+
if (raw === null) throw new NiadraError(`the space binds no tool ${tool2} for this key's source: see its tool-bindings`);
|
|
11572
11673
|
const ids = [...turnIds];
|
|
11573
11674
|
if ((options.scenarioIds ?? []).length > 0) {
|
|
11574
11675
|
const found2 = await this.niadra.callRoute({ method: "GET", path: "/v1/scenarios", query: { ids: (options.scenarioIds ?? []).join(","), limit: 50 } });
|
|
@@ -11586,7 +11687,7 @@ var Counterfactual = class {
|
|
|
11586
11687
|
continue;
|
|
11587
11688
|
}
|
|
11588
11689
|
for (const call of calls(record, tool2)) {
|
|
11589
|
-
const found2 = await this.case(record, call, fn, element, k);
|
|
11690
|
+
const found2 = await this.case(record, call, fn, raw, element, k);
|
|
11590
11691
|
if (found2 === null) run.untouched++;
|
|
11591
11692
|
else run.cases.push(found2);
|
|
11592
11693
|
}
|
|
@@ -11596,17 +11697,15 @@ var Counterfactual = class {
|
|
|
11596
11697
|
run.report = await this.niadra.callRoute({ method: "POST", path: "/v1/measure/counterfactual-runs", body: report });
|
|
11597
11698
|
return run;
|
|
11598
11699
|
}
|
|
11599
|
-
async case(record, call, fn, element, k) {
|
|
11700
|
+
async case(record, call, fn, raw, element, k) {
|
|
11600
11701
|
const base = { turn_id: record.turn_id, call_id: call.call_id };
|
|
11601
11702
|
const tool2 = String(call.name);
|
|
11602
11703
|
const wrapped = recordedTool(fn);
|
|
11603
|
-
const raw = this.options.bindings?.[tool2] ?? wrapped?.binding ?? await this.served(tool2);
|
|
11604
11704
|
let block;
|
|
11605
11705
|
let args;
|
|
11606
11706
|
try {
|
|
11607
11707
|
block = await this.value(record, blockBlob(record, call));
|
|
11608
11708
|
args = { ...await this.value(record, call.args) };
|
|
11609
|
-
if (raw === null) throw new BlobError("the tool has no binding");
|
|
11610
11709
|
} catch {
|
|
11611
11710
|
return { ...base, status: "infrastructure_error", dry_run: false };
|
|
11612
11711
|
}
|