@mindot/will 0.1.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.
Files changed (178) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +777 -0
  3. package/dist/index.d.ts +8144 -0
  4. package/dist/index.js +26231 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +73 -0
  7. package/src/cognition/agency/access.grants.ts +59 -0
  8. package/src/cognition/agency/competence.codec.ts +89 -0
  9. package/src/cognition/agency/engines/action.selector.ts +462 -0
  10. package/src/cognition/agency/engines/affordance.synthesizer.ts +384 -0
  11. package/src/cognition/agency/engines/deliberation.engine.ts +241 -0
  12. package/src/cognition/agency/engines/instruction.intake.ts +54 -0
  13. package/src/cognition/agency/engines/motor.schema.executor.ts +532 -0
  14. package/src/cognition/agency/engines/reafference.engine.ts +241 -0
  15. package/src/cognition/agency/execution.primitives.ts +118 -0
  16. package/src/cognition/agency/index.ts +58 -0
  17. package/src/cognition/agency/proactive.communicator.ts +274 -0
  18. package/src/cognition/agency/reconcile.learning.ts +82 -0
  19. package/src/cognition/agency/schemas/external.ts +59 -0
  20. package/src/cognition/agency/schemas/innate.ts +111 -0
  21. package/src/cognition/agency/schemas/repertoire.ts +246 -0
  22. package/src/cognition/agency/selection.scoring.ts +191 -0
  23. package/src/cognition/agency/types.ts +165 -0
  24. package/src/cognition/bus.ts +391 -0
  25. package/src/cognition/completion.inbox.ts +86 -0
  26. package/src/cognition/config.mirror.entities.ts +475 -0
  27. package/src/cognition/conversation.memory.ts +81 -0
  28. package/src/cognition/event.log.ts +116 -0
  29. package/src/cognition/event.schemas.ts +568 -0
  30. package/src/cognition/faculties/aesthetic.evaluator.ts +313 -0
  31. package/src/cognition/faculties/affective.blender.ts +562 -0
  32. package/src/cognition/faculties/attachment.evaluator.ts +432 -0
  33. package/src/cognition/faculties/attention.allocator.ts +422 -0
  34. package/src/cognition/faculties/autobiographical.narrator.ts +300 -0
  35. package/src/cognition/faculties/bias.detector.ts +363 -0
  36. package/src/cognition/faculties/circadian.oscillator.ts +294 -0
  37. package/src/cognition/faculties/confidence.calibrator.ts +324 -0
  38. package/src/cognition/faculties/dream.simulator.ts +251 -0
  39. package/src/cognition/faculties/empathy.simulator.ts +253 -0
  40. package/src/cognition/faculties/energy.regulator.ts +320 -0
  41. package/src/cognition/faculties/episodic.consolidator.ts +728 -0
  42. package/src/cognition/faculties/executive.engine/commands.ts +459 -0
  43. package/src/cognition/faculties/executive.engine/config.ts +46 -0
  44. package/src/cognition/faculties/executive.engine/context.ts +605 -0
  45. package/src/cognition/faculties/executive.engine/deferred.effects.ts +104 -0
  46. package/src/cognition/faculties/executive.engine/deliberate.reasoning.ts +60 -0
  47. package/src/cognition/faculties/executive.engine/effort.gate.ts +114 -0
  48. package/src/cognition/faculties/executive.engine/engine.ts +1028 -0
  49. package/src/cognition/faculties/executive.engine/escalation.buffer.ts +90 -0
  50. package/src/cognition/faculties/executive.engine/facet.supervisor.ts +271 -0
  51. package/src/cognition/faculties/executive.engine/facet.ts +628 -0
  52. package/src/cognition/faculties/executive.engine/gating.ts +222 -0
  53. package/src/cognition/faculties/executive.engine/index.ts +6 -0
  54. package/src/cognition/faculties/executive.engine/messages.ts +102 -0
  55. package/src/cognition/faculties/executive.engine/parser.ts +380 -0
  56. package/src/cognition/faculties/executive.engine/prompt.factory.ts +1053 -0
  57. package/src/cognition/faculties/executive.engine/types.ts +323 -0
  58. package/src/cognition/faculties/exteroception.ts +338 -0
  59. package/src/cognition/faculties/forgetting.curve.ts +202 -0
  60. package/src/cognition/faculties/frustration.evaluator.ts +280 -0
  61. package/src/cognition/faculties/goal.manager.ts +1008 -0
  62. package/src/cognition/faculties/inhibition.controller.ts +351 -0
  63. package/src/cognition/faculties/interoception.ts +417 -0
  64. package/src/cognition/faculties/introspection.engine.ts +246 -0
  65. package/src/cognition/faculties/known.entity.tracker.ts +439 -0
  66. package/src/cognition/faculties/loss.evaluator.ts +224 -0
  67. package/src/cognition/faculties/moral.evaluator.ts +437 -0
  68. package/src/cognition/faculties/novelty.detector.ts +254 -0
  69. package/src/cognition/faculties/persona.consolidator.ts +845 -0
  70. package/src/cognition/faculties/planning.engine/engine.ts +859 -0
  71. package/src/cognition/faculties/planning.engine/plan.frontier.ts +83 -0
  72. package/src/cognition/faculties/planning.engine/plan.store.ts +174 -0
  73. package/src/cognition/faculties/planning.engine/plan.supervision.ts +494 -0
  74. package/src/cognition/faculties/planning.engine/types.ts +143 -0
  75. package/src/cognition/faculties/reputation.tracker.ts +294 -0
  76. package/src/cognition/faculties/reward.evaluator.ts +304 -0
  77. package/src/cognition/faculties/self.model.updater.ts +677 -0
  78. package/src/cognition/faculties/semantic.engine/clustering.ts +673 -0
  79. package/src/cognition/faculties/semantic.engine/index.ts +6 -0
  80. package/src/cognition/faculties/semantic.engine/integrator.ts +750 -0
  81. package/src/cognition/faculties/semantic.engine/types.ts +53 -0
  82. package/src/cognition/faculties/sleep.pressure.regulator.ts +262 -0
  83. package/src/cognition/faculties/social.perception.ts +333 -0
  84. package/src/cognition/faculties/spaced.repetition.ts +605 -0
  85. package/src/cognition/faculties/stress.regulator.ts +375 -0
  86. package/src/cognition/faculties/task.switcher.ts +239 -0
  87. package/src/cognition/faculties/theory.of.mind.ts +333 -0
  88. package/src/cognition/faculties/threat.evaluator.ts +312 -0
  89. package/src/cognition/faculties/working.memory.ts +406 -0
  90. package/src/cognition/generative.model.ts +344 -0
  91. package/src/cognition/heartbeat.ts +70 -0
  92. package/src/cognition/index.ts +291 -0
  93. package/src/cognition/instruction.handler.ts +146 -0
  94. package/src/cognition/memory/index.ts +35 -0
  95. package/src/cognition/memory/vector.adapter.ts +316 -0
  96. package/src/cognition/memory/vector.content.ts +47 -0
  97. package/src/cognition/memory/vector.embedder.ts +212 -0
  98. package/src/cognition/memory/vector.index.ts +459 -0
  99. package/src/cognition/memory/vector.types.ts +65 -0
  100. package/src/cognition/orchestrator.ts +142 -0
  101. package/src/cognition/persona.prior.ts +265 -0
  102. package/src/cognition/schema.registry.ts +145 -0
  103. package/src/cognition/senses/audition.engine/engine.ts +976 -0
  104. package/src/cognition/senses/audition.engine/salience.ts +59 -0
  105. package/src/cognition/senses/base.sense.engine.ts +117 -0
  106. package/src/cognition/senses/gustation.engine.ts +24 -0
  107. package/src/cognition/senses/index.ts +172 -0
  108. package/src/cognition/senses/olfaction.engine.ts +24 -0
  109. package/src/cognition/senses/somatosensation.engine.ts +23 -0
  110. package/src/cognition/senses/vision.engine.ts +23 -0
  111. package/src/cognition/types.ts +63 -0
  112. package/src/cognition/utilities/token.tracker.ts +492 -0
  113. package/src/core/abstracts.ts +60 -0
  114. package/src/core/async.engine.ts +539 -0
  115. package/src/core/clock.ts +196 -0
  116. package/src/core/completion.recorder.ts +122 -0
  117. package/src/core/conflict.detector.ts +140 -0
  118. package/src/core/distributed.ts +626 -0
  119. package/src/core/event.bus.ts +292 -0
  120. package/src/core/inbound.recorder.ts +100 -0
  121. package/src/core/index.ts +167 -0
  122. package/src/core/logger.ts +85 -0
  123. package/src/core/metrics.ts +107 -0
  124. package/src/core/orchestrator.ts +625 -0
  125. package/src/core/replay.ts +589 -0
  126. package/src/core/scenario.ts +120 -0
  127. package/src/core/serialization.ts +448 -0
  128. package/src/core/simulation.ts +197 -0
  129. package/src/core/snapshot.manager.ts +293 -0
  130. package/src/core/state.manager.ts +283 -0
  131. package/src/core/types.ts +274 -0
  132. package/src/core/utils.ts +82 -0
  133. package/src/core/wall.clock.ts +23 -0
  134. package/src/extensions/livestream.ext.ts +570 -0
  135. package/src/extensions/time.ext.ts +339 -0
  136. package/src/index.ts +91 -0
  137. package/src/llm/gate.ts +140 -0
  138. package/src/llm/index.ts +716 -0
  139. package/src/llm/summarizer.ts +170 -0
  140. package/src/llm/wire.contracts.ts +67 -0
  141. package/src/pma/eval.ts +651 -0
  142. package/src/pma/index.ts +1082 -0
  143. package/src/profiles/built-in.ts +7 -0
  144. package/src/profiles/companion.ts +28 -0
  145. package/src/profiles/company-brain.ts +54 -0
  146. package/src/profiles/customer-service.ts +30 -0
  147. package/src/profiles/game-npc.ts +20 -0
  148. package/src/profiles/index.ts +42 -0
  149. package/src/profiles/smart-home.ts +34 -0
  150. package/src/runners/coherence.runner.ts +49 -0
  151. package/src/runners/outreach.runner.ts +158 -0
  152. package/src/runners/social.runner.ts +182 -0
  153. package/src/runners/thin-shim.runner.ts +195 -0
  154. package/src/sdk/will.ts +334 -0
  155. package/src/stem/assembly.audit.ts +88 -0
  156. package/src/stem/distribution.ts +203 -0
  157. package/src/stem/guards/identity.coherence.ts +152 -0
  158. package/src/stem/guards/identity.guard.ts +227 -0
  159. package/src/stem/index.ts +1145 -0
  160. package/src/stem/mind.ts +1090 -0
  161. package/src/stem/tracts/ack.reconciler.ts +55 -0
  162. package/src/stem/tracts/biography.writer.ts +190 -0
  163. package/src/stem/tracts/effector.controller.ts +143 -0
  164. package/src/stem/tracts/health.reporter.ts +113 -0
  165. package/src/stem/tracts/inbound.queue.ts +54 -0
  166. package/src/stem/tracts/outbox.controller.ts +167 -0
  167. package/src/stem/tracts/outbox.writer.ts +133 -0
  168. package/src/stem/tracts/pma.controller.ts +109 -0
  169. package/src/stem/tracts/replay.controller.ts +177 -0
  170. package/src/stem/tracts/sensory.controller.ts +168 -0
  171. package/src/stem/tracts/session.logger.ts +157 -0
  172. package/src/stem/tracts/transport/index.ts +38 -0
  173. package/src/stem/tracts/transport/loopback.transport.ts +86 -0
  174. package/src/stem/tracts/transport/socketio.transport.ts +200 -0
  175. package/src/stem/tracts/transport/stream.transport.ts +152 -0
  176. package/src/stem/tracts/transport/types.ts +193 -0
  177. package/src/stem/tracts/transport.controller.ts +380 -0
  178. package/src/types.ts +116 -0
