@livx.cc/agentx 0.99.118 → 0.99.119
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 +148 -28
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +52 -8
- package/dist/index.js +144 -27
- package/dist/index.js.map +1 -1
- package/dist/{secondChannel-BCEr_QyM.d.ts → secondChannel-DepBV0Zv.d.ts} +6 -0
- package/package.json +1 -1
package/dist/cli.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { o as RouterState, H as Hooks, p as RunResult, R as ReasoningEffort, C as ChannelMode, A as Agent } from './secondChannel-
|
|
2
|
+
import { o as RouterState, H as Hooks, p as RunResult, R as ReasoningEffort, C as ChannelMode, A as Agent } from './secondChannel-DepBV0Zv.js';
|
|
3
3
|
import { IFilesystem } from '@livx.cc/wcli/core';
|
|
4
4
|
import { M as Message, U as UserQuestion, H as HostBridge, c as ContentPart, o as MessageContent } from './tools-DZHZIyxh.js';
|
|
5
5
|
|
package/dist/cli.js
CHANGED
|
@@ -13436,11 +13436,26 @@ var SecondChannel = class {
|
|
|
13436
13436
|
}
|
|
13437
13437
|
/** Hard gates every line passes, whoever proposed it. */
|
|
13438
13438
|
allowed(k) {
|
|
13439
|
-
|
|
13440
|
-
|
|
13441
|
-
|
|
13442
|
-
|
|
13443
|
-
|
|
13439
|
+
return !this.blocked(k);
|
|
13440
|
+
}
|
|
13441
|
+
/** Why a line of kind `k` can't play now ('' = it can) — the call's ledger names a missing bridge's cause. */
|
|
13442
|
+
blocked(k) {
|
|
13443
|
+
if (!this.o.kinds.includes(k)) return "kind off";
|
|
13444
|
+
if (this.audioLocked) return `main audio (${this.main})`;
|
|
13445
|
+
if (this.inflight) return "a line still playing";
|
|
13446
|
+
if (this.o.now() - this.lastAt < this.o.minGapMs) return `${Math.round(this.o.now() - this.lastAt)}ms since the last line`;
|
|
13447
|
+
if (k === this.lastKind && (k !== "backchannel" || this.o.now() - this.lastAt < this.o.backchannelGapMs)) return "same kind as the last line";
|
|
13448
|
+
if (k === "backchannel") return this.o.aec && this.userSpeaking && this.main === "idle" && !this.capped() ? "" : "not a backchannel moment";
|
|
13449
|
+
if (k === "filler") return !this.userSpeaking && this.main === "idle" ? "" : "not a filler moment";
|
|
13450
|
+
return this.bridged ? "bridged already" : this.main === "queued" || this.main === "thinking" ? "" : `main ${this.main}`;
|
|
13451
|
+
}
|
|
13452
|
+
/** Why this turn gets no bridge by rule ('' = it may) — language, a quick/phatic turn, or blocked(). */
|
|
13453
|
+
bridgeBlock() {
|
|
13454
|
+
const w = words3(this.heard);
|
|
13455
|
+
if (!this.lang) return "language unknown";
|
|
13456
|
+
if (w.length <= 3 || w.length <= 6 && isPhatic(this.heard, this.bank)) return w.length <= 3 ? "quick turn" : "phatic";
|
|
13457
|
+
if (w.length < this.o.bridgeMinWords) return `under ${this.o.bridgeMinWords} words`;
|
|
13458
|
+
return this.blocked("bridge");
|
|
13444
13459
|
}
|
|
13445
13460
|
bcTimes = [];
|
|
13446
13461
|
capped() {
|
|
@@ -13487,7 +13502,10 @@ var SecondChannel = class {
|
|
|
13487
13502
|
return breath || /[,;:…]$/.test(this.heard);
|
|
13488
13503
|
}
|
|
13489
13504
|
async consider(trigger, pauseMs, breath = false, cue = null) {
|
|
13490
|
-
if (this.busy)
|
|
13505
|
+
if (this.busy) {
|
|
13506
|
+
if (trigger === "working") this.o.onEvent({ trigger, rule: "silence", ms: 0, acted: "silence", reason: "deciding another line" });
|
|
13507
|
+
return;
|
|
13508
|
+
}
|
|
13491
13509
|
const n0 = words3(this.heard).length;
|
|
13492
13510
|
this.decidedAt = n0;
|
|
13493
13511
|
if (!(this.o.anticipate && this.plan && trigger === "interim")) cue = null;
|
|
@@ -13497,7 +13515,10 @@ var SecondChannel = class {
|
|
|
13497
13515
|
log27.info("chatty mode without echo cancellation \u2014 normal timing (our lines would re-trigger the mic)");
|
|
13498
13516
|
}
|
|
13499
13517
|
const rule = this.rule(trigger, pauseMs, breath, cue);
|
|
13500
|
-
if (rule === "silence")
|
|
13518
|
+
if (rule === "silence") {
|
|
13519
|
+
if (trigger === "working") this.o.onEvent({ trigger, rule, ms: 0, acted: "silence", reason: this.bridgeBlock() || "rule" });
|
|
13520
|
+
return;
|
|
13521
|
+
}
|
|
13501
13522
|
this.busy = true;
|
|
13502
13523
|
const gen = this.gen, t0 = this.o.now();
|
|
13503
13524
|
const ev = (e) => this.o.onEvent({ trigger, rule, ms: Math.round(this.o.now() - t0), ...cue ? { cue: cue.line } : {}, ...e });
|
|
@@ -13691,6 +13712,9 @@ var VoiceCallOptions = class {
|
|
|
13691
13712
|
channel = {};
|
|
13692
13713
|
onMetric = () => {
|
|
13693
13714
|
};
|
|
13715
|
+
/** The host reports when a fill line's audio REALLY starts (heard()). Off: a line handed to `speak` counts as heard —
|
|
13716
|
+
* right only for a host whose speak() plays at once (a relay host would count lines its player later dropped). */
|
|
13717
|
+
hostAudio = false;
|
|
13694
13718
|
now = () => performance.now();
|
|
13695
13719
|
/** An aside (aside()) needs this long since the last one — a cue answered every time sounds scripted. */
|
|
13696
13720
|
asideGapMs = 8e3;
|
|
@@ -13710,11 +13734,17 @@ var VoiceCall = class {
|
|
|
13710
13734
|
} : {},
|
|
13711
13735
|
mode: o.mode,
|
|
13712
13736
|
aec: o.aec,
|
|
13713
|
-
|
|
13737
|
+
// 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
|
|
13738
|
+
// goes 300ms after the turn if MAIN is still silent (it always is that early: warm MAIN's first token is ≥1s), no veto
|
|
13739
|
+
bridgeDelayMs: 300,
|
|
13714
13740
|
instantBridge: true,
|
|
13715
|
-
// v3 §3: first sound <1.2s p50 — a bridge at 700ms if MAIN is still silent, no veto, no wait
|
|
13716
13741
|
...this.lang ? { lang: this.lang } : {},
|
|
13717
13742
|
...o.channel,
|
|
13743
|
+
// the ledger: a turn's bridge moment that stayed silent, and why (its wait then has no first sound until MAIN speaks)
|
|
13744
|
+
onEvent: (e) => {
|
|
13745
|
+
if (e.trigger === "working" && e.acted !== "spoken") o.onMetric({ name: "drop", ...this.cur ? { id: this.cur.id } : {}, kind: `no bridge: ${e.reason ?? e.acted}`, ...e.text ? { text: e.text } : {} });
|
|
13746
|
+
o.channel.onEvent?.(e);
|
|
13747
|
+
},
|
|
13718
13748
|
speak: (text, kind) => this.say(text, kind),
|
|
13719
13749
|
show: (text, kind) => o.show(text, kind),
|
|
13720
13750
|
cancel: () => o.cancel(),
|
|
@@ -13741,6 +13771,10 @@ var VoiceCall = class {
|
|
|
13741
13771
|
lastAudibleAt = -Infinity;
|
|
13742
13772
|
firstFinalAt = null;
|
|
13743
13773
|
// the first final of the turn being formed (hold/merge)
|
|
13774
|
+
lastWordAt = null;
|
|
13775
|
+
// the user's last word before the turn being formed (its latest final's)
|
|
13776
|
+
earlyHeard = null;
|
|
13777
|
+
// a fill line heard while that turn was still held
|
|
13744
13778
|
progressTimer = null;
|
|
13745
13779
|
ended = false;
|
|
13746
13780
|
get o() {
|
|
@@ -13769,12 +13803,37 @@ var VoiceCall = class {
|
|
|
13769
13803
|
this.follow(text);
|
|
13770
13804
|
this.fill.onInterim(text);
|
|
13771
13805
|
}
|
|
13772
|
-
/** STT final → TurnGate.
|
|
13773
|
-
|
|
13806
|
+
/** STT final → TurnGate. `lastWordAgoMs`: how long ago the user's last word of it ended (the STT's word clock,
|
|
13807
|
+
* bod-voice UtteranceMeta.lastWordAgoMs) — the turn's latency anchor; absent = the final's arrival. `lang`: the
|
|
13808
|
+
* language the STT identified for it (UtteranceMeta.language) — what the turn's words follow when they alone can't tell
|
|
13809
|
+
* (a short English line after a Hebrew one left the fill channel on Hebrew: its bridge was refused, the turn silent). */
|
|
13810
|
+
final(text, sttId, o = {}) {
|
|
13774
13811
|
if (this.ended) return;
|
|
13775
|
-
|
|
13812
|
+
const now4 = this.o.now(), { lastWordAgoMs } = o;
|
|
13813
|
+
this.firstFinalAt ??= now4;
|
|
13814
|
+
this.sttLang = o.lang ? primaryLang(o.lang) : null;
|
|
13815
|
+
this.lastWordAt = typeof lastWordAgoMs === "number" && lastWordAgoMs >= 0 ? now4 - lastWordAgoMs : null;
|
|
13816
|
+
this.finalAt = now4;
|
|
13776
13817
|
this.gate.final(text, sttId);
|
|
13777
13818
|
}
|
|
13819
|
+
finalAt = 0;
|
|
13820
|
+
sttLang = null;
|
|
13821
|
+
// the STT's language for the final being followed
|
|
13822
|
+
/** The host's player started a line's audio now (or in `inMs`): `fill`/`progress` = the fill channel's, `main` = MAIN's
|
|
13823
|
+
* reply (as main({type:'audio'})). With hostAudio this is what first_sound counts. */
|
|
13824
|
+
heard(by, inMs = 0) {
|
|
13825
|
+
if (this.ended) return;
|
|
13826
|
+
if (by === "main") return this.main({ type: "audio", ...this.cur ? { id: this.cur.id } : {} }, inMs);
|
|
13827
|
+
const at = this.o.now() + Math.max(0, inMs);
|
|
13828
|
+
if (this.gate.holding || !this.cur || this.cur.closed) {
|
|
13829
|
+
this.earlyHeard ??= { at, by };
|
|
13830
|
+
return;
|
|
13831
|
+
}
|
|
13832
|
+
this.lastAudibleAt = at;
|
|
13833
|
+
const c = this.cur;
|
|
13834
|
+
c.marks.fillAudio ??= at;
|
|
13835
|
+
this.sounded(c, by, at);
|
|
13836
|
+
}
|
|
13778
13837
|
/** A v2 host that decides turns itself: the user's line already went to MAIN (no TurnGate, no sendTurn) — the fill
|
|
13779
13838
|
* channel follows its language and covers the wait. */
|
|
13780
13839
|
hostTurn(text) {
|
|
@@ -13785,8 +13844,8 @@ var VoiceCall = class {
|
|
|
13785
13844
|
pause(ms) {
|
|
13786
13845
|
if (!this.ended) this.fill.onPause(ms);
|
|
13787
13846
|
}
|
|
13788
|
-
/** MAIN's stream. */
|
|
13789
|
-
main(ev) {
|
|
13847
|
+
/** MAIN's stream. (`inMs`: an audio event's start is that far ahead — the host player's queue.) */
|
|
13848
|
+
main(ev, inMs = 0) {
|
|
13790
13849
|
const c = this.cur;
|
|
13791
13850
|
if (!c || ev.id && ev.id !== c.id) return;
|
|
13792
13851
|
switch (ev.type) {
|
|
@@ -13795,6 +13854,8 @@ var VoiceCall = class {
|
|
|
13795
13854
|
return;
|
|
13796
13855
|
case "text":
|
|
13797
13856
|
if (!ev.text) return;
|
|
13857
|
+
c.marks.mainFirst ??= this.o.now();
|
|
13858
|
+
c.marks.mainText ??= this.o.now();
|
|
13798
13859
|
if (!c.streamed) {
|
|
13799
13860
|
c.streamed = true;
|
|
13800
13861
|
this.gate.replyStarted(c.id);
|
|
@@ -13804,25 +13865,32 @@ var VoiceCall = class {
|
|
|
13804
13865
|
this.fill.onMainTokens(ev.text);
|
|
13805
13866
|
return;
|
|
13806
13867
|
case "tool":
|
|
13868
|
+
c.marks.mainFirst ??= this.o.now();
|
|
13807
13869
|
this.gate.replyStarted(c.id);
|
|
13808
13870
|
void this.onTool(c, ev.name ?? "", ev.args);
|
|
13809
13871
|
return;
|
|
13810
13872
|
case "tool_done":
|
|
13811
13873
|
return;
|
|
13812
|
-
case "audio":
|
|
13813
|
-
|
|
13874
|
+
case "audio": {
|
|
13875
|
+
const at = this.o.now() + Math.max(0, inMs);
|
|
13876
|
+
this.lastAudibleAt = at;
|
|
13814
13877
|
this.fill.onAgentState("first_audio");
|
|
13815
|
-
this.sounded(c, "main");
|
|
13878
|
+
this.sounded(c, "main", at);
|
|
13816
13879
|
if (!c.worded) {
|
|
13817
13880
|
c.worded = true;
|
|
13818
|
-
|
|
13881
|
+
c.marks.mainAudio = at;
|
|
13882
|
+
this.o.onMetric({ name: "first_word", id: c.id, ms: Math.round(at - c.at), by: "main" });
|
|
13819
13883
|
}
|
|
13884
|
+
if (c.done) this.close(c, "answered");
|
|
13820
13885
|
return;
|
|
13886
|
+
}
|
|
13821
13887
|
case "done":
|
|
13822
13888
|
case "error":
|
|
13823
13889
|
c.running = false;
|
|
13890
|
+
c.done = true;
|
|
13824
13891
|
this.clearProgress();
|
|
13825
13892
|
this.fill.onAgentState("idle");
|
|
13893
|
+
if (c.worded) this.close(c, "answered");
|
|
13826
13894
|
return;
|
|
13827
13895
|
}
|
|
13828
13896
|
}
|
|
@@ -13839,6 +13907,7 @@ var VoiceCall = class {
|
|
|
13839
13907
|
this.cur.running = false;
|
|
13840
13908
|
this.o.abortTurn(this.cur.id);
|
|
13841
13909
|
}
|
|
13910
|
+
if (this.cur && !this.cur.worded) this.cur.end ??= "cut";
|
|
13842
13911
|
}
|
|
13843
13912
|
/** Soft barge-in: keep (a listener cue — no turn) or cut (→ barge()). */
|
|
13844
13913
|
async overlap(text) {
|
|
@@ -13868,6 +13937,7 @@ var VoiceCall = class {
|
|
|
13868
13937
|
return this.fill.drain();
|
|
13869
13938
|
}
|
|
13870
13939
|
end() {
|
|
13940
|
+
if (this.cur) this.close(this.cur);
|
|
13871
13941
|
this.ended = true;
|
|
13872
13942
|
this.gate.end();
|
|
13873
13943
|
this.clearProgress();
|
|
@@ -13876,24 +13946,39 @@ var VoiceCall = class {
|
|
|
13876
13946
|
/** Follow the user's language from their own words: a confident detection, else the current language if the words
|
|
13877
13947
|
* fit it, else unknown (silent). Pinned into the channel so its own detection never diverges. */
|
|
13878
13948
|
follow(text) {
|
|
13879
|
-
const
|
|
13949
|
+
const fits = (l2) => l2 && fitsLanguage(text, l2) ? l2 : null;
|
|
13950
|
+
const l = detectLanguage(text) ?? fits(this.sttLang) ?? fits(this.lang);
|
|
13880
13951
|
if (l !== this.lang) this.o.onMetric({ name: "lang", lang: l, text });
|
|
13881
13952
|
this.lang = l;
|
|
13882
13953
|
if (l) this.fill.setLanguage(l, true);
|
|
13883
13954
|
}
|
|
13884
13955
|
onTurn(t) {
|
|
13885
|
-
const
|
|
13956
|
+
const now4 = this.o.now(), lastWord = this.lastWordAt !== null;
|
|
13957
|
+
const at = this.lastWordAt ?? this.firstFinalAt ?? now4;
|
|
13958
|
+
const finalAt = this.finalAt || now4;
|
|
13886
13959
|
this.firstFinalAt = null;
|
|
13960
|
+
this.lastWordAt = null;
|
|
13961
|
+
if (this.cur) this.close(this.cur, t.replaces === this.cur.id ? "replaced" : void 0);
|
|
13887
13962
|
this.follow(t.text);
|
|
13888
13963
|
this.clearProgress();
|
|
13889
|
-
this.cur = { id: t.id, text: t.text, at, running: true, streamed: false, sounded: false, worded: false };
|
|
13964
|
+
this.cur = { id: t.id, text: t.text, at, finalAt, lastWord, running: true, streamed: false, sounded: false, worded: false, done: false, marks: { sent: now4 }, closed: false };
|
|
13965
|
+
const early = this.earlyHeard;
|
|
13966
|
+
this.earlyHeard = null;
|
|
13967
|
+
if (early && early.at >= at) {
|
|
13968
|
+
this.cur.marks.fillAudio = early.at;
|
|
13969
|
+
this.sounded(this.cur, early.by, early.at);
|
|
13970
|
+
}
|
|
13890
13971
|
this.progress.turn();
|
|
13891
13972
|
this.o.onMetric({ name: "turn", id: t.id, kind: t.kind, text: t.text });
|
|
13892
13973
|
this.o.sendTurn(t.text, { id: t.id, ...t.replaces ? { replaces: t.replaces } : {} });
|
|
13893
13974
|
if (t.kind === "new") this.fill.onUserTurn(t.text);
|
|
13894
13975
|
}
|
|
13895
13976
|
onDrop(text, why) {
|
|
13896
|
-
if (!this.gate.holding)
|
|
13977
|
+
if (!this.gate.holding) {
|
|
13978
|
+
this.firstFinalAt = null;
|
|
13979
|
+
this.lastWordAt = null;
|
|
13980
|
+
this.earlyHeard = null;
|
|
13981
|
+
}
|
|
13897
13982
|
this.o.onMetric({ name: "drop", kind: why, text });
|
|
13898
13983
|
}
|
|
13899
13984
|
/** Every fill/progress line passes here: only in the turn's known language, never after the call ended. */
|
|
@@ -13907,16 +13992,48 @@ var VoiceCall = class {
|
|
|
13907
13992
|
return false;
|
|
13908
13993
|
}
|
|
13909
13994
|
if (r === false) return false;
|
|
13910
|
-
this.lastAudibleAt = this.o.now();
|
|
13911
13995
|
this.o.onMetric({ name: "fill", kind, text, lang: this.lang });
|
|
13912
|
-
|
|
13913
|
-
|
|
13996
|
+
const c = this.cur && !this.cur.closed ? this.cur : void 0;
|
|
13997
|
+
const forTurn = !!c && (kind === "bridge" || kind === "progress" || kind === "filler" && c.running && !c.sounded);
|
|
13998
|
+
if (c && forTurn && c.marks.fill === void 0) {
|
|
13999
|
+
c.marks.fill = this.o.now();
|
|
14000
|
+
c.fillKind = kind;
|
|
14001
|
+
}
|
|
14002
|
+
if (this.o.hostAudio) return r;
|
|
14003
|
+
this.lastAudibleAt = this.o.now();
|
|
14004
|
+
if (c && forTurn) {
|
|
14005
|
+
c.marks.fillAudio ??= this.o.now();
|
|
14006
|
+
this.sounded(c, kind === "progress" ? "progress" : "fill");
|
|
14007
|
+
}
|
|
13914
14008
|
return r;
|
|
13915
14009
|
}
|
|
13916
|
-
sounded(c, by) {
|
|
14010
|
+
sounded(c, by, at = this.o.now()) {
|
|
13917
14011
|
if (c.sounded) return;
|
|
13918
14012
|
c.sounded = true;
|
|
13919
|
-
this.o.onMetric({ name: "first_sound", id: c.id, ms: Math.round(
|
|
14013
|
+
this.o.onMetric({ name: "first_sound", id: c.id, ms: Math.round(at - c.at), by });
|
|
14014
|
+
}
|
|
14015
|
+
/** The turn is over (answered + audible, replaced, the next turn, the call's end): its timeline, once. A turn whose MAIN
|
|
14016
|
+
* never became audible still reports first_word — with no ms and why (cut / replaced / silent) — so every turn has one. */
|
|
14017
|
+
close(c, end) {
|
|
14018
|
+
if (c.closed) return;
|
|
14019
|
+
c.closed = true;
|
|
14020
|
+
c.end = c.worded ? "answered" : end ?? c.end ?? "silent";
|
|
14021
|
+
if (!c.worded) this.o.onMetric({ name: "first_word", id: c.id, by: "main", kind: c.end });
|
|
14022
|
+
const rel = (t) => t === void 0 ? void 0 : Math.round(t - c.at);
|
|
14023
|
+
const m = c.marks, tl = {
|
|
14024
|
+
final: rel(c.finalAt),
|
|
14025
|
+
sent: rel(m.sent),
|
|
14026
|
+
fill: rel(m.fill),
|
|
14027
|
+
...c.fillKind ? { fillKind: c.fillKind } : {},
|
|
14028
|
+
fillAudio: rel(m.fillAudio),
|
|
14029
|
+
mainFirst: rel(m.mainFirst),
|
|
14030
|
+
mainText: rel(m.mainText),
|
|
14031
|
+
mainAudio: rel(m.mainAudio),
|
|
14032
|
+
lastWord: c.lastWord,
|
|
14033
|
+
end: c.end
|
|
14034
|
+
};
|
|
14035
|
+
for (const k of Object.keys(tl)) if (tl[k] === void 0) delete tl[k];
|
|
14036
|
+
this.o.onMetric({ name: "timeline", id: c.id, text: c.text, timeline: tl });
|
|
13920
14037
|
}
|
|
13921
14038
|
async onTool(c, name, args) {
|
|
13922
14039
|
const lang = this.lang;
|
|
@@ -22707,6 +22824,8 @@ async function channelServe(args, ai, cfg) {
|
|
|
22707
22824
|
channel: channelOptions(ai, process.env.AGENTX_CHANNEL_MODEL || model, args.voiceGender),
|
|
22708
22825
|
speak: () => true,
|
|
22709
22826
|
// the host plays {type:'channel'} lines (shown via show)
|
|
22827
|
+
hostAudio: true,
|
|
22828
|
+
// …and says when one really plays ({type:'heard'}) — a line its player drops never counts as sound
|
|
22710
22829
|
show: (text, kind) => out({ type: "channel", kind, text }),
|
|
22711
22830
|
sendTurn: (text, o) => out({ type: "turn", id: o.id, text, ...o.replaces ? { replaces: o.replaces } : {} }),
|
|
22712
22831
|
abortTurn: (id) => out({ type: "abort", id }),
|
|
@@ -22731,7 +22850,8 @@ async function channelServe(args, ai, cfg) {
|
|
|
22731
22850
|
if (m.type === "interim") {
|
|
22732
22851
|
if (typeof m.lang === "string") call.setLanguage(m.lang);
|
|
22733
22852
|
if (typeof m.text === "string") call.interim(m.text, Date.now(), typeof m.aec === "boolean" ? m.aec : void 0);
|
|
22734
|
-
} else if (m.type === "final" && typeof m.text === "string") call.final(m.text, m.sttId === void 0 ? void 0 : String(m.sttId));
|
|
22853
|
+
} else if (m.type === "final" && typeof m.text === "string") call.final(m.text, m.sttId === void 0 ? void 0 : String(m.sttId), { ...typeof m.lastWordAgoMs === "number" ? { lastWordAgoMs: m.lastWordAgoMs } : {}, ...typeof m.lang === "string" ? { lang: m.lang } : {} });
|
|
22854
|
+
else if (m.type === "heard" && ["fill", "progress", "main"].includes(m.by)) call.heard(m.by, typeof m.inMs === "number" ? m.inMs : 0);
|
|
22735
22855
|
else if (m.type === "main" && m.ev && typeof m.ev.type === "string") call.main(m.ev);
|
|
22736
22856
|
else if (m.type === "barge") call.barge();
|
|
22737
22857
|
else if (channelInput(call.fill, m)) return;
|