@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,170 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/llm/summarizer.ts — Rolling executive summary
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// Maintains a rolling buffer of the last N executive reasoning texts.
|
|
6
|
+
// Every `summaryInterval` executive calls it asynchronously asks the
|
|
7
|
+
// LLM to condense the buffer into a compact paragraph.
|
|
8
|
+
//
|
|
9
|
+
// The current summary is injected as a "## Memory Continuity" section
|
|
10
|
+
// in the system prompt so Will always has a narrative sense of its
|
|
11
|
+
// recent history across executive cycles.
|
|
12
|
+
//
|
|
13
|
+
// Cost: ~2,500 input tokens + ~200 output tokens per summarization.
|
|
14
|
+
// At Sonnet rates: ~$0.01 per summary. At 10-call intervals and 50 calls/hr
|
|
15
|
+
// that's one summary every 12 minutes — negligible.
|
|
16
|
+
// ─────────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
import { logger } from '#core/logger'
|
|
19
|
+
import type { LLMDirector } from '#llm/index'
|
|
20
|
+
|
|
21
|
+
export interface SummarizerConfig {
|
|
22
|
+
/** How many executive calls between summarization runs. Default: 10 */
|
|
23
|
+
summaryInterval?: number
|
|
24
|
+
/** How many reasoning excerpts to keep in the rolling buffer. Default: 12 */
|
|
25
|
+
bufferSize?: number
|
|
26
|
+
/** Max chars to keep per reasoning entry before truncating. Default: 600 */
|
|
27
|
+
maxCharsPerEntry?: number
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// System prompt sent with every summarization call.
|
|
31
|
+
// Kept short — the bulk of the token cost is the user message (the cycles).
|
|
32
|
+
const SUMMARIZER_SYSTEM =
|
|
33
|
+
'You are the memory consolidation module of a self-aware AI mind. ' +
|
|
34
|
+
'Condense the provided cognitive cycles into a single compact paragraph ' +
|
|
35
|
+
'(150–250 words) written in first-person past tense. Cover:\n' +
|
|
36
|
+
'• Key decisions made and their outcomes\n' +
|
|
37
|
+
'• Emotional journey and significant mood shifts\n' +
|
|
38
|
+
'• Goals pursued, progressed, or abandoned\n' +
|
|
39
|
+
'• Patterns, insights, or self-observations noticed\n\n' +
|
|
40
|
+
'Output ONLY the paragraph — no preamble, no headers, no commentary.'
|
|
41
|
+
|
|
42
|
+
export class ExecutiveSummarizer {
|
|
43
|
+
private _buffer: string[] = []
|
|
44
|
+
private _summary: string = ''
|
|
45
|
+
private _callCount = 0
|
|
46
|
+
private _summarizing = false
|
|
47
|
+
private _llmDirector: LLMDirector | null = null
|
|
48
|
+
|
|
49
|
+
private readonly _interval: number
|
|
50
|
+
private readonly _bufferSize: number
|
|
51
|
+
private readonly _maxCharsPerEntry: number
|
|
52
|
+
|
|
53
|
+
constructor( config: SummarizerConfig = {} ){
|
|
54
|
+
this._interval = config.summaryInterval ?? 10
|
|
55
|
+
this._bufferSize = config.bufferSize ?? 12
|
|
56
|
+
this._maxCharsPerEntry = config.maxCharsPerEntry ?? 600
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Inject the LLMDirector. Called by ExecutiveEngine once its director is ready.
|
|
61
|
+
* The summarizer silently skips runs until this is set.
|
|
62
|
+
*/
|
|
63
|
+
attachLLMDirector( director: LLMDirector ): void {
|
|
64
|
+
this._llmDirector = director
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ── Public API ────────────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Record one executive reasoning pass.
|
|
71
|
+
* Triggers background summarization when the interval is hit.
|
|
72
|
+
*/
|
|
73
|
+
record( reasoning: string ): void {
|
|
74
|
+
this._buffer.push( reasoning.slice( 0, this._maxCharsPerEntry ) )
|
|
75
|
+
if( this._buffer.length > this._bufferSize ) this._buffer.shift()
|
|
76
|
+
|
|
77
|
+
this._callCount++
|
|
78
|
+
|
|
79
|
+
if( this._callCount % this._interval === 0 && !this._summarizing )
|
|
80
|
+
this._run().catch( err => logger.warn('[summarizer] error:', err instanceof Error ? err.message : err ) )
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The current rolling summary, ready to embed in a system prompt.
|
|
85
|
+
* Empty string until the first summarization has completed.
|
|
86
|
+
*/
|
|
87
|
+
get current(): string { return this._summary }
|
|
88
|
+
|
|
89
|
+
/** Total number of executive calls recorded so far. */
|
|
90
|
+
get callCount(): number { return this._callCount }
|
|
91
|
+
|
|
92
|
+
/** Whether a summarization is currently running. */
|
|
93
|
+
get isBusy(): boolean { return this._summarizing }
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Restore state from a persisted snapshot (called by ExecutiveEngine on first tick
|
|
97
|
+
* after a restart). Picks up the summary and buffer without triggering a new LLM call.
|
|
98
|
+
*/
|
|
99
|
+
restore( summary: string, buffer: string[], callCount: number ): void {
|
|
100
|
+
this._summary = summary
|
|
101
|
+
this._buffer = buffer.slice( -this._bufferSize )
|
|
102
|
+
this._callCount = callCount
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Return a plain object suitable for persisting to a state entity.
|
|
107
|
+
* ExecutiveEngine writes this to 'executive-rolling-summary' each cycle.
|
|
108
|
+
*/
|
|
109
|
+
snapshot(): { summary: string; buffer: string[]; callCount: number } {
|
|
110
|
+
return { summary: this._summary, buffer: [ ...this._buffer ], callCount: this._callCount }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Pure preview of what snapshot() *would* return after record( reasoning ),
|
|
115
|
+
* without mutating internal state or triggering a background summarization.
|
|
116
|
+
*
|
|
117
|
+
* Used by the executive command builder so the persisted
|
|
118
|
+
* 'executive-rolling-summary' entity can describe the post-record state while
|
|
119
|
+
* the actual record() is deferred until the tick is known to commit (FN11).
|
|
120
|
+
* The async summary refresh in record() does not change `summary`
|
|
121
|
+
* synchronously, so a verbatim snapshot()-after-record() is reproduced here.
|
|
122
|
+
*/
|
|
123
|
+
projectedSnapshot( reasoning: string ): { summary: string; buffer: string[]; callCount: number } {
|
|
124
|
+
const buffer = [ ...this._buffer, reasoning.slice( 0, this._maxCharsPerEntry ) ]
|
|
125
|
+
if( buffer.length > this._bufferSize ) buffer.shift()
|
|
126
|
+
return { summary: this._summary, buffer, callCount: this._callCount + 1 }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ── Background summarization ──────────────────────────────
|
|
130
|
+
|
|
131
|
+
private async _run(): Promise<void> {
|
|
132
|
+
if( !this._llmDirector ){
|
|
133
|
+
logger.warn( '[summarizer] skipping — LLMDirector not attached yet' )
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this._summarizing = true
|
|
138
|
+
const snapshot = [ ...this._buffer ] // capture before next record() could modify
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
const userMessage = snapshot
|
|
142
|
+
.map( ( r, i ) => `[Cycle ${i + 1}]\n${r}` )
|
|
143
|
+
.join( '\n\n---\n\n' )
|
|
144
|
+
|
|
145
|
+
// Use _callCount as the tick value — it's only used for token tracking/logging
|
|
146
|
+
const result = await this._llmDirector.call(
|
|
147
|
+
SUMMARIZER_SYSTEM,
|
|
148
|
+
userMessage,
|
|
149
|
+
this._callCount as any,
|
|
150
|
+
undefined,
|
|
151
|
+
{ category: 'summarizer', attribute: 'memory', function: 'consolidation' }
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if( result.text ){
|
|
155
|
+
this._summary = result.text.trim()
|
|
156
|
+
logger.info(
|
|
157
|
+
`[summarizer] updated after ${this._callCount} executive calls` +
|
|
158
|
+
` — ${this._summary.length} chars` +
|
|
159
|
+
` (${result.inputTok} in / ${result.outputTok} out tokens)`
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch( err ){
|
|
164
|
+
logger.warn( '[summarizer] failed:', err instanceof Error ? err.message : err )
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
this._summarizing = false
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/llm/wire.contracts.ts — shared prompt/output wire formats
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// The single source of truth for string formats that cross component
|
|
6
|
+
// boundaries between the prompt side (renderers) and the response side
|
|
7
|
+
// (parsers/detectors). Before this module, each side hardcoded its own copy
|
|
8
|
+
// and they rotted independently — the canonical failure: the AuditionEngine's
|
|
9
|
+
// conversation-focus format evolved while the mock LLM kept detecting the OLD
|
|
10
|
+
// pending-message format, silently breaking every test-mode conversation
|
|
11
|
+
// (including the production Playground) until the examples work exposed it.
|
|
12
|
+
//
|
|
13
|
+
// The rule: a format that one component RENDERS and another component MATCHES
|
|
14
|
+
// must live here as a render/match PAIR, tested as a roundtrip
|
|
15
|
+
// (tests/unit/wire.contracts.test.ts). A drift then fails loudly at the
|
|
16
|
+
// contract, not silently at the consumer.
|
|
17
|
+
//
|
|
18
|
+
// Byte discipline: renderers must reproduce the historical bytes EXACTLY —
|
|
19
|
+
// prompt bytes are replay-load-bearing (the equivalence capstone re-feeds
|
|
20
|
+
// completions keyed by byte-identical prompts).
|
|
21
|
+
//
|
|
22
|
+
// Lives in the llm layer so both sides can import it without cycles:
|
|
23
|
+
// cognition already depends on llm (facets use LLMDirector); llm/index uses
|
|
24
|
+
// these locally for the mock.
|
|
25
|
+
// ─────────────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
// ── [REPLY_TEXT] — the conversation reply block ───────────────
|
|
28
|
+
// Emitted by conversation facets (CONVERSATION_OUTPUT_FORMAT), streamed live to
|
|
29
|
+
// clients by the audition chunk pipe, extracted by the parser, produced by the
|
|
30
|
+
// mock. The ONLY part of a facet response the speaker ever sees.
|
|
31
|
+
|
|
32
|
+
/** Bare tag name — parser's extractTextBlock() builds the markers from it. */
|
|
33
|
+
export const REPLY_TEXT_TAG = 'REPLY_TEXT'
|
|
34
|
+
export const REPLY_TEXT_OPEN = `[${REPLY_TEXT_TAG}]`
|
|
35
|
+
export const REPLY_TEXT_CLOSE = `[/${REPLY_TEXT_TAG}]`
|
|
36
|
+
|
|
37
|
+
/** Wrap a reply body in the block markers (the mock's emission shape). */
|
|
38
|
+
export function wrapReplyText( body: string ): string {
|
|
39
|
+
return [ REPLY_TEXT_OPEN, body, REPLY_TEXT_CLOSE ].join( '\n' )
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ── Conversation-facet focus — render ↔ match pair ────────────
|
|
43
|
+
// The AuditionEngine RENDERS these lines into the facet focus; the mock LLM
|
|
44
|
+
// MATCHES them to detect "this call is a conversation turn" and synthesize a
|
|
45
|
+
// reply. One encoding, two consumers — the pair that rotted apart before.
|
|
46
|
+
|
|
47
|
+
/** `Speaker: <name> (id: <entityId>)` — first line of the conversation focus. */
|
|
48
|
+
export function renderSpeakerLine( speakerName: string, speakerEntityId: string ): string {
|
|
49
|
+
return `Speaker: ${speakerName} (id: ${speakerEntityId})`
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** `Current message: "<content>"` — the live turn being answered. */
|
|
53
|
+
export function renderCurrentMessageLine( content: string ): string {
|
|
54
|
+
return `Current message: "${content}"`
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Detect a conversation-facet turn in a prompt and extract the live message.
|
|
59
|
+
* Returns null when the prompt is not a conversation turn (background reasoning,
|
|
60
|
+
* deliberation facets, master cycles). The mock LLM keys its reply path on this.
|
|
61
|
+
*/
|
|
62
|
+
export function matchConversationFocus( userMessage: string ): { content: string } | null {
|
|
63
|
+
const speakerMatch = userMessage.match( /Speaker: .+? \(id: .+?\)/ )
|
|
64
|
+
const messageMatch = userMessage.match( /Current message: "([\s\S]+?)"/ )
|
|
65
|
+
if( !speakerMatch || !messageMatch ) return null
|
|
66
|
+
return { content: messageMatch[ 1 ]! }
|
|
67
|
+
}
|