@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.
- package/LICENSE +202 -0
- package/README.md +777 -0
- package/dist/index.d.ts +8144 -0
- package/dist/index.js +26231 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
- package/src/cognition/agency/access.grants.ts +59 -0
- package/src/cognition/agency/competence.codec.ts +89 -0
- package/src/cognition/agency/engines/action.selector.ts +462 -0
- package/src/cognition/agency/engines/affordance.synthesizer.ts +384 -0
- package/src/cognition/agency/engines/deliberation.engine.ts +241 -0
- package/src/cognition/agency/engines/instruction.intake.ts +54 -0
- package/src/cognition/agency/engines/motor.schema.executor.ts +532 -0
- package/src/cognition/agency/engines/reafference.engine.ts +241 -0
- package/src/cognition/agency/execution.primitives.ts +118 -0
- package/src/cognition/agency/index.ts +58 -0
- package/src/cognition/agency/proactive.communicator.ts +274 -0
- package/src/cognition/agency/reconcile.learning.ts +82 -0
- package/src/cognition/agency/schemas/external.ts +59 -0
- package/src/cognition/agency/schemas/innate.ts +111 -0
- package/src/cognition/agency/schemas/repertoire.ts +246 -0
- package/src/cognition/agency/selection.scoring.ts +191 -0
- package/src/cognition/agency/types.ts +165 -0
- package/src/cognition/bus.ts +391 -0
- package/src/cognition/completion.inbox.ts +86 -0
- package/src/cognition/config.mirror.entities.ts +475 -0
- package/src/cognition/conversation.memory.ts +81 -0
- package/src/cognition/event.log.ts +116 -0
- package/src/cognition/event.schemas.ts +568 -0
- package/src/cognition/faculties/aesthetic.evaluator.ts +313 -0
- package/src/cognition/faculties/affective.blender.ts +562 -0
- package/src/cognition/faculties/attachment.evaluator.ts +432 -0
- package/src/cognition/faculties/attention.allocator.ts +422 -0
- package/src/cognition/faculties/autobiographical.narrator.ts +300 -0
- package/src/cognition/faculties/bias.detector.ts +363 -0
- package/src/cognition/faculties/circadian.oscillator.ts +294 -0
- package/src/cognition/faculties/confidence.calibrator.ts +324 -0
- package/src/cognition/faculties/dream.simulator.ts +251 -0
- package/src/cognition/faculties/empathy.simulator.ts +253 -0
- package/src/cognition/faculties/energy.regulator.ts +320 -0
- package/src/cognition/faculties/episodic.consolidator.ts +728 -0
- package/src/cognition/faculties/executive.engine/commands.ts +459 -0
- package/src/cognition/faculties/executive.engine/config.ts +46 -0
- package/src/cognition/faculties/executive.engine/context.ts +605 -0
- package/src/cognition/faculties/executive.engine/deferred.effects.ts +104 -0
- package/src/cognition/faculties/executive.engine/deliberate.reasoning.ts +60 -0
- package/src/cognition/faculties/executive.engine/effort.gate.ts +114 -0
- package/src/cognition/faculties/executive.engine/engine.ts +1028 -0
- package/src/cognition/faculties/executive.engine/escalation.buffer.ts +90 -0
- package/src/cognition/faculties/executive.engine/facet.supervisor.ts +271 -0
- package/src/cognition/faculties/executive.engine/facet.ts +628 -0
- package/src/cognition/faculties/executive.engine/gating.ts +222 -0
- package/src/cognition/faculties/executive.engine/index.ts +6 -0
- package/src/cognition/faculties/executive.engine/messages.ts +102 -0
- package/src/cognition/faculties/executive.engine/parser.ts +380 -0
- package/src/cognition/faculties/executive.engine/prompt.factory.ts +1053 -0
- package/src/cognition/faculties/executive.engine/types.ts +323 -0
- package/src/cognition/faculties/exteroception.ts +338 -0
- package/src/cognition/faculties/forgetting.curve.ts +202 -0
- package/src/cognition/faculties/frustration.evaluator.ts +280 -0
- package/src/cognition/faculties/goal.manager.ts +1008 -0
- package/src/cognition/faculties/inhibition.controller.ts +351 -0
- package/src/cognition/faculties/interoception.ts +417 -0
- package/src/cognition/faculties/introspection.engine.ts +246 -0
- package/src/cognition/faculties/known.entity.tracker.ts +439 -0
- package/src/cognition/faculties/loss.evaluator.ts +224 -0
- package/src/cognition/faculties/moral.evaluator.ts +437 -0
- package/src/cognition/faculties/novelty.detector.ts +254 -0
- package/src/cognition/faculties/persona.consolidator.ts +845 -0
- package/src/cognition/faculties/planning.engine/engine.ts +859 -0
- package/src/cognition/faculties/planning.engine/plan.frontier.ts +83 -0
- package/src/cognition/faculties/planning.engine/plan.store.ts +174 -0
- package/src/cognition/faculties/planning.engine/plan.supervision.ts +494 -0
- package/src/cognition/faculties/planning.engine/types.ts +143 -0
- package/src/cognition/faculties/reputation.tracker.ts +294 -0
- package/src/cognition/faculties/reward.evaluator.ts +304 -0
- package/src/cognition/faculties/self.model.updater.ts +677 -0
- package/src/cognition/faculties/semantic.engine/clustering.ts +673 -0
- package/src/cognition/faculties/semantic.engine/index.ts +6 -0
- package/src/cognition/faculties/semantic.engine/integrator.ts +750 -0
- package/src/cognition/faculties/semantic.engine/types.ts +53 -0
- package/src/cognition/faculties/sleep.pressure.regulator.ts +262 -0
- package/src/cognition/faculties/social.perception.ts +333 -0
- package/src/cognition/faculties/spaced.repetition.ts +605 -0
- package/src/cognition/faculties/stress.regulator.ts +375 -0
- package/src/cognition/faculties/task.switcher.ts +239 -0
- package/src/cognition/faculties/theory.of.mind.ts +333 -0
- package/src/cognition/faculties/threat.evaluator.ts +312 -0
- package/src/cognition/faculties/working.memory.ts +406 -0
- package/src/cognition/generative.model.ts +344 -0
- package/src/cognition/heartbeat.ts +70 -0
- package/src/cognition/index.ts +291 -0
- package/src/cognition/instruction.handler.ts +146 -0
- package/src/cognition/memory/index.ts +35 -0
- package/src/cognition/memory/vector.adapter.ts +316 -0
- package/src/cognition/memory/vector.content.ts +47 -0
- package/src/cognition/memory/vector.embedder.ts +212 -0
- package/src/cognition/memory/vector.index.ts +459 -0
- package/src/cognition/memory/vector.types.ts +65 -0
- package/src/cognition/orchestrator.ts +142 -0
- package/src/cognition/persona.prior.ts +265 -0
- package/src/cognition/schema.registry.ts +145 -0
- package/src/cognition/senses/audition.engine/engine.ts +976 -0
- package/src/cognition/senses/audition.engine/salience.ts +59 -0
- package/src/cognition/senses/base.sense.engine.ts +117 -0
- package/src/cognition/senses/gustation.engine.ts +24 -0
- package/src/cognition/senses/index.ts +172 -0
- package/src/cognition/senses/olfaction.engine.ts +24 -0
- package/src/cognition/senses/somatosensation.engine.ts +23 -0
- package/src/cognition/senses/vision.engine.ts +23 -0
- package/src/cognition/types.ts +63 -0
- package/src/cognition/utilities/token.tracker.ts +492 -0
- package/src/core/abstracts.ts +60 -0
- package/src/core/async.engine.ts +539 -0
- package/src/core/clock.ts +196 -0
- package/src/core/completion.recorder.ts +122 -0
- package/src/core/conflict.detector.ts +140 -0
- package/src/core/distributed.ts +626 -0
- package/src/core/event.bus.ts +292 -0
- package/src/core/inbound.recorder.ts +100 -0
- package/src/core/index.ts +167 -0
- package/src/core/logger.ts +85 -0
- package/src/core/metrics.ts +107 -0
- package/src/core/orchestrator.ts +625 -0
- package/src/core/replay.ts +589 -0
- package/src/core/scenario.ts +120 -0
- package/src/core/serialization.ts +448 -0
- package/src/core/simulation.ts +197 -0
- package/src/core/snapshot.manager.ts +293 -0
- package/src/core/state.manager.ts +283 -0
- package/src/core/types.ts +274 -0
- package/src/core/utils.ts +82 -0
- package/src/core/wall.clock.ts +23 -0
- package/src/extensions/livestream.ext.ts +570 -0
- package/src/extensions/time.ext.ts +339 -0
- package/src/index.ts +91 -0
- package/src/llm/gate.ts +140 -0
- package/src/llm/index.ts +716 -0
- package/src/llm/summarizer.ts +170 -0
- package/src/llm/wire.contracts.ts +67 -0
- package/src/pma/eval.ts +651 -0
- package/src/pma/index.ts +1082 -0
- package/src/profiles/built-in.ts +7 -0
- package/src/profiles/companion.ts +28 -0
- package/src/profiles/company-brain.ts +54 -0
- package/src/profiles/customer-service.ts +30 -0
- package/src/profiles/game-npc.ts +20 -0
- package/src/profiles/index.ts +42 -0
- package/src/profiles/smart-home.ts +34 -0
- package/src/runners/coherence.runner.ts +49 -0
- package/src/runners/outreach.runner.ts +158 -0
- package/src/runners/social.runner.ts +182 -0
- package/src/runners/thin-shim.runner.ts +195 -0
- package/src/sdk/will.ts +334 -0
- package/src/stem/assembly.audit.ts +88 -0
- package/src/stem/distribution.ts +203 -0
- package/src/stem/guards/identity.coherence.ts +152 -0
- package/src/stem/guards/identity.guard.ts +227 -0
- package/src/stem/index.ts +1145 -0
- package/src/stem/mind.ts +1090 -0
- package/src/stem/tracts/ack.reconciler.ts +55 -0
- package/src/stem/tracts/biography.writer.ts +190 -0
- package/src/stem/tracts/effector.controller.ts +143 -0
- package/src/stem/tracts/health.reporter.ts +113 -0
- package/src/stem/tracts/inbound.queue.ts +54 -0
- package/src/stem/tracts/outbox.controller.ts +167 -0
- package/src/stem/tracts/outbox.writer.ts +133 -0
- package/src/stem/tracts/pma.controller.ts +109 -0
- package/src/stem/tracts/replay.controller.ts +177 -0
- package/src/stem/tracts/sensory.controller.ts +168 -0
- package/src/stem/tracts/session.logger.ts +157 -0
- package/src/stem/tracts/transport/index.ts +38 -0
- package/src/stem/tracts/transport/loopback.transport.ts +86 -0
- package/src/stem/tracts/transport/socketio.transport.ts +200 -0
- package/src/stem/tracts/transport/stream.transport.ts +152 -0
- package/src/stem/tracts/transport/types.ts +193 -0
- package/src/stem/tracts/transport.controller.ts +380 -0
- package/src/types.ts +116 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/faculties/executive.engine/gating.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
import type { PendingMessage } from '#faculties/executive.engine/types'
|
|
6
|
+
import type { Tick, ReadonlySimulationState } from '#core/types'
|
|
7
|
+
import type { GenerativeModel } from '#cognition/generative.model'
|
|
8
|
+
import {
|
|
9
|
+
BUFFER_SALIENCE_TRIGGER,
|
|
10
|
+
BUFFER_MAX_AGE_TICKS,
|
|
11
|
+
} from '#faculties/executive.engine/config'
|
|
12
|
+
import type { CognitiveEvent } from '#cognition/bus'
|
|
13
|
+
|
|
14
|
+
function hasPendingInstructions( state: ReadonlySimulationState, pendingMessages: PendingMessage[] ): boolean {
|
|
15
|
+
for( const entity of state.entities.values() ){
|
|
16
|
+
if( entity.type === 'percept' || entity.type === 'percept.social' ){
|
|
17
|
+
const salience = (entity.metadata?.salience as number) ?? 0
|
|
18
|
+
if( salience > 0.7 ) return true
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if( entity.type === 'communication' && !entity.metadata?.processedByExecutive )
|
|
22
|
+
return true
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return pendingMessages.length > 0
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface GatingDependencies {
|
|
29
|
+
generativeModel: GenerativeModel
|
|
30
|
+
pendingMessages: PendingMessage[]
|
|
31
|
+
hasPendingWork: boolean
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface SalienceBufferEntry {
|
|
35
|
+
event: CognitiveEvent
|
|
36
|
+
tick: number
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface GatingState {
|
|
40
|
+
executiveInterval: number
|
|
41
|
+
cooldownTicks: number
|
|
42
|
+
lastExecutiveTick: number
|
|
43
|
+
salienceBuffer: SalienceBufferEntry[]
|
|
44
|
+
goallessTickCount: number
|
|
45
|
+
lowValenceTickCount: number
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface GatingResult {
|
|
49
|
+
shouldActivate: boolean
|
|
50
|
+
reason: string
|
|
51
|
+
/** Cleaned buffer with stale entries removed — caller must update GatingState. */
|
|
52
|
+
cleanedBuffer: SalienceBufferEntry[]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Full gating logic — pure function.
|
|
57
|
+
* Receives all state, returns decision + reason + cleaned buffer.
|
|
58
|
+
* The caller is responsible for updating GatingState with the result.
|
|
59
|
+
*/
|
|
60
|
+
export function evaluateGating(
|
|
61
|
+
state: ReadonlySimulationState,
|
|
62
|
+
tick: Tick,
|
|
63
|
+
deps: GatingDependencies,
|
|
64
|
+
gs: GatingState,
|
|
65
|
+
): GatingResult {
|
|
66
|
+
// ── In-flight work check ──────────────────────────────────
|
|
67
|
+
if( deps.hasPendingWork )
|
|
68
|
+
return {
|
|
69
|
+
shouldActivate: false,
|
|
70
|
+
reason: 'hasPendingWork',
|
|
71
|
+
cleanedBuffer: gs.salienceBuffer
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ── Cooldown — always enforced ────────────────────────────
|
|
75
|
+
if( tick - gs.lastExecutiveTick < gs.cooldownTicks )
|
|
76
|
+
return {
|
|
77
|
+
shouldActivate: false,
|
|
78
|
+
reason: 'cooldown',
|
|
79
|
+
cleanedBuffer: gs.salienceBuffer
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── Read metrics ──────────────────────────────────────────
|
|
83
|
+
const energy = state.metrics.get('energy.level') ?? 100
|
|
84
|
+
const isResting = state.metrics.get('state.resting') ?? 0
|
|
85
|
+
const isSleeping = state.metrics.get('state.sleeping') ?? 0
|
|
86
|
+
const isForcedRest = state.metrics.get('state.forced_rest') ?? 0
|
|
87
|
+
const novelty = state.metrics.get('perception.novelty') ?? 0
|
|
88
|
+
const sleepPressure = state.metrics.get('sleep.pressure') ?? 0
|
|
89
|
+
const stressLoad = state.metrics.get('stress.load') ?? 0
|
|
90
|
+
const valence = state.metrics.get('affect.valence') ?? 0
|
|
91
|
+
|
|
92
|
+
// ── Drop stale buffer entries ─────────────────────────────
|
|
93
|
+
const cleanedBuffer = gs.salienceBuffer.filter( e => tick - e.tick < BUFFER_MAX_AGE_TICKS )
|
|
94
|
+
|
|
95
|
+
// ── Accumulated workspace salience (GWT ignition pressure) ─
|
|
96
|
+
// Computed up-front so it both overrides prediction-gating at the interval
|
|
97
|
+
// boundary and drives the pre-interval early trigger further below.
|
|
98
|
+
const totalSalience = cleanedBuffer.reduce( ( s, e ) => s + ( e.event.salience ?? 0 ), 0 )
|
|
99
|
+
const salienceCharged = totalSalience >= BUFFER_SALIENCE_TRIGGER
|
|
100
|
+
|
|
101
|
+
// ── Forced shutdown (energy < 1) ──────────────────────────
|
|
102
|
+
if( isForcedRest > 0 )
|
|
103
|
+
return {
|
|
104
|
+
shouldActivate: false,
|
|
105
|
+
reason: 'forced_rest',
|
|
106
|
+
cleanedBuffer
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ── Voluntary rest/sleep — wake on high novelty or pending instructions ─
|
|
110
|
+
if( isResting > 0 || isSleeping > 0 ){
|
|
111
|
+
const
|
|
112
|
+
significantEvent = novelty > 0.8,
|
|
113
|
+
hasPending = hasPendingInstructions( state, deps.pendingMessages )
|
|
114
|
+
|
|
115
|
+
if( significantEvent || hasPending )
|
|
116
|
+
return {
|
|
117
|
+
shouldActivate: true,
|
|
118
|
+
reason: `awakened_from_${isSleeping > 0 ? 'sleep' : 'rest'}`,
|
|
119
|
+
cleanedBuffer
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
shouldActivate: false,
|
|
124
|
+
reason: 'resting',
|
|
125
|
+
cleanedBuffer
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ── Count active goals ────────────────────────────────────
|
|
130
|
+
let activeGoalCount = 0
|
|
131
|
+
for( const entity of state.entities.values() )
|
|
132
|
+
if( entity.type === 'goal' && entity.metadata?.status === 'active')
|
|
133
|
+
activeGoalCount++
|
|
134
|
+
|
|
135
|
+
// ── Physiological crises — bypass executiveInterval ───────
|
|
136
|
+
if( sleepPressure > 65 )
|
|
137
|
+
return { shouldActivate: true, reason: 'sleep_pressure_critical', cleanedBuffer }
|
|
138
|
+
|
|
139
|
+
if( stressLoad > 75 )
|
|
140
|
+
return { shouldActivate: true, reason: 'stress_overload', cleanedBuffer }
|
|
141
|
+
|
|
142
|
+
if( energy < 15 )
|
|
143
|
+
return { shouldActivate: true, reason: 'energy_critical', cleanedBuffer }
|
|
144
|
+
|
|
145
|
+
// ── Pending messages — always fire ────────────────────────
|
|
146
|
+
if( deps.pendingMessages.length > 0 )
|
|
147
|
+
return { shouldActivate: true, reason: 'pending_message', cleanedBuffer }
|
|
148
|
+
|
|
149
|
+
// ── Normal interval scheduling ────────────────────────────
|
|
150
|
+
if( tick - gs.lastExecutiveTick >= gs.executiveInterval ){
|
|
151
|
+
// Prediction-error gating — uses GenerativeModel.observe() which returns { gated }
|
|
152
|
+
const energyErr = deps.generativeModel.observe('energy.level', energy)
|
|
153
|
+
const stressErr = deps.generativeModel.observe('stress.load', stressLoad)
|
|
154
|
+
const noveltyErr = deps.generativeModel.observe('perception.novelty', novelty)
|
|
155
|
+
const valenceErr = deps.generativeModel.observe('affect.valence', valence)
|
|
156
|
+
|
|
157
|
+
const allGated = energyErr.gated && stressErr.gated && noveltyErr.gated && valenceErr.gated
|
|
158
|
+
const overdue = tick - gs.lastExecutiveTick >= gs.executiveInterval * 1.5
|
|
159
|
+
|
|
160
|
+
// A salience-charged workspace ignites even when every signal is well-predicted:
|
|
161
|
+
// accumulated salient coalitions are exactly what GWT ignition is meant to catch,
|
|
162
|
+
// so prediction-gating must not suppress them at the interval boundary.
|
|
163
|
+
if( allGated && !overdue && !salienceCharged )
|
|
164
|
+
return { shouldActivate: false, reason: 'prediction_gated', cleanedBuffer }
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
shouldActivate: true,
|
|
168
|
+
reason: salienceCharged ? 'salience_charged' : 'interval_elapsed',
|
|
169
|
+
cleanedBuffer
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ── Salience competition — early trigger (pre-interval) ───
|
|
174
|
+
if( salienceCharged )
|
|
175
|
+
return { shouldActivate: true, reason: 'salience_charged', cleanedBuffer }
|
|
176
|
+
|
|
177
|
+
// ── Cognitive crises — early trigger ──────────────────────
|
|
178
|
+
// Counter values are computed here (the caller will persist them via updateGatingState)
|
|
179
|
+
const goallessTicks = activeGoalCount === 0 ? gs.goallessTickCount + 1 : 0
|
|
180
|
+
const lowValenceTicks = valence < -0.4 ? gs.lowValenceTickCount + 1 : 0
|
|
181
|
+
|
|
182
|
+
if( goallessTicks > 20 )
|
|
183
|
+
return { shouldActivate: true, reason: 'goalless_crisis', cleanedBuffer }
|
|
184
|
+
|
|
185
|
+
if( lowValenceTicks > 30 )
|
|
186
|
+
return { shouldActivate: true, reason: 'low_valence_crisis', cleanedBuffer }
|
|
187
|
+
|
|
188
|
+
// ── High novelty — early trigger ──────────────────────────
|
|
189
|
+
if( novelty > 0.7 )
|
|
190
|
+
return { shouldActivate: true, reason: 'high_novelty', cleanedBuffer }
|
|
191
|
+
|
|
192
|
+
return { shouldActivate: false, reason: 'no_trigger', cleanedBuffer }
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Update the persistent gating state after a tick.
|
|
197
|
+
* Called every tick regardless of whether the executive activated.
|
|
198
|
+
*/
|
|
199
|
+
export function updateGatingState(
|
|
200
|
+
gs: GatingState,
|
|
201
|
+
state: ReadonlySimulationState,
|
|
202
|
+
_tick: Tick,
|
|
203
|
+
didActivate: boolean,
|
|
204
|
+
cleanedBuffer: SalienceBufferEntry[],
|
|
205
|
+
): void {
|
|
206
|
+
// Apply cleaned buffer
|
|
207
|
+
gs.salienceBuffer = cleanedBuffer
|
|
208
|
+
|
|
209
|
+
// Update crisis counters
|
|
210
|
+
let activeGoalCount = 0
|
|
211
|
+
for( const entity of state.entities.values() )
|
|
212
|
+
if( entity.type === 'goal' && entity.metadata?.status === 'active' )
|
|
213
|
+
activeGoalCount++
|
|
214
|
+
|
|
215
|
+
const valence = state.metrics.get('affect.valence') ?? 0
|
|
216
|
+
|
|
217
|
+
gs.goallessTickCount = activeGoalCount === 0 ? gs.goallessTickCount + 1 : 0
|
|
218
|
+
gs.lowValenceTickCount = valence < -0.4 ? gs.lowValenceTickCount + 1 : 0
|
|
219
|
+
|
|
220
|
+
if( didActivate )
|
|
221
|
+
gs.lastExecutiveTick = _tick
|
|
222
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/faculties/executive.engine/index.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
export { ExecutiveEngine, effortTargetForActions } from '#faculties/executive.engine/engine'
|
|
6
|
+
export type { ExecutiveEngineConfig, ExecutiveOutputFull } from '#faculties/executive.engine/types'
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/faculties/executive.engine/messages.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
import { logger } from '#core/logger'
|
|
6
|
+
import type { Tick, ReadonlySimulationState } from '#core/types'
|
|
7
|
+
import type { PendingMessage } from '#faculties/executive.engine/types'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Message queue state — tracks incoming communication entities,
|
|
11
|
+
* pending messages during in-flight LLM calls, and reply deduplication.
|
|
12
|
+
*/
|
|
13
|
+
export class MessageQueue {
|
|
14
|
+
/** Messages buffered while an LLM call is in-flight. */
|
|
15
|
+
pendingMessages: PendingMessage[] = []
|
|
16
|
+
|
|
17
|
+
/** Tick when the current (or most recent) LLM call started. */
|
|
18
|
+
pendingCallStartTick: number = -1
|
|
19
|
+
|
|
20
|
+
/** Entity IDs of communication entities that have been replied to this session. */
|
|
21
|
+
private _repliedEntityIds = new Set<string>()
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Scan the simulation state for unprocessed communication entities
|
|
25
|
+
* and queue them into pendingMessages. Call every tick.
|
|
26
|
+
*/
|
|
27
|
+
scanState( state: ReadonlySimulationState, tick: Tick ): void {
|
|
28
|
+
const seenIds = new Set( this.pendingMessages.map( m => m.id ) )
|
|
29
|
+
|
|
30
|
+
for( const [ id, entity ] of state.entities ){
|
|
31
|
+
if( entity.type !== 'communication' ) continue
|
|
32
|
+
if( entity.metadata?.processedByExecutive ) continue
|
|
33
|
+
if( seenIds.has( id ) ) continue
|
|
34
|
+
|
|
35
|
+
const msgTick = ( entity.metadata?.tick as number ) ?? 0
|
|
36
|
+
this.pendingMessages.push({
|
|
37
|
+
id,
|
|
38
|
+
content: (entity.metadata?.content as string) ?? '',
|
|
39
|
+
sender: (entity.metadata?.agentName as string) ?? 'unknown',
|
|
40
|
+
senderId: (entity.metadata?.keid as string) ?? 'unknown',
|
|
41
|
+
tick: msgTick
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
logger.info(`[executive] queued message from ${(entity.metadata?.agentName as string) ?? 'unknown'} (tick=${msgTick})`)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Clear messages that were included in the most recent LLM call.
|
|
50
|
+
* Any that arrived after the call started remain for the next cycle.
|
|
51
|
+
*/
|
|
52
|
+
clearProcessedMessages(): void {
|
|
53
|
+
this.pendingMessages = this.pendingMessages.filter( m => m.tick > this.pendingCallStartTick )
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Check if we've already replied to a specific communication entity this session.
|
|
58
|
+
*/
|
|
59
|
+
hasRepliedTo( entityId: string ): boolean {
|
|
60
|
+
return this._repliedEntityIds.has( entityId )
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Mark a communication entity as replied to.
|
|
65
|
+
*/
|
|
66
|
+
markReplied( entityId: string ): void {
|
|
67
|
+
this._repliedEntityIds.add( entityId )
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Build the set of communication entity IDs visible in state within the
|
|
72
|
+
* 30-tick window, plus any pending messages. Used to mark them as processed.
|
|
73
|
+
*/
|
|
74
|
+
getVisibleMessageIds( state: ReadonlySimulationState, tick: Tick ): Set<string> {
|
|
75
|
+
const ids = new Set<string>( this.pendingMessages.map( m => m.id ) )
|
|
76
|
+
for( const [ id, entity ] of state.entities ){
|
|
77
|
+
if( entity.type !== 'communication' ) continue
|
|
78
|
+
|
|
79
|
+
const msgTick = (entity.metadata?.tick as number) ?? 0
|
|
80
|
+
if( tick - msgTick > 30 ) continue
|
|
81
|
+
|
|
82
|
+
ids.add( id )
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return ids
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get stale communication entity IDs (>50 ticks old) for cleanup.
|
|
90
|
+
*/
|
|
91
|
+
getStaleMessageIds( state: ReadonlySimulationState, tick: Tick ): string[] {
|
|
92
|
+
const stale: string[] = []
|
|
93
|
+
for( const [ id, entity ] of state.entities ){
|
|
94
|
+
if( entity.type !== 'communication' ) continue
|
|
95
|
+
|
|
96
|
+
const msgTick = (entity.metadata?.tick as number) ?? 0
|
|
97
|
+
tick - msgTick > 50 && stale.push( id )
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return stale
|
|
101
|
+
}
|
|
102
|
+
}
|