@livx.cc/agentx 0.99.119 → 0.99.121
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 +1 -1
- package/dist/cli.js +55 -14
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +55 -14
- package/dist/index.js.map +1 -1
- package/dist/{secondChannel-DepBV0Zv.d.ts → secondChannel-D33Wvruo.d.ts} +8 -1
- package/package.json +2 -2
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, G as Gender, 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-D33Wvruo.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-D33Wvruo.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';
|
|
@@ -1684,6 +1684,8 @@ interface TurnTimeline {
|
|
|
1684
1684
|
mainText?: number;
|
|
1685
1685
|
/** MAIN's first audio started (the host's player). */
|
|
1686
1686
|
mainAudio?: number;
|
|
1687
|
+
/** false: a closer/acknowledgement ("Okay.", "תודה") — no answer due, no fill; its first sound is not a latency sample. */
|
|
1688
|
+
due?: false;
|
|
1687
1689
|
/** false: the host gave no last-word time — the anchor is the final's arrival. */
|
|
1688
1690
|
lastWord: boolean;
|
|
1689
1691
|
/** How the turn ended: answered = MAIN audio played · cut = barged · replaced = a fuller re-final took it · silent = no MAIN audio. */
|
package/dist/index.js
CHANGED
|
@@ -9695,8 +9695,17 @@ function isPhatic(text, bank) {
|
|
|
9695
9695
|
return !!q && (t === q || t.startsWith(q + " "));
|
|
9696
9696
|
});
|
|
9697
9697
|
}
|
|
9698
|
+
var CLOSER = new Set("ok okay k cool great nice perfect awesome amazing lovely excellent alright fine good thanks thank thx you so much very a lot bye goodbye cheers later see ya night got it i that that's thats is it's its all for now sounds understood noted makes sense oh ah wow right then just \u05EA\u05D5\u05D3\u05D4 \u05E8\u05D1\u05D4 \u05E1\u05D1\u05D1\u05D4 \u05D0\u05D5\u05E7\u05D9\u05D9 \u05D0\u05D5\u05E7\u05D9 \u05D1\u05E1\u05D3\u05E8 \u05D9\u05D5\u05E4\u05D9 \u05D0\u05D7\u05DC\u05D4 \u05DE\u05E2\u05D5\u05DC\u05D4 \u05DE\u05E6\u05D5\u05D9\u05DF \u05DE\u05D2\u05E0\u05D9\u05D1 \u05E0\u05D4\u05D3\u05E8 \u05D1\u05D9\u05D9 \u05DC\u05D4\u05EA\u05E8\u05D0\u05D5\u05EA \u05D8\u05D5\u05D1 \u05D6\u05D4\u05D5 \u05D6\u05D4 \u05D4\u05DB\u05DC \u05D1\u05D9\u05E0\u05EA\u05D9\u05D9\u05DD \u05D4\u05D1\u05E0\u05EA\u05D9 \u05DE\u05DE\u05E9 \u05DC\u05DA \u05D0\u05D6".split(" "));
|
|
9699
|
+
function turnIntent(text) {
|
|
9700
|
+
const t = text.trim();
|
|
9701
|
+
if (/\?[\s"')\]]*$/.test(t)) return "ask";
|
|
9702
|
+
const w = norm3(t).split(" ").filter(Boolean);
|
|
9703
|
+
const asks = requestOpener(t) && !/^ת/.test(lead(t)[0] ?? "") || pendingQuestion(t);
|
|
9704
|
+
if (w.length && w.length <= 8 && w.every((x) => CLOSER.has(x)) && !asks) return "closer";
|
|
9705
|
+
return asks || requestOpener(t) ? "ask" : "say";
|
|
9706
|
+
}
|
|
9698
9707
|
var SKIP = new Set("um uh uhm erm hmm mm oh ok okay so no yes yeah yep well hey hi and but right alright actually like now then wait hang on me speaker \u05D0\u05D5\u05E7\u05D9\u05D9 \u05D8\u05D5\u05D1 \u05D0\u05D6 \u05DC\u05D0 \u05DB\u05DF \u05E8\u05D2\u05E2 \u05D0\u05D4 \u05D0\u05DE \u05D9\u05D0\u05DC\u05DC\u05D4 \u05D5".split(" "));
|
|
9699
|
-
var ASK = "what whats how why where when who which whose is are was were do does did can could would will should shall have has may isnt arent dont doesnt didnt cant wont check open show tell find search look send run go lets please take give make write explain select focus order try compare list use set activate highlight outline capture start stop read play call book create add remove delete put type click close switch help get summarize translate mark keep remind schedule \u05DE\u05D4 \u05D0\u05D9\u05DA \u05DC\u05DE\u05D4 \u05D0\u05D9\u05E4\u05D4 \u05DE\u05EA\u05D9 \u05DE\u05D9 \u05D4\u05D0\u05DD \u05DB\u05DE\u05D4 \u05EA\u05DF \u05EA\u05E0\u05D9 \u05EA\u05D2\u05D9\u05D3 \u05EA\u05D2\u05D9\u05D3\u05D9 \u05D1\u05D5\u05D0 \u05D1\u05D5\u05D0\u05D9".split(" ");
|
|
9708
|
+
var ASK = "what whats how why where when who which whose is are was were do does did can could would will should shall have has may isnt arent dont doesnt didnt cant wont check open show tell find search look send run go lets please take give make write explain select focus order try compare list use set activate highlight outline capture start stop read play call book create add remove delete put type click close switch help get name recommend suggest summarize translate mark keep remind schedule \u05DE\u05D4 \u05D0\u05D9\u05DA \u05DC\u05DE\u05D4 \u05D0\u05D9\u05E4\u05D4 \u05DE\u05EA\u05D9 \u05DE\u05D9 \u05D4\u05D0\u05DD \u05DB\u05DE\u05D4 \u05EA\u05DF \u05EA\u05E0\u05D9 \u05EA\u05D2\u05D9\u05D3 \u05EA\u05D2\u05D9\u05D3\u05D9 \u05D1\u05D5\u05D0 \u05D1\u05D5\u05D0\u05D9".split(" ");
|
|
9700
9709
|
var WANT = /^(i (want|need|would like|d like|wanna)|אני (רוצה|צריך|צריכה|מבקש|מבקשת))(\s|$)/u;
|
|
9701
9710
|
var lead = (text) => {
|
|
9702
9711
|
const w = text.toLowerCase().replace(/[^\p{L}\p{N}\s]+/gu, "").split(/\s+/).filter(Boolean);
|
|
@@ -12832,6 +12841,9 @@ var SecondChannelOptions = class {
|
|
|
12832
12841
|
/** Duplex v3 (§3 first sound): a bridge skips the decider (the veto stays for backchannels/fillers) and speaks a
|
|
12833
12842
|
* canned line at once; a generated one is started at dispatch and used only if it already landed. */
|
|
12834
12843
|
instantBridge = false;
|
|
12844
|
+
/** Duplex v3 §3 late bridge: a turn that expects an answer (not a closer) and got no bridge yet gets one canned bridge
|
|
12845
|
+
* this long after the user's last word if channel-1 is still silent — the short turns the 0ms rule skips ("Hi"). 0 = off. */
|
|
12846
|
+
lateBridgeMs = 0;
|
|
12835
12847
|
/** No new interim for this long → a pause (hosts may also call onPause). */
|
|
12836
12848
|
fillerPauseMs = 700;
|
|
12837
12849
|
fillerMinWords = 4;
|
|
@@ -12895,6 +12907,11 @@ var SecondChannel = class {
|
|
|
12895
12907
|
pauseTimer = null;
|
|
12896
12908
|
bcTimer = null;
|
|
12897
12909
|
bridgeTimer = null;
|
|
12910
|
+
lateTimer = null;
|
|
12911
|
+
late = false;
|
|
12912
|
+
// the bridge moment being considered is the late one (no length rule)
|
|
12913
|
+
lastWordAgo = 0;
|
|
12914
|
+
// the dispatched turn: ms since the user's last word (anchors lateBridgeMs)
|
|
12898
12915
|
lastAt = -Infinity;
|
|
12899
12916
|
lastKind = null;
|
|
12900
12917
|
live = null;
|
|
@@ -13013,9 +13030,11 @@ var SecondChannel = class {
|
|
|
13013
13030
|
if (s === this.main) return;
|
|
13014
13031
|
this.main = s;
|
|
13015
13032
|
if (s === "first_audio" || s === "speaking") this.live = null;
|
|
13016
|
-
if (s !== "queued" && s !== "thinking"
|
|
13017
|
-
|
|
13018
|
-
|
|
13033
|
+
if (s !== "queued" && s !== "thinking") {
|
|
13034
|
+
for (const k of ["bridgeTimer", "lateTimer"]) if (this[k]) {
|
|
13035
|
+
clearTimeout(this[k]);
|
|
13036
|
+
this[k] = null;
|
|
13037
|
+
}
|
|
13019
13038
|
}
|
|
13020
13039
|
if (s === "idle") {
|
|
13021
13040
|
this.heard = "";
|
|
@@ -13036,7 +13055,7 @@ var SecondChannel = class {
|
|
|
13036
13055
|
this.userSpeaking = false;
|
|
13037
13056
|
this.bridged = false;
|
|
13038
13057
|
if (this.lastKind === "bridge") this.lastKind = null;
|
|
13039
|
-
for (const k of ["pauseTimer", "bcTimer", "bridgeTimer"]) {
|
|
13058
|
+
for (const k of ["pauseTimer", "bcTimer", "bridgeTimer", "lateTimer"]) {
|
|
13040
13059
|
if (this[k]) clearTimeout(this[k]);
|
|
13041
13060
|
this[k] = null;
|
|
13042
13061
|
}
|
|
@@ -13047,11 +13066,21 @@ var SecondChannel = class {
|
|
|
13047
13066
|
void this.consider("working");
|
|
13048
13067
|
}, wait);
|
|
13049
13068
|
else void this.consider("working");
|
|
13069
|
+
const late = this.o.lateBridgeMs - this.lastWordAgo;
|
|
13070
|
+
if (this.o.lateBridgeMs > 0) this.lateTimer = setTimeout(() => {
|
|
13071
|
+
this.lateTimer = null;
|
|
13072
|
+
if (this.bridged || this.busy || turnIntent(this.heard) === "closer" || this.blocked("bridge")) return;
|
|
13073
|
+
this.late = true;
|
|
13074
|
+
void this.consider("working").finally(() => {
|
|
13075
|
+
this.late = false;
|
|
13076
|
+
});
|
|
13077
|
+
}, Math.max(late, wait + 1));
|
|
13050
13078
|
}
|
|
13051
13079
|
}
|
|
13052
13080
|
/** The user's final line was dispatched to the main agent (its words are the bridge's micro-context). */
|
|
13053
|
-
onUserTurn(text) {
|
|
13081
|
+
onUserTurn(text, lastWordAgoMs = 0) {
|
|
13054
13082
|
this.heard = text.trim();
|
|
13083
|
+
this.lastWordAgo = Math.max(0, lastWordAgoMs);
|
|
13055
13084
|
this.floorWords = this.carried + words2(this.heard).length;
|
|
13056
13085
|
this.lastUser = this.heard;
|
|
13057
13086
|
this.detect(this.heard);
|
|
@@ -13119,12 +13148,19 @@ var SecondChannel = class {
|
|
|
13119
13148
|
}
|
|
13120
13149
|
/** Why this turn gets no bridge by rule ('' = it may) — language, a quick/phatic turn, or blocked(). */
|
|
13121
13150
|
bridgeBlock() {
|
|
13122
|
-
const w = words2(this.heard);
|
|
13151
|
+
const w = words2(this.heard), intent = turnIntent(this.heard);
|
|
13123
13152
|
if (!this.lang) return "language unknown";
|
|
13124
|
-
if (
|
|
13125
|
-
if (
|
|
13153
|
+
if (intent === "closer") return "no answer due";
|
|
13154
|
+
if (this.late) return this.blocked("bridge");
|
|
13155
|
+
const why = intent === "ask" ? w.length <= 6 && isPhatic(this.heard, this.bank) ? "phatic" : "" : this.shortTurn(w.length);
|
|
13156
|
+
if (why) return this.o.lateBridgeMs > 0 ? `${why} (late bridge armed)` : why;
|
|
13126
13157
|
return this.blocked("bridge");
|
|
13127
13158
|
}
|
|
13159
|
+
shortTurn(n) {
|
|
13160
|
+
if (n <= 3 || n <= 6 && isPhatic(this.heard, this.bank)) return n <= 3 ? "quick turn" : "phatic";
|
|
13161
|
+
if (n < this.o.bridgeMinWords) return `under ${this.o.bridgeMinWords} words`;
|
|
13162
|
+
return "";
|
|
13163
|
+
}
|
|
13128
13164
|
bcTimes = [];
|
|
13129
13165
|
capped() {
|
|
13130
13166
|
if (!this.o.maxPerWindow) return false;
|
|
@@ -13136,8 +13172,9 @@ var SecondChannel = class {
|
|
|
13136
13172
|
rule(trigger, pauseMs = 0, breath = false, cue = null) {
|
|
13137
13173
|
const w = words2(this.heard);
|
|
13138
13174
|
if (!this.lang) return "silence";
|
|
13175
|
+
if (trigger === "working") return this.bridgeBlock() ? "silence" : "bridge";
|
|
13139
13176
|
if (w.length <= 3 || w.length <= 6 && isPhatic(this.heard, this.bank)) return "silence";
|
|
13140
|
-
const k = trigger === "interim" ? this.backchannelMoment(w.length, breath) && (!this.o.anticipate || !this.plan || !silentTurn(this.plan) && (!!cue || !this.o.cueOnly && this.plan.density !== "low")) ? "backchannel" : null : trigger === "pause" ? pauseMs >= this.o.fillerPauseMs && w.length >= this.o.fillerMinWords ? "filler" : null :
|
|
13177
|
+
const k = trigger === "interim" ? this.backchannelMoment(w.length, breath) && (!this.o.anticipate || !this.plan || !silentTurn(this.plan) && (!!cue || !this.o.cueOnly && this.plan.density !== "low")) ? "backchannel" : null : trigger === "pause" ? pauseMs >= this.o.fillerPauseMs && w.length >= this.o.fillerMinWords ? "filler" : null : null;
|
|
13141
13178
|
return k && this.allowed(k) ? k : "silence";
|
|
13142
13179
|
}
|
|
13143
13180
|
/** Plan (or, with `heard`, revise) the backchannels of the user's turn — async, never on the hot path. */
|
|
@@ -13404,8 +13441,11 @@ var VoiceCall = class {
|
|
|
13404
13441
|
aec: o.aec,
|
|
13405
13442
|
// v3 §3: first sound <1.2s p50 from the last word — the endpoint takes ~0.6s and the bridge's TTS ~0.2s, so the bridge
|
|
13406
13443
|
// goes 300ms after the turn if MAIN is still silent (it always is that early: warm MAIN's first token is ≥1s), no veto
|
|
13444
|
+
// A short question gets that bridge too (by intent, not length); any other turn expecting an answer that got none
|
|
13445
|
+
// gets a late one at 1.3s from the last word while MAIN is still silent (API first byte runs 1-8s); a closer, none.
|
|
13407
13446
|
bridgeDelayMs: 300,
|
|
13408
13447
|
instantBridge: true,
|
|
13448
|
+
lateBridgeMs: 1300,
|
|
13409
13449
|
...this.lang ? { lang: this.lang } : {},
|
|
13410
13450
|
...o.channel,
|
|
13411
13451
|
// the ledger: a turn's bridge moment that stayed silent, and why (its wait then has no first sound until MAIN speaks)
|
|
@@ -13629,7 +13669,7 @@ var VoiceCall = class {
|
|
|
13629
13669
|
if (this.cur) this.close(this.cur, t.replaces === this.cur.id ? "replaced" : void 0);
|
|
13630
13670
|
this.follow(t.text);
|
|
13631
13671
|
this.clearProgress();
|
|
13632
|
-
this.cur = { id: t.id, text: t.text, at, finalAt, lastWord, running: true, streamed: false, sounded: false, worded: false, done: false, marks: { sent: now3 }, closed: false };
|
|
13672
|
+
this.cur = { id: t.id, text: t.text, at, finalAt, lastWord, running: true, streamed: false, sounded: false, worded: false, done: false, marks: { sent: now3 }, closed: false, due: turnIntent(t.text) !== "closer" };
|
|
13633
13673
|
const early = this.earlyHeard;
|
|
13634
13674
|
this.earlyHeard = null;
|
|
13635
13675
|
if (early && early.at >= at) {
|
|
@@ -13639,7 +13679,7 @@ var VoiceCall = class {
|
|
|
13639
13679
|
this.progress.turn();
|
|
13640
13680
|
this.o.onMetric({ name: "turn", id: t.id, kind: t.kind, text: t.text });
|
|
13641
13681
|
this.o.sendTurn(t.text, { id: t.id, ...t.replaces ? { replaces: t.replaces } : {} });
|
|
13642
|
-
if (t.kind === "new") this.fill.onUserTurn(t.text);
|
|
13682
|
+
if (t.kind === "new") this.fill.onUserTurn(t.text, now3 - at);
|
|
13643
13683
|
}
|
|
13644
13684
|
onDrop(text, why) {
|
|
13645
13685
|
if (!this.gate.holding) {
|
|
@@ -13678,7 +13718,7 @@ var VoiceCall = class {
|
|
|
13678
13718
|
sounded(c, by, at = this.o.now()) {
|
|
13679
13719
|
if (c.sounded) return;
|
|
13680
13720
|
c.sounded = true;
|
|
13681
|
-
this.o.onMetric({ name: "first_sound", id: c.id, ms: Math.round(at - c.at), by });
|
|
13721
|
+
this.o.onMetric(c.due ? { name: "first_sound", id: c.id, ms: Math.round(at - c.at), by } : { name: "first_sound", id: c.id, by, kind: "no answer due" });
|
|
13682
13722
|
}
|
|
13683
13723
|
/** The turn is over (answered + audible, replaced, the next turn, the call's end): its timeline, once. A turn whose MAIN
|
|
13684
13724
|
* never became audible still reports first_word — with no ms and why (cut / replaced / silent) — so every turn has one. */
|
|
@@ -13698,7 +13738,8 @@ var VoiceCall = class {
|
|
|
13698
13738
|
mainText: rel(m.mainText),
|
|
13699
13739
|
mainAudio: rel(m.mainAudio),
|
|
13700
13740
|
lastWord: c.lastWord,
|
|
13701
|
-
end: c.end
|
|
13741
|
+
end: c.end,
|
|
13742
|
+
...c.due ? {} : { due: false }
|
|
13702
13743
|
};
|
|
13703
13744
|
for (const k of Object.keys(tl)) if (tl[k] === void 0) delete tl[k];
|
|
13704
13745
|
this.o.onMetric({ name: "timeline", id: c.id, text: c.text, timeline: tl });
|