@animalabs/agent-framework 0.29.0 → 0.30.0
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/src/admission/admit.d.ts +90 -0
- package/dist/src/admission/admit.d.ts.map +1 -0
- package/dist/src/admission/admit.js +43 -0
- package/dist/src/admission/admit.js.map +1 -0
- package/dist/src/agent.d.ts +21 -0
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +43 -6
- package/dist/src/agent.js.map +1 -1
- package/dist/src/author-presentation.d.ts +50 -0
- package/dist/src/author-presentation.d.ts.map +1 -0
- package/dist/src/author-presentation.js +58 -0
- package/dist/src/author-presentation.js.map +1 -0
- package/dist/src/dendrite/index.d.ts +6 -0
- package/dist/src/dendrite/index.d.ts.map +1 -0
- package/dist/src/dendrite/index.js +3 -0
- package/dist/src/dendrite/index.js.map +1 -0
- package/dist/src/dendrite/presets.d.ts +60 -0
- package/dist/src/dendrite/presets.d.ts.map +1 -0
- package/dist/src/dendrite/presets.js +117 -0
- package/dist/src/dendrite/presets.js.map +1 -0
- package/dist/src/dendrite/registry.d.ts +260 -0
- package/dist/src/dendrite/registry.d.ts.map +1 -0
- package/dist/src/dendrite/registry.js +742 -0
- package/dist/src/dendrite/registry.js.map +1 -0
- package/dist/src/dendrite/types.d.ts +392 -0
- package/dist/src/dendrite/types.d.ts.map +1 -0
- package/dist/src/dendrite/types.js +24 -0
- package/dist/src/dendrite/types.js.map +1 -0
- package/dist/src/framework.d.ts +684 -33
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +2998 -350
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +12 -4
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +25 -5
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/host-presentation.d.ts +4 -0
- package/dist/src/host-presentation.d.ts.map +1 -1
- package/dist/src/host-presentation.js +7 -3
- package/dist/src/host-presentation.js.map +1 -1
- package/dist/src/index.d.ts +5 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +84 -9
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +136 -58
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +9 -0
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +21 -0
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/toolsets-module.d.ts.map +1 -1
- package/dist/src/mcpl/toolsets-module.js +7 -0
- package/dist/src/mcpl/toolsets-module.js.map +1 -1
- package/dist/src/notice-tags.d.ts +2 -0
- package/dist/src/notice-tags.d.ts.map +1 -1
- package/dist/src/notice-tags.js +2 -0
- package/dist/src/notice-tags.js.map +1 -1
- package/dist/src/silent-heartbeat.d.ts +4 -2
- package/dist/src/silent-heartbeat.d.ts.map +1 -1
- package/dist/src/silent-heartbeat.js +7 -4
- package/dist/src/silent-heartbeat.js.map +1 -1
- package/dist/src/stored-injections.d.ts +4 -0
- package/dist/src/stored-injections.d.ts.map +1 -1
- package/dist/src/stored-injections.js +6 -0
- package/dist/src/stored-injections.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +379 -9
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +1080 -97
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/tune-out/tools.d.ts +101 -5
- package/dist/src/tune-out/tools.d.ts.map +1 -1
- package/dist/src/tune-out/tools.js +55 -18
- package/dist/src/tune-out/tools.js.map +1 -1
- package/dist/src/types/agent.d.ts +25 -0
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +99 -0
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +136 -0
- package/dist/src/types/trace.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/admission/admit.ts +113 -0
- package/src/agent.ts +48 -6
- package/src/author-presentation.ts +81 -0
- package/src/dendrite/index.ts +32 -0
- package/src/dendrite/presets.ts +149 -0
- package/src/dendrite/registry.ts +808 -0
- package/src/dendrite/types.ts +397 -0
- package/src/framework.ts +3239 -369
- package/src/gate/event-gate.ts +31 -5
- package/src/host-presentation.ts +10 -3
- package/src/index.ts +15 -2
- package/src/mcpl/channel-registry.ts +170 -60
- package/src/mcpl/push-coalescer.ts +19 -0
- package/src/mcpl/toolsets-module.ts +7 -0
- package/src/notice-tags.ts +2 -0
- package/src/silent-heartbeat.ts +7 -4
- package/src/stored-injections.ts +7 -0
- package/src/tune-out/coordinator.ts +1229 -98
- package/src/tune-out/tools.ts +152 -11
- package/src/types/agent.ts +28 -0
- package/src/types/framework.ts +102 -0
- package/src/types/trace.ts +150 -0
package/dist/src/framework.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { type PresentationSnapshot } from "./tool-presentation.js";
|
|
2
2
|
import { JsStore } from '@animalabs/chronicle';
|
|
3
|
-
import type { Membrane, NormalizedRequest } from '@animalabs/membrane';
|
|
3
|
+
import type { Membrane, ContentBlock, NormalizedRequest } from '@animalabs/membrane';
|
|
4
4
|
import { type RetrySettings } from '@animalabs/membrane/retry';
|
|
5
5
|
import { ContextManager } from '@animalabs/context-manager';
|
|
6
|
-
import type { TokenBudget } from '@animalabs/context-manager';
|
|
6
|
+
import type { MessageMetadata, TokenBudget } from '@animalabs/context-manager';
|
|
7
7
|
import type { FrameworkConfig, ErrorPolicy, ErrorAction, TraceEventListener, InferenceLogQuery, InferenceLogQueryResult, InferenceLogEntryWithId, ProcessLogQuery, ProcessLogQueryResult, ProcessLogEntryWithId, ProcessEvent, ToolCall, ToolResult, AgentConfig, InferenceRequest, Module, ContextMaintenanceSnapshot, AgentRuntimeSettingsPatch, AgentRuntimeSettingsSnapshot, SameRoundThinkTextPolicy } from './types/index.js';
|
|
8
8
|
import { Agent, type RenderStats } from './agent.js';
|
|
9
9
|
import { type ToolClass, type ToolClassSource } from './mcpl/tool-classes.js';
|
|
10
10
|
import { ChannelRegistry } from './mcpl/channel-registry.js';
|
|
11
11
|
import { ConversationRouter } from './mcpl/conversation-router.js';
|
|
12
|
+
import type { ActivationRecord, AgentEndReason, AgentRecord, AgentSpec, EndOutcome, HeldMail, PolicyEpoch } from './dendrite/index.js';
|
|
12
13
|
/**
|
|
13
14
|
* The framework's own tools that belong to the host's built-in toolset
|
|
14
15
|
* ("settings", host-presentation.ts) rather than the tool list: the ones an
|
|
@@ -17,6 +18,7 @@ import { ConversationRouter } from './mcpl/conversation-router.js';
|
|
|
17
18
|
*/
|
|
18
19
|
export declare const BUILTIN_TOOLSET_TOOLS: ReadonlySet<string>;
|
|
19
20
|
import type { SessionUsageSnapshot } from './usage/types.js';
|
|
21
|
+
import type { ContextStrategy } from '@animalabs/context-manager';
|
|
20
22
|
import { type DiscordAwarenessView, type DiscordAwarenessCancelReceipt, type DiscordAwarenessMarks, type DiscordAwarenessRetractReceipt } from './recovery/discord-awareness-outbox.js';
|
|
21
23
|
import { type SurgeryMarkerReceipt, type SurgeryMarksPreview, type OperatorLogEntry, type OperatorLogInput, type OperatorRequester } from './operator-log.js';
|
|
22
24
|
/**
|
|
@@ -211,6 +213,85 @@ export declare class DefaultErrorPolicy implements ErrorPolicy {
|
|
|
211
213
|
constructor(settings?: RetrySettings);
|
|
212
214
|
onInferenceError(error: Error, _agentName: string, attempt: number): ErrorAction;
|
|
213
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* The admission record on a stored message: it was held from the residents
|
|
218
|
+
* by a policy epoch (`metadata.tuneOut = { epochId }`). ONE predicate for
|
|
219
|
+
* "held from the resident", read by the compiled-view filter and by the
|
|
220
|
+
* mid-turn injection alike (#232 H1), so the window and the wire agree.
|
|
221
|
+
*/
|
|
222
|
+
export declare const heldFromResidents: (metadata: Record<string, unknown> | undefined) => boolean;
|
|
223
|
+
/** Options for {@link AgentFramework.deriveAgent}. */
|
|
224
|
+
export interface DeriveAgentOptions {
|
|
225
|
+
/** The new agent's name. Single-use within this framework's lifetime. */
|
|
226
|
+
name: string;
|
|
227
|
+
/** The live agent whose context and configuration are inherited. */
|
|
228
|
+
from: string;
|
|
229
|
+
/** How context is inherited. Default `'shared'`. */
|
|
230
|
+
mode?: 'shared' | 'copy';
|
|
231
|
+
/** `'shared'` only. Default `'reuse'`. */
|
|
232
|
+
solve?: 'reuse' | 'fresh';
|
|
233
|
+
/**
|
|
234
|
+
* `'shared'` only. Also inherit the parent's refusal ledger (what it
|
|
235
|
+
* declined to compress). Default false; set for a fork that stands in
|
|
236
|
+
* for the parent's attention. Recorded as `inherit.refusals`.
|
|
237
|
+
*/
|
|
238
|
+
inheritRefusals?: boolean;
|
|
239
|
+
/**
|
|
240
|
+
* A fresh strategy instance for the child. Strategy instances hold state
|
|
241
|
+
* and are never shared; to reuse the parent's rendering it must be the
|
|
242
|
+
* same class with compatible configuration. Default: passthrough.
|
|
243
|
+
*/
|
|
244
|
+
strategy?: ContextStrategy;
|
|
245
|
+
/** Identity and settings overrides. Everything not named is the parent's. */
|
|
246
|
+
config?: Partial<Omit<AgentConfig, 'name' | 'strategy'>>;
|
|
247
|
+
/**
|
|
248
|
+
* The parent's tool round in flight, if any. While a tool call runs, the
|
|
249
|
+
* assistant turn that made it is not in the parent's store yet. By
|
|
250
|
+
* default the child's branch gets that turn verbatim (as its own, like
|
|
251
|
+
* the rest of the inheritance) followed by a tool-result message: results
|
|
252
|
+
* the parent has already received as they are; the call that derived the
|
|
253
|
+
* child with `madeBy.result`, or a note saying it did; and any other call
|
|
254
|
+
* still running with a note that its result was not available. So a fork
|
|
255
|
+
* sees the call that made it and never meets a dangling `tool_use`.
|
|
256
|
+
* `madeBy` defaults to the only open call when there is exactly one.
|
|
257
|
+
* `include: false` leaves the round out, and the child starts from the
|
|
258
|
+
* last stored message before it.
|
|
259
|
+
*/
|
|
260
|
+
pendingRound?: {
|
|
261
|
+
include?: boolean;
|
|
262
|
+
madeBy?: {
|
|
263
|
+
toolUseId: string;
|
|
264
|
+
result: string;
|
|
265
|
+
};
|
|
266
|
+
/** Results, from the child's side, for other calls still open, by tool-use id. */
|
|
267
|
+
results?: Record<string, string>;
|
|
268
|
+
};
|
|
269
|
+
/** Ordinary messages appended to the child before it runs. */
|
|
270
|
+
framing?: Array<{
|
|
271
|
+
participant: string;
|
|
272
|
+
content: ContentBlock[];
|
|
273
|
+
metadata?: MessageMetadata;
|
|
274
|
+
}>;
|
|
275
|
+
/** Who spawned it. Default: `from`. */
|
|
276
|
+
spawnedBy?: string;
|
|
277
|
+
/** Where its completion returns. */
|
|
278
|
+
resultTo?: import('./dendrite/index.js').ResultRoute;
|
|
279
|
+
/** What happens to it when its spawner ends. Default `'orphan'`. */
|
|
280
|
+
onParentEnd?: import('./dendrite/index.js').ParentEndPolicy;
|
|
281
|
+
deadlineMs?: number;
|
|
282
|
+
idleTimeoutMs?: number;
|
|
283
|
+
maxTurns?: number;
|
|
284
|
+
/** Preset label for discovery. Default `'task-fork'`. */
|
|
285
|
+
kind?: string;
|
|
286
|
+
metadata?: Record<string, unknown>;
|
|
287
|
+
}
|
|
288
|
+
/** Rejection delivered to the caller awaiting a bounded run that was ended from outside. */
|
|
289
|
+
export declare class AgentStoppedError extends Error {
|
|
290
|
+
readonly agentName: string;
|
|
291
|
+
readonly reason: AgentEndReason;
|
|
292
|
+
readonly by?: string | undefined;
|
|
293
|
+
constructor(agentName: string, reason: AgentEndReason, by?: string | undefined, detail?: string);
|
|
294
|
+
}
|
|
214
295
|
export interface ReinitAlertText {
|
|
215
296
|
opening: string;
|
|
216
297
|
message: string;
|
|
@@ -389,6 +470,13 @@ export declare class AgentFramework {
|
|
|
389
470
|
private quiesceReason?;
|
|
390
471
|
private quiescedAt?;
|
|
391
472
|
private traceListeners;
|
|
473
|
+
/** Traces emitted before start() — registry restore, interrupted work,
|
|
474
|
+
* resumed epochs — replayed to listeners that attach afterwards, since a
|
|
475
|
+
* host attaches its sinks after create() returns. Dropped at start().
|
|
476
|
+
* It keeps the first 1,000, the start of the stream, and counts the rest
|
|
477
|
+
* (earlyTracesDropped), which a replay ends by naming. */
|
|
478
|
+
private earlyTraces;
|
|
479
|
+
private earlyTracesDropped;
|
|
392
480
|
private syncIntervalMs;
|
|
393
481
|
private syncTimer;
|
|
394
482
|
private maintenanceIntervalMs;
|
|
@@ -442,8 +530,9 @@ export declare class AgentFramework {
|
|
|
442
530
|
private midTurnInputSignals;
|
|
443
531
|
/** Last outbound locus announced to each agent as a durable `[routing]`
|
|
444
532
|
* window message. Announce-on-change only: steady state emits nothing
|
|
445
|
-
* (KV-safe, no per-turn chatter).
|
|
446
|
-
*
|
|
533
|
+
* (KV-safe, no per-turn chatter). Kept in the store as well
|
|
534
|
+
* (rememberAnnouncedLocus), so a restart compares with what the agent was
|
|
535
|
+
* last told rather than with nothing. */
|
|
447
536
|
private lastAnnouncedLocus;
|
|
448
537
|
/** Every resident's held drafts: plain speech that was suppressed, bounced
|
|
449
538
|
* or left without a destination, never published except by their
|
|
@@ -527,6 +616,13 @@ export declare class AgentFramework {
|
|
|
527
616
|
private usedEphemeralAgentNames;
|
|
528
617
|
/** One-shot generation tickets minted by createEphemeralAgent. */
|
|
529
618
|
private ephemeralCandidates;
|
|
619
|
+
/**
|
|
620
|
+
* Derived agent → the agent whose tool presentation it shows. A derived
|
|
621
|
+
* agent that inherits its parent's tools must advertise the identical
|
|
622
|
+
* tool block (it is the front of the shared request prefix), including
|
|
623
|
+
* the parent's resident-edited visibility and descriptions.
|
|
624
|
+
*/
|
|
625
|
+
private toolSurfaceOwners;
|
|
530
626
|
/** Every agent createEphemeralAgent made, for as long as the object lives:
|
|
531
627
|
* its usage counts in the usage record's one shared ephemeral entry. Kept
|
|
532
628
|
* by the object, not the run's record (ephemeralRuns), which its cleanup
|
|
@@ -595,8 +691,25 @@ export declare class AgentFramework {
|
|
|
595
691
|
private subconsciousStrategy;
|
|
596
692
|
/** Its config (speak_in_channel gate, voice block provenance). */
|
|
597
693
|
private subconsciousConfig;
|
|
598
|
-
/** Tune-out coordinator (issue #77); non-null iff
|
|
694
|
+
/** Tune-out coordinator (issue #77); non-null iff a reader is configured + channels. */
|
|
599
695
|
private tuneOutCoordinator;
|
|
696
|
+
/** Residents are offered `tune_out` (a reader is configured, or `tuneOut.enabled`). */
|
|
697
|
+
private tuneOutOffered;
|
|
698
|
+
/**
|
|
699
|
+
* The reply anchor a coalesced delivery would set, parked until the
|
|
700
|
+
* acceptance is acknowledged to the server (handleCoalescedIncoming): an
|
|
701
|
+
* acceptance whose commit fails after its delivery moves no anchor, and the
|
|
702
|
+
* retry the receipt answers, which delivers nothing again, commits the one
|
|
703
|
+
* its first attempt parked. Keyed by server and event id; bounded.
|
|
704
|
+
*/
|
|
705
|
+
private parkedAnchors;
|
|
706
|
+
/** `tuneOut.announce`: the excepted channel hears the all-except scope open and close. */
|
|
707
|
+
private tuneOutAnnounce;
|
|
708
|
+
/** `speech.locus`: where prose goes when nothing names a destination (see FrameworkConfig). */
|
|
709
|
+
private speechLocus;
|
|
710
|
+
/** `subconscious.reader: 'forks'`: the reader is a succession of forks (Dendrite). */
|
|
711
|
+
private readerForks;
|
|
712
|
+
private readerForkCounter;
|
|
600
713
|
/** Agents an abandon could not cancel (token held, no stream) — surfaced
|
|
601
714
|
* in HostModeStatus until the next quiesce/resume. */
|
|
602
715
|
private lastUnabandonable;
|
|
@@ -614,6 +727,24 @@ export declare class AgentFramework {
|
|
|
614
727
|
/** True once the cap has been met in the current run, so its line is
|
|
615
728
|
* logged once a run, whatever began the run. */
|
|
616
729
|
private deferredWritesCapLogged;
|
|
730
|
+
/** The agent registry and its ended log, as recovery files beside the store
|
|
731
|
+
* (nissa's #546 finding 3): Chronicle state follows the store's branch, and
|
|
732
|
+
* an undo or an operator's surgery must not erase a result held for
|
|
733
|
+
* delivery or the record of work that ran. The file wins where it exists;
|
|
734
|
+
* the branch-local state is read only for stores that predate it. */
|
|
735
|
+
private agentRegistryPath;
|
|
736
|
+
private agentRegistryEndedPath;
|
|
737
|
+
/** The ended log as the recovery file keeps it: the newest records, bounded. */
|
|
738
|
+
private endedRecovery;
|
|
739
|
+
/** The branch-local ended log by name (its newest entry for each), and how far it is indexed (findEndedAgentRecord). */
|
|
740
|
+
private readonly endedLogIndex;
|
|
741
|
+
/** The ended log's entries by the namespace their context holds (the latest for each). */
|
|
742
|
+
private readonly endedLogNamespaceIndex;
|
|
743
|
+
/** Namespaces this process opened for an ephemeral agent's context, by owner: candidates not yet registered included. */
|
|
744
|
+
private readonly namespaceOwners;
|
|
745
|
+
private endedLogIndexed;
|
|
746
|
+
/** The last indexed entry's mark, so a log that changed under the index is seen. */
|
|
747
|
+
private endedLogTail;
|
|
617
748
|
/** Branch-independent recovery files (see FrameworkConfig.hostModePath /
|
|
618
749
|
* deferredWritesPath). Undefined → branch-local slot fallback. */
|
|
619
750
|
private hostModePath;
|
|
@@ -743,12 +874,27 @@ export declare class AgentFramework {
|
|
|
743
874
|
private coalescingSnapshotDirty;
|
|
744
875
|
private coalescingRecentReceipts;
|
|
745
876
|
/**
|
|
746
|
-
*
|
|
747
|
-
*
|
|
748
|
-
*
|
|
749
|
-
*
|
|
750
|
-
*
|
|
751
|
-
*/
|
|
877
|
+
* Dendrite agent registry — every agent this framework runs, with its
|
|
878
|
+
* roles, lifetime and relationships. `agents` stays the map of live Agent
|
|
879
|
+
* OBJECTS (the generation identity streams are checked against); the
|
|
880
|
+
* registry is what says what each of them is for. Selection sites read
|
|
881
|
+
* roles from here instead of excluding kinds by hand.
|
|
882
|
+
*/
|
|
883
|
+
private readonly registry;
|
|
884
|
+
/** Tell the first adoption candidate when task work is orphaned (config.dendrite.announceOrphans). */
|
|
885
|
+
private announceOrphans;
|
|
886
|
+
/**
|
|
887
|
+
* After this many derivations of one kind from one agent, that agent hears
|
|
888
|
+
* a count line every so many instead of a line per fork
|
|
889
|
+
* (config.dendrite.collapseDerivationNoticesAfter; 0 = never collapse).
|
|
890
|
+
*/
|
|
891
|
+
private collapseDerivationNoticesAfter;
|
|
892
|
+
/** The host's say over each derivation, ephemeral spawn and resume (config.dendrite.beforeDerive). */
|
|
893
|
+
private beforeDerive?;
|
|
894
|
+
/** What a source is told of a derivation (config.dendrite.derivationNotice); absent, the default line. */
|
|
895
|
+
private derivationNoticeHook?;
|
|
896
|
+
/** Per source agent, per kind: how many derivations, since when, and at which count the last note went. */
|
|
897
|
+
private derivationTallies;
|
|
752
898
|
private readonly sharedSlotAgents;
|
|
753
899
|
/** The batched-wake lines already written (placeWakeLines), so every agent a
|
|
754
900
|
* wake was for, and every later start of it, writes each at most once. */
|
|
@@ -757,6 +903,7 @@ export declare class AgentFramework {
|
|
|
757
903
|
* in the round counted by their share of the bound: such a round is
|
|
758
904
|
* stored by its share whether or not it fits (buildStoredToolResultContent). */
|
|
759
905
|
private readonly toolRoundsByShare;
|
|
906
|
+
/** Group commit: one fsync per event-loop turn, shared by every waiter. */
|
|
760
907
|
/** The windows of forks and runs deregistered while the host was quiesced,
|
|
761
908
|
* by agent name (releaseWindowNowOrAfterResume); resume() releases them
|
|
762
909
|
* (runReleasesAfterResume), or stop() passes on what they left, unread or
|
|
@@ -765,6 +912,7 @@ export declare class AgentFramework {
|
|
|
765
912
|
private readonly releasesAfterResume;
|
|
766
913
|
private readonly managerReleases;
|
|
767
914
|
private readonly releasedByCleanup;
|
|
915
|
+
private readonly resumesPending;
|
|
768
916
|
private readonly openManagers;
|
|
769
917
|
private readonly openManagerRefs;
|
|
770
918
|
private readonly storeSees;
|
|
@@ -778,19 +926,13 @@ export declare class AgentFramework {
|
|
|
778
926
|
private conversationRouter;
|
|
779
927
|
/** Agent configs by name — fork agents are built from the template's config. */
|
|
780
928
|
private agentConfigs;
|
|
781
|
-
/**
|
|
782
|
-
* Fork agent → its home channel. Permanent (unlike router bindings, which
|
|
783
|
-
* expire): publish/injection scoping must survive unbinding so the closure
|
|
784
|
-
* turn still lands in the right channel.
|
|
785
|
-
*/
|
|
786
|
-
private conversationAgentHomes;
|
|
787
929
|
/** Forks being spawned, by channel id, each until its spawn settles (see
|
|
788
930
|
* routeConversation). The promise never rejects. */
|
|
789
931
|
private readonly conversationSpawns;
|
|
790
932
|
/** Last idle-TTL sweep timestamp. */
|
|
791
933
|
private lastConversationSweep;
|
|
792
934
|
/** Forks whose TTL closure turn has been queued — disposed (removed from
|
|
793
|
-
* agents/agentConfigs
|
|
935
|
+
* agents/agentConfigs and ended in the registry) when their stream ends. */
|
|
794
936
|
private closingConversationAgents;
|
|
795
937
|
private codeExecution;
|
|
796
938
|
private scriptToolWaiters;
|
|
@@ -1155,7 +1297,10 @@ export declare class AgentFramework {
|
|
|
1155
1297
|
*/
|
|
1156
1298
|
private heartbeatWakeBefore;
|
|
1157
1299
|
/** The agents the heartbeat wakes: the residents, not conversation forks,
|
|
1158
|
-
* ephemeral runs or the subconscious, which keep windows of their own.
|
|
1300
|
+
* ephemeral runs or the subconscious, which keep windows of their own.
|
|
1301
|
+
* Read from the registry by role, as an untargeted push's recipients are
|
|
1302
|
+
* (the heartbeat's wakes were heartbeat-mcpl's pushes): the agents whose
|
|
1303
|
+
* spec takes untargeted inbound, in registration order. */
|
|
1159
1304
|
private heartbeatTargets;
|
|
1160
1305
|
/**
|
|
1161
1306
|
* The event a heartbeat wake is to the gate: a push from the server id
|
|
@@ -1405,7 +1550,9 @@ export declare class AgentFramework {
|
|
|
1405
1550
|
/**
|
|
1406
1551
|
* Add a trace event listener for observability.
|
|
1407
1552
|
*/
|
|
1408
|
-
onTrace(listener: TraceEventListener
|
|
1553
|
+
onTrace(listener: TraceEventListener, options?: {
|
|
1554
|
+
replay?: boolean;
|
|
1555
|
+
}): () => void;
|
|
1409
1556
|
/**
|
|
1410
1557
|
* Public accessor for the MCPL channel registry.
|
|
1411
1558
|
* Null when no MCPL servers are configured.
|
|
@@ -2248,11 +2395,334 @@ export declare class AgentFramework {
|
|
|
2248
2395
|
* ContextManager, before the store. Until then the ContextManager stays
|
|
2249
2396
|
* open.
|
|
2250
2397
|
*/
|
|
2251
|
-
createEphemeralAgent(config: AgentConfig
|
|
2398
|
+
createEphemeralAgent(config: AgentConfig,
|
|
2399
|
+
/**
|
|
2400
|
+
* How the registry should describe this agent. Omitted: an independent
|
|
2401
|
+
* fresh worker with no spawner and no result route, which is what every
|
|
2402
|
+
* caller of this method got before the registry existed. Supplying a
|
|
2403
|
+
* spec (see the presets in `dendrite/`) declares who spawned it, where
|
|
2404
|
+
* its result goes and what it inherited, so lifecycle rules — orphan
|
|
2405
|
+
* notice, reparenting, held results — apply to it.
|
|
2406
|
+
*/
|
|
2407
|
+
spec?: Omit<AgentSpec, 'name'>): Promise<{
|
|
2252
2408
|
agent: Agent;
|
|
2253
2409
|
contextManager: ContextManager;
|
|
2254
2410
|
cleanup: () => void;
|
|
2255
2411
|
}>;
|
|
2412
|
+
/**
|
|
2413
|
+
* Derive a new agent from a live one: the parent's context at a
|
|
2414
|
+
* checkpoint, a private continuation, and — unless overridden — the
|
|
2415
|
+
* parent's whole configuration (model, thinking, cache TTL, provider
|
|
2416
|
+
* params, prompt, tools). The parent keeps running.
|
|
2417
|
+
*
|
|
2418
|
+
* The returned agent is a bounded job, driven with
|
|
2419
|
+
* `runEphemeralToCompletion` exactly like one from `createEphemeralAgent`.
|
|
2420
|
+
*
|
|
2421
|
+
* **Inheritance.** `mode: 'shared'` (the default) gives the child the
|
|
2422
|
+
* parent's messages and fold state through shared storage: nothing is
|
|
2423
|
+
* copied, the child folds with the parent's memory tree, and neither can
|
|
2424
|
+
* alter what the other reads. It needs branch-bound store handles and is
|
|
2425
|
+
* refused, not silently downgraded, where they are missing. `mode: 'copy'`
|
|
2426
|
+
* is the historical mechanism — the parent's compiled context re-added as
|
|
2427
|
+
* the child's own messages — and works everywhere.
|
|
2428
|
+
*
|
|
2429
|
+
* **Rendering.** With `solve: 'reuse'` (the default) and nothing
|
|
2430
|
+
* overridden, the child's first request is the parent's request plus the
|
|
2431
|
+
* child's framing: the same system prompt and tool block, the parent's
|
|
2432
|
+
* turns presented as the child's own, and a cache marker on the end of
|
|
2433
|
+
* the parent's request so the prefix it wrote is read back. `solve:
|
|
2434
|
+
* 'fresh'` deliberately re-solves, e.g. at another budget; so does any
|
|
2435
|
+
* override that changes what is rendered. Those are operating choices —
|
|
2436
|
+
* the presentation changes and the provider cache misses.
|
|
2437
|
+
*
|
|
2438
|
+
* **Framing** is ordinary messages appended to the child before it runs:
|
|
2439
|
+
* the task, and whatever tells it which stream it is. The parent's turn
|
|
2440
|
+
* in flight is not in its store yet (see `getPendingAssistantRound`), so
|
|
2441
|
+
* a fork made from inside a tool call starts from the message before the
|
|
2442
|
+
* turn that made it.
|
|
2443
|
+
*
|
|
2444
|
+
* Context isolation is not process or filesystem isolation: parent and
|
|
2445
|
+
* child share tools, any shell and the workspace.
|
|
2446
|
+
*/
|
|
2447
|
+
deriveAgent(options: DeriveAgentOptions): Promise<{
|
|
2448
|
+
agent: Agent;
|
|
2449
|
+
contextManager: ContextManager;
|
|
2450
|
+
cleanup: () => void;
|
|
2451
|
+
}>;
|
|
2452
|
+
private discardEphemeralCandidate;
|
|
2453
|
+
/**
|
|
2454
|
+
* The default wording for the call that derived a child: who it is, what
|
|
2455
|
+
* kind, and how long — the fields the consent event names, so the fork
|
|
2456
|
+
* never has to infer its own lifetime from context (Linn, 10-09).
|
|
2457
|
+
*/
|
|
2458
|
+
private derivedNote;
|
|
2459
|
+
/**
|
|
2460
|
+
* The parent's in-flight tool round, reproduced on the child's branch so
|
|
2461
|
+
* the child sees the call that made it (see `DeriveAgentOptions.pendingRound`).
|
|
2462
|
+
*/
|
|
2463
|
+
private framePendingRound;
|
|
2464
|
+
/**
|
|
2465
|
+
* The assistant turn an agent has produced but not yet stored: its tool
|
|
2466
|
+
* calls and any text before them, held until every tool result is in so
|
|
2467
|
+
* the pair lands adjacently. A host deriving an agent from inside one of
|
|
2468
|
+
* those tool calls can reproduce the turn in the child's framing.
|
|
2469
|
+
*/
|
|
2470
|
+
getPendingAssistantRound(agentName: string): ContentBlock[] | undefined;
|
|
2471
|
+
/**
|
|
2472
|
+
* Bring an ended bounded job back as a new incarnation of the same
|
|
2473
|
+
* identity, on the context it left: an isolated agent's own namespace, or
|
|
2474
|
+
* a derived agent's own branch. Nothing is re-derived and nothing is
|
|
2475
|
+
* re-seeded — the agent continues from its last stored message, which is
|
|
2476
|
+
* the end of its last complete round (a round whose tool results never
|
|
2477
|
+
* all arrived was never stored).
|
|
2478
|
+
*
|
|
2479
|
+
* Use it for a job that was stopped, failed, or was interrupted by a
|
|
2480
|
+
* restart. Configuration is not persisted with an agent, so the caller
|
|
2481
|
+
* supplies it again; the role mapping a derived agent used is restored
|
|
2482
|
+
* from its record unless the config sets one. Relationships are kept
|
|
2483
|
+
* where the other agent still exists; a job whose spawner or result
|
|
2484
|
+
* recipient is gone resumes without that edge and can be reparented.
|
|
2485
|
+
*
|
|
2486
|
+
* External effects are not replayed and not undone: a tool the previous
|
|
2487
|
+
* incarnation ran before it ended has had its effect, and a call it never
|
|
2488
|
+
* received a result for may be made again by the model. Drive the result
|
|
2489
|
+
* with `runEphemeralToCompletion`.
|
|
2490
|
+
*/
|
|
2491
|
+
resumeAgent(name: string, config: Omit<AgentConfig, 'name'>): Promise<{
|
|
2492
|
+
agent: Agent;
|
|
2493
|
+
contextManager: ContextManager;
|
|
2494
|
+
cleanup: () => void;
|
|
2495
|
+
}>;
|
|
2496
|
+
/**
|
|
2497
|
+
* A context to read an agent's history from, without changing the live
|
|
2498
|
+
* system.
|
|
2499
|
+
*
|
|
2500
|
+
* - A live agent: a snapshot derived from its context — at the head, or
|
|
2501
|
+
* at `atSequence` for an earlier state. The snapshot is its own branch;
|
|
2502
|
+
* the agent keeps running and is not affected by anything done to it.
|
|
2503
|
+
* - An ended agent: the context it left, reopened where it lives.
|
|
2504
|
+
*
|
|
2505
|
+
* The returned manager uses a passthrough strategy: it shows what is
|
|
2506
|
+
* stored, raw. An ended agent's context is the real one — treat it as
|
|
2507
|
+
* read-only unless you mean to change what a later resume starts from.
|
|
2508
|
+
*/
|
|
2509
|
+
inspectAgentContext(name: string, options?: {
|
|
2510
|
+
atSequence?: number;
|
|
2511
|
+
}): Promise<ContextManager>;
|
|
2512
|
+
/** Open the context an ended agent left, wherever it lives. */
|
|
2513
|
+
private reopenAgentContext;
|
|
2514
|
+
/** Open a derived agent's context on a branch of its own (see deriveAgent). */
|
|
2515
|
+
private deriveSharedContext;
|
|
2516
|
+
/** Flat list of registered agents with their roles, lifetime and relationships. */
|
|
2517
|
+
listAgents(options?: {
|
|
2518
|
+
includeEnded?: boolean;
|
|
2519
|
+
}): AgentRecord[];
|
|
2520
|
+
/** One agent's record: the live one, else its most recent ended one. */
|
|
2521
|
+
getAgentRecord(name: string): AgentRecord | null;
|
|
2522
|
+
/** The agent that owns default delivery, or null before any is declared. */
|
|
2523
|
+
getPrimaryAgentName(): string | null;
|
|
2524
|
+
/**
|
|
2525
|
+
* Activations in flight, each with the agent that owns the work. Derived
|
|
2526
|
+
* from the live turn state, so it cannot disagree with what is running.
|
|
2527
|
+
*/
|
|
2528
|
+
listActivations(): ActivationRecord[];
|
|
2529
|
+
/**
|
|
2530
|
+
* Policy epochs currently in force (tune-out holds), read from the
|
|
2531
|
+
* coordinator's own durable state — not mirrored. An epoch is neither an
|
|
2532
|
+
* agent nor a task: ending one leaves both running.
|
|
2533
|
+
*/
|
|
2534
|
+
listPolicyEpochs(): PolicyEpoch[];
|
|
2535
|
+
/**
|
|
2536
|
+
* Cancel an agent's activation in flight, leaving the agent registered.
|
|
2537
|
+
* For a bounded job, whose lifetime is that one run, this ends the job.
|
|
2538
|
+
* Returns false when nothing was running.
|
|
2539
|
+
*/
|
|
2540
|
+
cancelActivation(name: string, options?: {
|
|
2541
|
+
by?: string;
|
|
2542
|
+
reason?: string;
|
|
2543
|
+
}): boolean;
|
|
2544
|
+
/**
|
|
2545
|
+
* End an agent: cancel its run, remove it from the framework, and settle
|
|
2546
|
+
* what it spawned — attention tenants end with it; task work is orphaned,
|
|
2547
|
+
* notified and offered for reparenting, and keeps running.
|
|
2548
|
+
*
|
|
2549
|
+
* The default-delivery owner cannot be stopped (the framework needs
|
|
2550
|
+
* exactly one); cancel its activation instead. A persistent agent stopped
|
|
2551
|
+
* here is declared by configuration and returns at the next boot.
|
|
2552
|
+
*/
|
|
2553
|
+
stopAgent(name: string, options?: {
|
|
2554
|
+
by?: string;
|
|
2555
|
+
reason?: string;
|
|
2556
|
+
}): EndOutcome;
|
|
2557
|
+
/**
|
|
2558
|
+
* Give an agent a new parent. Clears its orphan state; a result route
|
|
2559
|
+
* whose recipient is gone follows the new parent, and the mail it already
|
|
2560
|
+
* produced for the lost recipient, results and messages, is delivered to
|
|
2561
|
+
* the new one.
|
|
2562
|
+
*/
|
|
2563
|
+
reparentAgent(name: string, newParent: string, options?: {
|
|
2564
|
+
by?: string;
|
|
2565
|
+
}): AgentRecord;
|
|
2566
|
+
/**
|
|
2567
|
+
* An explicit message from one agent to another: the sender's verbatim
|
|
2568
|
+
* content, in the recipient's context under the SENDER's name, with the
|
|
2569
|
+
* sender's identity and incarnation and the causal chain in metadata.
|
|
2570
|
+
* Never an unmarked insertion into the recipient's own voice.
|
|
2571
|
+
*/
|
|
2572
|
+
sendAgentMessage(from: string, to: string, content: ContentBlock[], options?: {
|
|
2573
|
+
causedBy?: string[];
|
|
2574
|
+
wake?: boolean;
|
|
2575
|
+
}): {
|
|
2576
|
+
mailId: string;
|
|
2577
|
+
delivered: boolean;
|
|
2578
|
+
};
|
|
2579
|
+
/**
|
|
2580
|
+
* Return a bounded job's result along the agent's declared result route.
|
|
2581
|
+
* The result is recorded durably before delivery is attempted, so it is
|
|
2582
|
+
* neither lost nor delivered twice across a restart; if the recipient is
|
|
2583
|
+
* gone it is held as attributed mail until the agent is reparented.
|
|
2584
|
+
*
|
|
2585
|
+
* May be called after the agent's run has ended — its record stays
|
|
2586
|
+
* inspectable. Refused for a `tool-result` route: there the awaiting
|
|
2587
|
+
* caller already holds the result and delivers it itself.
|
|
2588
|
+
*/
|
|
2589
|
+
deliverAgentResult(from: string, content: ContentBlock[], options?: {
|
|
2590
|
+
causedBy?: string[];
|
|
2591
|
+
}): {
|
|
2592
|
+
mailId: string;
|
|
2593
|
+
delivered: boolean;
|
|
2594
|
+
to: string;
|
|
2595
|
+
};
|
|
2596
|
+
/** Communications not yet handed to their recipient, and why. */
|
|
2597
|
+
listHeldMail(filter?: {
|
|
2598
|
+
to?: string;
|
|
2599
|
+
from?: string;
|
|
2600
|
+
}): HeldMail[];
|
|
2601
|
+
/**
|
|
2602
|
+
* Try to hand one held item to its recipient. True when the message is in
|
|
2603
|
+
* (or queued for) the recipient's context; false when it stays held
|
|
2604
|
+
* because nobody can receive it. The held copy is released by
|
|
2605
|
+
* `addMessage` at the moment the message enters the store.
|
|
2606
|
+
*/
|
|
2607
|
+
private attemptMailDelivery;
|
|
2608
|
+
/**
|
|
2609
|
+
* An ended orphan's result held for a recipient that is gone: its first
|
|
2610
|
+
* adoption candidate is told it exists and how it arrives, since nothing
|
|
2611
|
+
* else would surface it (reparentAgent delivers it).
|
|
2612
|
+
*/
|
|
2613
|
+
private tellResultHeld;
|
|
2614
|
+
/** A host-framed lifecycle fact in an agent's context. Never voiced as anyone. */
|
|
2615
|
+
private lifecycleNotice;
|
|
2616
|
+
/**
|
|
2617
|
+
* The creation ("consent") event: names what kind of agent this is, what
|
|
2618
|
+
* ends it and what happens to it when its spawner ends. A derived agent's
|
|
2619
|
+
* creation is also told to the agent it was derived from (#270, Linn:
|
|
2620
|
+
* "told when the body changes" as a property, not a courtesy): one
|
|
2621
|
+
* host-framed line in the source's context, built from the same facts as
|
|
2622
|
+
* the trace, with no wake; a host's derivationNotice can replace the line
|
|
2623
|
+
* or send none. Both derivation paths announce after the
|
|
2624
|
+
* fork's branch or copy exists, so a fork never inherits the notice about
|
|
2625
|
+
* itself; a source that has ended is told nothing (lifecycleNotice).
|
|
2626
|
+
*/
|
|
2627
|
+
private announceAgentCreated;
|
|
2628
|
+
/** The derivation notice's text, addressed to the agent `from` the record was derived. */
|
|
2629
|
+
private derivationNotice;
|
|
2630
|
+
/** What a derived agent is, to the agent it was derived from: "a task-fork on your weights, …; …; …". */
|
|
2631
|
+
private derivationDescription;
|
|
2632
|
+
/**
|
|
2633
|
+
* Remove an ended agent's live object from the framework. A bounded run
|
|
2634
|
+
* is ended through its awaiting caller (whose teardown owns the
|
|
2635
|
+
* name-keyed state); any other agent is torn down here.
|
|
2636
|
+
*/
|
|
2637
|
+
private teardownEndedAgent;
|
|
2638
|
+
/**
|
|
2639
|
+
* Everything the process holds for a live, non-ephemeral agent that has
|
|
2640
|
+
* ended, released once, on every path an agent ends by — stopAgent, the
|
|
2641
|
+
* idle reap of a conversation fork, an end that cascades from a parent's
|
|
2642
|
+
* (nissa's #546 finding 5: a stop that skipped the window release dropped a
|
|
2643
|
+
* write queued for the agent at the next flush, and a failure notice it
|
|
2644
|
+
* never read reached no one). The window release delivers what the agent
|
|
2645
|
+
* never read to the primary, now or after a resume, as the idle reap did.
|
|
2646
|
+
*/
|
|
2647
|
+
private releaseAgentRuntime;
|
|
2648
|
+
/**
|
|
2649
|
+
* Carry out what the registry decided when an agent ended: tear down the
|
|
2650
|
+
* attention tenants that end with it, and tell each orphan — and the
|
|
2651
|
+
* first agent that could adopt it — what happened.
|
|
2652
|
+
*/
|
|
2653
|
+
private settleEndedAgent;
|
|
2654
|
+
/** An agent whose spawner has ended, and its first adoption candidate, are told; the trace says so. */
|
|
2655
|
+
private announceOrphaned;
|
|
2656
|
+
/** The registry's snapshot: the recovery file first (atomic, fsynced; it
|
|
2657
|
+
* wins at the next boot), then the branch-local state, kept for inspection
|
|
2658
|
+
* and for stores read by older code. Either write failing fails the call
|
|
2659
|
+
* that changed the registry (nissa's #546 finding 2): a change that isn't
|
|
2660
|
+
* durable isn't a success. */
|
|
2661
|
+
private persistAgentRegistry;
|
|
2662
|
+
/** An ended record: appended to the branch-local log, and the recovery
|
|
2663
|
+
* file rewritten with the newest records (as many as a restart reads). */
|
|
2664
|
+
private appendEndedAgentRecord;
|
|
2665
|
+
/**
|
|
2666
|
+
* A requested change was put back in the registry's memory: the recovery
|
|
2667
|
+
* files, each written before the branch-local store, are rewritten from it
|
|
2668
|
+
* (the snapshot's and the ended log's), so neither keeps the change the
|
|
2669
|
+
* caller was told failed. The branch-local snapshot needs no rewrite: it is
|
|
2670
|
+
* the last write a change makes, so a change that failed never reached it.
|
|
2671
|
+
* The branch-local ended log is append-only, so an end appended before the
|
|
2672
|
+
* failure stays there. It is read at boot only where no ended recovery
|
|
2673
|
+
* file exists (or the rewrite of that file failed too); the restore then
|
|
2674
|
+
* drops a bounded agent it lists as ended for the reason recorded, with no
|
|
2675
|
+
* restart notice to its recipient, while a persistent agent waits to be
|
|
2676
|
+
* re-declared as it would anyway. A rewrite that fails is reported, the
|
|
2677
|
+
* next is still made, and the caller's own error goes on.
|
|
2678
|
+
*/
|
|
2679
|
+
private rewriteAgentRegistryAfterRollback;
|
|
2680
|
+
/**
|
|
2681
|
+
* An ended record past the registry's memory, from the branch-local ended
|
|
2682
|
+
* log. A scan of the whole log takes tens of milliseconds at a few thousand
|
|
2683
|
+
* ends, and a name nobody used (a tool call's typo) is a miss, so the log is
|
|
2684
|
+
* indexed by name once, at the first lookup, and each later lookup indexes
|
|
2685
|
+
* only what was appended since. A log that changed under the index (a
|
|
2686
|
+
* branch switch) is indexed again: one that shrank, one whose last indexed
|
|
2687
|
+
* entry is no longer the one indexed, or one whose entry no longer carries
|
|
2688
|
+
* the name indexed for it.
|
|
2689
|
+
*/
|
|
2690
|
+
private findEndedAgentRecord;
|
|
2691
|
+
/**
|
|
2692
|
+
* The ended log's latest record whose own context a namespace holds. A
|
|
2693
|
+
* shared fork's record names its parent's namespace, where it owns only a
|
|
2694
|
+
* branch, so it is indexed by name alone.
|
|
2695
|
+
*/
|
|
2696
|
+
private findInEndedLog;
|
|
2697
|
+
/** Another agent whose context a namespace holds: opened in this process, in the registry, or in the ended log. */
|
|
2698
|
+
private namespaceHolder;
|
|
2699
|
+
/** The ended log's recovery file, rewritten as the newest records (as many as a restart reads). */
|
|
2700
|
+
private rewriteEndedRecovery;
|
|
2701
|
+
/**
|
|
2702
|
+
* Load the previous process's registry. Returns the bounded work it
|
|
2703
|
+
* interrupted. A registry that can't be read, or that reads as anything
|
|
2704
|
+
* but a version-1 registry, refuses the start and names the state (nissa's
|
|
2705
|
+
* #546 finding 1, main's rule for the framework's own state): taken as
|
|
2706
|
+
* empty, the results it holds for delivery and the records of the work it
|
|
2707
|
+
* ran would be overwritten by this boot's first registration.
|
|
2708
|
+
*/
|
|
2709
|
+
private restoreAgentRegistry;
|
|
2710
|
+
/**
|
|
2711
|
+
* Boot reconciliation, once configuration has declared its agents.
|
|
2712
|
+
* Restart behaviour follows from lifetime: persistent agents were just
|
|
2713
|
+
* re-created; everything else that was live was interrupted, and the
|
|
2714
|
+
* recipient of an interrupted job's result is told so. Results held from
|
|
2715
|
+
* before the restart are delivered now, exactly once.
|
|
2716
|
+
*/
|
|
2717
|
+
private reconcileAgentRegistry;
|
|
2718
|
+
/**
|
|
2719
|
+
* Deliver held mail that hasn't landed. Its copy may have reached the
|
|
2720
|
+
* recipient's store in the same sync that the release missed, and then it
|
|
2721
|
+
* is released instead; and a write the deferred queue still holds for it
|
|
2722
|
+
* lands at the next flush and releases it then (releaseLandedMail). Either
|
|
2723
|
+
* way a second delivery would put it in the window twice under one mail id.
|
|
2724
|
+
*/
|
|
2725
|
+
private deliverHeldMail;
|
|
2256
2726
|
private createDeferred;
|
|
2257
2727
|
/** Liveness ping for an active ephemeral run (no-op otherwise). */
|
|
2258
2728
|
private touchEphemeralRun;
|
|
@@ -2310,6 +2780,8 @@ export declare class AgentFramework {
|
|
|
2310
2780
|
/** Tune-out (issue #77): divert a channel to your subconscious. Present
|
|
2311
2781
|
* only when the subconscious resident is configured. */
|
|
2312
2782
|
private static readonly TUNE_OUT_TOOL;
|
|
2783
|
+
/** `focus`: the resident-facing alias for `tune_out` with scope "all-except" (#232 decision 2). */
|
|
2784
|
+
private static readonly FOCUS_TOOL;
|
|
2313
2785
|
/** Synthesized sleep/wake tool definitions (present when a gate is wired). */
|
|
2314
2786
|
private static readonly SLEEP_TOOLS;
|
|
2315
2787
|
/** Synthesized wake-rule tools: add/remove a gate.json policy at runtime.
|
|
@@ -2870,6 +3342,28 @@ export declare class AgentFramework {
|
|
|
2870
3342
|
* into the resident's window, which accumulates there.
|
|
2871
3343
|
*/
|
|
2872
3344
|
private createSubconsciousAgent;
|
|
3345
|
+
/**
|
|
3346
|
+
* `subconscious.reader: 'forks'`: no persistent agent. The coordinator
|
|
3347
|
+
* asks for a fork per invocation (see invokeReaderFork); the config is
|
|
3348
|
+
* kept for the voice block, the speech switch and the strategy factory.
|
|
3349
|
+
*/
|
|
3350
|
+
private configureReaderForks;
|
|
3351
|
+
/**
|
|
3352
|
+
* One reader invocation: derive a fork of the resident at its head with
|
|
3353
|
+
* the resident's refusals, hand it the held traffic since the last look
|
|
3354
|
+
* as ordinary framing, and run it. It reports through `deliver_summary`
|
|
3355
|
+
* (attributed mail), may cancel the hold, and ends when its turn ends.
|
|
3356
|
+
*/
|
|
3357
|
+
private invokeReaderFork;
|
|
3358
|
+
/**
|
|
3359
|
+
* Held messages still queued behind the resident's turn, as rows of a
|
|
3360
|
+
* reader fork's backlog: each named by its held handle, as module rows name
|
|
3361
|
+
* it until it lands (heldRows), at a provisional sequence past the
|
|
3362
|
+
* resident's last stored message, and timed when it was first held.
|
|
3363
|
+
*/
|
|
3364
|
+
private queuedReaderRows;
|
|
3365
|
+
/** A reader fork's own words to the resident: attributed mail when it has a route, else under its name. */
|
|
3366
|
+
private deliverFromReader;
|
|
2873
3367
|
private runLoop;
|
|
2874
3368
|
private processNextEvent;
|
|
2875
3369
|
private handleProcessEvent;
|
|
@@ -2895,6 +3389,14 @@ export declare class AgentFramework {
|
|
|
2895
3389
|
* Convert an incoming MCPL channel message to a context message.
|
|
2896
3390
|
* This replaces the old MCPLModule.onProcess() message conversion.
|
|
2897
3391
|
*/
|
|
3392
|
+
/**
|
|
3393
|
+
* A delivered inbound message becomes the latest delivered inbound (the
|
|
3394
|
+
* channel context's reply anchor; the legacy speech fallback) through the
|
|
3395
|
+
* registry's noteDelivered — at once for a plain channels/incoming, whose
|
|
3396
|
+
* acceptance the registry answers synchronously; parked for a coalesced one
|
|
3397
|
+
* until its acceptance is acknowledged (see parkedAnchors).
|
|
3398
|
+
*/
|
|
3399
|
+
private noteDeliveredOrPark;
|
|
2898
3400
|
private handleMcplChannelIncoming;
|
|
2899
3401
|
/**
|
|
2900
3402
|
* Route an incoming channel message through the ConversationRouter:
|
|
@@ -3185,6 +3687,27 @@ export declare class AgentFramework {
|
|
|
3185
3687
|
* channels answer to is never resolved to either.
|
|
3186
3688
|
*/
|
|
3187
3689
|
private channelNamed;
|
|
3690
|
+
/**
|
|
3691
|
+
* A live agent's home channel, from its registry record (channelOfHome):
|
|
3692
|
+
* defined for a conversation fork, and only for one. Undefined for an agent
|
|
3693
|
+
* with none, and for one that has ended.
|
|
3694
|
+
*/
|
|
3695
|
+
private homeOf;
|
|
3696
|
+
/**
|
|
3697
|
+
* The channel a registry record's `homeChannel` names: the channel on its
|
|
3698
|
+
* server. A bare channel id, as a record written before homes carried
|
|
3699
|
+
* their server keeps, is read as a wake that names its channel without its
|
|
3700
|
+
* server is (channelNamed): the one registered channel it names, read when
|
|
3701
|
+
* it's used, since the servers registered at that moment are what it can
|
|
3702
|
+
* mean. An id that names no one registered channel, as one no server
|
|
3703
|
+
* registers now or two servers do, is the home on no server (an empty
|
|
3704
|
+
* serverId, which channelNamed reads as none given), so the agent keeps a
|
|
3705
|
+
* home. A path that reads the pair finds no server registering it, and
|
|
3706
|
+
* refuses it; one that reads the name reads what the name means then: none
|
|
3707
|
+
* or two channels, which it refuses, or, once one server alone registers
|
|
3708
|
+
* the id, that server's channel.
|
|
3709
|
+
*/
|
|
3710
|
+
private channelOfHome;
|
|
3188
3711
|
/**
|
|
3189
3712
|
* Explicit mode's typing channel for one start of a turn, which has no
|
|
3190
3713
|
* locus, read once as the start opens (driveStream then shows what the
|
|
@@ -3225,6 +3748,23 @@ export declare class AgentFramework {
|
|
|
3225
3748
|
* it takes their agent up (passRequests). */
|
|
3226
3749
|
private processInferenceRequests;
|
|
3227
3750
|
private runInferencePass;
|
|
3751
|
+
/**
|
|
3752
|
+
* `channel_publish` with no channel goes where the turn's plain speech
|
|
3753
|
+
* would: the frozen turn locus (the waking delivery's channel, or one
|
|
3754
|
+
* opened this turn), then the registry's own resolution. Under
|
|
3755
|
+
* `speech.locus: 'delivery'` the registry alone has no default, and the
|
|
3756
|
+
* tool failed on the very turn its own delivery woke (first live run,
|
|
3757
|
+
* 2026-10-12). Both dispatch paths — the stream driver's and
|
|
3758
|
+
* executeToolCall's — pass through here. Only a call made inside the turn
|
|
3759
|
+
* (callingTurnOf) takes the turn's locus: one made outside it, as a script
|
|
3760
|
+
* left running after its turn makes or a host's executeToolCall naming the
|
|
3761
|
+
* agent, takes none of the turn's channels. A conversation fork's home
|
|
3762
|
+
* isn't the turn's but the fork's own, so such a call from a fork naming
|
|
3763
|
+
* no channel still goes there (homeOf), as the fork's dispatched calls do
|
|
3764
|
+
* (dispatchChannelToolCall); anyone else's takes the registry's own
|
|
3765
|
+
* default.
|
|
3766
|
+
*/
|
|
3767
|
+
private publishInputWithTurnLocus;
|
|
3228
3768
|
/**
|
|
3229
3769
|
* Stamps for the rows the agent's reply stores in its current turn: its
|
|
3230
3770
|
* assistant responses, its tool_result rows (through `storeResults`), and
|
|
@@ -3426,14 +3966,20 @@ export declare class AgentFramework {
|
|
|
3426
3966
|
* announced baseline alone (announceLocusIfChanged).
|
|
3427
3967
|
*/
|
|
3428
3968
|
private noticeHeartbeatTurn;
|
|
3969
|
+
private rememberAnnouncedLocus;
|
|
3970
|
+
private forgetAnnouncedLocus;
|
|
3971
|
+
/** The stored baseline's entry for the agent set (rememberAnnouncedLocus),
|
|
3972
|
+
* or removed (undefined) when the agent ends without coming back. */
|
|
3973
|
+
private writeAnnouncedLocus;
|
|
3429
3974
|
/**
|
|
3430
3975
|
* Announce-on-change locus notice (turn-frozen routing). Appends a durable
|
|
3431
3976
|
* `[routing]` window message when the turn's effective outbound locus
|
|
3432
3977
|
* differs from the last one announced — the agent must never have to guess
|
|
3433
3978
|
* where its plain prose lands. Durable append (never retracted) keeps the
|
|
3434
|
-
* KV prefix stable; change-only keeps it out of steady-state turns.
|
|
3435
|
-
*
|
|
3436
|
-
* no destination" is the unremarkable
|
|
3979
|
+
* KV prefix stable; change-only keeps it out of steady-state turns. An
|
|
3980
|
+
* agent never told of a locus, here or before a restart, hears only of a
|
|
3981
|
+
* non-null one ("prose has no destination" is the unremarkable start).
|
|
3982
|
+
* Never triggers
|
|
3437
3983
|
* inference; never locus-eligible itself (system + no channel metadata).
|
|
3438
3984
|
*/
|
|
3439
3985
|
private announceLocusIfChanged;
|
|
@@ -3445,7 +3991,11 @@ export declare class AgentFramework {
|
|
|
3445
3991
|
* as the agent's first view) that addressed the agent, or that follows up
|
|
3446
3992
|
* in a channel the turn sent into (TurnRouting.engaged). Undefined for any
|
|
3447
3993
|
* other message. A tool boundary weighs the messages it injects by it,
|
|
3448
|
-
* and noteArrival the ones no boundary of the turn weighs.
|
|
3994
|
+
* and noteArrival the ones no boundary of the turn weighs. The rule is
|
|
3995
|
+
* pure; what is done with its answer is `speech.locus`'s: under
|
|
3996
|
+
* `'latest-inbound'` the locus moves, under `'delivery'` (the default) the
|
|
3997
|
+
* agent is told it was addressed from elsewhere and the locus stays
|
|
3998
|
+
* (addressedElsewhereNotice).
|
|
3449
3999
|
*/
|
|
3450
4000
|
private repinChannel;
|
|
3451
4001
|
/** Whether `agent` has a turn alive: starting, streaming or waiting on its tools. */
|
|
@@ -3544,13 +4094,15 @@ export declare class AgentFramework {
|
|
|
3544
4094
|
* Weigh a message that no tool boundary of the agent's open logical turn
|
|
3545
4095
|
* will weigh: one that would re-pin the locus becomes one of the turn's
|
|
3546
4096
|
* arrivals (TurnRouting.arrivals). A message the agent's own view leaves
|
|
3547
|
-
* out, such as one
|
|
3548
|
-
*
|
|
4097
|
+
* out (agentSees), such as one held from the residents (heldFromResidents,
|
|
4098
|
+
* the admission stage's one predicate, which every resident's view filter
|
|
4099
|
+
* reads) or another agent's stored context injection, never enters its
|
|
4100
|
+
* compiled view, so the agent won't see it, and it moves nothing.
|
|
3549
4101
|
*/
|
|
3550
4102
|
private noteArrival;
|
|
3551
4103
|
/**
|
|
3552
4104
|
* Whether `agent`'s store is the residents' one message slot, which every
|
|
3553
|
-
* ordinary resident reads (
|
|
4105
|
+
* ordinary resident reads (`readsSharedSlot` in the registry). The subconscious reads that
|
|
3554
4106
|
* slot through a merged view, but its own store is isolated, as a fork's
|
|
3555
4107
|
* or an ephemeral agent's is.
|
|
3556
4108
|
*/
|
|
@@ -3591,6 +4143,23 @@ export declare class AgentFramework {
|
|
|
3591
4143
|
* so the agent's next turn announces where its speech lands.
|
|
3592
4144
|
*/
|
|
3593
4145
|
private repinTurnLocus;
|
|
4146
|
+
/**
|
|
4147
|
+
* Under `speech.locus: 'delivery'`: tell the agent that someone addressed
|
|
4148
|
+
* it from another channel while its turn was busy, since incoming traffic
|
|
4149
|
+
* never moves the locus and a neutral message carries nothing that names
|
|
4150
|
+
* its channel (first live run, 2026-10-12, finding C). Once per channel
|
|
4151
|
+
* per turn (TurnRouting.addressedElsewhere); nothing for the turn's own
|
|
4152
|
+
* locus. Stored durably; returned as stored for a live stream to inject
|
|
4153
|
+
* with its boundary's other messages. Undefined when nothing was stored.
|
|
4154
|
+
*/
|
|
4155
|
+
private addressedElsewhereNotice;
|
|
4156
|
+
/**
|
|
4157
|
+
* The arrivals a start of the turn consumes under `speech.locus:
|
|
4158
|
+
* 'delivery'`: each one that addressed the agent, whose message is still
|
|
4159
|
+
* in the store, gets the addressed-elsewhere notice, oldest first. A
|
|
4160
|
+
* follow-up in an engaged channel addressed nobody and is not announced.
|
|
4161
|
+
*/
|
|
4162
|
+
private noticeAddressedArrivals;
|
|
3594
4163
|
/**
|
|
3595
4164
|
* Durable window notice for a channel the agent did not ask to open: a
|
|
3596
4165
|
* subscription-policy admission, announced as the decision before its
|
|
@@ -4041,8 +4610,10 @@ export declare class AgentFramework {
|
|
|
4041
4610
|
* (ctx.callTool → executeToolCallFrom with {kind:'module'}), which is exempt
|
|
4042
4611
|
* from agent allowlists. Registered agents' allowedTools is enforced at
|
|
4043
4612
|
* dispatch, including namespaced utility names. Genuinely unidentified public callers (including
|
|
4044
|
-
* unknown legacy names) remain unrestricted.
|
|
4045
|
-
*
|
|
4613
|
+
* unknown legacy names) remain unrestricted. A name the framework made in
|
|
4614
|
+
* this process is refused while it isn't registered, even if its configured
|
|
4615
|
+
* list allows the tool; after a restart, such a name is a host's caller name
|
|
4616
|
+
* like any other.
|
|
4046
4617
|
*/
|
|
4047
4618
|
executeToolCall(call: ToolCall): Promise<ToolResult>;
|
|
4048
4619
|
/**
|
|
@@ -4107,6 +4678,29 @@ export declare class AgentFramework {
|
|
|
4107
4678
|
* tool it makes, under that tool's model-facing name and with its
|
|
4108
4679
|
* arguments, its id kept; or the reason it can't be sent. */
|
|
4109
4680
|
private resolveToolsetAct;
|
|
4681
|
+
/**
|
|
4682
|
+
* A reader reads and reports: a reader fork (registry kind
|
|
4683
|
+
* 'subconscious-fork', in every incarnation) may call only its own tools,
|
|
4684
|
+
* and speak_in_channel where allowChannelSpeech allows it. Every other
|
|
4685
|
+
* tool the resident has stays in its block (the shared prefix) and is
|
|
4686
|
+
* refused here, so with speech off a fork can post nowhere (scout's
|
|
4687
|
+
* condition, 2026-10-19). It's decided at each call from what the reader
|
|
4688
|
+
* may call, not from what it is shown, so a tool added or moved out of
|
|
4689
|
+
* the block later is refused too.
|
|
4690
|
+
*/
|
|
4691
|
+
private readerRefuses;
|
|
4692
|
+
/**
|
|
4693
|
+
* What a reader fork may call: exactly its own tools and the speech its
|
|
4694
|
+
* configuration allows, never widened or narrowed by its resident's
|
|
4695
|
+
* allowedTools. The resident's list bounds the resident's own surface;
|
|
4696
|
+
* the reader's tools are the framework's, for reading on its behalf. A
|
|
4697
|
+
* denyToolsAtDispatch entry the fork takes from its resident that names
|
|
4698
|
+
* one of them still refuses it (mayCallTool checks the deny first): a
|
|
4699
|
+
* resident never holds a reader tool, so such an entry is about readers.
|
|
4700
|
+
* The fork still shows its resident's block (the shared prefix): what it
|
|
4701
|
+
* may call is decided here, at each call, apart from what it is shown.
|
|
4702
|
+
*/
|
|
4703
|
+
private readerMayCall;
|
|
4110
4704
|
/** A toolsets--act call a host toolset resolved (HostPresentation.resolveAct):
|
|
4111
4705
|
* its refusal answered, or the tool's own call dispatched in its place,
|
|
4112
4706
|
* with the act's id, so its result is the act's. */
|
|
@@ -4456,9 +5050,15 @@ export declare class AgentFramework {
|
|
|
4456
5050
|
* that. Never prefix-map insertion order.
|
|
4457
5051
|
*/
|
|
4458
5052
|
private resolveMcplTool;
|
|
4459
|
-
/** Registered policy
|
|
4460
|
-
* while
|
|
5053
|
+
/** Registered policy. Within this process, a name the framework made has no
|
|
5054
|
+
* dispatch authority while it isn't registered; after a restart, a host call names
|
|
5055
|
+
* its caller as any host call does. Genuine legacy caller names retain
|
|
5056
|
+
* their surface. */
|
|
4461
5057
|
private canAgentUseTool;
|
|
5058
|
+
/** Whether a call of `toolName` as `agentName` is refused at dispatch (AgentConfig.denyToolsAtDispatch, or a reader's own rule). */
|
|
5059
|
+
private deniedAtDispatch;
|
|
5060
|
+
/** Whether `agentName` may call `toolName`: the one rule dispatch applies (agentToolPermissionFailure), for whatever else judges a call. */
|
|
5061
|
+
private mayCallTool;
|
|
4462
5062
|
private agentToolPermissionFailure;
|
|
4463
5063
|
private markedInputFailure;
|
|
4464
5064
|
private cutOffResults;
|
|
@@ -4571,6 +5171,14 @@ export declare class AgentFramework {
|
|
|
4571
5171
|
* the start now beginning (no tool boundary will weigh it), and one for
|
|
4572
5172
|
* every other resident's open turn. */
|
|
4573
5173
|
private noteStored;
|
|
5174
|
+
/**
|
|
5175
|
+
* Held agent mail is released only when its message has actually entered
|
|
5176
|
+
* the recipient's store — never on a deferral. Called at every site that
|
|
5177
|
+
* writes a message into a context: the direct path above and the two
|
|
5178
|
+
* deferred-write flushes (turn start, tool boundary). Both writes reach
|
|
5179
|
+
* disk in the same sync, so a crash keeps either both or neither.
|
|
5180
|
+
*/
|
|
5181
|
+
private releaseLandedMail;
|
|
4574
5182
|
/**
|
|
4575
5183
|
* Splice out the deferred messages addressed to `agentName` (explicitly
|
|
4576
5184
|
* via forAgent, or implicitly when it is the primary), leaving other
|
|
@@ -5008,7 +5616,7 @@ export declare class AgentFramework {
|
|
|
5008
5616
|
* The writes the framework holds for the store `reader` reads, in queue
|
|
5009
5617
|
* order: those addressed to it and, when it's an ordinary resident, those
|
|
5010
5618
|
* addressed to any ordinary resident, since residents share one message
|
|
5011
|
-
* slot (
|
|
5619
|
+
* slot (`readsSharedSlot` in the registry). A write whose target is gone isn't among them:
|
|
5012
5620
|
* no module reads that agent's store, and the write waits for its window's
|
|
5013
5621
|
* release (drainDeferredFor) or, at its flush, is dropped (addMessage), a
|
|
5014
5622
|
* failed reply, or a channel notice its reader could act on, passing to the
|
|
@@ -5944,6 +6552,15 @@ export declare class AgentFramework {
|
|
|
5944
6552
|
* error and nothing is written.
|
|
5945
6553
|
*/
|
|
5946
6554
|
private dispatchWakeRuleToolCall;
|
|
6555
|
+
/**
|
|
6556
|
+
* A reader's own tool (SUBCONSCIOUS_TOOL_NAMES), for both entries that run
|
|
6557
|
+
* an agent's call: the dispatcher's, for the model's call, and
|
|
6558
|
+
* executeToolCallFrom's, for a host's or the puppet's. The tools are
|
|
6559
|
+
* advertised to residents so reader forks share their prefix, and only a
|
|
6560
|
+
* registered reader may use them. A rejection is answered with a failed
|
|
6561
|
+
* result, never left unhandled.
|
|
6562
|
+
*/
|
|
6563
|
+
private readerToolCall;
|
|
5947
6564
|
/**
|
|
5948
6565
|
* Handle the synthesized `sleep` / `wake` tools. `sleep` arms the gate's
|
|
5949
6566
|
* suppression window, optionally announces in the sticky channel, and ends
|
|
@@ -5951,6 +6568,40 @@ export declare class AgentFramework {
|
|
|
5951
6568
|
*/
|
|
5952
6569
|
/** tune_out tool (residents): enter or cancel a channel tune-out. */
|
|
5953
6570
|
private dispatchTuneOutToolCall;
|
|
6571
|
+
/** `focus` is `tune_out` with scope "all-except". */
|
|
6572
|
+
private handleFocusTool;
|
|
6573
|
+
/**
|
|
6574
|
+
* A tune-out call's refusal for a channel it can't resolve: main's words
|
|
6575
|
+
* for a name no registered channel, and none of the calling turn's own,
|
|
6576
|
+
* answers to, and the registry's own otherwise, as for an id that is
|
|
6577
|
+
* ambiguous across servers (#232 gap 8).
|
|
6578
|
+
*/
|
|
6579
|
+
private unknownChannelWords;
|
|
6580
|
+
/**
|
|
6581
|
+
* The tune_out tool's body. Channel resolution is server-qualified
|
|
6582
|
+
* (ChannelRegistry.resolveChannel): with a `serverId`, that server's
|
|
6583
|
+
* channel with the id; inside the calling turn, a name one of the turn's
|
|
6584
|
+
* own channels answers to by its id means that channel; otherwise the one
|
|
6585
|
+
* channel the name means, which may be server-qualified, and a name two
|
|
6586
|
+
* servers' channels answer to is refused with them as candidates (#232
|
|
6587
|
+
* gap 8). `turn` is the turn that made the call (callingTurnOf), the only
|
|
6588
|
+
* one whose speech an all-except entry moves.
|
|
6589
|
+
*/
|
|
6590
|
+
private handleTuneOutTool;
|
|
6591
|
+
/**
|
|
6592
|
+
* The admission stage for one inbound event: the pure decision over the
|
|
6593
|
+
* framework's policy inputs (recipients, the hold in force, the wake
|
|
6594
|
+
* gate), traced. Callers apply it; nothing downstream re-asks.
|
|
6595
|
+
*/
|
|
6596
|
+
private admitInbound;
|
|
6597
|
+
/**
|
|
6598
|
+
* Make delivered messages durable now, including those the delivery left
|
|
6599
|
+
* in the deferred queue: a tune-out release flips durable epoch state
|
|
6600
|
+
* first, so its dump must not be lost to a crash in between (#232 gap 6).
|
|
6601
|
+
*/
|
|
6602
|
+
private commitDeliveries;
|
|
6603
|
+
/** The history-reading tool the primary resident actually has, if any (#232 gap 11). */
|
|
6604
|
+
private residentHistoryTool;
|
|
5954
6605
|
private dispatchSleepToolCall;
|
|
5955
6606
|
/**
|
|
5956
6607
|
* Handle the synthesized `read_image` tool: read image bytes from a
|