@livx.cc/agentx 0.99.57 → 0.99.58
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 +7 -0
- package/dist/cli.js +2074 -302
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +167 -29
- package/dist/index.js +1472 -186
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -889,6 +889,19 @@ declare function reflectOnRun(o: ReflectOptions): Promise<string | null>;
|
|
|
889
889
|
*/
|
|
890
890
|
declare function loadInstructions(fs: IFilesystem, names?: string[]): Promise<string>;
|
|
891
891
|
|
|
892
|
+
/** Structural subset of ai.libx.js DecideClient.decide — keeps this module provider-agnostic. */
|
|
893
|
+
interface Decider {
|
|
894
|
+
decide(o: {
|
|
895
|
+
state: unknown;
|
|
896
|
+
questions: Record<string, unknown>;
|
|
897
|
+
}): Promise<{
|
|
898
|
+
answers: Record<string, {
|
|
899
|
+
choice: string;
|
|
900
|
+
probabilities: Record<string, number>;
|
|
901
|
+
}>;
|
|
902
|
+
}>;
|
|
903
|
+
}
|
|
904
|
+
|
|
892
905
|
/**
|
|
893
906
|
* DuplexAgent — voice-optimized three-tier conversational engine, composed on top of `Agent`.
|
|
894
907
|
*
|
|
@@ -928,15 +941,24 @@ interface TaskRecord {
|
|
|
928
941
|
splitter?: SpokenSplitter;
|
|
929
942
|
/** Set when the user barged in / took the floor while this task was in flight: its remaining SPOKEN
|
|
930
943
|
* delivery is suppressed (don't talk over the new topic), but its full result still lands in the
|
|
931
|
-
* transcript so the reflex can surface it on request. See parkInFlightDeliveries().
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
*
|
|
944
|
+
* transcript so the reflex can surface it on request. See parkInFlightDeliveries().
|
|
945
|
+
* 'barge' = cut by a barge the user's next line has not resolved yet — a resume revives it (its unheard segments
|
|
946
|
+
* are parked); 'moved_on' = the user moved on (a steer, a new dispatch) or its outcome went to an integration turn
|
|
947
|
+
* (failed / stopped early) — it stays stale for good: nothing it says is spoken or parked, and no later barge or
|
|
948
|
+
* "go on" revives it. */
|
|
949
|
+
deliveryParked?: 'barge' | 'moved_on';
|
|
950
|
+
/** Accumulated `<spoken>` delivery text (every segment, whether or not it was actually voiced) — what the task
|
|
951
|
+
* SAID (TaskStatus). Never replayed: a resume replays only the unheard part (DuplexAgent.parkedRedeliver). */
|
|
935
952
|
spokenText?: string;
|
|
936
953
|
/** The user-turn counter (DuplexAgent.turn) at dispatch time. parkInFlightDeliveries() parks only tasks
|
|
937
954
|
* from a PRIOR turn (a superseded topic) — never the task the current turn just launched, so a barge on
|
|
938
955
|
* stale audio (or a substantive redirect) can't collateral-silence the work the user actually wants. */
|
|
939
956
|
createdTurn: number;
|
|
957
|
+
/** Chars of this delivery voiced so far (spokenBudgetChars); `budgetSpent` once it was cut — a resume goes on unbudgeted. */
|
|
958
|
+
voicedChars?: number;
|
|
959
|
+
budgetSpent?: boolean;
|
|
960
|
+
/** The budget offer spoken in place of the cut rest — folded into the transcript after the written result. */
|
|
961
|
+
capOffer?: string;
|
|
940
962
|
}
|
|
941
963
|
type WorkerTier = 'act' | 'think';
|
|
942
964
|
declare class DuplexAgentOptions {
|
|
@@ -972,6 +994,13 @@ declare class DuplexAgentOptions {
|
|
|
972
994
|
/** Teach the model to emit inline `[emotion]` tags for Cartesia emotion control. Only set when the
|
|
973
995
|
* TTS actually speaks them — text-duplex (no TTS) would otherwise print literal tags. */
|
|
974
996
|
emotionTags: boolean;
|
|
997
|
+
/** Judge a post-barge line while a delivery is parked: resume it now, answer an aside and carry it on (the reflex,
|
|
998
|
+
* told what was heard — see asideNote), or drop it (steer/stop). Unset → the conservative `isTrivialBarge` allowlist (resume | steer); a throwing judge
|
|
999
|
+
* falls back to it too. */
|
|
1000
|
+
bargeIntent?: (text: string) => Promise<'resume' | 'aside' | 'steer' | 'stop'>;
|
|
1001
|
+
/** Typed-decision model (e.g. ai.libx.js DecideClient → Jev). Judges reflex sentences the leak screen flags as
|
|
1002
|
+
* SUSPECT (src/voice/leak.ts) — only suspects pay the ~300ms call. Unset → only the strict leak shapes are cut. */
|
|
1003
|
+
decider?: Decider;
|
|
975
1004
|
/** Awaited BEFORE a worker spawns — open a per-task checkpoint frame, audit, etc.
|
|
976
1005
|
* (post-spawn would race the worker's first edits). */
|
|
977
1006
|
onTaskStart?: (id: string, label: string) => void | Promise<void>;
|
|
@@ -980,6 +1009,13 @@ declare class DuplexAgentOptions {
|
|
|
980
1009
|
progressUpdates: boolean;
|
|
981
1010
|
/** Min ms between progress re-voices per task. */
|
|
982
1011
|
progressIntervalMs: number;
|
|
1012
|
+
/** Spoken budget of ONE task delivery (chars, ~3 short sentences). Past it the rest is parked — cut at a sentence
|
|
1013
|
+
* boundary, `spokenOffer` spoken instead — so "go on" continues it once (the parked/resume path) and an aside or
|
|
1014
|
+
* steer handles it like any parked delivery. The worker is also asked for a short spoken summary + one offer (the
|
|
1015
|
+
* source); this is the backstop. Live 20260924-093945: ~20s and ~70s monologues whose closing choice went unspoken.
|
|
1016
|
+
* The full result always folds into the transcript. 0 = unbudgeted. */
|
|
1017
|
+
spokenBudgetChars: number;
|
|
1018
|
+
spokenOffer: string;
|
|
983
1019
|
/** Relay worker questions (AskUserQuestion + permission asks via parkQuestion) through the VOICE:
|
|
984
1020
|
* the question re-voices as '[task <id> asks] …', the user answers conversationally, and the
|
|
985
1021
|
* voice model resolves it with the AnswerTask tool. Off → host.ask passthrough (text menus). */
|
|
@@ -1015,14 +1051,22 @@ declare class DuplexAgent {
|
|
|
1015
1051
|
* (TaskRecord.createdTurn) so parking can tell a prior-topic task from the current turn's fresh one. */
|
|
1016
1052
|
private turn;
|
|
1017
1053
|
private pendingEvents;
|
|
1018
|
-
/**
|
|
1019
|
-
*
|
|
1054
|
+
/** THE parked delivery: every piece the user has NOT heard, in speaking order — the unheard rest a barge cut out of
|
|
1055
|
+
* the voice queue (parkCutDelivery) followed by each segment a barge-parked task produced since (deliverSegment).
|
|
1056
|
+
* Nothing already voiced is ever added, so a resume never repeats what was heard. The next line's barge intent
|
|
1057
|
+
* decides: resume → spoken verbatim, aside → handed to the reflex to carry on after its answer (asideNote) — both
|
|
1058
|
+
* send the barge-parked tasks live again; steer/stop → cleared, and those tasks
|
|
1059
|
+
* are moved on from (the full result stays in the transcript, recoverable by asking). `task` = the owner, so a
|
|
1060
|
+
* task whose outcome goes to an integration turn takes its pieces back (dropParked). */
|
|
1020
1061
|
private parkedRedeliver;
|
|
1021
|
-
/**
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1062
|
+
/** parkedRedeliver length when the last barge parked (parkInFlightDeliveries): the cut it hands over later
|
|
1063
|
+
* (parkCutDelivery) was voiced BEFORE anything parked since, so it is inserted here. */
|
|
1064
|
+
private bargeMark;
|
|
1065
|
+
/** The last barge cut a REFLEX reply (parkCutDelivery): a "go on" is then the reflex's to answer — it runs a normal
|
|
1066
|
+
* turn (the host's interruption note continues the reply), and only then does the parked delivery resume. */
|
|
1067
|
+
private reflexCut;
|
|
1068
|
+
/** Recent live task segments → their task id: attributes a cut delivery (parkCutDelivery) to the task that spoke it. */
|
|
1069
|
+
private voicedBy;
|
|
1026
1070
|
/** Out-of-band follow-up attribution for the events coalescing into the next flush turn: TRUE iff ≥1 of
|
|
1027
1071
|
* the tasks being integrated was NON-CLEAN (early-stop/failure). Carried out-of-band on the enqueue call
|
|
1028
1072
|
* by the caller that KNOWS the outcome — a plain boolean the MODEL CANNOT PERTURB. It is NOT scanned from
|
|
@@ -1045,6 +1089,15 @@ declare class DuplexAgent {
|
|
|
1045
1089
|
private reflexBuf;
|
|
1046
1090
|
private reflexForwarded;
|
|
1047
1091
|
private fabricationCut;
|
|
1092
|
+
private leakCuts;
|
|
1093
|
+
private leakStep;
|
|
1094
|
+
private leakHit;
|
|
1095
|
+
private stepMarks;
|
|
1096
|
+
private leakVerdicts;
|
|
1097
|
+
private judging?;
|
|
1098
|
+
private turnGen;
|
|
1099
|
+
private turnSpoken;
|
|
1100
|
+
private turnBase;
|
|
1048
1101
|
/** TRUE for the duration of a re-voice turn that is integrating ≥1 NON-CLEAN task (turn-eligibility,
|
|
1049
1102
|
* carried out-of-band — NOT derived from any worker/brief string). ANY Act/Think dispatched in such a
|
|
1050
1103
|
* turn is stamped followUp:true. This GUARANTEES the dangerous direction is impossible: a genuine
|
|
@@ -1082,9 +1135,38 @@ declare class DuplexAgent {
|
|
|
1082
1135
|
constructor(options?: Partial<DuplexAgentOptions>);
|
|
1083
1136
|
/** Resolve memory tools + inject index into voice system prompt (once). */
|
|
1084
1137
|
private initMemory;
|
|
1085
|
-
/**
|
|
1086
|
-
*
|
|
1087
|
-
|
|
1138
|
+
/** Forward what the reflex's spoken-stream gates allow (text_delta → host/TTS; forwarded audio can't be unsent):
|
|
1139
|
+
* - hold a trailing fragment that could be a `[task` opener split across deltas ("[ta" + "sk"), and an UNCLOSED
|
|
1140
|
+
* "(" (a stage direction is judged — and dropped — only once its ")" arrives; bounded at 80 chars);
|
|
1141
|
+
* - the leak gate: whole sentences only, each screened by isLeakSuspect the moment it completes — a strict match
|
|
1142
|
+
* is cut, any other suspect waits for the decider's verdict (judgeLeak) while the rest queues behind it.
|
|
1143
|
+
* `final` = the stream is done: release the holds and judge whatever is left as a sentence. Text before a step
|
|
1144
|
+
* boundary (stepMarks) is complete — no holds, its tail is a sentence. Idempotent; re-run as verdicts land. */
|
|
1145
|
+
private pumpReflex;
|
|
1146
|
+
private forwardReflex;
|
|
1147
|
+
/** Leak verdict for one complete sentence: false = speak, true = cut, undefined = the judge is still out.
|
|
1148
|
+
* Non-suspects pass free; strict shapes are cut without a call; other suspects go to the decider (if any) —
|
|
1149
|
+
* one call at a time, cached per turn. A failed/slow judge fails OPEN (speech is never muted on a guess). */
|
|
1150
|
+
private leakVerdict;
|
|
1151
|
+
private static readonly LEAK_JUDGE_TIMEOUT_MS;
|
|
1152
|
+
/** The stream is done: settle every pending verdict and release everything the gates still hold. */
|
|
1153
|
+
private drainReflex;
|
|
1154
|
+
/** Drop any in-flight judge of the current stream (its verdict must not pump a stream that moved on). */
|
|
1155
|
+
private dropJudge;
|
|
1156
|
+
/** Remove a cut analysis leak from this turn's assistant message(s) — left in, it primes the next turn to
|
|
1157
|
+
* leak again and reads as something we said. Keeps any legit prefix; drops a message left empty. */
|
|
1158
|
+
private scrubLeakFromTranscript;
|
|
1159
|
+
/** A Hold turn is silent BY DESIGN: every reflex text after the Hold is muted (voiceHost drops it), so none of it may
|
|
1160
|
+
* persist either — the transcript is what the agent SAID. Live 20260923-125143 msg 10: the model's reasoning ("We
|
|
1161
|
+
* need to respond according to guidelines… So we should hold") was saved as an assistant reply and fed every later
|
|
1162
|
+
* turn. Strips the text of assistant messages after the Hold call (tool calls stay — they happened); a message left
|
|
1163
|
+
* empty is removed. */
|
|
1164
|
+
private scrubHeldText;
|
|
1165
|
+
/** Shared turn epilogue (user turn, confirmed speculation, re-voice): release held text, scrub a cut leak,
|
|
1166
|
+
* then repair dead air — unless the turn was ABORTED: the user took the floor (barge-in / Esc), which is
|
|
1167
|
+
* not dead air, and a nudge would run on the same aborted signal (live: the "[reminder]" landed in the
|
|
1168
|
+
* transcript as a user turn with no reply, session 20260923-101910 msg 27). */
|
|
1169
|
+
private endTurn;
|
|
1088
1170
|
/** Remove complete stage-direction parentheticals from the UNFORWARDED reflex text (STAGE_DIRECTION_RE).
|
|
1089
1171
|
* Only the unforwarded region is touched — already-spoken audio can't be unsent, and splicing before
|
|
1090
1172
|
* reflexForwarded would corrupt the forward offset. */
|
|
@@ -1115,13 +1197,35 @@ declare class DuplexAgent {
|
|
|
1115
1197
|
* hosts/tests key on it. */
|
|
1116
1198
|
private static readonly FALLBACK_ACKS;
|
|
1117
1199
|
private static readonly FALLBACK_RETRY;
|
|
1200
|
+
private static readonly FALLBACK_OWN;
|
|
1118
1201
|
private lastFallback;
|
|
1119
1202
|
/** One user turn: the voice agent streams the reply (and may Act/Think). Serialized with re-voice turns.
|
|
1120
1203
|
* If a speculative reflex call is pending and this content CONFIRMS it (the final matches the
|
|
1121
1204
|
* speculated partial), the in-flight call is adopted as THE turn: its buffered output flushes to the
|
|
1122
1205
|
* host NOW (this is the latency win) and streaming continues live. Any other content aborts the
|
|
1123
|
-
* speculation first (rolled back silently) and runs a normal turn behind it.
|
|
1124
|
-
|
|
1206
|
+
* speculation first (rolled back silently) and runs a normal turn behind it.
|
|
1207
|
+
* `opts.id` names the turn; `opts.replaces` names an earlier one this content REPLACES — the voice engine's
|
|
1208
|
+
* fuller re-finalization of an utterance whose reply had not started ("…previous" → "…previous
|
|
1209
|
+
* conversation."). The replaced turn is skipped if it has not run yet, else aborted and rolled back out of
|
|
1210
|
+
* the transcript (kept only if it already dispatched work) — one reply, to the full text. */
|
|
1211
|
+
send(content: MessageContent, opts?: {
|
|
1212
|
+
id?: string;
|
|
1213
|
+
replaces?: string;
|
|
1214
|
+
}): Promise<RunResult>;
|
|
1215
|
+
/** Host-named user turns (send opts.id), so a later send can replace one. Bounded; a replace that arrives
|
|
1216
|
+
* BEFORE its target (the host's dispatch hops can reorder) leaves a pre-superseded record behind. */
|
|
1217
|
+
private userTurns;
|
|
1218
|
+
private turnSignal?;
|
|
1219
|
+
private trackTurn;
|
|
1220
|
+
private replaceTurn;
|
|
1221
|
+
private static replacedResult;
|
|
1222
|
+
/** A turn replaced mid-run: mute whatever it still holds, and erase it from the transcript (the replacing turn
|
|
1223
|
+
* carries the user's full words) — unless it already dispatched work or SPOKE: the task is real, and the user
|
|
1224
|
+
* heard those words, so both stay visible to the replacing turn. An aborted stream never reaches the transcript,
|
|
1225
|
+
* so what was spoken is recorded as the replaced turn's reply. */
|
|
1226
|
+
private dropReplacedTurn;
|
|
1227
|
+
private resumeParked;
|
|
1228
|
+
private sendTurn;
|
|
1125
1229
|
/** Start a HELD speculative reflex turn on a stable partial (VoiceEngine.onSpeculate). Its spoken
|
|
1126
1230
|
* output buffers in emitHost; send() later confirms (flush + adopt) or aborts it. The turn holds the
|
|
1127
1231
|
* voice mutex until that decision (bounded by a safety timeout), so no other turn can interleave
|
|
@@ -1138,18 +1242,45 @@ declare class DuplexAgent {
|
|
|
1138
1242
|
* superseded topic never talks over the new one (the debt-after-jokes regression). Tasks keep running and
|
|
1139
1243
|
* still fold their result into the transcript — recoverable, just not spoken. Returns parked ids (logging).
|
|
1140
1244
|
* Does NOT cancel. Two callers, two shapes:
|
|
1141
|
-
* - BARGE (default): the user interrupted AUDIO. Park EVERY running task (including this turn's) — the
|
|
1142
|
-
* worker they cut off must stop, whatever turn launched it —
|
|
1143
|
-
*
|
|
1144
|
-
* - SUPERSEDE (`priorTurnsOnly`, `
|
|
1145
|
-
*
|
|
1146
|
-
*
|
|
1147
|
-
parkInFlightDeliveries(
|
|
1148
|
-
/**
|
|
1149
|
-
* one
|
|
1245
|
+
* - BARGE (default): the user interrupted AUDIO. Park EVERY live running task (including this turn's) — the
|
|
1246
|
+
* worker they cut off must stop, whatever turn launched it — as 'barge', so a following "go on" can bring
|
|
1247
|
+
* it back. A task the user already moved on from stays moved on: a barge never revives it.
|
|
1248
|
+
* - SUPERSEDE (`priorTurnsOnly`, `barge:false`, from dispatch()): a new dispatch redirected to fresh work.
|
|
1249
|
+
* Park only PRIOR-turn live tasks so parallel siblings dispatched in the SAME turn don't silence each other,
|
|
1250
|
+
* as 'moved_on' (don't resurface on a stray "go on"). */
|
|
1251
|
+
parkInFlightDeliveries(barge?: boolean, priorTurnsOnly?: boolean): string[];
|
|
1252
|
+
/** A barge-in cut a worker delivery the VOICE ENGINE was still speaking — the queued utterances it dropped plus the
|
|
1253
|
+
* unheard rest of the one playing (cli splitCut). It joins the parked delivery AHEAD of whatever parked tasks
|
|
1254
|
+
* produced since the barge (it was voiced first); the user's next line runs the barge-intent judge — resume it,
|
|
1255
|
+
* answer an aside and carry it on, or drop it on a steer/stop. `heard` = the cut utterance's part the user DID hear
|
|
1256
|
+
* (the aside note tells the reflex what was heard vs missed).
|
|
1257
|
+
* Live 20260923-125143: "Oh, that— that's new." cut an iOS-news delivery and its 6 remaining utterances vanished.
|
|
1258
|
+
* `reflexCut` = the barge cut a REFLEX reply (the host's cut had a reply): a "go on" then runs the reflex (see send).
|
|
1259
|
+
* A cut spoken by a task the user moved on from (or whose outcome went to an integration turn) is not parked. */
|
|
1260
|
+
parkCutDelivery(text: string, reflexCut?: boolean, heard?: string): void;
|
|
1261
|
+
/** One spoken segment of a task's delivery — the ONLY path a worker's speech takes (streamed segments, the settle
|
|
1262
|
+
* tail, the no-spoken fallback). Live → the voice queue; barge-parked → the parked delivery, in order; superseded
|
|
1263
|
+
* (the user moved on) → nowhere (the result still folds into the transcript at settle). */
|
|
1264
|
+
private deliverSegment;
|
|
1265
|
+
/** Split a delivery segment at the spoken budget (whole sentences; the first sentence always speaks): what to voice
|
|
1266
|
+
* now, and the rest to park. Marks the budget spent on a cut, so a resumed delivery runs on unbudgeted. */
|
|
1267
|
+
private budgetSplit;
|
|
1268
|
+
/** The cap offer last spoken and the task whose rest it offers — a barge over it is not a delivery to park
|
|
1269
|
+
* (parkCutDelivery). */
|
|
1270
|
+
private offer;
|
|
1271
|
+
/** The cap offer was the last thing voiced (no delivery or turn has spoken since) — a plain yes accepts it (send). */
|
|
1272
|
+
private offerOpen;
|
|
1273
|
+
/** The task's outcome now belongs to its integration turn (failed / stopped early): take back its parked pieces and
|
|
1274
|
+
* keep it from being revived — a "go on" must not replay raw segments of a result the reflex is about to explain. */
|
|
1275
|
+
private dropParked;
|
|
1276
|
+
/** True while there is a parked delivery the next line may resume: unheard text already parked, or a barge-parked
|
|
1277
|
+
* task still running (one the user moved on from does not count). */
|
|
1150
1278
|
private hasParkedDelivery;
|
|
1151
|
-
/**
|
|
1152
|
-
*
|
|
1279
|
+
/** The note for an aside over a parked delivery: the same reply-interruption note a cut reflex reply gets
|
|
1280
|
+
* (interruptionNote), over the delivery as it was being said — the cut utterance's heard part, then every unheard
|
|
1281
|
+
* piece. Nothing parked yet (the task is still working) → its result simply follows the answer. */
|
|
1282
|
+
private asideNote;
|
|
1283
|
+
/** Speak the parked delivery now (resume), in order, and clear it. */
|
|
1153
1284
|
private redeliverParked;
|
|
1154
1285
|
/** Resolve when all queued voice turns AND all in-flight worker tasks have settled (tests, graceful shutdown). */
|
|
1155
1286
|
idle(): Promise<void>;
|
|
@@ -1170,6 +1301,8 @@ declare class DuplexAgent {
|
|
|
1170
1301
|
* Act briefs get a self-verify footer — the worker's report is trusted without review, so it
|
|
1171
1302
|
* must check its own work before reporting (nearly free under prompt caching; measured honest:
|
|
1172
1303
|
* it does NOT fix one-shot logic bugs — see mind/10). Think tasks are pure reasoning — no footer. */
|
|
1304
|
+
/** Static text snapshot of the last `turns` user/assistant messages (`role: text` lines). */
|
|
1305
|
+
recentExcerpt(turns?: number): string;
|
|
1173
1306
|
private buildBrief;
|
|
1174
1307
|
/** Spawn a detached worker for task `id`; its settlement notifies + enqueues the re-voice turn. */
|
|
1175
1308
|
private spawnWorker;
|
|
@@ -1209,11 +1342,11 @@ declare class DuplexAgent {
|
|
|
1209
1342
|
private integrationPrompt;
|
|
1210
1343
|
private onWorkerSettled;
|
|
1211
1344
|
private onWorkerFailed;
|
|
1212
|
-
/** A delivery the user has SUPERSEDED —
|
|
1345
|
+
/** A delivery the user has SUPERSEDED — moved on from (deliveryParked 'moved_on', set by a redirect) —
|
|
1213
1346
|
* must not hijack the voice when it settles late (partial or failed): that would talk over the new topic
|
|
1214
1347
|
* and, worse, auto-escalate work the user already abandoned. Fold a recoverable note into the transcript
|
|
1215
1348
|
* instead (the reflex can surface it if asked) and report true so the caller skips queueRevoice. A merely
|
|
1216
|
-
* barge-parked task (
|
|
1349
|
+
* barge-parked task ('barge' — a "go on" may still resume it) is NOT superseded: it
|
|
1217
1350
|
* keeps the normal surfacing path so a failure the user still cares about is not swallowed. */
|
|
1218
1351
|
private foldIfSuperseded;
|
|
1219
1352
|
private failTask;
|
|
@@ -1226,6 +1359,11 @@ declare class DuplexAgent {
|
|
|
1226
1359
|
* `followUp` marks an automatic escalation/re-delegation (set by the integration turn) so the new
|
|
1227
1360
|
* task's own integration turn won't escalate again — capping auto-follow-ups to one hop. */
|
|
1228
1361
|
dispatch(brief: string, tier?: WorkerTier, label?: string, followUp?: boolean): Promise<string>;
|
|
1362
|
+
/** Tool result for a dispatch. The task is ALREADY RUNNING — live, the terse "Acknowledge briefly" drew
|
|
1363
|
+
* "Did you want me to look up today's news?" right after dispatching exactly that (session 20260923-101910
|
|
1364
|
+
* msg 18). Also truthful about delivery: a clean result is spoken by the worker itself and lands in
|
|
1365
|
+
* context (TaskStatus returns it); only failures come back as a [task … failed] event. */
|
|
1366
|
+
private dispatchResult;
|
|
1229
1367
|
private actTool;
|
|
1230
1368
|
private thinkTool;
|
|
1231
1369
|
private taskStatusTool;
|