@livx.cc/agentx 0.97.5 → 0.97.9
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 +25 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.js +22 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -858,6 +858,10 @@ interface TaskRecord {
|
|
|
858
858
|
/** Per-worker `<spoken>` splitter — the worker OWNS delivery: spoken segments stream during its run.
|
|
859
859
|
* Read at settle (spokeAny) to decide the no-spoken fallback. */
|
|
860
860
|
splitter?: SpokenSplitter;
|
|
861
|
+
/** Set when the user barged in / took the floor while this task was in flight: its remaining SPOKEN
|
|
862
|
+
* delivery is suppressed (don't talk over the new topic), but its full result still lands in the
|
|
863
|
+
* transcript so the reflex can surface it on request. See parkInFlightDeliveries(). */
|
|
864
|
+
deliveryParked?: boolean;
|
|
861
865
|
}
|
|
862
866
|
type WorkerTier = 'act' | 'think';
|
|
863
867
|
declare class DuplexAgentOptions {
|
|
@@ -998,6 +1002,11 @@ declare class DuplexAgent {
|
|
|
998
1002
|
send(content: MessageContent): Promise<RunResult>;
|
|
999
1003
|
/** Cancel a running background task — shared by the CancelTask tool and the CLI /tasks picker. */
|
|
1000
1004
|
cancelTask(id: string): string;
|
|
1005
|
+
/** Barge-in: the user took the floor while task(s) were running. Suppress those tasks' remaining SPOKEN
|
|
1006
|
+
* delivery so a superseded topic never talks over the new one (the debt-after-jokes regression). The
|
|
1007
|
+
* tasks keep running and still fold their result into the transcript — recoverable, just not spoken.
|
|
1008
|
+
* Returns the parked ids (for logging). Does NOT cancel: that's a deliberate reflex/user action. */
|
|
1009
|
+
parkInFlightDeliveries(): string[];
|
|
1001
1010
|
/** Resolve when all queued voice turns AND all in-flight worker tasks have settled (tests, graceful shutdown). */
|
|
1002
1011
|
idle(): Promise<void>;
|
|
1003
1012
|
/** Promise-chain mutex: turns run strictly one at a time; a failed turn doesn't poison the chain. */
|
package/dist/index.js
CHANGED
|
@@ -4651,6 +4651,8 @@ init_logging();
|
|
|
4651
4651
|
// src/voice/spokenSplitter.ts
|
|
4652
4652
|
var OPEN = "<spoken>";
|
|
4653
4653
|
var CLOSE = "</spoken>";
|
|
4654
|
+
var CLOSERS = `"')]}\xBB\u201D\u2019`;
|
|
4655
|
+
var hasSpeech = (s) => /[\p{L}\p{N}]/u.test(s);
|
|
4654
4656
|
var SentenceCoalescer = class _SentenceCoalescer {
|
|
4655
4657
|
buf = "";
|
|
4656
4658
|
static isEnd(c) {
|
|
@@ -4661,14 +4663,15 @@ var SentenceCoalescer = class _SentenceCoalescer {
|
|
|
4661
4663
|
let cut = -1;
|
|
4662
4664
|
for (let i = 0; i < this.buf.length; i++) if (_SentenceCoalescer.isEnd(this.buf[i])) cut = i;
|
|
4663
4665
|
if (cut < 0) return "";
|
|
4666
|
+
if (this.buf[cut] !== "\n") while (cut + 1 < this.buf.length && CLOSERS.includes(this.buf[cut + 1])) cut++;
|
|
4664
4667
|
const ready = this.buf.slice(0, cut + 1).trim();
|
|
4665
4668
|
this.buf = this.buf.slice(cut + 1);
|
|
4666
|
-
return ready;
|
|
4669
|
+
return hasSpeech(ready) ? ready : "";
|
|
4667
4670
|
}
|
|
4668
4671
|
flush() {
|
|
4669
4672
|
const s = this.buf.trim();
|
|
4670
4673
|
this.buf = "";
|
|
4671
|
-
return s;
|
|
4674
|
+
return hasSpeech(s) ? s : "";
|
|
4672
4675
|
}
|
|
4673
4676
|
};
|
|
4674
4677
|
var SpokenSplitter = class {
|
|
@@ -5011,6 +5014,19 @@ Today's date: ${(/* @__PURE__ */ new Date()).toDateString()}.`;
|
|
|
5011
5014
|
rec.controller.abort();
|
|
5012
5015
|
return `Task ${rec.id} (${rec.label}) cancelled.`;
|
|
5013
5016
|
}
|
|
5017
|
+
/** Barge-in: the user took the floor while task(s) were running. Suppress those tasks' remaining SPOKEN
|
|
5018
|
+
* delivery so a superseded topic never talks over the new one (the debt-after-jokes regression). The
|
|
5019
|
+
* tasks keep running and still fold their result into the transcript — recoverable, just not spoken.
|
|
5020
|
+
* Returns the parked ids (for logging). Does NOT cancel: that's a deliberate reflex/user action. */
|
|
5021
|
+
parkInFlightDeliveries() {
|
|
5022
|
+
const parked = [];
|
|
5023
|
+
for (const rec of this.tasks.values())
|
|
5024
|
+
if (rec.status === "running" && !rec.deliveryParked) {
|
|
5025
|
+
rec.deliveryParked = true;
|
|
5026
|
+
parked.push(rec.id);
|
|
5027
|
+
}
|
|
5028
|
+
return parked;
|
|
5029
|
+
}
|
|
5014
5030
|
/** Resolve when all queued voice turns AND all in-flight worker tasks have settled (tests, graceful shutdown). */
|
|
5015
5031
|
async idle() {
|
|
5016
5032
|
while (true) {
|
|
@@ -5108,7 +5124,7 @@ ${recent}` : brief) + verify + deliverContract;
|
|
|
5108
5124
|
};
|
|
5109
5125
|
const splitter = new SpokenSplitter();
|
|
5110
5126
|
const speak = (seg) => {
|
|
5111
|
-
if (seg) o.host?.notify?.({ kind: "speak_utterance", message: seg });
|
|
5127
|
+
if (seg && !this.tasks.get(id)?.deliveryParked) o.host?.notify?.({ kind: "speak_utterance", message: seg });
|
|
5112
5128
|
};
|
|
5113
5129
|
const coalescer = new SentenceCoalescer();
|
|
5114
5130
|
const feedSpoken = (s) => {
|
|
@@ -5329,9 +5345,9 @@ Another agent just implemented the above. Independently check the CURRENT state
|
|
|
5329
5345
|
return this.queueRevoice(this.integrationPrompt(rec, "incomplete", res.text, res.finishReason), true);
|
|
5330
5346
|
}
|
|
5331
5347
|
const tail = rec.splitter?.flush();
|
|
5332
|
-
if (tail?.spoken) this.options.host?.notify?.({ kind: "speak_utterance", message: tail.spoken });
|
|
5348
|
+
if (tail?.spoken && !rec.deliveryParked) this.options.host?.notify?.({ kind: "speak_utterance", message: tail.spoken });
|
|
5333
5349
|
if (res.text.trim()) this.voice.transcript.push({ role: "assistant", content: res.text });
|
|
5334
|
-
if (!rec.splitter?.spokeAny && res.text.trim())
|
|
5350
|
+
if (!rec.splitter?.spokeAny && res.text.trim() && !rec.deliveryParked)
|
|
5335
5351
|
this.options.host?.notify?.({ kind: "speak_utterance", message: res.text });
|
|
5336
5352
|
}
|
|
5337
5353
|
onWorkerFailed(id, err) {
|
|
@@ -5946,7 +5962,7 @@ var VoiceEngine = class _VoiceEngine {
|
|
|
5946
5962
|
* If nothing is currently speaking it plays immediately; otherwise it queues and plays after the
|
|
5947
5963
|
* current utterance fully ends (settle → pumpQueue) — never spliced into an open reflex utterance. */
|
|
5948
5964
|
enqueueUtterance(text) {
|
|
5949
|
-
if (!text ||
|
|
5965
|
+
if (!text || !/[\p{L}\p{N}]/u.test(text)) return;
|
|
5950
5966
|
this.uttQueue.push(text);
|
|
5951
5967
|
if (!this.speaking) this.pumpQueue();
|
|
5952
5968
|
}
|