@vinaverse/client 0.1.0-alpha.6 → 0.1.0-alpha.8
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/README.md +69 -7
- package/dist/agent/index.cjs +526 -75
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +3 -3
- package/dist/agent/index.d.ts +3 -3
- package/dist/agent/index.js +2 -2
- package/dist/backend/index.cjs +268 -0
- package/dist/backend/index.cjs.map +1 -0
- package/dist/backend/index.d.cts +72 -0
- package/dist/backend/index.d.ts +72 -0
- package/dist/backend/index.js +250 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/{chunk-ZWG2TMUL.js → chunk-46D3FSLU.js} +24 -2
- package/dist/chunk-46D3FSLU.js.map +1 -0
- package/dist/chunk-DI4DPUNA.js +843 -0
- package/dist/chunk-DI4DPUNA.js.map +1 -0
- package/dist/chunk-YNUHXJD6.js +9 -0
- package/dist/{chunk-VSJDVLCP.js.map → chunk-YNUHXJD6.js.map} +1 -1
- package/dist/contract-DmQs8amJ.d.cts +6 -0
- package/dist/contract-DmQs8amJ.d.ts +6 -0
- package/dist/conversation/index.cjs +24 -2
- package/dist/conversation/index.cjs.map +1 -1
- package/dist/conversation/index.d.cts +5 -5
- package/dist/conversation/index.d.ts +5 -5
- package/dist/conversation/index.js +3 -3
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{runtime-DLJbJkSr.d.ts → runtime-A4ovUdrc.d.cts} +147 -21
- package/dist/{runtime-CErMdYxJ.d.cts → runtime-B6_l8--U.d.ts} +147 -21
- package/dist/{session-8W3fRNeb.d.cts → session-CPz4pcPu.d.cts} +246 -7
- package/dist/{session-8W3fRNeb.d.ts → session-CPz4pcPu.d.ts} +246 -7
- package/dist/{store-C7FtS5AY.d.cts → store-BxiicOKG.d.cts} +32 -2
- package/dist/{store-DFk0ayh8.d.ts → store-DZka9T2-.d.ts} +32 -2
- package/dist/testing/index.cjs +38 -1
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +15 -4
- package/dist/testing/index.d.ts +15 -4
- package/dist/testing/index.js +40 -3
- package/dist/testing/index.js.map +1 -1
- package/package.json +41 -2
- package/dist/chunk-VSJDVLCP.js +0 -9
- package/dist/chunk-XPES5PZ3.js +0 -416
- package/dist/chunk-XPES5PZ3.js.map +0 -1
- package/dist/chunk-ZWG2TMUL.js.map +0 -1
- package/dist/contract-_NMdPjgN.d.cts +0 -6
- package/dist/contract-_NMdPjgN.d.ts +0 -6
package/dist/agent/index.cjs
CHANGED
|
@@ -1816,6 +1816,7 @@ var ConversationStore = class {
|
|
|
1816
1816
|
throw new RangeError(`A message is at most ${MAX_TEXT} characters.`);
|
|
1817
1817
|
const id = (this.options.createId ?? randomId)();
|
|
1818
1818
|
this.sent.set(id, { text: text2, order: lastOrder(this.engine.state()) + 0.5 });
|
|
1819
|
+
this.tellActivity({ type: "message_sent", id });
|
|
1819
1820
|
if (!this.session) {
|
|
1820
1821
|
this.early.set(id, text2);
|
|
1821
1822
|
void this.ensureSession("open");
|
|
@@ -2063,9 +2064,30 @@ var ConversationStore = class {
|
|
|
2063
2064
|
this.lastStatus = status;
|
|
2064
2065
|
this.update();
|
|
2065
2066
|
}
|
|
2067
|
+
/** The app's analytics hears of a step; what it throws is reported (`onError`), never in the way of a send or a frame. */
|
|
2068
|
+
tellActivity(activity) {
|
|
2069
|
+
try {
|
|
2070
|
+
this.options.onActivity?.(activity);
|
|
2071
|
+
} catch (error) {
|
|
2072
|
+
this.options.onError?.(error);
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
/** The live frames analytics hears of: a reply finished, cards drawn. */
|
|
2076
|
+
activity(frame) {
|
|
2077
|
+
if (!this.options.onActivity) return;
|
|
2078
|
+
const on = (a) => this.tellActivity(a);
|
|
2079
|
+
if (frame.type === "message.completed" && typeof frame.turn_id === "string")
|
|
2080
|
+
on({ type: "reply_completed", turnId: frame.turn_id });
|
|
2081
|
+
if (frame.type === "ui.cards" && Array.isArray(frame.cards)) {
|
|
2082
|
+
for (const card of frame.cards)
|
|
2083
|
+
if (typeof card.id === "string" && typeof card.kind === "string")
|
|
2084
|
+
on({ type: "card_shown", cardId: card.id, kind: card.kind });
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2066
2087
|
event(event) {
|
|
2067
2088
|
const frame = event;
|
|
2068
2089
|
const str2 = (v) => typeof v === "string" ? v : null;
|
|
2090
|
+
this.activity(frame);
|
|
2069
2091
|
const add = (key, kind, data) => {
|
|
2070
2092
|
if (this.system.some((s) => s.item.key === key)) return;
|
|
2071
2093
|
this.system = [
|
|
@@ -2448,7 +2470,106 @@ var AgentRefusal = class extends Error {
|
|
|
2448
2470
|
reason;
|
|
2449
2471
|
code;
|
|
2450
2472
|
};
|
|
2473
|
+
var GREETED = "vinaverse.greeted";
|
|
2474
|
+
var GREETED_BEFORE = "vinaverse.agent.greeted";
|
|
2475
|
+
function greetedKey(subject, mode) {
|
|
2476
|
+
return `${GREETED}.${JSON.stringify([subject, mode])}`;
|
|
2477
|
+
}
|
|
2478
|
+
function tupleOf(key, prefix) {
|
|
2479
|
+
if (!key.startsWith(`${prefix}.[`)) return null;
|
|
2480
|
+
try {
|
|
2481
|
+
const t = JSON.parse(key.slice(prefix.length + 1));
|
|
2482
|
+
return Array.isArray(t) ? t : null;
|
|
2483
|
+
} catch {
|
|
2484
|
+
return null;
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
function legacyTranscripts(keys, prefix) {
|
|
2488
|
+
const out = [];
|
|
2489
|
+
for (const key of keys) {
|
|
2490
|
+
const t = tupleOf(key, prefix);
|
|
2491
|
+
if (t)
|
|
2492
|
+
out.push(
|
|
2493
|
+
`${prefix}.${t[1] ?? "guest"}|${t[2]}|${t[3] ?? "-"}|${t[4] ?? "chat"}`
|
|
2494
|
+
);
|
|
2495
|
+
}
|
|
2496
|
+
return out;
|
|
2497
|
+
}
|
|
2498
|
+
function legacyGreetings(pairs) {
|
|
2499
|
+
const out = [];
|
|
2500
|
+
for (const [subject, mode] of pairs)
|
|
2501
|
+
out.push(`${GREETED_BEFORE}.${subject ?? "guest"}:${mode}`);
|
|
2502
|
+
return out;
|
|
2503
|
+
}
|
|
2451
2504
|
var NOT_KEPT = /* @__PURE__ */ new Set(["starting", "unavailable", "unauthorized", "closed"]);
|
|
2505
|
+
var CLEARED = { screen: "other" };
|
|
2506
|
+
function hashKey(key, salt) {
|
|
2507
|
+
return `k${sha256(`${salt}\0${key}`).slice(0, 32)}`;
|
|
2508
|
+
}
|
|
2509
|
+
var K;
|
|
2510
|
+
var H;
|
|
2511
|
+
function sha256(text2) {
|
|
2512
|
+
if (!K || !H) {
|
|
2513
|
+
K = [];
|
|
2514
|
+
H = [];
|
|
2515
|
+
for (let n = 2; K.length < 64; n++) {
|
|
2516
|
+
let prime = true;
|
|
2517
|
+
for (let d = 2; d * d <= n; d++) if (n % d === 0) prime = false;
|
|
2518
|
+
if (!prime) continue;
|
|
2519
|
+
if (H.length < 8) H.push(Math.sqrt(n) % 1 * 2 ** 32 | 0);
|
|
2520
|
+
K.push(Math.cbrt(n) % 1 * 2 ** 32 | 0);
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
const bytes = [];
|
|
2524
|
+
const s = encodeURIComponent(text2);
|
|
2525
|
+
for (let i = 0; i < s.length; i++)
|
|
2526
|
+
if (s[i] === "%") {
|
|
2527
|
+
bytes.push(Number.parseInt(s.slice(i + 1, i + 3), 16));
|
|
2528
|
+
i += 2;
|
|
2529
|
+
} else bytes.push(s.charCodeAt(i));
|
|
2530
|
+
const bits = bytes.length * 8;
|
|
2531
|
+
bytes.push(128);
|
|
2532
|
+
while (bytes.length % 64 !== 56) bytes.push(0);
|
|
2533
|
+
for (const word of [Math.floor(bits / 2 ** 32), bits >>> 0])
|
|
2534
|
+
bytes.push(
|
|
2535
|
+
word >>> 24,
|
|
2536
|
+
word >>> 16 & 255,
|
|
2537
|
+
word >>> 8 & 255,
|
|
2538
|
+
word & 255
|
|
2539
|
+
);
|
|
2540
|
+
const h = [...H];
|
|
2541
|
+
const w = new Array(64);
|
|
2542
|
+
const ror = (x, n) => x >>> n | x << 32 - n;
|
|
2543
|
+
for (let at = 0; at < bytes.length; at += 64) {
|
|
2544
|
+
for (let i = 0; i < 64; i++) {
|
|
2545
|
+
if (i < 16) {
|
|
2546
|
+
const b2 = at + i * 4;
|
|
2547
|
+
w[i] = bytes[b2] << 24 | bytes[b2 + 1] << 16 | bytes[b2 + 2] << 8 | bytes[b2 + 3];
|
|
2548
|
+
} else {
|
|
2549
|
+
const x = w[i - 15];
|
|
2550
|
+
const y = w[i - 2];
|
|
2551
|
+
w[i] = w[i - 16] + (ror(x, 7) ^ ror(x, 18) ^ x >>> 3) + w[i - 7] + (ror(y, 17) ^ ror(y, 19) ^ y >>> 10) | 0;
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
let [a, b, c, d, e, f, g, k] = h;
|
|
2555
|
+
for (let i = 0; i < 64; i++) {
|
|
2556
|
+
const t1 = k + (ror(e, 6) ^ ror(e, 11) ^ ror(e, 25)) + (e & f ^ ~e & g) + K[i] + w[i] | 0;
|
|
2557
|
+
const t2 = (ror(a, 2) ^ ror(a, 13) ^ ror(a, 22)) + (a & b ^ a & c ^ b & c) | 0;
|
|
2558
|
+
k = g;
|
|
2559
|
+
g = f;
|
|
2560
|
+
f = e;
|
|
2561
|
+
e = d + t1 | 0;
|
|
2562
|
+
d = c;
|
|
2563
|
+
c = b;
|
|
2564
|
+
b = a;
|
|
2565
|
+
a = t1 + t2 | 0;
|
|
2566
|
+
}
|
|
2567
|
+
[a, b, c, d, e, f, g, k].forEach((v, i) => {
|
|
2568
|
+
h[i] = h[i] + v | 0;
|
|
2569
|
+
});
|
|
2570
|
+
}
|
|
2571
|
+
return h.map((v) => (v >>> 0).toString(16).padStart(8, "0")).join("");
|
|
2572
|
+
}
|
|
2452
2573
|
var NO_FEATURES = {
|
|
2453
2574
|
history: false,
|
|
2454
2575
|
memory: false,
|
|
@@ -2456,8 +2577,14 @@ var NO_FEATURES = {
|
|
|
2456
2577
|
businessSetup: false
|
|
2457
2578
|
};
|
|
2458
2579
|
var SYSTEM_CLOCK = { now: () => Date.now() };
|
|
2459
|
-
function agentKey(key) {
|
|
2460
|
-
return
|
|
2580
|
+
function agentKey(key, agent = null) {
|
|
2581
|
+
return JSON.stringify([
|
|
2582
|
+
agent,
|
|
2583
|
+
key.subject,
|
|
2584
|
+
key.mode,
|
|
2585
|
+
key.scope ?? null,
|
|
2586
|
+
key.thread ?? "chat"
|
|
2587
|
+
]);
|
|
2461
2588
|
}
|
|
2462
2589
|
var samePlace = (a, b) => a?.screen === b?.screen && (a?.entity?.type ?? null) === (b?.entity?.type ?? null) && (a?.entity?.id ?? null) === (b?.entity?.id ?? null) && JSON.stringify(a?.filters ?? null) === JSON.stringify(b?.filters ?? null);
|
|
2463
2590
|
function usable(session, insecure) {
|
|
@@ -2467,9 +2594,12 @@ function warnInsecure(insecure, warn) {
|
|
|
2467
2594
|
if (!(insecure.realtime || insecure.turns)) return;
|
|
2468
2595
|
if (globalThis.__DEV__ === true) return;
|
|
2469
2596
|
warn(
|
|
2470
|
-
"@vinaverse/client/agent: insecureAddresses lets sessions use plaintext ws:// or http:// addresses.
|
|
2597
|
+
"@vinaverse/client/agent: insecureAddresses lets sessions use plaintext ws:// or http:// addresses. For mocks and local development only.",
|
|
2598
|
+
{ code: "insecure_addresses" }
|
|
2471
2599
|
);
|
|
2472
2600
|
}
|
|
2601
|
+
var OPEN_KEPT_MS = 24 * 36e5;
|
|
2602
|
+
var MAX_WAITING = 100;
|
|
2473
2603
|
function createAgentRuntime(options) {
|
|
2474
2604
|
const { backend } = options;
|
|
2475
2605
|
const policy = {
|
|
@@ -2487,7 +2617,76 @@ function createAgentRuntime(options) {
|
|
|
2487
2617
|
let status = null;
|
|
2488
2618
|
let reading = null;
|
|
2489
2619
|
let sessionName = null;
|
|
2490
|
-
|
|
2620
|
+
let generation = 0;
|
|
2621
|
+
const keyOf = (key) => agentKey(key, options.agent ?? null);
|
|
2622
|
+
const prefix = options.conversation?.persistenceKey ?? "vinaverse.agent";
|
|
2623
|
+
const storage = guardedStorage(
|
|
2624
|
+
options.conversation?.persistence,
|
|
2625
|
+
prefix,
|
|
2626
|
+
() => generation
|
|
2627
|
+
);
|
|
2628
|
+
const greetings = guardedStorage(
|
|
2629
|
+
options.greetingStorage,
|
|
2630
|
+
GREETED,
|
|
2631
|
+
() => generation
|
|
2632
|
+
);
|
|
2633
|
+
const warn = options.onWarning ?? ((m) => console.warn(m));
|
|
2634
|
+
const isolated = (what, call) => {
|
|
2635
|
+
try {
|
|
2636
|
+
call();
|
|
2637
|
+
} catch (error) {
|
|
2638
|
+
warn(
|
|
2639
|
+
`@vinaverse/client/agent: the app's ${what} threw (${error instanceof Error ? error.message : String(error)}); the conversation went on.`,
|
|
2640
|
+
{ code: "callback_threw", callback: what }
|
|
2641
|
+
);
|
|
2642
|
+
}
|
|
2643
|
+
};
|
|
2644
|
+
const saltStore = options.conversation?.persistence ?? options.greetingStorage;
|
|
2645
|
+
const saltKey = `${prefix}:salt`;
|
|
2646
|
+
let salt = null;
|
|
2647
|
+
const waiting = [];
|
|
2648
|
+
const loadSalt = () => {
|
|
2649
|
+
if (!options.onEvent) return;
|
|
2650
|
+
const settle = (kept2) => {
|
|
2651
|
+
if (salt !== null) return;
|
|
2652
|
+
if (kept2) salt = kept2;
|
|
2653
|
+
else {
|
|
2654
|
+
salt = randomId().slice(3);
|
|
2655
|
+
void Promise.resolve(saltStore?.setItem(saltKey, salt)).catch(
|
|
2656
|
+
() => void 0
|
|
2657
|
+
);
|
|
2658
|
+
}
|
|
2659
|
+
for (const event of waiting.splice(0)) deliver(event);
|
|
2660
|
+
};
|
|
2661
|
+
try {
|
|
2662
|
+
const got = saltStore?.getItem(saltKey);
|
|
2663
|
+
if (typeof got === "string" || got == null) settle(got);
|
|
2664
|
+
else got.then(settle, () => settle(null));
|
|
2665
|
+
} catch {
|
|
2666
|
+
settle(null);
|
|
2667
|
+
}
|
|
2668
|
+
};
|
|
2669
|
+
const deliver = (event) => isolated(
|
|
2670
|
+
"onEvent",
|
|
2671
|
+
() => options.onEvent?.(
|
|
2672
|
+
event.key ? { ...event, key: hashKey(event.key, salt ?? "") } : event
|
|
2673
|
+
)
|
|
2674
|
+
);
|
|
2675
|
+
let dropping = false;
|
|
2676
|
+
const emit = (event) => {
|
|
2677
|
+
if (!options.onEvent) return;
|
|
2678
|
+
if (salt !== null) return deliver(event);
|
|
2679
|
+
if (waiting.push(event) > MAX_WAITING) {
|
|
2680
|
+
waiting.shift();
|
|
2681
|
+
if (!dropping)
|
|
2682
|
+
warn(
|
|
2683
|
+
"@vinaverse/client/agent: the analytics salt is still being read from storage; the oldest events are dropped.",
|
|
2684
|
+
{ code: "events_dropped" }
|
|
2685
|
+
);
|
|
2686
|
+
dropping = true;
|
|
2687
|
+
}
|
|
2688
|
+
};
|
|
2689
|
+
loadSalt();
|
|
2491
2690
|
const changed = () => {
|
|
2492
2691
|
for (const l of [...listeners]) l();
|
|
2493
2692
|
};
|
|
@@ -2499,6 +2698,7 @@ function createAgentRuntime(options) {
|
|
|
2499
2698
|
const entry = live.get(k);
|
|
2500
2699
|
if (!entry) return;
|
|
2501
2700
|
live.delete(k);
|
|
2701
|
+
clearTimeout(entry.timer);
|
|
2502
2702
|
entry.store.dispose();
|
|
2503
2703
|
emit({ type: "conversation_ended", key: k });
|
|
2504
2704
|
changed();
|
|
@@ -2511,32 +2711,45 @@ function createAgentRuntime(options) {
|
|
|
2511
2711
|
);
|
|
2512
2712
|
async function open(entry, key, request) {
|
|
2513
2713
|
if (live.get(entry.key) !== entry) throw new AgentRefusal("unavailable");
|
|
2514
|
-
const
|
|
2515
|
-
|
|
2714
|
+
const held = entry.failedOpen && clock.now() - entry.failedOpen.at < OPEN_KEPT_MS ? entry.failedOpen : void 0;
|
|
2715
|
+
entry.failedOpen = void 0;
|
|
2716
|
+
const asked = held ? {
|
|
2717
|
+
...held.request,
|
|
2718
|
+
...request.signal ? { signal: request.signal } : {}
|
|
2719
|
+
} : {
|
|
2720
|
+
...request,
|
|
2721
|
+
conversationId: request.conversationId ?? current.get(entry.key) ?? null,
|
|
2722
|
+
key,
|
|
2723
|
+
openId: `op_${randomId().slice(3)}`,
|
|
2724
|
+
agent: options.agent ?? null,
|
|
2725
|
+
place: entry.place,
|
|
2726
|
+
placeRevision: ++entry.revision,
|
|
2727
|
+
entryPoint: entry.entryPoint
|
|
2728
|
+
};
|
|
2729
|
+
const { conversationId, openId, place: told } = asked;
|
|
2516
2730
|
let session;
|
|
2517
2731
|
try {
|
|
2518
2732
|
session = await patiently(
|
|
2519
|
-
() => backend.openSession(
|
|
2520
|
-
...request,
|
|
2521
|
-
conversationId,
|
|
2522
|
-
key,
|
|
2523
|
-
place: told,
|
|
2524
|
-
entryPoint: entry.entryPoint
|
|
2525
|
-
}),
|
|
2733
|
+
() => backend.openSession(asked),
|
|
2526
2734
|
request.signal,
|
|
2527
2735
|
entry.key
|
|
2528
2736
|
);
|
|
2529
2737
|
if (!usable(session, insecure))
|
|
2530
2738
|
throw new AgentRefusal("unavailable", {
|
|
2531
2739
|
reason: "invalid_session",
|
|
2532
|
-
message: "
|
|
2740
|
+
message: "Unusable session: an id, a secret, wss:// and https:// addresses."
|
|
2533
2741
|
});
|
|
2534
2742
|
} catch (error) {
|
|
2535
2743
|
if (live.get(entry.key) === entry) {
|
|
2536
|
-
const failure = error
|
|
2744
|
+
const failure = isRefusal(error) ? error.kind === "ended" && conversationId !== null ? "ended" : "unavailable" : policy.isRetryable(error) ? "unreachable" : "unavailable";
|
|
2537
2745
|
const reason = reasonOf(error, failure);
|
|
2538
|
-
const code = error
|
|
2539
|
-
|
|
2746
|
+
const code = isRefusal(error) ? error.code : codeOf(error);
|
|
2747
|
+
if (failure === "unreachable") {
|
|
2748
|
+
const { signal, ...again } = asked;
|
|
2749
|
+
entry.failedOpen = { request: again, at: held?.at ?? clock.now() };
|
|
2750
|
+
}
|
|
2751
|
+
const unsettled = reason === "unknown_open" ? String(field(error, "openId") ?? openId) : null;
|
|
2752
|
+
update(entry, { failure, reason, code, openId: unsettled });
|
|
2540
2753
|
emit({ type: "session_failed", key: entry.key, failure, reason });
|
|
2541
2754
|
}
|
|
2542
2755
|
throw error;
|
|
@@ -2555,7 +2768,9 @@ function createAgentRuntime(options) {
|
|
|
2555
2768
|
failure: null,
|
|
2556
2769
|
reason: null,
|
|
2557
2770
|
code: null,
|
|
2771
|
+
openId: null,
|
|
2558
2772
|
sessionId: session.id,
|
|
2773
|
+
conversationId: session.conversation_id ?? conversationId,
|
|
2559
2774
|
moved: !samePlace(told, entry.place)
|
|
2560
2775
|
});
|
|
2561
2776
|
emit({
|
|
@@ -2566,25 +2781,106 @@ function createAgentRuntime(options) {
|
|
|
2566
2781
|
});
|
|
2567
2782
|
return session;
|
|
2568
2783
|
}
|
|
2569
|
-
const kept = (k) => `${
|
|
2784
|
+
const kept = (k) => `${prefix}.${k}`;
|
|
2785
|
+
const signOut = async (erasing) => {
|
|
2786
|
+
generation++;
|
|
2787
|
+
if (erasing) salt = null;
|
|
2788
|
+
for (const entry of live.values()) {
|
|
2789
|
+
clearTimeout(entry.timer);
|
|
2790
|
+
entry.store.clear();
|
|
2791
|
+
}
|
|
2792
|
+
const known = /* @__PURE__ */ new Set([...live.keys(), ...current.keys()]);
|
|
2793
|
+
live.clear();
|
|
2794
|
+
current.clear();
|
|
2795
|
+
sessionName = null;
|
|
2796
|
+
status = null;
|
|
2797
|
+
reading = null;
|
|
2798
|
+
changed();
|
|
2799
|
+
const pairs = [];
|
|
2800
|
+
await Promise.all([
|
|
2801
|
+
backend.endSessions?.().catch(() => void 0),
|
|
2802
|
+
storage?.purge(
|
|
2803
|
+
[`${prefix}.`],
|
|
2804
|
+
(keys) => {
|
|
2805
|
+
const all = /* @__PURE__ */ new Set([...keys, ...[...known].map(kept)]);
|
|
2806
|
+
for (const key of all) {
|
|
2807
|
+
const t = tupleOf(key, prefix);
|
|
2808
|
+
if (t) pairs.push([t[1], t[2]]);
|
|
2809
|
+
}
|
|
2810
|
+
return [
|
|
2811
|
+
...all,
|
|
2812
|
+
...legacyTranscripts(all, prefix),
|
|
2813
|
+
...options.legacyKeys ?? []
|
|
2814
|
+
];
|
|
2815
|
+
},
|
|
2816
|
+
`${GREETED}.`
|
|
2817
|
+
)
|
|
2818
|
+
]);
|
|
2819
|
+
if (!erasing) return;
|
|
2820
|
+
await Promise.all([
|
|
2821
|
+
Promise.resolve(saltStore?.removeItem(saltKey)).catch(() => void 0),
|
|
2822
|
+
greetings?.purge([`${GREETED}.`, `${GREETED_BEFORE}.`], (keys) => {
|
|
2823
|
+
for (const key of keys) {
|
|
2824
|
+
const t = tupleOf(key, GREETED);
|
|
2825
|
+
if (t) pairs.push([t[0], t[1]]);
|
|
2826
|
+
}
|
|
2827
|
+
return [...legacyGreetings(pairs), ...options.legacyKeys ?? []];
|
|
2828
|
+
})
|
|
2829
|
+
]);
|
|
2830
|
+
loadSalt();
|
|
2831
|
+
};
|
|
2832
|
+
const forget = (k) => {
|
|
2833
|
+
current.delete(k);
|
|
2834
|
+
const entry = live.get(k);
|
|
2835
|
+
if (entry) {
|
|
2836
|
+
entry.store.clear();
|
|
2837
|
+
end(k);
|
|
2838
|
+
} else void storage?.removeItem(kept(k));
|
|
2839
|
+
};
|
|
2840
|
+
const activity = (entry, a) => {
|
|
2841
|
+
const sessionId = entry.state.sessionId;
|
|
2842
|
+
if (a.type === "reply_completed" && sessionId) {
|
|
2843
|
+
entry.turns.set(a.turnId, sessionId);
|
|
2844
|
+
update(entry, {});
|
|
2845
|
+
}
|
|
2846
|
+
emit({
|
|
2847
|
+
type: a.type,
|
|
2848
|
+
key: entry.key,
|
|
2849
|
+
...sessionId ? { sessionId } : {},
|
|
2850
|
+
...a.type === "reply_completed" ? { turnId: a.turnId } : {},
|
|
2851
|
+
...a.type === "card_shown" ? { cardId: a.cardId, kind: a.kind } : {}
|
|
2852
|
+
});
|
|
2853
|
+
};
|
|
2570
2854
|
function make(key) {
|
|
2571
|
-
const k =
|
|
2855
|
+
const k = keyOf(key);
|
|
2572
2856
|
const own = options.conversation ?? {};
|
|
2573
2857
|
const refresh = backend.refreshSecret?.bind(backend);
|
|
2574
2858
|
const entry = {
|
|
2575
2859
|
key: k,
|
|
2576
2860
|
store: createConversation({
|
|
2577
2861
|
...own,
|
|
2578
|
-
...
|
|
2862
|
+
...storage ? {
|
|
2863
|
+
persistence: storage,
|
|
2579
2864
|
persistenceKey: kept(k)
|
|
2580
2865
|
} : {},
|
|
2866
|
+
onActivity: (a) => {
|
|
2867
|
+
activity(entry, a);
|
|
2868
|
+
isolated("onActivity", () => own.onActivity?.(a));
|
|
2869
|
+
},
|
|
2581
2870
|
getSession: (request) => open(entry, key, request),
|
|
2582
2871
|
...refresh ? {
|
|
2583
|
-
|
|
2872
|
+
// A refusal (`session_closed`) is the store's cue to go on in a new session, never a fault.
|
|
2873
|
+
refreshSecret: (id) => patiently(() => refresh(id), void 0, k).catch((error) => {
|
|
2874
|
+
throw isRefusal(error) ? new VinaverseClientError(
|
|
2875
|
+
"needs_new_session",
|
|
2876
|
+
error.message
|
|
2877
|
+
) : error;
|
|
2878
|
+
})
|
|
2584
2879
|
} : {},
|
|
2585
2880
|
clock,
|
|
2586
2881
|
onError: (error) => {
|
|
2587
|
-
if (!(error
|
|
2882
|
+
if (!isRefusal(error) && codeOf(error) !== "needs_new_session")
|
|
2883
|
+
own.onError?.(error);
|
|
2588
2884
|
}
|
|
2589
2885
|
}),
|
|
2590
2886
|
listeners: /* @__PURE__ */ new Set(),
|
|
@@ -2594,7 +2890,9 @@ function createAgentRuntime(options) {
|
|
|
2594
2890
|
code: null,
|
|
2595
2891
|
moved: false,
|
|
2596
2892
|
ratings: /* @__PURE__ */ new Map(),
|
|
2597
|
-
sessionId: null
|
|
2893
|
+
sessionId: null,
|
|
2894
|
+
conversationId: current.get(k) ?? null,
|
|
2895
|
+
openId: null
|
|
2598
2896
|
},
|
|
2599
2897
|
place: null,
|
|
2600
2898
|
told: null,
|
|
@@ -2604,32 +2902,59 @@ function createAgentRuntime(options) {
|
|
|
2604
2902
|
shown: 0,
|
|
2605
2903
|
started: false,
|
|
2606
2904
|
suspended: false,
|
|
2607
|
-
sentOnce: /* @__PURE__ */ new Set()
|
|
2905
|
+
sentOnce: /* @__PURE__ */ new Set(),
|
|
2906
|
+
timer: void 0,
|
|
2907
|
+
turns: /* @__PURE__ */ new Map(),
|
|
2908
|
+
failedOpen: void 0
|
|
2608
2909
|
};
|
|
2609
2910
|
return entry;
|
|
2610
2911
|
}
|
|
2611
2912
|
const over = (entry) => entry.expiresAt !== null && entry.expiresAt <= clock.now();
|
|
2913
|
+
const expireLater = (entry) => {
|
|
2914
|
+
clearTimeout(entry.timer);
|
|
2915
|
+
if (entry.expiresAt === null) return;
|
|
2916
|
+
entry.timer = setTimeout(
|
|
2917
|
+
() => {
|
|
2918
|
+
entry.timer = void 0;
|
|
2919
|
+
if (live.get(entry.key) !== entry || entry.shown > 0) return;
|
|
2920
|
+
if (over(entry)) end(entry.key);
|
|
2921
|
+
else expireLater(entry);
|
|
2922
|
+
},
|
|
2923
|
+
Math.max(0, entry.expiresAt - clock.now())
|
|
2924
|
+
);
|
|
2925
|
+
};
|
|
2612
2926
|
const tell = (entry, at) => {
|
|
2613
|
-
entry.place = at.place
|
|
2614
|
-
entry.entryPoint = at.entryPoint
|
|
2927
|
+
if (at.place !== void 0) entry.place = at.place;
|
|
2928
|
+
if (at.entryPoint !== void 0) entry.entryPoint = at.entryPoint;
|
|
2615
2929
|
const sessionId = entry.state.sessionId;
|
|
2616
2930
|
const moved = sessionId !== null && !samePlace(entry.told, entry.place);
|
|
2617
2931
|
update(entry, { moved });
|
|
2618
|
-
const
|
|
2619
|
-
if (!moved || !
|
|
2620
|
-
|
|
2621
|
-
const
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2932
|
+
const updateContext = backend.updateContext?.bind(backend);
|
|
2933
|
+
if (!moved || !updateContext || sessionId === null) return;
|
|
2934
|
+
const asked = generation;
|
|
2935
|
+
const current2 = () => asked === generation && live.get(entry.key) === entry && entry.state.sessionId === sessionId;
|
|
2936
|
+
const send = (again) => {
|
|
2937
|
+
const place = entry.place;
|
|
2938
|
+
const revision = ++entry.revision;
|
|
2939
|
+
updateContext(sessionId, place ?? CLEARED, revision).then(
|
|
2940
|
+
() => {
|
|
2941
|
+
if (!current2() || entry.revision !== revision) return;
|
|
2942
|
+
entry.told = place;
|
|
2943
|
+
update(entry, { moved: !samePlace(entry.told, entry.place) });
|
|
2944
|
+
emit({ type: "context_updated", key: entry.key, sessionId });
|
|
2945
|
+
},
|
|
2946
|
+
(error) => {
|
|
2947
|
+
const theirs = field(error, "currentRevision");
|
|
2948
|
+
const conflict = field(error, "outcome") === "context_conflict" || field(error, "reason") === "conflict";
|
|
2949
|
+
if (!conflict || again || !current2() || entry.revision !== revision)
|
|
2950
|
+
return;
|
|
2951
|
+
if (typeof theirs === "number" && theirs >= entry.revision)
|
|
2952
|
+
entry.revision = theirs;
|
|
2953
|
+
send(true);
|
|
2954
|
+
}
|
|
2955
|
+
);
|
|
2956
|
+
};
|
|
2957
|
+
send(false);
|
|
2633
2958
|
};
|
|
2634
2959
|
function handle(entry) {
|
|
2635
2960
|
return {
|
|
@@ -2642,6 +2967,8 @@ function createAgentRuntime(options) {
|
|
|
2642
2967
|
return () => void 0;
|
|
2643
2968
|
}
|
|
2644
2969
|
entry.shown++;
|
|
2970
|
+
clearTimeout(entry.timer);
|
|
2971
|
+
entry.timer = void 0;
|
|
2645
2972
|
if (entry.suspended) {
|
|
2646
2973
|
entry.suspended = false;
|
|
2647
2974
|
entry.store.setForeground(true);
|
|
@@ -2663,6 +2990,7 @@ function createAgentRuntime(options) {
|
|
|
2663
2990
|
}
|
|
2664
2991
|
entry.suspended = true;
|
|
2665
2992
|
entry.store.setForeground(false);
|
|
2993
|
+
expireLater(entry);
|
|
2666
2994
|
};
|
|
2667
2995
|
},
|
|
2668
2996
|
tell: (at) => tell(entry, at),
|
|
@@ -2672,13 +3000,18 @@ function createAgentRuntime(options) {
|
|
|
2672
3000
|
return () => entry.listeners.delete(listener);
|
|
2673
3001
|
},
|
|
2674
3002
|
retry() {
|
|
2675
|
-
update(entry, {
|
|
3003
|
+
update(entry, {
|
|
3004
|
+
failure: null,
|
|
3005
|
+
reason: null,
|
|
3006
|
+
code: null,
|
|
3007
|
+
openId: null
|
|
3008
|
+
});
|
|
2676
3009
|
entry.store.start();
|
|
2677
3010
|
},
|
|
3011
|
+
canRate: (turnId) => entry.turns.has(turnId),
|
|
2678
3012
|
rate(turnId, rating) {
|
|
2679
|
-
const sessionId = entry.
|
|
2680
|
-
if (sessionId
|
|
2681
|
-
return;
|
|
3013
|
+
const sessionId = entry.turns.get(turnId);
|
|
3014
|
+
if (!sessionId || entry.state.ratings.get(turnId) === rating) return;
|
|
2682
3015
|
update(entry, {
|
|
2683
3016
|
ratings: new Map(entry.state.ratings).set(turnId, rating)
|
|
2684
3017
|
});
|
|
@@ -2694,7 +3027,7 @@ function createAgentRuntime(options) {
|
|
|
2694
3027
|
}
|
|
2695
3028
|
const handles = /* @__PURE__ */ new WeakMap();
|
|
2696
3029
|
const lookup = (key) => {
|
|
2697
|
-
const k =
|
|
3030
|
+
const k = keyOf(key);
|
|
2698
3031
|
let entry = live.get(k);
|
|
2699
3032
|
if (!entry) {
|
|
2700
3033
|
entry = make(key);
|
|
@@ -2709,63 +3042,72 @@ function createAgentRuntime(options) {
|
|
|
2709
3042
|
};
|
|
2710
3043
|
return {
|
|
2711
3044
|
conversation(key) {
|
|
2712
|
-
const k =
|
|
3045
|
+
const k = keyOf(key);
|
|
2713
3046
|
const entry = live.get(k);
|
|
2714
3047
|
if (entry && entry.shown === 0 && over(entry)) end(k);
|
|
2715
3048
|
return lookup(key);
|
|
2716
3049
|
},
|
|
2717
3050
|
peek: lookup,
|
|
2718
3051
|
startNew(key) {
|
|
2719
|
-
const k =
|
|
3052
|
+
const k = keyOf(key);
|
|
2720
3053
|
current.delete(k);
|
|
2721
3054
|
end(k);
|
|
2722
3055
|
},
|
|
2723
3056
|
dispose(key) {
|
|
2724
|
-
end(
|
|
3057
|
+
end(keyOf(key));
|
|
3058
|
+
},
|
|
3059
|
+
forget(key) {
|
|
3060
|
+
forget(keyOf(key));
|
|
3061
|
+
},
|
|
3062
|
+
sweep() {
|
|
3063
|
+
for (const entry of [...live.values()])
|
|
3064
|
+
if (entry.shown === 0 && over(entry)) end(entry.key);
|
|
2725
3065
|
},
|
|
2726
3066
|
continue(key, conversationId) {
|
|
2727
|
-
const k =
|
|
3067
|
+
const k = keyOf(key);
|
|
2728
3068
|
if (current.get(k) !== conversationId) {
|
|
3069
|
+
forget(k);
|
|
2729
3070
|
current.set(k, conversationId);
|
|
2730
|
-
const entry = live.get(k);
|
|
2731
|
-
if (entry) {
|
|
2732
|
-
entry.store.clear();
|
|
2733
|
-
end(k);
|
|
2734
|
-
} else {
|
|
2735
|
-
try {
|
|
2736
|
-
void Promise.resolve(
|
|
2737
|
-
options.conversation?.persistence?.removeItem(kept(k))
|
|
2738
|
-
).catch(() => void 0);
|
|
2739
|
-
} catch {
|
|
2740
|
-
}
|
|
2741
|
-
}
|
|
2742
3071
|
}
|
|
2743
3072
|
return lookup(key);
|
|
2744
3073
|
},
|
|
2745
3074
|
async signOut() {
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
changed();
|
|
2751
|
-
await backend.endSessions?.().catch(() => void 0);
|
|
3075
|
+
await signOut(false);
|
|
3076
|
+
},
|
|
3077
|
+
async erase() {
|
|
3078
|
+
await signOut(true);
|
|
2752
3079
|
},
|
|
3080
|
+
async deleteConversation(key, conversationId) {
|
|
3081
|
+
if (!backend.deleteConversation)
|
|
3082
|
+
throw new Error(
|
|
3083
|
+
"@vinaverse/client/agent: deleteConversation needs AgentBackend.deleteConversation."
|
|
3084
|
+
);
|
|
3085
|
+
await backend.deleteConversation(conversationId);
|
|
3086
|
+
const k = keyOf(key);
|
|
3087
|
+
const continued = current.get(k) ?? live.get(k)?.store.getSnapshot().conversationId ?? null;
|
|
3088
|
+
if (continued === conversationId) forget(k);
|
|
3089
|
+
},
|
|
3090
|
+
greetings: greetings ?? null,
|
|
2753
3091
|
status() {
|
|
2754
3092
|
if (status && clock.now() - status.at < staleMs)
|
|
2755
3093
|
return Promise.resolve(status.value);
|
|
2756
|
-
reading
|
|
3094
|
+
if (reading) return reading;
|
|
3095
|
+
const asked = generation;
|
|
3096
|
+
const read = readStatus(backend).then(
|
|
2757
3097
|
(value) => {
|
|
3098
|
+
if (asked !== generation) return value;
|
|
2758
3099
|
reading = null;
|
|
2759
3100
|
status = { value, at: clock.now() };
|
|
2760
3101
|
changed();
|
|
2761
3102
|
return value;
|
|
2762
3103
|
},
|
|
2763
3104
|
(error) => {
|
|
2764
|
-
reading = null;
|
|
3105
|
+
if (asked === generation) reading = null;
|
|
2765
3106
|
throw error;
|
|
2766
3107
|
}
|
|
2767
3108
|
);
|
|
2768
|
-
|
|
3109
|
+
reading = read;
|
|
3110
|
+
return read;
|
|
2769
3111
|
},
|
|
2770
3112
|
getStatus: () => status?.value ?? null,
|
|
2771
3113
|
getName: () => sessionName ?? status?.value.displayName ?? null,
|
|
@@ -2776,6 +3118,100 @@ function createAgentRuntime(options) {
|
|
|
2776
3118
|
emit
|
|
2777
3119
|
};
|
|
2778
3120
|
}
|
|
3121
|
+
function guardedStorage(raw, prefix, generation) {
|
|
3122
|
+
if (!raw) return void 0;
|
|
3123
|
+
const indexKey = `${prefix}:index`;
|
|
3124
|
+
const chains = /* @__PURE__ */ new Map();
|
|
3125
|
+
const pending = /* @__PURE__ */ new Map();
|
|
3126
|
+
const queued = (key, op) => {
|
|
3127
|
+
pending.set(key, (pending.get(key) ?? 0) + 1);
|
|
3128
|
+
const run = (chains.get(key) ?? Promise.resolve()).then(op);
|
|
3129
|
+
const settled = run.then(
|
|
3130
|
+
() => void 0,
|
|
3131
|
+
() => void 0
|
|
3132
|
+
);
|
|
3133
|
+
chains.set(key, settled);
|
|
3134
|
+
void settled.then(() => {
|
|
3135
|
+
const left = (pending.get(key) ?? 1) - 1;
|
|
3136
|
+
if (left > 0) pending.set(key, left);
|
|
3137
|
+
else {
|
|
3138
|
+
pending.delete(key);
|
|
3139
|
+
if (chains.get(key) === settled) chains.delete(key);
|
|
3140
|
+
}
|
|
3141
|
+
});
|
|
3142
|
+
return run;
|
|
3143
|
+
};
|
|
3144
|
+
const safe = (p) => p.catch(() => void 0);
|
|
3145
|
+
const readIndex = async () => {
|
|
3146
|
+
try {
|
|
3147
|
+
const value = await raw.getItem(indexKey);
|
|
3148
|
+
const list3 = value ? JSON.parse(value) : [];
|
|
3149
|
+
return new Set(
|
|
3150
|
+
Array.isArray(list3) ? list3.filter((k) => typeof k === "string") : []
|
|
3151
|
+
);
|
|
3152
|
+
} catch {
|
|
3153
|
+
return /* @__PURE__ */ new Set();
|
|
3154
|
+
}
|
|
3155
|
+
};
|
|
3156
|
+
const listed = /* @__PURE__ */ new Set();
|
|
3157
|
+
const list2 = (key) => {
|
|
3158
|
+
if (listed.has(key)) return;
|
|
3159
|
+
listed.add(key);
|
|
3160
|
+
void safe(
|
|
3161
|
+
queued(indexKey, async () => {
|
|
3162
|
+
const all = await readIndex();
|
|
3163
|
+
if (all.has(key)) return;
|
|
3164
|
+
all.add(key);
|
|
3165
|
+
await raw.setItem(indexKey, JSON.stringify([...all]));
|
|
3166
|
+
})
|
|
3167
|
+
);
|
|
3168
|
+
};
|
|
3169
|
+
return {
|
|
3170
|
+
getItem(key) {
|
|
3171
|
+
const asked = generation();
|
|
3172
|
+
const read = pending.has(key) ? queued(key, () => raw.getItem(key)) : raw.getItem(key);
|
|
3173
|
+
if (typeof read === "string" || read === null) return read;
|
|
3174
|
+
return Promise.resolve(read).then(
|
|
3175
|
+
(v) => asked === generation() ? v ?? null : null,
|
|
3176
|
+
() => null
|
|
3177
|
+
);
|
|
3178
|
+
},
|
|
3179
|
+
setItem(key, value) {
|
|
3180
|
+
const asked = generation();
|
|
3181
|
+
return safe(
|
|
3182
|
+
queued(key, () => {
|
|
3183
|
+
if (asked !== generation()) return;
|
|
3184
|
+
list2(key);
|
|
3185
|
+
return raw.setItem(key, value);
|
|
3186
|
+
})
|
|
3187
|
+
);
|
|
3188
|
+
},
|
|
3189
|
+
removeItem: (key) => safe(queued(key, () => raw.removeItem(key))),
|
|
3190
|
+
/**
|
|
3191
|
+
* Everything kept: the index, what the app's storage finds under `under` (`removePrefix`, else `keys`), and `extra`
|
|
3192
|
+
* (older key shapes). Nothing under `keep` goes, so `removePrefix` is used only for a prefix that cannot reach it.
|
|
3193
|
+
*/
|
|
3194
|
+
async purge(under, extra = () => [], keep) {
|
|
3195
|
+
const all = /* @__PURE__ */ new Set([...listed, ...await readIndex()]);
|
|
3196
|
+
listed.clear();
|
|
3197
|
+
for (const p of under)
|
|
3198
|
+
try {
|
|
3199
|
+
if (raw.removePrefix && !keep?.startsWith(p))
|
|
3200
|
+
await raw.removePrefix(p);
|
|
3201
|
+
else if (raw.keys) {
|
|
3202
|
+
for (const key of await raw.keys(p))
|
|
3203
|
+
if (!keep || !key.startsWith(keep)) all.add(key);
|
|
3204
|
+
}
|
|
3205
|
+
} catch {
|
|
3206
|
+
}
|
|
3207
|
+
for (const key of extra(all)) all.add(key);
|
|
3208
|
+
await Promise.all(
|
|
3209
|
+
[...all].map((key) => safe(queued(key, () => raw.removeItem(key))))
|
|
3210
|
+
);
|
|
3211
|
+
await safe(queued(indexKey, () => raw.removeItem(indexKey)));
|
|
3212
|
+
}
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
2779
3215
|
async function readStatus(backend) {
|
|
2780
3216
|
const read = backend.status ? await backend.status() : { available: true };
|
|
2781
3217
|
const available = read.available === true;
|
|
@@ -2793,10 +3229,20 @@ async function readStatus(backend) {
|
|
|
2793
3229
|
}
|
|
2794
3230
|
};
|
|
2795
3231
|
}
|
|
3232
|
+
function isRefusal(error) {
|
|
3233
|
+
return error instanceof AgentRefusal || field(error, "name") === "AgentRefusal" && (field(error, "kind") === "ended" || field(error, "kind") === "unavailable");
|
|
3234
|
+
}
|
|
2796
3235
|
var field = (error, name) => typeof error === "object" && error !== null ? error[name] : void 0;
|
|
2797
3236
|
var retryable = (error) => field(error, "retryable") === true;
|
|
2798
3237
|
var REASONS = /* @__PURE__ */ new Set([
|
|
2799
3238
|
"ended",
|
|
3239
|
+
"not_found",
|
|
3240
|
+
"expired",
|
|
3241
|
+
"mismatch",
|
|
3242
|
+
"completed",
|
|
3243
|
+
"forbidden",
|
|
3244
|
+
"conflict",
|
|
3245
|
+
"unknown_open",
|
|
2800
3246
|
"auth",
|
|
2801
3247
|
"off",
|
|
2802
3248
|
"rate_limited",
|
|
@@ -2806,7 +3252,7 @@ var REASONS = /* @__PURE__ */ new Set([
|
|
|
2806
3252
|
"unknown"
|
|
2807
3253
|
]);
|
|
2808
3254
|
function reasonOf(error, failure) {
|
|
2809
|
-
if (error
|
|
3255
|
+
if (isRefusal(error)) return error.reason;
|
|
2810
3256
|
const given = field(error, "reason");
|
|
2811
3257
|
if (typeof given === "string" && REASONS.has(given))
|
|
2812
3258
|
return given;
|
|
@@ -2817,7 +3263,7 @@ function reasonOf(error, failure) {
|
|
|
2817
3263
|
return failure === "unreachable" ? "network" : "unknown";
|
|
2818
3264
|
}
|
|
2819
3265
|
function codeOf(error) {
|
|
2820
|
-
const code = field(error, "code");
|
|
3266
|
+
const code = field(error, "code") ?? field(error, "outcome");
|
|
2821
3267
|
return typeof code === "string" ? code : null;
|
|
2822
3268
|
}
|
|
2823
3269
|
async function retrying(run, policy, signal, onRetry) {
|
|
@@ -2825,9 +3271,11 @@ async function retrying(run, policy, signal, onRetry) {
|
|
|
2825
3271
|
try {
|
|
2826
3272
|
return await run();
|
|
2827
3273
|
} catch (error) {
|
|
2828
|
-
const
|
|
2829
|
-
if (
|
|
3274
|
+
const delay = policy.delays[attempt];
|
|
3275
|
+
if (delay === void 0 || !policy.isRetryable(error) || signal?.aborted)
|
|
2830
3276
|
throw error;
|
|
3277
|
+
const asked = field(error, "retryAfterMs");
|
|
3278
|
+
const wait = typeof asked === "number" && asked > delay ? Math.min(asked, 6e4) : delay;
|
|
2831
3279
|
await new Promise((resolve, reject) => {
|
|
2832
3280
|
const timer = setTimeout(() => {
|
|
2833
3281
|
signal?.removeEventListener("abort", stop);
|
|
@@ -2847,6 +3295,9 @@ async function retrying(run, policy, signal, onRetry) {
|
|
|
2847
3295
|
exports.AgentRefusal = AgentRefusal;
|
|
2848
3296
|
exports.agentKey = agentKey;
|
|
2849
3297
|
exports.createAgentRuntime = createAgentRuntime;
|
|
3298
|
+
exports.greetedKey = greetedKey;
|
|
3299
|
+
exports.hashKey = hashKey;
|
|
3300
|
+
exports.isRefusal = isRefusal;
|
|
2850
3301
|
exports.readCard = readCard;
|
|
2851
3302
|
//# sourceMappingURL=index.cjs.map
|
|
2852
3303
|
//# sourceMappingURL=index.cjs.map
|