@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.
- package/README.md +87 -22
- package/dist/channels/discord.d.ts +67 -6
- package/dist/channels/discord.js +112 -6
- package/dist/channels/discord.js.map +1 -1
- package/dist/channels/whatsapp.d.ts +1 -1
- package/dist/channels/whatsapp.js +4 -1
- package/dist/channels/whatsapp.js.map +1 -1
- package/dist/cli.js +13733 -11057
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3729 -1199
- package/dist/index.js.map +1 -1
- package/dist/mcp/effectors.d.ts +1 -1
- package/dist/{will-DAW0l-lY.d.ts → will-DbDj_TEH.d.ts} +1214 -93
- package/package.json +1 -1
- package/src/channels/discord.ts +189 -11
- package/src/channels/types.ts +90 -0
- package/src/channels/whatsapp.ts +13 -4
- package/src/cli.ts +9 -4
- package/src/cognition/agency/consequence.ts +122 -1
- package/src/cognition/agency/conversation.aim.ts +260 -0
- package/src/cognition/agency/engines/action.selector.ts +85 -3
- package/src/cognition/agency/engines/affordance.synthesizer.ts +90 -1
- package/src/cognition/agency/engines/motor.schema.executor.ts +152 -10
- package/src/cognition/agency/engines/reafference.engine.ts +129 -2
- package/src/cognition/agency/proactive.communicator.ts +19 -3
- package/src/cognition/agency/reconcile.learning.ts +16 -2
- package/src/cognition/agency/restart.ts +66 -0
- package/src/cognition/agency/schemas/repertoire.ts +12 -5
- package/src/cognition/agency/selection.scoring.ts +33 -0
- package/src/cognition/agency/types.ts +35 -0
- package/src/cognition/cache/composition.ts +232 -0
- package/src/cognition/cache/deliberation.cache.ts +219 -0
- package/src/cognition/cache/fingerprint.ts +120 -0
- package/src/cognition/cache/types.ts +105 -0
- package/src/cognition/config.mirror.entities.ts +109 -1
- package/src/cognition/event.schemas.ts +22 -0
- package/src/cognition/faculties/autobiographical.narrator.ts +5 -10
- package/src/cognition/faculties/episodic.consolidator.ts +59 -3
- package/src/cognition/faculties/executive.engine/commands.ts +189 -14
- package/src/cognition/faculties/executive.engine/context.ts +67 -13
- package/src/cognition/faculties/executive.engine/deliberate.reasoning.ts +1 -1
- package/src/cognition/faculties/executive.engine/engine.ts +686 -187
- package/src/cognition/faculties/executive.engine/escalation.buffer.ts +162 -44
- package/src/cognition/faculties/executive.engine/facet.supervisor.ts +310 -65
- package/src/cognition/faculties/executive.engine/facet.ts +89 -26
- package/src/cognition/faculties/executive.engine/gating.ts +14 -14
- package/src/cognition/faculties/executive.engine/parser.ts +21 -1
- package/src/cognition/faculties/executive.engine/prompt.factory.ts +169 -20
- package/src/cognition/faculties/executive.engine/types.ts +69 -0
- package/src/cognition/faculties/goal.manager.ts +94 -14
- package/src/cognition/faculties/known.entity.tracker.ts +267 -28
- package/src/cognition/faculties/moral.evaluator.ts +8 -3
- package/src/cognition/faculties/persona.consolidator.ts +141 -0
- package/src/cognition/faculties/reputation.tracker.ts +66 -2
- package/src/cognition/faculties/self.model.updater.ts +19 -12
- package/src/cognition/faculties/social.perception.ts +47 -3
- package/src/cognition/faculties/threat.evaluator.ts +7 -0
- package/src/cognition/faculties/working.memory.ts +10 -20
- package/src/cognition/identity.entity.ts +205 -0
- package/src/cognition/index.ts +11 -0
- package/src/cognition/memory/vector.adapter.ts +12 -3
- package/src/cognition/memory/vector.embedder.ts +54 -7
- package/src/cognition/persona.prior.ts +6 -0
- package/src/cognition/senses/audition.engine/engine.ts +404 -46
- package/src/cognition/senses/base.sense.engine.ts +1 -1
- package/src/cognition/senses/index.ts +12 -0
- package/src/cognition/social.identity.ts +273 -0
- package/src/cognition/utilities/token.tracker.ts +246 -98
- package/src/core/orchestrator.ts +38 -0
- package/src/host/boot.ts +78 -22
- package/src/index.ts +35 -0
- package/src/llm/index.ts +415 -97
- package/src/llm/routing.ts +204 -0
- package/src/llm/summarizer.ts +5 -1
- package/src/llm/wire.contracts.ts +19 -0
- package/src/pma/index.ts +67 -53
- package/src/runners/thin-shim.runner.ts +18 -6
- package/src/sdk/will.ts +121 -22
- package/src/stem/assembly.audit.ts +1 -0
- package/src/stem/guards/identity.coherence.ts +17 -6
- package/src/stem/index.ts +82 -5
- package/src/stem/mind.ts +327 -79
- package/src/stem/policy/arbiter.ts +49 -14
- package/src/stem/policy/rule.table.ts +2 -2
- package/src/stem/tracts/effector.controller.ts +56 -9
- package/src/stem/tracts/outbox.writer.ts +40 -2
- package/src/cognition/faculties/executive.engine/messages.ts +0 -102
|
@@ -928,6 +928,22 @@ declare class DefaultOrchestrator implements Orchestrator {
|
|
|
928
928
|
* calls _executeTick() which handles pause/stop checks internally.
|
|
929
929
|
* The orchestrator is the sole driver of ticks.
|
|
930
930
|
*/
|
|
931
|
+
/**
|
|
932
|
+
* A plain SimulationEngine's `react()` is implicitly "finish inside the tick" —
|
|
933
|
+
* only an AsyncEngine is allowed to span ticks, and it does so by LAUNCHING work
|
|
934
|
+
* and landing it later (see async.engine.ts: "react() never awaits LLM calls").
|
|
935
|
+
* Nothing enforces that on everyone else, and the failure is silent and severe:
|
|
936
|
+
* every agency deadline is denominated in TICKS, so an engine that awaits network
|
|
937
|
+
* I/O does not merely run slowly, it rescales time for the whole mind.
|
|
938
|
+
*
|
|
939
|
+
* Measured: one rate-limited embedding call awaited inside EpisodicConsolidator
|
|
940
|
+
* made two consecutive ticks take 64.9s and 63.5s. `AWAIT_TIMEOUT` — 15 ticks,
|
|
941
|
+
* normally ~15s — silently became 15 minutes, so a communicate intent sat
|
|
942
|
+
* 'awaiting' forever and the serial selector never chose anything again. 45
|
|
943
|
+
* executive decisions produced one intent and zero delivered messages, with no
|
|
944
|
+
* error anywhere. This turns that into a line in the log the first time it happens.
|
|
945
|
+
*/
|
|
946
|
+
private _warnIfSlow;
|
|
931
947
|
private _runLoop;
|
|
932
948
|
private _shutdown;
|
|
933
949
|
stop(): void;
|
|
@@ -1332,7 +1348,6 @@ declare class WorkingMemory implements SimulationEngine, CognitiveEngine {
|
|
|
1332
1348
|
private _emitEvents;
|
|
1333
1349
|
private _items;
|
|
1334
1350
|
private _modulatedCapacity;
|
|
1335
|
-
private _currentFocusId;
|
|
1336
1351
|
private _activeGoalCount;
|
|
1337
1352
|
/**
|
|
1338
1353
|
* Monotonic suffix counter for injected WM item ids. Replaces Math.random()
|
|
@@ -1373,8 +1388,10 @@ declare class WorkingMemory implements SimulationEngine, CognitiveEngine {
|
|
|
1373
1388
|
*/
|
|
1374
1389
|
private _ingestGoals;
|
|
1375
1390
|
/**
|
|
1376
|
-
* Mark the currently focused entity's WM item as attended this tick
|
|
1377
|
-
*
|
|
1391
|
+
* Mark the currently focused entity's WM item as attended this tick, from the
|
|
1392
|
+
* `attention.focus` entities AttentionAllocator writes. (A second, bus-driven
|
|
1393
|
+
* branch used to sit above this one, labelled "preferred"; the event behind it was
|
|
1394
|
+
* never published, so this loop has always been the only path — see #114.)
|
|
1378
1395
|
*/
|
|
1379
1396
|
private _applyAttention;
|
|
1380
1397
|
/**
|
|
@@ -1446,6 +1463,10 @@ interface GoalState {
|
|
|
1446
1463
|
activatedAt: Tick;
|
|
1447
1464
|
deadline?: Tick;
|
|
1448
1465
|
tags: string[];
|
|
1466
|
+
/** Why this goal was abandoned, when it was. Set only on status 'abandoned'.
|
|
1467
|
+
* The reason used to be pushed onto `tags`, which threw once the goal had
|
|
1468
|
+
* been rehydrated from a deep-frozen state entity. */
|
|
1469
|
+
abandonedReason?: string;
|
|
1449
1470
|
/** Snapshot of memory.beliefs_total when this goal was activated.
|
|
1450
1471
|
* Used to compute epistemic progress: (currentBeliefs - baseline) / threshold. */
|
|
1451
1472
|
beliefsAtActivation: number;
|
|
@@ -1573,6 +1594,19 @@ declare class GoalManager implements SimulationEngine, CognitiveEngine {
|
|
|
1573
1594
|
* "learn" ↔ "learning").
|
|
1574
1595
|
*/
|
|
1575
1596
|
private _nudgeActionGoals;
|
|
1597
|
+
/**
|
|
1598
|
+
* Somebody answered. Advance the action goals that were about reaching them.
|
|
1599
|
+
*
|
|
1600
|
+
* Linked the way every other goal→person link in the system is linked: the
|
|
1601
|
+
* `keid:<id>` tag (selection.scoring's `collectGoalTargets` reads the same one
|
|
1602
|
+
* to lift a reach-out's goal relevance) or `requestingEntityId`, set when a
|
|
1603
|
+
* conversation escalation created the goal. Nothing here guesses from wording.
|
|
1604
|
+
*
|
|
1605
|
+
* Unmatched by design: a goal with no link to this person gets nothing, even if
|
|
1606
|
+
* it is tagged 'communication'. Being answered by one person is not progress on
|
|
1607
|
+
* wanting to talk to another.
|
|
1608
|
+
*/
|
|
1609
|
+
private _nudgeAnsweredGoals;
|
|
1576
1610
|
/** True when a metric completionCondition (e.g. "emotion.boredom < 40") is already met. */
|
|
1577
1611
|
private _isConditionMet;
|
|
1578
1612
|
private _evaluateMetricProgress;
|
|
@@ -1586,32 +1620,62 @@ declare class GoalManager implements SimulationEngine, CognitiveEngine {
|
|
|
1586
1620
|
private _persistGoals;
|
|
1587
1621
|
}
|
|
1588
1622
|
|
|
1589
|
-
/**
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
* - Per-engine breakdowns
|
|
1598
|
-
* - Per-agent breakdowns
|
|
1599
|
-
*
|
|
1600
|
-
* Exposes as metrics so the orchestrator and runner can log costs,
|
|
1601
|
-
* and the ParameterOptimizer can factor cost into optimization decisions.
|
|
1602
|
-
*/
|
|
1603
|
-
|
|
1623
|
+
/** Top-level cost bucket for an LLM call. */
|
|
1624
|
+
type LLMCallCategory = 'executive' | 'summarizer' | 'embedding' | 'identity-guard';
|
|
1625
|
+
/** The actor/subsystem doing the work. */
|
|
1626
|
+
type LLMCallAttribute = 'master' | 'facet' | 'memory' | 'guard';
|
|
1627
|
+
/** The specific cognitive process being paid for. */
|
|
1628
|
+
type LLMCallProcess = 'cog' | 'decision' | 'ideation';
|
|
1629
|
+
/** The specific cognitive function being paid for. */
|
|
1630
|
+
type LLMCallFunction = '-' | 'deliberation' | 'conversation' | 'outreach' | 'planning' | 'supervision' | 'consolidation' | 'recall' | 'index' | 'identity-coherence';
|
|
1604
1631
|
/** One attributed ledger record (5-axis attribution + tokens + cost). */
|
|
1605
1632
|
type TokenLedgerRecord = Record<string, unknown>;
|
|
1606
1633
|
type TokenRecordListener = (record: TokenLedgerRecord) => void;
|
|
1607
|
-
/**
|
|
1608
|
-
|
|
1634
|
+
/** USD per 1M tokens for one model. */
|
|
1635
|
+
interface ModelPrice {
|
|
1609
1636
|
input: number;
|
|
1610
1637
|
output: number;
|
|
1611
|
-
}
|
|
1638
|
+
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Host-supplied prices, keyed by model id. Matching is exact first, then
|
|
1641
|
+
* normalized (provider prefix, date stamp and context qualifier stripped), so
|
|
1642
|
+
* `claude-sonnet-5` matches `claude-sonnet-5-20260114`.
|
|
1643
|
+
*
|
|
1644
|
+
* Prices belong to the host: they change on a vendor's schedule, differ per
|
|
1645
|
+
* account, and are ~0 for a self-hosted model. The engine ships none.
|
|
1646
|
+
*/
|
|
1647
|
+
type PriceTable = Record<string, ModelPrice>;
|
|
1648
|
+
/**
|
|
1649
|
+
* Resolve the price for a model id from the host's table.
|
|
1650
|
+
*
|
|
1651
|
+
* The engine ships no prices at all. A table baked into a release is wrong the
|
|
1652
|
+
* week a vendor changes a rate, differs per account, and is meaningless for a
|
|
1653
|
+
* self-hosted model — and a *partial* table is worse than none, because some
|
|
1654
|
+
* models then report plausible-but-stale numbers while others honestly report
|
|
1655
|
+
* nothing. Prices live with the host, next to the routing policy they inform.
|
|
1656
|
+
*
|
|
1657
|
+
* `null` does NOT mean free — it means *unknown*, and the caller reports zero
|
|
1658
|
+
* cost with `priced: false` so the gap stays visible rather than confidently
|
|
1659
|
+
* wrong. (The removed built-in default priced every unrecognised model at
|
|
1660
|
+
* Sonnet's rate, overstating a budget model's output by ~54×.)
|
|
1661
|
+
*/
|
|
1662
|
+
declare function resolvePricing(model: string, hostPrices?: PriceTable): ModelPrice | null;
|
|
1612
1663
|
interface TokenUsage {
|
|
1613
1664
|
/** Model identifier (e.g., 'openai/gpt-4o') */
|
|
1614
1665
|
model: string;
|
|
1666
|
+
/**
|
|
1667
|
+
* The provider that actually served this call.
|
|
1668
|
+
*
|
|
1669
|
+
* Not derivable from `model`: routing is what makes the same model id
|
|
1670
|
+
* reachable from several places — `deepseek-v3` direct, through a gateway, or
|
|
1671
|
+
* self-hosted — at prices that differ by orders of magnitude. Without this a
|
|
1672
|
+
* host billing across a multi-vendor routing table can attribute spend to a
|
|
1673
|
+
* model but never to the vendor it actually paid.
|
|
1674
|
+
*
|
|
1675
|
+
* Optional because a caller recording usage directly (outside the LLM
|
|
1676
|
+
* director) may not know it; absent means unattributed, not "the default".
|
|
1677
|
+
*/
|
|
1678
|
+
provider?: string;
|
|
1615
1679
|
/** Input/prompt tokens consumed */
|
|
1616
1680
|
promptTokens: number;
|
|
1617
1681
|
/** Output/completion tokens consumed */
|
|
@@ -1622,14 +1686,33 @@ interface TokenUsage {
|
|
|
1622
1686
|
cacheReadTokens?: number;
|
|
1623
1687
|
/** Anthropic prompt-cache write tokens (billed at 1.25× input). Optional. */
|
|
1624
1688
|
cacheWriteTokens?: number;
|
|
1625
|
-
/** Estimated cost in USD */
|
|
1689
|
+
/** Estimated cost in USD. Zero when `priced` is false — unknown, not free. */
|
|
1626
1690
|
estimatedCostUsd: number;
|
|
1627
|
-
/**
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1691
|
+
/**
|
|
1692
|
+
* Whether a price was found for this model. False ⇒ `estimatedCostUsd` is 0
|
|
1693
|
+
* because nothing priced it, NOT because the call was free. A consumer
|
|
1694
|
+
* summing costs should surface unpriced calls rather than fold them in as
|
|
1695
|
+
* zero.
|
|
1696
|
+
*/
|
|
1697
|
+
priced: boolean;
|
|
1698
|
+
/**
|
|
1699
|
+
* How much this call demanded, 0..1 — the cognitive measure the router saw.
|
|
1700
|
+
*
|
|
1701
|
+
* Recorded so routing can be ANSWERED rather than argued. Every call computes
|
|
1702
|
+
* this, routes on it, and until now threw it away — which left questions like
|
|
1703
|
+
* "is deliberation being rated by the tick's mood rather than the stakes of
|
|
1704
|
+
* its own choice?" with no dataset at all.
|
|
1705
|
+
*
|
|
1706
|
+
* Absent means UNMEASURED, never zero. It must stay nullable all the way to
|
|
1707
|
+
* storage: a call that never reported demand and a call that reported 0.0 are
|
|
1708
|
+
* different facts, and collapsing them would put a floor of invented
|
|
1709
|
+
* confidence under exactly the analysis this exists to enable.
|
|
1710
|
+
*/
|
|
1711
|
+
demand?: number;
|
|
1712
|
+
category: LLMCallCategory;
|
|
1713
|
+
attribute: LLMCallAttribute;
|
|
1714
|
+
process: LLMCallProcess;
|
|
1715
|
+
function: LLMCallFunction;
|
|
1633
1716
|
/** Optional specific id or namespace: facet id, entity id, model name. */
|
|
1634
1717
|
scope?: string;
|
|
1635
1718
|
/** Human-readable label — auto-composed from the axes when the caller omits it. */
|
|
@@ -1642,10 +1725,16 @@ interface TokenUsage {
|
|
|
1642
1725
|
latencyMs: number;
|
|
1643
1726
|
}
|
|
1644
1727
|
/** What callers pass to {@link TokenTracker.recordUsage} — cost and label are derived. */
|
|
1645
|
-
type RecordUsageInput = Omit<TokenUsage, 'estimatedCostUsd' | 'label'> & {
|
|
1728
|
+
type RecordUsageInput = Omit<TokenUsage, 'estimatedCostUsd' | 'label' | 'priced'> & {
|
|
1646
1729
|
label?: string;
|
|
1647
1730
|
};
|
|
1648
1731
|
interface TokenTrackerConfig {
|
|
1732
|
+
/**
|
|
1733
|
+
* Host-supplied model prices (USD per 1M tokens), merged from the per-provider
|
|
1734
|
+
* `prices` maps in `WillLLMConfig.providers`. These win over the built-in
|
|
1735
|
+
* fallback table. Omitted ⇒ fallback only.
|
|
1736
|
+
*/
|
|
1737
|
+
prices?: PriceTable;
|
|
1649
1738
|
/** Whether to emit cost events */
|
|
1650
1739
|
emitCostEvents?: boolean;
|
|
1651
1740
|
/** Cost threshold for warning events */
|
|
@@ -1664,6 +1753,7 @@ declare class TokenTracker implements SimulationEngine {
|
|
|
1664
1753
|
readonly name = "token-tracker";
|
|
1665
1754
|
private _emitCostEvents;
|
|
1666
1755
|
private _costWarningThreshold;
|
|
1756
|
+
private _prices;
|
|
1667
1757
|
private _usageLog;
|
|
1668
1758
|
private _totalPromptTokens;
|
|
1669
1759
|
private _totalCompletionTokens;
|
|
@@ -1672,6 +1762,10 @@ declare class TokenTracker implements SimulationEngine {
|
|
|
1672
1762
|
private _categoryTokens;
|
|
1673
1763
|
private _functionCosts;
|
|
1674
1764
|
private _functionTokens;
|
|
1765
|
+
private _processCosts;
|
|
1766
|
+
private _processTokens;
|
|
1767
|
+
private _providerCosts;
|
|
1768
|
+
private _providerTokens;
|
|
1675
1769
|
private _tickCosts;
|
|
1676
1770
|
private _maxTickCostSamples;
|
|
1677
1771
|
private _lastCostWarningTick;
|
|
@@ -1716,6 +1810,28 @@ declare class TokenTracker implements SimulationEngine {
|
|
|
1716
1810
|
prompt: number;
|
|
1717
1811
|
completion: number;
|
|
1718
1812
|
}>;
|
|
1813
|
+
/** Cost broken down by process ('decision' | 'ideation' | 'cog'). */
|
|
1814
|
+
get processBreakdown(): ReadonlyMap<string, number>;
|
|
1815
|
+
/** Token counts (prompt + completion) broken down by process. */
|
|
1816
|
+
get processTokenBreakdown(): ReadonlyMap<string, {
|
|
1817
|
+
prompt: number;
|
|
1818
|
+
completion: number;
|
|
1819
|
+
}>;
|
|
1820
|
+
/**
|
|
1821
|
+
* Cost broken down by provider ('anthropic' | 'glm' | 'moonshot' | …), plus
|
|
1822
|
+
* an `unattributed` bucket for usage recorded without one.
|
|
1823
|
+
*
|
|
1824
|
+
* This is the axis a host reconciles against vendor invoices. Calls whose
|
|
1825
|
+
* model went unpriced contribute 0 here, so compare against
|
|
1826
|
+
* `getUsageLog()`'s `priced` flag before treating a small number as a small
|
|
1827
|
+
* bill.
|
|
1828
|
+
*/
|
|
1829
|
+
get providerBreakdown(): ReadonlyMap<string, number>;
|
|
1830
|
+
/** Token counts (prompt + completion) broken down by provider. */
|
|
1831
|
+
get providerTokenBreakdown(): ReadonlyMap<string, {
|
|
1832
|
+
prompt: number;
|
|
1833
|
+
completion: number;
|
|
1834
|
+
}>;
|
|
1719
1835
|
/** Cost per call average */
|
|
1720
1836
|
get averageCostPerCall(): number;
|
|
1721
1837
|
/** Cost per tick average */
|
|
@@ -1739,6 +1855,8 @@ declare class TokenTracker implements SimulationEngine {
|
|
|
1739
1855
|
* - Mock embedder for testing/deterministic replay
|
|
1740
1856
|
*/
|
|
1741
1857
|
|
|
1858
|
+
/** Embedding is only ever a read or a write. */
|
|
1859
|
+
type EmbedFunction = Extract<LLMCallFunction, 'recall' | 'index'>;
|
|
1742
1860
|
interface EmbeddingProvider {
|
|
1743
1861
|
readonly modelName: string;
|
|
1744
1862
|
readonly dimensions: number;
|
|
@@ -1761,12 +1879,26 @@ declare class OpenAICompatibleEmbedder implements EmbeddingProvider {
|
|
|
1761
1879
|
private _maxConcurrency;
|
|
1762
1880
|
private _timeoutMs;
|
|
1763
1881
|
private _tokenTracker;
|
|
1882
|
+
/**
|
|
1883
|
+
* Own gate — the same LLMSemaphore the LLM calls use, on a separate instance so
|
|
1884
|
+
* embeddings and reasoning do not compete for one another's slots. It bounds the
|
|
1885
|
+
* fan-out that produced the 10.7s tail, and `withGate` additionally retries a 429
|
|
1886
|
+
* with backoff, which a bare `embed()` previously surfaced as a hard failure.
|
|
1887
|
+
*/
|
|
1888
|
+
private _gate;
|
|
1764
1889
|
constructor(config: {
|
|
1765
1890
|
modelName: string;
|
|
1766
1891
|
dimensions: number;
|
|
1767
1892
|
apiUrl: string;
|
|
1768
1893
|
apiKey?: string | null;
|
|
1769
|
-
/**
|
|
1894
|
+
/**
|
|
1895
|
+
* Max embedding requests in flight at once — across ALL callers, not just one
|
|
1896
|
+
* embedBatch(). Default 4, chosen from measured provider behaviour rather than
|
|
1897
|
+
* taste: gemini-embedding-001 answers a lone request in ~1.1s, but queues hard
|
|
1898
|
+
* under fan-out — at 8 in flight the slowest three took 10.7s (all HTTP 200, no
|
|
1899
|
+
* 429, simply serialized). That tail is what made recall exceed its 5s budget
|
|
1900
|
+
* and return "no recall" while a mind with six live facets was asking.
|
|
1901
|
+
*/
|
|
1770
1902
|
maxConcurrency?: number;
|
|
1771
1903
|
/** @deprecated use maxConcurrency — kept as its fallback for back-compat. */
|
|
1772
1904
|
batchSize?: number;
|
|
@@ -1775,12 +1907,20 @@ declare class OpenAICompatibleEmbedder implements EmbeddingProvider {
|
|
|
1775
1907
|
/**
|
|
1776
1908
|
* Per-Will token tracker. When provided, each embedding call records its
|
|
1777
1909
|
* input-token usage under the 'embedding' category so memory-vector spend is
|
|
1778
|
-
* visible alongside LLM spend instead of being a silent
|
|
1910
|
+
* visible alongside LLM spend instead of being a silent cost leak.
|
|
1779
1911
|
*/
|
|
1780
1912
|
tokenTracker?: TokenTracker | null;
|
|
1781
1913
|
});
|
|
1782
|
-
|
|
1783
|
-
|
|
1914
|
+
/**
|
|
1915
|
+
* Embed one item, gated. Every caller funnels through here — a facet building a
|
|
1916
|
+
* prompt, the master recalling, the consolidator indexing — so the gate is the
|
|
1917
|
+
* only place total in-flight fan-out is bounded. Waiting for a slot is strictly
|
|
1918
|
+
* better than the alternative it replaces: an ungated request that returns after
|
|
1919
|
+
* the recall budget has already expired is a request whose answer is thrown away.
|
|
1920
|
+
*/
|
|
1921
|
+
embed(content: unknown, fn?: EmbedFunction): Promise<number[]>;
|
|
1922
|
+
private _embedOnce;
|
|
1923
|
+
embedBatch(contents: unknown[], fn?: EmbedFunction): Promise<number[][]>;
|
|
1784
1924
|
areEquivalent(embedding1: number[], embedding2: number[], tolerance?: number): boolean;
|
|
1785
1925
|
}
|
|
1786
1926
|
/**
|
|
@@ -1792,8 +1932,8 @@ declare class MockEmbedder implements EmbeddingProvider {
|
|
|
1792
1932
|
readonly dimensions = 128;
|
|
1793
1933
|
private _seed;
|
|
1794
1934
|
constructor(seed?: number);
|
|
1795
|
-
embed(content: unknown, _fn?:
|
|
1796
|
-
embedBatch(contents: unknown[], fn?:
|
|
1935
|
+
embed(content: unknown, _fn?: EmbedFunction): Promise<number[]>;
|
|
1936
|
+
embedBatch(contents: unknown[], fn?: EmbedFunction): Promise<number[][]>;
|
|
1797
1937
|
areEquivalent(embedding1: number[], embedding2: number[], tolerance?: number): boolean;
|
|
1798
1938
|
private _hashString;
|
|
1799
1939
|
private _next;
|
|
@@ -1945,6 +2085,16 @@ declare class DefaultVectorMemoryAdapter implements VectorMemoryAdapter {
|
|
|
1945
2085
|
persist(): Promise<void>;
|
|
1946
2086
|
load(): Promise<void>;
|
|
1947
2087
|
private _evictColdest;
|
|
2088
|
+
/**
|
|
2089
|
+
* Throttle, NOT a debounce. The previous version cleared and re-armed the timer on
|
|
2090
|
+
* every index(), so it only ever fired after 5s of complete inactivity — and a mind
|
|
2091
|
+
* consolidating steadily indexes far more often than that, so the write was pushed
|
|
2092
|
+
* back indefinitely and the index never reached disk while it was awake.
|
|
2093
|
+
*
|
|
2094
|
+
* A pending timer is now left alone: the first write after a quiet period sets the
|
|
2095
|
+
* deadline, and everything indexed within the window rides along on it. Persist is
|
|
2096
|
+
* bounded at 5s from the FIRST pending change rather than the last.
|
|
2097
|
+
*/
|
|
1948
2098
|
private _schedulePersist;
|
|
1949
2099
|
}
|
|
1950
2100
|
|
|
@@ -2007,6 +2157,13 @@ declare class EpisodicConsolidator implements SimulationEngine, CognitiveEngine
|
|
|
2007
2157
|
private _affectDominance;
|
|
2008
2158
|
private _bus;
|
|
2009
2159
|
private _vectorMemory;
|
|
2160
|
+
/**
|
|
2161
|
+
* In-flight background indexing. Indexing is deliberately not awaited inside
|
|
2162
|
+
* react() (a rate-limit retry chain would stall the whole tick loop), so this is
|
|
2163
|
+
* the handle for the two callers that genuinely must wait for it: shutdown,
|
|
2164
|
+
* before persisting the index, and tests asserting on it.
|
|
2165
|
+
*/
|
|
2166
|
+
private _indexing;
|
|
2010
2167
|
private _embedder;
|
|
2011
2168
|
private _autoIndex;
|
|
2012
2169
|
private readonly _model;
|
|
@@ -2044,6 +2201,8 @@ declare class EpisodicConsolidator implements SimulationEngine, CognitiveEngine
|
|
|
2044
2201
|
* Other metadata narrowing (sourceType / tags) remains the caller's job on the
|
|
2045
2202
|
* returned episodes (which carry all metadata).
|
|
2046
2203
|
*/
|
|
2204
|
+
/** Await any background indexing still in flight. Shutdown and tests only. */
|
|
2205
|
+
flushIndexing(): Promise<void>;
|
|
2047
2206
|
semanticQuery(query: unknown, filters?: {
|
|
2048
2207
|
minSimilarity?: number;
|
|
2049
2208
|
limit?: number;
|
|
@@ -2567,7 +2726,152 @@ declare class CompletionInbox {
|
|
|
2567
2726
|
clear(): number;
|
|
2568
2727
|
}
|
|
2569
2728
|
|
|
2570
|
-
|
|
2729
|
+
/**
|
|
2730
|
+
* Where a single call should go. Every field except `model` falls back to the
|
|
2731
|
+
* Will's default when omitted.
|
|
2732
|
+
*/
|
|
2733
|
+
interface ModelRoute {
|
|
2734
|
+
/**
|
|
2735
|
+
* Omit to keep the Will's default provider and change only the model — the
|
|
2736
|
+
* common "same vendor, different model for this kind of work" route, and what
|
|
2737
|
+
* the per-role model map compiles to (a role has never had a provider of its
|
|
2738
|
+
* own). Name a provider to cross vendors; it must appear in `llm.providers`
|
|
2739
|
+
* or the route falls back to the default.
|
|
2740
|
+
*/
|
|
2741
|
+
provider?: LLMProvider;
|
|
2742
|
+
model: string;
|
|
2743
|
+
/** Override the provider's API base (self-hosted / OpenAI-compatible servers). */
|
|
2744
|
+
baseUrl?: string;
|
|
2745
|
+
/** Override the output-token ceiling for this call. */
|
|
2746
|
+
maxOutputTokens?: number;
|
|
2747
|
+
}
|
|
2748
|
+
/**
|
|
2749
|
+
* Chooses a model for a call.
|
|
2750
|
+
*
|
|
2751
|
+
* Returning `null` means "no opinion" — the Will's default model is used. A
|
|
2752
|
+
* router should return `null` rather than guess when it does not recognise a
|
|
2753
|
+
* call: falling back is always safe, and a wrong route is not.
|
|
2754
|
+
*/
|
|
2755
|
+
interface ModelRouter {
|
|
2756
|
+
/** Stable identifier, recorded alongside routing telemetry. */
|
|
2757
|
+
readonly name: string;
|
|
2758
|
+
route(meta: LLMCallMeta): ModelRoute | null;
|
|
2759
|
+
}
|
|
2760
|
+
/**
|
|
2761
|
+
* The default. Has no opinion about anything, allocates nothing.
|
|
2762
|
+
*
|
|
2763
|
+
* A Will running this must be byte-identical to one built before the routing
|
|
2764
|
+
* seam existed — that property is asserted by test, and it is what lets this
|
|
2765
|
+
* ship dark.
|
|
2766
|
+
*/
|
|
2767
|
+
declare const NULL_ROUTER: ModelRouter;
|
|
2768
|
+
/** True when the router is the no-op default (used to skip the seam entirely). */
|
|
2769
|
+
declare function isNullRouter(router: ModelRouter | null | undefined): boolean;
|
|
2770
|
+
/**
|
|
2771
|
+
* One entry in a {@link TableRouter}'s table. All present conditions must match
|
|
2772
|
+
* (logical AND); an absent condition matches anything.
|
|
2773
|
+
*/
|
|
2774
|
+
interface RoutingRule {
|
|
2775
|
+
/**
|
|
2776
|
+
* Match `LLMCallMeta.category` exactly (e.g. 'executive', 'summarizer').
|
|
2777
|
+
*
|
|
2778
|
+
* The axes are typed rather than free strings so a rule that names a bucket
|
|
2779
|
+
* the engine never emits fails to compile instead of silently never matching
|
|
2780
|
+
* — a routing table's worst failure is the rule that looks right and is dead.
|
|
2781
|
+
*/
|
|
2782
|
+
category?: LLMCallMeta['category'];
|
|
2783
|
+
/** Match `LLMCallMeta.attribute` exactly (e.g. 'master', 'facet', 'guard'). */
|
|
2784
|
+
attribute?: LLMCallMeta['attribute'];
|
|
2785
|
+
/** Match `LLMCallMeta.process` exactly (e.g. 'decision', 'ideation'). */
|
|
2786
|
+
process?: LLMCallMeta['process'];
|
|
2787
|
+
/** Match `LLMCallMeta.function` exactly (e.g. 'decision', 'consolidation'). */
|
|
2788
|
+
function?: LLMCallMeta['function'];
|
|
2789
|
+
/**
|
|
2790
|
+
* Inclusive lower bound on `LLMCallMeta.demand`. A call with no demand
|
|
2791
|
+
* reported never matches a rule that sets this — absent means unknown, and
|
|
2792
|
+
* unknown must not be treated as zero.
|
|
2793
|
+
*/
|
|
2794
|
+
minDemand?: number;
|
|
2795
|
+
/** Exclusive upper bound on `LLMCallMeta.demand`. Same absence rule. */
|
|
2796
|
+
maxDemand?: number;
|
|
2797
|
+
/** Where a matching call goes. */
|
|
2798
|
+
route: ModelRoute;
|
|
2799
|
+
}
|
|
2800
|
+
/**
|
|
2801
|
+
* A worked example of the seam: first matching rule wins, otherwise no opinion.
|
|
2802
|
+
*
|
|
2803
|
+
* This ships so that the interface has a reference implementation and so that
|
|
2804
|
+
* hosts have something to copy — it is deliberately dumb. It is not a routing
|
|
2805
|
+
* strategy, and the engine ships no table of its own: what belongs where is the
|
|
2806
|
+
* host's decision, expressed as configuration.
|
|
2807
|
+
*
|
|
2808
|
+
* Rules are evaluated in order, so put specific rules before general ones.
|
|
2809
|
+
*/
|
|
2810
|
+
declare class TableRouter implements ModelRouter {
|
|
2811
|
+
readonly name: string;
|
|
2812
|
+
private readonly _rules;
|
|
2813
|
+
constructor(rules: readonly RoutingRule[], name?: string);
|
|
2814
|
+
route(meta: LLMCallMeta): ModelRoute | null;
|
|
2815
|
+
}
|
|
2816
|
+
/**
|
|
2817
|
+
* Ask each router in turn; the first with an opinion wins.
|
|
2818
|
+
*
|
|
2819
|
+
* This exists because a Will can have two sources of routing at once: the
|
|
2820
|
+
* host's own router, and the one compiled from its per-role model map. Order
|
|
2821
|
+
* expresses precedence — an explicit router is consulted before the role map,
|
|
2822
|
+
* which is the precedence those two mechanisms already had when roles were
|
|
2823
|
+
* served by separate directors.
|
|
2824
|
+
*
|
|
2825
|
+
* A throwing link is skipped, not propagated. The links are independent
|
|
2826
|
+
* decisions, and one broken router must not take a working one down with it —
|
|
2827
|
+
* that would silently demote every role-mapped call to the default model.
|
|
2828
|
+
*/
|
|
2829
|
+
declare function chainRouters(...routers: (ModelRouter | null | undefined)[]): ModelRouter;
|
|
2830
|
+
|
|
2831
|
+
/**
|
|
2832
|
+
* The request/response dialect an endpoint speaks. This — not the provider's
|
|
2833
|
+
* name — is what the transport actually branches on.
|
|
2834
|
+
*/
|
|
2835
|
+
type LLMWire = 'anthropic' | 'openai' | 'google';
|
|
2836
|
+
/** Providers with built-in defaults. Any other string is equally valid. */
|
|
2837
|
+
type KnownProvider = 'anthropic' | 'glm' | 'openai' | 'google' | 'deepseek' | 'moonshot' | 'qwen' | 'xai' | 'minimax' | 'mistral' | 'ollama' | 'vllm';
|
|
2838
|
+
/**
|
|
2839
|
+
* A provider name. Deliberately open: the field of providers changes monthly,
|
|
2840
|
+
* and a closed union meant a host reaching Kimi or Qwen had to masquerade as
|
|
2841
|
+
* `openai`, which then lied on the completion tape and in cost attribution.
|
|
2842
|
+
*
|
|
2843
|
+
* `(string & {})` keeps editor autocomplete for the known names while accepting
|
|
2844
|
+
* anything. A provider outside {@link KNOWN_PROVIDERS} simply has to declare its
|
|
2845
|
+
* `wire` and `baseUrl` — see `WillLLMConfig.providers`.
|
|
2846
|
+
*/
|
|
2847
|
+
type LLMProvider = KnownProvider | (string & {});
|
|
2848
|
+
/**
|
|
2849
|
+
* Built-in wire + base URL per provider. This is *data*, not support: it saves
|
|
2850
|
+
* a host from looking up an endpoint, and nothing more. Any provider absent
|
|
2851
|
+
* from this table works identically once the host declares `wire` + `baseUrl`
|
|
2852
|
+
* on its `llm.providers` entry.
|
|
2853
|
+
*
|
|
2854
|
+
* WHY THIS TABLE SURVIVES WHEN THE PRICE TABLE DID NOT. A stale price is
|
|
2855
|
+
* invisible: it produces a confident wrong number nobody doubts. A stale base
|
|
2856
|
+
* URL fails on the first call, loudly, with the endpoint in the message. They
|
|
2857
|
+
* also move on completely different clocks — vendors reprice quarterly, and
|
|
2858
|
+
* change an API host about once a decade. Convenience is worth it when being
|
|
2859
|
+
* wrong is self-announcing.
|
|
2860
|
+
*
|
|
2861
|
+
* REGIONAL ENDPOINTS. `moonshot`, `qwen` and `minimax` all run separate
|
|
2862
|
+
* mainland-China hosts (`api.moonshot.cn`, `dashscope.aliyuncs.com`,
|
|
2863
|
+
* `api.minimaxi.com`). The international host is the default here; a key issued
|
|
2864
|
+
* on the other one authenticates nowhere, so a host on a China account must set
|
|
2865
|
+
* `baseUrl` explicitly.
|
|
2866
|
+
*/
|
|
2867
|
+
declare const KNOWN_PROVIDERS: Record<string, {
|
|
2868
|
+
wire: LLMWire;
|
|
2869
|
+
baseUrl: string;
|
|
2870
|
+
}>;
|
|
2871
|
+
/** Built-in wire for a known provider, or undefined — the host must declare it. */
|
|
2872
|
+
declare function knownWireFor(provider: LLMProvider): LLMWire | undefined;
|
|
2873
|
+
/** Built-in base URL for a known provider, or undefined — the host must declare it. */
|
|
2874
|
+
declare function defaultBaseFor(provider: LLMProvider): string | undefined;
|
|
2571
2875
|
interface LLMDirectorConfig {
|
|
2572
2876
|
willId: string;
|
|
2573
2877
|
model: string;
|
|
@@ -2597,6 +2901,38 @@ interface LLMDirectorConfig {
|
|
|
2597
2901
|
* replay runs). This replaces the former process-global getTokenTracker().
|
|
2598
2902
|
*/
|
|
2599
2903
|
tokenTracker?: TokenTracker | null;
|
|
2904
|
+
/**
|
|
2905
|
+
* MODEL_ROUTING W3 — per-call model selection. Absent (or NULL_ROUTER) means
|
|
2906
|
+
* every call uses the default model below, exactly as before the seam existed.
|
|
2907
|
+
* A router that throws, or names a provider with no usable credential, falls
|
|
2908
|
+
* back to the default: a routing problem must never kill a running mind.
|
|
2909
|
+
*/
|
|
2910
|
+
router?: ModelRouter | null;
|
|
2911
|
+
/**
|
|
2912
|
+
* Per-provider credentials for routed calls. The top-level `apiKey`/`baseUrl`
|
|
2913
|
+
* remain the default entry; a route to a provider absent from this map falls
|
|
2914
|
+
* back to the default endpoint.
|
|
2915
|
+
*/
|
|
2916
|
+
credentials?: Partial<Record<string, ProviderCredential>>;
|
|
2917
|
+
/**
|
|
2918
|
+
* Dialect for the default provider. Required when the provider is not one of
|
|
2919
|
+
* {@link KNOWN_PROVIDERS} — the engine will not guess how to talk to an
|
|
2920
|
+
* endpoint it has never heard of.
|
|
2921
|
+
*/
|
|
2922
|
+
wire?: LLMWire;
|
|
2923
|
+
}
|
|
2924
|
+
/**
|
|
2925
|
+
* Everything a single call needs to reach a model. Resolved once per call and
|
|
2926
|
+
* threaded through the provider methods — never stored on the instance, because
|
|
2927
|
+
* the concurrency gate lets several calls be in flight on one director at once
|
|
2928
|
+
* and per-call state on `this` would race between them.
|
|
2929
|
+
*/
|
|
2930
|
+
/** What a host supplies so a routed provider can be reached. */
|
|
2931
|
+
interface ProviderCredential {
|
|
2932
|
+
apiKey: string;
|
|
2933
|
+
baseUrl?: string;
|
|
2934
|
+
/** Required for providers outside {@link KNOWN_PROVIDERS}. */
|
|
2935
|
+
wire?: LLMWire;
|
|
2600
2936
|
}
|
|
2601
2937
|
interface LLMCallResult {
|
|
2602
2938
|
text: string;
|
|
@@ -2614,17 +2950,56 @@ interface LLMCallResult {
|
|
|
2614
2950
|
* here, letting the TokenTracker break spend down per category for transparency.
|
|
2615
2951
|
*/
|
|
2616
2952
|
interface LLMCallMeta {
|
|
2617
|
-
/** Top-level cost bucket
|
|
2618
|
-
category:
|
|
2619
|
-
/** The actor/subsystem doing the work
|
|
2620
|
-
attribute:
|
|
2621
|
-
/** The specific cognitive function
|
|
2622
|
-
|
|
2953
|
+
/** Top-level cost bucket. */
|
|
2954
|
+
category: LLMCallCategory;
|
|
2955
|
+
/** The actor/subsystem doing the work. */
|
|
2956
|
+
attribute: LLMCallAttribute;
|
|
2957
|
+
/** The specific cognitive function. */
|
|
2958
|
+
process: LLMCallProcess;
|
|
2959
|
+
/** The specific cognitive function. */
|
|
2960
|
+
function: LLMCallFunction;
|
|
2623
2961
|
/** Optional specific id or namespace: facet id, entity id, model name. */
|
|
2624
2962
|
scope?: string;
|
|
2625
2963
|
/** Free-form human-readable label. Auto-composed from the axes when omitted. */
|
|
2626
2964
|
label?: string;
|
|
2965
|
+
/**
|
|
2966
|
+
* How much this call demands, 0..1 — MODEL_ROUTING W0.
|
|
2967
|
+
*
|
|
2968
|
+
* A *cognitive* measure, never a commercial one: it says how consequential or
|
|
2969
|
+
* uncertain this moment is, never who is paying for it.
|
|
2970
|
+
*
|
|
2971
|
+
* What actually reports it today:
|
|
2972
|
+
* · the master and every facet — including the deliberation facet — forward
|
|
2973
|
+
* `effortScore`, the a-priori effort gate (uncertainty, prior confidence,
|
|
2974
|
+
* novelty, a pending reply, stress load);
|
|
2975
|
+
* · structurally background work (summarising, the identity guard) reports a
|
|
2976
|
+
* low constant, because it is background whether the mind is calm or in
|
|
2977
|
+
* crisis.
|
|
2978
|
+
*
|
|
2979
|
+
* Note what is NOT here: agency's `stakes( winner, bias )` — the consequence
|
|
2980
|
+
* of the specific choice under contest — is computed in
|
|
2981
|
+
* `agency/selection.scoring.ts` and never reaches a call. So a deliberation
|
|
2982
|
+
* facet currently reports the tick's general effort, not the stakes of the
|
|
2983
|
+
* choice it is deliberating. Carrying it is MODEL_ROUTING W1, still open.
|
|
2984
|
+
* This comment previously claimed deliberation passed those stakes; it does
|
|
2985
|
+
* not, and a doc comment that ships to npm is a bad place to be aspirational.
|
|
2986
|
+
*
|
|
2987
|
+
* Absent means UNKNOWN, not zero: a consumer must fall back to its default
|
|
2988
|
+
* rather than treat a missing value as "cheapest possible".
|
|
2989
|
+
*
|
|
2990
|
+
* This field is inert with respect to cognition. It rides along to whoever
|
|
2991
|
+
* resolves the model for a call; no engine may read it back and behave
|
|
2992
|
+
* differently, or the routing layer becomes a hidden input to the mind.
|
|
2993
|
+
*/
|
|
2994
|
+
demand?: number;
|
|
2627
2995
|
}
|
|
2996
|
+
/** Structurally background work — see `LLMCallMeta.demand`. */
|
|
2997
|
+
declare const BACKGROUND_DEMAND = 0.1;
|
|
2998
|
+
/**
|
|
2999
|
+
* Escalation is elevated by construction: the buffer only fires once something
|
|
3000
|
+
* has already failed to resolve on its own.
|
|
3001
|
+
*/
|
|
3002
|
+
declare const ESCALATION_DEMAND = 0.7;
|
|
2628
3003
|
declare class LLMDirector {
|
|
2629
3004
|
private _willId;
|
|
2630
3005
|
private _model;
|
|
@@ -2636,7 +3011,20 @@ declare class LLMDirector {
|
|
|
2636
3011
|
private _baseUrl;
|
|
2637
3012
|
private _timeoutMs;
|
|
2638
3013
|
private _tokenTracker;
|
|
3014
|
+
private _router;
|
|
3015
|
+
private _credentials;
|
|
3016
|
+
/** Default endpoint — what every call used before the routing seam existed. */
|
|
3017
|
+
private _defaultEndpoint;
|
|
3018
|
+
/** Routes already warned about (missing credential / bad provider) — log once. */
|
|
3019
|
+
private _routeWarned;
|
|
2639
3020
|
constructor(config: LLMDirectorConfig);
|
|
3021
|
+
/**
|
|
3022
|
+
* Resolve which model serves this call. Falls back to the default endpoint
|
|
3023
|
+
* whenever the router has no opinion, throws, or names a provider we hold no
|
|
3024
|
+
* credential for — degrade, never crash.
|
|
3025
|
+
*/
|
|
3026
|
+
private _resolveEndpoint;
|
|
3027
|
+
private _warnRouteOnce;
|
|
2640
3028
|
/**
|
|
2641
3029
|
* Returns a structurally valid executive output with zero API cost.
|
|
2642
3030
|
* Used when `mock: true` — e.g. for `bw_test_` key holders and the Playground.
|
|
@@ -2705,8 +3093,6 @@ declare class LLMDirector {
|
|
|
2705
3093
|
/** Cost-attribution tag for this call. Defaults to the master executive. */
|
|
2706
3094
|
meta?: LLMCallMeta): Promise<LLMCallResult>;
|
|
2707
3095
|
private _callProvider;
|
|
2708
|
-
/** Default API base URL (including version segment) for a provider. */
|
|
2709
|
-
private _baseFor;
|
|
2710
3096
|
/** Resolved API base: explicit override wins, else the provider default. */
|
|
2711
3097
|
private _resolvedBase;
|
|
2712
3098
|
/**
|
|
@@ -2866,6 +3252,18 @@ interface ExecutiveOutputFull {
|
|
|
2866
3252
|
name?: string;
|
|
2867
3253
|
learned?: string[];
|
|
2868
3254
|
feeling?: number;
|
|
3255
|
+
/**
|
|
3256
|
+
* "This is the same someone as that" — another keid I now believe is this
|
|
3257
|
+
* same referent, fusing two of my records into one.
|
|
3258
|
+
*
|
|
3259
|
+
* The mind's own verdict on an identity, and it may do what the recognition
|
|
3260
|
+
* heuristic will not: absorb an ESTABLISHED relationship. The heuristic is
|
|
3261
|
+
* right to refuse — fusing two real people who share a name would take one of
|
|
3262
|
+
* them's whole history — but the mind has evidence a name-match does not,
|
|
3263
|
+
* usually because somebody just told it. Without this, the same human
|
|
3264
|
+
* well-established on two channels stayed two people permanently.
|
|
3265
|
+
*/
|
|
3266
|
+
sameAs?: string;
|
|
2869
3267
|
}>;
|
|
2870
3268
|
newGoals?: Array<{
|
|
2871
3269
|
description: string;
|
|
@@ -2884,6 +3282,8 @@ interface ExecutiveOutputFull {
|
|
|
2884
3282
|
reason: string;
|
|
2885
3283
|
}>;
|
|
2886
3284
|
selfObservations?: string[];
|
|
3285
|
+
/** Compound actions the mind is naming as single skills (see ProposedSkill). */
|
|
3286
|
+
newSkills?: ProposedSkill[];
|
|
2887
3287
|
/**
|
|
2888
3288
|
* Plain-text reply from a conversation facet — populated by parseResponse()
|
|
2889
3289
|
* from the [REPLY_TEXT]...[/REPLY_TEXT] block.
|
|
@@ -2891,6 +3291,11 @@ interface ExecutiveOutputFull {
|
|
|
2891
3291
|
* Paragraphs (double-newline separated) map to separate reply bubbles.
|
|
2892
3292
|
*/
|
|
2893
3293
|
replyText?: string;
|
|
3294
|
+
/**
|
|
3295
|
+
* Set when the facet declared it is NOT speaking this cycle, carrying why.
|
|
3296
|
+
* Present ⇒ nothing is sent, whatever else the response contains.
|
|
3297
|
+
*/
|
|
3298
|
+
noMessage?: string;
|
|
2894
3299
|
/**
|
|
2895
3300
|
* @deprecated Legacy JSON reply format — no longer emitted by conversation facets.
|
|
2896
3301
|
* Kept for backward compatibility with any tests/tooling that inspect parsed output.
|
|
@@ -2940,6 +3345,24 @@ interface ExecutiveEngineConfig$1 {
|
|
|
2940
3345
|
cooldownTicks?: number;
|
|
2941
3346
|
bus?: CognitiveBus;
|
|
2942
3347
|
}
|
|
3348
|
+
/**
|
|
3349
|
+
* A compound action the mind names as one thing it does — "when I do A then B,
|
|
3350
|
+
* that is <name>". Registered into the SchemaRepertoire as a composite, after
|
|
3351
|
+
* which it competes as a single affordance and can proceduralize into a habit.
|
|
3352
|
+
*
|
|
3353
|
+
* This is the creation seam for the instrumental→habitual gradient. Before it,
|
|
3354
|
+
* `agency.composite.proposed` was subscribed by ReafferenceEngine — whose handler
|
|
3355
|
+
* is the only caller of `registerComposite()` anywhere — and published by nothing,
|
|
3356
|
+
* so no Will could ever hold a skill beyond the innate floor (#114).
|
|
3357
|
+
*/
|
|
3358
|
+
interface ProposedSkill {
|
|
3359
|
+
/** What the mind calls it. Becomes the schema id. */
|
|
3360
|
+
id: string;
|
|
3361
|
+
/** The sub-schemas it is made of, in order. Two or more, or it is not compound. */
|
|
3362
|
+
composedOf: string[];
|
|
3363
|
+
tags?: string[];
|
|
3364
|
+
cost?: number;
|
|
3365
|
+
}
|
|
2943
3366
|
|
|
2944
3367
|
/**
|
|
2945
3368
|
* PromptFactory — single source of truth for all executive prompts
|
|
@@ -2996,7 +3419,7 @@ interface FocusSection {
|
|
|
2996
3419
|
* into the facet's LLM calls as `LLMCallMeta.function` so the TokenTracker can
|
|
2997
3420
|
* break spend down per facet type. Defaults to 'facet' when unset.
|
|
2998
3421
|
*/
|
|
2999
|
-
function?:
|
|
3422
|
+
function?: LLMCallFunction;
|
|
3000
3423
|
/**
|
|
3001
3424
|
* Optional: Custom output format to append instead of the standard executive format.
|
|
3002
3425
|
* Pass via PromptBuildOptions.outputFormat when building the user message.
|
|
@@ -3027,6 +3450,18 @@ interface FocusSection {
|
|
|
3027
3450
|
* only sees that person's plans. When unset, those sections show all.
|
|
3028
3451
|
*/
|
|
3029
3452
|
awarenessEntityId?: string;
|
|
3453
|
+
/**
|
|
3454
|
+
* Optional: WHO this facet is engaged with — the keid and the name the mind has
|
|
3455
|
+
* learned for them. Reported back to the master on every `executive.facet.sync`.
|
|
3456
|
+
*
|
|
3457
|
+
* Without it the master was told, in its own system prompt, that "focused facets
|
|
3458
|
+
* may run simultaneously… their reasoning syncs back to me" while the sync payload
|
|
3459
|
+
* carried only a facetId and a confidence number — so a mind holding two live
|
|
3460
|
+
* conversations could not tell you whose they were. The master is the singular
|
|
3461
|
+
* seat: it has to know who is at the table to reason about them together.
|
|
3462
|
+
*/
|
|
3463
|
+
subjectEntityId?: string;
|
|
3464
|
+
subjectName?: string;
|
|
3030
3465
|
/**
|
|
3031
3466
|
* Optional: Provided by the creating engine to convert the LLM's parsed output
|
|
3032
3467
|
* into a domain-specific decision payload.
|
|
@@ -3053,6 +3488,18 @@ interface FacetReport {
|
|
|
3053
3488
|
contextId?: string;
|
|
3054
3489
|
/** Optional dynamic instructions to append to the user message */
|
|
3055
3490
|
instructions?: string;
|
|
3491
|
+
/**
|
|
3492
|
+
* Attend to something else for THIS report only, leaving the facet's standing
|
|
3493
|
+
* focus untouched.
|
|
3494
|
+
*
|
|
3495
|
+
* A facet's focus was a single mutable field, so anything that wanted a live
|
|
3496
|
+
* facet to consider one different thing had to `setFocus()` first — clobbering
|
|
3497
|
+
* whatever the facet was already set up for, and racing with any report already
|
|
3498
|
+
* queued behind it. That is why a self-initiated message to someone the mind was
|
|
3499
|
+
* ALREADY talking to had to be composed by a separate, transient facet that could
|
|
3500
|
+
* not see the live conversation at all.
|
|
3501
|
+
*/
|
|
3502
|
+
focus?: FocusSection;
|
|
3056
3503
|
}
|
|
3057
3504
|
interface FacetDecision {
|
|
3058
3505
|
facetId: string;
|
|
@@ -3062,6 +3509,16 @@ interface FacetDecision {
|
|
|
3062
3509
|
decision: unknown;
|
|
3063
3510
|
reasoning: string;
|
|
3064
3511
|
confidence: number;
|
|
3512
|
+
/**
|
|
3513
|
+
* Sim tick this decision was reasoned at.
|
|
3514
|
+
*
|
|
3515
|
+
* The facet has always known it and never passed it on, so a subscriber writing
|
|
3516
|
+
* state in response had no deterministic clock and reached for a process-local
|
|
3517
|
+
* counter instead — which resets on restart and collides. Never wall-clock: this
|
|
3518
|
+
* reaches ids that live in state, and a wall-clock id makes recorded and replayed
|
|
3519
|
+
* runs diverge (R2).
|
|
3520
|
+
*/
|
|
3521
|
+
tick: number;
|
|
3065
3522
|
}
|
|
3066
3523
|
type FacetEventListener = (decision: FacetDecision) => void;
|
|
3067
3524
|
interface ExecutiveFacetHandle {
|
|
@@ -3095,6 +3552,44 @@ interface ExecutiveFacetHandle {
|
|
|
3095
3552
|
onReaped: (handler: () => void) => void;
|
|
3096
3553
|
}
|
|
3097
3554
|
|
|
3555
|
+
/**
|
|
3556
|
+
* DeliberationCache — types and contracts.
|
|
3557
|
+
*
|
|
3558
|
+
* The cache stores past executive outputs keyed by a deterministic
|
|
3559
|
+
* cognitive fingerprint. It is pure, deterministic, and R2-safe:
|
|
3560
|
+
* the same state + same history ⇒ same retrieval + same composition.
|
|
3561
|
+
*
|
|
3562
|
+
* Scope note: Phase 1 caches the ACTIONS block only. The composed output
|
|
3563
|
+
* is a valid `ExecutiveOutputFull` carrying the three required fields
|
|
3564
|
+
* (actions, reasoning, confidence) plus whatever optional blocks the
|
|
3565
|
+
* enabled scopes cover. Everything else stays undefined and the existing
|
|
3566
|
+
* downstream (`buildStateCommands`) treats it as "nothing to do", which is
|
|
3567
|
+
* exactly the intended Phase-1 behaviour.
|
|
3568
|
+
*/
|
|
3569
|
+
|
|
3570
|
+
/** Which blocks of the executive output the cache may synthesise. */
|
|
3571
|
+
type CacheScope = 'actions' | 'goals' | 'beliefs';
|
|
3572
|
+
interface DeliberationCacheConfig {
|
|
3573
|
+
/** Maximum patterns to retain. Lowest (competence × recency) evicted when full. */
|
|
3574
|
+
maxPatterns?: number;
|
|
3575
|
+
/** Neighbors retrieved for composition. */
|
|
3576
|
+
k?: number;
|
|
3577
|
+
/** Minimum similarity for a stored pattern to count as a neighbor. */
|
|
3578
|
+
minSimilarity?: number;
|
|
3579
|
+
/** Confidence threshold θ — cache hit requires ρ ≥ θ. Start conservative. */
|
|
3580
|
+
theta?: number;
|
|
3581
|
+
/** Temperature for softmax weights over neighbors. */
|
|
3582
|
+
tau?: number;
|
|
3583
|
+
/** Learning rate (EMA) for competence updates. */
|
|
3584
|
+
eta?: number;
|
|
3585
|
+
/** Competence decay per executive cycle (applied via decay()). */
|
|
3586
|
+
decayPerCycle?: number;
|
|
3587
|
+
/** Verify 1-in-N cache hits against the LLM (0 = never). */
|
|
3588
|
+
verifyEveryNHits?: number;
|
|
3589
|
+
/** Which output blocks to synthesise. Phase 1 default: ['actions']. */
|
|
3590
|
+
scopes?: CacheScope[];
|
|
3591
|
+
}
|
|
3592
|
+
|
|
3098
3593
|
interface ExecutiveEngineConfig {
|
|
3099
3594
|
executiveInterval?: number;
|
|
3100
3595
|
cooldownTicks?: number;
|
|
@@ -3108,20 +3603,26 @@ declare class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
|
|
|
3108
3603
|
private _consumedBufferEntries;
|
|
3109
3604
|
private _llmDirector;
|
|
3110
3605
|
private _testMode;
|
|
3111
|
-
private _messageQueue;
|
|
3112
3606
|
private _recentActionTypes;
|
|
3113
3607
|
private _coherenceVersion;
|
|
3114
3608
|
private _lastEpistemicUncertainty;
|
|
3115
3609
|
private _lastExecutiveOutput;
|
|
3116
3610
|
private _lastExecutiveTick;
|
|
3611
|
+
private _cache;
|
|
3612
|
+
private _cacheRestored;
|
|
3613
|
+
private _pendingVerify;
|
|
3614
|
+
private _lastCacheHit;
|
|
3615
|
+
private _lastCacheConfidence;
|
|
3616
|
+
private _lastCacheNeighborCount;
|
|
3117
3617
|
private _willId;
|
|
3118
|
-
/**
|
|
3119
|
-
|
|
3618
|
+
/**
|
|
3619
|
+
* The Will's default model (config.model's `executive` role, resolved in
|
|
3620
|
+
* mind.ts). Every other role reaches its model through the router — see
|
|
3621
|
+
* `compileRoleRouter`.
|
|
3622
|
+
*/
|
|
3623
|
+
private _modelId;
|
|
3120
3624
|
/** Per-Will LLM transport overrides (config.llm) — env fallbacks apply per field. */
|
|
3121
3625
|
private _llm;
|
|
3122
|
-
/** One director per distinct model — same config, different model. Shared
|
|
3123
|
-
* tracker/recorder/willId, so ledger attribution and replay hold per role. */
|
|
3124
|
-
private _directorCache;
|
|
3125
3626
|
private _workingMemory;
|
|
3126
3627
|
private _goalManager;
|
|
3127
3628
|
private _episodicConsolidator;
|
|
@@ -3134,11 +3635,28 @@ declare class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
|
|
|
3134
3635
|
private _inbox;
|
|
3135
3636
|
private _tokenTracker;
|
|
3136
3637
|
private readonly _facetSupervisor;
|
|
3137
|
-
|
|
3638
|
+
/**
|
|
3639
|
+
* Who each live facet is engaged with, learned from `executive.facet.sync`.
|
|
3640
|
+
* Keyed by facetId; the last sync wins. Rendered into the master's own prompt so
|
|
3641
|
+
* the singular seat can reason across its conversations "as if they were sitting
|
|
3642
|
+
* at the same table" — which it cannot do while it only knows facet numbers.
|
|
3643
|
+
* Stale entries age out on read (see _activeConversations).
|
|
3644
|
+
*/
|
|
3645
|
+
private _facetSubjects;
|
|
3138
3646
|
private readonly _model;
|
|
3139
3647
|
private readonly _generativeModel;
|
|
3140
3648
|
private _summarizerRestored;
|
|
3141
3649
|
private _lastStateRef;
|
|
3650
|
+
/**
|
|
3651
|
+
* The tick currently being processed, refreshed every react() — distinct from
|
|
3652
|
+
* `_lastStateRef` (which tracks the REASONING tick and must not move under
|
|
3653
|
+
* onReasoningComplete) and from `_lastExecutiveTick` (the last cycle that ran).
|
|
3654
|
+
*
|
|
3655
|
+
* Off-tick arrivals — a facet handoff, in particular — need to be stamped with
|
|
3656
|
+
* when they actually happened. Using `_lastExecutiveTick` for that dated them to
|
|
3657
|
+
* the last master cycle, which can be hundreds of ticks behind.
|
|
3658
|
+
*/
|
|
3659
|
+
private _currentTick;
|
|
3142
3660
|
private readonly _deferred;
|
|
3143
3661
|
private _chunkBroadcaster;
|
|
3144
3662
|
private readonly _escalations;
|
|
@@ -3164,19 +3682,15 @@ declare class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
|
|
|
3164
3682
|
*/
|
|
3165
3683
|
attachCompletionInbox(inbox: CompletionInbox): void;
|
|
3166
3684
|
set willId(willId: string);
|
|
3167
|
-
/**
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
summarizer: string | null;
|
|
3177
|
-
deliberation: string | null;
|
|
3178
|
-
conversation: string | null;
|
|
3179
|
-
};
|
|
3685
|
+
/**
|
|
3686
|
+
* The Will's default model. Set before the first tick.
|
|
3687
|
+
*
|
|
3688
|
+
* This replaced a four-role map (W7): the other roles are routing rules now,
|
|
3689
|
+
* compiled in mind.ts, so the engine holds one model and one router rather
|
|
3690
|
+
* than a model per role plus a router.
|
|
3691
|
+
*/
|
|
3692
|
+
set modelId(id: string | null);
|
|
3693
|
+
get modelId(): string | null;
|
|
3180
3694
|
/** Per-Will LLM transport overrides (config.llm). Set before the first tick. */
|
|
3181
3695
|
set llm(c: {
|
|
3182
3696
|
provider?: string;
|
|
@@ -3184,9 +3698,10 @@ declare class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
|
|
|
3184
3698
|
baseUrl?: string;
|
|
3185
3699
|
maxOutputTokens?: number;
|
|
3186
3700
|
timeoutMs?: number;
|
|
3701
|
+
credentials?: Partial<Record<string, ProviderCredential>>;
|
|
3702
|
+
router?: ModelRouter | null;
|
|
3703
|
+
wire?: LLMWire;
|
|
3187
3704
|
} | null);
|
|
3188
|
-
/** The executive-role model id (back-compat read). */
|
|
3189
|
-
get modelId(): string | null;
|
|
3190
3705
|
get latestOutput(): ExecutiveOutputFull | null;
|
|
3191
3706
|
isFresh(currentTick: Tick): boolean;
|
|
3192
3707
|
/**
|
|
@@ -3202,11 +3717,56 @@ declare class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
|
|
|
3202
3717
|
* and subscribe() to receive facet decisions.
|
|
3203
3718
|
*/
|
|
3204
3719
|
/** Get-or-create the director for a model id (shared config, per-Will). */
|
|
3205
|
-
|
|
3206
|
-
|
|
3720
|
+
/**
|
|
3721
|
+
* The provider, from config or environment — never guessed.
|
|
3722
|
+
*
|
|
3723
|
+
* This used to default to 'anthropic', which is how a Will configured for one
|
|
3724
|
+
* vendor could quietly talk to another. An unset provider is a configuration
|
|
3725
|
+
* error, and saying so at construction is far cheaper than a 401 mid-tick.
|
|
3726
|
+
*/
|
|
3727
|
+
private _requireProvider;
|
|
3728
|
+
/**
|
|
3729
|
+
* True when this Will cannot make a live call, so provider/model are not
|
|
3730
|
+
* required: mock mode, or a replay re-feeding recorded completions.
|
|
3731
|
+
*/
|
|
3732
|
+
private _noLiveCalls;
|
|
3733
|
+
/**
|
|
3734
|
+
* Build this Will's one and only director.
|
|
3735
|
+
*
|
|
3736
|
+
* There used to be a cache of them, keyed by model, because the per-role
|
|
3737
|
+
* model map had no other way to make a role use a different model. Routing
|
|
3738
|
+
* gave it one — the role map now compiles to rules (see `compileRoleRouter`)
|
|
3739
|
+
* and a single director resolves every call's endpoint per call. That is also
|
|
3740
|
+
* strictly more faithful: a facet follows the work it is doing rather than
|
|
3741
|
+
* whatever role it happened to be spawned under.
|
|
3742
|
+
*/
|
|
3743
|
+
private _buildDirector;
|
|
3744
|
+
/**
|
|
3745
|
+
* Spawn a facet.
|
|
3746
|
+
*
|
|
3747
|
+
* `role` declares the facet's intent at the call site. It no longer selects a
|
|
3748
|
+
* model: that used to happen here, pinning a facet for life to whatever role
|
|
3749
|
+
* it was spawned under, and it now happens per call from the focus function
|
|
3750
|
+
* the caller sets immediately afterwards (W7). The two always agreed — every
|
|
3751
|
+
* spawn site sets a focus whose `function` matches its role — so the routed
|
|
3752
|
+
* answer is the same one, decided later and from the work itself.
|
|
3753
|
+
*/
|
|
3754
|
+
spawnFacet(role?: 'deliberation' | 'conversation' | 'outreach' | 'supervision',
|
|
3755
|
+
/**
|
|
3756
|
+
* What this facet is FOR — see `FacetSpawnDeps.key`. Two spawns with the same
|
|
3757
|
+
* key get the same facet, so callers no longer each invent their own dedup
|
|
3758
|
+
* (and `authorOutreach`, which had none, no longer opens a rival facet on a
|
|
3759
|
+
* person the mind is already talking to).
|
|
3760
|
+
*/
|
|
3761
|
+
key?: string): {
|
|
3207
3762
|
attention: 'available' | 'full';
|
|
3208
3763
|
handle?: ExecutiveFacetHandle;
|
|
3209
3764
|
};
|
|
3765
|
+
/**
|
|
3766
|
+
* The facet already attending to `key`, if one is open — without spawning.
|
|
3767
|
+
* See FacetSupervisor.handleFor.
|
|
3768
|
+
*/
|
|
3769
|
+
facetFor(key: string): ExecutiveFacetHandle | undefined;
|
|
3210
3770
|
subscribes(): string[];
|
|
3211
3771
|
publishes(): CognitiveEventSchema[];
|
|
3212
3772
|
snapshot(): Record<string, unknown>;
|
|
@@ -3218,12 +3778,119 @@ declare class ExecutiveEngine extends AsyncEngine implements CognitiveEngine {
|
|
|
3218
3778
|
* its `executive.last_tick` metric reflects whether our prior commands landed.
|
|
3219
3779
|
*/
|
|
3220
3780
|
react(delta: Duration, tick: Tick, state: ReadonlySimulationState, context: SimulationContext): Promise<EngineResult>;
|
|
3781
|
+
/**
|
|
3782
|
+
* What the mind is attending to because a facet is reasoning about it, as
|
|
3783
|
+
* `attention.demand` entities the AttentionAllocator allocates real capacity
|
|
3784
|
+
* against (`_extractSalienceSignals` reads this type; `costPerFocus` is then
|
|
3785
|
+
* charged against the same 100-unit budget as perceptual foci).
|
|
3786
|
+
*
|
|
3787
|
+
* This closes a loop that was open in one direction only: the allocator's
|
|
3788
|
+
* `freeFraction` scaled the facet budget, but facets never appeared in
|
|
3789
|
+
* `_activeFocus`, so holding three conversations reported exactly as much spare
|
|
3790
|
+
* attention as holding none. The budget was being scaled by a signal blind to the
|
|
3791
|
+
* thing it was bounding.
|
|
3792
|
+
*
|
|
3793
|
+
* `urgency` sits below 1 on purpose: a live conversation is a genuine claim on
|
|
3794
|
+
* attention but must not automatically outrank every percept — the allocator sorts
|
|
3795
|
+
* candidates by salience into `maxFoci` slots, and a facet that always won would
|
|
3796
|
+
* starve perception. Only BUSY facets are charged; an open-but-quiet thread is one
|
|
3797
|
+
* the mind is in, not one it is attending to.
|
|
3798
|
+
*/
|
|
3799
|
+
private _facetAttentionDemands;
|
|
3221
3800
|
protected shouldAct(state: ReadonlySimulationState, tick: Tick, _context: SimulationContext): boolean;
|
|
3222
3801
|
protected readState(state: ReadonlySimulationState, tick: Tick): ReasoningFootprint;
|
|
3223
3802
|
protected reasonAsync(footprint: ReasoningFootprint, state: ReadonlySimulationState, context: SimulationContext, stream: IntermediateStream): Promise<unknown>;
|
|
3224
3803
|
protected onIntermediateResult(step: string, result: unknown, _footprint: ReasoningFootprint, _context: SimulationContext): StateCommands | null;
|
|
3225
3804
|
protected onReasoningComplete(output: unknown, footprint: ReasoningFootprint, _context: SimulationContext): StateCommands;
|
|
3226
|
-
|
|
3805
|
+
/**
|
|
3806
|
+
* The people the mind is in conversation with right now, newest first.
|
|
3807
|
+
*
|
|
3808
|
+
* Pruned against the supervisor's live facets on every read: a reaped facet is a
|
|
3809
|
+
* conversation that has ended, and a master that still believes it is mid-thread
|
|
3810
|
+
* with someone reasons about a table that is no longer there.
|
|
3811
|
+
*/
|
|
3812
|
+
private _activeConversations;
|
|
3813
|
+
/**
|
|
3814
|
+
* Facet sync — remember WHO each facet is with, and wake the master.
|
|
3815
|
+
*
|
|
3816
|
+
* Reached from `onCognitiveEvent`, NOT from its own `bus.subscribe`. The bus
|
|
3817
|
+
* stores one subscription per engineId (`_subscriptions.set( engineId, … )`),
|
|
3818
|
+
* so a second `subscribe(this.name, …)` silently REPLACES the first — and the
|
|
3819
|
+
* orchestrator registers `subscribe( engine.name, engine.subscribes(), … )`
|
|
3820
|
+
* after `attachBus`, which replaced everything registered here. Two dedicated
|
|
3821
|
+
* handlers used to be installed at this point; the second overwrote the first
|
|
3822
|
+
* and the orchestrator then overwrote that, so neither ever ran. The escalation
|
|
3823
|
+
* leg had been dead in production for its whole life: a facet could escalate,
|
|
3824
|
+
* the audition engine published, and nothing was listening.
|
|
3825
|
+
*/
|
|
3826
|
+
/**
|
|
3827
|
+
* Retire undertakings the mind has already honoured, and refuse to restate one
|
|
3828
|
+
* it is already carrying.
|
|
3829
|
+
*
|
|
3830
|
+
* An undertaking percept says, in the first person, "I said I would reach X and
|
|
3831
|
+
* nothing has gone to them yet". That sentence has to stop being true at some
|
|
3832
|
+
* point, and nothing made it stop. Measured on a live Will: SEVEN of them
|
|
3833
|
+
* accumulated in state, every one still asserting nothing had been sent, while
|
|
3834
|
+
* a `conversation.sent` to that person sat right beside them. She read seven
|
|
3835
|
+
* standing unfulfilled promises every cycle and dutifully sent the same message
|
|
3836
|
+
* again, five times in five minutes and once more in the next session — the
|
|
3837
|
+
* percept meant to stop her forgetting a promise was making her unable to
|
|
3838
|
+
* believe she had kept it.
|
|
3839
|
+
*
|
|
3840
|
+
* Discharged by EVIDENCE, not by a timer: a `conversation.sent` to that target,
|
|
3841
|
+
* written no earlier than the undertaking, means the contact happened. That
|
|
3842
|
+
* record is durable and snapshots with the state, so the discharge survives a
|
|
3843
|
+
* restart exactly as the promise does — which the tick-scoped satiation in
|
|
3844
|
+
* `enactionFootprint` deliberately cannot.
|
|
3845
|
+
*
|
|
3846
|
+
* It stays a decision, not an erasure. Retiring the percept removes the standing
|
|
3847
|
+
* claim that the words are unsent; whether to say more to that person is then an
|
|
3848
|
+
* ordinary competition like any other.
|
|
3849
|
+
*/
|
|
3850
|
+
private _reconcileUndertakings;
|
|
3851
|
+
private _onFacetSync;
|
|
3852
|
+
/**
|
|
3853
|
+
* A focused part of me surfaced something the singular seat owns — work to plan
|
|
3854
|
+
* (`escalation`) or an intention toward a third party (`undertaking`).
|
|
3855
|
+
*
|
|
3856
|
+
* ONE handler for every facet type. This was `_onAuditionTaskSignal`, listening
|
|
3857
|
+
* on a topic named for one sense engine and typed with one sense engine's nouns
|
|
3858
|
+
* (`entityId`, `threadId`), which meant a planning, supervision or deliberation
|
|
3859
|
+
* facet had no way to hand anything up at all. See EscalationBuffer for the full
|
|
3860
|
+
* rationale; new kinds go in `HandoffBody`, not in a new topic and a new handler
|
|
3861
|
+
* beside this one.
|
|
3862
|
+
*
|
|
3863
|
+
* Master stays out of the reply path entirely:
|
|
3864
|
+
* • The facet has already said (or will say) whatever the person in front of
|
|
3865
|
+
* it needed to hear.
|
|
3866
|
+
* • The master's job is purely cognitive: create a [PLANS] block, update
|
|
3867
|
+
* goals, reflect, or decide whether it still means to make that contact.
|
|
3868
|
+
* Any follow-up communication flows through the agency competition —
|
|
3869
|
+
* NEVER via [REPLY].
|
|
3870
|
+
*
|
|
3871
|
+
* Buffered rather than written directly: state is read-only here, so
|
|
3872
|
+
* `EscalationBuffer.drainToPercepts()` emits it as a StateCommand on the next
|
|
3873
|
+
* master cycle, where Exteroception surfaces it under "## Percepts (What I Notice)".
|
|
3874
|
+
*/
|
|
3875
|
+
private _onFacetHandoff;
|
|
3876
|
+
/** Enable the deliberation cache (off by default). Call during mind assembly. */
|
|
3877
|
+
enableCache(config?: DeliberationCacheConfig): void;
|
|
3878
|
+
/** True when the cache is active. */
|
|
3879
|
+
get cacheEnabled(): boolean;
|
|
3880
|
+
/** Telemetry snapshot for harnesses / eval. Null when disabled. */
|
|
3881
|
+
cacheStats(): {
|
|
3882
|
+
size: number;
|
|
3883
|
+
hits: number;
|
|
3884
|
+
misses: number;
|
|
3885
|
+
} | null;
|
|
3886
|
+
/**
|
|
3887
|
+
* Reafference hook — update cache competence from a confirmed action outcome.
|
|
3888
|
+
* Optional, layered on top of the inline verify loop. Reward follows the
|
|
3889
|
+
* research sketch: mean of (action succeeded, stress relief, goal progress).
|
|
3890
|
+
*/
|
|
3891
|
+
onActionOutcome(state: ReadonlySimulationState, tick: Tick, success: boolean, stressDelta: number, goalProgressDelta: number): void;
|
|
3892
|
+
private _actionTypesMatch;
|
|
3893
|
+
private _restoreDeliberationCache;
|
|
3227
3894
|
private _restoreSummarizer;
|
|
3228
3895
|
}
|
|
3229
3896
|
|
|
@@ -3837,6 +4504,13 @@ declare class ThreatEvaluator implements SimulationEngine, CognitiveEngine {
|
|
|
3837
4504
|
* metadata.hostile === true). Updates _threatFromHostile and re-emits
|
|
3838
4505
|
* the full threat/emotion metrics so that downstream engines always see
|
|
3839
4506
|
* a current picture even when no bus event arrives.
|
|
4507
|
+
*
|
|
4508
|
+
* `threat` is a HOST SEAM, not a starved input (#114). No core engine writes
|
|
4509
|
+
* one — appraisal runs entirely off this engine's six bus inputs (energy,
|
|
4510
|
+
* sleep, stress, novelty, metacognition, prediction), all of which are live.
|
|
4511
|
+
* A host embedding a Will in a world with actual hostile agents writes `threat`
|
|
4512
|
+
* entities to make them felt. Empty here means nothing is hostile, not that
|
|
4513
|
+
* nothing is wired.
|
|
3840
4514
|
*/
|
|
3841
4515
|
react(_delta: Duration, _tick: Tick, state: ReadonlySimulationState, _context: SimulationContext): Promise<EngineResult>;
|
|
3842
4516
|
private _computeScarcityThreat;
|
|
@@ -4696,6 +5370,8 @@ declare class SelfModelUpdater extends AsyncEngine implements CognitiveEngine {
|
|
|
4696
5370
|
private _affectObservations;
|
|
4697
5371
|
private _bus;
|
|
4698
5372
|
private _semanticIntegrator;
|
|
5373
|
+
/** The reasoning tick's state — onReasoningComplete needs it to merge identity. */
|
|
5374
|
+
private _lastStateRef;
|
|
4699
5375
|
private readonly _model;
|
|
4700
5376
|
constructor(config?: SelfModelUpdaterConfig);
|
|
4701
5377
|
attachBus(bus: CognitiveBus): void;
|
|
@@ -5275,6 +5951,19 @@ interface Reputation {
|
|
|
5275
5951
|
negativeInteractions: number;
|
|
5276
5952
|
lastInteractionTick: Tick;
|
|
5277
5953
|
confidence: number;
|
|
5954
|
+
/**
|
|
5955
|
+
* Everything the mind has OBSERVED about this person, acts and silences alike.
|
|
5956
|
+
*
|
|
5957
|
+
* `interactionCount` counts acts, and only acts — a silence must never inflate
|
|
5958
|
+
* it or the mind remembers conversations that never happened. But confidence is
|
|
5959
|
+
* about how much evidence a read rests on, and a silence is evidence. Counting
|
|
5960
|
+
* only acts meant someone who never answers could never be confidently known as
|
|
5961
|
+
* someone who never answers, which is precisely the read worth holding.
|
|
5962
|
+
*
|
|
5963
|
+
* Rises in lockstep with `interactionCount` on the interaction path, so a mind
|
|
5964
|
+
* that has only ever been spoken to behaves exactly as it did before.
|
|
5965
|
+
*/
|
|
5966
|
+
observations: number;
|
|
5278
5967
|
}
|
|
5279
5968
|
declare class ReputationTracker implements SimulationEngine, CognitiveEngine {
|
|
5280
5969
|
readonly name = "reputation-tracker";
|
|
@@ -5286,6 +5975,8 @@ declare class ReputationTracker implements SimulationEngine, CognitiveEngine {
|
|
|
5286
5975
|
/** True after reputations have been rehydrated from persisted state on first tick. */
|
|
5287
5976
|
private _restored;
|
|
5288
5977
|
private _pendingInteractions;
|
|
5978
|
+
/** Whether someone answered when the mind spoke to them (ReafferenceEngine). */
|
|
5979
|
+
private _pendingResponsiveness;
|
|
5289
5980
|
private _bus;
|
|
5290
5981
|
private readonly _model;
|
|
5291
5982
|
constructor(config?: ReputationTrackerConfig);
|
|
@@ -5307,6 +5998,36 @@ declare class ReputationTracker implements SimulationEngine, CognitiveEngine {
|
|
|
5307
5998
|
private _prune;
|
|
5308
5999
|
}
|
|
5309
6000
|
|
|
6001
|
+
/**
|
|
6002
|
+
* A way this referent has been reachable, and what happened there.
|
|
6003
|
+
*
|
|
6004
|
+
* `kind` is the one fact that decides whether a room is the right place for a
|
|
6005
|
+
* given utterance, and it was being computed at the Discord edge (`isDM`) and
|
|
6006
|
+
* discarded before the mind could see it.
|
|
6007
|
+
*
|
|
6008
|
+
* `lastAnsweredTick` is evidence, not configuration — it arrives free from the
|
|
6009
|
+
* `social.responsiveness` signal. It is what lets the mind prefer the DM because
|
|
6010
|
+
* that is where this person actually answers, rather than because a constant in
|
|
6011
|
+
* the code says DMs rank higher.
|
|
6012
|
+
*/
|
|
6013
|
+
interface Handle {
|
|
6014
|
+
/** The transport address — what a channel bridge can actually deliver to. */
|
|
6015
|
+
keid: string;
|
|
6016
|
+
/**
|
|
6017
|
+
* 'dm' — a private thread. 'room' — somewhere others are listening. Left open
|
|
6018
|
+
* for a non-social referent, where the meaningful distinction is a different one.
|
|
6019
|
+
*/
|
|
6020
|
+
kind: 'dm' | 'room' | 'unknown';
|
|
6021
|
+
/** The place this handle lives in, once places are dossiers of their own. */
|
|
6022
|
+
place?: string;
|
|
6023
|
+
/** When the mind last SAID something here. */
|
|
6024
|
+
lastUsedTick?: Tick;
|
|
6025
|
+
/** When someone last answered it here — the only evidence that this route works. */
|
|
6026
|
+
lastAnsweredTick?: Tick;
|
|
6027
|
+
/** Free-form, so a host can mark what its own vocabulary cares about. */
|
|
6028
|
+
tags?: string[];
|
|
6029
|
+
}
|
|
6030
|
+
|
|
5310
6031
|
/**
|
|
5311
6032
|
* KnownEntityTracker — the cross-modal binder, and owner of the known-entity dossier.
|
|
5312
6033
|
*
|
|
@@ -5361,6 +6082,31 @@ interface KnownEntity {
|
|
|
5361
6082
|
lastSeenTick: Tick;
|
|
5362
6083
|
/** 0–1: how identified/coherent this referent is (a name + repeated encounters raise it). */
|
|
5363
6084
|
resolutionConfidence: number;
|
|
6085
|
+
/**
|
|
6086
|
+
* The ways this referent has been reachable, with the circumstances.
|
|
6087
|
+
*
|
|
6088
|
+
* Distinct from an ALIAS, and the distinction is load-bearing: an alias is
|
|
6089
|
+
* another NAME for the same referent (a transport user id), a handle is a
|
|
6090
|
+
* PLACE it can be reached (a thread, a room). One person has one identity and
|
|
6091
|
+
* several rooms, and conflating them is what made "which room should I say
|
|
6092
|
+
* this in?" unaskable.
|
|
6093
|
+
*/
|
|
6094
|
+
handles: Handle[];
|
|
6095
|
+
/**
|
|
6096
|
+
* Referents this one MIGHT be the same someone as, unresolved.
|
|
6097
|
+
*
|
|
6098
|
+
* A blocked merge used to vanish. `_recognise` will only absorb a THIN handle
|
|
6099
|
+
* into an established relationship — rightly, because fusing two real people
|
|
6100
|
+
* who share a name is the dangerous direction — so once the same human was
|
|
6101
|
+
* well-established on two channels they stayed two people permanently, and
|
|
6102
|
+
* nothing anywhere recorded the near-miss.
|
|
6103
|
+
*
|
|
6104
|
+
* A person does not silently fail here. They NOTICE — "hang on, is this the
|
|
6105
|
+
* same Mara?" — and then resolve it by asking. So the doubt is kept, shown, and
|
|
6106
|
+
* left for the mind to settle. Deliberately not a merge: this is a question,
|
|
6107
|
+
* and the answer is the mind's to give.
|
|
6108
|
+
*/
|
|
6109
|
+
suspectedSameAs?: string[];
|
|
5364
6110
|
}
|
|
5365
6111
|
declare class KnownEntityTracker implements SimulationEngine, CognitiveEngine {
|
|
5366
6112
|
readonly name = "known-entity-tracker";
|
|
@@ -5376,6 +6122,13 @@ declare class KnownEntityTracker implements SimulationEngine, CognitiveEngine {
|
|
|
5376
6122
|
private _pendingEncounters;
|
|
5377
6123
|
private _pendingConscious;
|
|
5378
6124
|
private _pendingOutcomes;
|
|
6125
|
+
/**
|
|
6126
|
+
* Aliases minted this tick, awaiting persistence. `_getOrCreate` runs deep inside
|
|
6127
|
+
* the drain loops with no access to the command list, and an alias that lives
|
|
6128
|
+
* only in memory is one the mind forgets on restart — every transport address
|
|
6129
|
+
* would mint a SECOND anchor next boot and the person would fork in two.
|
|
6130
|
+
*/
|
|
6131
|
+
private _mintedAliases;
|
|
5379
6132
|
private _bus;
|
|
5380
6133
|
private readonly _model;
|
|
5381
6134
|
constructor(config?: KnownEntityTrackerConfig);
|
|
@@ -5392,7 +6145,31 @@ declare class KnownEntityTracker implements SimulationEngine, CognitiveEngine {
|
|
|
5392
6145
|
snapshot(): Record<string, unknown>;
|
|
5393
6146
|
react(_delta: Duration, tick: Tick, state: ReadonlySimulationState, _ctx: SimulationContext): Promise<EngineResult>;
|
|
5394
6147
|
/** The dossier for a referent, if the Will has one. */
|
|
6148
|
+
/**
|
|
6149
|
+
* The dossier for anything that names this referent — its anchor, or any address
|
|
6150
|
+
* it has been met at.
|
|
6151
|
+
*
|
|
6152
|
+
* Alias-aware because a caller has no business knowing the anchor. This read
|
|
6153
|
+
* `_dossiers.get(keid)` raw, so the moment addresses became aliases of a minted
|
|
6154
|
+
* anchor, every caller holding a transport id got `undefined` — the mind would
|
|
6155
|
+
* have looked up someone it knows perfectly well and found a stranger. The
|
|
6156
|
+
* existing Phase-4 tests caught it, which is exactly what they are for.
|
|
6157
|
+
*/
|
|
5395
6158
|
getDossier(keid: string): KnownEntity | undefined;
|
|
6159
|
+
/**
|
|
6160
|
+
* Absorb `alias` into `canon` — one someone where there were two.
|
|
6161
|
+
*
|
|
6162
|
+
* Shared by the recognition heuristic and by the mind's own `sameAs` verdict,
|
|
6163
|
+
* because "these are the same person" must mean the same thing whichever
|
|
6164
|
+
* concluded it. The only difference is who is ENTITLED to conclude it: the
|
|
6165
|
+
* heuristic will not absorb an established relationship, the mind may, because
|
|
6166
|
+
* it has reasons a name-match does not — usually that somebody just told it.
|
|
6167
|
+
*
|
|
6168
|
+
* Routes MOVE. This used to delete the absorbed dossier and keep only a
|
|
6169
|
+
* redirect, so the mind concluded "same person" and in the same breath threw
|
|
6170
|
+
* away the second way to reach them.
|
|
6171
|
+
*/
|
|
6172
|
+
private _fuse;
|
|
5396
6173
|
/** Resolution confidence: a learned name plus repeated encounters identify a referent. */
|
|
5397
6174
|
private _resolution;
|
|
5398
6175
|
/**
|
|
@@ -5400,12 +6177,51 @@ declare class KnownEntityTracker implements SimulationEngine, CognitiveEngine {
|
|
|
5400
6177
|
* true if any merge happened. Pure + deterministic.
|
|
5401
6178
|
*/
|
|
5402
6179
|
private _recognise;
|
|
6180
|
+
/**
|
|
6181
|
+
* The dossier for a referent, minting its anchor the first time it is met.
|
|
6182
|
+
*
|
|
6183
|
+
* A transport address arriving here (`discord:1019…`) is not an identity, it is
|
|
6184
|
+
* a way the world happened to name someone. So it becomes an ALIAS of a fresh
|
|
6185
|
+
* `ke:` anchor, and the dossier lives under the anchor. Everything downstream —
|
|
6186
|
+
* reputation, theory-of-mind, attachment, goals, the PMA — keeps working
|
|
6187
|
+
* untouched: it still sees one opaque string per referent, which is simply no
|
|
6188
|
+
* longer a route. The same human met later on another channel resolves to this
|
|
6189
|
+
* same anchor instead of becoming a second person nobody could connect.
|
|
6190
|
+
*/
|
|
5403
6191
|
private _getOrCreate;
|
|
5404
6192
|
/** Keep the most-familiar dossiers; absence-faded acquaintances fall away (forgetting). */
|
|
6193
|
+
/**
|
|
6194
|
+
* Forget the least-held referents when over capacity.
|
|
6195
|
+
*
|
|
6196
|
+
* Ranked by more than exposure, deliberately. This sorted on `familiarity`
|
|
6197
|
+
* alone, which is MERE EXPOSURE — and now that a referent need not be a person
|
|
6198
|
+
* (a document, a repo, a room), things get far more exposure than people do. A
|
|
6199
|
+
* mind that touched sixty files would have evicted a colleague it speaks to
|
|
6200
|
+
* weekly in favour of a config file it opened a lot, silently, taking that
|
|
6201
|
+
* person's reputation, theory-of-mind model and attachment bond with it.
|
|
6202
|
+
*
|
|
6203
|
+
* So a referent the mind has actually got to know is stickier than one it has
|
|
6204
|
+
* merely seen often: knowing their NAME is the single strongest signal (it is
|
|
6205
|
+
* what distinguishes a someone from a blip), then how resolved the referent is,
|
|
6206
|
+
* then exposure. Nothing here is about being a person — a named, well-resolved
|
|
6207
|
+
* document outranks a glimpsed stranger, which is correct.
|
|
6208
|
+
*/
|
|
5405
6209
|
private _prune;
|
|
5406
6210
|
private _restoreFromState;
|
|
5407
6211
|
}
|
|
5408
6212
|
|
|
6213
|
+
/**
|
|
6214
|
+
* Referent → a deliverable address, and the room to use when none was chosen.
|
|
6215
|
+
*
|
|
6216
|
+
* Returns null when the referent is already an address (nothing to translate) or
|
|
6217
|
+
* when the mind holds no route at all — in which case the row goes out as-is and
|
|
6218
|
+
* the bridge's own roster fallback still applies, so a message is never silently
|
|
6219
|
+
* dropped for want of a handle.
|
|
6220
|
+
*/
|
|
6221
|
+
type OutboxRouting = (targetEntityId: string, chosenThread: string | undefined) => {
|
|
6222
|
+
targetEntityId: string;
|
|
6223
|
+
threadId?: string;
|
|
6224
|
+
} | null;
|
|
5409
6225
|
/** The caller-supplied fields of an outbox row; the writer stamps id + defaults. */
|
|
5410
6226
|
interface OutboxRow {
|
|
5411
6227
|
targetEntityId: string;
|
|
@@ -5427,11 +6243,24 @@ declare class OutboxWriter {
|
|
|
5427
6243
|
* which made the embedded ids in `conversation.sent` diverge every run).
|
|
5428
6244
|
*/
|
|
5429
6245
|
private _seq;
|
|
6246
|
+
private _routing;
|
|
5430
6247
|
constructor(opts?: {
|
|
5431
6248
|
outbox?: OutboxMessage[];
|
|
5432
6249
|
willId?: string;
|
|
5433
6250
|
});
|
|
5434
6251
|
attachSessionLogger(logger: SessionLogger | null): void;
|
|
6252
|
+
/**
|
|
6253
|
+
* Turn a referent into somewhere the world can actually be spoken to.
|
|
6254
|
+
*
|
|
6255
|
+
* Injected rather than read here, because this writer is deliberately dumb —
|
|
6256
|
+
* it holds no state and must stay replay-safe. Assembly closes over the state
|
|
6257
|
+
* manager (the same shape as `attachMemorySink`).
|
|
6258
|
+
*
|
|
6259
|
+
* This is the ONE seam both send paths cross: ProactiveCommunicator's
|
|
6260
|
+
* `enqueue()` and AuditionEngine's `enqueueReply()`. Translating anywhere else
|
|
6261
|
+
* would mean doing it twice and getting it wrong once.
|
|
6262
|
+
*/
|
|
6263
|
+
attachRouting(resolve: OutboxRouting | null): void;
|
|
5435
6264
|
private _genId;
|
|
5436
6265
|
/**
|
|
5437
6266
|
* Push one canonical outbox row and return its generated id. The single point
|
|
@@ -5533,6 +6362,18 @@ interface TextMessage {
|
|
|
5533
6362
|
content: string;
|
|
5534
6363
|
/** Display name — used in the facet focus content. */
|
|
5535
6364
|
speakerName?: string;
|
|
6365
|
+
/**
|
|
6366
|
+
* True when `threadId` is a PRIVATE thread — this someone and the mind, nobody
|
|
6367
|
+
* else listening. The single fact that decides whether a room is the right
|
|
6368
|
+
* place for a given utterance, and the Discord edge has always computed it
|
|
6369
|
+
* (`isDM`) and discarded it before the mind could see it: a follow-up promised
|
|
6370
|
+
* in a DM went out to a public channel, because the roster's "where did I last
|
|
6371
|
+
* see them" is a different question from "where did I promise this".
|
|
6372
|
+
*
|
|
6373
|
+
* Undefined means the channel did not say, which is honestly different from
|
|
6374
|
+
* false — an unknown room is not known to be public.
|
|
6375
|
+
*/
|
|
6376
|
+
direct?: boolean;
|
|
5536
6377
|
}
|
|
5537
6378
|
interface VoiceChunk {
|
|
5538
6379
|
kind: 'voice';
|
|
@@ -5716,6 +6557,12 @@ declare class AuditionEngine extends BaseSenseEngine {
|
|
|
5716
6557
|
* other percept uses. Wired to `stateManager.setEntity` in assembleMind().
|
|
5717
6558
|
*/
|
|
5718
6559
|
private _memorySink;
|
|
6560
|
+
/**
|
|
6561
|
+
* Sim tick of the most recent facet decision — the only deterministic clock this
|
|
6562
|
+
* off-tick engine has. Stamped from `FacetDecision.tick`, and used to key the
|
|
6563
|
+
* conversation records it writes into state.
|
|
6564
|
+
*/
|
|
6565
|
+
private _lastDecisionTick;
|
|
5719
6566
|
/** Speaker attachment strength accessor (0–1) — weights salience by relationship. */
|
|
5720
6567
|
private _getAttachmentScore;
|
|
5721
6568
|
/** Active-goal topic text accessor — for salience topic-overlap. */
|
|
@@ -5724,6 +6571,8 @@ declare class AuditionEngine extends BaseSenseEngine {
|
|
|
5724
6571
|
private _inflightInbound;
|
|
5725
6572
|
/** In-flight thread per entity — stamps chunk envelopes with the current threadId. */
|
|
5726
6573
|
private _inflightThread;
|
|
6574
|
+
/** Targets with an outreach being composed right now — see authorOutreach. */
|
|
6575
|
+
private _outreachInFlight;
|
|
5727
6576
|
attachExecutiveEngine(exec: ExecutiveEngine): void;
|
|
5728
6577
|
/**
|
|
5729
6578
|
* Inject the OutboxWriter so reply bubbles are delivered through the canonical
|
|
@@ -5767,7 +6616,7 @@ declare class AuditionEngine extends BaseSenseEngine {
|
|
|
5767
6616
|
attachAttachmentScore(fn: (entityId: string) => number): void;
|
|
5768
6617
|
/** Inject an active-goal topic-text accessor (reads GoalManager) for salience overlap. */
|
|
5769
6618
|
attachActiveGoalText(fn: () => string[]): void;
|
|
5770
|
-
/** Override: audition adds the master
|
|
6619
|
+
/** Override: audition adds the facet→master handoff to the base percept schema. */
|
|
5771
6620
|
publishes(): CognitiveEventSchema[];
|
|
5772
6621
|
snapshot(): Record<string, unknown>;
|
|
5773
6622
|
/**
|
|
@@ -5836,6 +6685,52 @@ declare class AuditionEngine extends BaseSenseEngine {
|
|
|
5836
6685
|
* (Section 1.2) routes ingest through the tick loop. The entity carries no
|
|
5837
6686
|
* wall-clock timestamp — `setEntity` stamps createdAt/tick from the sim clock.
|
|
5838
6687
|
*/
|
|
6688
|
+
/**
|
|
6689
|
+
* The inbound as a social signal in state — mirror of `conversation.sent`.
|
|
6690
|
+
*
|
|
6691
|
+
* Shaped for `SocialPerception._scanSocialSignals`, which reads `sourceKeid` for
|
|
6692
|
+
* who acted and `directedAtSelf` for whether it was aimed at us. Valence is left
|
|
6693
|
+
* UNSET on purpose: the words have not been appraised yet, and guessing a number
|
|
6694
|
+
* here would feed reputation and affect a sentiment nobody measured. Absent, the
|
|
6695
|
+
* scanner falls back to its neutral default, so the Will learns *that* someone
|
|
6696
|
+
* engaged (familiarity, recency, reliability) without inventing how it felt.
|
|
6697
|
+
*/
|
|
6698
|
+
/**
|
|
6699
|
+
* A durable, deterministic id for a conversation record.
|
|
6700
|
+
*
|
|
6701
|
+
* `<prefix>-<entity>-<tick>-<hash of the words>`. Every part earns its place:
|
|
6702
|
+
* • entity — whose conversation this is;
|
|
6703
|
+
* • tick — WHEN, from the sim clock, which resumes from the snapshot and so
|
|
6704
|
+
* keeps rising across restarts;
|
|
6705
|
+
* • hash — which utterance, so two things said to one person on one tick stay
|
|
6706
|
+
* two records.
|
|
6707
|
+
*
|
|
6708
|
+
* What it replaces was `<prefix>-<entity>-<N>` with N a process-local counter.
|
|
6709
|
+
* It restarted at 1 on every boot, so each session OVERWROTE the previous
|
|
6710
|
+
* session's records of the same person — a mind that had spoken with someone
|
|
6711
|
+
* across four restarts held one session's worth of evidence that it ever had.
|
|
6712
|
+
* Found by diffing a live snapshot against the Discord transcript it came from:
|
|
6713
|
+
* `conv-sent-reply-discord:1019…-1` held that morning's greeting, and every
|
|
6714
|
+
* earlier conversation keyed to the same id was simply gone.
|
|
6715
|
+
*
|
|
6716
|
+
* No wallClock: these ids live in state, and a wall-clock id makes the recorded
|
|
6717
|
+
* and replayed runs diverge (R2).
|
|
6718
|
+
*/
|
|
6719
|
+
private _sentKey;
|
|
6720
|
+
private _writeReceived;
|
|
6721
|
+
/**
|
|
6722
|
+
* Record that the mind SPOKE to someone, mirroring `_writeReceived`.
|
|
6723
|
+
*
|
|
6724
|
+
* Only ProactiveCommunicator wrote `conversation.sent`, so a reply — which is
|
|
6725
|
+
* most of what a Will says — left no durable trace of having spoken. Everything
|
|
6726
|
+
* that asks "have I already said something to them?" was therefore blind to
|
|
6727
|
+
* conversation: satiation could not damp repeating a relay delivered as a reply,
|
|
6728
|
+
* and an undertaking discharged inside a conversation stayed forever unkept,
|
|
6729
|
+
* which is exactly how the same message went out again and again.
|
|
6730
|
+
*
|
|
6731
|
+
* Speaking is speaking, whichever path carried it.
|
|
6732
|
+
*/
|
|
6733
|
+
private _writeSent;
|
|
5839
6734
|
private _persistExchangeMemory;
|
|
5840
6735
|
private _onFacetDecision;
|
|
5841
6736
|
/**
|
|
@@ -6012,6 +6907,30 @@ interface LearnedSkill {
|
|
|
6012
6907
|
lastEnactedTick: number;
|
|
6013
6908
|
}
|
|
6014
6909
|
|
|
6910
|
+
/**
|
|
6911
|
+
* WHY this denial is final — the distinction that makes a refusal learnable
|
|
6912
|
+
* rather than a wall to re-probe forever. Each value selects a different
|
|
6913
|
+
* cognitive fate; they are not degrees of one severity.
|
|
6914
|
+
*
|
|
6915
|
+
* • 'class' — the ACTION ITSELF is never permitted. Suppress the
|
|
6916
|
+
* affordance hard, erase any learned envelope, and let go of
|
|
6917
|
+
* a commitment currently deliberating toward it.
|
|
6918
|
+
* • 'parameter' — the action is fine; THESE ARGUMENTS were not (bound
|
|
6919
|
+
* exceeded, wrong target). Narrow the envelope the Will
|
|
6920
|
+
* reaches for; the ability stays.
|
|
6921
|
+
* • 'context' — the refusal was NOT ABOUT THE ACTION at all (tainted
|
|
6922
|
+
* context, unavailable dependency). Touch nothing: no
|
|
6923
|
+
* availability delta, no envelope, no competence.
|
|
6924
|
+
*
|
|
6925
|
+
* POLICY_REAFFERENCE P5 widened this from 'class' | 'instance' after the HELM
|
|
6926
|
+
* joint RFC ("Denials That Teach") identified that an instance-scoped refusal
|
|
6927
|
+
* splits in two, and that the two halves demand opposite responses. These are
|
|
6928
|
+
* OUR names for the distinctions, deliberately not HELM's wire spellings — see
|
|
6929
|
+
* the naming-boundary note in .TODO/POLICY_REAFFERENCE.md. A provider adapter
|
|
6930
|
+
* translates; this interface stays vendor-neutral.
|
|
6931
|
+
*/
|
|
6932
|
+
type DenialFinality = 'class' | 'parameter' | 'context';
|
|
6933
|
+
|
|
6015
6934
|
interface OutcomeObservation {
|
|
6016
6935
|
schema: string;
|
|
6017
6936
|
success: boolean;
|
|
@@ -6055,11 +6974,17 @@ declare class SchemaRepertoire {
|
|
|
6055
6974
|
availabilityOf(schema: string): number;
|
|
6056
6975
|
/**
|
|
6057
6976
|
* Fold a policy refusal into the availability layer (NOT competence). A
|
|
6058
|
-
* `class` refusal cuts availability hard;
|
|
6977
|
+
* `class` refusal cuts availability hard; a `parameter` refusal dents it
|
|
6059
6978
|
* lightly. Multiplicative so repeated refusals compound toward — but never
|
|
6060
6979
|
* reach — zero, keeping re-probe alive.
|
|
6980
|
+
*
|
|
6981
|
+
* `context` is EXCLUDED FROM THE SIGNATURE, not handled inside: a refusal
|
|
6982
|
+
* that was not about the action must never reach the availability layer at
|
|
6983
|
+
* all, and making that a type error rather than a convention means a future
|
|
6984
|
+
* caller cannot quietly re-introduce the dent. The routing decision lives in
|
|
6985
|
+
* the ReafferenceEngine's refused branch (P5).
|
|
6061
6986
|
*/
|
|
6062
|
-
recordRefusal(schema: string, finality:
|
|
6987
|
+
recordRefusal(schema: string, finality: Exclude<DenialFinality, 'context'>, tick: number): number;
|
|
6063
6988
|
/**
|
|
6064
6989
|
* Fold one outcome into the schema's learned skill. Returns the updated skill
|
|
6065
6990
|
* and whether it just crossed the proceduralization threshold this update.
|
|
@@ -6112,6 +7037,16 @@ declare class AffordanceSynthesizer implements CognitiveEngine {
|
|
|
6112
7037
|
private _schemas;
|
|
6113
7038
|
private _skills;
|
|
6114
7039
|
private _repertoire;
|
|
7040
|
+
/**
|
|
7041
|
+
* This tick's live consequence descriptors — the acts the mind has performed
|
|
7042
|
+
* whose outcome has not yet come back. Refreshed once at the top of react()
|
|
7043
|
+
* because `_build` runs per candidate and reading them is a full-entity scan.
|
|
7044
|
+
*/
|
|
7045
|
+
private _inFlight;
|
|
7046
|
+
/** Ticks an act stays satiating (engine-config-action-selector.repeatWindowTicks). */
|
|
7047
|
+
private _satiationWindow;
|
|
7048
|
+
/** Tick of the last thing said to each entity — outlives the descriptor sweep. */
|
|
7049
|
+
private _spokenAt;
|
|
6115
7050
|
private _bus;
|
|
6116
7051
|
private _defaultCap;
|
|
6117
7052
|
private _lastFieldSize;
|
|
@@ -6245,6 +7180,21 @@ declare class MotorSchemaExecutor implements CognitiveEngine {
|
|
|
6245
7180
|
private _author;
|
|
6246
7181
|
private _grants;
|
|
6247
7182
|
private _bus;
|
|
7183
|
+
/**
|
|
7184
|
+
* Two-phase outreach authoring. A facet cannot be awaited from inside a tick:
|
|
7185
|
+
* `ExecutiveFacet.report()` only QUEUES in tick-discipline mode and the reasoning
|
|
7186
|
+
* launches from `pump()`, which the ExecutiveEngine calls once per tick — so an
|
|
7187
|
+
* in-tick `await` blocks the very loop that would produce the answer. Observed
|
|
7188
|
+
* live: a 61s freeze of the whole mind inside one tick, then an empty result.
|
|
7189
|
+
* (It passes unit tests because bare facets have no inbox and author inline.)
|
|
7190
|
+
*
|
|
7191
|
+
* So `_deliver` REQUESTS words and returns false (the intent holds 'awaiting'),
|
|
7192
|
+
* the facet answers off-tick, and a later tick delivers. Process-local by design:
|
|
7193
|
+
* an authoring call in flight cannot survive a restart, and the intent would
|
|
7194
|
+
* simply re-request.
|
|
7195
|
+
*/
|
|
7196
|
+
private _authoring;
|
|
7197
|
+
private _authored;
|
|
6248
7198
|
constructor(schemas?: MotorSchema[]);
|
|
6249
7199
|
attachBus(bus: CognitiveBus): void;
|
|
6250
7200
|
/** Resolve schemas (incl. learned composites) from the live repertoire first. */
|
|
@@ -6284,6 +7234,13 @@ declare class MotorSchemaExecutor implements CognitiveEngine {
|
|
|
6284
7234
|
* conversation facet); this is the single enaction → delivery path.
|
|
6285
7235
|
*/
|
|
6286
7236
|
private _deliver;
|
|
7237
|
+
/**
|
|
7238
|
+
* Ask a facet for the words, off-tick. Fire-and-forget on purpose: awaiting this
|
|
7239
|
+
* from inside `react()` deadlocks the tick loop against the facet pump. Idempotent
|
|
7240
|
+
* per intent — a request already in flight is not duplicated, so the intent may sit
|
|
7241
|
+
* 'awaiting' across many ticks with exactly one LLM call behind it.
|
|
7242
|
+
*/
|
|
7243
|
+
private _requestAuthoring;
|
|
6287
7244
|
private _emitEnacted;
|
|
6288
7245
|
/**
|
|
6289
7246
|
* Publish `action.outcome` for EVERY enaction — the shared metacognitive/affective
|
|
@@ -6292,6 +7249,32 @@ declare class MotorSchemaExecutor implements CognitiveEngine {
|
|
|
6292
7249
|
* RewardEvaluator reads it as a reward signal. `confidence` carries the agency's
|
|
6293
7250
|
* own forward-model prior so calibration has a real prediction to score.
|
|
6294
7251
|
*/
|
|
7252
|
+
/**
|
|
7253
|
+
* Retire the `ideomotor.intent` that produced this act.
|
|
7254
|
+
*
|
|
7255
|
+
* Nothing deleted these. They were cleared only when the executive next ran and
|
|
7256
|
+
* declined to name the same action again — and the executive runs on an interval,
|
|
7257
|
+
* so between cycles a willed reach-out STOOD in state, was rebuilt into an
|
|
7258
|
+
* affordance every single tick, and competed every single tick. Observed as
|
|
7259
|
+
* dozens of identical lines:
|
|
7260
|
+
*
|
|
7261
|
+
* [selector] willed reach-out → … NOT selected: 0.297 < inspect… 0.340
|
|
7262
|
+
*
|
|
7263
|
+
* losing by four thousandths, over and over, until it won — twice. Fabrice got
|
|
7264
|
+
* the same message byte-for-byte 25 ticks apart, two outbox ids.
|
|
7265
|
+
*
|
|
7266
|
+
* `justEnacted` was built to hold this line and cannot: it is a DECAYING
|
|
7267
|
+
* quantity, capped at `repeatDamping` (0.30), and a standing intent outlasts it
|
|
7268
|
+
* by construction. Damping a permanent pull only ever delays it. So the intention
|
|
7269
|
+
* is discharged by being acted on, which is what an intention is — you meant to
|
|
7270
|
+
* tell someone something, you told them, and it is finished. If the mind still
|
|
7271
|
+
* wants to say more, the next executive cycle forms a new one, now seeing "I said
|
|
7272
|
+
* this 25 ticks ago and have had no answer" in front of it.
|
|
7273
|
+
*
|
|
7274
|
+
* Satiation stays exactly as it was, and still earns its keep: it damps saying
|
|
7275
|
+
* the same thing again for reasons that did NOT come from a standing will.
|
|
7276
|
+
*/
|
|
7277
|
+
private _dischargeWill;
|
|
6295
7278
|
private _emitActionOutcome;
|
|
6296
7279
|
private _emitDispatch;
|
|
6297
7280
|
}
|
|
@@ -6308,6 +7291,35 @@ declare class ReafferenceEngine implements CognitiveEngine {
|
|
|
6308
7291
|
onCognitiveEvent(e: CognitiveEvent): void;
|
|
6309
7292
|
snapshot(): Record<string, unknown>;
|
|
6310
7293
|
react(_delta: Duration, tick: Tick, state: ReadonlySimulationState, _context: SimulationContext): Promise<EngineResult>;
|
|
7294
|
+
/**
|
|
7295
|
+
* Latch each open turn's fate onto its own record and announce it once.
|
|
7296
|
+
*
|
|
7297
|
+
* Two rules earn their keep here:
|
|
7298
|
+
*
|
|
7299
|
+
* • MERGE, never replace. `StateManager.setEntity` overwrites the whole entity,
|
|
7300
|
+
* and a `conversation.sent` carries `outboxMessageIds` — the sole key by which
|
|
7301
|
+
* a later delivery ack can find it. Rewriting the record with only the fields
|
|
7302
|
+
* this method cares about would sever that, silently, for every turn that got
|
|
7303
|
+
* an answer.
|
|
7304
|
+
*
|
|
7305
|
+
* • Latch, don't recompute. `answeredAt`/`unansweredAt` persist, so the event
|
|
7306
|
+
* fires on the one tick the fact changed rather than every tick for the rest
|
|
7307
|
+
* of the session — which for an unanswered turn would be thousands of
|
|
7308
|
+
* identical reputation hits against one person for one silence.
|
|
7309
|
+
*/
|
|
7310
|
+
private _resolveReplies;
|
|
7311
|
+
/**
|
|
7312
|
+
* Publish how a person responded to being spoken to.
|
|
7313
|
+
*
|
|
7314
|
+
* Deliberately NOT an `interaction.occurred`: that event means "someone did
|
|
7315
|
+
* something toward us" and carries a valence for what they did. A silence is
|
|
7316
|
+
* nobody doing anything, and forcing it through that channel would have the
|
|
7317
|
+
* ReputationTracker book a hostile *act* where there was only an absence — the
|
|
7318
|
+
* mind would come to think it was being rebuffed rather than simply not
|
|
7319
|
+
* answered yet. Separate signal, separate meaning, one consumer decides what
|
|
7320
|
+
* either is worth.
|
|
7321
|
+
*/
|
|
7322
|
+
private _emitResponsiveness;
|
|
6311
7323
|
private _emitProceduralized;
|
|
6312
7324
|
/**
|
|
6313
7325
|
* Emit the `action.outcome{planId,stepId}` for an async (host-acked) plan-step
|
|
@@ -6339,6 +7351,12 @@ type EngineRegistry = {
|
|
|
6339
7351
|
affectiveBlender: AffectiveBlender;
|
|
6340
7352
|
workingMemory: WorkingMemory;
|
|
6341
7353
|
episodicConsolidator: EpisodicConsolidator;
|
|
7354
|
+
/**
|
|
7355
|
+
* The vector index, when semantic recall is configured. Exposed so shutdown can
|
|
7356
|
+
* FLUSH it: it lives outside the state snapshot and previously persisted only from
|
|
7357
|
+
* a debounce timer no shutdown path awaited, so it died with the process.
|
|
7358
|
+
*/
|
|
7359
|
+
vectorMemory: VectorMemoryAdapter | null;
|
|
6342
7360
|
semanticIntegrator: SemanticIntegrator;
|
|
6343
7361
|
spacedRepetition: SpacedRepetition;
|
|
6344
7362
|
forgettingCurve: ForgettingCurve;
|
|
@@ -6645,12 +7663,53 @@ interface WillModelConfig {
|
|
|
6645
7663
|
* `apiKey` is held in memory only — it is never mirrored into state entities,
|
|
6646
7664
|
* session logs, or the PMA.
|
|
6647
7665
|
*/
|
|
7666
|
+
interface WillProviderConfig {
|
|
7667
|
+
/** Credential for this provider. Held in memory only — never state/logs/PMA. */
|
|
7668
|
+
apiKey?: string;
|
|
7669
|
+
/** Base URL override — self-hosted or OpenAI-compatible endpoints. */
|
|
7670
|
+
baseUrl?: string;
|
|
7671
|
+
/**
|
|
7672
|
+
* USD per 1M tokens, keyed by model id. Host-owned on purpose: prices change
|
|
7673
|
+
* on a vendor's schedule, differ per account, and are ~0 self-hosted, so they
|
|
7674
|
+
* cannot be tracked from inside an npm release. These win over the engine's
|
|
7675
|
+
* built-in fallback table.
|
|
7676
|
+
*
|
|
7677
|
+
* Cost is telemetry only — it never enters simulation state — so changing a
|
|
7678
|
+
* price can never change what a mind does or break a replay.
|
|
7679
|
+
*/
|
|
7680
|
+
prices?: PriceTable;
|
|
7681
|
+
}
|
|
6648
7682
|
interface WillLLMConfig {
|
|
6649
7683
|
provider?: LLMProvider;
|
|
6650
7684
|
apiKey?: string;
|
|
6651
7685
|
baseUrl?: string;
|
|
6652
7686
|
maxOutputTokens?: number;
|
|
6653
7687
|
timeoutMs?: number;
|
|
7688
|
+
/**
|
|
7689
|
+
* Everything the host knows about each provider — credential, endpoint, and
|
|
7690
|
+
* prices — declared once per provider. The single-provider fields above stay
|
|
7691
|
+
* the simple path; this map is for hosts reaching more than one.
|
|
7692
|
+
*/
|
|
7693
|
+
providers?: Partial<Record<LLMProvider, WillProviderConfig>>;
|
|
7694
|
+
/**
|
|
7695
|
+
* Per-call model selection. Omitted (or NULL_ROUTER) means every call uses
|
|
7696
|
+
* `model` above, exactly as before the seam existed.
|
|
7697
|
+
*
|
|
7698
|
+
* The router sees only the call's attribution — what kind of work it is and
|
|
7699
|
+
* how much the moment demands — never who is paying or what anything costs.
|
|
7700
|
+
* Routes name providers from the `providers` map above; a route to a provider
|
|
7701
|
+
* with no credential falls back to the default rather than failing the call.
|
|
7702
|
+
*/
|
|
7703
|
+
router?: ModelRouter | null;
|
|
7704
|
+
/**
|
|
7705
|
+
* Concrete LLM model id(s) for this Will — a single id for every role, or a
|
|
7706
|
+
* per-role map. An explicit WILL_LLM_MODEL env pins the thinking roles
|
|
7707
|
+
* (operator single-model deployments); unset roles fall back to `executive`,
|
|
7708
|
+
* then the LLMDirector's built-in default. Product-level labels (pricing
|
|
7709
|
+
* tiers, model families) live host-side and resolve to concrete ids BEFORE
|
|
7710
|
+
* reaching the engine.
|
|
7711
|
+
*/
|
|
7712
|
+
model?: string | WillModelConfig;
|
|
6654
7713
|
}
|
|
6655
7714
|
interface WillIdentity {
|
|
6656
7715
|
/**
|
|
@@ -6691,17 +7750,26 @@ interface WillConfig {
|
|
|
6691
7750
|
profile?: string | null;
|
|
6692
7751
|
/** Persona definition seeded into the will.identity entity. */
|
|
6693
7752
|
identity: WillIdentity;
|
|
6694
|
-
/** Anatomy — 'mind' (default) or the no-LLM 'reflex' shell. */
|
|
6695
|
-
anatomy?: Anatomy;
|
|
6696
7753
|
/**
|
|
6697
|
-
*
|
|
6698
|
-
*
|
|
6699
|
-
*
|
|
6700
|
-
*
|
|
6701
|
-
*
|
|
6702
|
-
*
|
|
7754
|
+
* This config's `identity` is a PLACEHOLDER — the real one arrives from a PMA
|
|
7755
|
+
* artifact moments later, on the same boot.
|
|
7756
|
+
*
|
|
7757
|
+
* Set by `Will.wake`, which passes `{ prompt: '' }` because a woken mind's
|
|
7758
|
+
* persona belongs to its artifact, not to the caller. Without this flag the
|
|
7759
|
+
* creation-time identity guard inspected that placeholder and warned, on every
|
|
7760
|
+
* single wake, that "identity.values is empty", "identity.style is generic" and
|
|
7761
|
+
* "identity is shallow (strength 0)" — three alarms about a config nobody
|
|
7762
|
+
* intended to use, fired before the real identity had loaded.
|
|
7763
|
+
*
|
|
7764
|
+
* It suppresses only the WARNINGS. Errors still throw (an over-long or
|
|
7765
|
+
* malformed prompt is a hard failure whenever it appears), and the artifact's
|
|
7766
|
+
* OWN identity is fully guarded at the load boundary by PMAController.load,
|
|
7767
|
+
* which is the honest place to ask whether this mind's persona is thin — it is
|
|
7768
|
+
* the only point where the answer is knowable.
|
|
6703
7769
|
*/
|
|
6704
|
-
|
|
7770
|
+
identityFromArtifact?: boolean;
|
|
7771
|
+
/** Anatomy — 'mind' (default) or the no-LLM 'reflex' shell. */
|
|
7772
|
+
anatomy?: Anatomy;
|
|
6705
7773
|
/**
|
|
6706
7774
|
* Per-Will LLM transport overrides (provider, BYO apiKey, baseUrl, output
|
|
6707
7775
|
* cap, timeout). Unset fields fall back to WILL_LLM_* envs. The apiKey never
|
|
@@ -6735,6 +7803,21 @@ interface WillConfig {
|
|
|
6735
7803
|
* Plan-enforced floor for executiveInterval — the customer cannot go faster.
|
|
6736
7804
|
*/
|
|
6737
7805
|
minExecutiveInterval?: number;
|
|
7806
|
+
/**
|
|
7807
|
+
* Enable the DeliberationCache — a learned fast path that composes an executive
|
|
7808
|
+
* output from highly-similar, highly-competent precedent instead of calling the
|
|
7809
|
+
* LLM. Off unless asked for.
|
|
7810
|
+
*
|
|
7811
|
+
* OFF BY DEFAULT ON PURPOSE, and the default is the interesting part: this
|
|
7812
|
+
* changes how a mind THINKS, not how fast it runs. A cache hit means the mind
|
|
7813
|
+
* acted from precedent without deliberating, which is a real thing minds do and
|
|
7814
|
+
* a real thing an operator must opt into for a specific Will — not something a
|
|
7815
|
+
* dependency bump should switch on underneath one that is already living.
|
|
7816
|
+
*
|
|
7817
|
+
* Pass `true` for the built-in conservative settings, or a config object to tune
|
|
7818
|
+
* the retrieval/competence parameters (see cognition/cache/types).
|
|
7819
|
+
*/
|
|
7820
|
+
deliberationCache?: boolean | DeliberationCacheConfig;
|
|
6738
7821
|
/**
|
|
6739
7822
|
* Goals seeded before the first tick. If omitted or empty, the Will starts
|
|
6740
7823
|
* goalless — the executive engine will generate context-appropriate goals on its
|
|
@@ -7465,7 +8548,7 @@ interface WillSummary {
|
|
|
7465
8548
|
createdAt: Date;
|
|
7466
8549
|
lastTickAt: Date | null;
|
|
7467
8550
|
anatomy: WillConfig['anatomy'];
|
|
7468
|
-
model: WillConfig['model'];
|
|
8551
|
+
model: NonNullable<WillConfig['llm']>['model'];
|
|
7469
8552
|
}
|
|
7470
8553
|
|
|
7471
8554
|
interface WillInstance {
|
|
@@ -7828,6 +8911,8 @@ interface Stimulus {
|
|
|
7828
8911
|
speaker?: string;
|
|
7829
8912
|
/** Conversation/thread id (default = `from`). */
|
|
7830
8913
|
thread?: string;
|
|
8914
|
+
/** True when `thread` is private — just this someone and the Will. See TextMessage.direct. */
|
|
8915
|
+
direct?: boolean;
|
|
7831
8916
|
}
|
|
7832
8917
|
/** A message the Will emitted to someone. */
|
|
7833
8918
|
interface WillMessage {
|
|
@@ -7837,6 +8922,20 @@ interface WillMessage {
|
|
|
7837
8922
|
content: string;
|
|
7838
8923
|
/** Entity id the Will addressed (the speaker you used in say()/tell(), or a bond). */
|
|
7839
8924
|
to: string;
|
|
8925
|
+
/**
|
|
8926
|
+
* The conversation this belongs to — the `thread` from the `perceive()` that
|
|
8927
|
+
* prompted it. Absent when the Will spoke unprompted, which genuinely has no
|
|
8928
|
+
* thread.
|
|
8929
|
+
*
|
|
8930
|
+
* WHERE, not just to whom. The engine knew this the whole way down —
|
|
8931
|
+
* `OutboxMessage.threadId` carries it — and the projection dropped it here, so
|
|
8932
|
+
* a channel adapter had nothing to answer INTO and had to guess from a roster.
|
|
8933
|
+
* Observed live: a DM arrived on `discord:1532693…`, she answered it correctly
|
|
8934
|
+
* and in seconds, and the reply went to the shared server channel because that
|
|
8935
|
+
* was the last room the roster had seen this person in. From the operator's
|
|
8936
|
+
* side she had simply ignored him.
|
|
8937
|
+
*/
|
|
8938
|
+
thread?: string;
|
|
7840
8939
|
}
|
|
7841
8940
|
/**
|
|
7842
8941
|
* A motor act the Will *chose* to enact — a projection of its agency, surfaced
|
|
@@ -7941,20 +9040,42 @@ interface CreateWillOptions {
|
|
|
7941
9040
|
anatomy?: Anatomy;
|
|
7942
9041
|
/** Concrete LLM model id, or a per-role map ({ executive, summarizer?,
|
|
7943
9042
|
* deliberation?, embedding? } — unset thinking roles fall back to executive).
|
|
7944
|
-
* Unset → env / provider default.
|
|
9043
|
+
* Unset → env / provider default.
|
|
9044
|
+
* @deprecated Pass `llmConfig: { model }` instead — model and transport are
|
|
9045
|
+
* one concern. Still honoured; an explicit `llmConfig.model` wins. */
|
|
7945
9046
|
model?: string | WillModelConfig;
|
|
7946
|
-
/** Per-Will LLM
|
|
9047
|
+
/** Per-Will LLM config: provider, model(s), BYO apiKey, baseUrl, caps.
|
|
7947
9048
|
* Unset fields fall back to WILL_LLM_* envs. apiKey stays in memory only.
|
|
7948
|
-
* (Named llmConfig because `llm` is the
|
|
9049
|
+
* (Named llmConfig because `llm` is the provider MODE switch.) */
|
|
7949
9050
|
llmConfig?: WillLLMConfig;
|
|
7950
9051
|
/**
|
|
7951
|
-
* LLM mode
|
|
7952
|
-
*
|
|
7953
|
-
*
|
|
7954
|
-
*
|
|
7955
|
-
*
|
|
9052
|
+
* LLM mode — which provider the executive speaks to.
|
|
9053
|
+
*
|
|
9054
|
+
* 'mock' (the default when no key is present) runs a deterministic canned
|
|
9055
|
+
* executive: zero keys, zero cost. Every other value names a provider and
|
|
9056
|
+
* needs its key, either the provider's own env below or the
|
|
9057
|
+
* provider-agnostic WILL_LLM_API_KEY:
|
|
9058
|
+
*
|
|
9059
|
+
* anthropic ANTHROPIC_API_KEY Claude, native Messages wire
|
|
9060
|
+
* glm ZAI_API_KEY Z.ai GLM, Anthropic-compatible wire
|
|
9061
|
+
* openai OPENAI_API_KEY OpenAI wire
|
|
9062
|
+
* google GOOGLE_API_KEY | GEMINI_API_KEY native Gemini wire
|
|
9063
|
+
* deepseek DEEPSEEK_API_KEY OpenAI wire
|
|
9064
|
+
* moonshot MOONSHOT_API_KEY Kimi — OpenAI wire
|
|
9065
|
+
* qwen DASHSCOPE_API_KEY Alibaba Model Studio — OpenAI wire
|
|
9066
|
+
* xai XAI_API_KEY Grok — OpenAI wire
|
|
9067
|
+
* minimax MINIMAX_API_KEY OpenAI wire
|
|
9068
|
+
* mistral MISTRAL_API_KEY OpenAI wire
|
|
9069
|
+
* ollama · vllm local; no key, set `llm` explicitly
|
|
9070
|
+
*
|
|
9071
|
+
* Any other string works too — it just has to declare its `wire` and
|
|
9072
|
+
* `baseUrl` on `llmConfig.providers`. Naming the vendor rather than
|
|
9073
|
+
* borrowing `openai` because it speaks that wire is what keeps the
|
|
9074
|
+
* completion tape and the cost breakdown honest.
|
|
9075
|
+
*
|
|
9076
|
+
* Omit to auto-detect from whichever key is set.
|
|
7956
9077
|
*/
|
|
7957
|
-
llm?: 'mock' |
|
|
9078
|
+
llm?: 'mock' | LLMProvider;
|
|
7958
9079
|
/**
|
|
7959
9080
|
* Abilities the Will can choose to enact. `name → handler`, or
|
|
7960
9081
|
* `name → { handler, description?, cost?, valence?, preconditions? }` to seed
|
|
@@ -8077,4 +9198,4 @@ declare class Will {
|
|
|
8077
9198
|
private _emitError;
|
|
8078
9199
|
}
|
|
8079
9200
|
|
|
8080
|
-
export {
|
|
9201
|
+
export { type CognitiveHealth as $, type AckResult as A, type AsyncEngineConfig as B, type ConflictReport as C, AttachmentEvaluator as D, type EffectorHandler as E, type AttachmentEvaluatorConfig as F, AttentionAllocator as G, type AttentionAllocatorConfig as H, type InboundEnvelope as I, AuditionEngine as J, AutobiographicalNarrator as K, type AutobiographicalNarratorConfig as L, BACKGROUND_DEMAND as M, type BehavioralProbeResult as N, type OutboundEnvelope as O, BiasDetector as P, type BiasDetectorConfig as Q, type RestoreOptions as R, type SimulationContext as S, type TransportStatus as T, BunStorageAdapter as U, type ChunkEnvelope as V, Will as W, type CircadianConfig as X, CircadianOscillator as Y, type ClockConfig as Z, type Cognition as _, type ExternalTransport as a, type KnownProvider as a$, ConfidenceCalibrator as a0, type ConfidenceCalibratorConfig as a1, type Coordinates as a2, type CreateWillOptions as a3, DefaultEventBus as a4, DefaultMetricCollector as a5, DefaultOrchestrator as a6, DefaultReplayRecorder as a7, DefaultReplaySession as a8, DefaultScenario as a9, type EventBus as aA, type EventBusConfig as aB, type EventFilter as aC, type EventHandler as aD, type EventPayload as aE, ExecutiveEngine as aF, type ExecutiveEngineConfig$1 as aG, Exteroception as aH, type ExteroceptionConfig as aI, ForgettingCurve as aJ, type ForgettingCurveConfig as aK, FrustrationEvaluator as aL, type FrustrationEvaluatorConfig as aM, GoalManager as aN, type GoalManagerConfig as aO, GustationEngine as aP, type InboundMessageEnvelope as aQ, type InboundPerceptEnvelope as aR, InhibitionController as aS, type InhibitionControllerConfig as aT, Interoception as aU, type InteroceptionConfig as aV, IntrospectionEngine as aW, type IntrospectionEngineConfig as aX, KNOWN_PROVIDERS as aY, KnownEntityTracker as aZ, type KnownEntityTrackerConfig as a_, DefaultSerializer as aa, DefaultSimulation as ab, DefaultSimulationClock as ac, DefaultStateManager as ad, DefaultVectorMemoryAdapter as ae, DeliberationEngine as af, DeltaEncoder as ag, type DeltaSnapshot as ah, DreamSimulator as ai, type DreamSimulatorConfig as aj, type Duration as ak, ESCALATION_DEMAND as al, type EffectorDeclaration as am, type EffectorEntry as an, type EffectorResult as ao, type EffectorSpec as ap, type EmbeddingProvider as aq, EmpathySimulator as ar, type EmpathySimulatorConfig as as, EnergyRegulator as at, type EnergyRegulatorConfig as au, type EngineRegistry as av, type EngineResult as aw, type Envelope as ax, EpisodicConsolidator as ay, type EpisodicConsolidatorConfig as az, type SeededPRNG as b, SelfModelUpdater as b$, type LLMCallMeta as b0, type LLMCompletionRecord as b1, type LLMCompletionSink as b2, type LLMProvider as b3, type LLMWire as b4, LossEvaluator as b5, type LossEvaluatorConfig as b6, type MessageEnvelope as b7, type MetricCollector as b8, type MetricPoint as b9, type PersonaConsolidatorConfig as bA, PlanningEngine as bB, type PlanningEngineConfig as bC, type PriceTable as bD, type ProviderCredential as bE, ReafferenceEngine as bF, type ReconstructionFidelityReport as bG, type ReconstructionFidelityScores as bH, type RecordUsageInput as bI, type ReplayComparison as bJ, type ReplayConfig as bK, type ReplayDifference as bL, ReplayManager as bM, type ReplayMetadata as bN, type ReplayRecord as bO, type ReplayRecorder as bP, type ReplaySession as bQ, type ReplyEnvelope as bR, ReputationTracker as bS, type ReputationTrackerConfig as bT, RewardEvaluator as bU, type RewardEvaluatorConfig as bV, type RoutingRule as bW, type Scenario as bX, type ScenarioConfig as bY, type ScenarioValidationResult as bZ, type SchemaPrecondition as b_, type MinimalContext as ba, MockEmbedder as bb, type ModelPrice as bc, type ModelRoute as bd, type ModelRouter as be, MoralEvaluator as bf, type MoralEvaluatorConfig as bg, MotorSchemaExecutor as bh, NULL_ROUTER as bi, NoveltyDetector as bj, type NoveltyDetectorConfig as bk, OlfactionEngine as bl, OpenAICompatibleEmbedder as bm, type Orchestrator as bn, type OrchestratorConfig as bo, type OutboxMessage as bp, type PMABehavioral as bq, type PMABelief as br, type PMAEmotionalBaseline as bs, PMAEvalHarness as bt, type PMAGoal as bu, type PMAIdentity as bv, type PMAProbe as bw, type PMASnapshot as bx, type PerceptEnvelope as by, PersonaConsolidator as bz, type SimulationEntity as c, assembleMind as c$, type SelfModelUpdaterConfig as c0, SemanticIntegrator as c1, type SemanticIntegratorConfig as c2, type SensoryInput as c3, type SerializationConfig as c4, type SerializationFormat as c5, type SerializedEntity as c6, type SerializedState as c7, type Serializer as c8, type SessionLogEnvelope as c9, type TickListener as cA, type TokenLedgerRecord as cB, type TokenReportEnvelope as cC, TokenTracker as cD, type TokenTrackerConfig as cE, type TokenUsage as cF, type VectorIndex as cG, type VectorMemoryAdapter as cH, type VectorMemoryConfig as cI, type VectorQueryFilter as cJ, type VectorQueryResult as cK, type VectorRecord as cL, VisionEngine as cM, type VoiceChunk as cN, type WillAffect as cO, type WillConfig as cP, type WillEffectorAct as cQ, type WillInstance as cR, type WillMessage as cS, type WillStateSummary as cT, type WillStatus as cU, WillStem as cV, type WillSummary as cW, WorkingMemory as cX, type WorkingMemoryConfig as cY, type WorldEntity as cZ, type WorldInterface as c_, type Simulation as ca, type SimulationClock as cb, type SimulationConfig as cc, type SimulationEngine as cd, type SimulationEventBase as ce, type SimulationEventListener as cf, type SleepPressureConfig as cg, SleepPressureRegulator as ch, SocialPerception as ci, type SocialPerceptionConfig as cj, SomatosensationEngine as ck, SpacedRepetition as cl, type SpacedRepetitionConfig as cm, type StateSnapshot as cn, type Stimulus as co, type StorageAdapter as cp, StressRegulator as cq, type StressRegulatorConfig as cr, TableRouter as cs, TaskSwitcher as ct, type TaskSwitcherConfig as cu, type TextMessage as cv, TheoryOfMind as cw, type TheoryOfMindConfig as cx, ThreatEvaluator as cy, type ThreatEvaluatorConfig as cz, type Timestamp as d, chainRouters as d0, clearCompletionRecorder as d1, defaultBaseFor as d2, type effectorInvocation as d3, type effectorInvocationEnvelope as d4, getCompletionRecorder as d5, isNullRouter as d6, knownWireFor as d7, resolvePricing as d8, setCompletionRecorder as d9, type SimulationEvent as e, type StateManager as f, type Tick as g, type SimulationState as h, type StateCommands as i, type ReasoningFootprint as j, type ReadonlySimulationState as k, type ConflictStrategy as l, type ConflictResolution as m, type AckEnvelope as n, type ActionRequest as o, type ActionResult as p, ActionSelector as q, type ActivityEnvelope as r, type ActivityEvent as s, type ActivityEventHandler as t, AestheticEvaluator as u, type AestheticEvaluatorConfig as v, AffectiveBlender as w, type AffectiveBlenderConfig as x, AffordanceSynthesizer as y, AsyncEngine as z };
|