@vinaverse/client 0.1.0-alpha.6 → 0.1.0-alpha.7
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 +66 -6
- package/dist/agent/index.cjs +523 -75
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +2 -2
- package/dist/agent/index.d.ts +2 -2
- 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-3BLRAWNC.js +840 -0
- package/dist/chunk-3BLRAWNC.js.map +1 -0
- package/dist/{chunk-ZWG2TMUL.js → chunk-46D3FSLU.js} +24 -2
- package/dist/chunk-46D3FSLU.js.map +1 -0
- package/dist/conversation/index.cjs +22 -0
- package/dist/conversation/index.cjs.map +1 -1
- package/dist/conversation/index.d.cts +2 -2
- package/dist/conversation/index.d.ts +2 -2
- package/dist/conversation/index.js +2 -2
- package/dist/{runtime-DLJbJkSr.d.ts → runtime-C3ZknHdG.d.cts} +137 -20
- package/dist/{runtime-CErMdYxJ.d.cts → runtime-CZ1hLvAl.d.ts} +137 -20
- package/dist/{store-C7FtS5AY.d.cts → store-7WU1kD9W.d.cts} +31 -1
- package/dist/{store-DFk0ayh8.d.ts → store-DrXSPHu6.d.ts} +31 -1
- package/dist/testing/index.cjs +38 -1
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +14 -3
- package/dist/testing/index.d.ts +14 -3
- package/dist/testing/index.js +40 -3
- package/dist/testing/index.js.map +1 -1
- package/package.json +21 -2
- 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/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,11 @@ 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."
|
|
2471
2598
|
);
|
|
2472
2599
|
}
|
|
2600
|
+
var OPEN_KEPT_MS = 24 * 36e5;
|
|
2601
|
+
var MAX_WAITING = 100;
|
|
2473
2602
|
function createAgentRuntime(options) {
|
|
2474
2603
|
const { backend } = options;
|
|
2475
2604
|
const policy = {
|
|
@@ -2487,7 +2616,74 @@ function createAgentRuntime(options) {
|
|
|
2487
2616
|
let status = null;
|
|
2488
2617
|
let reading = null;
|
|
2489
2618
|
let sessionName = null;
|
|
2490
|
-
|
|
2619
|
+
let generation = 0;
|
|
2620
|
+
const keyOf = (key) => agentKey(key, options.agent ?? null);
|
|
2621
|
+
const prefix = options.conversation?.persistenceKey ?? "vinaverse.agent";
|
|
2622
|
+
const storage = guardedStorage(
|
|
2623
|
+
options.conversation?.persistence,
|
|
2624
|
+
prefix,
|
|
2625
|
+
() => generation
|
|
2626
|
+
);
|
|
2627
|
+
const greetings = guardedStorage(
|
|
2628
|
+
options.greetingStorage,
|
|
2629
|
+
GREETED,
|
|
2630
|
+
() => generation
|
|
2631
|
+
);
|
|
2632
|
+
const warn = options.onWarning ?? ((m) => console.warn(m));
|
|
2633
|
+
const isolated = (what, call) => {
|
|
2634
|
+
try {
|
|
2635
|
+
call();
|
|
2636
|
+
} catch (error) {
|
|
2637
|
+
warn(
|
|
2638
|
+
`@vinaverse/client/agent: the app's ${what} threw (${error instanceof Error ? error.message : String(error)}); the conversation went on.`
|
|
2639
|
+
);
|
|
2640
|
+
}
|
|
2641
|
+
};
|
|
2642
|
+
const saltStore = options.conversation?.persistence ?? options.greetingStorage;
|
|
2643
|
+
const saltKey = `${prefix}:salt`;
|
|
2644
|
+
let salt = null;
|
|
2645
|
+
const waiting = [];
|
|
2646
|
+
const loadSalt = () => {
|
|
2647
|
+
if (!options.onEvent) return;
|
|
2648
|
+
const settle = (kept2) => {
|
|
2649
|
+
if (salt !== null) return;
|
|
2650
|
+
if (kept2) salt = kept2;
|
|
2651
|
+
else {
|
|
2652
|
+
salt = randomId().slice(3);
|
|
2653
|
+
void Promise.resolve(saltStore?.setItem(saltKey, salt)).catch(
|
|
2654
|
+
() => void 0
|
|
2655
|
+
);
|
|
2656
|
+
}
|
|
2657
|
+
for (const event of waiting.splice(0)) deliver(event);
|
|
2658
|
+
};
|
|
2659
|
+
try {
|
|
2660
|
+
const got = saltStore?.getItem(saltKey);
|
|
2661
|
+
if (typeof got === "string" || got == null) settle(got);
|
|
2662
|
+
else got.then(settle, () => settle(null));
|
|
2663
|
+
} catch {
|
|
2664
|
+
settle(null);
|
|
2665
|
+
}
|
|
2666
|
+
};
|
|
2667
|
+
const deliver = (event) => isolated(
|
|
2668
|
+
"onEvent",
|
|
2669
|
+
() => options.onEvent?.(
|
|
2670
|
+
event.key ? { ...event, key: hashKey(event.key, salt ?? "") } : event
|
|
2671
|
+
)
|
|
2672
|
+
);
|
|
2673
|
+
let dropping = false;
|
|
2674
|
+
const emit = (event) => {
|
|
2675
|
+
if (!options.onEvent) return;
|
|
2676
|
+
if (salt !== null) return deliver(event);
|
|
2677
|
+
if (waiting.push(event) > MAX_WAITING) {
|
|
2678
|
+
waiting.shift();
|
|
2679
|
+
if (!dropping)
|
|
2680
|
+
warn(
|
|
2681
|
+
"@vinaverse/client/agent: the analytics salt is still being read from storage; the oldest events are dropped."
|
|
2682
|
+
);
|
|
2683
|
+
dropping = true;
|
|
2684
|
+
}
|
|
2685
|
+
};
|
|
2686
|
+
loadSalt();
|
|
2491
2687
|
const changed = () => {
|
|
2492
2688
|
for (const l of [...listeners]) l();
|
|
2493
2689
|
};
|
|
@@ -2499,6 +2695,7 @@ function createAgentRuntime(options) {
|
|
|
2499
2695
|
const entry = live.get(k);
|
|
2500
2696
|
if (!entry) return;
|
|
2501
2697
|
live.delete(k);
|
|
2698
|
+
clearTimeout(entry.timer);
|
|
2502
2699
|
entry.store.dispose();
|
|
2503
2700
|
emit({ type: "conversation_ended", key: k });
|
|
2504
2701
|
changed();
|
|
@@ -2511,32 +2708,45 @@ function createAgentRuntime(options) {
|
|
|
2511
2708
|
);
|
|
2512
2709
|
async function open(entry, key, request) {
|
|
2513
2710
|
if (live.get(entry.key) !== entry) throw new AgentRefusal("unavailable");
|
|
2514
|
-
const
|
|
2515
|
-
|
|
2711
|
+
const held = entry.failedOpen && clock.now() - entry.failedOpen.at < OPEN_KEPT_MS ? entry.failedOpen : void 0;
|
|
2712
|
+
entry.failedOpen = void 0;
|
|
2713
|
+
const asked = held ? {
|
|
2714
|
+
...held.request,
|
|
2715
|
+
...request.signal ? { signal: request.signal } : {}
|
|
2716
|
+
} : {
|
|
2717
|
+
...request,
|
|
2718
|
+
conversationId: request.conversationId ?? current.get(entry.key) ?? null,
|
|
2719
|
+
key,
|
|
2720
|
+
openId: `op_${randomId().slice(3)}`,
|
|
2721
|
+
agent: options.agent ?? null,
|
|
2722
|
+
place: entry.place,
|
|
2723
|
+
placeRevision: ++entry.revision,
|
|
2724
|
+
entryPoint: entry.entryPoint
|
|
2725
|
+
};
|
|
2726
|
+
const { conversationId, openId, place: told } = asked;
|
|
2516
2727
|
let session;
|
|
2517
2728
|
try {
|
|
2518
2729
|
session = await patiently(
|
|
2519
|
-
() => backend.openSession(
|
|
2520
|
-
...request,
|
|
2521
|
-
conversationId,
|
|
2522
|
-
key,
|
|
2523
|
-
place: told,
|
|
2524
|
-
entryPoint: entry.entryPoint
|
|
2525
|
-
}),
|
|
2730
|
+
() => backend.openSession(asked),
|
|
2526
2731
|
request.signal,
|
|
2527
2732
|
entry.key
|
|
2528
2733
|
);
|
|
2529
2734
|
if (!usable(session, insecure))
|
|
2530
2735
|
throw new AgentRefusal("unavailable", {
|
|
2531
2736
|
reason: "invalid_session",
|
|
2532
|
-
message: "
|
|
2737
|
+
message: "Unusable session: an id, a secret, wss:// and https:// addresses."
|
|
2533
2738
|
});
|
|
2534
2739
|
} catch (error) {
|
|
2535
2740
|
if (live.get(entry.key) === entry) {
|
|
2536
|
-
const failure = error
|
|
2741
|
+
const failure = isRefusal(error) ? error.kind === "ended" && conversationId !== null ? "ended" : "unavailable" : policy.isRetryable(error) ? "unreachable" : "unavailable";
|
|
2537
2742
|
const reason = reasonOf(error, failure);
|
|
2538
|
-
const code = error
|
|
2539
|
-
|
|
2743
|
+
const code = isRefusal(error) ? error.code : codeOf(error);
|
|
2744
|
+
if (failure === "unreachable") {
|
|
2745
|
+
const { signal, ...again } = asked;
|
|
2746
|
+
entry.failedOpen = { request: again, at: held?.at ?? clock.now() };
|
|
2747
|
+
}
|
|
2748
|
+
const unsettled = reason === "unknown_open" ? String(field(error, "openId") ?? openId) : null;
|
|
2749
|
+
update(entry, { failure, reason, code, openId: unsettled });
|
|
2540
2750
|
emit({ type: "session_failed", key: entry.key, failure, reason });
|
|
2541
2751
|
}
|
|
2542
2752
|
throw error;
|
|
@@ -2555,7 +2765,9 @@ function createAgentRuntime(options) {
|
|
|
2555
2765
|
failure: null,
|
|
2556
2766
|
reason: null,
|
|
2557
2767
|
code: null,
|
|
2768
|
+
openId: null,
|
|
2558
2769
|
sessionId: session.id,
|
|
2770
|
+
conversationId: session.conversation_id ?? conversationId,
|
|
2559
2771
|
moved: !samePlace(told, entry.place)
|
|
2560
2772
|
});
|
|
2561
2773
|
emit({
|
|
@@ -2566,25 +2778,106 @@ function createAgentRuntime(options) {
|
|
|
2566
2778
|
});
|
|
2567
2779
|
return session;
|
|
2568
2780
|
}
|
|
2569
|
-
const kept = (k) => `${
|
|
2781
|
+
const kept = (k) => `${prefix}.${k}`;
|
|
2782
|
+
const signOut = async (erasing) => {
|
|
2783
|
+
generation++;
|
|
2784
|
+
if (erasing) salt = null;
|
|
2785
|
+
for (const entry of live.values()) {
|
|
2786
|
+
clearTimeout(entry.timer);
|
|
2787
|
+
entry.store.clear();
|
|
2788
|
+
}
|
|
2789
|
+
const known = /* @__PURE__ */ new Set([...live.keys(), ...current.keys()]);
|
|
2790
|
+
live.clear();
|
|
2791
|
+
current.clear();
|
|
2792
|
+
sessionName = null;
|
|
2793
|
+
status = null;
|
|
2794
|
+
reading = null;
|
|
2795
|
+
changed();
|
|
2796
|
+
const pairs = [];
|
|
2797
|
+
await Promise.all([
|
|
2798
|
+
backend.endSessions?.().catch(() => void 0),
|
|
2799
|
+
storage?.purge(
|
|
2800
|
+
[`${prefix}.`],
|
|
2801
|
+
(keys) => {
|
|
2802
|
+
const all = /* @__PURE__ */ new Set([...keys, ...[...known].map(kept)]);
|
|
2803
|
+
for (const key of all) {
|
|
2804
|
+
const t = tupleOf(key, prefix);
|
|
2805
|
+
if (t) pairs.push([t[1], t[2]]);
|
|
2806
|
+
}
|
|
2807
|
+
return [
|
|
2808
|
+
...all,
|
|
2809
|
+
...legacyTranscripts(all, prefix),
|
|
2810
|
+
...options.legacyKeys ?? []
|
|
2811
|
+
];
|
|
2812
|
+
},
|
|
2813
|
+
`${GREETED}.`
|
|
2814
|
+
)
|
|
2815
|
+
]);
|
|
2816
|
+
if (!erasing) return;
|
|
2817
|
+
await Promise.all([
|
|
2818
|
+
Promise.resolve(saltStore?.removeItem(saltKey)).catch(() => void 0),
|
|
2819
|
+
greetings?.purge([`${GREETED}.`, `${GREETED_BEFORE}.`], (keys) => {
|
|
2820
|
+
for (const key of keys) {
|
|
2821
|
+
const t = tupleOf(key, GREETED);
|
|
2822
|
+
if (t) pairs.push([t[0], t[1]]);
|
|
2823
|
+
}
|
|
2824
|
+
return [...legacyGreetings(pairs), ...options.legacyKeys ?? []];
|
|
2825
|
+
})
|
|
2826
|
+
]);
|
|
2827
|
+
loadSalt();
|
|
2828
|
+
};
|
|
2829
|
+
const forget = (k) => {
|
|
2830
|
+
current.delete(k);
|
|
2831
|
+
const entry = live.get(k);
|
|
2832
|
+
if (entry) {
|
|
2833
|
+
entry.store.clear();
|
|
2834
|
+
end(k);
|
|
2835
|
+
} else void storage?.removeItem(kept(k));
|
|
2836
|
+
};
|
|
2837
|
+
const activity = (entry, a) => {
|
|
2838
|
+
const sessionId = entry.state.sessionId;
|
|
2839
|
+
if (a.type === "reply_completed" && sessionId) {
|
|
2840
|
+
entry.turns.set(a.turnId, sessionId);
|
|
2841
|
+
update(entry, {});
|
|
2842
|
+
}
|
|
2843
|
+
emit({
|
|
2844
|
+
type: a.type,
|
|
2845
|
+
key: entry.key,
|
|
2846
|
+
...sessionId ? { sessionId } : {},
|
|
2847
|
+
...a.type === "reply_completed" ? { turnId: a.turnId } : {},
|
|
2848
|
+
...a.type === "card_shown" ? { cardId: a.cardId, kind: a.kind } : {}
|
|
2849
|
+
});
|
|
2850
|
+
};
|
|
2570
2851
|
function make(key) {
|
|
2571
|
-
const k =
|
|
2852
|
+
const k = keyOf(key);
|
|
2572
2853
|
const own = options.conversation ?? {};
|
|
2573
2854
|
const refresh = backend.refreshSecret?.bind(backend);
|
|
2574
2855
|
const entry = {
|
|
2575
2856
|
key: k,
|
|
2576
2857
|
store: createConversation({
|
|
2577
2858
|
...own,
|
|
2578
|
-
...
|
|
2859
|
+
...storage ? {
|
|
2860
|
+
persistence: storage,
|
|
2579
2861
|
persistenceKey: kept(k)
|
|
2580
2862
|
} : {},
|
|
2863
|
+
onActivity: (a) => {
|
|
2864
|
+
activity(entry, a);
|
|
2865
|
+
isolated("onActivity", () => own.onActivity?.(a));
|
|
2866
|
+
},
|
|
2581
2867
|
getSession: (request) => open(entry, key, request),
|
|
2582
2868
|
...refresh ? {
|
|
2583
|
-
|
|
2869
|
+
// A refusal (`session_closed`) is the store's cue to go on in a new session, never a fault.
|
|
2870
|
+
refreshSecret: (id) => patiently(() => refresh(id), void 0, k).catch((error) => {
|
|
2871
|
+
throw isRefusal(error) ? new VinaverseClientError(
|
|
2872
|
+
"needs_new_session",
|
|
2873
|
+
error.message
|
|
2874
|
+
) : error;
|
|
2875
|
+
})
|
|
2584
2876
|
} : {},
|
|
2585
2877
|
clock,
|
|
2586
2878
|
onError: (error) => {
|
|
2587
|
-
if (!(error
|
|
2879
|
+
if (!isRefusal(error) && codeOf(error) !== "needs_new_session")
|
|
2880
|
+
own.onError?.(error);
|
|
2588
2881
|
}
|
|
2589
2882
|
}),
|
|
2590
2883
|
listeners: /* @__PURE__ */ new Set(),
|
|
@@ -2594,7 +2887,9 @@ function createAgentRuntime(options) {
|
|
|
2594
2887
|
code: null,
|
|
2595
2888
|
moved: false,
|
|
2596
2889
|
ratings: /* @__PURE__ */ new Map(),
|
|
2597
|
-
sessionId: null
|
|
2890
|
+
sessionId: null,
|
|
2891
|
+
conversationId: current.get(k) ?? null,
|
|
2892
|
+
openId: null
|
|
2598
2893
|
},
|
|
2599
2894
|
place: null,
|
|
2600
2895
|
told: null,
|
|
@@ -2604,32 +2899,59 @@ function createAgentRuntime(options) {
|
|
|
2604
2899
|
shown: 0,
|
|
2605
2900
|
started: false,
|
|
2606
2901
|
suspended: false,
|
|
2607
|
-
sentOnce: /* @__PURE__ */ new Set()
|
|
2902
|
+
sentOnce: /* @__PURE__ */ new Set(),
|
|
2903
|
+
timer: void 0,
|
|
2904
|
+
turns: /* @__PURE__ */ new Map(),
|
|
2905
|
+
failedOpen: void 0
|
|
2608
2906
|
};
|
|
2609
2907
|
return entry;
|
|
2610
2908
|
}
|
|
2611
2909
|
const over = (entry) => entry.expiresAt !== null && entry.expiresAt <= clock.now();
|
|
2910
|
+
const expireLater = (entry) => {
|
|
2911
|
+
clearTimeout(entry.timer);
|
|
2912
|
+
if (entry.expiresAt === null) return;
|
|
2913
|
+
entry.timer = setTimeout(
|
|
2914
|
+
() => {
|
|
2915
|
+
entry.timer = void 0;
|
|
2916
|
+
if (live.get(entry.key) !== entry || entry.shown > 0) return;
|
|
2917
|
+
if (over(entry)) end(entry.key);
|
|
2918
|
+
else expireLater(entry);
|
|
2919
|
+
},
|
|
2920
|
+
Math.max(0, entry.expiresAt - clock.now())
|
|
2921
|
+
);
|
|
2922
|
+
};
|
|
2612
2923
|
const tell = (entry, at) => {
|
|
2613
|
-
entry.place = at.place
|
|
2614
|
-
entry.entryPoint = at.entryPoint
|
|
2924
|
+
if (at.place !== void 0) entry.place = at.place;
|
|
2925
|
+
if (at.entryPoint !== void 0) entry.entryPoint = at.entryPoint;
|
|
2615
2926
|
const sessionId = entry.state.sessionId;
|
|
2616
2927
|
const moved = sessionId !== null && !samePlace(entry.told, entry.place);
|
|
2617
2928
|
update(entry, { moved });
|
|
2618
|
-
const
|
|
2619
|
-
if (!moved || !
|
|
2620
|
-
|
|
2621
|
-
const
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2929
|
+
const updateContext = backend.updateContext?.bind(backend);
|
|
2930
|
+
if (!moved || !updateContext || sessionId === null) return;
|
|
2931
|
+
const asked = generation;
|
|
2932
|
+
const current2 = () => asked === generation && live.get(entry.key) === entry && entry.state.sessionId === sessionId;
|
|
2933
|
+
const send = (again) => {
|
|
2934
|
+
const place = entry.place;
|
|
2935
|
+
const revision = ++entry.revision;
|
|
2936
|
+
updateContext(sessionId, place ?? CLEARED, revision).then(
|
|
2937
|
+
() => {
|
|
2938
|
+
if (!current2() || entry.revision !== revision) return;
|
|
2939
|
+
entry.told = place;
|
|
2940
|
+
update(entry, { moved: !samePlace(entry.told, entry.place) });
|
|
2941
|
+
emit({ type: "context_updated", key: entry.key, sessionId });
|
|
2942
|
+
},
|
|
2943
|
+
(error) => {
|
|
2944
|
+
const theirs = field(error, "currentRevision");
|
|
2945
|
+
const conflict = field(error, "outcome") === "context_conflict" || field(error, "reason") === "conflict";
|
|
2946
|
+
if (!conflict || again || !current2() || entry.revision !== revision)
|
|
2947
|
+
return;
|
|
2948
|
+
if (typeof theirs === "number" && theirs >= entry.revision)
|
|
2949
|
+
entry.revision = theirs;
|
|
2950
|
+
send(true);
|
|
2951
|
+
}
|
|
2952
|
+
);
|
|
2953
|
+
};
|
|
2954
|
+
send(false);
|
|
2633
2955
|
};
|
|
2634
2956
|
function handle(entry) {
|
|
2635
2957
|
return {
|
|
@@ -2642,6 +2964,8 @@ function createAgentRuntime(options) {
|
|
|
2642
2964
|
return () => void 0;
|
|
2643
2965
|
}
|
|
2644
2966
|
entry.shown++;
|
|
2967
|
+
clearTimeout(entry.timer);
|
|
2968
|
+
entry.timer = void 0;
|
|
2645
2969
|
if (entry.suspended) {
|
|
2646
2970
|
entry.suspended = false;
|
|
2647
2971
|
entry.store.setForeground(true);
|
|
@@ -2663,6 +2987,7 @@ function createAgentRuntime(options) {
|
|
|
2663
2987
|
}
|
|
2664
2988
|
entry.suspended = true;
|
|
2665
2989
|
entry.store.setForeground(false);
|
|
2990
|
+
expireLater(entry);
|
|
2666
2991
|
};
|
|
2667
2992
|
},
|
|
2668
2993
|
tell: (at) => tell(entry, at),
|
|
@@ -2672,13 +2997,18 @@ function createAgentRuntime(options) {
|
|
|
2672
2997
|
return () => entry.listeners.delete(listener);
|
|
2673
2998
|
},
|
|
2674
2999
|
retry() {
|
|
2675
|
-
update(entry, {
|
|
3000
|
+
update(entry, {
|
|
3001
|
+
failure: null,
|
|
3002
|
+
reason: null,
|
|
3003
|
+
code: null,
|
|
3004
|
+
openId: null
|
|
3005
|
+
});
|
|
2676
3006
|
entry.store.start();
|
|
2677
3007
|
},
|
|
3008
|
+
canRate: (turnId) => entry.turns.has(turnId),
|
|
2678
3009
|
rate(turnId, rating) {
|
|
2679
|
-
const sessionId = entry.
|
|
2680
|
-
if (sessionId
|
|
2681
|
-
return;
|
|
3010
|
+
const sessionId = entry.turns.get(turnId);
|
|
3011
|
+
if (!sessionId || entry.state.ratings.get(turnId) === rating) return;
|
|
2682
3012
|
update(entry, {
|
|
2683
3013
|
ratings: new Map(entry.state.ratings).set(turnId, rating)
|
|
2684
3014
|
});
|
|
@@ -2694,7 +3024,7 @@ function createAgentRuntime(options) {
|
|
|
2694
3024
|
}
|
|
2695
3025
|
const handles = /* @__PURE__ */ new WeakMap();
|
|
2696
3026
|
const lookup = (key) => {
|
|
2697
|
-
const k =
|
|
3027
|
+
const k = keyOf(key);
|
|
2698
3028
|
let entry = live.get(k);
|
|
2699
3029
|
if (!entry) {
|
|
2700
3030
|
entry = make(key);
|
|
@@ -2709,63 +3039,72 @@ function createAgentRuntime(options) {
|
|
|
2709
3039
|
};
|
|
2710
3040
|
return {
|
|
2711
3041
|
conversation(key) {
|
|
2712
|
-
const k =
|
|
3042
|
+
const k = keyOf(key);
|
|
2713
3043
|
const entry = live.get(k);
|
|
2714
3044
|
if (entry && entry.shown === 0 && over(entry)) end(k);
|
|
2715
3045
|
return lookup(key);
|
|
2716
3046
|
},
|
|
2717
3047
|
peek: lookup,
|
|
2718
3048
|
startNew(key) {
|
|
2719
|
-
const k =
|
|
3049
|
+
const k = keyOf(key);
|
|
2720
3050
|
current.delete(k);
|
|
2721
3051
|
end(k);
|
|
2722
3052
|
},
|
|
2723
3053
|
dispose(key) {
|
|
2724
|
-
end(
|
|
3054
|
+
end(keyOf(key));
|
|
3055
|
+
},
|
|
3056
|
+
forget(key) {
|
|
3057
|
+
forget(keyOf(key));
|
|
3058
|
+
},
|
|
3059
|
+
sweep() {
|
|
3060
|
+
for (const entry of [...live.values()])
|
|
3061
|
+
if (entry.shown === 0 && over(entry)) end(entry.key);
|
|
2725
3062
|
},
|
|
2726
3063
|
continue(key, conversationId) {
|
|
2727
|
-
const k =
|
|
3064
|
+
const k = keyOf(key);
|
|
2728
3065
|
if (current.get(k) !== conversationId) {
|
|
3066
|
+
forget(k);
|
|
2729
3067
|
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
3068
|
}
|
|
2743
3069
|
return lookup(key);
|
|
2744
3070
|
},
|
|
2745
3071
|
async signOut() {
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
changed();
|
|
2751
|
-
await backend.endSessions?.().catch(() => void 0);
|
|
3072
|
+
await signOut(false);
|
|
3073
|
+
},
|
|
3074
|
+
async erase() {
|
|
3075
|
+
await signOut(true);
|
|
2752
3076
|
},
|
|
3077
|
+
async deleteConversation(key, conversationId) {
|
|
3078
|
+
if (!backend.deleteConversation)
|
|
3079
|
+
throw new Error(
|
|
3080
|
+
"@vinaverse/client/agent: deleteConversation needs AgentBackend.deleteConversation."
|
|
3081
|
+
);
|
|
3082
|
+
await backend.deleteConversation(conversationId);
|
|
3083
|
+
const k = keyOf(key);
|
|
3084
|
+
const continued = current.get(k) ?? live.get(k)?.store.getSnapshot().conversationId ?? null;
|
|
3085
|
+
if (continued === conversationId) forget(k);
|
|
3086
|
+
},
|
|
3087
|
+
greetings: greetings ?? null,
|
|
2753
3088
|
status() {
|
|
2754
3089
|
if (status && clock.now() - status.at < staleMs)
|
|
2755
3090
|
return Promise.resolve(status.value);
|
|
2756
|
-
reading
|
|
3091
|
+
if (reading) return reading;
|
|
3092
|
+
const asked = generation;
|
|
3093
|
+
const read = readStatus(backend).then(
|
|
2757
3094
|
(value) => {
|
|
3095
|
+
if (asked !== generation) return value;
|
|
2758
3096
|
reading = null;
|
|
2759
3097
|
status = { value, at: clock.now() };
|
|
2760
3098
|
changed();
|
|
2761
3099
|
return value;
|
|
2762
3100
|
},
|
|
2763
3101
|
(error) => {
|
|
2764
|
-
reading = null;
|
|
3102
|
+
if (asked === generation) reading = null;
|
|
2765
3103
|
throw error;
|
|
2766
3104
|
}
|
|
2767
3105
|
);
|
|
2768
|
-
|
|
3106
|
+
reading = read;
|
|
3107
|
+
return read;
|
|
2769
3108
|
},
|
|
2770
3109
|
getStatus: () => status?.value ?? null,
|
|
2771
3110
|
getName: () => sessionName ?? status?.value.displayName ?? null,
|
|
@@ -2776,6 +3115,100 @@ function createAgentRuntime(options) {
|
|
|
2776
3115
|
emit
|
|
2777
3116
|
};
|
|
2778
3117
|
}
|
|
3118
|
+
function guardedStorage(raw, prefix, generation) {
|
|
3119
|
+
if (!raw) return void 0;
|
|
3120
|
+
const indexKey = `${prefix}:index`;
|
|
3121
|
+
const chains = /* @__PURE__ */ new Map();
|
|
3122
|
+
const pending = /* @__PURE__ */ new Map();
|
|
3123
|
+
const queued = (key, op) => {
|
|
3124
|
+
pending.set(key, (pending.get(key) ?? 0) + 1);
|
|
3125
|
+
const run = (chains.get(key) ?? Promise.resolve()).then(op);
|
|
3126
|
+
const settled = run.then(
|
|
3127
|
+
() => void 0,
|
|
3128
|
+
() => void 0
|
|
3129
|
+
);
|
|
3130
|
+
chains.set(key, settled);
|
|
3131
|
+
void settled.then(() => {
|
|
3132
|
+
const left = (pending.get(key) ?? 1) - 1;
|
|
3133
|
+
if (left > 0) pending.set(key, left);
|
|
3134
|
+
else {
|
|
3135
|
+
pending.delete(key);
|
|
3136
|
+
if (chains.get(key) === settled) chains.delete(key);
|
|
3137
|
+
}
|
|
3138
|
+
});
|
|
3139
|
+
return run;
|
|
3140
|
+
};
|
|
3141
|
+
const safe = (p) => p.catch(() => void 0);
|
|
3142
|
+
const readIndex = async () => {
|
|
3143
|
+
try {
|
|
3144
|
+
const value = await raw.getItem(indexKey);
|
|
3145
|
+
const list3 = value ? JSON.parse(value) : [];
|
|
3146
|
+
return new Set(
|
|
3147
|
+
Array.isArray(list3) ? list3.filter((k) => typeof k === "string") : []
|
|
3148
|
+
);
|
|
3149
|
+
} catch {
|
|
3150
|
+
return /* @__PURE__ */ new Set();
|
|
3151
|
+
}
|
|
3152
|
+
};
|
|
3153
|
+
const listed = /* @__PURE__ */ new Set();
|
|
3154
|
+
const list2 = (key) => {
|
|
3155
|
+
if (listed.has(key)) return;
|
|
3156
|
+
listed.add(key);
|
|
3157
|
+
void safe(
|
|
3158
|
+
queued(indexKey, async () => {
|
|
3159
|
+
const all = await readIndex();
|
|
3160
|
+
if (all.has(key)) return;
|
|
3161
|
+
all.add(key);
|
|
3162
|
+
await raw.setItem(indexKey, JSON.stringify([...all]));
|
|
3163
|
+
})
|
|
3164
|
+
);
|
|
3165
|
+
};
|
|
3166
|
+
return {
|
|
3167
|
+
getItem(key) {
|
|
3168
|
+
const asked = generation();
|
|
3169
|
+
const read = pending.has(key) ? queued(key, () => raw.getItem(key)) : raw.getItem(key);
|
|
3170
|
+
if (typeof read === "string" || read === null) return read;
|
|
3171
|
+
return Promise.resolve(read).then(
|
|
3172
|
+
(v) => asked === generation() ? v ?? null : null,
|
|
3173
|
+
() => null
|
|
3174
|
+
);
|
|
3175
|
+
},
|
|
3176
|
+
setItem(key, value) {
|
|
3177
|
+
const asked = generation();
|
|
3178
|
+
return safe(
|
|
3179
|
+
queued(key, () => {
|
|
3180
|
+
if (asked !== generation()) return;
|
|
3181
|
+
list2(key);
|
|
3182
|
+
return raw.setItem(key, value);
|
|
3183
|
+
})
|
|
3184
|
+
);
|
|
3185
|
+
},
|
|
3186
|
+
removeItem: (key) => safe(queued(key, () => raw.removeItem(key))),
|
|
3187
|
+
/**
|
|
3188
|
+
* Everything kept: the index, what the app's storage finds under `under` (`removePrefix`, else `keys`), and `extra`
|
|
3189
|
+
* (older key shapes). Nothing under `keep` goes, so `removePrefix` is used only for a prefix that cannot reach it.
|
|
3190
|
+
*/
|
|
3191
|
+
async purge(under, extra = () => [], keep) {
|
|
3192
|
+
const all = /* @__PURE__ */ new Set([...listed, ...await readIndex()]);
|
|
3193
|
+
listed.clear();
|
|
3194
|
+
for (const p of under)
|
|
3195
|
+
try {
|
|
3196
|
+
if (raw.removePrefix && !keep?.startsWith(p))
|
|
3197
|
+
await raw.removePrefix(p);
|
|
3198
|
+
else if (raw.keys) {
|
|
3199
|
+
for (const key of await raw.keys(p))
|
|
3200
|
+
if (!keep || !key.startsWith(keep)) all.add(key);
|
|
3201
|
+
}
|
|
3202
|
+
} catch {
|
|
3203
|
+
}
|
|
3204
|
+
for (const key of extra(all)) all.add(key);
|
|
3205
|
+
await Promise.all(
|
|
3206
|
+
[...all].map((key) => safe(queued(key, () => raw.removeItem(key))))
|
|
3207
|
+
);
|
|
3208
|
+
await safe(queued(indexKey, () => raw.removeItem(indexKey)));
|
|
3209
|
+
}
|
|
3210
|
+
};
|
|
3211
|
+
}
|
|
2779
3212
|
async function readStatus(backend) {
|
|
2780
3213
|
const read = backend.status ? await backend.status() : { available: true };
|
|
2781
3214
|
const available = read.available === true;
|
|
@@ -2793,10 +3226,20 @@ async function readStatus(backend) {
|
|
|
2793
3226
|
}
|
|
2794
3227
|
};
|
|
2795
3228
|
}
|
|
3229
|
+
function isRefusal(error) {
|
|
3230
|
+
return error instanceof AgentRefusal || field(error, "name") === "AgentRefusal" && (field(error, "kind") === "ended" || field(error, "kind") === "unavailable");
|
|
3231
|
+
}
|
|
2796
3232
|
var field = (error, name) => typeof error === "object" && error !== null ? error[name] : void 0;
|
|
2797
3233
|
var retryable = (error) => field(error, "retryable") === true;
|
|
2798
3234
|
var REASONS = /* @__PURE__ */ new Set([
|
|
2799
3235
|
"ended",
|
|
3236
|
+
"not_found",
|
|
3237
|
+
"expired",
|
|
3238
|
+
"mismatch",
|
|
3239
|
+
"completed",
|
|
3240
|
+
"forbidden",
|
|
3241
|
+
"conflict",
|
|
3242
|
+
"unknown_open",
|
|
2800
3243
|
"auth",
|
|
2801
3244
|
"off",
|
|
2802
3245
|
"rate_limited",
|
|
@@ -2806,7 +3249,7 @@ var REASONS = /* @__PURE__ */ new Set([
|
|
|
2806
3249
|
"unknown"
|
|
2807
3250
|
]);
|
|
2808
3251
|
function reasonOf(error, failure) {
|
|
2809
|
-
if (error
|
|
3252
|
+
if (isRefusal(error)) return error.reason;
|
|
2810
3253
|
const given = field(error, "reason");
|
|
2811
3254
|
if (typeof given === "string" && REASONS.has(given))
|
|
2812
3255
|
return given;
|
|
@@ -2817,7 +3260,7 @@ function reasonOf(error, failure) {
|
|
|
2817
3260
|
return failure === "unreachable" ? "network" : "unknown";
|
|
2818
3261
|
}
|
|
2819
3262
|
function codeOf(error) {
|
|
2820
|
-
const code = field(error, "code");
|
|
3263
|
+
const code = field(error, "code") ?? field(error, "outcome");
|
|
2821
3264
|
return typeof code === "string" ? code : null;
|
|
2822
3265
|
}
|
|
2823
3266
|
async function retrying(run, policy, signal, onRetry) {
|
|
@@ -2825,9 +3268,11 @@ async function retrying(run, policy, signal, onRetry) {
|
|
|
2825
3268
|
try {
|
|
2826
3269
|
return await run();
|
|
2827
3270
|
} catch (error) {
|
|
2828
|
-
const
|
|
2829
|
-
if (
|
|
3271
|
+
const delay = policy.delays[attempt];
|
|
3272
|
+
if (delay === void 0 || !policy.isRetryable(error) || signal?.aborted)
|
|
2830
3273
|
throw error;
|
|
3274
|
+
const asked = field(error, "retryAfterMs");
|
|
3275
|
+
const wait = typeof asked === "number" && asked > delay ? Math.min(asked, 6e4) : delay;
|
|
2831
3276
|
await new Promise((resolve, reject) => {
|
|
2832
3277
|
const timer = setTimeout(() => {
|
|
2833
3278
|
signal?.removeEventListener("abort", stop);
|
|
@@ -2847,6 +3292,9 @@ async function retrying(run, policy, signal, onRetry) {
|
|
|
2847
3292
|
exports.AgentRefusal = AgentRefusal;
|
|
2848
3293
|
exports.agentKey = agentKey;
|
|
2849
3294
|
exports.createAgentRuntime = createAgentRuntime;
|
|
3295
|
+
exports.greetedKey = greetedKey;
|
|
3296
|
+
exports.hashKey = hashKey;
|
|
3297
|
+
exports.isRefusal = isRefusal;
|
|
2850
3298
|
exports.readCard = readCard;
|
|
2851
3299
|
//# sourceMappingURL=index.cjs.map
|
|
2852
3300
|
//# sourceMappingURL=index.cjs.map
|