@mindot/will 0.7.0 → 0.9.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 (88) hide show
  1. package/README.md +87 -22
  2. package/dist/channels/discord.d.ts +67 -6
  3. package/dist/channels/discord.js +112 -6
  4. package/dist/channels/discord.js.map +1 -1
  5. package/dist/channels/whatsapp.d.ts +1 -1
  6. package/dist/channels/whatsapp.js +4 -1
  7. package/dist/channels/whatsapp.js.map +1 -1
  8. package/dist/cli.js +13733 -11057
  9. package/dist/cli.js.map +1 -1
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.js +3729 -1199
  12. package/dist/index.js.map +1 -1
  13. package/dist/mcp/effectors.d.ts +1 -1
  14. package/dist/{will-DAW0l-lY.d.ts → will-DbDj_TEH.d.ts} +1214 -93
  15. package/package.json +1 -1
  16. package/src/channels/discord.ts +189 -11
  17. package/src/channels/types.ts +90 -0
  18. package/src/channels/whatsapp.ts +13 -4
  19. package/src/cli.ts +9 -4
  20. package/src/cognition/agency/consequence.ts +122 -1
  21. package/src/cognition/agency/conversation.aim.ts +260 -0
  22. package/src/cognition/agency/engines/action.selector.ts +85 -3
  23. package/src/cognition/agency/engines/affordance.synthesizer.ts +90 -1
  24. package/src/cognition/agency/engines/motor.schema.executor.ts +152 -10
  25. package/src/cognition/agency/engines/reafference.engine.ts +129 -2
  26. package/src/cognition/agency/proactive.communicator.ts +19 -3
  27. package/src/cognition/agency/reconcile.learning.ts +16 -2
  28. package/src/cognition/agency/restart.ts +66 -0
  29. package/src/cognition/agency/schemas/repertoire.ts +12 -5
  30. package/src/cognition/agency/selection.scoring.ts +33 -0
  31. package/src/cognition/agency/types.ts +35 -0
  32. package/src/cognition/cache/composition.ts +232 -0
  33. package/src/cognition/cache/deliberation.cache.ts +219 -0
  34. package/src/cognition/cache/fingerprint.ts +120 -0
  35. package/src/cognition/cache/types.ts +105 -0
  36. package/src/cognition/config.mirror.entities.ts +109 -1
  37. package/src/cognition/event.schemas.ts +22 -0
  38. package/src/cognition/faculties/autobiographical.narrator.ts +5 -10
  39. package/src/cognition/faculties/episodic.consolidator.ts +59 -3
  40. package/src/cognition/faculties/executive.engine/commands.ts +189 -14
  41. package/src/cognition/faculties/executive.engine/context.ts +67 -13
  42. package/src/cognition/faculties/executive.engine/deliberate.reasoning.ts +1 -1
  43. package/src/cognition/faculties/executive.engine/engine.ts +686 -187
  44. package/src/cognition/faculties/executive.engine/escalation.buffer.ts +162 -44
  45. package/src/cognition/faculties/executive.engine/facet.supervisor.ts +310 -65
  46. package/src/cognition/faculties/executive.engine/facet.ts +89 -26
  47. package/src/cognition/faculties/executive.engine/gating.ts +14 -14
  48. package/src/cognition/faculties/executive.engine/parser.ts +21 -1
  49. package/src/cognition/faculties/executive.engine/prompt.factory.ts +169 -20
  50. package/src/cognition/faculties/executive.engine/types.ts +69 -0
  51. package/src/cognition/faculties/goal.manager.ts +94 -14
  52. package/src/cognition/faculties/known.entity.tracker.ts +267 -28
  53. package/src/cognition/faculties/moral.evaluator.ts +8 -3
  54. package/src/cognition/faculties/persona.consolidator.ts +141 -0
  55. package/src/cognition/faculties/reputation.tracker.ts +66 -2
  56. package/src/cognition/faculties/self.model.updater.ts +19 -12
  57. package/src/cognition/faculties/social.perception.ts +47 -3
  58. package/src/cognition/faculties/threat.evaluator.ts +7 -0
  59. package/src/cognition/faculties/working.memory.ts +10 -20
  60. package/src/cognition/identity.entity.ts +205 -0
  61. package/src/cognition/index.ts +11 -0
  62. package/src/cognition/memory/vector.adapter.ts +12 -3
  63. package/src/cognition/memory/vector.embedder.ts +54 -7
  64. package/src/cognition/persona.prior.ts +6 -0
  65. package/src/cognition/senses/audition.engine/engine.ts +404 -46
  66. package/src/cognition/senses/base.sense.engine.ts +1 -1
  67. package/src/cognition/senses/index.ts +12 -0
  68. package/src/cognition/social.identity.ts +273 -0
  69. package/src/cognition/utilities/token.tracker.ts +246 -98
  70. package/src/core/orchestrator.ts +38 -0
  71. package/src/host/boot.ts +78 -22
  72. package/src/index.ts +35 -0
  73. package/src/llm/index.ts +415 -97
  74. package/src/llm/routing.ts +204 -0
  75. package/src/llm/summarizer.ts +5 -1
  76. package/src/llm/wire.contracts.ts +19 -0
  77. package/src/pma/index.ts +67 -53
  78. package/src/runners/thin-shim.runner.ts +18 -6
  79. package/src/sdk/will.ts +121 -22
  80. package/src/stem/assembly.audit.ts +1 -0
  81. package/src/stem/guards/identity.coherence.ts +17 -6
  82. package/src/stem/index.ts +82 -5
  83. package/src/stem/mind.ts +327 -79
  84. package/src/stem/policy/arbiter.ts +49 -14
  85. package/src/stem/policy/rule.table.ts +2 -2
  86. package/src/stem/tracts/effector.controller.ts +56 -9
  87. package/src/stem/tracts/outbox.writer.ts +40 -2
  88. package/src/cognition/faculties/executive.engine/messages.ts +0 -102
