@livx.cc/agentx 0.97.3 → 0.97.5

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 CHANGED
@@ -4585,6 +4585,26 @@ init_logging();
4585
4585
  // src/voice/spokenSplitter.ts
4586
4586
  var OPEN = "<spoken>";
4587
4587
  var CLOSE = "</spoken>";
4588
+ var SentenceCoalescer = class _SentenceCoalescer {
4589
+ buf = "";
4590
+ static isEnd(c) {
4591
+ return c === "\n" || c === "." || c === "!" || c === "?" || c === "\u2026";
4592
+ }
4593
+ feed(delta) {
4594
+ if (delta) this.buf += delta;
4595
+ let cut = -1;
4596
+ for (let i = 0; i < this.buf.length; i++) if (_SentenceCoalescer.isEnd(this.buf[i])) cut = i;
4597
+ if (cut < 0) return "";
4598
+ const ready = this.buf.slice(0, cut + 1).trim();
4599
+ this.buf = this.buf.slice(cut + 1);
4600
+ return ready;
4601
+ }
4602
+ flush() {
4603
+ const s = this.buf.trim();
4604
+ this.buf = "";
4605
+ return s;
4606
+ }
4607
+ };
4588
4608
  var SpokenSplitter = class {
4589
4609
  buf = "";
4590
4610
  inSpoken = false;
@@ -5024,13 +5044,19 @@ ${recent}` : brief) + verify + deliverContract;
5024
5044
  const speak = (seg) => {
5025
5045
  if (seg) o.host?.notify?.({ kind: "speak_utterance", message: seg });
5026
5046
  };
5047
+ const coalescer = new SentenceCoalescer();
5048
+ const feedSpoken = (s) => {
5049
+ const ready = coalescer.feed(s);
5050
+ if (ready) speak(ready);
5051
+ };
5052
+ const flushSpoken = () => speak(coalescer.flush());
5027
5053
  const askBridge = o.askRelay ? { ask: relayAsk } : o.host?.ask ? { ask: (q2) => o.host.ask(q2) } : {};
5028
5054
  const workerHost = {
5029
5055
  ...askBridge,
5030
5056
  notify: (ev) => {
5031
5057
  if (ev?.kind === "text_delta" && typeof ev.message === "string") {
5032
5058
  const { spoken, detail } = splitter.feed(ev.message);
5033
- speak(spoken);
5059
+ feedSpoken(spoken);
5034
5060
  if (detail.trim()) pushTail(detail.trim());
5035
5061
  return;
5036
5062
  }
@@ -5053,7 +5079,13 @@ ${recent}` : brief) + verify + deliverContract;
5053
5079
  signal: controller.signal
5054
5080
  // shared with the checker so a cancel tears down both
5055
5081
  };
5056
- const promise = new Agent(agentOpts).run(briefText).then((res) => this.maybeVerify(id, brief, res, tier, agentOpts, askBridge)).then((res) => this.onWorkerSettled(id, res)).catch((err2) => this.onWorkerFailed(id, err2));
5082
+ const promise = new Agent(agentOpts).run(briefText).then((res) => {
5083
+ const { spoken, detail } = splitter.flush();
5084
+ feedSpoken(spoken);
5085
+ if (detail.trim()) pushTail(detail.trim());
5086
+ flushSpoken();
5087
+ return res;
5088
+ }).then((res) => this.maybeVerify(id, brief, res, tier, agentOpts, askBridge)).then((res) => this.onWorkerSettled(id, res)).catch((err2) => this.onWorkerFailed(id, err2));
5057
5089
  this.tasks.set(id, { id, label, status: "running", controller, promise, tail, brief, followUp, splitter });
5058
5090
  if (this.tasks.size > this.options.maxTaskRecords)
5059
5091
  for (const [tid, rec] of this.tasks) {