@livx.cc/agentx 0.99.112 → 0.99.114
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.d.ts +3 -1
- package/dist/cli.js +137 -28
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +17 -4
- package/dist/index.js +104 -14
- package/dist/index.js.map +1 -1
- package/dist/{secondChannel-CJMY5EbL.d.ts → secondChannel-Cl-fIl-F.d.ts} +30 -27
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as AgentOptions, H as Hooks, p as RunResult, f as Decider, A as Agent, i as PermissionPolicy, L as LineKind, C as ChannelMode, q as SecondChannelOptions, S as SecondChannel } from './secondChannel-
|
|
2
|
-
export { b as ChatFragment, c as Classification, d as Classifier, e as CompactResult, D as DEFAULT_MUTATING, g as Decision, M as ModelRouter, h as ModelRouterOptions, P as PermissionOptions, j as PermissionRule, k as PreToolUseDecision, R as ReasoningEffort, l as RecordingHooks, m as RecordingLifecycle, n as RouteDecision, o as RouterState, T as Tier, r as ToolUse, s as ToolUseMeta, t as claudeCodeDisallowedTools, u as composeHooks, v as estimateTokens, w as jevAvailable, x as jevClassifier, y as pickTier, z as planMode, B as reasoningToChatFragment } from './secondChannel-
|
|
1
|
+
import { a as AgentOptions, H as Hooks, p as RunResult, f as Decider, A as Agent, i as PermissionPolicy, G as Gender, L as LineKind, C as ChannelMode, q as SecondChannelOptions, S as SecondChannel } from './secondChannel-Cl-fIl-F.js';
|
|
2
|
+
export { b as ChatFragment, c as Classification, d as Classifier, e as CompactResult, D as DEFAULT_MUTATING, g as Decision, M as ModelRouter, h as ModelRouterOptions, P as PermissionOptions, j as PermissionRule, k as PreToolUseDecision, R as ReasoningEffort, l as RecordingHooks, m as RecordingLifecycle, n as RouteDecision, o as RouterState, T as Tier, r as ToolUse, s as ToolUseMeta, t as claudeCodeDisallowedTools, u as composeHooks, v as estimateTokens, w as jevAvailable, x as jevClassifier, y as pickTier, z as planMode, B as reasoningToChatFragment } from './secondChannel-Cl-fIl-F.js';
|
|
3
3
|
export { MODEL_ALIASES, ModelSwitch, ResolveModelSwitchOpts, latestClaude, modelShortLabel, resolveModelAlias, resolveModelSwitch } from './models.js';
|
|
4
4
|
import { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';
|
|
5
5
|
export { CommandExecutor, FileMetadata, IFilesystem, IndexedDbFilesystem, MemFilesystem, registerHeadlessCommands } from '@livx.cc/wcli/core';
|
|
@@ -1621,11 +1621,14 @@ declare function makeTaskBatchTool(opts: TaskToolOptions): AgentTool;
|
|
|
1621
1621
|
/** Component-scoped logger (libx.js). debug/verbose gated via DEBUG env/localStorage. */
|
|
1622
1622
|
declare const forComponent: (name: string) => libx_js_src_modules_log.ComponentLogger;
|
|
1623
1623
|
|
|
1624
|
-
type Topic = 'board' | 'search' | '
|
|
1625
|
-
/** Two phrasings per topic and language (never the same line twice in a call).
|
|
1624
|
+
type Topic = 'board' | 'websearch' | 'page' | 'browser' | 'search' | 'mail' | 'calendar' | 'memory' | 'write' | 'run' | 'read' | 'delegate';
|
|
1625
|
+
/** Two phrasings per topic and language (never the same line twice in a call). Hebrew is gendered on the speaker:
|
|
1626
|
+
* 'he-f' / 'he-m' follow the voice (ProgressOptions.gender); 'he' (plural present) when the gender is unknown. */
|
|
1626
1627
|
declare const PROGRESS_TEMPLATES: Record<string, Record<Topic, string[]>>;
|
|
1627
1628
|
declare class ProgressOptions {
|
|
1628
1629
|
templates: Record<string, Partial<Record<Topic, string[]>>>;
|
|
1630
|
+
/** The voice's gender: picks the gendered table (`${lang}-f`/`-m`) when one exists. */
|
|
1631
|
+
gender: Gender;
|
|
1629
1632
|
/** Fast-model fallback for a tool with no template (fastProgressGenerator). Absent → silence. */
|
|
1630
1633
|
generate?: (tool: string, hint: string, lang: string, signal: AbortSignal) => Promise<string>;
|
|
1631
1634
|
generateBudgetMs: number;
|
|
@@ -1695,6 +1698,8 @@ declare class VoiceCallOptions {
|
|
|
1695
1698
|
bankCacheDir?: string;
|
|
1696
1699
|
/** The host STT's language (BCP-47) — the starting language; each turn's own words still decide. */
|
|
1697
1700
|
lang?: string;
|
|
1701
|
+
/** The voice's gender: generated fill/progress lines speak of themselves in it (Hebrew templates too). '' = neutral. */
|
|
1702
|
+
gender: Gender;
|
|
1698
1703
|
aec: boolean;
|
|
1699
1704
|
mode: ChannelMode;
|
|
1700
1705
|
gate: Partial<TurnGateOptions>;
|
|
@@ -1703,6 +1708,8 @@ declare class VoiceCallOptions {
|
|
|
1703
1708
|
channel: Partial<SecondChannelOptions>;
|
|
1704
1709
|
onMetric: (m: CallMetric) => void;
|
|
1705
1710
|
now: () => number;
|
|
1711
|
+
/** An aside (aside()) needs this long since the last one — a cue answered every time sounds scripted. */
|
|
1712
|
+
asideGapMs: number;
|
|
1706
1713
|
}
|
|
1707
1714
|
declare class VoiceCall {
|
|
1708
1715
|
options?: Partial<VoiceCallOptions> | undefined;
|
|
@@ -1712,6 +1719,7 @@ declare class VoiceCall {
|
|
|
1712
1719
|
private judge;
|
|
1713
1720
|
private cur?;
|
|
1714
1721
|
private lang;
|
|
1722
|
+
private lastAside;
|
|
1715
1723
|
private lastAudibleAt;
|
|
1716
1724
|
private firstFinalAt;
|
|
1717
1725
|
private progressTimer;
|
|
@@ -1742,6 +1750,11 @@ declare class VoiceCall {
|
|
|
1742
1750
|
barge(): void;
|
|
1743
1751
|
/** Soft barge-in: keep (a listener cue — no turn) or cut (→ barge()). */
|
|
1744
1752
|
overlap(text: string): Promise<OverlapVerdict>;
|
|
1753
|
+
/** The fill channel's spoken aside for an overlap judged 'keep' ("yeah" → "Oh yeah, definitely."): the host plays it
|
|
1754
|
+
* while the reply is held, then resumes the same reply (bod-voice decideOverlap's aside). ≤4 canned words, never a
|
|
1755
|
+
* claim, the cue's language; null = stay quiet (a plain listener cue, too soon after the last, or no line). It is a
|
|
1756
|
+
* fill line: never MAIN history. */
|
|
1757
|
+
aside(text: string): string | null;
|
|
1745
1758
|
/** Did the last barge cut OUR fill line `text`? (hosts strip it from the cut reply — it is not MAIN's speech) */
|
|
1746
1759
|
spoke(text: string): boolean;
|
|
1747
1760
|
/** 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";
|
|
@@ -9778,6 +9804,9 @@ var KIND_HINT = {
|
|
|
9778
9804
|
bridge: `neutral one-moment cues while the answer is prepared (like "let me see\u2026", "one sec\u2026") \u2014 never the start of a statement or opinion ("the thing is", "well actually", "here's the deal")`,
|
|
9779
9805
|
phatic: 'greetings, thanks and yes/no openers a person starts a turn with (like "hi", "thanks", "how are you")'
|
|
9780
9806
|
};
|
|
9807
|
+
function personaHint(gender) {
|
|
9808
|
+
return gender === "female" ? 'You are a woman: when you refer to yourself, use feminine grammatical forms (e.g. Hebrew "\u05D1\u05D5\u05D3\u05E7\u05EA", not "\u05D1\u05D5\u05D3\u05E7").' : gender === "male" ? 'You are a man: when you refer to yourself, use masculine grammatical forms (e.g. Hebrew "\u05D1\u05D5\u05D3\u05E7", not "\u05D1\u05D5\u05D3\u05E7\u05EA").' : "";
|
|
9809
|
+
}
|
|
9781
9810
|
function fastBankGenerator(ai, model, perKind = 12) {
|
|
9782
9811
|
return async (lang, avoid, signal) => {
|
|
9783
9812
|
const name = languageName(lang);
|
|
@@ -12534,14 +12563,19 @@ init_logging();
|
|
|
12534
12563
|
var log26 = forComponent("Progress");
|
|
12535
12564
|
var HE_RESULT_CLAIM = /(?:^|\s)(?:מצאתי|סיימתי|בוצע|הנה|אין)(?=\s|$|[.,!…])/u;
|
|
12536
12565
|
var TOPICS = [
|
|
12566
|
+
[/toolsearch|^mcp__.*__(list_commands|call_info)$/, null],
|
|
12567
|
+
// tool plumbing — no line (and no generated one)
|
|
12537
12568
|
[/kanban|board|card|\bkb\b|list_cards/, "board"],
|
|
12538
12569
|
[/mail|gmail|inbox/, "mail"],
|
|
12539
12570
|
[/calendar|event|schedule/, "calendar"],
|
|
12540
12571
|
[/memory|recall|remember/, "memory"],
|
|
12541
|
-
[/web_?search|
|
|
12572
|
+
[/web_?search|search_web|google/, "websearch"],
|
|
12573
|
+
[/fetch|read_page|get_page|page_text|navigate|url|history/, "page"],
|
|
12574
|
+
[/click|type|press_key|scroll|screenshot|tab|browser|highlight|point|wait_for|upload/, "browser"],
|
|
12542
12575
|
[/grep|glob|search|find|lookup|quicklook/, "search"],
|
|
12576
|
+
[/^(agent|task)$|subagent|delegate/, "delegate"],
|
|
12543
12577
|
[/edit|write|patch|create|update|save|delete|move/, "write"],
|
|
12544
|
-
[/shell|bash|exec|run|command|terminal/, "run"],
|
|
12578
|
+
[/shell|bash|exec|run|command|terminal|eval/, "run"],
|
|
12545
12579
|
[/read|open|view|cat|look|get|list|ls/, "read"]
|
|
12546
12580
|
];
|
|
12547
12581
|
var PROGRESS_TEMPLATES = {
|
|
@@ -12550,27 +12584,62 @@ var PROGRESS_TEMPLATES = {
|
|
|
12550
12584
|
mail: ["checking the mail\u2026", "going through the inbox\u2026"],
|
|
12551
12585
|
calendar: ["checking the calendar\u2026", "looking at the schedule\u2026"],
|
|
12552
12586
|
memory: ["checking my notes\u2026", "looking back\u2026"],
|
|
12553
|
-
|
|
12587
|
+
websearch: ["searching\u2026", "searching the web\u2026"],
|
|
12588
|
+
page: ["reading the page\u2026", "going through the page\u2026"],
|
|
12589
|
+
browser: ["working in the browser\u2026", "on the page now\u2026"],
|
|
12554
12590
|
search: ["searching\u2026", "still looking\u2026"],
|
|
12591
|
+
delegate: ["working on it\u2026", "still on it\u2026"],
|
|
12555
12592
|
write: ["making the change\u2026", "writing it down\u2026"],
|
|
12556
12593
|
run: ["running it\u2026", "still running\u2026"],
|
|
12557
12594
|
read: ["reading it\u2026", "going through it\u2026"]
|
|
12558
12595
|
},
|
|
12559
12596
|
he: {
|
|
12560
|
-
// plural present: gender-neutral for a voice of either gender
|
|
12561
12597
|
board: ["\u05D1\u05D5\u05D3\u05E7\u05D9\u05DD \u05D1\u05DC\u05D5\u05D7\u2026", "\u05DE\u05E1\u05EA\u05DB\u05DC\u05D9\u05DD \u05E2\u05DC \u05D4\u05DB\u05E8\u05D8\u05D9\u05E1\u05D9\u05DD\u2026"],
|
|
12562
12598
|
mail: ["\u05D1\u05D5\u05D3\u05E7\u05D9\u05DD \u05D0\u05EA \u05D4\u05DE\u05D9\u05D9\u05DC\u2026", "\u05E2\u05D5\u05D1\u05E8\u05D9\u05DD \u05E2\u05DC \u05D4\u05D3\u05D5\u05D0\u05E8\u2026"],
|
|
12563
12599
|
calendar: ["\u05D1\u05D5\u05D3\u05E7\u05D9\u05DD \u05D1\u05D9\u05D5\u05DE\u05DF\u2026", "\u05DE\u05E1\u05EA\u05DB\u05DC\u05D9\u05DD \u05D1\u05DC\u05D5\u05F4\u05D6\u2026"],
|
|
12564
12600
|
memory: ["\u05D1\u05D5\u05D3\u05E7\u05D9\u05DD \u05D1\u05E8\u05E9\u05D9\u05DE\u05D5\u05EA\u2026", "\u05DE\u05D7\u05E4\u05E9\u05D9\u05DD \u05D1\u05D6\u05D9\u05DB\u05E8\u05D5\u05DF\u2026"],
|
|
12565
|
-
|
|
12601
|
+
websearch: ["\u05DE\u05D7\u05E4\u05E9\u05D9\u05DD\u2026", "\u05DE\u05D7\u05E4\u05E9\u05D9\u05DD \u05D1\u05E8\u05E9\u05EA\u2026"],
|
|
12602
|
+
page: ["\u05E7\u05D5\u05E8\u05D0\u05D9\u05DD \u05D0\u05EA \u05D4\u05D3\u05E3\u2026", "\u05E2\u05D5\u05D1\u05E8\u05D9\u05DD \u05E2\u05DC \u05D4\u05D3\u05E3\u2026"],
|
|
12603
|
+
browser: ["\u05E2\u05D5\u05D1\u05D3\u05D9\u05DD \u05D1\u05D3\u05E4\u05D3\u05E4\u05DF\u2026", "\u05E2\u05DC \u05D4\u05D3\u05E3 \u05E2\u05DB\u05E9\u05D9\u05D5\u2026"],
|
|
12566
12604
|
search: ["\u05DE\u05D7\u05E4\u05E9\u05D9\u05DD\u2026", "\u05E2\u05D3\u05D9\u05D9\u05DF \u05DE\u05D7\u05E4\u05E9\u05D9\u05DD\u2026"],
|
|
12605
|
+
delegate: ["\u05E2\u05D5\u05D1\u05D3\u05D9\u05DD \u05E2\u05DC \u05D6\u05D4\u2026", "\u05E2\u05D3\u05D9\u05D9\u05DF \u05E2\u05DC \u05D6\u05D4\u2026"],
|
|
12567
12606
|
write: ["\u05DE\u05D1\u05E6\u05E2\u05D9\u05DD \u05D0\u05EA \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9\u2026", "\u05DB\u05D5\u05EA\u05D1\u05D9\u05DD \u05D0\u05EA \u05D6\u05D4\u2026"],
|
|
12568
12607
|
run: ["\u05DE\u05E8\u05D9\u05E6\u05D9\u05DD\u2026", "\u05E2\u05D3\u05D9\u05D9\u05DF \u05E8\u05E5\u2026"],
|
|
12569
12608
|
read: ["\u05E7\u05D5\u05E8\u05D0\u05D9\u05DD\u2026", "\u05E2\u05D5\u05D1\u05E8\u05D9\u05DD \u05E2\u05DC \u05D6\u05D4\u2026"]
|
|
12609
|
+
},
|
|
12610
|
+
"he-f": {
|
|
12611
|
+
board: ["\u05D1\u05D5\u05D3\u05E7\u05EA \u05D1\u05DC\u05D5\u05D7\u2026", "\u05DE\u05E1\u05EA\u05DB\u05DC\u05EA \u05E2\u05DC \u05D4\u05DB\u05E8\u05D8\u05D9\u05E1\u05D9\u05DD\u2026"],
|
|
12612
|
+
mail: ["\u05D1\u05D5\u05D3\u05E7\u05EA \u05D0\u05EA \u05D4\u05DE\u05D9\u05D9\u05DC\u2026", "\u05E2\u05D5\u05D1\u05E8\u05EA \u05E2\u05DC \u05D4\u05D3\u05D5\u05D0\u05E8\u2026"],
|
|
12613
|
+
calendar: ["\u05D1\u05D5\u05D3\u05E7\u05EA \u05D1\u05D9\u05D5\u05DE\u05DF\u2026", "\u05DE\u05E1\u05EA\u05DB\u05DC\u05EA \u05D1\u05DC\u05D5\u05F4\u05D6\u2026"],
|
|
12614
|
+
memory: ["\u05D1\u05D5\u05D3\u05E7\u05EA \u05D1\u05E8\u05E9\u05D9\u05DE\u05D5\u05EA\u2026", "\u05DE\u05D7\u05E4\u05E9\u05EA \u05D1\u05D6\u05D9\u05DB\u05E8\u05D5\u05DF\u2026"],
|
|
12615
|
+
websearch: ["\u05DE\u05D7\u05E4\u05E9\u05EA\u2026", "\u05DE\u05D7\u05E4\u05E9\u05EA \u05D1\u05E8\u05E9\u05EA\u2026"],
|
|
12616
|
+
page: ["\u05E7\u05D5\u05E8\u05D0\u05EA \u05D0\u05EA \u05D4\u05D3\u05E3\u2026", "\u05E2\u05D5\u05D1\u05E8\u05EA \u05E2\u05DC \u05D4\u05D3\u05E3\u2026"],
|
|
12617
|
+
browser: ["\u05E2\u05D5\u05D1\u05D3\u05EA \u05D1\u05D3\u05E4\u05D3\u05E4\u05DF\u2026", "\u05E2\u05DC \u05D4\u05D3\u05E3 \u05E2\u05DB\u05E9\u05D9\u05D5\u2026"],
|
|
12618
|
+
search: ["\u05DE\u05D7\u05E4\u05E9\u05EA\u2026", "\u05E2\u05D3\u05D9\u05D9\u05DF \u05DE\u05D7\u05E4\u05E9\u05EA\u2026"],
|
|
12619
|
+
delegate: ["\u05E2\u05D5\u05D1\u05D3\u05EA \u05E2\u05DC \u05D6\u05D4\u2026", "\u05E2\u05D3\u05D9\u05D9\u05DF \u05E2\u05DC \u05D6\u05D4\u2026"],
|
|
12620
|
+
write: ["\u05DE\u05D1\u05E6\u05E2\u05EA \u05D0\u05EA \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9\u2026", "\u05DB\u05D5\u05EA\u05D1\u05EA \u05D0\u05EA \u05D6\u05D4\u2026"],
|
|
12621
|
+
run: ["\u05DE\u05E8\u05D9\u05E6\u05D4\u2026", "\u05E2\u05D3\u05D9\u05D9\u05DF \u05E8\u05E5\u2026"],
|
|
12622
|
+
read: ["\u05E7\u05D5\u05E8\u05D0\u05EA\u2026", "\u05E2\u05D5\u05D1\u05E8\u05EA \u05E2\u05DC \u05D6\u05D4\u2026"]
|
|
12623
|
+
},
|
|
12624
|
+
"he-m": {
|
|
12625
|
+
board: ["\u05D1\u05D5\u05D3\u05E7 \u05D1\u05DC\u05D5\u05D7\u2026", "\u05DE\u05E1\u05EA\u05DB\u05DC \u05E2\u05DC \u05D4\u05DB\u05E8\u05D8\u05D9\u05E1\u05D9\u05DD\u2026"],
|
|
12626
|
+
mail: ["\u05D1\u05D5\u05D3\u05E7 \u05D0\u05EA \u05D4\u05DE\u05D9\u05D9\u05DC\u2026", "\u05E2\u05D5\u05D1\u05E8 \u05E2\u05DC \u05D4\u05D3\u05D5\u05D0\u05E8\u2026"],
|
|
12627
|
+
calendar: ["\u05D1\u05D5\u05D3\u05E7 \u05D1\u05D9\u05D5\u05DE\u05DF\u2026", "\u05DE\u05E1\u05EA\u05DB\u05DC \u05D1\u05DC\u05D5\u05F4\u05D6\u2026"],
|
|
12628
|
+
memory: ["\u05D1\u05D5\u05D3\u05E7 \u05D1\u05E8\u05E9\u05D9\u05DE\u05D5\u05EA\u2026", "\u05DE\u05D7\u05E4\u05E9 \u05D1\u05D6\u05D9\u05DB\u05E8\u05D5\u05DF\u2026"],
|
|
12629
|
+
websearch: ["\u05DE\u05D7\u05E4\u05E9\u2026", "\u05DE\u05D7\u05E4\u05E9 \u05D1\u05E8\u05E9\u05EA\u2026"],
|
|
12630
|
+
page: ["\u05E7\u05D5\u05E8\u05D0 \u05D0\u05EA \u05D4\u05D3\u05E3\u2026", "\u05E2\u05D5\u05D1\u05E8 \u05E2\u05DC \u05D4\u05D3\u05E3\u2026"],
|
|
12631
|
+
browser: ["\u05E2\u05D5\u05D1\u05D3 \u05D1\u05D3\u05E4\u05D3\u05E4\u05DF\u2026", "\u05E2\u05DC \u05D4\u05D3\u05E3 \u05E2\u05DB\u05E9\u05D9\u05D5\u2026"],
|
|
12632
|
+
search: ["\u05DE\u05D7\u05E4\u05E9\u2026", "\u05E2\u05D3\u05D9\u05D9\u05DF \u05DE\u05D7\u05E4\u05E9\u2026"],
|
|
12633
|
+
delegate: ["\u05E2\u05D5\u05D1\u05D3 \u05E2\u05DC \u05D6\u05D4\u2026", "\u05E2\u05D3\u05D9\u05D9\u05DF \u05E2\u05DC \u05D6\u05D4\u2026"],
|
|
12634
|
+
write: ["\u05DE\u05D1\u05E6\u05E2 \u05D0\u05EA \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9\u2026", "\u05DB\u05D5\u05EA\u05D1 \u05D0\u05EA \u05D6\u05D4\u2026"],
|
|
12635
|
+
run: ["\u05DE\u05E8\u05D9\u05E5\u2026", "\u05E2\u05D3\u05D9\u05D9\u05DF \u05E8\u05E5\u2026"],
|
|
12636
|
+
read: ["\u05E7\u05D5\u05E8\u05D0\u2026", "\u05E2\u05D5\u05D1\u05E8 \u05E2\u05DC \u05D6\u05D4\u2026"]
|
|
12570
12637
|
}
|
|
12571
12638
|
};
|
|
12572
12639
|
var ProgressOptions = class {
|
|
12573
12640
|
templates = PROGRESS_TEMPLATES;
|
|
12641
|
+
/** The voice's gender: picks the gendered table (`${lang}-f`/`-m`) when one exists. */
|
|
12642
|
+
gender = "";
|
|
12574
12643
|
/** Fast-model fallback for a tool with no template (fastProgressGenerator). Absent → silence. */
|
|
12575
12644
|
generate;
|
|
12576
12645
|
generateBudgetMs = 800;
|
|
@@ -12619,8 +12688,11 @@ var Progress = class {
|
|
|
12619
12688
|
async line(tool, args, lang) {
|
|
12620
12689
|
if (this.streamed) return "";
|
|
12621
12690
|
const name = tool.toLowerCase();
|
|
12622
|
-
const
|
|
12623
|
-
|
|
12691
|
+
const hit = TOPICS.find(([re]) => re.test(name));
|
|
12692
|
+
if (hit && hit[1] === null) return "";
|
|
12693
|
+
const topic = hit?.[1];
|
|
12694
|
+
const g = this.o.gender ? this.o.templates[`${lang}-${this.o.gender[0]}`] : void 0;
|
|
12695
|
+
const pool = topic ? (g ?? this.o.templates[lang])?.[topic] ?? [] : [];
|
|
12624
12696
|
const fresh = pool.find((l2) => !this.said.has(norm3(l2)));
|
|
12625
12697
|
if (fresh) return fresh;
|
|
12626
12698
|
if (!this.o.generate) return "";
|
|
@@ -12641,9 +12713,9 @@ var Progress = class {
|
|
|
12641
12713
|
return l;
|
|
12642
12714
|
}
|
|
12643
12715
|
};
|
|
12644
|
-
function fastProgressGenerator(ai, model) {
|
|
12716
|
+
function fastProgressGenerator(ai, model, gender) {
|
|
12645
12717
|
return async (tool, hint, lang, signal) => {
|
|
12646
|
-
const prompt = `An assistant on a live voice call is running the tool "${tool}"${hint ? ` (about: "${hint}")` : ""}. Write ONE spoken line of 2-5 words, in ${languageName(lang)}, saying what it is doing right now (like "checking the board\u2026"). Never state a result or a finding. Output only the line.`;
|
|
12718
|
+
const prompt = `An assistant on a live voice call is running the tool "${tool}"${hint ? ` (about: "${hint}")` : ""}. Write ONE spoken line of 2-5 words, in ${languageName(lang)}, saying what it is doing right now (like "checking the board\u2026"). Never state a result or a finding. ${personaHint(gender)} Output only the line.`;
|
|
12647
12719
|
const reasoning = /gpt-oss/.test(model) ? { providerOptions: { reasoning_effort: "low" } } : {};
|
|
12648
12720
|
const r = await ai.chat({ model, messages: [{ role: "user", content: prompt }], stream: false, signal, maxTokens: 150, ...reasoning });
|
|
12649
12721
|
return r.content ?? "";
|
|
@@ -13230,14 +13302,14 @@ var KIND_HINT2 = {
|
|
|
13230
13302
|
bridge: 'a neutral one-moment cue while the answer is prepared ("let me see\u2026", "one sec\u2026") \u2014 never the start of a statement or opinion ("the thing is", "well actually")'
|
|
13231
13303
|
};
|
|
13232
13304
|
var REACT_HINT = 'a short reaction to their LAST words instead: feeling ("oh no", "ha, nice", "ugh"), surprise ("wait, really?", "huh"), a light laugh if they joke or laugh ("ha!"), or an echo of their key word ("the deploy?") \u2014 still never asks for an answer or takes the turn; if nothing there deserves a reaction, a plain "mm-hm"';
|
|
13233
|
-
function fastLineGenerator(ai, model) {
|
|
13305
|
+
function fastLineGenerator(ai, model, gender) {
|
|
13234
13306
|
return async (c, signal) => {
|
|
13235
13307
|
const prompt = `You voice the tiny side-sounds of a live spoken conversation. Write ONE line of 1-5 words: ${KIND_HINT2[c.kind]}.
|
|
13236
13308
|
` + (c.react ? `Here the line may be ${REACT_HINT}.
|
|
13237
13309
|
` : "") + `The user just said: "${c.heard}"
|
|
13238
13310
|
The assistant is: ${c.state}.
|
|
13239
13311
|
` + (c.avoid.length ? `Do not reuse any of: ${c.avoid.map((a) => `"${a}"`).join(", ")}.
|
|
13240
|
-
` : "") + `React to their actual words, casually, in ${languageName(c.lang)}. Output only the line.`;
|
|
13312
|
+
` : "") + `React to their actual words, casually, in ${languageName(c.lang)}. ${personaHint(gender)} Output only the line.`;
|
|
13241
13313
|
const reasoning = /gpt-oss/.test(model) ? { providerOptions: { reasoning_effort: "low" } } : {};
|
|
13242
13314
|
const r = await ai.chat({ model, messages: [{ role: "user", content: prompt }], stream: false, signal, maxTokens: 150, ...reasoning });
|
|
13243
13315
|
return r.content ?? "";
|
|
@@ -13275,6 +13347,8 @@ var VoiceCallOptions = class {
|
|
|
13275
13347
|
bankCacheDir;
|
|
13276
13348
|
/** The host STT's language (BCP-47) — the starting language; each turn's own words still decide. */
|
|
13277
13349
|
lang;
|
|
13350
|
+
/** The voice's gender: generated fill/progress lines speak of themselves in it (Hebrew templates too). '' = neutral. */
|
|
13351
|
+
gender = "";
|
|
13278
13352
|
aec = false;
|
|
13279
13353
|
mode = "normal";
|
|
13280
13354
|
gate = {};
|
|
@@ -13284,6 +13358,8 @@ var VoiceCallOptions = class {
|
|
|
13284
13358
|
onMetric = () => {
|
|
13285
13359
|
};
|
|
13286
13360
|
now = () => performance.now();
|
|
13361
|
+
/** An aside (aside()) needs this long since the last one — a cue answered every time sounds scripted. */
|
|
13362
|
+
asideGapMs = 8e3;
|
|
13287
13363
|
};
|
|
13288
13364
|
var VoiceCall = class {
|
|
13289
13365
|
constructor(options) {
|
|
@@ -13296,7 +13372,7 @@ var VoiceCall = class {
|
|
|
13296
13372
|
...ai ? {
|
|
13297
13373
|
banks: new ChannelBanks({ generate: fastBankGenerator(ai, o.fastModel), ...o.bankCacheDir ? { cacheDir: o.bankCacheDir } : {} }),
|
|
13298
13374
|
decide: channelDecide(ai),
|
|
13299
|
-
generate: fastLineGenerator(ai, o.fastModel)
|
|
13375
|
+
generate: fastLineGenerator(ai, o.fastModel, o.gender)
|
|
13300
13376
|
} : {},
|
|
13301
13377
|
mode: o.mode,
|
|
13302
13378
|
aec: o.aec,
|
|
@@ -13310,7 +13386,7 @@ var VoiceCall = class {
|
|
|
13310
13386
|
cancel: () => o.cancel(),
|
|
13311
13387
|
now: o.now
|
|
13312
13388
|
});
|
|
13313
|
-
this.progress = new Progress({ ...ai ? { generate: fastProgressGenerator(ai, o.fastModel) } : {}, now: o.now, ...o.progress });
|
|
13389
|
+
this.progress = new Progress({ ...ai ? { generate: fastProgressGenerator(ai, o.fastModel, o.gender) } : {}, gender: o.gender, now: o.now, ...o.progress });
|
|
13314
13390
|
this.judge = new OverlapJudge({ ...ai ? { model: overlapModelFor(ai) } : {}, now: o.now });
|
|
13315
13391
|
this.gate = new TurnGate({
|
|
13316
13392
|
now: o.now,
|
|
@@ -13327,6 +13403,7 @@ var VoiceCall = class {
|
|
|
13327
13403
|
judge;
|
|
13328
13404
|
cur;
|
|
13329
13405
|
lang = null;
|
|
13406
|
+
lastAside = { text: "", at: -Infinity };
|
|
13330
13407
|
lastAudibleAt = -Infinity;
|
|
13331
13408
|
firstFinalAt = null;
|
|
13332
13409
|
// the first final of the turn being formed (hold/merge)
|
|
@@ -13435,6 +13512,19 @@ var VoiceCall = class {
|
|
|
13435
13512
|
if (d.verdict === "cut") this.barge();
|
|
13436
13513
|
return d.verdict;
|
|
13437
13514
|
}
|
|
13515
|
+
/** The fill channel's spoken aside for an overlap judged 'keep' ("yeah" → "Oh yeah, definitely."): the host plays it
|
|
13516
|
+
* while the reply is held, then resumes the same reply (bod-voice decideOverlap's aside). ≤4 canned words, never a
|
|
13517
|
+
* claim, the cue's language; null = stay quiet (a plain listener cue, too soon after the last, or no line). It is a
|
|
13518
|
+
* fill line: never MAIN history. */
|
|
13519
|
+
aside(text) {
|
|
13520
|
+
const now3 = this.o.now();
|
|
13521
|
+
if (now3 - this.lastAside.at < this.o.asideGapMs) return null;
|
|
13522
|
+
const line = overlapAside(text, this.lang, this.lastAside.text);
|
|
13523
|
+
if (!line) return null;
|
|
13524
|
+
this.lastAside = { text: line, at: now3 };
|
|
13525
|
+
this.o.onMetric({ name: "fill", kind: "aside", text: line, lang: this.lang });
|
|
13526
|
+
return line;
|
|
13527
|
+
}
|
|
13438
13528
|
/** Did the last barge cut OUR fill line `text`? (hosts strip it from the cut reply — it is not MAIN's speech) */
|
|
13439
13529
|
spoke(text) {
|
|
13440
13530
|
return this.fill.spoke(text);
|