emocentric 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +144 -0
  3. package/dist/actions/action.d.ts +70 -0
  4. package/dist/actions/action.js +47 -0
  5. package/dist/actions/index.d.ts +2 -0
  6. package/dist/actions/index.js +2 -0
  7. package/dist/actions/registry.d.ts +12 -0
  8. package/dist/actions/registry.js +26 -0
  9. package/dist/agent.d.ts +141 -0
  10. package/dist/agent.js +246 -0
  11. package/dist/blueprint/blueprint.d.ts +60 -0
  12. package/dist/blueprint/blueprint.js +20 -0
  13. package/dist/blueprint/index.d.ts +2 -0
  14. package/dist/blueprint/index.js +2 -0
  15. package/dist/blueprint/scope.d.ts +26 -0
  16. package/dist/blueprint/scope.js +21 -0
  17. package/dist/emotion/definitions.d.ts +34 -0
  18. package/dist/emotion/definitions.js +43 -0
  19. package/dist/emotion/index.d.ts +3 -0
  20. package/dist/emotion/index.js +3 -0
  21. package/dist/emotion/persona.d.ts +35 -0
  22. package/dist/emotion/persona.js +22 -0
  23. package/dist/emotion/state.d.ts +52 -0
  24. package/dist/emotion/state.js +35 -0
  25. package/dist/events/context-event.d.ts +49 -0
  26. package/dist/events/context-event.js +43 -0
  27. package/dist/events/guards.d.ts +14 -0
  28. package/dist/events/guards.js +72 -0
  29. package/dist/events/index.d.ts +8 -0
  30. package/dist/events/index.js +5 -0
  31. package/dist/events/media.d.ts +23 -0
  32. package/dist/events/media.js +16 -0
  33. package/dist/events/merge.d.ts +24 -0
  34. package/dist/events/merge.js +61 -0
  35. package/dist/events/payload.d.ts +54 -0
  36. package/dist/events/payload.js +8 -0
  37. package/dist/gateway/client.d.ts +28 -0
  38. package/dist/gateway/client.js +79 -0
  39. package/dist/gateway/index.d.ts +1 -0
  40. package/dist/gateway/index.js +1 -0
  41. package/dist/index.d.ts +9 -0
  42. package/dist/index.js +13 -0
  43. package/dist/llm/index.d.ts +1 -0
  44. package/dist/llm/index.js +1 -0
  45. package/dist/llm/types.d.ts +40 -0
  46. package/dist/llm/types.js +1 -0
  47. package/dist/memory/fact.d.ts +54 -0
  48. package/dist/memory/fact.js +1 -0
  49. package/dist/memory/index.d.ts +4 -0
  50. package/dist/memory/index.js +2 -0
  51. package/dist/memory/openai-embedder.d.ts +50 -0
  52. package/dist/memory/openai-embedder.js +124 -0
  53. package/dist/memory/scoring.d.ts +24 -0
  54. package/dist/memory/scoring.js +20 -0
  55. package/dist/memory/store.d.ts +79 -0
  56. package/dist/memory/store.js +1 -0
  57. package/dist/openrouter/client.d.ts +27 -0
  58. package/dist/openrouter/client.js +118 -0
  59. package/dist/openrouter/index.d.ts +1 -0
  60. package/dist/openrouter/index.js +1 -0
  61. package/dist/pipeline/actor.d.ts +31 -0
  62. package/dist/pipeline/actor.js +11 -0
  63. package/dist/pipeline/appraiser.d.ts +55 -0
  64. package/dist/pipeline/appraiser.js +132 -0
  65. package/dist/pipeline/consolidator.d.ts +62 -0
  66. package/dist/pipeline/consolidator.js +98 -0
  67. package/dist/pipeline/inbox.d.ts +60 -0
  68. package/dist/pipeline/inbox.js +107 -0
  69. package/dist/pipeline/index.d.ts +11 -0
  70. package/dist/pipeline/index.js +11 -0
  71. package/dist/pipeline/interpretation.d.ts +47 -0
  72. package/dist/pipeline/interpretation.js +24 -0
  73. package/dist/pipeline/llm-interpreter.d.ts +28 -0
  74. package/dist/pipeline/llm-interpreter.js +173 -0
  75. package/dist/pipeline/loop.d.ts +58 -0
  76. package/dist/pipeline/loop.js +73 -0
  77. package/dist/pipeline/processor.d.ts +63 -0
  78. package/dist/pipeline/processor.js +144 -0
  79. package/dist/pipeline/recaller.d.ts +34 -0
  80. package/dist/pipeline/recaller.js +38 -0
  81. package/dist/pipeline/time-appraiser.d.ts +85 -0
  82. package/dist/pipeline/time-appraiser.js +189 -0
  83. package/dist/pipeline/writer.d.ts +113 -0
  84. package/dist/pipeline/writer.js +210 -0
  85. package/dist/postgres/create-instance.d.ts +107 -0
  86. package/dist/postgres/create-instance.js +182 -0
  87. package/dist/postgres/emotional-state.d.ts +42 -0
  88. package/dist/postgres/emotional-state.js +134 -0
  89. package/dist/postgres/index.d.ts +5 -0
  90. package/dist/postgres/index.js +5 -0
  91. package/dist/postgres/instances.d.ts +32 -0
  92. package/dist/postgres/instances.js +77 -0
  93. package/dist/postgres/schema.d.ts +31 -0
  94. package/dist/postgres/schema.js +98 -0
  95. package/dist/postgres/short-term.d.ts +32 -0
  96. package/dist/postgres/short-term.js +95 -0
  97. package/dist/postgres/store.d.ts +85 -0
  98. package/dist/postgres/store.js +347 -0
  99. package/dist/short-term/index.d.ts +1 -0
  100. package/dist/short-term/index.js +1 -0
  101. package/dist/short-term/short-term.d.ts +66 -0
  102. package/dist/short-term/short-term.js +72 -0
  103. package/package.json +50 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 The Resonance Lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # Emocentric
