alive-ai 0.1.0 → 0.1.2

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 CHANGED
@@ -1,57 +1,77 @@
1
- # Alive-AI
1
+ <div align="center">
2
+ <img src="docs/assets/logo.svg" alt="Alive-AI" width="96" height="96">
2
3
 
3
- ![Alive-AI logo](docs/assets/logo.svg)
4
+ # Alive-AI
4
5
 
5
- Give your AI a nervous system: persistent feelings, memory, impulses, and a local dashboard.
6
+ Give your AI a nervous system: persistent mood, memory, impulses, terminal chat, Telegram, OpenMind, and a local WebUI.
6
7
 
7
- Most agents answer a prompt and reset. Alive-AI keeps internal state alive between messages. It can be your friend, boyfriend, girlfriend, study partner, creative partner, or any local companion you configure. The experiment asks a harder question: what changes when an AI does not just respond, but carries emotional residue forward?
8
+ [![npm](https://img.shields.io/npm/v/alive-ai)](https://www.npmjs.com/package/alive-ai)
9
+ [![Node.js 18+](https://img.shields.io/badge/Node.js-18%2B-339933?logo=nodedotjs&logoColor=white)](https://nodejs.org/)
10
+ [![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/)
11
+ [![Platforms](https://img.shields.io/badge/macOS%20%7C%20Windows%20%7C%20Linux-supported-41f0a1)](#platform-support)
12
+ [![OpenMind](https://img.shields.io/badge/OpenMind-optional-6366F1)](#openmind-memory)
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
14
+ </div>
8
15
 
9
- Alive-AI does not claim biological consciousness. It is an open-source runtime for simulated affect: mood, attachment, trust, desire, memory, inconsistency, idle thoughts, and proactive impulses.
16
+ Alive-AI is a local-first emotional AI runtime. Most agents answer a prompt and reset. Alive-AI keeps internal state alive between messages: mood, attachment, trust, desire, memory, inconsistency, idle thoughts, proactive impulses, and a dashboard that shows what is happening inside the loop.
10
17
 
11
- ## Install
18
+ It can be used as a friend, partner-style companion, study partner, creative character, research subject, or experimental local agent. Use it at your own risk: it is designed to feel continuous, warm, attached, and present, and that can make it hard to stop talking to it.
19
+
20
+ Alive-AI does not claim biological consciousness. It is an open-source runtime for simulated affect and transparent memory.
21
+
22
+ ## Quick Start
12
23
 
13
24
  ```bash
14
- npx github:vindepemarte/alive-ai init my-ai
25
+ npx alive-ai@latest init my-ai
15
26
  cd my-ai
16
27
  npx . setup
17
- npx . demo
28
+ npx . doctor
29
+ npx . chat
30
+ ```
31
+
32
+ The terminal chat starts the real runtime and prints responses in your shell. The dashboard runs locally at:
33
+
34
+ ```text
35
+ http://127.0.0.1:8080
18
36
  ```
19
37
 
20
- Start the real runtime:
38
+ To use Telegram instead of terminal chat:
21
39
 
22
40
  ```bash
23
41
  npx . start
24
42
  ```
25
43
 
26
- The local dashboard runs at:
44
+ Global install is optional:
27
45
 
28
- ```text
29
- http://127.0.0.1:8080
46
+ ```bash
47
+ npm install -g alive-ai
48
+ alive-ai init my-ai
30
49
  ```
31
50
 
32
- ## Why This Is Different
51
+ ## Commands
33
52
 
34
- - **Emotions persist.** State does not reset after every message. Joy, trust, fear, anticipation, attachment, and vulnerability decay over time instead of disappearing.
35
- - **Memory has weight.** Conversations become episodic memory, semantic memory, and emotional memory.
36
- - **It thinks when idle.** A default-mode loop creates background reflections and proactive impulses.
37
- - **It has a live nervous system.** FastAPI + SSE exposes mood, thoughts, somatic state, conflicts, memories, and uptime.
38
- - **It is local-first.** Your config, memory, media, and dashboard are owned by the project folder you run.
53
+ | Command | What it does |
54
+ | --- | --- |
55
+ | `npx alive-ai@latest init my-ai` | Scaffold a clean local Alive-AI project. |
56
+ | `npx . setup` | Guided onboarding for local config, providers, Telegram, voice, images, and memory. |
57
+ | `npx . doctor` | Check OS, Node, Python, uv, ffmpeg, Docker, and OpenMind reachability. |
58
+ | `npx . chat` | Start the real runtime with terminal chat input. |
59
+ | `npx . demo` | Run a keyless animated dashboard demo. |
60
+ | `npx . start` | Start the runtime using the configured input channel, usually Telegram. |
61
+ | `npx . start --skip-install` | Start again without reinstalling Python dependencies. |
39
62
 
40
- ## Commands
63
+ Stop a foreground run with `Ctrl+C`.
64
+
65
+ If you use Docker:
41
66
 
42
67
  ```bash
43
- npx github:vindepemarte/alive-ai init my-ai # scaffold a clean local project
44
- cd my-ai
45
- npx . setup # create safe local config
46
- npx . demo # preview animated dashboard, no keys needed
47
- npx . doctor # check Python, uv, ffmpeg, Docker
48
- npx . start # install Python deps and run the runtime
68
+ docker compose down
49
69
  ```
50
70
 
51
- For repeat starts after dependencies are installed:
71
+ If you only started Redis:
52
72
 
53
73
  ```bash
54
- npx . start --skip-install
74
+ docker compose stop redis
55
75
  ```
56
76
 
57
77
  ## Setup
@@ -68,14 +88,34 @@ mypics/
68
88
  myvids/
69
89
  ```
70
90
 
71
- Minimum useful setup:
91
+ The setup accepts `skip` for optional keys and `local` for Ollama.
92
+
93
+ | Setup item | Options |
94
+ | --- | --- |
95
+ | LLM | `local`/Ollama, OpenRouter, ZAI, or `skip` for demo/fallback-only mode. |
96
+ | Telegram | Bot token and owner ID are optional. Use terminal chat if you do not want Telegram. |
97
+ | Voice | `gtts` local/free default, Google TTS, VibeVoice, or `skip`. |
98
+ | Images | Fal.ai API key or `skip`. Local media folders still work without image generation. |
99
+ | Memory | Built-in local memory, OpenMind cloud, or OpenMind local. |
72
100
 
73
- - **Demo only:** no keys.
74
- - **Local LLM:** install Ollama and pull the configured model, for example `ollama pull qwen3:4b`.
75
- - **Telegram runtime:** create a Telegram bot token with BotFather and add it during setup.
76
- - **Cloud LLM fallback:** add OpenRouter or ZAI keys during setup or edit `config/settings.json`.
101
+ Minimum useful paths:
77
102
 
78
- Media is optional. Add your own files:
103
+ ```bash
104
+ # Terminal-only local run
105
+ npx . setup
106
+ npx . chat
107
+
108
+ # Local LLM
109
+ ollama pull qwen3:4b
110
+ npx . setup
111
+ npx . chat
112
+
113
+ # Telegram
114
+ npx . setup
115
+ npx . start
116
+ ```
117
+
118
+ Media is optional. Add your own local files:
79
119
 
80
120
  ```text
81
121
  mypics/example.jpg
@@ -84,38 +124,114 @@ myvids/example.mp4
84
124
  myvids/example.txt
85
125
  ```
86
126
 
87
- ## Architecture
127
+ ## Terminal Chat
128
+
129
+ `npx . chat` uses the same core runtime as Telegram. It emits the same `message_received` events, saves memory the same way, and updates the local WebUI.
130
+
131
+ Terminal commands:
132
+
133
+ ```text
134
+ /help
135
+ /status
136
+ /stats
137
+ /dashboard
138
+ /self
139
+ /discover <trait>
140
+ /iam <key>=<value>
141
+ /ilike <thing>
142
+ /ihate <thing>
143
+ /rethink
144
+ /settings show
145
+ /settings get <key>
146
+ /settings set <key> <value>
147
+ /reset
148
+ /impulse
149
+ /exit
150
+ ```
151
+
152
+ ## OpenMind Memory
153
+
154
+ Alive-AI has built-in local working, episodic, semantic, and emotional memory. OpenMind is optional and works as a hybrid long-term semantic memory layer.
155
+
156
+ Modes:
157
+
158
+ | Mode | Behavior |
159
+ | --- | --- |
160
+ | Built-in only | Alive-AI uses its local project memory only. |
161
+ | OpenMind cloud | Alive-AI captures/searches long-term memories through `https://theopenmind.pro`. |
162
+ | OpenMind local | Alive-AI captures/searches a local OpenMind server, normally `http://127.0.0.1:3333`. |
88
163
 
89
- Alive-AI is an event-driven Python runtime.
164
+ OpenMind does not replace Alive-AI's emotional state. It adds durable semantic recall across tools and machines.
165
+
166
+ Cloud setup:
90
167
 
91
168
  ```text
92
- Telegram or input
93
- -> NervousSystem event bus
94
- -> Message handler
95
- -> Heart, memory, skills, directives, personality
96
- -> LLM provider or fallback chain
97
- -> output events
98
- -> dashboard state stream
169
+ OPENMIND_ENABLED=true
170
+ OPENMIND_MODE=hybrid
171
+ OPENMIND_BASE_URL=https://theopenmind.pro
172
+ OPENMIND_API_KEY=om_...
173
+ ```
174
+
175
+ Local setup:
176
+
177
+ ```bash
178
+ npx @vindepemarte/openmind init --local
179
+ # or run your local OpenMind stack, then configure Alive-AI:
180
+ OPENMIND_BASE_URL=http://127.0.0.1:3333
99
181
  ```
100
182
 
101
- Core subsystems:
183
+ ## Requirements
184
+
185
+ Minimum for cloud LLMs or remote Ollama:
102
186
 
103
- - `heart/`: continuous emotion, circadian rhythm, attachment, scars, somatic state, inconsistency.
104
- - `brain/`: LLM providers, memory, default-mode processing, bid detection, curiosity, dreams.
105
- - `skills/`: self-authorship, memory callbacks, relationship milestones, progression layers, media selection.
106
- - `webui/`: local dashboard with Server-Sent Events.
107
- - `input/telegram/`: Telegram listener and owner commands.
187
+ | Requirement | Minimum |
188
+ | --- | --- |
189
+ | Node.js | 18+ |
190
+ | Python | 3.11+ |
191
+ | RAM | 8 GB |
192
+ | Disk | 2 GB free |
193
+ | LLM | OpenRouter, ZAI, remote Ollama, or local Ollama already installed |
194
+
195
+ Comfortable local setup:
196
+
197
+ | Requirement | Recommended |
198
+ | --- | --- |
199
+ | Node.js | 20+ |
200
+ | RAM | 16 GB for 3B-4B local models |
201
+ | RAM for bigger models | 32 GB for 7B+ local models, Redis, voice, and long sessions |
202
+ | Disk | 10 GB+, more if you keep local models/media |
203
+ | Optional tools | `uv`, `ffmpeg`, Docker, Ollama |
204
+
205
+ `npx . start` creates `.alive-ai/venv` and installs Python dependencies. System-level packages such as Node, Python, Ollama, Docker, and ffmpeg must already exist on the machine.
206
+
207
+ ## Platform Support
208
+
209
+ Alive-AI is designed for macOS, Windows, and Linux.
210
+
211
+ | Platform | Notes |
212
+ | --- | --- |
213
+ | macOS | First-class local development path. Use Homebrew for Python, uv, ffmpeg, Docker, and Ollama. |
214
+ | Windows | Supported from PowerShell with Node 18+ and Python 3.11+. WSL is recommended for heavier local model and Docker workflows. |
215
+ | Linux | Supported with distro packages for Python/venv, ffmpeg, Docker, and Ollama. |
216
+
217
+ Local model quality and speed depend on your machine. Cloud LLMs reduce RAM pressure.
108
218
 
109
219
  ## Dashboard
110
220
 
111
- `npx . demo` starts a zero-config animated dashboard preview. The real dashboard uses the same idea, but streams live state from the runtime:
221
+ The real WebUI streams local runtime state over Server-Sent Events and shows:
112
222
 
113
- - emotions and mood,
114
- - recent thoughts,
115
- - memory counters,
116
- - somatic state,
117
- - attachment/inconsistency signals,
118
- - uptime and health.
223
+ - emotional state,
224
+ - recent thoughts and idle processing,
225
+ - memory counters and uptime,
226
+ - hormones and interoceptive body state,
227
+ - attachment, circadian rhythm, body memory, dreams, curiosity, and conflicts,
228
+ - runtime health through local endpoints.
229
+
230
+ GitHub Pages cannot run the Python/FastAPI backend, so the public page includes a static export of the actual WebUI with mocked state:
231
+
232
+ ```text
233
+ https://vindepemarte.github.io/alive-ai/
234
+ ```
119
235
 
120
236
  ## Docker
121
237
 
@@ -132,9 +248,41 @@ Or run everything in containers:
132
248
  docker compose up --build
133
249
  ```
134
250
 
251
+ ## Roadmap
252
+
253
+ Implemented:
254
+
255
+ - [x] Local-first emotional runtime
256
+ - [x] Persistent emotion model with decay and compound state
257
+ - [x] Working, episodic, semantic, and emotional memory modules
258
+ - [x] Default-mode loop for idle thoughts and proactive impulses
259
+ - [x] Attachment, circadian rhythm, body memory, curiosity, dreams, and internal conflicts
260
+ - [x] Per-user memory/state isolation
261
+ - [x] Telegram input/output runtime
262
+ - [x] Terminal chat runtime with owner-style slash commands
263
+ - [x] Local WebUI dashboard with live state streaming
264
+ - [x] Optional hybrid OpenMind cloud/local semantic memory
265
+ - [x] npm/npx CLI scaffold, setup, doctor, demo, chat, and start commands
266
+ - [x] Clean public repo with private personas, media, runtime data, and multi-AI orchestration removed
267
+ - [x] GitHub Pages site and full static WebUI export
268
+
269
+ Next:
270
+
271
+ - [ ] One-command local model bootstrap through Ollama profiles
272
+ - [ ] Desktop app wrapper with tray controls and local service lifecycle
273
+ - [ ] Browser-based onboarding wizard for personality, boundaries, LLM provider, and memory settings
274
+ - [ ] Better guided system install commands per OS
275
+ - [ ] More input channels beyond terminal and Telegram
276
+ - [ ] Import/export for memories and personality snapshots
277
+ - [ ] Plugin API for new senses, skills, and output modalities
278
+ - [ ] Evaluation harness for emotional continuity, memory drift, and unhealthy attachment risk
279
+ - [ ] Optional cloud sync that preserves local-first ownership
280
+
135
281
  ## Important Boundaries
136
282
 
137
- Alive-AI is a simulation framework. It can make agents feel more continuous, emotionally coherent, and alive, but it is not proof of consciousness and should not be used to manipulate emotional dependence.
283
+ Alive-AI is a simulation framework. It can make agents feel more continuous, emotionally coherent, and alive, but it is not proof of consciousness.
284
+
285
+ Do not use it to manipulate emotional dependence. If you are building a companion, character, partner, or friend-like system, make the boundaries explicit and keep the operator in control.
138
286
 
139
287
  The public repo intentionally excludes private personas, private media, runtime data, and secrets. Put those only in your local project folder.
140
288
 
@@ -37,11 +37,19 @@ class Memory:
37
37
  self.fact_extractor = FactExtractor(self.data_path / "facts.json")
38
38
  self.summarizer = ConversationSummarizer(self.data_path)
39
39
  self.vector_store = None
40
+ self.openmind = None
40
41
  self.bot_id = bot_id.lower()
41
42
  if embedding_service:
42
43
  self.vector_store = VectorMemoryStore(embedding_service, user_id=user_id, bot_id=bot_id)
43
44
  if self.vector_store.connect():
44
45
  print(f"[Memory] Vector store ready for user {user_id} on bot {bot_id}! {self.vector_store.count()} memories")
46
+ try:
47
+ from .openmind import OpenMindMemoryBridge
48
+ if OpenMindMemoryBridge.enabled():
49
+ self.openmind = OpenMindMemoryBridge(nervous, user_id=user_id, bot_id=bot_id)
50
+ print(f"[Memory] OpenMind bridge enabled for user {user_id} on bot {bot_id}")
51
+ except Exception as e:
52
+ print(f"[Memory] OpenMind bridge unavailable: {e}")
45
53
  self.turn_count = 0
46
54
  nervous.on("memory_save", self._on_save)
47
55
 
@@ -123,6 +131,14 @@ class Memory:
123
131
  related = ""
124
132
  if current_message and self.vector_store:
125
133
  related = self.search_relevant_memories(current_message, limit=3)
134
+ if current_message and self.openmind:
135
+ openmind_related = await self.openmind.search_context(current_message, limit=3)
136
+ if openmind_related:
137
+ related = (
138
+ f"{related}\n\nOpenMind long-term memory:\n{openmind_related}"
139
+ if related else
140
+ f"OpenMind long-term memory:\n{openmind_related}"
141
+ )
126
142
 
127
143
  # Get working memory (empty after restart)
128
144
  history = self.working.get_history()
@@ -0,0 +1,128 @@
1
+ """Optional OpenMind semantic memory bridge."""
2
+
3
+ import asyncio
4
+ import os
5
+ from typing import Any, Dict, List, Optional
6
+
7
+ import aiohttp
8
+
9
+ from core.settings import get as settings_get
10
+
11
+
12
+ class OpenMindMemoryBridge:
13
+ """Syncs Alive-AI turns to OpenMind and retrieves long-term semantic context."""
14
+
15
+ def __init__(self, nervous, user_id: str, bot_id: str):
16
+ self.nervous = nervous
17
+ self.user_id = str(user_id or "default")
18
+ self.bot_id = str(bot_id or "alive_ai").lower()
19
+ nervous.on("memory_save", self._on_memory_save)
20
+
21
+ @staticmethod
22
+ def enabled() -> bool:
23
+ return str(settings_get("OPENMIND_ENABLED", os.environ.get("OPENMIND_ENABLED", "false"))).lower() in (
24
+ "1", "true", "yes", "on"
25
+ )
26
+
27
+ @staticmethod
28
+ def base_url() -> str:
29
+ return str(settings_get("OPENMIND_BASE_URL", os.environ.get("OPENMIND_BASE_URL", "https://theopenmind.pro"))).rstrip("/")
30
+
31
+ @staticmethod
32
+ def api_key() -> str:
33
+ return str(settings_get("OPENMIND_API_KEY", os.environ.get("OPENMIND_API_KEY", ""))).strip()
34
+
35
+ def _headers(self) -> Dict[str, str]:
36
+ headers = {"content-type": "application/json"}
37
+ key = self.api_key()
38
+ if key:
39
+ headers["authorization"] = f"Bearer {key}"
40
+ return headers
41
+
42
+ def _on_memory_save(self, data: dict):
43
+ if not self.enabled() or data.get("type") != "conversation":
44
+ return
45
+ event_user_id = data.get("user_id")
46
+ if event_user_id:
47
+ if str(event_user_id) != self.user_id:
48
+ return
49
+ elif self.user_id != "default":
50
+ return
51
+ asyncio.ensure_future(self.capture_turn(data))
52
+
53
+ async def capture_turn(self, data: dict) -> Optional[dict]:
54
+ user_msg = (data.get("user_message") or "").strip()
55
+ ai_msg = (data.get("ai_response") or "").strip()
56
+ if not user_msg and not ai_msg:
57
+ return None
58
+
59
+ emotion = data.get("emotion") or {}
60
+ mood = emotion.get("mood", "unknown")
61
+ content = "\n".join(
62
+ part for part in [
63
+ f"Alive-AI agent: {self.bot_id}",
64
+ f"User id: {self.user_id}",
65
+ f"Mood: {mood}",
66
+ f"User: {user_msg}" if user_msg else "",
67
+ f"Alive-AI: {ai_msg}" if ai_msg else "",
68
+ ] if part
69
+ )
70
+ tags = ["alive-ai", self.bot_id, f"user-{self.user_id}", f"mood-{mood}"]
71
+ payload = {
72
+ "content": content,
73
+ "source": "alive-ai",
74
+ "type": "conversation",
75
+ "tags": tags,
76
+ }
77
+
78
+ try:
79
+ timeout = aiohttp.ClientTimeout(total=12)
80
+ async with aiohttp.ClientSession(timeout=timeout) as session:
81
+ async with session.post(f"{self.base_url()}/capture", json=payload, headers=self._headers()) as resp:
82
+ if resp.status >= 400:
83
+ body = await resp.text()
84
+ print(f"[OpenMind] Capture failed ({resp.status}): {body[:200]}")
85
+ return None
86
+ result = await resp.json()
87
+ print(f"[OpenMind] Captured memory: {result.get('status', 'ok')}")
88
+ return result
89
+ except Exception as exc:
90
+ print(f"[OpenMind] Capture unavailable: {exc}")
91
+ return None
92
+
93
+ async def search_context(self, query: str, limit: int = 3) -> str:
94
+ if not self.enabled() or not query.strip():
95
+ return ""
96
+ try:
97
+ timeout = aiohttp.ClientTimeout(total=10)
98
+ async with aiohttp.ClientSession(timeout=timeout) as session:
99
+ async with session.get(
100
+ f"{self.base_url()}/search",
101
+ params={"q": query, "limit": str(limit)},
102
+ headers=self._headers(),
103
+ ) as resp:
104
+ if resp.status >= 400:
105
+ body = await resp.text()
106
+ print(f"[OpenMind] Search failed ({resp.status}): {body[:200]}")
107
+ return ""
108
+ rows = await resp.json()
109
+ except Exception as exc:
110
+ print(f"[OpenMind] Search unavailable: {exc}")
111
+ return ""
112
+
113
+ if not isinstance(rows, list):
114
+ return ""
115
+ return self._format_results(rows[:limit])
116
+
117
+ def _format_results(self, rows: List[Dict[str, Any]]) -> str:
118
+ lines = []
119
+ for row in rows:
120
+ content = str(row.get("content") or row.get("summary") or "").strip()
121
+ if not content:
122
+ continue
123
+ similarity = row.get("similarity")
124
+ prefix = "OpenMind"
125
+ if isinstance(similarity, (int, float)):
126
+ prefix = f"OpenMind {round(similarity * 100)}%"
127
+ lines.append(f"{prefix}: {content[:700]}")
128
+ return "\n".join(lines)