@@ -12,6 +12,11 @@
12
12
  */
13
13
 
14
14
  import type { TokenTracker } from '#cognition/utilities/token.tracker'
15
+ import type { LLMCallFunction } from '#cognition/utilities/token.tracker'
16
+ import { LLMSemaphore, withGate } from '#llm/gate'
17
+
18
+ /** Embedding is only ever a read or a write. */
19
+ export type EmbedFunction = Extract<LLMCallFunction, 'recall' | 'index'>
15
20
 
16
21
  export interface EmbeddingProvider {
17
22
  readonly modelName: string
@@ -40,13 +45,27 @@ export class OpenAICompatibleEmbedder implements EmbeddingProvider {
40
45
  private _maxConcurrency: number
41
46
  private _timeoutMs: number
42
47
  private _tokenTracker: TokenTracker | null
48
+ /**
49
+ * Own gate — the same LLMSemaphore the LLM calls use, on a separate instance so
50
+ * embeddings and reasoning do not compete for one another's slots. It bounds the
51
+ * fan-out that produced the 10.7s tail, and `withGate` additionally retries a 429
52
+ * with backoff, which a bare `embed()` previously surfaced as a hard failure.
53
+ */
54
+ private _gate: LLMSemaphore
43
55
 
44
56
  constructor( config: {
45
57
  modelName: string
46
58
  dimensions: number
47
59
  apiUrl: string
48
60
  apiKey?: string | null
49
- /** Max embedding requests in flight at once for embedBatch(). Default 8. */
61
+ /**
62
+ * Max embedding requests in flight at once — across ALL callers, not just one
63
+ * embedBatch(). Default 4, chosen from measured provider behaviour rather than
64
+ * taste: gemini-embedding-001 answers a lone request in ~1.1s, but queues hard
65
+ * under fan-out — at 8 in flight the slowest three took 10.7s (all HTTP 200, no
66
+ * 429, simply serialized). That tail is what made recall exceed its 5s budget
67
+ * and return "no recall" while a mind with six live facets was asking.
68
+ */
50
69
  maxConcurrency?: number
51
70
  /** @deprecated use maxConcurrency — kept as its fallback for back-compat. */
52
71
  batchSize?: number
@@ -55,7 +74,7 @@ export class OpenAICompatibleEmbedder implements EmbeddingProvider {
55
74
  /**
56
75
  * Per-Will token tracker. When provided, each embedding call records its
57
76
  * input-token usage under the 'embedding' category so memory-vector spend is
58
- * visible alongside LLM spend instead of being a silent COGS leak.
77
+ * visible alongside LLM spend instead of being a silent cost leak.
59
78
  */
60
79
  tokenTracker?: TokenTracker | null
61
80
  } ){
@@ -63,12 +82,24 @@ export class OpenAICompatibleEmbedder implements EmbeddingProvider {
63
82
  this.dimensions = config.dimensions
64
83
  this._apiUrl = config.apiUrl
65
84
  this._apiKey = config.apiKey ?? null
66
- this._maxConcurrency = Math.max( 1, config.maxConcurrency ?? config.batchSize ?? 8 )
85
+ this._maxConcurrency = Math.max( 1, config.maxConcurrency ?? config.batchSize ?? 4 )
86
+ this._gate = new LLMSemaphore( this._maxConcurrency )
67
87
  this._timeoutMs = config.timeoutMs ?? 30_000
68
88
  this._tokenTracker = config.tokenTracker ?? null
69
89
  }
70
90
 
71
- async embed( content: unknown, fn: string = 'recall'): Promise<number[]> {
91
+ /**
92
+ * Embed one item, gated. Every caller funnels through here — a facet building a
93
+ * prompt, the master recalling, the consolidator indexing — so the gate is the
94
+ * only place total in-flight fan-out is bounded. Waiting for a slot is strictly
95
+ * better than the alternative it replaces: an ungated request that returns after
96
+ * the recall budget has already expired is a request whose answer is thrown away.
97
+ */
98
+ async embed( content: unknown, fn: EmbedFunction = 'recall'): Promise<number[]> {
99
+ return withGate( () => this._embedOnce( content, fn ), `embed:${ this.modelName }`, this._gate )
100
+ }
101
+
102
+ private async _embedOnce( content: unknown, fn: EmbedFunction ): Promise<number[]> {
72
103
  let response: Response
73
104
  try {
74
105
  response = await fetch(`${this._apiUrl}/embeddings`, {
@@ -106,6 +137,21 @@ export class OpenAICompatibleEmbedder implements EmbeddingProvider {
106
137
  if( !Array.isArray( embedding ) || embedding.length === 0 )
107
138
  throw new Error(`Embedding response was empty or malformed for model ${this.modelName}`)
108
139
 
140
+ // The configured width must match what the provider actually returns. This class
141
+ // sends no `dimensions` param, so the index is sized from config alone — and a
142
+ // wrong number does not fail, it silently builds an index that can never match.
143
+ // Providers differ per model family and change defaults between versions, so the
144
+ // number is checked against reality once rather than trusted. Failing here is safe:
145
+ // indexing degrades to "deferred" and recall to "no recall", both already
146
+ // best-effort, and the message carries the value to set.
147
+ if( embedding.length !== this.dimensions )
148
+ throw new Error(
149
+ `Embedding width mismatch for ${ this.modelName }: provider returned ${ embedding.length } ` +
150
+ `dimensions, index is configured for ${ this.dimensions }. ` +
151
+ `Set WILL_EMBEDDING_DIMENSIONS=${ embedding.length } (and delete any existing ` +
152
+ `vector_index built at the old width).`
153
+ )
154
+
109
155
  // Meter embedding token usage (input-only — embeddings have no completion).
110
156
  // Recorded under the 'embedding' category so per-Will dashboards can split
111
157
  // memory-vector spend from LLM reasoning spend.
@@ -118,6 +164,7 @@ export class OpenAICompatibleEmbedder implements EmbeddingProvider {
118
164
  totalTokens: usedTok,
119
165
  category: 'embedding',
120
166
  attribute: 'memory',
167
+ process: 'cog', // background: no deliberation happens here
121
168
  function: fn, // 'recall' (query) | 'index' (write)
122
169
  scope: this.modelName,
123
170
  tick: 0,
@@ -128,7 +175,7 @@ export class OpenAICompatibleEmbedder implements EmbeddingProvider {
128
175
  return embedding
129
176
  }
130
177
 
131
- async embedBatch( contents: unknown[], fn: string = 'index'): Promise<number[][]> {
178
+ async embedBatch( contents: unknown[], fn: EmbedFunction = 'index'): Promise<number[][]> {
132
179
  // Bounded fan-out: cap concurrent requests at _maxConcurrency instead of
133
180
  // firing all of them at once (FN16), while preserving input order.
134
181
  const results: number[][] = new Array( contents.length )
@@ -170,7 +217,7 @@ export class MockEmbedder implements EmbeddingProvider {
170
217
  this._seed = seed
171
218
  }
172
219
 
173
- async embed( content: unknown, _fn: string = 'recall'): Promise<number[]> {
220
+ async embed( content: unknown, _fn: EmbedFunction = 'recall'): Promise<number[]> {
174
221
  const str = typeof content === 'string' ? content : JSON.stringify( content )
175
222
  const hash = this._hashString( str )
176
223
  const embedding: number[] = []
@@ -184,7 +231,7 @@ export class MockEmbedder implements EmbeddingProvider {
184
231
  return embedding
185
232
  }
186
233
 
187
- async embedBatch( contents: unknown[], fn: string = 'index'): Promise<number[][]> {
234
+ async embedBatch( contents: unknown[], fn: EmbedFunction = 'index'): Promise<number[][]> {
188
235
  return Promise.all( contents.map( c => this.embed( c, fn ) ) )
189
236
  }
190
237
 
@@ -118,6 +118,7 @@ const PRIOR_DESCRIPTIONS: Record<string, { lower: string; raise: string }> = {
118
118
  'engine-config-inhibition.baseInhibitionStrength': { lower: 'acting on impulse more freely', raise: 'holding myself in check more firmly before acting' },
119
119
  'engine-config-self-model.minNewExperiences': { lower: 're-evaluating who I am on less new experience', raise: 'requiring more new experience before re-evaluating who I am' },
120
120
  'engine-config-attention.shiftInertia': { lower: 'shifting my attention more readily', raise: 'holding my attention more fixedly' },
121
+ 'engine-config-attention.maxFoci': { lower: 'attending to one thing at a time, narrowly', raise: 'keeping several things in view at once' },
121
122
  'engine-config-goal-manager.gritPriority': { lower: 'refusing to give up on more of what matters to me', raise: 'letting go of goals more readily' },
122
123
  'engine-config-goal-manager.gritPatienceScale': { lower: 'losing patience with stuck goals sooner', raise: 'staying the course on hard goals far longer' },
123
124
  'engine-config-goal-manager.frustrationTolerance': { lower: 'giving up faster when frustrated', raise: 'holding steady through frustration' },
@@ -129,6 +130,7 @@ const PRIOR_DESCRIPTIONS: Record<string, { lower: string; raise: string }> = {
129
130
  'engine-config-executive.riskTolerance': { lower: 'playing it safer', raise: 'taking bigger risks' },
130
131
  'engine-config-frustration.irritabilityRate': { lower: 'letting frustration snowball into a bad mood more slowly', raise: 'getting wound up into a bad mood faster' },
131
132
  'engine-config-executive.deliberateThreshold': { lower: 'stopping to think things through more readily', raise: 'going with my gut more, deliberating less' },
133
+ 'engine-config-executive.maxFacets': { lower: 'keeping fewer things going at once, one at a time', raise: 'holding more conversations and threads at once' },
132
134
  'engine-config-reward.socialWeight': { lower: 'caring less about social warmth', raise: 'finding warmth and connection more rewarding' },
133
135
  'engine-config-frustration.angerReactivity': { lower: 'letting slights go, yielding rather than bristling', raise: 'bristling harder when I feel wronged' },
134
136
  'engine-config-novelty.significanceThreshold': { lower: 'noticing what is new and unusual more readily', raise: 'needing more for something to strike me as new' },
@@ -143,6 +145,10 @@ const PRIOR_DESCRIPTIONS: Record<string, { lower: string; raise: string }> = {
143
145
  'engine-config-action-selector.switchCost': { lower: 'dropping what I am doing for a new pull more easily', raise: 'seeing an action through, harder to knock off course once underway' },
144
146
  'engine-config-action-selector.riskWeight': { lower: 'weighing the downside of what I do less — acting bolder', raise: 'weighing what could go wrong more heavily before I act' },
145
147
  'engine-config-action-selector.noveltyWeight': { lower: 'feeling less pull toward the untried', raise: 'drawn more strongly to do the untried and unpracticed' },
148
+ 'engine-config-action-selector.repeatDamping': { lower: 'following up sooner when I have had no answer', raise: 'giving people room after I have said my piece' },
149
+ 'engine-config-action-selector.repeatWindowTicks': { lower: 'coming back to something sooner after I have said it', raise: 'letting what I have said stand for longer before returning to it' },
150
+ 'engine-config-action-selector.replyWindowTicks': { lower: 'reading a silence as an answer sooner', raise: 'giving someone longer before I take their quiet as telling me anything' },
151
+ 'engine-config-action-selector.socialWeight': { lower: 'reaching for people regardless of whether they answer me', raise: 'drawn toward the people who actually answer me' },
146
152
  'engine-config-moral.eventThreshold': { lower: 'holding myself to my principles more sharply', raise: 'letting moral lapses weigh on me less' },
147
153
  'engine-config-frustration.decayRate': { lower: 'staying frustrated for longer after a setback', raise: 'shaking off frustration and bouncing back faster' },
148
154
  'engine-config-reward.socialWarmthBoost': { lower: 'being warmed less by a kind exchange', raise: 'being warmed more by every kind exchange' },