@livx.cc/agentx 0.99.111 → 0.99.113
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/dist/cli.js +59 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +43 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1703,6 +1703,8 @@ declare class VoiceCallOptions {
|
|
|
1703
1703
|
channel: Partial<SecondChannelOptions>;
|
|
1704
1704
|
onMetric: (m: CallMetric) => void;
|
|
1705
1705
|
now: () => number;
|
|
1706
|
+
/** An aside (aside()) needs this long since the last one — a cue answered every time sounds scripted. */
|
|
1707
|
+
asideGapMs: number;
|
|
1706
1708
|
}
|
|
1707
1709
|
declare class VoiceCall {
|
|
1708
1710
|
options?: Partial<VoiceCallOptions> | undefined;
|
|
@@ -1712,6 +1714,7 @@ declare class VoiceCall {
|
|
|
1712
1714
|
private judge;
|
|
1713
1715
|
private cur?;
|
|
1714
1716
|
private lang;
|
|
1717
|
+
private lastAside;
|
|
1715
1718
|
private lastAudibleAt;
|
|
1716
1719
|
private firstFinalAt;
|
|
1717
1720
|
private progressTimer;
|
|
@@ -1742,6 +1745,11 @@ declare class VoiceCall {
|
|
|
1742
1745
|
barge(): void;
|
|
1743
1746
|
/** Soft barge-in: keep (a listener cue — no turn) or cut (→ barge()). */
|
|
1744
1747
|
overlap(text: string): Promise<OverlapVerdict>;
|
|
1748
|
+
/** The fill channel's spoken aside for an overlap judged 'keep' ("yeah" → "Oh yeah, definitely."): the host plays it
|
|
1749
|
+
* while the reply is held, then resumes the same reply (bod-voice decideOverlap's aside). ≤4 canned words, never a
|
|
1750
|
+
* claim, the cue's language; null = stay quiet (a plain listener cue, too soon after the last, or no line). It is a
|
|
1751
|
+
* fill line: never MAIN history. */
|
|
1752
|
+
aside(text: string): string | null;
|
|
1745
1753
|
/** Did the last barge cut OUR fill line `text`? (hosts strip it from the cut reply — it is not MAIN's speech) */
|
|
1746
1754
|
spoke(text: string): boolean;
|
|
1747
1755
|
/** Resolves when the in-flight fill line finished — hosts queue MAIN audio behind it (stack, don't cut). */
|
package/dist/index.js
CHANGED
|
@@ -9304,14 +9304,40 @@ var ACK = new Set("yeah yea yes yep yup ya ok okay k right sure true totally exa
|
|
|
9304
9304
|
var LEAD = /* @__PURE__ */ new Set(["and", "so", "um", "uh", "er", "well", "oh"]);
|
|
9305
9305
|
var LEADER = /* @__PURE__ */ new Set(["yeah", "yea", "yes", "yep", "yup", "ok", "okay", "right", "sure", "alright", "mm", "mhm", "hmm", "uh-huh", "totally", "exactly", "true"]);
|
|
9306
9306
|
var PHRASES = ["got it", "i see", "makes sense", "of course", "for sure", "all right", "that's right", "that's true", "thats right", "thats true", "love it", "i know", "me too", "uh huh"];
|
|
9307
|
+
var CONTINUE = /^(?:(?:and|so|oh) )?(?:and|so|really|seriously|then what|and then|go on|keep going|ואז|באמת|נו)$/;
|
|
9308
|
+
var AGREE = new Set("yeah yea yes yep yup right sure true totally exactly definitely absolutely agreed correct indeed \u05DB\u05DF \u05E0\u05DB\u05D5\u05DF \u05D1\u05D3\u05D9\u05D5\u05E7 \u05D1\u05E8\u05D5\u05E8 \u05D1\u05D8\u05D7 \u05D0\u05DB\u05DF \u05DC\u05D2\u05DE\u05E8\u05D9 \u05DE\u05E1\u05DB\u05D9\u05DD \u05DE\u05E1\u05DB\u05D9\u05DE\u05D4 \u05DE\u05DE\u05E9".split(" "));
|
|
9309
|
+
var AGREE_PHRASES = ["of course", "for sure", "that's right", "that's true", "thats right", "thats true", "makes sense", "i agree"];
|
|
9310
|
+
var HE_ACK = new Set("\u05DB\u05DF \u05E0\u05DB\u05D5\u05DF \u05D1\u05D3\u05D9\u05D5\u05E7 \u05D1\u05E8\u05D5\u05E8 \u05D1\u05D8\u05D7 \u05D0\u05DB\u05DF \u05DC\u05D2\u05DE\u05E8\u05D9 \u05DE\u05DE\u05E9 \u05D0\u05D5\u05E7\u05D9\u05D9 \u05D0\u05D5\u05E7\u05D9 \u05E1\u05D1\u05D1\u05D4 \u05D9\u05E4\u05D4 \u05DE\u05E2\u05D5\u05DC\u05D4 \u05D5\u05D5\u05D0\u05D5 \u05D0\u05D4\u05D4 \u05D0\u05D4 \u05D4\u05DE\u05DE \u05DE\u05DE\u05DE".split(" "));
|
|
9311
|
+
function cueKind(text) {
|
|
9312
|
+
const t = norm2(text);
|
|
9313
|
+
if (!t) return null;
|
|
9314
|
+
if (CONTINUE.test(t)) return "continue";
|
|
9315
|
+
let r = t;
|
|
9316
|
+
for (const p of AGREE_PHRASES) if (r.includes(p)) return "agree";
|
|
9317
|
+
r = r.split(/[\s-]+/).filter((w) => !LEAD.has(w)).join(" ");
|
|
9318
|
+
return r.split(" ").some((w) => AGREE.has(w)) ? "agree" : null;
|
|
9319
|
+
}
|
|
9320
|
+
var ASIDES = {
|
|
9321
|
+
en: { agree: ["Oh yeah, definitely.", "Yeah, exactly.", "Right, yeah."], continue: ["Yeah, so\u2026", "So, yeah\u2026"] },
|
|
9322
|
+
he: { agree: ["\u05DB\u05DF, \u05D1\u05D3\u05D9\u05D5\u05E7.", "\u05DB\u05DF, \u05DE\u05DE\u05E9.", "\u05E0\u05DB\u05D5\u05DF, \u05DB\u05DF."], continue: ["\u05DB\u05DF, \u05D0\u05D6\u2026", "\u05D0\u05D6 \u05DB\u05DF\u2026"] }
|
|
9323
|
+
};
|
|
9324
|
+
function overlapAside(text, lang, avoid = "", pick = (n) => Math.floor(Math.random() * n)) {
|
|
9325
|
+
const kind = cueKind(text);
|
|
9326
|
+
const l = new RegExp("\\p{Script=Hebrew}", "u").test(text) ? "he" : /[a-z]/i.test(text) ? "en" : lang;
|
|
9327
|
+
const pool = kind && l ? ASIDES[l]?.[kind] : void 0;
|
|
9328
|
+
if (!pool?.length) return null;
|
|
9329
|
+
const fresh = pool.filter((x) => x !== avoid);
|
|
9330
|
+
return fresh[pick(fresh.length)] ?? null;
|
|
9331
|
+
}
|
|
9307
9332
|
function overlapRule(text) {
|
|
9333
|
+
if (CONTINUE.test(norm2(text))) return "keep";
|
|
9308
9334
|
if (/\?/.test(text)) return "cut";
|
|
9309
9335
|
let t = norm2(text);
|
|
9310
9336
|
if (!t) return void 0;
|
|
9311
9337
|
if (HARD.test(t)) return "cut";
|
|
9312
9338
|
for (const p of PHRASES) t = t.split(p).join(" ");
|
|
9313
9339
|
const words3 = t.split(/[\s-]+/).filter(Boolean);
|
|
9314
|
-
const ack = (w) => ACK.has(w) || /^(?:ha)+h?$|^(?:he)+h?$|^m+(?:hm+)?$|^h?m+$/.test(w);
|
|
9340
|
+
const ack = (w) => ACK.has(w) || HE_ACK.has(w) || /^(?:ha)+h?$|^(?:he)+h?$|^m+(?:hm+)?$|^h?m+$/.test(w);
|
|
9315
9341
|
if (words3.every(ack)) return "keep";
|
|
9316
9342
|
const lead2 = words3.findIndex((w) => !LEAD.has(w));
|
|
9317
9343
|
if (lead2 >= 0 && LEADER.has(words3[lead2]) && words3.slice(lead2).filter((w) => !ack(w) && !LEAD.has(w)).length <= 1) return "keep";
|
|
@@ -13284,6 +13310,8 @@ var VoiceCallOptions = class {
|
|
|
13284
13310
|
onMetric = () => {
|
|
13285
13311
|
};
|
|
13286
13312
|
now = () => performance.now();
|
|
13313
|
+
/** An aside (aside()) needs this long since the last one — a cue answered every time sounds scripted. */
|
|
13314
|
+
asideGapMs = 8e3;
|
|
13287
13315
|
};
|
|
13288
13316
|
var VoiceCall = class {
|
|
13289
13317
|
constructor(options) {
|
|
@@ -13327,6 +13355,7 @@ var VoiceCall = class {
|
|
|
13327
13355
|
judge;
|
|
13328
13356
|
cur;
|
|
13329
13357
|
lang = null;
|
|
13358
|
+
lastAside = { text: "", at: -Infinity };
|
|
13330
13359
|
lastAudibleAt = -Infinity;
|
|
13331
13360
|
firstFinalAt = null;
|
|
13332
13361
|
// the first final of the turn being formed (hold/merge)
|
|
@@ -13435,6 +13464,19 @@ var VoiceCall = class {
|
|
|
13435
13464
|
if (d.verdict === "cut") this.barge();
|
|
13436
13465
|
return d.verdict;
|
|
13437
13466
|
}
|
|
13467
|
+
/** The fill channel's spoken aside for an overlap judged 'keep' ("yeah" → "Oh yeah, definitely."): the host plays it
|
|
13468
|
+
* while the reply is held, then resumes the same reply (bod-voice decideOverlap's aside). ≤4 canned words, never a
|
|
13469
|
+
* claim, the cue's language; null = stay quiet (a plain listener cue, too soon after the last, or no line). It is a
|
|
13470
|
+
* fill line: never MAIN history. */
|
|
13471
|
+
aside(text) {
|
|
13472
|
+
const now3 = this.o.now();
|
|
13473
|
+
if (now3 - this.lastAside.at < this.o.asideGapMs) return null;
|
|
13474
|
+
const line = overlapAside(text, this.lang, this.lastAside.text);
|
|
13475
|
+
if (!line) return null;
|
|
13476
|
+
this.lastAside = { text: line, at: now3 };
|
|
13477
|
+
this.o.onMetric({ name: "fill", kind: "aside", text: line, lang: this.lang });
|
|
13478
|
+
return line;
|
|
13479
|
+
}
|
|
13438
13480
|
/** Did the last barge cut OUR fill line `text`? (hosts strip it from the cut reply — it is not MAIN's speech) */
|
|
13439
13481
|
spoke(text) {
|
|
13440
13482
|
return this.fill.spoke(text);
|