2
+
3
+ A cross-platform, emotionally-driven agentic framework. Emocentric agents
4
+ don't just respond to events — they **feel** their way through them:
5
+ persistent emotions shape how an agent interprets what it sees, what it
6
+ remembers, and what it chooses to do.
7
+
8
+ ## Blueprints and instances
9
+
10
+ An agent is a **blueprint**, not a being: a serializable definition of who
11
+ the character is — persona, emotion palette, action menu, and the memories
12
+ it starts life with. Nobody talks to a blueprint. Each user gets their own
13
+ **instance** of it, born on first contact with the blueprint's starting
14
+ emotions and seed memories, and diverging from there. Two users of the same
15
+ blueprint share nothing: separate feelings, separate memories.
16
+
17
+ Instances are keyed by `(blueprintId, userId)` — with a `sessionId` slot
18
+ reserved for the future case of several people sharing one instance.
19
+
20
+ ## The pipeline
21
+
22
+ Every incoming event (a chat message, a photo, a game action) runs one
23
+ heartbeat:
24
+
25
+ ```
26
+ ContextEvent (you build this from your platform's event)
27
+
28
+
29
+ 1. time appraisal feelings drift toward baseline for the time
30
+ │ since last contact (math today, LLM-ready)
31
+
32
+ 2. interpret/recall describe the event → search memory → look again
33
+ │ with memories in hand, until nothing new turns up
34
+
35
+ 3. event appraisal one LLM call decides how each emotion moves,
36
+ │ in character; applied to persistent state
37
+
38
+ 4. writer new facts extracted into memory; contradictions
39
+ │ supersede old facts (history is kept, not erased)
40
+
41
+ 5. processor actions chosen from the CURRENT feelings;
42
+ executed only if you allow it
43
+ ```
44
+
45
+ ## Quickstart
46
+
47
+ ```ts
48
+ import { createContextEvent, type AgentBlueprint } from "emocentric";
49
+ import { createAgentInstance } from "emocentric/postgres";
50
+ import { OpenRouterClient } from "emocentric/openrouter";
51
+
52
+ // The blueprint: authored once (eventually in the studio), stored as JSON.
53
+ const blueprint: AgentBlueprint = {
54
+ id: "lyra",
55
+ persona: {
56
+ name: "Lyra",
57
+ summary: "a warm, observant cellist who remembers the small things",
58
+ temperament: [{ emotion: "joy", sensitivity: 1.5 }],
59
+ },
60
+ actions: [
61
+ {
62
+ name: "send_message",
63
+ description: "Reply to the user. Use when a verbal response fits.",
64
+ slot: "voice",
65
+ paramsSchema: { type: "object", properties: { text: { type: "string" } }, required: ["text"] },
66
+ },
67
+ ],
68
+ seedFacts: [
69
+ { kind: "persona", content: "Lyra grew up in a port town and misses the sea", importance: 0.8 },
70
+ ],
71
+ };
72
+
73
+ // This user's private instance — created on first contact, found after.
74
+ const { agent, close } = await createAgentInstance({
75
+ blueprint,
76
+ userId: "user-42",
77
+ llm: new OpenRouterClient({ model: "anthropic/claude-sonnet-4.6" }),
78
+ executors: {
79
+ // the platform's side of each blueprint action
80
+ send_message: (params, ctx) => myPlatform.send(ctx.event.channelId, params.text),
81
+ },
82
+ act: true,
83
+ });
84
+
85
+ // your platform glue: native event → ContextEvent → one call
86
+ const event = createContextEvent({
87
+ platform: "discord",
88
+ actor: { id: "user-42", displayName: "Alice" },
89
+ payload: { kind: "text", text: "Biscuit just learned to fetch!!" },
90
+ });
91
+
92
+ const result = await agent.handleEvent(event);
93
+ // `result` is the full transcript: time drift, grounded description,
94
+ // emotion deltas with reasons, facts written, actions executed.
95
+ ```
96
+
97
+ Payloads cover text, images, audio/video (via transcripts), platform
98
+ actions (game moves, button presses), and composites of those.
99
+
100
+ Instance management lives in `emocentric/postgres` too: `listInstances`
101
+ (all instances of a blueprint, or everything a user owns) and
102
+ `deleteInstance` (erase one user's memories, feelings, and directory row).
103
+
104
+ ## Setup
105
+
106
+ ```sh
107
+ npm install
108
+ docker compose up -d # local Postgres (pgvector) — schema auto-creates
109
+ cp .env.example .env # add your OPENROUTER_API_KEY
110
+ npm test # 110+ tests; DB/live tests skip when unconfigured
111
+ npm run demo # one event through the full pipeline, with receipts
112
+ ```
113
+
114
+ **Production:** provision PostgreSQL on Railway (pgvector included), hand the
115
+ app its `DATABASE_URL`. Tables create themselves on first connect.
116
+
117
+ ## Design principles
118
+
119
+ - **A blueprint is a recipe, not a being.** What the character *is* lives in
120
+ one JSON document; what each instance *has lived* stays in the database.
121
+ Seed facts are copied at birth — editing a blueprint affects only new
122
+ instances.
123
+ - **Everything is swappable.** Memory is a 5-method interface, emotional
124
+ state is 5 methods, each pipeline stage is 1 method, the LLM is 1 method.
125
+ Rewrite any layer without touching the others; the shipped defaults are
126
+ just defaults. (`createAgentInstance` is itself just a convenience over
127
+ `new Agent(...)` with scoped stores.)
128
+ - **LLM-agnostic.** All model calls go through OpenRouter — the model is a
129
+ string you choose, per stage if you like. Or implement `LLMClient` for
130
+ any provider.
131
+ - **Feelings and memories persist per instance.** Postgres-backed; instances
132
+ never reset between sessions. One database serves many blueprints and all
133
+ their instances.
134
+ - **Actions are described in data, executed in code.** The blueprint declares
135
+ what the agent can do and when (the LLM's menu); your codebase supplies the
136
+ side effects via `executors`.
137
+
138
+ ## Package layout
139
+
140
+ | Import | Contents |
141
+ |---|---|
142
+ | `emocentric` | core: events, blueprints/scopes, memory/emotion/LLM interfaces, pipeline stages, `Agent` |
143
+ | `emocentric/postgres` | `createAgentInstance`, `PostgresMemoryStore`, `PostgresEmotionalState`, instance directory (Node-only) |
144
+ | `emocentric/openrouter` | `OpenRouterClient` |
@@ -0,0 +1,70 @@
1
+ import type { ContextEvent } from "../events/context-event.js";
2
+ import type { Fact } from "../memory/fact.js";
3
+ import type { EmotionSnapshot } from "../emotion/definitions.js";
4
+ import type { Persona } from "../emotion/persona.js";
5
+ /** Everything an action implementation gets to work with when it runs —
6
+ * including the platform-native `event.raw` (reply tokens, channel handles)
7
+ * and the agent's current feelings. */
8
+ export interface ActionContext {
9
+ event: ContextEvent;
10
+ description: string;
11
+ memories: Fact[];
12
+ emotions: EmotionSnapshot;
13
+ persona?: Persona;
14
+ }
15
+ /**
16
+ * One thing the agent can do, defined by the developer in code.
17
+ *
18
+ * - `description` is written for the LLM: what it does AND when to use it.
19
+ * - `slot` groups mutually exclusive actions — at most one action per slot
20
+ * makes it into a plan. No slot = combines freely.
21
+ * - `paramsSchema` (JSON schema) describes the arguments the LLM must fill
22
+ * (e.g. the text of a message). Omit for parameter-less actions.
23
+ * - `act` is the developer's side effect; the SDK never touches platforms
24
+ * itself. May return anything (captured in the execution report).
25
+ */
26
+ export interface ActionDefinition {
27
+ name: string;
28
+ description: string;
29
+ slot?: string;
30
+ paramsSchema?: Record<string, unknown>;
31
+ act(params: Record<string, unknown>, context: ActionContext): Promise<unknown> | unknown;
32
+ }
33
+ /** An action the processor chose, with the LLM-filled params. Carries the
34
+ * real definition, so `planned.action.act(...)` is directly callable. */
35
+ export interface PlannedAction {
36
+ action: ActionDefinition;
37
+ params: Record<string, unknown>;
38
+ reason?: string;
39
+ }
40
+ /** Outcome of running one planned action. */
41
+ export interface ActionExecution {
42
+ name: string;
43
+ params: Record<string, unknown>;
44
+ status: "succeeded" | "failed";
45
+ result?: unknown;
46
+ error?: string;
47
+ }
48
+ /**
49
+ * The processor's output: slot-enforced chosen actions plus a record of
50
+ * what got dropped and why. `execute()` runs the plan (in order, errors
51
+ * isolated per action) — call it yourself when the processor ran with
52
+ * `act: false`.
53
+ */
54
+ export declare class ActionPlan {
55
+ /** Accepted actions, in the LLM's chosen order, at most one per slot. */
56
+ readonly actions: PlannedAction[];
57
+ /** Valid actions dropped because their slot was already taken. */
58
+ readonly droppedConflicts: PlannedAction[];
59
+ /** Names the LLM picked that don't exist in the registry. */
60
+ readonly unknownActions: string[];
61
+ private readonly context;
62
+ constructor(
63
+ /** Accepted actions, in the LLM's chosen order, at most one per slot. */
64
+ actions: PlannedAction[],
65
+ /** Valid actions dropped because their slot was already taken. */
66
+ droppedConflicts: PlannedAction[],
67
+ /** Names the LLM picked that don't exist in the registry. */
68
+ unknownActions: string[], context: ActionContext);
69
+ execute(): Promise<ActionExecution[]>;
70
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The processor's output: slot-enforced chosen actions plus a record of
3
+ * what got dropped and why. `execute()` runs the plan (in order, errors
4
+ * isolated per action) — call it yourself when the processor ran with
5
+ * `act: false`.
6
+ */
7
+ export class ActionPlan {
8
+ actions;
9
+ droppedConflicts;
10
+ unknownActions;
11
+ context;
12
+ constructor(
13
+ /** Accepted actions, in the LLM's chosen order, at most one per slot. */
14
+ actions,
15
+ /** Valid actions dropped because their slot was already taken. */
16
+ droppedConflicts,
17
+ /** Names the LLM picked that don't exist in the registry. */
18
+ unknownActions, context) {
19
+ this.actions = actions;
20
+ this.droppedConflicts = droppedConflicts;
21
+ this.unknownActions = unknownActions;
22
+ this.context = context;
23
+ }
24
+ async execute() {
25
+ const executions = [];
26
+ for (const planned of this.actions) {
27
+ try {
28
+ const result = await planned.action.act(planned.params, this.context);
29
+ executions.push({
30
+ name: planned.action.name,
31
+ params: planned.params,
32
+ status: "succeeded",
33
+ ...(result !== undefined && { result }),
34
+ });
35
+ }
36
+ catch (error) {
37
+ executions.push({
38
+ name: planned.action.name,
39
+ params: planned.params,
40
+ status: "failed",
41
+ error: error instanceof Error ? error.message : String(error),
42
+ });
43
+ }
44
+ }
45
+ return executions;
46
+ }
47
+ }
@@ -0,0 +1,2 @@
1
+ export { ActionPlan, type ActionContext, type ActionDefinition, type ActionExecution, type PlannedAction, } from "./action.js";
2
+ export { ActionRegistry } from "./registry.js";
@@ -0,0 +1,2 @@
1
+ export { ActionPlan, } from "./action.js";
2
+ export { ActionRegistry } from "./registry.js";
@@ -0,0 +1,12 @@
1
+ import type { ActionDefinition } from "./action.js";
2
+ /**
3
+ * The agent's menu of possible actions. Built in code at startup (actions
4
+ * are behavior, not data — they live in your codebase, not the database).
5
+ */
6
+ export declare class ActionRegistry {
7
+ private readonly actions;
8
+ register(action: ActionDefinition): this;
9
+ get(name: string): ActionDefinition | undefined;
10
+ list(): ActionDefinition[];
11
+ get size(): number;
12
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The agent's menu of possible actions. Built in code at startup (actions
3
+ * are behavior, not data — they live in your codebase, not the database).
4
+ */
5
+ export class ActionRegistry {
6
+ actions = new Map();
7
+ register(action) {
8
+ if (!action.name || action.name.trim() === "") {
9
+ throw new Error("Action name must be a non-empty string.");
10
+ }
11
+ if (this.actions.has(action.name)) {
12
+ throw new Error(`Action "${action.name}" is already registered.`);
13
+ }
14
+ this.actions.set(action.name, action);
15
+ return this;
16
+ }
17
+ get(name) {
18
+ return this.actions.get(name);
19
+ }
20
+ list() {
21
+ return [...this.actions.values()];
22
+ }
23
+ get size() {
24
+ return this.actions.size;
25
+ }
26
+ }
@@ -0,0 +1,141 @@
1
+ import type { ContextEvent } from "./events/context-event.js";
2
+ import type { MemoryStore } from "./memory/store.js";
3
+ import { type Engagement, type ShortTermMemory } from "./short-term/short-term.js";
4
+ import type { EmotionalState } from "./emotion/state.js";
5
+ import type { Persona } from "./emotion/persona.js";
6
+ import type { LLMClient } from "./llm/types.js";
7
+ import { ActionRegistry } from "./actions/registry.js";
8
+ import type { Interpreter } from "./pipeline/interpretation.js";
9
+ import { type Recaller } from "./pipeline/recaller.js";
10
+ import { InterpretRecallLoop, type InterpretRecallResult } from "./pipeline/loop.js";
11
+ import { type AppraisalResult, type Appraiser } from "./pipeline/appraiser.js";
12
+ import { type TimeAppraisalResult, type TimeAppraiser } from "./pipeline/time-appraiser.js";
13
+ import { type WriteResult, type Writer } from "./pipeline/writer.js";
14
+ import { type ProcessResult, type Processor } from "./pipeline/processor.js";
15
+ import { type ActResult, type Actor } from "./pipeline/actor.js";
16
+ import { type Consolidator } from "./pipeline/consolidator.js";
17
+ import { type EnqueueOutcome } from "./pipeline/inbox.js";
18
+ export interface AgentOptions {
19
+ /** Used to build every default stage. Override stages individually to
20
+ * use different models per stage. */
21
+ llm: LLMClient;
22
+ memory: MemoryStore;
23
+ /** The agent's short-term window of recent engagements — fed to the
24
+ * interpreter and processor for immediate conversational context. Defaults
25
+ * to a process-local {@link InMemoryShortTermMemory}; pass a persistent one
26
+ * to keep the window across sessions. */
27
+ shortTermMemory?: ShortTermMemory;
28
+ emotions: EmotionalState;
29
+ /** The action menu. Omit (or leave empty) for an agent that only
30
+ * perceives, feels, and remembers — the processor stage is skipped. */
31
+ actions?: ActionRegistry;
32
+ persona?: Persona;
33
+ timeAppraiser?: TimeAppraiser;
34
+ interpreter?: Interpreter;
35
+ recaller?: Recaller;
36
+ /** Supersedes `interpreter`/`recaller` if provided (a loop already
37
+ * contains both). */
38
+ loop?: InterpretRecallLoop;
39
+ appraiser?: Appraiser;
40
+ writer?: Writer;
41
+ processor?: Processor;
42
+ /** Runs the chosen plan and records what the agent did. Defaults to
43
+ * {@link DefaultActor}, which executes via the actions' own `act` handlers. */
44
+ actor?: Actor;
45
+ /** Writes memory from the agent's own actions (e.g. "I met Bill" → remember
46
+ * meeting Bill). Defaults to {@link LLMConsolidator}. */
47
+ consolidator?: Consolidator;
48
+ /** Max interpreter LLM calls per event (default 3). Ignored when a
49
+ * custom `loop` is provided. */
50
+ maxLoopIterations?: number;
51
+ }
52
+ export interface HandleEventOptions {
53
+ /** Cancellation for the coalescing inbox. When it aborts before the
54
+ * appraisal commits, the heartbeat throws {@link HeartbeatCancelled} at its
55
+ * next stage boundary. Set by `enqueue`; omit for a plain, uninterruptible
56
+ * run. */
57
+ signal?: AbortSignal;
58
+ /** Called synchronously the instant the heartbeat passes its last
59
+ * cancellable point (just before feelings persist). Set by `enqueue`. */
60
+ onCommit?: () => void;
61
+ }
62
+ /** The full transcript of one heartbeat — every stage's receipt. Log this
63
+ * and you can replay exactly why the agent felt and did what it did. */
64
+ export interface AgentResult {
65
+ event: ContextEvent;
66
+ /** The short-term window the agent walked in with — the recent engagements
67
+ * the interpreter and processor reasoned over (this event not yet added). */
68
+ shortTerm: Engagement[];
69
+ time: TimeAppraisalResult;
70
+ interpretation: InterpretRecallResult;
71
+ appraisal: AppraisalResult;
72
+ memory: WriteResult;
73
+ actions: ProcessResult;
74
+ /** What the agent actually did — the executed plan's outcomes. */
75
+ acted: ActResult;
76
+ /** Memory written from the agent's own actions this turn. */
77
+ consolidation: WriteResult;
78
+ }
79
+ export type AgentStage = "time-appraisal" | "interpretation" | "appraisal" | "write" | "process" | "act" | "consolidate";
80
+ /** Wraps a stage failure with which stage broke; the original error is on
81
+ * `cause`. Bad LLM *output* never raises this (stages degrade to no-ops) —
82
+ * this is for genuine failures: LLM outage, database down, bugs. */
83
+ export declare class AgentError extends Error {
84
+ readonly stage: AgentStage;
85
+ constructor(stage: AgentStage, cause: unknown);
86
+ }
87
+ /**
88
+ * The orchestrator: wires the six pipeline stages into one call.
89
+ *
90
+ * handleEvent(event):
91
+ * 1. time appraisal feelings drift for the time since last contact
92
+ * 2. interpret/recall understand the event, grounded in memories
93
+ * 3. event appraisal feelings respond (persisted)
94
+ * 4. writer new facts filed, contradictions superseded
95
+ * 5. processor actions chosen in-feeling; plan returned, never
96
+ * executed — the caller runs plan.execute()
97
+ *
98
+ * Every stage is the shipped default unless overridden in options, and the
99
+ * developer-owned pieces (memory, emotions, actions, persona, LLM) are
100
+ * injected — so any layer can be rewritten without touching this class.
101
+ */
102
+ export declare class Agent {
103
+ readonly memory: MemoryStore;
104
+ readonly shortTermMemory: ShortTermMemory;
105
+ readonly emotions: EmotionalState;
106
+ readonly actions: ActionRegistry;
107
+ readonly persona: Persona | undefined;
108
+ private readonly timeAppraiser;
109
+ private readonly loop;
110
+ private readonly appraiser;
111
+ private readonly writer;
112
+ private readonly processor;
113
+ private readonly actor;
114
+ private readonly consolidator;
115
+ /** Serializes + coalesces events for this agent. enqueue() is the entry;
116
+ * it drives handleEvent under cancellation. */
117
+ private readonly inbox;
118
+ constructor(options: AgentOptions);
119
+ /**
120
+ * The production entry point: hand an event to this agent's funnel. Events
121
+ * for one agent process one at a time; a burst that arrives before the
122
+ * current heartbeat commits its feelings is merged and run as one. Resolves
123
+ * to the heartbeat's {@link AgentResult}, or a {@link MergedOutcome} marker
124
+ * when this event was folded into a later one (do nothing in that case).
125
+ *
126
+ * Prefer this over {@link handleEvent} — it is the only path that serializes
127
+ * and coalesces. handleEvent runs immediately and bypasses both.
128
+ */
129
+ enqueue(event: ContextEvent): Promise<EnqueueOutcome<AgentResult>>;
130
+ /**
131
+ * Run one heartbeat immediately, bypassing the funnel. Internal: the inbox
132
+ * calls this under cancellation control. Calling it directly skips
133
+ * serialization and coalescing — only safe when you guarantee no concurrent
134
+ * events for this agent. Most callers want {@link enqueue}.
135
+ */
136
+ handleEvent(event: ContextEvent, options?: HandleEventOptions): Promise<AgentResult>;
137
+ /** Record one engagement in short-term memory: what the agent perceived and
138
+ * the words it actually said back (joined; empty when it stayed silent). */
139
+ private remember;
140
+ private stage;
141
+ }