@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/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, 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, L as LineKind, C as ChannelMode, q as SecondChannelOptions, S as SecondChannel } from './secondChannel-3IPP3Qgh.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-3IPP3Qgh.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';
|
|
@@ -1275,6 +1275,11 @@ declare class DuplexAgent {
|
|
|
1275
1275
|
* back and re-run once on `reflexFallbackModel` — a re-prompt of the same model (the dead-air nudge) only hits the
|
|
1276
1276
|
* same limit and ends in "could you say that again?". */
|
|
1277
1277
|
private reflexSend;
|
|
1278
|
+
/** The host's per-line context (call rules, browser context, earlier conversation) rides THIS call only, fenced as the app's —
|
|
1279
|
+
* inside the user turn it read as the user's own words (live #938: "repeat everything I said" recited the call rules). The
|
|
1280
|
+
* stored turn keeps only what the user said, so later turns, briefs and the saved session never carry it. A block, not a
|
|
1281
|
+
* mid-transcript system message: the Anthropic/Google adapters keep only the leading system message. */
|
|
1282
|
+
private sendWithContext;
|
|
1278
1283
|
/** The turn SAID it is on it ("got it — checking…") but called no tool and nothing is running: a promise nothing
|
|
1279
1284
|
* keeps — the user waits on silence (live Para #798: a follow-up while the reflex believed a finished task still ran). */
|
|
1280
1285
|
private get hollowPromise();
|
|
@@ -1341,6 +1346,7 @@ declare class DuplexAgent {
|
|
|
1341
1346
|
id?: string;
|
|
1342
1347
|
replaces?: string;
|
|
1343
1348
|
followUp?: string | Record<string, string>;
|
|
1349
|
+
context?: string;
|
|
1344
1350
|
}): Promise<RunResult>;
|
|
1345
1351
|
/** Host-named user turns (send opts.id), so a later send can replace one. Bounded; a replace that arrives
|
|
1346
1352
|
* BEFORE its target (the host's dispatch hops can reorder) leaves a pre-superseded record behind. */
|
package/dist/index.js
CHANGED
|
@@ -10177,6 +10177,14 @@ function nameScore(want, have) {
|
|
|
10177
10177
|
var RESERVED_EVENT_MARKER = /\[task\b[^\]\n]*\b(?:completed|failed|progress|asks)\b/i;
|
|
10178
10178
|
var RESERVED_EVENT_OPENER = /\[\s*task\b/i;
|
|
10179
10179
|
var STAGE_DIRECTION_RE = /^\(\s*(?:(?:waiting|checking|searching|thinking|processing|loading|working|fetching|looking)\b[^)]*|[^)]*(?:\.\.\.|…)\s*)\)$/i;
|
|
10180
|
+
function hostContextBlock(context) {
|
|
10181
|
+
return `<host_context>
|
|
10182
|
+
${context.trim()}
|
|
10183
|
+
</host_context>
|
|
10184
|
+
(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.)
|
|
10185
|
+
|
|
10186
|
+
`;
|
|
10187
|
+
}
|
|
10180
10188
|
function nowLine() {
|
|
10181
10189
|
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" })}`;
|
|
10182
10190
|
}
|
|
@@ -10670,9 +10678,9 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
10670
10678
|
/** One reflex model call for a turn; a turn rejected for load (rateLimited) that has not spoken or dispatched yet is rolled
|
|
10671
10679
|
* back and re-run once on `reflexFallbackModel` — a re-prompt of the same model (the dead-air nudge) only hits the
|
|
10672
10680
|
* same limit and ends in "could you say that again?". */
|
|
10673
|
-
async reflexSend(content) {
|
|
10681
|
+
async reflexSend(content, context) {
|
|
10674
10682
|
const base = this.voice.transcript.length;
|
|
10675
|
-
const res = await this.
|
|
10683
|
+
const res = await this.sendWithContext(content, context);
|
|
10676
10684
|
const fb = this.options.reflexFallbackModel, model = this.voice.options.model;
|
|
10677
10685
|
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;
|
|
10678
10686
|
log24.warn(`reflex ${model} rate-limited \u2014 re-running the turn on ${fb}`);
|
|
@@ -10680,11 +10688,25 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
10680
10688
|
this.voice.transcript.length = base;
|
|
10681
10689
|
this.voice.options.model = fb;
|
|
10682
10690
|
try {
|
|
10683
|
-
return await this.
|
|
10691
|
+
return await this.sendWithContext(content, context);
|
|
10684
10692
|
} finally {
|
|
10685
10693
|
this.voice.options.model = model;
|
|
10686
10694
|
}
|
|
10687
10695
|
}
|
|
10696
|
+
/** The host's per-line context (call rules, browser context, earlier conversation) rides THIS call only, fenced as the app's —
|
|
10697
|
+
* inside the user turn it read as the user's own words (live #938: "repeat everything I said" recited the call rules). The
|
|
10698
|
+
* stored turn keeps only what the user said, so later turns, briefs and the saved session never carry it. A block, not a
|
|
10699
|
+
* mid-transcript system message: the Anthropic/Google adapters keep only the leading system message. */
|
|
10700
|
+
async sendWithContext(content, context) {
|
|
10701
|
+
if (!context?.trim() || typeof content !== "string") return this.voice.send(content);
|
|
10702
|
+
const base = this.voice.transcript.length;
|
|
10703
|
+
try {
|
|
10704
|
+
return await this.voice.send(hostContextBlock(context) + content);
|
|
10705
|
+
} finally {
|
|
10706
|
+
const m = this.voice.transcript.slice(base).find((x) => x.role === "user");
|
|
10707
|
+
if (m) m.content = content;
|
|
10708
|
+
}
|
|
10709
|
+
}
|
|
10688
10710
|
/** The turn SAID it is on it ("got it — checking…") but called no tool and nothing is running: a promise nothing
|
|
10689
10711
|
* keeps — the user waits on silence (live Para #798: a follow-up while the reflex believed a finished task still ran). */
|
|
10690
10712
|
get hollowPromise() {
|
|
@@ -10888,6 +10910,7 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
10888
10910
|
* second Act). The host gets `turn_replace` {id, replaces, rolledBack, followed?}: only a rollback drops the replaced
|
|
10889
10911
|
* line; `followed` = the kept turn whose follow-up ran (absent: the merged text ran). */
|
|
10890
10912
|
send(content, opts) {
|
|
10913
|
+
const ctx = opts?.context;
|
|
10891
10914
|
this.clearHoldResume();
|
|
10892
10915
|
this.holdResumed = false;
|
|
10893
10916
|
if (opts?.replaces) this.replaceTurn(opts.replaces);
|
|
@@ -10913,7 +10936,7 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
10913
10936
|
if (intent === "resume" && !reflexCut) return this.resumeParked();
|
|
10914
10937
|
if (intent === "aside" || intent === "resume") {
|
|
10915
10938
|
const told = intent === "aside" ? [...this.parkedRedeliver] : [];
|
|
10916
|
-
return this.sendTurn(intent === "aside" ? content + this.asideNote(told) : content, true, rec, ext).then(async (r) => {
|
|
10939
|
+
return this.sendTurn(intent === "aside" ? content + this.asideNote(told) : content, true, rec, ext, ctx).then(async (r) => {
|
|
10917
10940
|
if (r.finishReason === "aborted" || this.heldThisTurn) return r;
|
|
10918
10941
|
const missed = unsaidClauses(told.map((p) => p.text), this.turnSpoken, this.options.decider);
|
|
10919
10942
|
const turn = this.turn;
|
|
@@ -10928,10 +10951,10 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
10928
10951
|
return r;
|
|
10929
10952
|
});
|
|
10930
10953
|
}
|
|
10931
|
-
return this.sendTurn(content, false, rec, ext);
|
|
10954
|
+
return this.sendTurn(content, false, rec, ext, ctx);
|
|
10932
10955
|
});
|
|
10933
10956
|
}
|
|
10934
|
-
return this.sendTurn(typeof content === "string" ? content + this.acceptNote(content) : content, false, rec, ext);
|
|
10957
|
+
return this.sendTurn(typeof content === "string" ? content + this.acceptNote(content) : content, false, rec, ext, ctx);
|
|
10935
10958
|
}
|
|
10936
10959
|
/** Host-named user turns (send opts.id), so a later send can replace one. Bounded; a replace that arrives
|
|
10937
10960
|
* BEFORE its target (the host's dispatch hops can reorder) leaves a pre-superseded record behind. */
|
|
@@ -10999,7 +11022,7 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
10999
11022
|
return { text: "", steps: 0, finishReason: "stop", messages: [] };
|
|
11000
11023
|
});
|
|
11001
11024
|
}
|
|
11002
|
-
sendTurn(content, keepParked = false, rec, ext) {
|
|
11025
|
+
sendTurn(content, keepParked = false, rec, ext, context) {
|
|
11003
11026
|
const spec = this.spec;
|
|
11004
11027
|
if (spec?.state === "pending") {
|
|
11005
11028
|
if (typeof content === "string" && speculationConfirms(spec.text, content)) {
|
|
@@ -11052,7 +11075,7 @@ ${nowLine()}. Anchor every relative or time-sensitive reference \u2014 "today",
|
|
|
11052
11075
|
if (typeof content === "string") content += spellingNote(content);
|
|
11053
11076
|
let res;
|
|
11054
11077
|
try {
|
|
11055
|
-
res = await this.reflexSend(content);
|
|
11078
|
+
res = await this.reflexSend(content, context);
|
|
11056
11079
|
} finally {
|
|
11057
11080
|
if (signal) {
|
|
11058
11081
|
this.voice.options.signal = ext;
|
|
@@ -12690,6 +12713,9 @@ var SecondChannelOptions = class {
|
|
|
12690
12713
|
/** A bridge waits this long after the user's turn is dispatched, and plays only if channel-1 has said nothing yet
|
|
12691
12714
|
* (a fast reply/ack needs no bridge — one before it reads as the agent starting a different sentence). 0 = at once. */
|
|
12692
12715
|
bridgeDelayMs = 1200;
|
|
12716
|
+
/** Duplex v3 (§3 first sound): a bridge skips the decider (the veto stays for backchannels/fillers) and speaks a
|
|
12717
|
+
* canned line at once; a generated one is started at dispatch and used only if it already landed. */
|
|
12718
|
+
instantBridge = false;
|
|
12693
12719
|
/** No new interim for this long → a pause (hosts may also call onPause). */
|
|
12694
12720
|
fillerPauseMs = 700;
|
|
12695
12721
|
fillerMinWords = 4;
|
|
@@ -12761,6 +12787,8 @@ var SecondChannel = class {
|
|
|
12761
12787
|
// the line the last barge actually cut (spoke())
|
|
12762
12788
|
bridged = false;
|
|
12763
12789
|
// one bridge per main turn
|
|
12790
|
+
bridgeDraft = null;
|
|
12791
|
+
// a bridge generated ahead, used only if ready in time
|
|
12764
12792
|
recent = [];
|
|
12765
12793
|
picks = /* @__PURE__ */ new Map();
|
|
12766
12794
|
inflight = null;
|
|
@@ -12896,6 +12924,7 @@ var SecondChannel = class {
|
|
|
12896
12924
|
if (this[k]) clearTimeout(this[k]);
|
|
12897
12925
|
this[k] = null;
|
|
12898
12926
|
}
|
|
12927
|
+
if (this.o.instantBridge) this.prefetchBridge();
|
|
12899
12928
|
const wait = Math.max(this.o.bridgeDelayMs, this.o.minGapMs - (this.o.now() - this.lastAt));
|
|
12900
12929
|
if (wait > 0) this.bridgeTimer = setTimeout(() => {
|
|
12901
12930
|
this.bridgeTimer = null;
|
|
@@ -13028,7 +13057,7 @@ var SecondChannel = class {
|
|
|
13028
13057
|
try {
|
|
13029
13058
|
let kind = rule;
|
|
13030
13059
|
let choice;
|
|
13031
|
-
if (this.o.decide && !cue) {
|
|
13060
|
+
if (this.o.decide && !cue && !(rule === "bridge" && this.o.instantBridge)) {
|
|
13032
13061
|
const ac = new AbortController();
|
|
13033
13062
|
const d = await withBudget(this.o.decide(this.tail(), { ...this.state(pauseMs), rule }, ac.signal), this.o.decisionBudgetMs, "channel decision", ac);
|
|
13034
13063
|
choice = d?.choice;
|
|
@@ -13062,7 +13091,24 @@ var SecondChannel = class {
|
|
|
13062
13091
|
call_ms: Math.round(now3 - this.startedAt)
|
|
13063
13092
|
};
|
|
13064
13093
|
}
|
|
13094
|
+
/** Start writing this turn's bridge now, so it may be ready by bridgeDelayMs. The bridge never waits for it. */
|
|
13095
|
+
prefetchBridge() {
|
|
13096
|
+
this.bridgeDraft = null;
|
|
13097
|
+
if (!this.o.generate || !this.o.generateFor.includes("bridge") || !this.lang || !this.heard) return;
|
|
13098
|
+
const gen = this.gen, ac = new AbortController();
|
|
13099
|
+
const ctx = { kind: "bridge", heard: this.tail(), state: this.main, avoid: [...this.recent], lang: this.lang };
|
|
13100
|
+
void withBudget(this.o.generate(ctx, ac.signal), Math.max(this.o.generateBudgetMs, this.o.bridgeDelayMs), "bridge generate", ac).then((raw) => {
|
|
13101
|
+
const text = cleanLine(raw ?? "", ctx.lang);
|
|
13102
|
+
if (text && gen === this.gen) this.bridgeDraft = { gen, text };
|
|
13103
|
+
}).catch((e) => log28.debug(`bridge prefetch failed: ${e?.message ?? e}`));
|
|
13104
|
+
}
|
|
13065
13105
|
async line(kind, react = true) {
|
|
13106
|
+
if (kind === "bridge" && this.o.instantBridge) {
|
|
13107
|
+
const d = this.bridgeDraft?.gen === this.gen ? this.bridgeDraft.text : "";
|
|
13108
|
+
this.bridgeDraft = null;
|
|
13109
|
+
if (d && !this.recent.some((r) => norm3(r) === norm3(d))) return d;
|
|
13110
|
+
return this.pick(kind);
|
|
13111
|
+
}
|
|
13066
13112
|
if (this.o.generate && this.o.generateFor.includes(kind) && (kind !== "backchannel" || react)) {
|
|
13067
13113
|
const ac = new AbortController();
|
|
13068
13114
|
const ctx = { kind, heard: this.tail(), state: this.main, avoid: [...this.recent], lang: this.lang, ...kind === "backchannel" && this.o.reactionGapMs ? { react: true } : {} };
|
|
@@ -13212,6 +13258,9 @@ var VoiceCall = class {
|
|
|
13212
13258
|
} : {},
|
|
13213
13259
|
mode: o.mode,
|
|
13214
13260
|
aec: o.aec,
|
|
13261
|
+
bridgeDelayMs: 700,
|
|
13262
|
+
instantBridge: true,
|
|
13263
|
+
// v3 §3: first sound <1.2s p50 — a bridge at 700ms if MAIN is still silent, no veto, no wait
|
|
13215
13264
|
...this.lang ? { lang: this.lang } : {},
|
|
13216
13265
|
...o.channel,
|
|
13217
13266
|
speak: (text, kind) => this.say(text, kind),
|