@@ -0,0 +1,152 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/stem/tracts/transport/stream.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+ //
5
+ // StreamTransport — an in-process ExternalTransport.
6
+ //
7
+ // Selected the same way as LoopbackTransport / SocketIoTransport: pass an
8
+ // instance as `config.transport`. Everything the Will emits — replies, chunks,
9
+ // messages, and the observability channels (`session_log`, `token_report`) —
10
+ // is delivered to the consumer's subscribed listeners instead of being written
11
+ // to files or S3 inside the Will. The consumer owns persistence/forwarding
12
+ // (Postgres, S3, Kafka, a billing meter, an SSE feed).
13
+ //
14
+ // `injectInbound()` lets the consumer drive inbound envelopes (messages,
15
+ // percepts, acks) into the Will, mirroring LoopbackTransport.
16
+ //
17
+ // Files remain available in DEVELOPMENT only: the producers (SessionLogger,
18
+ // TokenTracker) keep a local file mirror behind `fileLoggingEnabled()`.
19
+ // ─────────────────────────────────────────────────────────────
20
+
21
+ import type {
22
+ ExternalTransport,
23
+ OutboundEnvelope,
24
+ InboundEnvelope,
25
+ AckResult,
26
+ TransportStatus,
27
+ } from './types'
28
+
29
+ /** Channels a consumer can filter on (any OutboundEnvelope channel, or '*'). */
30
+ export type StreamChannel = OutboundEnvelope['channel'] | '*'
31
+ export type OutboundListener = ( env: OutboundEnvelope ) => void
32
+
33
+ export class StreamTransport implements ExternalTransport {
34
+ readonly willId: string
35
+
36
+ private _connected = true
37
+ private readonly _outbound = new Set<OutboundListener>()
38
+ private readonly _outboundByCh = new Map<string, Set<OutboundListener>>()
39
+ private readonly _inboundHandlers = new Set<( env: InboundEnvelope ) => void>()
40
+ private readonly _statusHandlers = new Set<( s: TransportStatus ) => void>()
41
+
42
+ constructor( willId: string = 'stream' ){
43
+ this.willId = willId
44
+ }
45
+
46
+ get connected(): boolean { return this._connected }
47
+
48
+ // ── ExternalTransport: Will → consumer ──────────────────────
49
+
50
+ /**
51
+ * Deliver an outbound envelope to subscribers. In-process and synchronous, so
52
+ * it resolves immediately (`via: 'event'`) — there is no remote peer to ack.
53
+ * A listener that throws is isolated; it can never break the tick loop.
54
+ */
55
+ async emit( env: OutboundEnvelope ): Promise<AckResult> {
56
+ this._dispatch( this._outbound, env )
57
+ this._dispatch( this._outboundByCh.get( env.channel ), env )
58
+ return { acked: true, via: 'event' }
59
+ }
60
+
61
+ // ── Consumer subscription (Will → consumer) ─────────────────
62
+
63
+ /** Subscribe to every outbound envelope. Returns an unsubscribe function. */
64
+ subscribe( listener: OutboundListener ): () => void {
65
+ this._outbound.add( listener )
66
+ return () => { this._outbound.delete( listener ) }
67
+ }
68
+
69
+ /**
70
+ * Subscribe to a single channel (e.g. `'token_report'`, `'session_log'`,
71
+ * `'reply'`) or `'*'` for all. Returns an unsubscribe function.
72
+ */
73
+ on( channel: StreamChannel, listener: OutboundListener ): () => void {
74
+ if( channel === '*' ) return this.subscribe( listener )
75
+ let set = this._outboundByCh.get( channel )
76
+ if( !set ){ set = new Set(); this._outboundByCh.set( channel, set ) }
77
+ set.add( listener )
78
+ return () => { set!.delete( listener ) }
79
+ }
80
+
81
+ // ── Consumer → Will (inbound) ───────────────────────────────
82
+
83
+ /**
84
+ * Inject an inbound envelope (message, percept, ack) into the Will. The stem
85
+ * enqueues it onto the tick-stamped InboundQueue and applies it deterministically
86
+ * on tick — this method itself never touches simulation state.
87
+ */
88
+ injectInbound( env: InboundEnvelope ): void {
89
+ for( const fn of this._inboundHandlers ){
90
+ try { fn( env ) }
91
+ catch { /* handler fault isolated */ }
92
+ }
93
+ }
94
+
95
+ onInbound( handler: ( env: InboundEnvelope ) => void ): () => void {
96
+ this._inboundHandlers.add( handler )
97
+ return () => { this._inboundHandlers.delete( handler ) }
98
+ }
99
+
100
+ onStatus( handler: ( s: TransportStatus ) => void ): () => void {
101
+ this._statusHandlers.add( handler )
102
+ return () => { this._statusHandlers.delete( handler ) }
103
+ }
104
+
105
+ /** Notify status subscribers (e.g. flip to 'disconnected' in a test). */
106
+ setStatus( status: TransportStatus ): void {
107
+ this._connected = status === 'connected'
108
+ for( const fn of this._statusHandlers ){
109
+ try { fn( status ) }
110
+ catch { /* isolated */ }
111
+ }
112
+ }
113
+
114
+ close(): void {
115
+ this._connected = false
116
+ this._outbound.clear()
117
+ this._outboundByCh.clear()
118
+ this._inboundHandlers.clear()
119
+ this._statusHandlers.clear()
120
+ }
121
+
122
+ /** Total active outbound listeners (diagnostics/tests). */
123
+ get listenerCount(): number {
124
+ let n = this._outbound.size
125
+ for( const set of this._outboundByCh.values() ) n += set.size
126
+ return n
127
+ }
128
+
129
+ private _dispatch( set: Set<OutboundListener> | undefined, env: OutboundEnvelope ): void {
130
+ if( !set ) return
131
+ for( const fn of set ){
132
+ try { fn( env ) }
133
+ catch { /* consumer listener must never break the Will */ }
134
+ }
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Whether producers should ALSO write their telemetry to local files.
140
+ *
141
+ * Files are a development convenience only. In production the stream/transport is
142
+ * the single source of truth and the consumer owns persistence.
143
+ *
144
+ * - `WILL_FILE_LOGS=true|1|false|0` — explicit override (wins).
145
+ * - otherwise: on when `NODE_ENV` is neither `production` nor `test`.
146
+ */
147
+ export function fileLoggingEnabled(): boolean {
148
+ const override = process.env['WILL_FILE_LOGS']
149
+ if( override !== undefined ) return override === 'true' || override === '1'
150
+ const env = process.env['NODE_ENV']
151
+ return env !== 'production' && env !== 'test'
152
+ }
@@ -0,0 +1,193 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/stem/tracts/transport/types.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+ //
5
+ // ExternalTransport — Will's unified bidirectional channel to its host peer
6
+ // (in production, a socket.io server owned by the backend).
7
+ //
8
+ // Replaces the per-concern, tick-drained SSE delivery model with a single
9
+ // envelope channel carrying every outbound concern (replies, chunks, outbox
10
+ // messages, effector invocations, activity) and every inbound concern (messages,
11
+ // percepts, acks).
12
+ //
13
+ // DETERMINISM CONTRACT (see EXTERNAL_TRANSPORT_TODO.md § guardrails):
14
+ // - This module and its implementations live ONLY under src/stem/tracts/.
15
+ // Nothing under src/cognition/ may import it.
16
+ // - Outbound emit() is a pure side effect — it never mutates simulation state.
17
+ // - Inbound is NOT applied here. The stem enqueues every InboundEnvelope onto
18
+ // the tick-stamped InboundQueue; the tick loop applies it deterministically.
19
+ // - wallTime is telemetry only (R2) — never feed it into replay-sensitive state.
20
+ // ─────────────────────────────────────────────────────────────
21
+
22
+ import type { effectorInvocation, OutboxMessage } from '#types'
23
+
24
+ // ── Shared base ────────────────────────────────────────────────
25
+
26
+ interface BaseEnvelope {
27
+ /** Will instance this envelope belongs to (routing key for the peer). */
28
+ willId: string
29
+ /**
30
+ * Stable id used to match an outbound envelope to its ack(s).
31
+ * For messages this is the OutboxMessage id; for effector invocations the
32
+ * decisionRecordId; for replies/chunks a generated id.
33
+ */
34
+ correlationId: string
35
+ /** Monotonic per-Will sequence number — ordering + dedup at the peer. */
36
+ seq: number
37
+ /** Wall-clock emit/arrival time. Telemetry only (R2) — never replay state. */
38
+ wallTime: number
39
+ }
40
+
41
+ // ── Outbound (Will → peer) ─────────────────────────────────────
42
+
43
+ /** Facet reply, assembled. Fast path — emitted the instant the facet decides. */
44
+ export interface ReplyEnvelope extends BaseEnvelope {
45
+ channel: 'reply'
46
+ entityId: string
47
+ threadId: string
48
+ bubbles: string[]
49
+ replyToMessageId?: string
50
+ }
51
+
52
+ /** One streamed LLM token for a live conversation. Fast path, best-effort. */
53
+ export interface ChunkEnvelope extends BaseEnvelope {
54
+ channel: 'chunk'
55
+ entityId: string
56
+ threadId: string
57
+ content: string
58
+ }
59
+
60
+ /** Generic outbox message (talk/text/gesture/broadcast). Bridged on tick drain. */
61
+ export interface MessageEnvelope extends BaseEnvelope {
62
+ channel: 'message'
63
+ message: OutboxMessage
64
+ }
65
+
66
+ /** External effector call for the peer/host to execute. Result returns via ack. */
67
+ export interface effectorInvocationEnvelope extends BaseEnvelope {
68
+ channel: 'effector_invocation'
69
+ invocation: effectorInvocation
70
+ }
71
+
72
+ /** Projection of a cognitive percept — observability only. */
73
+ export interface PerceptEnvelope extends BaseEnvelope {
74
+ channel: 'percept'
75
+ domain: string
76
+ payload: Record<string, unknown>
77
+ }
78
+
79
+ /** Plan/activity event for the peer's activity stream. */
80
+ export interface ActivityEnvelope extends BaseEnvelope {
81
+ channel: 'activity'
82
+ entityId: string
83
+ eventType: string
84
+ payload: Record<string, unknown>
85
+ }
86
+
87
+ /**
88
+ * A SessionLogger NDJSON entry — observability. Emitted so the consumer owns log
89
+ * persistence (Postgres, S3, Kafka, …) instead of the Will writing files/S3.
90
+ */
91
+ export interface SessionLogEnvelope extends BaseEnvelope {
92
+ channel: 'session_log'
93
+ entry: Record<string, unknown>
94
+ }
95
+
96
+ /**
97
+ * One attributed token/cost ledger record — observability + billing. Carries the
98
+ * 5-axis attribution (category/attribute/function/scope/label) + tokens + costUsd
99
+ * so the consumer can meter and re-bill end-users straight off the stream.
100
+ */
101
+ export interface TokenReportEnvelope extends BaseEnvelope {
102
+ channel: 'token_report'
103
+ report: Record<string, unknown>
104
+ }
105
+
106
+ export type OutboundEnvelope =
107
+ | ReplyEnvelope
108
+ | ChunkEnvelope
109
+ | MessageEnvelope
110
+ | effectorInvocationEnvelope
111
+ | PerceptEnvelope
112
+ | ActivityEnvelope
113
+ | SessionLogEnvelope
114
+ | TokenReportEnvelope
115
+
116
+ // ── Inbound (peer → Will) ──────────────────────────────────────
117
+
118
+ /** Conversational text/voice from an external entity. */
119
+ export interface InboundMessageEnvelope extends BaseEnvelope {
120
+ channel: 'inbound_message'
121
+ kind: 'text' | 'voice'
122
+ entityId: string
123
+ threadId: string
124
+ content: string
125
+ speakerName?: string
126
+ }
127
+
128
+ /** A non-conversational external percept (webhook, system signal, etc.). */
129
+ export interface InboundPerceptEnvelope extends BaseEnvelope {
130
+ channel: 'inbound_percept'
131
+ domain: string
132
+ payload: Record<string, unknown>
133
+ }
134
+
135
+ /**
136
+ * Acknowledgement for a prior outbound envelope.
137
+ * - 'delivery' → receipt confirmation (edge-level; updates outbox status)
138
+ * - 'result' → effector execution result (crosses determinism boundary →
139
+ * applied on tick via confirmExecution)
140
+ * `correlationId` points back to the acked outbound envelope.
141
+ */
142
+ export interface AckEnvelope extends BaseEnvelope {
143
+ channel: 'ack'
144
+ ackKind: 'delivery' | 'result'
145
+ delivered?: boolean
146
+ result?: {
147
+ success: boolean
148
+ description: string
149
+ metrics?: Record<string, number>
150
+ }
151
+ }
152
+
153
+ export type InboundEnvelope =
154
+ | InboundMessageEnvelope
155
+ | InboundPerceptEnvelope
156
+ | AckEnvelope
157
+
158
+ export type Envelope = OutboundEnvelope | InboundEnvelope
159
+
160
+ // ── Transport interface ────────────────────────────────────────
161
+
162
+ export type TransportStatus = 'connected' | 'disconnected' | 'reconnecting'
163
+
164
+ export interface AckResult {
165
+ acked: boolean
166
+ via: 'callback' | 'event' | 'timeout'
167
+ payload?: unknown
168
+ }
169
+
170
+ export interface ExternalTransport {
171
+ /** True when a live connection to the peer exists. */
172
+ readonly connected: boolean
173
+
174
+ /**
175
+ * Emit an outbound envelope. Resolves when the peer acks (via socket.io ack
176
+ * callback) or the ack times out. Resolution NEVER mutates simulation state —
177
+ * the caller decides what to do with the AckResult (e.g. requeue the outbox).
178
+ */
179
+ emit( env: OutboundEnvelope, opts?: { ackTimeoutMs?: number } ): Promise<AckResult>
180
+
181
+ /**
182
+ * Register a handler for inbound envelopes. The stem's handler MUST do nothing
183
+ * but enqueue onto the InboundQueue — application happens on tick.
184
+ * Returns an unsubscribe function.
185
+ */
186
+ onInbound( handler: ( env: InboundEnvelope ) => void ): () => void
187
+
188
+ /** Connection lifecycle notifications (for buffer flush on reconnect). */
189
+ onStatus( handler: ( status: TransportStatus ) => void ): () => void
190
+
191
+ /** Tear down the connection and all handlers. */
192
+ close(): void
193
+ }