@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,274 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/agency/proactive.communication.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ProactiveCommunicator — the agency pipeline's communicate-enaction handler.
|
|
7
|
+
*
|
|
8
|
+
* Owned privately by the MotorSchemaExecutor (its only caller): when a `communicate`
|
|
9
|
+
* motor schema wins the action competition, this turns the decided intent into
|
|
10
|
+
* delivery + memory. It validates the request, emits the memory/state side-effects
|
|
11
|
+
* (`conversation.sent` + the shared `conversation.exchange`), and hands the actual
|
|
12
|
+
* outbox row(s) to the shared OutboxWriter. It does NOT own the row shape (the
|
|
13
|
+
* writer does) and does NOT gate (AccessGrants does, upstream in the executor).
|
|
14
|
+
*
|
|
15
|
+
* Effectors handled: listen, talk, text, gesture, broadcast
|
|
16
|
+
*
|
|
17
|
+
* Outbound flow:
|
|
18
|
+
* agency MotorSchemaExecutor → ProactiveCommunicator → OutboxWriter.enqueue
|
|
19
|
+
* → OutboxController drains per tick → TransportController emits (or SSE)
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { logger } from '#core/logger'
|
|
23
|
+
import { wallClock } from '#core/wall.clock'
|
|
24
|
+
import type { ActionRequest, ActionResult } from '#types'
|
|
25
|
+
import type { ReadonlySimulationState, StateCommands } from '#core/types'
|
|
26
|
+
import type { OutboxWriter } from '#stem/tracts/outbox.writer'
|
|
27
|
+
import type { SessionLogger } from '#stem/tracts/session.logger'
|
|
28
|
+
import { buildConversationExchange } from '#cognition/conversation.memory'
|
|
29
|
+
|
|
30
|
+
export interface ProactiveCommunicatorOptions {
|
|
31
|
+
/** Shared outbox producer — owns the row shape; the executor delegates pushes. */
|
|
32
|
+
writer: OutboxWriter
|
|
33
|
+
willId?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class ProactiveCommunicator {
|
|
37
|
+
private _writer: OutboxWriter
|
|
38
|
+
private _willId: string
|
|
39
|
+
private _sessionLogger: SessionLogger | null = null
|
|
40
|
+
|
|
41
|
+
constructor( options: ProactiveCommunicatorOptions ){
|
|
42
|
+
this._writer = options.writer
|
|
43
|
+
this._willId = options.willId ?? 'will'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
attachSessionLogger( logger: SessionLogger | null ): void {
|
|
47
|
+
this._sessionLogger = logger
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async executeAction(
|
|
51
|
+
request: ActionRequest,
|
|
52
|
+
_state: ReadonlySimulationState,
|
|
53
|
+
): Promise<ActionResult> {
|
|
54
|
+
const commands: StateCommands = { metrics: [] }
|
|
55
|
+
|
|
56
|
+
switch( request.effector ){
|
|
57
|
+
case 'listen': return this._handleListen( request, commands )
|
|
58
|
+
case 'talk': return this._handleOutboundMessage('talk', request, commands )
|
|
59
|
+
case 'text': return this._handleOutboundMessage('text', request, commands )
|
|
60
|
+
case 'gesture': return this._handleGesture( request, commands )
|
|
61
|
+
case 'broadcast': return this._handleBroadcast( request, commands )
|
|
62
|
+
default:
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
description: `ProactiveCommunicator does not handle: ${request.effector}`,
|
|
66
|
+
commands,
|
|
67
|
+
feedback: { outcomeQuality: 0, surprise: 0, lessons: [] },
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ── Handlers ─────────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
private async _handleListen(
|
|
75
|
+
_request: ActionRequest,
|
|
76
|
+
commands: StateCommands,
|
|
77
|
+
): Promise<ActionResult> {
|
|
78
|
+
return {
|
|
79
|
+
success: true,
|
|
80
|
+
description: `You open yourself to incoming communication. Others may now reach you through available channels.`,
|
|
81
|
+
commands,
|
|
82
|
+
feedback: {
|
|
83
|
+
outcomeQuality: 1.0,
|
|
84
|
+
surprise: 0.05,
|
|
85
|
+
lessons: [ 'Being reachable allows others to connect with you.' ],
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private async _handleGesture(
|
|
91
|
+
request: ActionRequest,
|
|
92
|
+
commands: StateCommands,
|
|
93
|
+
): Promise<ActionResult> {
|
|
94
|
+
const targetEntityId = request.targetEntityId
|
|
95
|
+
?? ( request.parameters?.targetEntityId as string )
|
|
96
|
+
?? 'unknown'
|
|
97
|
+
const gestureType = ( request.parameters?.gestureType as string ) ?? 'gesture'
|
|
98
|
+
|
|
99
|
+
this._writer.enqueue({
|
|
100
|
+
targetEntityId,
|
|
101
|
+
content: gestureType,
|
|
102
|
+
effectorName: 'gesture',
|
|
103
|
+
gestureType,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
success: true,
|
|
108
|
+
description: `You ${gestureType} toward ${targetEntityId}. The gesture is directed and sincere.`,
|
|
109
|
+
commands,
|
|
110
|
+
feedback: {
|
|
111
|
+
outcomeQuality: 0.8,
|
|
112
|
+
surprise: 0.1,
|
|
113
|
+
lessons: [ 'Non-verbal communication carries its own weight.' ],
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private async _handleBroadcast(
|
|
119
|
+
request: ActionRequest,
|
|
120
|
+
commands: StateCommands,
|
|
121
|
+
): Promise<ActionResult> {
|
|
122
|
+
const rawMessages = request.parameters?.messages
|
|
123
|
+
const contentParam = ( request.parameters?.content as string ) ?? ''
|
|
124
|
+
const targetEntityIds = ( request.parameters?.targetEntityIds as string[] ) ?? []
|
|
125
|
+
|
|
126
|
+
const bubbles: string[] = Array.isArray( rawMessages )
|
|
127
|
+
? ( rawMessages as string[] ).filter( Boolean )
|
|
128
|
+
: [ contentParam || ( request.parameters?.message as string ) || '' ].filter( Boolean )
|
|
129
|
+
|
|
130
|
+
const finalContent = bubbles.join(' ')
|
|
131
|
+
const target = targetEntityIds.length > 0 ? targetEntityIds.join(',') : '*'
|
|
132
|
+
this._writer.enqueue({
|
|
133
|
+
targetEntityId: target,
|
|
134
|
+
content: finalContent,
|
|
135
|
+
effectorName: 'broadcast',
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
success: true,
|
|
140
|
+
description: `You broadcast: "${finalContent.slice( 0, 80 )}${finalContent.length > 80 ? '…' : ''}"`,
|
|
141
|
+
commands,
|
|
142
|
+
feedback: {
|
|
143
|
+
outcomeQuality: 0.75,
|
|
144
|
+
surprise: 0.2,
|
|
145
|
+
lessons: [ 'Broadcasts reach multiple entities simultaneously.' ],
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private async _handleOutboundMessage(
|
|
151
|
+
effectorName: 'talk' | 'text',
|
|
152
|
+
request: ActionRequest,
|
|
153
|
+
commands: StateCommands,
|
|
154
|
+
): Promise<ActionResult> {
|
|
155
|
+
const targetEntityId = request.targetEntityId
|
|
156
|
+
?? ( request.parameters?.targetEntityId as string )
|
|
157
|
+
const targetEntityName = ( request.parameters?.targetEntityName as string ) ?? targetEntityId ?? 'them'
|
|
158
|
+
|
|
159
|
+
// The executive always writes the actual words — no composition step.
|
|
160
|
+
// Accept `messages` (array), or legacy `message`/`content` (single string).
|
|
161
|
+
const rawMessages = request.parameters?.messages
|
|
162
|
+
const bubbles: string[] = Array.isArray( rawMessages )
|
|
163
|
+
? ( rawMessages as string[] ).filter( Boolean )
|
|
164
|
+
: [ ( request.parameters?.message as string )
|
|
165
|
+
|| ( request.parameters?.content as string )
|
|
166
|
+
|| '' ].filter( Boolean )
|
|
167
|
+
|
|
168
|
+
if( !targetEntityId ){
|
|
169
|
+
return {
|
|
170
|
+
success: false,
|
|
171
|
+
description: `You want to ${effectorName} but there is no one specific to reach out to.`,
|
|
172
|
+
commands,
|
|
173
|
+
feedback: {
|
|
174
|
+
outcomeQuality: 0,
|
|
175
|
+
surprise: 0.2,
|
|
176
|
+
lessons: [ 'Specify a targetEntityId to send a message.' ],
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if( bubbles.length === 0 ){
|
|
182
|
+
return {
|
|
183
|
+
success: false,
|
|
184
|
+
description: `You wanted to ${effectorName} ${targetEntityName} but didn't write anything.`,
|
|
185
|
+
commands,
|
|
186
|
+
feedback: { outcomeQuality: 0, surprise: 0.1, lessons: [ 'Provide a messages array with the actual words.' ] },
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Generate outbox message IDs first so we can embed them in conversation.sent
|
|
191
|
+
// and correlate deliveries back to this intent (TODO 11.3).
|
|
192
|
+
const originalMessage = ( request.parameters?.originalMessage as string ) ?? ''
|
|
193
|
+
const deliveryTick = ( request.parameters?.tick as number ) ?? 0
|
|
194
|
+
const replyToMessageId = ( request.parameters?.replyToMessageId as string ) ?? undefined
|
|
195
|
+
const isAck = ( request.parameters?.isAck as boolean ) ?? false
|
|
196
|
+
|
|
197
|
+
const outboxMessageIds: string[] = []
|
|
198
|
+
bubbles.forEach( ( bubble, i ) => {
|
|
199
|
+
logger.info(`[communication] pushing to outbox: ${effectorName} → ${targetEntityId} "${bubble.slice( 0, 80 )}"`)
|
|
200
|
+
outboxMessageIds.push( this._writer.enqueue({
|
|
201
|
+
targetEntityId,
|
|
202
|
+
targetEntityName,
|
|
203
|
+
content: bubble,
|
|
204
|
+
effectorName,
|
|
205
|
+
replyToMessageId,
|
|
206
|
+
}, `-${ i }` ) )
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
// Write the intent record at push time so context-builder can see what we said.
|
|
210
|
+
// NOTE (11.3): this entity tracks intent, not confirmation. confirmMessageDelivery()
|
|
211
|
+
// will update it with delivered:true once the client ACKs.
|
|
212
|
+
const sentEntityId = `conv-sent-${targetEntityId}-${deliveryTick}`
|
|
213
|
+
|
|
214
|
+
commands.set ??= []
|
|
215
|
+
commands.set.push({
|
|
216
|
+
id: sentEntityId,
|
|
217
|
+
type: 'conversation.sent',
|
|
218
|
+
createdAt: wallClock(),
|
|
219
|
+
metadata: {
|
|
220
|
+
targetEntityId,
|
|
221
|
+
targetEntityName,
|
|
222
|
+
messageCount: bubbles.length,
|
|
223
|
+
preview: bubbles[0]?.slice( 0, 100 ) ?? '',
|
|
224
|
+
effectorName,
|
|
225
|
+
tick: deliveryTick,
|
|
226
|
+
delivered: false,
|
|
227
|
+
isAck,
|
|
228
|
+
outboxMessageIds, // enables confirmMessageDelivery to update this entity
|
|
229
|
+
},
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
// Log the outbound message for session auditing (D4)
|
|
233
|
+
this._sessionLogger?.write({
|
|
234
|
+
type: 'conversation.out',
|
|
235
|
+
tick: deliveryTick,
|
|
236
|
+
targetEntityId,
|
|
237
|
+
targetEntityName,
|
|
238
|
+
messageCount: bubbles.length,
|
|
239
|
+
messages: bubbles.map( b => b.slice( 0, 300 ) ),
|
|
240
|
+
preview: bubbles[0]?.slice( 0, 100 ) ?? '',
|
|
241
|
+
isAck,
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
const fullReply = bubbles.join(' ')
|
|
245
|
+
|
|
246
|
+
// Persist every outbound as a conversation.exchange WM item so it consolidates
|
|
247
|
+
// into episodic + vector memory — the same shape the AuditionEngine uses for
|
|
248
|
+
// facet replies (built by the shared buildConversationExchange). UNCONDITIONAL
|
|
249
|
+
// (option a): master-initiated outreach (no inbound `originalMessage`) must also
|
|
250
|
+
// be remembered, so a facet later spawned to continue recalls what was said.
|
|
251
|
+
commands.set ??= []
|
|
252
|
+
commands.set.push( buildConversationExchange({
|
|
253
|
+
entityId: targetEntityId,
|
|
254
|
+
entityName: targetEntityName,
|
|
255
|
+
userMessage: originalMessage,
|
|
256
|
+
willReply: fullReply,
|
|
257
|
+
tick: ( request.parameters?.tick as number ) ?? 0,
|
|
258
|
+
idSeed: wallClock(),
|
|
259
|
+
createdAt: wallClock(),
|
|
260
|
+
}) )
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
success: true,
|
|
264
|
+
description: `You reach out to ${targetEntityName}: "${fullReply.slice( 0, 80 )}${fullReply.length > 80 ? '…' : ''}"`,
|
|
265
|
+
commands,
|
|
266
|
+
feedback: {
|
|
267
|
+
outcomeQuality: 0.85,
|
|
268
|
+
surprise: 0.15,
|
|
269
|
+
lessons: [ `Your message is queued for delivery to ${targetEntityName}.` ],
|
|
270
|
+
},
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/agency/reconcile.learning.ts — host-ack reconciliation
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// Closes the async loop for `external` / `communicate` enactions. When the
|
|
6
|
+
// MotorSchemaExecutor dispatches a host-owned effector it leaves the intent
|
|
7
|
+
// 'awaiting' and emits `agency.invocation`. The host later executes it and calls
|
|
8
|
+
// back; `reconcileInvocation` turns that callback into the `agency.outcome` the
|
|
9
|
+
// ReafferenceEngine already consumes — which both teaches the skill the real
|
|
10
|
+
// result AND frees the serial Will (reafference deletes the awaiting intent via
|
|
11
|
+
// the outcome's `intentId`).
|
|
12
|
+
//
|
|
13
|
+
// This is the agency-native equivalent of the legacy effectorController.
|
|
14
|
+
// confirmExecution — same efference-copy / reafference contract, new vocabulary.
|
|
15
|
+
// The stem wires its host ack endpoint to call this and write the returned entity.
|
|
16
|
+
// ─────────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
import type { EntityInput, Tick } from '#core/types'
|
|
19
|
+
|
|
20
|
+
export interface HostAckResult {
|
|
21
|
+
success: boolean
|
|
22
|
+
/** 0..1 — how good the world's reply was. Defaults from `success` when omitted. */
|
|
23
|
+
outcomeQuality?: number
|
|
24
|
+
/** −1..1 felt valence of the outcome. */
|
|
25
|
+
valence?: number
|
|
26
|
+
description?: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Build the `agency.outcome` entity that confirms an awaiting invocation. The
|
|
31
|
+
* caller (stem host-ack endpoint) writes it via `stateManager.setEntity`; the
|
|
32
|
+
* ReafferenceEngine consumes it next tick — learning from it and deleting the
|
|
33
|
+
* awaiting intent identified by `intentId`.
|
|
34
|
+
*
|
|
35
|
+
* `schema` is the awaiting intent's schema (the host has it from the
|
|
36
|
+
* `agency.invocation` payload); `predictedReward`/`predictedValence` are the
|
|
37
|
+
* efference copy the executor persisted on the intent, so surprise is honest.
|
|
38
|
+
*
|
|
39
|
+
* `provenance` carries the awaiting intent's plan link (planId/stepId) when it was
|
|
40
|
+
* committed from a plan's frontier prior. It rides on the agency.outcome so the
|
|
41
|
+
* ReafferenceEngine — the engine that consumes async-acked outcomes — can emit the
|
|
42
|
+
* `action.outcome{planId,stepId}` the PlanningEngine advances on. (The executor
|
|
43
|
+
* emits that itself for sync/timeout outcomes; the host-ack path has no executor in
|
|
44
|
+
* the loop, so reafference is the single emitter for it — see ReafferenceEngine.)
|
|
45
|
+
*/
|
|
46
|
+
export function reconcileInvocation(
|
|
47
|
+
intentId: string,
|
|
48
|
+
schema: string,
|
|
49
|
+
result: HostAckResult,
|
|
50
|
+
tick: Tick,
|
|
51
|
+
predicted: { reward: number; valence: number } = { reward: 0.5, valence: 0 },
|
|
52
|
+
provenance: { planId?: string; stepId?: string } = {},
|
|
53
|
+
): EntityInput {
|
|
54
|
+
const outcomeQuality = result.outcomeQuality ?? ( result.success ? 0.8 : 0.1 )
|
|
55
|
+
const valence = result.valence ?? ( result.success ? 0.2 : -0.2 )
|
|
56
|
+
const surprise = clamp01( Math.abs( predicted.reward - outcomeQuality ) )
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
id: `agency-outcome-${ tick }-${ intentId }`,
|
|
60
|
+
type: 'agency.outcome',
|
|
61
|
+
metadata: {
|
|
62
|
+
schema,
|
|
63
|
+
intentId,
|
|
64
|
+
success: result.success,
|
|
65
|
+
outcomeQuality,
|
|
66
|
+
valence,
|
|
67
|
+
predictedReward: predicted.reward,
|
|
68
|
+
predictedValence: predicted.valence,
|
|
69
|
+
surprise,
|
|
70
|
+
description: result.description ?? ( result.success ? 'The world confirmed the action.' : 'The world rejected the action.' ),
|
|
71
|
+
mode: 'external',
|
|
72
|
+
tick,
|
|
73
|
+
reconciled: true,
|
|
74
|
+
...( provenance.planId ? { planId: provenance.planId } : {} ),
|
|
75
|
+
...( provenance.stepId ? { stepId: provenance.stepId } : {} ),
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function clamp01( n: number ): number {
|
|
81
|
+
return n < 0 ? 0 : n > 1 ? 1 : n
|
|
82
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/agency/schemas/external.ts — host-owned domain effectors
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// A host (game engine, app, robot) declares the domain effectors its world
|
|
6
|
+
// supports — `move`, `attack`, `trade`, `give`, `use`, … — via a profile's
|
|
7
|
+
// `effectors` list or the Will's `allowedGenericEffectors`. This turns those
|
|
8
|
+
// declarations into enactable MotorSchemas so they enter the agency loop like
|
|
9
|
+
// anything else: the AffordanceSynthesizer surfaces them in the field, the
|
|
10
|
+
// ActionSelector competes them, and the MotorSchemaExecutor routes the chosen
|
|
11
|
+
// one to the host via the `external` enaction mode (emitted now, acked later,
|
|
12
|
+
// the result returning as reafference the Will learns from).
|
|
13
|
+
//
|
|
14
|
+
// Excluded: the communication surface (listen/talk/text/gesture/broadcast),
|
|
15
|
+
// which is governed by AccessGrants + the ProactiveCommunicator; and any name
|
|
16
|
+
// that shadows an innate stance (the innate floor already provides it).
|
|
17
|
+
//
|
|
18
|
+
// Scope (Phase 1): objectless schemas — the Will chooses the act and the host
|
|
19
|
+
// resolves the target. Entity-bound external effectors (e.g. attack a specific
|
|
20
|
+
// perceived entity) are a follow-up; the synthesizer currently binds a single
|
|
21
|
+
// entity schema. See CUSTOM_EFFECTOR_WIRING_TODO.md.
|
|
22
|
+
// ─────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
import type { MotorSchema } from '#agency/types'
|
|
25
|
+
import { EXPLICIT_EFFECTORS } from '#agency/access.grants'
|
|
26
|
+
import { INNATE_SCHEMA_BY_ID } from '#agency/schemas/innate'
|
|
27
|
+
|
|
28
|
+
/** Default effort/energy demand for a host action when none is specified. */
|
|
29
|
+
const DEFAULT_EXTERNAL_COST = 0.15
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Build enactable MotorSchemas for a host's declared domain effectors. Comms
|
|
33
|
+
* names and innate-shadowing names are filtered out; the rest become objectless,
|
|
34
|
+
* `external`-tagged primitives that route to the host on enaction.
|
|
35
|
+
*/
|
|
36
|
+
export function externalSchemas( effectors?: string[] | null ): MotorSchema[] {
|
|
37
|
+
const seen = new Set<string>()
|
|
38
|
+
const out: MotorSchema[] = []
|
|
39
|
+
|
|
40
|
+
for( const name of effectors ?? [] ){
|
|
41
|
+
if( typeof name !== 'string' || name.length === 0 ) continue
|
|
42
|
+
if( EXPLICIT_EFFECTORS.has( name ) ) continue // communication — handled by AccessGrants
|
|
43
|
+
if( INNATE_SCHEMA_BY_ID.has( name ) ) continue // shadows an innate stance
|
|
44
|
+
if( seen.has( name ) ) continue
|
|
45
|
+
seen.add( name )
|
|
46
|
+
|
|
47
|
+
out.push({
|
|
48
|
+
id: name,
|
|
49
|
+
kind: 'primitive',
|
|
50
|
+
source: 'external',
|
|
51
|
+
cost: DEFAULT_EXTERNAL_COST,
|
|
52
|
+
binds: 'none',
|
|
53
|
+
baseValence: 0,
|
|
54
|
+
tags: [ 'external', 'host' ],
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return out
|
|
59
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/agency/schemas/innate.ts — the always-on floor of the field
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// Innate schemas are the reflexive floor of agency — the possibilities a mind
|
|
6
|
+
// always has available simply by being an embodied perceiver, before it has
|
|
7
|
+
// learned anything. Most need no object (orient, rest, reflect); two bind to
|
|
8
|
+
// what perception surfaces (`inspect` a percept, `reach-out` to a known mind).
|
|
9
|
+
//
|
|
10
|
+
// This is NOT a catalog the executive picks from. It is the seed set the
|
|
11
|
+
// AffordanceSynthesizer draws on so the field is never empty; learned composite
|
|
12
|
+
// schemas (Phase 3) are layered on top via the repertoire.
|
|
13
|
+
// ─────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
import type { MotorSchema } from '#agency/types'
|
|
16
|
+
|
|
17
|
+
export const INNATE_SCHEMAS: MotorSchema[] = [
|
|
18
|
+
// ── objectless stances ───────────────────────────────────────
|
|
19
|
+
{
|
|
20
|
+
id: 'orient',
|
|
21
|
+
kind: 'primitive',
|
|
22
|
+
source: 'innate',
|
|
23
|
+
binds: 'none',
|
|
24
|
+
cost: 0.05,
|
|
25
|
+
baseValence: 0.0,
|
|
26
|
+
tags: [ 'perception', 'reflexive' ],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'attend',
|
|
30
|
+
kind: 'primitive',
|
|
31
|
+
source: 'innate',
|
|
32
|
+
binds: 'none',
|
|
33
|
+
cost: 0.08,
|
|
34
|
+
preconditions: [ { metric: 'energy.level', op: 'gt', value: 10 } ],
|
|
35
|
+
baseValence: 0.0,
|
|
36
|
+
tags: [ 'attention', 'meta-cognition' ],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'rest',
|
|
40
|
+
kind: 'primitive',
|
|
41
|
+
source: 'innate',
|
|
42
|
+
binds: 'none',
|
|
43
|
+
cost: 0.0,
|
|
44
|
+
preconditions: [ { metric: 'energy.level', op: 'lt', value: 95 } ],
|
|
45
|
+
baseValence: 0.15,
|
|
46
|
+
tags: [ 'self-care', 'regulatory' ],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'withdraw',
|
|
50
|
+
kind: 'primitive',
|
|
51
|
+
source: 'innate',
|
|
52
|
+
binds: 'none',
|
|
53
|
+
cost: 0.03,
|
|
54
|
+
baseValence: 0.05,
|
|
55
|
+
tags: [ 'self-protection', 'regulatory' ],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'reflect',
|
|
59
|
+
kind: 'primitive',
|
|
60
|
+
source: 'innate',
|
|
61
|
+
binds: 'none',
|
|
62
|
+
cost: 0.06,
|
|
63
|
+
preconditions: [ { metric: 'energy.level', op: 'gt', value: 10 } ],
|
|
64
|
+
baseValence: 0.05,
|
|
65
|
+
tags: [ 'cognitive', 'meta-cognition', 'internal' ],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 'wait',
|
|
69
|
+
kind: 'primitive',
|
|
70
|
+
source: 'innate',
|
|
71
|
+
binds: 'none',
|
|
72
|
+
cost: 0.01,
|
|
73
|
+
baseValence: 0.0,
|
|
74
|
+
tags: [ 'neutral' ],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 'express',
|
|
78
|
+
kind: 'primitive',
|
|
79
|
+
source: 'innate',
|
|
80
|
+
binds: 'none',
|
|
81
|
+
cost: 0.02,
|
|
82
|
+
baseValence: 0.1,
|
|
83
|
+
tags: [ 'affective', 'expression' ],
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// ── perception-bound possibilities ───────────────────────────
|
|
87
|
+
{
|
|
88
|
+
id: 'inspect',
|
|
89
|
+
kind: 'primitive',
|
|
90
|
+
source: 'perceptual',
|
|
91
|
+
binds: 'percept',
|
|
92
|
+
cost: 0.06,
|
|
93
|
+
preconditions: [ { metric: 'energy.level', op: 'gt', value: 8 } ],
|
|
94
|
+
baseValence: 0.05,
|
|
95
|
+
tags: [ 'perception', 'information' ],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 'reach-out',
|
|
99
|
+
kind: 'primitive',
|
|
100
|
+
source: 'social',
|
|
101
|
+
binds: 'entity',
|
|
102
|
+
cost: 0.1,
|
|
103
|
+
preconditions: [ { metric: 'energy.level', op: 'gt', value: 5 } ],
|
|
104
|
+
baseValence: 0.2,
|
|
105
|
+
tags: [ 'social', 'communication' ],
|
|
106
|
+
},
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
/** Fast id → schema lookup over the innate floor. */
|
|
110
|
+
export const INNATE_SCHEMA_BY_ID: ReadonlyMap<string, MotorSchema> =
|
|
111
|
+
new Map( INNATE_SCHEMAS.map( s => [ s.id, s ] ) )
|