@cosmonapse/sdk 0.1.2 → 0.1.3

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/index.d.ts CHANGED
@@ -153,6 +153,10 @@ declare function taskSignal(args: {
153
153
  directed?: DirectedInput;
154
154
  contextRef?: string;
155
155
  capabilities?: string[];
156
+ /** Terminal-handler finalize: the worker Dendrite that runs the addressed
157
+ * (or routed) Axon promotes a successful AGENT_OUTPUT by also emitting
158
+ * FINAL on the trace. Set automatically by `dispatch({ scope: "terminal" })`. */
159
+ finalize?: boolean;
156
160
  meta?: Json;
157
161
  }): Signal;
158
162
  /** [A] Wrap a Neuron's raw output in a neutral AGENT_OUTPUT envelope. */
@@ -224,17 +228,23 @@ declare function errorSignal(args: {
224
228
  * [A] A participant connecting to the Synapse and declaring its capabilities.
225
229
  *
226
230
  * Both Neurons and Engrams register the same way: `directed.id` is the
227
- * participant id, `directed.type` its type (neuron type or engram_kind), and
228
- * `directed.capabilities` its capability list. Pass `engram: true` for an
229
- * Engram so receivers record it as an Engram registration. `capabilities` is
230
- * mirrored into the payload for registry stores; when omitted it falls back to
231
- * `directed.capabilities`.
231
+ * participant id, `directed.type` its kind (`neuron_kind` for Neurons,
232
+ * `engram_kind` for Engrams), and `directed.capabilities` its capability list.
233
+ *
234
+ * Every REGISTER carries one universal discriminator, `payload.role`
235
+ * (`"neuron"` or `"engram"`): the single field every consumer (Dendrite
236
+ * registry, Prism, doppler) checks to classify the participant. `role`
237
+ * defaults from the `engram` flag when omitted. The legacy
238
+ * `payload.engram = true` marker is still emitted for Engrams as an alias.
239
+ * `capabilities` is mirrored into the payload for registry stores; when
240
+ * omitted it falls back to `directed.capabilities`.
232
241
  */
233
242
  declare function registerSignal(args: {
234
243
  directed: DirectedInput;
235
244
  capabilities?: string[];
236
245
  version?: string;
237
246
  engram?: boolean;
247
+ role?: "neuron" | "engram";
238
248
  meta?: Json;
239
249
  }): Signal;
240
250
  /** [A] A participant disconnecting from the Synapse. */
@@ -277,6 +287,30 @@ declare function bidSignal(args: {
277
287
  confidence?: number;
278
288
  meta?: Json;
279
289
  }): Signal;
290
+ /** [C] Award a TASK_OFFER to one bidder. The winning Axon's Dendrite treats
291
+ * this exactly like a TASK: `input` is the work payload, `directed`
292
+ * addresses the winner. `winningBid` carries the accepted bid for
293
+ * observability; `finalize` propagates the terminal-handler-finalize tag
294
+ * into the TASK the winner's Dendrite synthesises. */
295
+ declare function taskAwardedSignal(args: {
296
+ traceId: string;
297
+ parentId: string;
298
+ input: Json;
299
+ directed?: DirectedInput;
300
+ winningBid?: Json;
301
+ contextRef?: string;
302
+ finalize?: boolean;
303
+ meta?: Json;
304
+ }): Signal;
305
+ /** [C/A] Decline a TASK_OFFER. Producers emit this for losing bidders after
306
+ * picking a winner (informational); workers may emit it proactively. */
307
+ declare function taskDeclinedSignal(args: {
308
+ traceId: string;
309
+ parentId: string;
310
+ directed?: DirectedInput;
311
+ reason?: string;
312
+ meta?: Json;
313
+ }): Signal;
280
314
  /** [C] Peer review of another Neuron's output. `verdict`: 'pass' | 'fail' | 'revise'. */
281
315
  declare function critiqueSignal(args: {
282
316
  traceId: string;
@@ -984,6 +1018,22 @@ declare class LifecycleHooks<O> {
984
1018
  private spawnLoop;
985
1019
  }
986
1020
 
1021
+ /**
1022
+ * @cosmonapse/sdk - ambient trace context
1023
+ *
1024
+ * The (traceId, parentId) of the TASK currently being handled, carried in an
1025
+ * AsyncLocalStorage so code that runs *inside* a task but without explicit
1026
+ * trace plumbing - e.g. a `detects*` hook calling `dendrite.imprint` -
1027
+ * inherits the task's trace instead of minting a fresh one. The TS
1028
+ * counterpart to Python's `cosmonapse.envelope.trace_context` ContextVar.
1029
+ * Async-safe: each async execution context sees its own binding.
1030
+ */
1031
+ /** Return the ambient (traceId, parentId) of the task being handled, or null. */
1032
+ declare function ambientTrace(): readonly [string, string] | null;
1033
+ /** Bind the ambient (traceId, parentId) for the duration of `fn`. Set by
1034
+ * `Axon.handleTask` around the whole handling pass. */
1035
+ declare function runWithTraceContext<T>(traceId: string, parentId: string, fn: () => T): T;
1036
+
987
1037
  /**
988
1038
  * @cosmonapse/sdk - neuron contract
989
1039
  *
@@ -1005,7 +1055,33 @@ declare class LifecycleHooks<O> {
1005
1055
  * returns - a JSON-serialisable object, a {@link ClarificationOutput}, or a
1006
1056
  * {@link PermissionRequestOutput}.
1007
1057
  */
1008
- type NeuronFn = (input: Json, context: unknown[]) => Promise<Json> | Json;
1058
+ /**
1059
+ * Engram helpers handed to a Neuron as its (optional) third argument when the
1060
+ * hosting Axon declares `engrams: [...]` bindings. The TS counterpart to the
1061
+ * Python SDK's parameter-introspected `recall=` / `imprint=` injection - TS
1062
+ * cannot introspect parameter names, so the helpers ride a context object the
1063
+ * Neuron is free to ignore.
1064
+ */
1065
+ interface NeuronHelpers {
1066
+ recall(name: string, args: {
1067
+ query: Record<string, unknown>;
1068
+ filters?: Record<string, unknown>;
1069
+ contextRef?: string;
1070
+ deadlineMs?: number;
1071
+ recallMode?: "first" | "merge" | "all";
1072
+ minConfidence?: number;
1073
+ meta?: Record<string, unknown>;
1074
+ }): Promise<unknown>;
1075
+ imprint(name: string, args: {
1076
+ op: "add" | "append" | "merge" | "upsert" | "delete";
1077
+ entry: Record<string, unknown>;
1078
+ mergeKey?: string;
1079
+ awaitAck?: boolean;
1080
+ deadlineMs?: number;
1081
+ meta?: Record<string, unknown>;
1082
+ }): Promise<unknown>;
1083
+ }
1084
+ type NeuronFn = (input: Json, context: unknown[], helpers?: NeuronHelpers) => Promise<Json> | Json;
1009
1085
  /**
1010
1086
  * A NeuronFn that also exposes an async `close()` to release any resource it
1011
1087
  * holds (e.g. an MCP subprocess). The Axon calls `close()` automatically when
@@ -1069,6 +1145,142 @@ declare function errorResult(message: string, opts?: {
1069
1145
  /** Type guard: did the Neuron / recogniser return an error marker? */
1070
1146
  declare function isErrorOutput(output: unknown): output is ErrorOutput;
1071
1147
 
1148
+ /**
1149
+ * @cosmonapse/sdk - Engram (shared memory)
1150
+ *
1151
+ * Ported from the Python `cosmonapse.engram` package (see ENGRAM_DESIGN.md).
1152
+ * An Engram is the synapse-side participant that services RECALL / IMPRINT
1153
+ * signals. Engrams are NOT Neurons: they never produce AGENT_OUTPUT. A hosting
1154
+ * Dendrite mounts one via `dendrite.attachEngram(engram)`.
1155
+ *
1156
+ * This module is the value layer: the data types, the `Engram` contract, and
1157
+ * the default in-process `InMemoryEngram`. The SQLite / Postgres backends live
1158
+ * in `engram-sqlite.ts` / `engram-postgres.ts`; the caller-side correlation
1159
+ * table lives in `engram-client.ts`.
1160
+ */
1161
+
1162
+ type RecallMode = "first" | "merge" | "all";
1163
+ type ImprintOp = "add" | "append" | "merge" | "upsert" | "delete";
1164
+ /** One search result. `score` is backend-dependent; relational backends use 1.0. */
1165
+ interface Hit {
1166
+ id: string;
1167
+ entry: Json;
1168
+ score: number;
1169
+ }
1170
+ /** What a recall() call returns to the caller. */
1171
+ interface RecallResult {
1172
+ hits: Hit[];
1173
+ engramIds: string[];
1174
+ truncated: boolean;
1175
+ tookMs: number | null;
1176
+ }
1177
+ /** What an imprint() call returns to the caller. */
1178
+ interface ImprintReceipt {
1179
+ engramId: string;
1180
+ op: string;
1181
+ id: string | null;
1182
+ version: number | null;
1183
+ tookMs: number | null;
1184
+ error: string | null;
1185
+ /** Convenience: true when `error` is null. */
1186
+ ok: boolean;
1187
+ }
1188
+ interface EngramBindingInit {
1189
+ name: string;
1190
+ directedId?: string;
1191
+ directedType?: string;
1192
+ defaultDeadlineMs?: number;
1193
+ defaultRecallMode?: RecallMode;
1194
+ }
1195
+ /**
1196
+ * Declarative wiring of one Engram into an Axon. The Neuron addresses an Engram
1197
+ * by the stable local `name`; `directedId` / `directedType` determine how
1198
+ * RECALL/IMPRINT are routed on the wire. At least one of them must be set.
1199
+ */
1200
+ declare class EngramBinding {
1201
+ readonly name: string;
1202
+ readonly directedId: string | null;
1203
+ readonly directedType: string | null;
1204
+ readonly defaultDeadlineMs: number | null;
1205
+ readonly defaultRecallMode: RecallMode;
1206
+ constructor(init: EngramBindingInit);
1207
+ /** Build the `Directed` addressing this Engram. */
1208
+ toDirected(): Directed;
1209
+ }
1210
+ declare class EngramError extends Error {
1211
+ constructor(message?: string);
1212
+ }
1213
+ /** Raised when a RECALL or IMPRINT deadline elapses with no response. */
1214
+ declare class EngramTimeout extends EngramError {
1215
+ }
1216
+ /** Raised when the containing TASK terminates while a call is in flight. */
1217
+ declare class EngramCancelled extends EngramError {
1218
+ }
1219
+ /** Raised when a Neuron asks for an Engram binding its Axon was not wired to. */
1220
+ declare class EngramNotBound extends EngramError {
1221
+ }
1222
+ /** Raised by a backend that must shed load (surfaces as an IMPRINTED error). */
1223
+ declare class EngramOverloaded extends EngramError {
1224
+ }
1225
+ interface RecallOptions {
1226
+ filters?: Json;
1227
+ contextRef?: string;
1228
+ deadlineMs?: number;
1229
+ minConfidence?: number;
1230
+ }
1231
+ interface ImprintOptions {
1232
+ mergeKey?: string;
1233
+ /** Originating IMPRINT signal id; backends use it for idempotency. */
1234
+ imprintId?: string;
1235
+ }
1236
+ /**
1237
+ * Storage wrapper. One backend per Engram instance. Every backend implements
1238
+ * this exact interface; the test suite runs against any conforming Engram.
1239
+ */
1240
+ declare abstract class Engram {
1241
+ abstract engramId: string;
1242
+ abstract engramKind: string;
1243
+ abstract capabilities: string[];
1244
+ version: string | null;
1245
+ /** Open backend resources (DB pool, file handle, ...). */
1246
+ abstract connect(): Promise<void>;
1247
+ /** Release backend resources. */
1248
+ abstract close(): Promise<void>;
1249
+ /** Return matching entries. Empty array on a miss; never throw on a miss. */
1250
+ abstract recall(query: Json, opts?: RecallOptions): Promise<Hit[]>;
1251
+ /** Write to the backend. `op` is one of add | append | merge | upsert | delete. */
1252
+ abstract imprint(op: ImprintOp, entry: Json, opts?: ImprintOptions): Promise<ImprintReceipt>;
1253
+ /** Return false if this Engram cannot satisfy the query. Default: serve all. */
1254
+ canServe(_query: Json): Promise<boolean>;
1255
+ }
1256
+ interface InMemoryEngramInit {
1257
+ engramId?: string;
1258
+ engramKind?: string;
1259
+ capabilities?: string[];
1260
+ version?: string | null;
1261
+ }
1262
+ /** Dict-backed Engram. The default backend for tests and local dev. */
1263
+ declare class InMemoryEngram extends Engram {
1264
+ engramId: string;
1265
+ engramKind: string;
1266
+ capabilities: string[];
1267
+ private entries;
1268
+ private byMergeKey;
1269
+ private imprintSeen;
1270
+ constructor(init?: InMemoryEngramInit);
1271
+ connect(): Promise<void>;
1272
+ close(): Promise<void>;
1273
+ recall(query: Json, opts?: RecallOptions): Promise<Hit[]>;
1274
+ imprint(op: ImprintOp, entry: Json, opts?: ImprintOptions): Promise<ImprintReceipt>;
1275
+ /** Test/debug helper - NOT part of the Engram contract. */
1276
+ snapshot(): Json[];
1277
+ private makeEntry;
1278
+ private store;
1279
+ private evict;
1280
+ }
1281
+ /** Conservative deep merge: dicts merge, lists concat-dedup, scalars overwrite. */
1282
+ declare function deepMerge(base: unknown, incoming: unknown): unknown;
1283
+
1072
1284
  /**
1073
1285
  * @cosmonapse/sdk - MCP-server Neuron
1074
1286
  *
@@ -1146,6 +1358,18 @@ declare function mcpNeuron(opts: McpNeuronOptions): CloseableNeuronFn;
1146
1358
  * Output: `{ response: "<text>", meta: <raw provider payload> }`.
1147
1359
  */
1148
1360
 
1361
+ type Dict = Record<string, unknown>;
1362
+ /**
1363
+ * Render the close-the-loop TASK shapes into a prompt continuation.
1364
+ *
1365
+ * `respondToClarification` re-dispatches `{ clarification: { question,
1366
+ * answer, ... } }` and `respondToPermission` re-dispatches `{ permission:
1367
+ * { action, granted, reason?, ttl_ms?, ... } }`. Built-in LLM Neurons have no
1368
+ * native understanding of those keys, so without this rendering every default
1369
+ * close-the-loop flow died with "expects 'prompt' or 'messages'". Custom
1370
+ * NeuronFns can read the raw objects directly and never hit this path.
1371
+ */
1372
+ declare function followupPrompt(input: Dict): string | null;
1149
1373
  interface OllamaNeuronOptions {
1150
1374
  /** Ollama model tag, e.g. "llama3", "mistral", "phi3". */
1151
1375
  model: string;
@@ -1281,6 +1505,169 @@ declare function neuron(source: "openai", opts: OpenAINeuronOptions): NeuronFn;
1281
1505
  declare function neuron(source: "anthropic", opts: AnthropicNeuronOptions): NeuronFn;
1282
1506
  declare function neuron(source: OpenAICompatAlias, opts?: OpenAICompatNeuronOptions): NeuronFn;
1283
1507
 
1508
+ /**
1509
+ * @cosmonapse/sdk - pathway
1510
+ *
1511
+ * The Pathway primitive - a per-trace event handle, ported from
1512
+ * `cosmonapse.pathway`.
1513
+ *
1514
+ * A Pathway is the client-side observation surface for one logical workflow,
1515
+ * identified by its `trace_id`. Open one with
1516
+ * `dendrite.dispatch({ neuron, input })` (you become the *originator*), or
1517
+ * `dendrite.observePathway(traceId)` to watch a trace another peer started
1518
+ * (*observer*). Every Signal whose `trace_id` matches is delivered into it.
1519
+ *
1520
+ * Three consumption shapes on the same primitive:
1521
+ *
1522
+ * - `await pathway.wait()` - resolve on the next AGENT_OUTPUT /
1523
+ * CLARIFICATION / PERMISSION / ERROR / FINAL (request/reply shape).
1524
+ * - `pathway.on(SignalType.X, fn)` - callback per matching Signal
1525
+ * (reactive shape).
1526
+ * - `for await (const sig of pathway)` - iterate every Signal until close
1527
+ * (streaming shape).
1528
+ *
1529
+ * The shapes compose: callbacks, iteration and `wait()` each observe every
1530
+ * Signal independently - broadcasting, not draining a queue.
1531
+ *
1532
+ * Lifecycle: auto-closes on the first FINAL or ERROR; close explicitly with
1533
+ * `await pathway.close()`; the owning Dendrite closes survivors on `stop()`.
1534
+ */
1535
+
1536
+ /** Signals that auto-close a Pathway. AGENT_OUTPUT alone does NOT close it
1537
+ * because a streaming workflow may produce several before finalising. */
1538
+ declare const TERMINAL_TYPES: ReadonlySet<SignalType>;
1539
+ /**
1540
+ * Signal types that flow through a Pathway. Excludes management types
1541
+ * (REGISTER / DEREGISTER / HEARTBEAT / DISCOVER - own trace_id space) and
1542
+ * TASK (the originator knows it dispatched; excluding TASK also avoids a
1543
+ * double subscription on Dendrites that both host Axons and dispatch).
1544
+ */
1545
+ declare const PATHWAY_TYPES: ReadonlySet<SignalType>;
1546
+ type PathwaySignalHandler = (signal: Signal) => void | Promise<void>;
1547
+ type PathwayCloseHook = (pathway: Pathway) => void | Promise<void>;
1548
+ /** Raised when `wait()` is called on (or interrupted by) a closed Pathway. */
1549
+ declare class PathwayClosedError extends Error {
1550
+ constructor(message: string);
1551
+ }
1552
+ type PathwayRole = "originator" | "observer";
1553
+ type PathwayScope = "all" | "terminal";
1554
+ interface PathwayOptions {
1555
+ traceId: string;
1556
+ /** Per-operation correlation key: when set, the owning Dendrite routes
1557
+ * inbound Signals here by `signal.parent_id === parentId` (request/reply)
1558
+ * instead of by trace. This is what lets request/reply clients (e.g. an
1559
+ * EngramClient, `awaitDecision`) be thin wrappers over a Pathway. */
1560
+ parentId?: string | null;
1561
+ role?: PathwayRole;
1562
+ onClose?: PathwayCloseHook;
1563
+ /** "all" (default): every PATHWAY_TYPES Signal on the trace. "terminal":
1564
+ * only FINAL / ERROR / CLARIFICATION / PERMISSION - registered `on()`
1565
+ * callbacks still fire for scoped-out types (explicit interest). */
1566
+ scope?: PathwayScope;
1567
+ }
1568
+ declare class Pathway implements AsyncIterable<Signal> {
1569
+ readonly traceId: string;
1570
+ readonly parentId: string | null;
1571
+ readonly role: PathwayRole;
1572
+ readonly scope: PathwayScope;
1573
+ private readonly scopeFilter;
1574
+ private readonly onCloseHook;
1575
+ private readonly handlers;
1576
+ private waiters;
1577
+ private buffered;
1578
+ private closed_;
1579
+ private iterPush;
1580
+ private iterPull;
1581
+ constructor(opts: PathwayOptions);
1582
+ get closed(): boolean;
1583
+ /** Resolve on the next AGENT_OUTPUT, CLARIFICATION, PERMISSION, ERROR or
1584
+ * FINAL. Rejects with PathwayClosedError if the Pathway closes first, and
1585
+ * with a TimeoutError-named Error if `timeoutMs` elapses. */
1586
+ wait(timeoutMs?: number): Promise<Signal>;
1587
+ /** Resolve on the next Signal of the given type. */
1588
+ waitFor(type: SignalType, timeoutMs?: number): Promise<Signal>;
1589
+ private waitForTypes;
1590
+ /** Register a callback fired for each Signal of the given type. */
1591
+ on(type: SignalType, fn: PathwaySignalHandler): PathwaySignalHandler;
1592
+ [Symbol.asyncIterator](): AsyncIterator<Signal>;
1593
+ private iterEmit;
1594
+ /** Close the Pathway. Idempotent. Pending waits reject with
1595
+ * PathwayClosedError; iteration completes; the onClose hook fires once. */
1596
+ close(): Promise<void>;
1597
+ /** `await using pathway = ...` support. */
1598
+ [Symbol.asyncDispose](): Promise<void>;
1599
+ /** @internal */
1600
+ _deliver(signal: Signal): Promise<void>;
1601
+ private fireHandlers;
1602
+ }
1603
+
1604
+ /**
1605
+ * @cosmonapse/sdk - Engram caller-side client
1606
+ *
1607
+ * Ported from `cosmonapse.engram.client`. EngramClient is the caller-side
1608
+ * bridge: it builds RECALL / IMPRINT envelopes, publishes them, registers
1609
+ * pending promises keyed by the envelope id, and resolves them when a matching
1610
+ * RECALLED / IMPRINTED arrives (correlated by `parent_id`). It enforces
1611
+ * per-call deadlines and cancels in-flight calls when a TASK terminates.
1612
+ *
1613
+ * To avoid an import cycle with the Dendrite, the client depends only on a
1614
+ * minimal {@link EngramPublisher} (the Dendrite implements it by passing
1615
+ * itself in). The Dendrite owns the subscription to RECALLED / IMPRINTED and
1616
+ * calls `deliver(signal)` for each inbound.
1617
+ */
1618
+
1619
+ /** The slice of the Dendrite the client needs: a way to put a Signal on the wire. */
1620
+ interface EngramPublisher {
1621
+ publish(signal: Signal): Promise<void>;
1622
+ }
1623
+ interface RecallCallArgs {
1624
+ binding?: EngramBinding;
1625
+ engramId?: string;
1626
+ engramKind?: string;
1627
+ query: Json;
1628
+ filters?: Json;
1629
+ contextRef?: string;
1630
+ deadlineMs?: number;
1631
+ recallMode?: RecallMode;
1632
+ minConfidence?: number;
1633
+ traceId: string;
1634
+ parentId: string;
1635
+ meta?: Json;
1636
+ }
1637
+ interface ImprintCallArgs {
1638
+ binding?: EngramBinding;
1639
+ engramId?: string;
1640
+ engramKind?: string;
1641
+ op: ImprintOp;
1642
+ entry: Json;
1643
+ mergeKey?: string;
1644
+ awaitAck?: boolean;
1645
+ deadlineMs?: number;
1646
+ traceId: string;
1647
+ parentId: string;
1648
+ meta?: Json;
1649
+ }
1650
+ declare class EngramClient {
1651
+ private readonly publisher;
1652
+ private pendingRecalls;
1653
+ private pendingImprints;
1654
+ private byTrace;
1655
+ constructor(publisher: EngramPublisher);
1656
+ recall(args: RecallCallArgs): Promise<RecallResult>;
1657
+ imprint(args: ImprintCallArgs): Promise<ImprintReceipt | null>;
1658
+ /** Match RECALLED / IMPRINTED by parent_id and resolve pendings. */
1659
+ deliver(sig: Signal): void;
1660
+ /** Cancel every in-flight recall/imprint on a trace (FINAL/ERROR or shutdown). */
1661
+ cancelTrace(traceId: string): void;
1662
+ cancelAll(): void;
1663
+ private onRecallDeadline;
1664
+ private onImprintDeadline;
1665
+ private track;
1666
+ private cleanupRecall;
1667
+ private cleanupImprint;
1668
+ private discardTrace;
1669
+ }
1670
+
1284
1671
  /**
1285
1672
  * @cosmonapse/sdk - dendrite
1286
1673
  *
@@ -1288,27 +1675,29 @@ declare function neuron(source: OpenAICompatAlias, opts?: OpenAICompatNeuronOpti
1288
1675
  *
1289
1676
  * Construction is minimal: only `synapse` is required. Everything else is
1290
1677
  * opt-in:
1291
- * - Attach Axons -> subscribes to TASK, emits REGISTER / HEARTBEAT /
1292
- * DEREGISTER, routes inbound TASKs to the right Axon.
1293
- * - Register handlers -> subscribes to that AXON_TYPE and dispatches.
1678
+ * - Attach Axons -> subscribes to TASK (addressed broadcast) and the
1679
+ * capability-routed subject (queue-grouped), emits
1680
+ * REGISTER / HEARTBEAT / DEREGISTER, routes inbound
1681
+ * TASKs to the right Axon.
1682
+ * - Register handlers -> subscribes to that SignalType and dispatches.
1294
1683
  * - heartbeatMs = 0 -> the heartbeat loop never starts.
1295
1684
  *
1296
1685
  * The Dendrite does NOT own the Synapse - the caller builds and closes it.
1297
1686
  *
1298
- * There is no separate Cortex class: every Dendrite has dispatchTask /
1299
- * emitFinal / emitError / emit plus the inbound-handler hooks. `Cortex` is
1300
- * kept as a back-compat alias.
1687
+ * There is no separate Cortex class: every Dendrite has the dispatch family
1688
+ * (dispatch / dispatchAndWait / dispatchAndSubscribe / dispatchOffer /
1689
+ * dispatchTask), emitFinal / emitError / the cognition emit helpers, plus the
1690
+ * inbound-handler hooks. `Cortex` is kept as a back-compat alias.
1301
1691
  *
1302
- * Lifecycle: call `await dendrite.start()` / `await dendrite.stop()`, or use
1303
- * `await using dendrite = new Dendrite({...}); await dendrite.start();` - the
1304
- * Symbol.asyncDispose implementation calls stop() automatically when the scope
1305
- * exits. This is the TS counterpart to Python's `async with dendrite:`.
1692
+ * Unified dispatch: `dispatch()` returns a {@link Pathway} scoped to the
1693
+ * trace - await it, attach callbacks, or iterate. `scope: "terminal"`
1694
+ * additionally tags the TASK with `payload.finalize` (terminal-handler
1695
+ * finalize): the worker Dendrite that runs the Axon promotes a successful
1696
+ * AGENT_OUTPUT by also emitting FINAL, so terminal-scoped Pathways resolve
1697
+ * against stock workers.
1306
1698
  *
1307
- * LifecycleHooks (onConnect / onRefresh / onSchedule) are wired in: connect
1308
- * hooks fire and schedule loops launch at the end of start(); refresh hooks
1309
- * fire on every heartbeat tick and whenever a REGISTER / DEREGISTER / HEARTBEAT
1310
- * updates the registry; all loops stop in stop(). Attached Axons' hooks are
1311
- * driven alongside the Dendrite's own.
1699
+ * Lifecycle: `await dendrite.start()` / `await dendrite.stop()`, or
1700
+ * `await using dendrite = new Dendrite({...})`.
1312
1701
  */
1313
1702
 
1314
1703
  declare global {
@@ -1317,11 +1706,19 @@ declare global {
1317
1706
  }
1318
1707
  }
1319
1708
  type SignalHandler = (signal: Signal) => void | Promise<void>;
1709
+ /** Optional narrowing for handler registration - the TS counterpart to the
1710
+ * Python decorators' `neuron=` / `capability=` / `trace_id=` kwargs. */
1711
+ interface HandlerFilter {
1712
+ neuron?: string;
1713
+ capability?: string;
1714
+ traceId?: string;
1715
+ }
1320
1716
  /** Raised when an emit violates the protocol (e.g. emitting an Axon-only type). */
1321
1717
  declare class DendriteProtocolError extends Error {
1322
1718
  constructor(message: string);
1323
1719
  }
1324
1720
 
1721
+ type DendriteRole = "orchestrator" | "worker";
1325
1722
  interface DendriteOptions {
1326
1723
  synapse: Synapse;
1327
1724
  /** Optional registry. When set, the Dendrite mirrors its own Axons and
@@ -1333,101 +1730,323 @@ interface DendriteOptions {
1333
1730
  heartbeatMs?: number;
1334
1731
  /** Re-emit REGISTER on every heartbeat tick so late joiners catch up. */
1335
1732
  reregisterOnHeartbeat?: boolean;
1733
+ /** "orchestrator" (default, may dispatch TASKs) or "worker" (hosts Axons;
1734
+ * TASK initiation is refused, everything else is role-agnostic). */
1735
+ role?: DendriteRole;
1736
+ /** Default bidder (default true): a Dendrite hosting Axons answers
1737
+ * TASK_OFFERs whose capability set a hosted Axon covers, with cost 0 /
1738
+ * confidence 1 - unless a user onTaskOffer handler is registered, which
1739
+ * suppresses the default bidder entirely. */
1740
+ autoBid?: boolean;
1741
+ /** Liveness: a registered Neuron whose last heartbeat is older than this is
1742
+ * marked deregistered by the heartbeat loop's sweep. Default: 3 heartbeat
1743
+ * intervals; 0 disables. */
1744
+ staleAfterMs?: number;
1745
+ }
1746
+ interface DispatchArgs {
1747
+ neuron?: string;
1748
+ input: Json;
1749
+ traceId?: string;
1750
+ parentId?: string | null;
1751
+ contextRef?: string;
1752
+ capabilities?: string[];
1753
+ meta?: Json;
1336
1754
  }
1337
1755
  declare class Dendrite {
1338
1756
  readonly synapse: Synapse;
1339
1757
  readonly registryStore: RegistryStore | null;
1340
1758
  readonly namespace: string;
1341
1759
  readonly dendriteId: string;
1760
+ readonly role: DendriteRole;
1342
1761
  private readonly heartbeatMs;
1343
1762
  private readonly reregisterOnHeartbeat;
1763
+ private readonly autoBid;
1764
+ private readonly staleAfterMs;
1344
1765
  private readonly _axons;
1345
1766
  private readonly handlers;
1346
1767
  private taskSub;
1768
+ private routedTaskSub;
1347
1769
  private readonly inboundSubs;
1770
+ private readonly inflightSubs;
1771
+ private readonly pendingSubs;
1772
+ /** Recently seen CLARIFICATION_ANSWER / PERMISSION_DECISION signals keyed
1773
+ * by parent_id, so {@link awaitDecision} can serve an answer that arrived
1774
+ * before it was called (an in-process synapse can deliver the whole
1775
+ * request->answer chain within the original publish). Bounded FIFO. */
1776
+ private readonly recentDecisions;
1777
+ /** Hosted Engrams keyed by engramId, plus a kind index so RECALL/IMPRINT
1778
+ * addressed by engramKind reach every matching host. */
1779
+ private readonly _engrams;
1780
+ private readonly engramKindIndex;
1781
+ /** Engrams learned from peer REGISTER signals (possibly out-of-process). */
1782
+ private readonly _engramRegistrations;
1783
+ private readonly engramRegKindIndex;
1784
+ /** Caller-side correlation table for RECALL/IMPRINT awaiting
1785
+ * RECALLED/IMPRINTED. The Dendrite owns the subscriptions and feeds it. */
1786
+ readonly engramClient: EngramClient;
1348
1787
  private heartbeatTimer;
1349
1788
  private heartbeatStopped;
1350
1789
  private running;
1790
+ /** Open Pathways keyed by trace_id (dispatch / observePathway). */
1791
+ private readonly pathways;
1792
+ /** Per-operation Pathways keyed by the issuing request's id (matched
1793
+ * against inbound parent_id) - the generic request/reply primitive
1794
+ * behind awaitDecision (and a future EngramClient wiring). */
1795
+ private readonly opPathways;
1351
1796
  /** @internal - lifecycle hooks for this Dendrite. */
1352
1797
  readonly hooks: LifecycleHooks<Dendrite>;
1353
1798
  constructor(opts: DendriteOptions);
1354
1799
  get axons(): ReadonlyMap<string, Axon>;
1355
1800
  axon(neuronId: string): Axon | undefined;
1801
+ /** Aggregate of every attached Axon's capabilities, deduplicated + sorted. */
1802
+ get capabilities(): string[];
1803
+ /** Canonical queue-group name for this Dendrite's aggregate caps, or null
1804
+ * when no Axons are attached. Identical Dendrites share a group. */
1805
+ private capQueueGroup;
1806
+ private requireOrchestrator;
1807
+ /**
1808
+ * Attach an Axon to a *stopped* Dendrite. Throws if the Dendrite is
1809
+ * running - a running Dendrite needs the async activation path
1810
+ * (subscriptions, queue-group refresh, REGISTER): use
1811
+ * `await dendrite.addAxon(axon)` instead, which works in both states.
1812
+ */
1356
1813
  attachAxon(axon: Axon): void;
1814
+ private attachAxonRecord;
1815
+ /**
1816
+ * Attach an Axon; if the Dendrite is running, activate it live: ensure the
1817
+ * addressed + routed TASK subscriptions exist (re-keying the routed queue
1818
+ * group for the new aggregate cap profile), subscribe TASK_AWARDED /
1819
+ * DISCOVER (and TASK_OFFER when autoBid), mirror to the registry store,
1820
+ * emit REGISTER, and fire the Axon's onConnect hooks.
1821
+ */
1822
+ addAxon(axon: Axon): Promise<void>;
1823
+ /** Detach an Axon. If running: deregister, tear down its hooks, and re-key
1824
+ * (or drop) the TASK subscriptions for the changed cap profile. */
1825
+ detachAxon(neuronId: string, opts?: {
1826
+ reason?: string;
1827
+ }): Promise<void>;
1828
+ /**
1829
+ * Mount an Engram on this Dendrite. After attachment (and start), the
1830
+ * Dendrite subscribes to RECALL/IMPRINT, routes Signals addressed to
1831
+ * `engram.engramId` or matching `engram.engramKind` to the instance, and
1832
+ * announces it on the Synapse with an engram REGISTER. The Engram still
1833
+ * owns its backend lifecycle: `connect()` on start(), `close()` on stop().
1834
+ * When the Dendrite is already running, the backend is connected and the
1835
+ * subscriptions/REGISTER are established immediately.
1836
+ */
1837
+ attachEngram(engram: Engram): Promise<void>;
1838
+ /** Remove a hosted Engram. Closes its backend if the Dendrite is running. */
1839
+ detachEngram(engramId: string): Promise<void>;
1840
+ get engrams(): ReadonlyMap<string, Engram>;
1841
+ /** Engrams learned via REGISTER, keyed by directed.id (or directed.type
1842
+ * when no id), including in-process ones. */
1843
+ get engramRegistrations(): ReadonlyMap<string, Directed>;
1844
+ /** True when an Engram with this id/kind is reachable - hosted
1845
+ * in-process or learned from a peer's REGISTER. */
1846
+ isEngramKnown(opts: {
1847
+ engramId?: string;
1848
+ engramKind?: string;
1849
+ }): boolean;
1850
+ /** (Re)subscribe the capability-routed TASK subscription so its queue
1851
+ * group matches the *current* aggregate cap profile. */
1852
+ private refreshRoutedSub;
1853
+ private wrapWithFilter;
1854
+ private neuronHasCapability;
1357
1855
  private on;
1358
- onAgentOutput(fn: SignalHandler): SignalHandler;
1359
- onClarification(fn: SignalHandler): SignalHandler;
1856
+ /**
1857
+ * Generic handler registration for *any* SignalType - the escape hatch
1858
+ * behind every named `on*` helper. New protocol types are observable the
1859
+ * day they exist. Supports the same filters as the named helpers.
1860
+ */
1861
+ onSignal(type: SignalType, fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1862
+ /** Await until inbound subscriptions exist for `types` - removes the
1863
+ * late-registration race deterministically. Idempotent. */
1864
+ ensureSubscribed(...types: SignalType[]): Promise<void>;
1865
+ onAgentOutput(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1866
+ onClarification(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1360
1867
  /**
1361
1868
  * Register a handler fired on inbound PERMISSION requests - the *answering*
1362
- * side. A central Cortex or a peer Dendrite evaluates the request (often
1363
- * consulting an Engram of standing grants, keyed per-neuron) and replies via
1364
- * {@link respondToPermission} (re-dispatch a TASK with the verdict) or
1365
- * {@link grantPermission} / {@link denyPermission} (emit a discrete
1366
- * PERMISSION_DECISION). It may also imprint the decision into an Engram so
1367
- * future recalls hit.
1869
+ * side. Reply via {@link respondToPermission} (re-dispatch a TASK with the
1870
+ * verdict) or {@link grantPermission} / {@link denyPermission} (emit a
1871
+ * discrete PERMISSION_DECISION).
1368
1872
  */
1369
- onPermission(fn: SignalHandler): SignalHandler;
1370
- onErrorSignal(fn: SignalHandler): SignalHandler;
1371
- onRegister(fn: SignalHandler): SignalHandler;
1372
- onDeregister(fn: SignalHandler): SignalHandler;
1373
- onHeartbeat(fn: SignalHandler): SignalHandler;
1374
- /** Register a fire-once handler called after start() completes. */
1873
+ onPermission(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1874
+ onErrorSignal(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1875
+ /** Register a handler fired on FINAL - workflow conclusion. */
1876
+ onFinal(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1877
+ /** Observe inbound TASKs (audit/logging). Observation only - Axon routing
1878
+ * happens on its own subscription and is unaffected. */
1879
+ onTaskSignal(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1880
+ onRegister(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1881
+ onDeregister(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1882
+ onHeartbeat(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1883
+ onDiscover(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1884
+ onPlan(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1885
+ onThoughtDelta(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1886
+ onToolCall(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1887
+ onToolResult(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1888
+ onMemoryAppend(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1889
+ onCritique(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1890
+ onEscalation(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1891
+ onConsensus(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1892
+ onContextSync(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1893
+ /** Workers use this to evaluate offers and call {@link bid} to compete.
1894
+ * Registering it suppresses the default auto-bidder entirely. */
1895
+ onTaskOffer(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1896
+ /** Observe BIDs (market observability). dispatchOffer collects its own. */
1897
+ onBid(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1898
+ /** Observe TASK_AWARDED. The hosting Dendrite's award-to-TASK synthesis is
1899
+ * unaffected by handlers here. */
1900
+ onTaskAwarded(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1901
+ /** e.g. release a reservation made while bidding. */
1902
+ onTaskDeclined(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1903
+ /** Fired on CLARIFICATION_ANSWER - correlate by `sig.parent_id === the
1904
+ * CLARIFICATION's id`, or use {@link awaitDecision}. */
1905
+ onClarificationAnswer(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1906
+ /** Fired on PERMISSION_DECISION - correlate by parent_id, or use
1907
+ * {@link awaitDecision}. */
1908
+ onPermissionDecision(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1909
+ onRecalled(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1910
+ onImprinted(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1911
+ onRecallSignal(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1912
+ onImprintSignal(fn: SignalHandler, filter?: HandlerFilter): SignalHandler;
1913
+ private static readonly TRACE_DEFAULT_TYPES;
1914
+ /** Register one handler for multiple types narrowed to a single workflow. */
1915
+ onTrace(traceId: string, fn: SignalHandler, types?: SignalType[]): SignalHandler;
1375
1916
  onConnect(fn: ConnectHook<Dendrite>): ConnectHook<Dendrite>;
1376
- /** Register a handler called whenever this Dendrite's state refreshes. */
1377
1917
  onRefresh(fn: RefreshHook<Dendrite>): RefreshHook<Dendrite>;
1378
- /** Register a periodic handler that runs every `everyMs` until stop(). */
1379
1918
  onSchedule(everyMs: number, fn: ScheduleHook<Dendrite>): ScheduleHook<Dendrite>;
1380
- /** Manually fire a refresh event (reason defaults to "manual"). */
1381
1919
  refresh(opts?: {
1382
1920
  reason?: string;
1383
1921
  neuronId?: string | null;
1384
1922
  extra?: Record<string, unknown>;
1385
1923
  }): Promise<void>;
1386
1924
  start(): Promise<void>;
1387
- /**
1388
- * Heartbeat as a self-scheduling async loop rather than `setInterval`.
1389
- *
1390
- * Why not setInterval: it fires on a fixed wall-clock cadence regardless of
1391
- * whether the previous tick finished, so under load ticks overlap and the
1392
- * effective interval drifts; and because the callback is sync, any rejection
1393
- * from the async work inside is an unhandled rejection that setInterval
1394
- * silently drops. Here each tick is fully awaited, its errors are caught, and
1395
- * only then is the next tick scheduled - matching the Python SDK's
1396
- * asyncio.Task semantics (structured error handling + clean cancellation).
1397
- */
1398
1925
  private startHeartbeatLoop;
1399
1926
  stop(reason?: string): Promise<void>;
1400
- /**
1401
- * Explicit-resource-management hook so a Dendrite can be used with
1402
- * `await using` - the TS equivalent of Python's `async with dendrite:`.
1403
- *
1404
- * ```ts
1405
- * await using dendrite = new Dendrite({ synapse });
1406
- * dendrite.attachAxon(axon);
1407
- * await dendrite.start();
1408
- * // ... stop() runs automatically when this scope exits, even on throw.
1409
- * ```
1410
- *
1411
- * Idempotent: stop() is a no-op if the Dendrite was never started or already
1412
- * stopped. As with stop(), the caller still owns the Synapse/registry store.
1413
- */
1414
1927
  [Symbol.asyncDispose](): Promise<void>;
1415
1928
  private requireStore;
1416
1929
  /** All known records, optionally filtered (live records only by default). */
1417
- registrySnapshot(opts?: ListOptions): Promise<NeuronRecord[]>;
1418
- /** Live (non-deregistered) records, optionally filtered by capability. */
1930
+ registrySnapshot(opts?: ListOptions & {
1931
+ maxAgeMs?: number;
1932
+ }): Promise<NeuronRecord[]>;
1933
+ /** Live (non-deregistered) records, optionally filtered by capability.
1934
+ * `maxAgeMs` additionally drops records whose last heartbeat is older -
1935
+ * a read-side freshness guard when the background sweep can't be relied on. */
1419
1936
  findNeurons(opts?: {
1420
1937
  capability?: string;
1938
+ maxAgeMs?: number;
1421
1939
  }): Promise<NeuronRecord[]>;
1422
- dispatchTask(args: {
1423
- neuron: string;
1940
+ private static filterFresh;
1941
+ /**
1942
+ * Emit a TASK. Addressed (`neuron`) or capability-routed (`capabilities`)
1943
+ * - at least one must be set. `finalize: true` tags the TASK so the
1944
+ * handling worker Dendrite promotes a successful AGENT_OUTPUT to FINAL
1945
+ * (terminal-handler finalize - see {@link dispatch}). Only
1946
+ * orchestrator-role Dendrites may dispatch.
1947
+ */
1948
+ dispatchTask(args: DispatchArgs & {
1949
+ finalize?: boolean;
1950
+ }): Promise<Signal>;
1951
+ /** Publish a TASK to the right subject for its routing mode. Addressed ->
1952
+ * broadcast subject; capability-routed -> queue-grouped routed subject. */
1953
+ private publishTask;
1954
+ /**
1955
+ * Dispatch a TASK and return a {@link Pathway} scoped to its trace -
1956
+ * await it, attach callbacks, or iterate:
1957
+ *
1958
+ * ```ts
1959
+ * // 1) sequential / request-reply
1960
+ * const pw = await orch.dispatch({ neuron: "summarize", input });
1961
+ * const out = await pw.wait();
1962
+ *
1963
+ * // 2) reactive
1964
+ * pw.on(SignalType.PLAN, (sig) => { ... });
1965
+ *
1966
+ * // 3) streaming
1967
+ * for await (const sig of pw) { ... }
1968
+ * ```
1969
+ *
1970
+ * `capabilities` instead of `neuron` gives event-driven dispatch. Delivery
1971
+ * is exactly-once within a queue group (identical cap profiles) but
1972
+ * **at-least-once across heterogeneous groups** - use
1973
+ * {@link dispatchOffer} when overlapping profiles need an atomic claim.
1974
+ *
1975
+ * `scope: "terminal"` filters delivery to FINAL / ERROR / CLARIFICATION /
1976
+ * PERMISSION. `finalize` (default: true exactly when scope is "terminal")
1977
+ * tags the TASK for terminal-handler finalize: the worker Dendrite promotes
1978
+ * a successful AGENT_OUTPUT by also emitting FINAL - a default Axon never
1979
+ * emits FINAL itself, so a terminal-scoped Pathway would otherwise never
1980
+ * resolve against stock workers.
1981
+ */
1982
+ dispatch(args: DispatchArgs & {
1983
+ scope?: PathwayScope;
1984
+ finalize?: boolean;
1985
+ }): Promise<Pathway>;
1986
+ /** Sync-shape sugar: dispatch, await the first matching Signal, close the
1987
+ * Pathway, return the Signal. Use `scope: "terminal"` to wait only for
1988
+ * FINAL / ERROR / CLARIFICATION / PERMISSION. */
1989
+ dispatchAndWait(args: DispatchArgs & {
1990
+ scope?: PathwayScope;
1991
+ finalize?: boolean;
1992
+ timeoutMs?: number;
1993
+ }): Promise<Signal>;
1994
+ /** Async-shape sugar: dispatch, return the live Pathway immediately. The
1995
+ * caller attaches `pw.on(...)` callbacks or iterates. */
1996
+ dispatchAndSubscribe(args: DispatchArgs & {
1997
+ scope?: PathwayScope;
1998
+ finalize?: boolean;
1999
+ }): Promise<Pathway>;
2000
+ /** Open a Pathway in *observer* role for a trace another peer started. */
2001
+ observePathway(traceId: string): Promise<Pathway>;
2002
+ private ensurePathwaySubs;
2003
+ private openOpPathway;
2004
+ private cancelOpPathways;
2005
+ /**
2006
+ * Await the discrete answer to a CLARIFICATION or PERMISSION request.
2007
+ *
2008
+ * Opens a per-operation Pathway keyed on `request.id` and resolves on the
2009
+ * first CLARIFICATION_ANSWER / PERMISSION_DECISION whose parent_id matches.
2010
+ * The awaitable counterpart to {@link onClarificationAnswer} /
2011
+ * {@link onPermissionDecision}.
2012
+ */
2013
+ awaitDecision(request: Signal, opts?: {
2014
+ timeoutMs?: number;
2015
+ }): Promise<Signal>;
2016
+ /**
2017
+ * Broadcast a TASK_OFFER, collect BIDs for `deadlineMs`, award the winner
2018
+ * per `select` ("first_bid" | "lowest_cost" | "highest_confidence"), and
2019
+ * return a Pathway scoped to the resulting workflow. Losers get
2020
+ * TASK_DECLINED. Throws a TimeoutError-named Error when no BID arrives.
2021
+ * `finalize` follows the same rule as {@link dispatch}.
2022
+ */
2023
+ dispatchOffer(args: {
1424
2024
  input: Json;
2025
+ capabilities?: string[];
2026
+ deadlineMs?: number;
2027
+ select?: "first_bid" | "lowest_cost" | "highest_confidence";
1425
2028
  traceId?: string;
1426
2029
  parentId?: string | null;
1427
2030
  contextRef?: string;
1428
- capabilities?: string[];
2031
+ meta?: Json;
2032
+ scope?: PathwayScope;
2033
+ finalize?: boolean;
2034
+ }): Promise<Pathway>;
2035
+ /**
2036
+ * Emit a BID in response to a TASK_OFFER, on behalf of the local Axon named
2037
+ * by `neuron`. Bypasses the role guard - a worker bidding announces
2038
+ * capability, not orchestration.
2039
+ */
2040
+ bid(offer: Signal, args: {
2041
+ neuron: string;
2042
+ cost: number;
2043
+ etaMs?: number;
2044
+ confidence?: number;
1429
2045
  meta?: Json;
1430
2046
  }): Promise<Signal>;
2047
+ /** Default bidder: first hosted Axon whose caps cover the offer answers
2048
+ * (cost 0, confidence 1). No-op when nothing matches. */
2049
+ private maybeAutoBid;
1431
2050
  emitFinal(args: {
1432
2051
  traceId: string;
1433
2052
  parentId: string;
@@ -1442,16 +2061,109 @@ declare class Dendrite {
1442
2061
  recoverable?: boolean;
1443
2062
  meta?: Json;
1444
2063
  }): Promise<Signal>;
1445
- /** Emit a synapse-side Signal. Refuses Axon-owned types. */
2064
+ emitPlan(args: {
2065
+ traceId: string;
2066
+ parentId: string;
2067
+ steps: unknown[];
2068
+ rationale?: string;
2069
+ neuron?: string;
2070
+ meta?: Json;
2071
+ }): Promise<Signal>;
2072
+ emitThoughtDelta(args: {
2073
+ traceId: string;
2074
+ parentId: string;
2075
+ delta: string;
2076
+ seq?: number;
2077
+ neuron?: string;
2078
+ meta?: Json;
2079
+ }): Promise<Signal>;
2080
+ emitToolCall(args: {
2081
+ traceId: string;
2082
+ parentId: string;
2083
+ tool: string;
2084
+ args_: Json;
2085
+ callId?: string;
2086
+ neuron?: string;
2087
+ meta?: Json;
2088
+ }): Promise<Signal>;
2089
+ emitToolResult(args: {
2090
+ traceId: string;
2091
+ parentId: string;
2092
+ tool: string;
2093
+ result?: unknown;
2094
+ error?: string;
2095
+ callId?: string;
2096
+ neuron?: string;
2097
+ meta?: Json;
2098
+ }): Promise<Signal>;
2099
+ emitMemoryAppend(args: {
2100
+ traceId: string;
2101
+ parentId: string;
2102
+ key: string;
2103
+ value: unknown;
2104
+ neuron?: string;
2105
+ meta?: Json;
2106
+ }): Promise<Signal>;
2107
+ emitCritique(args: {
2108
+ traceId: string;
2109
+ parentId: string;
2110
+ targetEventId: string;
2111
+ issues: Json[];
2112
+ verdict: "pass" | "fail" | "revise";
2113
+ neuron?: string;
2114
+ meta?: Json;
2115
+ }): Promise<Signal>;
2116
+ emitEscalation(args: {
2117
+ traceId: string;
2118
+ parentId: string;
2119
+ reason: string;
2120
+ target?: string;
2121
+ context?: Json;
2122
+ neuron?: string;
2123
+ meta?: Json;
2124
+ }): Promise<Signal>;
2125
+ emitConsensus(args: {
2126
+ traceId: string;
2127
+ parentId: string;
2128
+ members: string[];
2129
+ verdict: string;
2130
+ votes?: Json;
2131
+ neuron?: string;
2132
+ meta?: Json;
2133
+ }): Promise<Signal>;
2134
+ emitContextSync(args: {
2135
+ traceId: string;
2136
+ parentId: string;
2137
+ snapshot: Json;
2138
+ version?: string;
2139
+ neuron?: string;
2140
+ meta?: Json;
2141
+ }): Promise<Signal>;
2142
+ /**
2143
+ * Reply to a CLARIFICATION by re-dispatching a TASK with the answer. The
2144
+ * new TASK is addressed by default to the asking Neuron, with parentId =
2145
+ * the clarification's id and the original traceId carried over. Input
2146
+ * shape: `{ clarification: { question, answer, ...extra } }`.
2147
+ */
2148
+ respondToClarification(request: Signal, opts: {
2149
+ answer: unknown;
2150
+ extra?: Json;
2151
+ neuron?: string;
2152
+ meta?: Json;
2153
+ }): Promise<Signal>;
2154
+ /**
2155
+ * Reply to an ESCALATION by dispatching a TASK to the escalation target
2156
+ * (default: `payload.target`). Default input:
2157
+ * `{ escalation: { reason, context, from } }`.
2158
+ */
2159
+ respondToEscalation(request: Signal, opts?: {
2160
+ neuron?: string;
2161
+ input?: Json;
2162
+ meta?: Json;
2163
+ }): Promise<Signal>;
1446
2164
  /**
1447
2165
  * Reply to a PERMISSION by re-dispatching a TASK carrying the verdict.
1448
- *
1449
- * The "send it back to the axon" path: the follow-up TASK is addressed by
1450
- * default to the Neuron that asked (`signal.neuron`), with `parentId` = the
1451
- * PERMISSION's id and the original `traceId` carried over, so the Neuron
1452
- * resumes on the same thread and can imprint the decision into an Engram (or
1453
- * recall it next time). New TASK input: `{ permission: { action, granted,
1454
- * reason?, ttlMs?, ...extra } }`.
2166
+ * Input shape: `{ permission: { action, granted, reason?, ttl_ms?, ...extra } }`.
1455
2167
  */
1456
2168
  respondToPermission(request: Signal, opts: {
1457
2169
  granted: boolean;
@@ -1461,8 +2173,7 @@ declare class Dendrite {
1461
2173
  neuron?: string;
1462
2174
  meta?: Json;
1463
2175
  }): Promise<Signal>;
1464
- /** Approve a PERMISSION request. `ttlMs` optionally advertises how long the
1465
- * grant is valid so the requester can cache it (e.g. in an Engram). */
2176
+ /** Approve a PERMISSION request. */
1466
2177
  grantPermission(request: Signal, opts?: {
1467
2178
  reason?: string;
1468
2179
  ttlMs?: number;
@@ -1474,24 +2185,86 @@ declare class Dendrite {
1474
2185
  meta?: Json;
1475
2186
  }): Promise<Signal>;
1476
2187
  private decidePermission;
1477
- /** Answer a *blocking* CLARIFICATION (the Neuron called ask(...) and is
1478
- * awaiting). Distinct from the legacy return-marker flow. */
2188
+ /** Answer a CLARIFICATION with a discrete CLARIFICATION_ANSWER signal
2189
+ * (parent_id = the request's id). Consumers pick it up via
2190
+ * {@link onClarificationAnswer} or {@link awaitDecision}. Distinct from
2191
+ * {@link respondToClarification}, which re-dispatches a TASK. */
1479
2192
  answerClarification(request: Signal, answer: unknown, opts?: {
1480
2193
  meta?: Json;
1481
2194
  }): Promise<Signal>;
2195
+ /** Emit a synapse-side Signal. Refuses Axon-owned types; TASK initiation
2196
+ * additionally requires orchestrator role. */
1482
2197
  emit(signal: Signal): Promise<void>;
1483
2198
  publish(signal: Signal): Promise<void>;
1484
2199
  subscribe(type: SignalType, handler: MessageHandler, opts?: {
1485
2200
  queueGroup?: string;
1486
2201
  }): Promise<Subscription>;
1487
2202
  private subject;
2203
+ /** Subject for capability-routed TASKs (queue-grouped consumers). */
2204
+ private routedSubject;
1488
2205
  private ensureInboundSub;
2206
+ /**
2207
+ * Route an inbound TASK to a local Axon. Addressed: by neuron_id (drop if
2208
+ * not hosted here). Capability-routed: first local Axon whose caps superset
2209
+ * the request. After publishing the reply, apply terminal-handler finalize:
2210
+ * a TASK tagged `payload.finalize` promotes a successful AGENT_OUTPUT by
2211
+ * also emitting FINAL (parented to the AGENT_OUTPUT, attributed to the
2212
+ * producing Neuron). Only AGENT_OUTPUT is promoted - CLARIFICATION /
2213
+ * PERMISSION pause the workflow and ERROR is already terminal.
2214
+ */
1489
2215
  private onTask;
1490
2216
  private emitRegister;
1491
2217
  private emitDeregister;
1492
2218
  private heartbeatTick;
2219
+ /** Mark Neurons deregistered when their last heartbeat is older than
2220
+ * `staleAfterMs`. Own hosted Axons were touched immediately before the
2221
+ * sweep, so they never qualify. */
2222
+ private sweepStaleNeurons;
1493
2223
  private mirrorToStore;
2224
+ /** Respond to a DISCOVER by re-emitting REGISTER for matching Axons. */
2225
+ private respondToDiscover;
1494
2226
  private dispatchInbound;
2227
+ /** Pick the hosted Engrams that should respond to a RECALL/IMPRINT.
2228
+ * directed.id (engramId) wins over directed.type (engramKind). */
2229
+ private resolveEngramTargets;
2230
+ private onRecall;
2231
+ private onImprint;
2232
+ private emitEngramRegister;
2233
+ private isEngramRegister;
2234
+ private recordEngramRegistration;
2235
+ /** Resolve (traceId, parentId) for a caller-side engram op: explicit ids
2236
+ * win, then the ambient task context (bound by Axon.handleTask), then a
2237
+ * freshly minted trace (the pre-task-hydration shape). */
2238
+ private static resolveTrace;
2239
+ /** Emit RECALL and await RECALLED. Trace attribution: explicit ids win,
2240
+ * then the ambient task context, then a fresh trace. */
2241
+ recall(args: {
2242
+ engramId?: string;
2243
+ engramKind?: string;
2244
+ query: Json;
2245
+ filters?: Json;
2246
+ contextRef?: string;
2247
+ deadlineMs?: number;
2248
+ recallMode?: RecallMode;
2249
+ minConfidence?: number;
2250
+ traceId?: string;
2251
+ parentId?: string;
2252
+ meta?: Json;
2253
+ }): Promise<RecallResult>;
2254
+ /** Emit IMPRINT. Resolves null unless `awaitAck: true`. Trace attribution
2255
+ * as {@link recall}. */
2256
+ imprint(args: {
2257
+ engramId?: string;
2258
+ engramKind?: string;
2259
+ op: ImprintOp;
2260
+ entry: Json;
2261
+ mergeKey?: string;
2262
+ awaitAck?: boolean;
2263
+ deadlineMs?: number;
2264
+ traceId?: string;
2265
+ parentId?: string;
2266
+ meta?: Json;
2267
+ }): Promise<ImprintReceipt | null>;
1495
2268
  private updateRegistry;
1496
2269
  }
1497
2270
  /** Back-compat alias - a Cortex is just a Dendrite. */
@@ -1545,25 +2318,49 @@ interface AxonOptions {
1545
2318
  neuronFn: NeuronFn;
1546
2319
  capabilities?: string[];
1547
2320
  version?: string;
2321
+ /** Participant kind carried on REGISTER as `directed.type` - the Neuron-side
2322
+ * analogue of an Engram's `engram_kind`. Defaults to `"neuron"`. */
2323
+ neuronKind?: string;
1548
2324
  contextFetcher?: ContextFetcher;
1549
2325
  /** Recognition the Axon applies to the Neuron's raw output before wrapping. */
1550
2326
  outputParser?: OutputParser;
2327
+ /**
2328
+ * Engram bindings the Neuron may address. Keyed by `binding.name` - the
2329
+ * Neuron passes that name to `helpers.recall(...)` / `helpers.imprint(...)`
2330
+ * (the helpers object is the Neuron's optional third argument). The Axon
2331
+ * enforces the whitelist, so a Neuron cannot hit an Engram it was not
2332
+ * declared to depend on.
2333
+ */
2334
+ engrams?: EngramBinding[];
1551
2335
  }
1552
2336
  /** Axon metadata accepted by the source-paired factories. */
1553
2337
  interface AxonExtra {
1554
2338
  capabilities?: string[];
1555
2339
  version?: string;
2340
+ /** Participant kind carried on REGISTER as `directed.type` (default "neuron"). */
2341
+ neuronKind?: string;
1556
2342
  contextFetcher?: ContextFetcher;
1557
2343
  /** Attach the source's recogniser (default true). */
1558
2344
  recognize?: boolean;
2345
+ /**
2346
+ * Append {@link COSMO_INTENT_SYSTEM_PROMPT} to the source's `system` prompt
2347
+ * so the model knows the `{"cosmo": ...}` convention the recogniser parses.
2348
+ * Default: true exactly when `recognize` is on and the source accepts a
2349
+ * `system` option (every LLM source except `huggingface`; `mcp` is never
2350
+ * taught). Pass false to opt out; passing true for an unsupported source
2351
+ * throws.
2352
+ */
2353
+ teachIntents?: boolean;
1559
2354
  }
1560
2355
  declare class Axon {
1561
2356
  readonly neuronId: string;
1562
2357
  readonly capabilities: string[];
1563
2358
  readonly version: string | undefined;
2359
+ readonly neuronKind: string;
1564
2360
  private readonly fn;
1565
2361
  private readonly contextFetcher;
1566
2362
  private readonly outputParser;
2363
+ private readonly engramBindings;
1567
2364
  private dendrite;
1568
2365
  /**
1569
2366
  * Decorator-registered recognisers, one bucket per capability (the asking
@@ -1572,9 +2369,21 @@ declare class Axon {
1572
2369
  * output by {@link applyRecognisers}.
1573
2370
  */
1574
2371
  private readonly recognisers;
2372
+ /** Pre-task hooks (beforeTask): transform/validate/reject the TASK input
2373
+ * before the Neuron runs. */
2374
+ private readonly beforeTaskHooks;
1575
2375
  /** @internal - lifecycle hooks, driven by the hosting Dendrite. */
1576
2376
  readonly hooks: LifecycleHooks<Axon>;
1577
2377
  constructor(opts: AxonOptions);
2378
+ /** Declared Engram bindings, keyed by name. */
2379
+ get engrams(): ReadonlyMap<string, EngramBinding>;
2380
+ private resolveBinding;
2381
+ /** Build the per-task helpers object handed to the Neuron as its third
2382
+ * argument. Helpers throw EngramNotBound for undeclared names and
2383
+ * require a hosting Dendrite (the only thing the Axon pulls from it). */
2384
+ private buildHelpers;
2385
+ /** Resolve the teach-intents decision and return (possibly augmented) source opts. */
2386
+ private static applyTeachIntents;
1578
2387
  private static build;
1579
2388
  /** Axon paired with any registered Neuron source + its recogniser. */
1580
2389
  static fromSource(source: NeuronSource, neuronId: string, opts: any, extra?: AxonExtra): Axon;
@@ -1588,6 +2397,16 @@ declare class Axon {
1588
2397
  static huggingface(neuronId: string, opts: HuggingFaceNeuronOptions, extra?: AxonExtra): Axon;
1589
2398
  /** Axon paired with a stdio MCP server. */
1590
2399
  static mcp(neuronId: string, opts: McpNeuronOptions, extra?: AxonExtra): Axon;
2400
+ /**
2401
+ * Register a pre-task hook over the TASK's `input`. Runs before the Neuron.
2402
+ * Sync or async; multiple hooks run in registration order, each receiving
2403
+ * the previous one's result. Return a (new) object to replace the input,
2404
+ * return null/undefined to pass through unchanged, or throw to reject the
2405
+ * TASK (surfaces as an ERROR Signal, code NEURON_EXCEPTION). The natural
2406
+ * place for input normalisation or per-Axon policy checks.
2407
+ */
2408
+ beforeTask(fn: (input: Json) => unknown | Promise<unknown>): (input: Json) => unknown | Promise<unknown>;
2409
+ private applyBeforeTask;
1591
2410
  /** Detector returning the AGENT_OUTPUT payload, or null to wrap verbatim. */
1592
2411
  detectsOutput(fn: Recogniser): Recogniser;
1593
2412
  /** Detector returning `{ question, context? }` to emit CLARIFICATION, or null. */
@@ -1612,217 +2431,30 @@ declare class Axon {
1612
2431
  [ATTACH](dendrite: Dendrite): void;
1613
2432
  /** Package-internal: invoked via the {@link DETACH} symbol. */
1614
2433
  [DETACH](): void;
1615
- /** Run the Neuron and return AGENT_OUTPUT / CLARIFICATION / ERROR. */
2434
+ /** Run the Neuron and return AGENT_OUTPUT / CLARIFICATION / ERROR.
2435
+ *
2436
+ * Binds the TASK's (traceId, parentId=task.id) as the ambient trace
2437
+ * context for the whole handling pass - neuronFn, detectors, and hooks
2438
+ * included - so engram calls made without explicit trace plumbing (e.g.
2439
+ * `dendrite.imprint` from a `detectsOutput` hook) are attributed to this
2440
+ * task's trace. */
1616
2441
  handleTask(task: Signal): Promise<Signal>;
2442
+ private handleTaskInner;
1617
2443
  }
2444
+ /**
2445
+ * System-prompt fragment teaching an LLM the `cosmo` intent convention.
2446
+ * Without it a hosted model never knows it *can* clarify / request permission
2447
+ * / signal a structured error, so the recognisers have nothing to recognise.
2448
+ * `Axon.fromSource(..., { recognize: true })` (the default) appends this to
2449
+ * the source's `system` prompt for system-capable LLM sources; opt out with
2450
+ * `teachIntents: false`.
2451
+ */
2452
+ declare const COSMO_INTENT_SYSTEM_PROMPT: string;
1618
2453
  /** Recogniser for LLM sources returning `{ response: text, meta }`. */
1619
2454
  declare function parseLlmIntents(raw: unknown): unknown;
1620
2455
  /** Recogniser for the `mcp` source: `is_error` -> ERROR, else pass through. */
1621
2456
  declare function parseMcpIntents(raw: unknown): unknown;
1622
2457
 
1623
- /**
1624
- * @cosmonapse/sdk - Engram (shared memory)
1625
- *
1626
- * Ported from the Python `cosmonapse.engram` package (see ENGRAM_DESIGN.md).
1627
- * An Engram is the synapse-side participant that services RECALL / IMPRINT
1628
- * signals. Engrams are NOT Neurons: they never produce AGENT_OUTPUT. A hosting
1629
- * Dendrite mounts one via `dendrite.attachEngram(engram)`.
1630
- *
1631
- * This module is the value layer: the data types, the `Engram` contract, and
1632
- * the default in-process `InMemoryEngram`. The SQLite / Postgres backends live
1633
- * in `engram-sqlite.ts` / `engram-postgres.ts`; the caller-side correlation
1634
- * table lives in `engram-client.ts`.
1635
- */
1636
-
1637
- type RecallMode = "first" | "merge" | "all";
1638
- type ImprintOp = "add" | "append" | "merge" | "upsert" | "delete";
1639
- /** One search result. `score` is backend-dependent; relational backends use 1.0. */
1640
- interface Hit {
1641
- id: string;
1642
- entry: Json;
1643
- score: number;
1644
- }
1645
- /** What a recall() call returns to the caller. */
1646
- interface RecallResult {
1647
- hits: Hit[];
1648
- engramIds: string[];
1649
- truncated: boolean;
1650
- tookMs: number | null;
1651
- }
1652
- /** What an imprint() call returns to the caller. */
1653
- interface ImprintReceipt {
1654
- engramId: string;
1655
- op: string;
1656
- id: string | null;
1657
- version: number | null;
1658
- tookMs: number | null;
1659
- error: string | null;
1660
- /** Convenience: true when `error` is null. */
1661
- ok: boolean;
1662
- }
1663
- interface EngramBindingInit {
1664
- name: string;
1665
- directedId?: string;
1666
- directedType?: string;
1667
- defaultDeadlineMs?: number;
1668
- defaultRecallMode?: RecallMode;
1669
- }
1670
- /**
1671
- * Declarative wiring of one Engram into an Axon. The Neuron addresses an Engram
1672
- * by the stable local `name`; `directedId` / `directedType` determine how
1673
- * RECALL/IMPRINT are routed on the wire. At least one of them must be set.
1674
- */
1675
- declare class EngramBinding {
1676
- readonly name: string;
1677
- readonly directedId: string | null;
1678
- readonly directedType: string | null;
1679
- readonly defaultDeadlineMs: number | null;
1680
- readonly defaultRecallMode: RecallMode;
1681
- constructor(init: EngramBindingInit);
1682
- /** Build the `Directed` addressing this Engram. */
1683
- toDirected(): Directed;
1684
- }
1685
- declare class EngramError extends Error {
1686
- constructor(message?: string);
1687
- }
1688
- /** Raised when a RECALL or IMPRINT deadline elapses with no response. */
1689
- declare class EngramTimeout extends EngramError {
1690
- }
1691
- /** Raised when the containing TASK terminates while a call is in flight. */
1692
- declare class EngramCancelled extends EngramError {
1693
- }
1694
- /** Raised when a Neuron asks for an Engram binding its Axon was not wired to. */
1695
- declare class EngramNotBound extends EngramError {
1696
- }
1697
- /** Raised by a backend that must shed load (surfaces as an IMPRINTED error). */
1698
- declare class EngramOverloaded extends EngramError {
1699
- }
1700
- interface RecallOptions {
1701
- filters?: Json;
1702
- contextRef?: string;
1703
- deadlineMs?: number;
1704
- minConfidence?: number;
1705
- }
1706
- interface ImprintOptions {
1707
- mergeKey?: string;
1708
- /** Originating IMPRINT signal id; backends use it for idempotency. */
1709
- imprintId?: string;
1710
- }
1711
- /**
1712
- * Storage wrapper. One backend per Engram instance. Every backend implements
1713
- * this exact interface; the test suite runs against any conforming Engram.
1714
- */
1715
- declare abstract class Engram {
1716
- abstract engramId: string;
1717
- abstract engramKind: string;
1718
- abstract capabilities: string[];
1719
- version: string | null;
1720
- /** Open backend resources (DB pool, file handle, ...). */
1721
- abstract connect(): Promise<void>;
1722
- /** Release backend resources. */
1723
- abstract close(): Promise<void>;
1724
- /** Return matching entries. Empty array on a miss; never throw on a miss. */
1725
- abstract recall(query: Json, opts?: RecallOptions): Promise<Hit[]>;
1726
- /** Write to the backend. `op` is one of add | append | merge | upsert | delete. */
1727
- abstract imprint(op: ImprintOp, entry: Json, opts?: ImprintOptions): Promise<ImprintReceipt>;
1728
- /** Return false if this Engram cannot satisfy the query. Default: serve all. */
1729
- canServe(_query: Json): Promise<boolean>;
1730
- }
1731
- interface InMemoryEngramInit {
1732
- engramId?: string;
1733
- engramKind?: string;
1734
- capabilities?: string[];
1735
- version?: string | null;
1736
- }
1737
- /** Dict-backed Engram. The default backend for tests and local dev. */
1738
- declare class InMemoryEngram extends Engram {
1739
- engramId: string;
1740
- engramKind: string;
1741
- capabilities: string[];
1742
- private entries;
1743
- private byMergeKey;
1744
- private imprintSeen;
1745
- constructor(init?: InMemoryEngramInit);
1746
- connect(): Promise<void>;
1747
- close(): Promise<void>;
1748
- recall(query: Json, opts?: RecallOptions): Promise<Hit[]>;
1749
- imprint(op: ImprintOp, entry: Json, opts?: ImprintOptions): Promise<ImprintReceipt>;
1750
- /** Test/debug helper - NOT part of the Engram contract. */
1751
- snapshot(): Json[];
1752
- private makeEntry;
1753
- private store;
1754
- private evict;
1755
- }
1756
- /** Conservative deep merge: dicts merge, lists concat-dedup, scalars overwrite. */
1757
- declare function deepMerge(base: unknown, incoming: unknown): unknown;
1758
-
1759
- /**
1760
- * @cosmonapse/sdk - Engram caller-side client
1761
- *
1762
- * Ported from `cosmonapse.engram.client`. EngramClient is the caller-side
1763
- * bridge: it builds RECALL / IMPRINT envelopes, publishes them, registers
1764
- * pending promises keyed by the envelope id, and resolves them when a matching
1765
- * RECALLED / IMPRINTED arrives (correlated by `parent_id`). It enforces
1766
- * per-call deadlines and cancels in-flight calls when a TASK terminates.
1767
- *
1768
- * To avoid an import cycle with the Dendrite, the client depends only on a
1769
- * minimal {@link EngramPublisher} (the Dendrite implements it by passing
1770
- * itself in). The Dendrite owns the subscription to RECALLED / IMPRINTED and
1771
- * calls `deliver(signal)` for each inbound.
1772
- */
1773
-
1774
- /** The slice of the Dendrite the client needs: a way to put a Signal on the wire. */
1775
- interface EngramPublisher {
1776
- publish(signal: Signal): Promise<void>;
1777
- }
1778
- interface RecallCallArgs {
1779
- binding?: EngramBinding;
1780
- engramId?: string;
1781
- engramKind?: string;
1782
- query: Json;
1783
- filters?: Json;
1784
- contextRef?: string;
1785
- deadlineMs?: number;
1786
- recallMode?: RecallMode;
1787
- minConfidence?: number;
1788
- traceId: string;
1789
- parentId: string;
1790
- meta?: Json;
1791
- }
1792
- interface ImprintCallArgs {
1793
- binding?: EngramBinding;
1794
- engramId?: string;
1795
- engramKind?: string;
1796
- op: ImprintOp;
1797
- entry: Json;
1798
- mergeKey?: string;
1799
- awaitAck?: boolean;
1800
- deadlineMs?: number;
1801
- traceId: string;
1802
- parentId: string;
1803
- meta?: Json;
1804
- }
1805
- declare class EngramClient {
1806
- private readonly publisher;
1807
- private pendingRecalls;
1808
- private pendingImprints;
1809
- private byTrace;
1810
- constructor(publisher: EngramPublisher);
1811
- recall(args: RecallCallArgs): Promise<RecallResult>;
1812
- imprint(args: ImprintCallArgs): Promise<ImprintReceipt | null>;
1813
- /** Match RECALLED / IMPRINTED by parent_id and resolve pendings. */
1814
- deliver(sig: Signal): void;
1815
- /** Cancel every in-flight recall/imprint on a trace (FINAL/ERROR or shutdown). */
1816
- cancelTrace(traceId: string): void;
1817
- cancelAll(): void;
1818
- private onRecallDeadline;
1819
- private onImprintDeadline;
1820
- private track;
1821
- private cleanupRecall;
1822
- private cleanupImprint;
1823
- private discardTrace;
1824
- }
1825
-
1826
2458
  /**
1827
2459
  * @cosmonapse/sdk - SQLite Engram
1828
2460
  *
@@ -1912,4 +2544,4 @@ declare class PostgresEngram extends Engram {
1912
2544
  */
1913
2545
  declare const VERSION: string;
1914
2546
 
1915
- export { AXON_TYPES, type AnthropicNeuronOptions, Axon, type AxonExtra, type AxonOptions, type ClarificationOutput, type CloseableNeuronFn, type ConnectHook, type ContextFetcher, Cortex, DendriteProtocolError as CortexProtocolError, Dendrite, type DendriteOptions, DendriteProtocolError, DevSynapse, type DevSynapseOptions, DevSynapseServer, type DevSynapseServerOptions, type Directed, type DirectedInput, Engram, EngramBinding, type EngramBindingInit, EngramCancelled, EngramClient, EngramError, EngramNotBound, EngramOverloaded, type EngramPublisher, EngramTimeout, type ErrorOutput, type Hit, type HuggingFaceNeuronOptions, type ImprintCallArgs, type ImprintOp, type ImprintOptions, type ImprintReceipt, InMemoryEngram, type InMemoryEngramInit, type Json, KafkaSynapse, type KafkaSynapseOptions, LifecycleHooks, type ListOptions, type McpNeuronOptions, MemoryRegistryStore, MemorySynapse, type MessageHandler, NatsSynapse, type NatsSynapseOptions, type NeuronFn, type NeuronRecord, type NeuronRecordInit, type NeuronSource, type NeuronStatus, type NewSignalInput, type OllamaNeuronOptions, type OpenAICompatNeuronOptions, type OpenAINeuronOptions, type OutputParser, type PermissionRequestOutput, PostgresEngram, type PostgresEngramInit, PostgresRegistryStore, type PostgresRegistryStoreOptions, type RecallCallArgs, type RecallMode, type RecallOptions, type RecallResult, type Recogniser, type RefreshEvent, type RefreshHook, type RegistryStore, type RequestOptions, SYNAPSE_TYPES, type ScheduleHook, type Signal, type SignalHandler, SignalType, SqliteEngram, type SqliteEngramInit, SqliteRegistryStore, type SubscribeOptions, type Subscription, type Synapse, VERSION, agentOutputSignal, anthropicNeuron, bidSignal, clarificationAnswerSignal, clarificationSignal, clarify, connectSynapse, consensusSignal, contextSyncSignal, createSignal, critiqueSignal, decode, deepMerge, deregisterSignal, directedTo, discoverSignal, encode, errorResult, errorSignal, escalationSignal, finalSignal, heartbeatSignal, huggingFaceNeuron, imprintSignal, imprintedSignal, isClarification, isErrorOutput, isPermissionRequest, mcpNeuron, memoryAppendSignal, neuron, neuronRecord, newEngramId, newEventId, newTraceId, normalizeDirected, ollamaNeuron, openaiNeuron, parseLlmIntents, parseMcpIntents, permissionDecisionSignal, permissionRequest, permissionSignal, planSignal, recallSignal, recalledSignal, registerSignal, reply, standardMcpServers, synapseFromUrl, taskOfferSignal, taskSignal, thoughtDeltaSignal, toolCallSignal, toolResultSignal, validateSignal };
2547
+ export { AXON_TYPES, type AnthropicNeuronOptions, Axon, type AxonExtra, type AxonOptions, COSMO_INTENT_SYSTEM_PROMPT, type ClarificationOutput, type CloseableNeuronFn, type ConnectHook, type ContextFetcher, Cortex, DendriteProtocolError as CortexProtocolError, Dendrite, type DendriteOptions, DendriteProtocolError, type DendriteRole, DevSynapse, type DevSynapseOptions, DevSynapseServer, type DevSynapseServerOptions, type Directed, type DirectedInput, Engram, EngramBinding, type EngramBindingInit, EngramCancelled, EngramClient, EngramError, EngramNotBound, EngramOverloaded, type EngramPublisher, EngramTimeout, type ErrorOutput, type HandlerFilter, type Hit, type HuggingFaceNeuronOptions, type ImprintCallArgs, type ImprintOp, type ImprintOptions, type ImprintReceipt, InMemoryEngram, type InMemoryEngramInit, type Json, KafkaSynapse, type KafkaSynapseOptions, LifecycleHooks, type ListOptions, type McpNeuronOptions, MemoryRegistryStore, MemorySynapse, type MessageHandler, NatsSynapse, type NatsSynapseOptions, type NeuronFn, type NeuronHelpers, type NeuronRecord, type NeuronRecordInit, type NeuronSource, type NeuronStatus, type NewSignalInput, type OllamaNeuronOptions, type OpenAICompatNeuronOptions, type OpenAINeuronOptions, type OutputParser, PATHWAY_TYPES, Pathway, type PathwayCloseHook, PathwayClosedError, type PathwayOptions, type PathwayRole, type PathwayScope, type PathwaySignalHandler, type PermissionRequestOutput, PostgresEngram, type PostgresEngramInit, PostgresRegistryStore, type PostgresRegistryStoreOptions, type RecallCallArgs, type RecallMode, type RecallOptions, type RecallResult, type Recogniser, type RefreshEvent, type RefreshHook, type RegistryStore, type RequestOptions, SYNAPSE_TYPES, type ScheduleHook, type Signal, type SignalHandler, SignalType, SqliteEngram, type SqliteEngramInit, SqliteRegistryStore, type SubscribeOptions, type Subscription, type Synapse, TERMINAL_TYPES, VERSION, agentOutputSignal, ambientTrace, anthropicNeuron, bidSignal, clarificationAnswerSignal, clarificationSignal, clarify, connectSynapse, consensusSignal, contextSyncSignal, createSignal, critiqueSignal, decode, deepMerge, deregisterSignal, directedTo, discoverSignal, encode, errorResult, errorSignal, escalationSignal, finalSignal, followupPrompt, heartbeatSignal, huggingFaceNeuron, imprintSignal, imprintedSignal, isClarification, isErrorOutput, isPermissionRequest, mcpNeuron, memoryAppendSignal, neuron, neuronRecord, newEngramId, newEventId, newTraceId, normalizeDirected, ollamaNeuron, openaiNeuron, parseLlmIntents, parseMcpIntents, permissionDecisionSignal, permissionRequest, permissionSignal, planSignal, recallSignal, recalledSignal, registerSignal, reply, runWithTraceContext, standardMcpServers, synapseFromUrl, taskAwardedSignal, taskDeclinedSignal, taskOfferSignal, taskSignal, thoughtDeltaSignal, toolCallSignal, toolResultSignal, validateSignal };