@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,339 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/extensions/time.ext.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+
5
+ /**
6
+ * Time extension for logistics, mobility, IoT, and smart home scenarios.
7
+ * These are NOT part of core — they layer on top.
8
+ */
9
+
10
+ import type { SimulationClock } from '#core/clock'
11
+ import type { Timestamp } from '#core/types'
12
+
13
+ // ── Time-of-day utilities ─────────────────────────────────
14
+
15
+ export interface TimeOfDay {
16
+ hour: number
17
+ minute: number
18
+ second: number
19
+ millisecond: number
20
+ }
21
+
22
+ export interface DateComponents {
23
+ year: number
24
+ month: number
25
+ day: number
26
+ hour: number
27
+ minute: number
28
+ second: number
29
+ millisecond: number
30
+ dayOfWeek: number // 0 = Sunday, 6 = Saturday
31
+ timestamp: Timestamp
32
+ }
33
+
34
+ export interface TimeWindow {
35
+ startHour: number // 0-23
36
+ endHour: number // 0-23, can wrap (e.g., 22-6 for overnight)
37
+ startMinute?: number // 0-59
38
+ endMinute?: number // 0-59
39
+ }
40
+
41
+ export class TimeExtension {
42
+ private _clock: SimulationClock
43
+ private _timezoneOffset: number // minutes from UTC, e.g., -480 for PST
44
+ // private _referenceDate: Date
45
+
46
+ constructor( clock: SimulationClock, timezoneOffsetMinutes: number = 0 ){
47
+ this._clock = clock
48
+ this._timezoneOffset = timezoneOffsetMinutes
49
+ // this._referenceDate = new Date( this._clock.now )
50
+ }
51
+
52
+ // ── Time-of-day (no date) ───────────────────────────────
53
+
54
+ getTimeOfDay(): TimeOfDay {
55
+ const date = this._getDateWithOffset()
56
+
57
+ return {
58
+ hour: date.getHours(),
59
+ minute: date.getMinutes(),
60
+ second: date.getSeconds(),
61
+ millisecond: date.getMilliseconds()
62
+ }
63
+ }
64
+
65
+ getHour(): number {
66
+ return this._getDateWithOffset().getHours()
67
+ }
68
+
69
+ getMinute(): number {
70
+ return this._getDateWithOffset().getMinutes()
71
+ }
72
+
73
+ isBetweenHours( startHour: number, endHour: number ): boolean {
74
+ const hour = this.getHour()
75
+
76
+ // Handle overnight windows (e.g., 22-6)
77
+ if( startHour > endHour )
78
+ return hour >= startHour || hour <= endHour
79
+
80
+ return hour >= startHour && hour <= endHour
81
+ }
82
+
83
+ isWithinTimeWindow( window: TimeWindow ): boolean {
84
+ const
85
+ hour = this.getHour(),
86
+ minute = this.getMinute(),
87
+
88
+ currentMinutes = hour * 60 + minute,
89
+ startMinutes = ( window.startHour * 60 ) + ( window.startMinute ?? 0 ),
90
+ endMinutes = ( window.endHour * 60 ) + ( window.endMinute ?? 0 )
91
+
92
+ // Handle overnight windows
93
+ if( startMinutes > endMinutes )
94
+ return currentMinutes >= startMinutes || currentMinutes <= endMinutes
95
+
96
+ return currentMinutes >= startMinutes && currentMinutes <= endMinutes
97
+ }
98
+
99
+ // ── Full date/time (for scheduling) ─────────────────────
100
+
101
+ getCurrentDateComponents(): DateComponents {
102
+ const date = this._getDateWithOffset()
103
+
104
+ return {
105
+ year: date.getFullYear(),
106
+ month: date.getMonth(),
107
+ day: date.getDate(),
108
+ hour: date.getHours(),
109
+ minute: date.getMinutes(),
110
+ second: date.getSeconds(),
111
+ millisecond: date.getMilliseconds(),
112
+ dayOfWeek: date.getDay(),
113
+ timestamp: this._clock.now
114
+ }
115
+ }
116
+
117
+ // ── Business hours / shift detection ────────────────────
118
+
119
+ isBusinessHours(
120
+ businessStartHour: number = 9,
121
+ businessEndHour: number = 17,
122
+ includeWeekends: boolean = false
123
+ ): boolean {
124
+ const
125
+ components = this.getCurrentDateComponents(),
126
+ isWeekend = components.dayOfWeek === 0 || components.dayOfWeek === 6
127
+
128
+ if( !includeWeekends && isWeekend ) return false
129
+
130
+ return this.isBetweenHours( businessStartHour, businessEndHour )
131
+ }
132
+
133
+ isRushHour( cityType: 'urban' | 'suburban' | 'rural' = 'urban'): boolean {
134
+ const hour = this.getHour()
135
+
136
+ switch( cityType ) {
137
+ case 'urban':
138
+ // Morning: 7-9, Evening: 16-19
139
+ return ( hour >= 7 && hour <= 9 ) || ( hour >= 16 && hour <= 19 )
140
+
141
+ case 'suburban':
142
+ // Morning: 6-8, Evening: 17-19
143
+ return ( hour >= 6 && hour <= 8 ) || ( hour >= 17 && hour <= 19 )
144
+
145
+ case 'rural':
146
+ // Minimal rush hour
147
+ return ( hour >= 7 && hour <= 8 ) || ( hour >= 17 && hour <= 18 )
148
+
149
+ default: return false
150
+ }
151
+ }
152
+
153
+ // ── Day part detection (for smart home) ─────────────────
154
+
155
+ getDayPart(): 'dawn' | 'morning' | 'afternoon' | 'evening' | 'night' | 'late-night' {
156
+ const hour = this.getHour()
157
+
158
+ if( hour >= 5 && hour < 7 ) return 'dawn'
159
+ if( hour >= 7 && hour < 12 ) return 'morning'
160
+ if( hour >= 12 && hour < 17 ) return 'afternoon'
161
+ if( hour >= 17 && hour < 21 ) return 'evening'
162
+ if( hour >= 21 && hour < 24 ) return 'night'
163
+ return 'late-night'
164
+ }
165
+
166
+ // ── ETA with time-of-day adjustment (logistics) ─────────
167
+
168
+ calculateAdjustedEta(
169
+ baseMinutes: number,
170
+ trafficMultiplier: number = 1.0
171
+ ): number {
172
+ let multiplier = trafficMultiplier
173
+
174
+ // Apply rush hour penalty
175
+ if( this.isRushHour() ) multiplier *= 1.5
176
+
177
+ // Apply night time bonus (less traffic)
178
+ const hour = this.getHour()
179
+ if( hour >= 22 || hour <= 5 ) multiplier *= 0.8
180
+
181
+ return baseMinutes * multiplier
182
+ }
183
+
184
+ // ── Scheduling helpers ──────────────────────────────────
185
+
186
+ getMinutesUntil( targetHour: number, targetMinute: number = 0 ): number {
187
+ const
188
+ current = this.getTimeOfDay(),
189
+ currentMinutes = current.hour * 60 + current.minute,
190
+ targetMinutes = targetHour * 60 + targetMinute
191
+
192
+ if( targetMinutes > currentMinutes )
193
+ return targetMinutes - currentMinutes
194
+
195
+ // Target is tomorrow
196
+ return ( 24 * 60 - currentMinutes ) + targetMinutes
197
+ }
198
+
199
+ getNextOccurrence(
200
+ targetHour: number,
201
+ targetMinute: number = 0,
202
+ onlyFuture: boolean = true
203
+ ): { minutesFromNow: number; timestamp: Timestamp } {
204
+ const
205
+ current = this.getTimeOfDay(),
206
+ currentMinutes = current.hour * 60 + current.minute,
207
+ targetMinutes = targetHour * 60 + targetMinute,
208
+ msPerMinute = 60 * 1000
209
+
210
+ let minutesDelta: number
211
+ if( targetMinutes > currentMinutes )
212
+ minutesDelta = targetMinutes - currentMinutes
213
+
214
+ else if( onlyFuture )
215
+ minutesDelta = ( 24 * 60 - currentMinutes ) + targetMinutes
216
+
217
+ else minutesDelta = targetMinutes - currentMinutes
218
+
219
+ const wallDeltaMs = this._clock.toWallMs( minutesDelta * 60 * 1000 )
220
+
221
+ return {
222
+ minutesFromNow: minutesDelta,
223
+ timestamp: Date.now() + wallDeltaMs
224
+ }
225
+ }
226
+
227
+ // ── Private helpers ─────────────────────────────────────
228
+
229
+ private _getDateWithOffset(): Date {
230
+ const
231
+ simTime = this._clock.now,
232
+ offsetMs = this._timezoneOffset * 60 * 1000
233
+
234
+ return new Date( simTime + offsetMs )
235
+ }
236
+
237
+ // ── Convenience factory ─────────────────────────────────
238
+
239
+ static forTimezone( clock: SimulationClock, timezone: string ): TimeExtension {
240
+ // NOTE: Full IANA timezone support requires a library like 'luxon'
241
+ // For now, uses local system timezone
242
+ const offsetMinutes = -new Date().getTimezoneOffset()
243
+ // In production, use Intl.DateTimeFormat or a library like 'luxon' for IANA conversion
244
+ return new TimeExtension( clock, offsetMinutes )
245
+ }
246
+ }
247
+
248
+ // ── Scenario helpers for time-based tests ─────────────────
249
+
250
+ export interface TimeScenarioConfig {
251
+ startHour?: number
252
+ startMinute?: number
253
+ timeMultiplier?: number
254
+ timezone?: string
255
+ }
256
+
257
+ export class TimeScenarioHelper {
258
+ private _clock: SimulationClock
259
+ private _extension: TimeExtension
260
+
261
+ constructor( clock: SimulationClock, config: TimeScenarioConfig = {} ){
262
+ this._clock = clock
263
+
264
+ // Set initial time if specified
265
+ if( config.startHour !== undefined ) {
266
+ const startDate = new Date( this._clock.now )
267
+
268
+ startDate.setHours( config.startHour, config.startMinute ?? 0, 0, 0 )
269
+ this._clock.setTime( startDate.getTime() )
270
+ }
271
+
272
+ if( config.timeMultiplier )
273
+ this._clock.setMultiplier( config.timeMultiplier )
274
+
275
+ this._extension = config.timezone
276
+ ? TimeExtension.forTimezone( this._clock, config.timezone )
277
+ : new TimeExtension( this._clock, -new Date().getTimezoneOffset() )
278
+ }
279
+
280
+ get clock(): SimulationClock { return this._clock }
281
+ get time(): TimeExtension { return this._extension }
282
+
283
+ // Fast-forward simulation to a specific time of day
284
+ async advanceToTimeOfDay(
285
+ targetHour: number,
286
+ targetMinute: number = 0,
287
+ maxWaitMs: number = 30000 // 30 seconds real-time max
288
+ ): Promise<void> {
289
+ const
290
+ { minutesFromNow } = this._extension.getNextOccurrence( targetHour, targetMinute ),
291
+ waitWallMs = this._clock.toWallMs( minutesFromNow * 60 * 1000 )
292
+
293
+ if( waitWallMs > maxWaitMs )
294
+ throw new Error(`Target time would require waiting ${waitWallMs}ms, exceeds max ${maxWaitMs}ms`)
295
+
296
+ await this._clock.simSleep( minutesFromNow * 60 * 1000 )
297
+ }
298
+ }
299
+
300
+ // Usage Examples
301
+ // Logistics: Time-of-day for delivery windows
302
+ // typescript
303
+ // import { DefaultSimulationClock } from './core/clock'
304
+ // import { TimeExtension } from './extension/time.ext'
305
+
306
+ // const clock = new DefaultSimulationClock({ timeScale: 60 }) // 1 real sec = 1 sim minute
307
+ // clock.startTicks()
308
+
309
+ // const timeExt = new TimeExtension( clock, -480 ) // PST
310
+
311
+ // // Check if within delivery window
312
+ // const isWithinWindow = timeExt.isWithinTimeWindow({
313
+ // startHour: 9,
314
+ // endHour: 17,
315
+ // startMinute: 0,
316
+ // endMinute: 0
317
+ // })
318
+
319
+ // // Adjust ETA for rush hour
320
+ // const baseEta = 30 // minutes
321
+ // const adjustedEta = timeExt.calculateAdjustedEta( baseEta, 1.2 )
322
+ // Smart Home: Day part detection
323
+ // typescript
324
+ // const dayPart = timeExt.getDayPart()
325
+
326
+ // switch( dayPart ) {
327
+ // case 'dawn':
328
+ // // Gradually increase lights
329
+ // break
330
+ // case 'night':
331
+ // // Arm security system, turn off non-essential devices
332
+ // break
333
+ // }
334
+ // Mobility: Rush hour detection
335
+ // typescript
336
+ // if( timeExt.isRushHour('urban') ) {
337
+ // // Reroute to avoid congested areas
338
+ // // Increase surge pricing
339
+ // }
package/src/index.ts ADDED
@@ -0,0 +1,91 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/index.ts — Will public API
3
+ // ─────────────────────────────────────────────────────────────
4
+
5
+ // Core simulation primitives (includes StorageAdapter, BunStorageAdapter, etc.)
6
+ export * from '#core/index'
7
+
8
+ // All cognitive engines
9
+ export * from '#cognition/index'
10
+
11
+ // Public types (OutboxMessage, effectorInvocation, ActionRequest, ActionResult, etc.)
12
+ export * from '#types'
13
+
14
+ // Deployment layer — WillStem, WillConfig, WillSummary, CognitiveHealth, TickListener …
15
+ export {
16
+ WillStem,
17
+ type WillInstance,
18
+ type WillSummary,
19
+ type CognitiveHealth,
20
+ type WillStatus,
21
+ type TickListener,
22
+ type SimulationEventListener,
23
+ type StateSnapshot,
24
+ OUTBOX_TTL_TICKS,
25
+ } from '#stem/index'
26
+
27
+ export { assembleMind, type WillConfig } from '#stem/mind'
28
+
29
+ // External transport — the unified bidirectional envelope channel between a Will
30
+ // and its host peer (backend). Exposes the transport interface, every envelope
31
+ // type, and the three implementations:
32
+ // • SocketIoTransport — production (Will = client, backend hosts the server)
33
+ // • StreamTransport — live in-process consumer (per-channel demux via on())
34
+ // • LoopbackTransport — deterministic in-memory transport for tests/replay
35
+ export * from '#stem/tracts/transport/index'
36
+
37
+ // Vector memory — semantic episodic recall. Exposes the adapter, the VectorIndex
38
+ // interface, and the embedders so a host can inject a custom backend (e.g.
39
+ // pgvector) via WillConfig.vectorMemoryAdapter. (EmbeddingProvider / VectorRecord
40
+ // / VectorQueryResult / VectorQueryFilter are already exported via #cognition.)
41
+ export {
42
+ DefaultVectorMemoryAdapter,
43
+ type VectorMemoryAdapter,
44
+ type VectorIndex,
45
+ OpenAICompatibleEmbedder,
46
+ MockEmbedder,
47
+ type EmbeddingProvider,
48
+ type VectorRecord,
49
+ type VectorQueryResult,
50
+ type VectorQueryFilter,
51
+ type VectorMemoryConfig,
52
+ } from '#cognition/memory/index'
53
+
54
+ // Profile registry — built-in profiles are auto-registered when this package is imported
55
+ // (mind.ts imports '#profiles/built-in' as a side effect).
56
+ export { resolveProfile, listProfiles, type WorldProfile } from '#profiles/index'
57
+
58
+ // PMA (Personal Mind Archive) snapshot types
59
+ export type {
60
+ PMASnapshot,
61
+ PMAIdentity,
62
+ PMABelief,
63
+ PMAGoal,
64
+ PMAEmotionalBaseline,
65
+ PMABehavioral,
66
+ } from '#pma/index'
67
+
68
+ // PMA eval harness — behavioral fidelity scoring
69
+ export { PMAEvalHarness } from '#pma/eval'
70
+ export type {
71
+ ReconstructionFidelityReport,
72
+ ReconstructionFidelityScores,
73
+ BehavioralProbeResult,
74
+ PMAProbe,
75
+ } from '#pma/eval'
76
+
77
+ // Sensory input types — used by callers of WillManager.ingestText()
78
+ export type { TextMessage, VoiceChunk, SensoryInput } from '#senses/index'
79
+
80
+ // ── SDK facade — the ergonomic embedding API (recommended entry point) ──
81
+ // `Will.create()` wraps WillStem in the shape a developer expects: on('message'),
82
+ // effector(name, handler), say(), state(), hibernate()/wake(). Drop to `.stem`
83
+ // for the full contract. See src/sdk/will.ts + examples/effectors.ts.
84
+ export { Will } from '#sdk/will'
85
+ export type {
86
+ CreateWillOptions,
87
+ WillMessage,
88
+ WillStateSummary,
89
+ EffectorHandler,
90
+ EffectorResult,
91
+ } from '#sdk/will'
@@ -0,0 +1,140 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/llm/gate.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+
5
+ /**
6
+ * Global concurrency gate for all LLM calls.
7
+ *
8
+ * Two protections:
9
+ * 1. Semaphore — caps simultaneous in-flight requests so independent
10
+ * engines (decision, semantic, planning…) can run in parallel up to
11
+ * the concurrency limit without flooding the API.
12
+ * 2. Retry with exponential backoff — on 429 the call waits and retries.
13
+ *
14
+ * No minimum interval is enforced. A fixed inter-call floor causes
15
+ * starvation: every engine serialises into a single queue and slower
16
+ * engines (semantic integrator) never get a timely slot because faster
17
+ * engines (decision) keep resetting the clock. The retry mechanism is
18
+ * the right tool for actual rate-limit overages.
19
+ *
20
+ * Configured via env vars:
21
+ * WILL_LLM_CONCURRENCY max simultaneous LLM calls (default 2)
22
+ * WILL_LLM_MAX_RETRIES retries before giving up on a 429 (default 4)
23
+ * WILL_LLM_RETRY_BASE_MS first retry wait, doubles each attempt (default 2000)
24
+ */
25
+
26
+ import { logger } from '#core/logger'
27
+
28
+ const MAX_CONCURRENT = parseInt( process.env.WILL_LLM_CONCURRENCY ?? '2')
29
+
30
+ // Read lazily (per retry, not per module load) so tests and live tuning can
31
+ // adjust the backoff without re-importing the module. Jitter scales with the
32
+ // base delay (base/2 ⇒ up to 1000 ms at the 2000 ms default — unchanged).
33
+ const maxRetries = () => parseInt( process.env.WILL_LLM_MAX_RETRIES ?? '4')
34
+ const baseDelayMs = () => parseInt( process.env.WILL_LLM_RETRY_BASE_MS ?? '2000')
35
+
36
+ // ── Semaphore ─────────────────────────────────────────────────
37
+
38
+ export class LLMSemaphore {
39
+ private _running = 0
40
+ private readonly _max: number
41
+ private _queue: Array<() => void> = []
42
+
43
+ constructor( max: number ){ this._max = max }
44
+
45
+ async acquire(): Promise<() => void> {
46
+ if( this._running < this._max ){
47
+ this._running++
48
+ return this._release()
49
+ }
50
+
51
+ // No free slot — wait until one is handed off directly to us. The releasing
52
+ // call transfers its slot without decrementing _running, so we must NOT
53
+ // increment here: we already own the slot the moment we resume.
54
+ await new Promise<void>( resolve => this._queue.push( resolve ) )
55
+ return this._release()
56
+ }
57
+
58
+ private _release(): () => void {
59
+ let done = false
60
+ return () => {
61
+ if( done ) return
62
+ done = true
63
+
64
+ // Hand the slot directly to the next waiter, keeping _running unchanged so
65
+ // a concurrent acquire() can't slip into a transient gap and over-admit
66
+ // past _max. Only decrement when nobody is waiting.
67
+ const next = this._queue.shift()
68
+ if( next ) next()
69
+ else this._running--
70
+ }
71
+ }
72
+
73
+ get running(): number { return this._running }
74
+ get queued(): number { return this._queue.length }
75
+ }
76
+
77
+ export const llmGate = new LLMSemaphore( MAX_CONCURRENT )
78
+
79
+ // ── Rate-limit detection ──────────────────────────────────────
80
+
81
+ export function isRateLimitError( err: unknown ): boolean {
82
+ if( !( err instanceof Error ) ) return false
83
+ const msg = err.message
84
+
85
+ return (
86
+ msg.includes('rate_limit_error') ||
87
+ ( err as { statusCode?: number } ).statusCode === 429 ||
88
+ msg.includes('rate limit') ||
89
+ msg.includes('429')
90
+ )
91
+ }
92
+
93
+ // ── Gate + retry wrapper ──────────────────────────────────────
94
+
95
+ /**
96
+ * Run `fn` through the global semaphore with automatic 429 retry.
97
+ *
98
+ * - Waits for a slot before calling `fn`
99
+ * - On 429: releases the slot, waits (exponential backoff + jitter), retries
100
+ * - Throws after MAX_RETRIES exhausted, or for non-retryable errors
101
+ */
102
+ export async function withGate<T>(
103
+ fn: () => Promise<T>,
104
+ label: string,
105
+ gate: LLMSemaphore = llmGate
106
+ ): Promise<T> {
107
+ let attempt = 0
108
+
109
+ // eslint-disable-next-line no-constant-condition
110
+ while( true ){
111
+ const release = await gate.acquire()
112
+ let retryDelay: number | null = null
113
+
114
+ try {
115
+ const result = await fn()
116
+ return result
117
+ }
118
+ catch( err ){
119
+ if( isRateLimitError( err ) && attempt < maxRetries() ){
120
+ attempt++
121
+ const base = baseDelayMs()
122
+ retryDelay = Math.min(
123
+ 60_000,
124
+ base * Math.pow( 2, attempt ) + Math.random() * ( base / 2 )
125
+ )
126
+ }
127
+ else throw err
128
+ }
129
+ finally { release() }
130
+
131
+ // Slot released in `finally` above — the backoff wait happens OUTSIDE the
132
+ // slot-holding region, so a rate-limited call no longer starves the other
133
+ // engines of concurrency while it sleeps.
134
+ logger.warn(
135
+ `[LLMGate] ${label} rate limited — retry ${attempt}/${maxRetries()} in ${Math.round( retryDelay! )}ms` +
136
+ ` (running=${gate.running} queued=${gate.queued})`
137
+ )
138
+ await new Promise( r => setTimeout( r, retryDelay! ) )
139
+ }
140
+ }