@livx.cc/agentx 0.99.107 → 0.99.109
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 +59 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +58 -9
- package/dist/index.js.map +1 -1
- package/dist/{secondChannel-BYW5qPAJ.d.ts → secondChannel-3IPP3Qgh.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-3IPP3Qgh.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
|
@@ -10509,6 +10509,14 @@ function nameScore(want, have) {
|
|
|
10509
10509
|
var RESERVED_EVENT_MARKER = /\[task\b[^\]\n]*\b(?:completed|failed|progress|asks)\b/i;
|
|
10510
10510
|
var RESERVED_EVENT_OPENER = /\[\s*task\b/i;
|
|
10511
10511
|
var STAGE_DIRECTION_RE = /^\(\s*(?:(?:waiting|checking|searching|thinking|processing|loading|working|fetching|looking)\b[^)]*|[^)]*(?:\.\.\.|…)\s*)\)$/i;
|
|
10512
|
+
function hostContextBlock(context) {
|
|
10513
|
+
return `<host_context>
|
|
10514
|
+
${context.trim()}
|
|
10515
|
+
</host_context>
|
|
10516
|
+
(Above: context and instructions from the app \u2014 NOT the user's words. Never read it aloud, quote it, or attribute it to the user. The user's line follows.)
|
|
10517
|
+
|
|
10518
|
+
`;
|
|
10519
|
+
}
|
|
10512
10520
|
function nowLine() {
|
|
10513
10521
|
return `Current date and time: ${(/* @__PURE__ */ new Date()).toLocaleString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "2-digit", timeZoneName: "short" })}`;
|
|
10514
10522
|
}
|
|
@@ -11002,9 +11010,9 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
11002
11010
|
/** One reflex model call for a turn; a turn rejected for load (rateLimited) that has not spoken or dispatched yet is rolled
|
|
11003
11011
|
* back and re-run once on `reflexFallbackModel` — a re-prompt of the same model (the dead-air nudge) only hits the
|
|
11004
11012
|
* same limit and ends in "could you say that again?". */
|
|
11005
|
-
async reflexSend(content) {
|
|
11013
|
+
async reflexSend(content, context) {
|
|
11006
11014
|
const base = this.voice.transcript.length;
|
|
11007
|
-
const res = await this.
|
|
11015
|
+
const res = await this.sendWithContext(content, context);
|
|
11008
11016
|
const fb = this.options.reflexFallbackModel, model = this.voice.options.model;
|
|
11009
11017
|
if (res.finishReason !== "error" || !rateLimited(res.error) || !fb || fb === model || fb.includes("/") && model.includes("/") && fb.split("/")[0] !== model.split("/")[0] || this.turnDispatched || this.turnSpoken.trim()) return res;
|
|
11010
11018
|
log23.warn(`reflex ${model} rate-limited \u2014 re-running the turn on ${fb}`);
|
|
@@ -11012,11 +11020,25 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
11012
11020
|
this.voice.transcript.length = base;
|
|
11013
11021
|
this.voice.options.model = fb;
|
|
11014
11022
|
try {
|
|
11015
|
-
return await this.
|
|
11023
|
+
return await this.sendWithContext(content, context);
|
|
11016
11024
|
} finally {
|
|
11017
11025
|
this.voice.options.model = model;
|
|
11018
11026
|
}
|
|
11019
11027
|
}
|
|
11028
|
+
/** The host's per-line context (call rules, browser context, earlier conversation) rides THIS call only, fenced as the app's —
|
|
11029
|
+
* inside the user turn it read as the user's own words (live #938: "repeat everything I said" recited the call rules). The
|
|
11030
|
+
* stored turn keeps only what the user said, so later turns, briefs and the saved session never carry it. A block, not a
|
|
11031
|
+
* mid-transcript system message: the Anthropic/Google adapters keep only the leading system message. */
|
|
11032
|
+
async sendWithContext(content, context) {
|
|
11033
|
+
if (!context?.trim() || typeof content !== "string") return this.voice.send(content);
|
|
11034
|
+
const base = this.voice.transcript.length;
|
|
11035
|
+
try {
|
|
11036
|
+
return await this.voice.send(hostContextBlock(context) + content);
|
|
11037
|
+
} finally {
|
|
11038
|
+
const m = this.voice.transcript.slice(base).find((x) => x.role === "user");
|
|
11039
|
+
if (m) m.content = content;
|
|
11040
|
+
}
|
|
11041
|
+
}
|
|
11020
11042
|
/** The turn SAID it is on it ("got it — checking…") but called no tool and nothing is running: a promise nothing
|
|
11021
11043
|
* keeps — the user waits on silence (live Para #798: a follow-up while the reflex believed a finished task still ran). */
|
|
11022
11044
|
get hollowPromise() {
|
|
@@ -11220,6 +11242,7 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
11220
11242
|
* second Act). The host gets `turn_replace` {id, replaces, rolledBack, followed?}: only a rollback drops the replaced
|
|
11221
11243
|
* line; `followed` = the kept turn whose follow-up ran (absent: the merged text ran). */
|
|
11222
11244
|
send(content, opts) {
|
|
11245
|
+
const ctx = opts?.context;
|
|
11223
11246
|
this.clearHoldResume();
|
|
11224
11247
|
this.holdResumed = false;
|
|
11225
11248
|
if (opts?.replaces) this.replaceTurn(opts.replaces);
|
|
@@ -11245,7 +11268,7 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
11245
11268
|
if (intent === "resume" && !reflexCut) return this.resumeParked();
|
|
11246
11269
|
if (intent === "aside" || intent === "resume") {
|
|
11247
11270
|
const told = intent === "aside" ? [...this.parkedRedeliver] : [];
|
|
11248
|
-
return this.sendTurn(intent === "aside" ? content + this.asideNote(told) : content, true, rec, ext).then(async (r) => {
|
|
11271
|
+
return this.sendTurn(intent === "aside" ? content + this.asideNote(told) : content, true, rec, ext, ctx).then(async (r) => {
|
|
11249
11272
|
if (r.finishReason === "aborted" || this.heldThisTurn) return r;
|
|
11250
11273
|
const missed = unsaidClauses(told.map((p) => p.text), this.turnSpoken, this.options.decider);
|
|
11251
11274
|
const turn = this.turn;
|
|
@@ -11260,10 +11283,10 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
11260
11283
|
return r;
|
|
11261
11284
|
});
|
|
11262
11285
|
}
|
|
11263
|
-
return this.sendTurn(content, false, rec, ext);
|
|
11286
|
+
return this.sendTurn(content, false, rec, ext, ctx);
|
|
11264
11287
|
});
|
|
11265
11288
|
}
|
|
11266
|
-
return this.sendTurn(typeof content === "string" ? content + this.acceptNote(content) : content, false, rec, ext);
|
|
11289
|
+
return this.sendTurn(typeof content === "string" ? content + this.acceptNote(content) : content, false, rec, ext, ctx);
|
|
11267
11290
|
}
|
|
11268
11291
|
/** Host-named user turns (send opts.id), so a later send can replace one. Bounded; a replace that arrives
|
|
11269
11292
|
* BEFORE its target (the host's dispatch hops can reorder) leaves a pre-superseded record behind. */
|
|
@@ -11331,7 +11354,7 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
11331
11354
|
return { text: "", steps: 0, finishReason: "stop", messages: [] };
|
|
11332
11355
|
});
|
|
11333
11356
|
}
|
|
11334
|
-
sendTurn(content, keepParked = false, rec, ext) {
|
|
11357
|
+
sendTurn(content, keepParked = false, rec, ext, context) {
|
|
11335
11358
|
const spec = this.spec;
|
|
11336
11359
|
if (spec?.state === "pending") {
|
|
11337
11360
|
if (typeof content === "string" && speculationConfirms(spec.text, content)) {
|
|
@@ -11384,7 +11407,7 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
11384
11407
|
if (typeof content === "string") content += spellingNote(content);
|
|
11385
11408
|
let res;
|
|
11386
11409
|
try {
|
|
11387
|
-
res = await this.reflexSend(content);
|
|
11410
|
+
res = await this.reflexSend(content, context);
|
|
11388
11411
|
} finally {
|
|
11389
11412
|
if (signal) {
|
|
11390
11413
|
this.voice.options.signal = ext;
|
|
@@ -13022,6 +13045,9 @@ var SecondChannelOptions = class {
|
|
|
13022
13045
|
/** A bridge waits this long after the user's turn is dispatched, and plays only if channel-1 has said nothing yet
|
|
13023
13046
|
* (a fast reply/ack needs no bridge — one before it reads as the agent starting a different sentence). 0 = at once. */
|
|
13024
13047
|
bridgeDelayMs = 1200;
|
|
13048
|
+
/** Duplex v3 (§3 first sound): a bridge skips the decider (the veto stays for backchannels/fillers) and speaks a
|
|
13049
|
+
* canned line at once; a generated one is started at dispatch and used only if it already landed. */
|
|
13050
|
+
instantBridge = false;
|
|
13025
13051
|
/** No new interim for this long → a pause (hosts may also call onPause). */
|
|
13026
13052
|
fillerPauseMs = 700;
|
|
13027
13053
|
fillerMinWords = 4;
|
|
@@ -13093,6 +13119,8 @@ var SecondChannel = class {
|
|
|
13093
13119
|
// the line the last barge actually cut (spoke())
|
|
13094
13120
|
bridged = false;
|
|
13095
13121
|
// one bridge per main turn
|
|
13122
|
+
bridgeDraft = null;
|
|
13123
|
+
// a bridge generated ahead, used only if ready in time
|
|
13096
13124
|
recent = [];
|
|
13097
13125
|
picks = /* @__PURE__ */ new Map();
|
|
13098
13126
|
inflight = null;
|
|
@@ -13228,6 +13256,7 @@ var SecondChannel = class {
|
|
|
13228
13256
|
if (this[k]) clearTimeout(this[k]);
|
|
13229
13257
|
this[k] = null;
|
|
13230
13258
|
}
|
|
13259
|
+
if (this.o.instantBridge) this.prefetchBridge();
|
|
13231
13260
|
const wait = Math.max(this.o.bridgeDelayMs, this.o.minGapMs - (this.o.now() - this.lastAt));
|
|
13232
13261
|
if (wait > 0) this.bridgeTimer = setTimeout(() => {
|
|
13233
13262
|
this.bridgeTimer = null;
|
|
@@ -13360,7 +13389,7 @@ var SecondChannel = class {
|
|
|
13360
13389
|
try {
|
|
13361
13390
|
let kind = rule;
|
|
13362
13391
|
let choice;
|
|
13363
|
-
if (this.o.decide && !cue) {
|
|
13392
|
+
if (this.o.decide && !cue && !(rule === "bridge" && this.o.instantBridge)) {
|
|
13364
13393
|
const ac = new AbortController();
|
|
13365
13394
|
const d = await withBudget(this.o.decide(this.tail(), { ...this.state(pauseMs), rule }, ac.signal), this.o.decisionBudgetMs, "channel decision", ac);
|
|
13366
13395
|
choice = d?.choice;
|
|
@@ -13394,7 +13423,24 @@ var SecondChannel = class {
|
|
|
13394
13423
|
call_ms: Math.round(now4 - this.startedAt)
|
|
13395
13424
|
};
|
|
13396
13425
|
}
|
|
13426
|
+
/** Start writing this turn's bridge now, so it may be ready by bridgeDelayMs. The bridge never waits for it. */
|
|
13427
|
+
prefetchBridge() {
|
|
13428
|
+
this.bridgeDraft = null;
|
|
13429
|
+
if (!this.o.generate || !this.o.generateFor.includes("bridge") || !this.lang || !this.heard) return;
|
|
13430
|
+
const gen = this.gen, ac = new AbortController();
|
|
13431
|
+
const ctx = { kind: "bridge", heard: this.tail(), state: this.main, avoid: [...this.recent], lang: this.lang };
|
|
13432
|
+
void withBudget(this.o.generate(ctx, ac.signal), Math.max(this.o.generateBudgetMs, this.o.bridgeDelayMs), "bridge generate", ac).then((raw) => {
|
|
13433
|
+
const text = cleanLine(raw ?? "", ctx.lang);
|
|
13434
|
+
if (text && gen === this.gen) this.bridgeDraft = { gen, text };
|
|
13435
|
+
}).catch((e) => log27.debug(`bridge prefetch failed: ${e?.message ?? e}`));
|
|
13436
|
+
}
|
|
13397
13437
|
async line(kind, react = true) {
|
|
13438
|
+
if (kind === "bridge" && this.o.instantBridge) {
|
|
13439
|
+
const d = this.bridgeDraft?.gen === this.gen ? this.bridgeDraft.text : "";
|
|
13440
|
+
this.bridgeDraft = null;
|
|
13441
|
+
if (d && !this.recent.some((r) => norm3(r) === norm3(d))) return d;
|
|
13442
|
+
return this.pick(kind);
|
|
13443
|
+
}
|
|
13398
13444
|
if (this.o.generate && this.o.generateFor.includes(kind) && (kind !== "backchannel" || react)) {
|
|
13399
13445
|
const ac = new AbortController();
|
|
13400
13446
|
const ctx = { kind, heard: this.tail(), state: this.main, avoid: [...this.recent], lang: this.lang, ...kind === "backchannel" && this.o.reactionGapMs ? { react: true } : {} };
|
|
@@ -13544,6 +13590,9 @@ var VoiceCall = class {
|
|
|
13544
13590
|
} : {},
|
|
13545
13591
|
mode: o.mode,
|
|
13546
13592
|
aec: o.aec,
|
|
13593
|
+
bridgeDelayMs: 700,
|
|
13594
|
+
instantBridge: true,
|
|
13595
|
+
// v3 §3: first sound <1.2s p50 — a bridge at 700ms if MAIN is still silent, no veto, no wait
|
|
13547
13596
|
...this.lang ? { lang: this.lang } : {},
|
|
13548
13597
|
...o.channel,
|
|
13549
13598
|
speak: (text, kind) => this.say(text, kind),
|
|
@@ -22471,7 +22520,7 @@ async function duplexServe(args, ai, cfg, cwd) {
|
|
|
22471
22520
|
const done2 = () => {
|
|
22472
22521
|
if (seq === scTurn) sc?.onAgentState("idle");
|
|
22473
22522
|
};
|
|
22474
|
-
void runTurn(dx.voice, store, session, m.text + note, void 0, cwd, (c) => dx.send(c, { id, replaces: m.replaces ? String(m.replaces) : void 0, followUp: typeof m.followUp === "string" || m.followUp && typeof m.followUp === "object" ? m.followUp : void 0 })).then(({ res, error }) => {
|
|
22523
|
+
void runTurn(dx.voice, store, session, m.text + note, void 0, cwd, (c) => dx.send(c, { id, replaces: m.replaces ? String(m.replaces) : void 0, followUp: typeof m.followUp === "string" || m.followUp && typeof m.followUp === "object" ? m.followUp : void 0, context: typeof m.context === "string" ? m.context : void 0 })).then(({ res, error }) => {
|
|
22475
22524
|
const why = (res?.finishReason ?? "error") === "error" ? duplexError(res?.error ?? error, dx.options.reflexModel) : "";
|
|
22476
22525
|
done2();
|
|
22477
22526
|
out({ type: "turn_done", id, finishReason: res?.finishReason ?? "error", ...why ? { error: why } : {} });
|