ohwow 0.1.13 → 0.3.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 (35) hide show
  1. package/LICENSE +17 -17
  2. package/README.md +202 -138
  3. package/dist/api.d.ts +91 -0
  4. package/dist/api.js +2 -0
  5. package/dist/index.d.ts +1 -90
  6. package/dist/index.js +1983 -596
  7. package/dist/mcp-server/index.js +64 -49
  8. package/dist/migrations/001-data-plane-tables.sql +1 -1
  9. package/dist/migrations/002-agents-table.sql +1 -1
  10. package/dist/migrations/017-openclaw-call-logs.sql +15 -0
  11. package/dist/migrations/038-peer-queue-tracking.sql +5 -0
  12. package/dist/migrations/039-task-delegation.sql +5 -0
  13. package/dist/migrations/040-self-improvement-tables.sql +109 -0
  14. package/dist/migrations/041-session-metadata.sql +3 -0
  15. package/dist/migrations/042-memory-sync.sql +45 -0
  16. package/dist/migrations/043-multi-connection.sql +18 -0
  17. package/dist/migrations/044-multi-connection-fixes.sql +32 -0
  18. package/dist/migrations/045-task-state.sql +21 -0
  19. package/dist/migrations/046-state-changelog.sql +18 -0
  20. package/dist/migrations/047-outbound-queue.sql +9 -0
  21. package/dist/migrations/048-tasks-column-alignment.sql +37 -0
  22. package/dist/migrations/049-agents-column-alignment.sql +25 -0
  23. package/dist/migrations/050-workflows-trigger-alignment.sql +25 -0
  24. package/dist/migrations/051-execution-engine-tables.sql +132 -0
  25. package/dist/migrations/052-a2a-rate-limit-alignment.sql +8 -0
  26. package/dist/migrations/053-llm-cache.sql +20 -0
  27. package/dist/migrations/054-task-checkpoints.sql +13 -0
  28. package/dist/migrations/055-resource-usage.sql +12 -0
  29. package/dist/migrations/056-sandbox-tables.sql +35 -0
  30. package/dist/migrations/057-persona-soul.sql +20 -0
  31. package/dist/web/assets/index-DkZG6rzJ.css +1 -0
  32. package/dist/web/assets/{index-D6DkPUkA.js → index-fXgVWRQU.js} +28 -28
  33. package/dist/web/index.html +2 -2
  34. package/package.json +59 -14
  35. package/dist/web/assets/index-DSojxPLI.css +0 -1
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- Business Source License 1.1
1
+ MIT License
2
2
 
3
- Parameters
3
+ Copyright (c) 2026 Jesus David Oñoro Delgado
4
4
 
5
- Licensor: ohwow
6
- Licensed Work: ohwow runtime (all versions)
7
- Additional Use Grant: You may use the Licensed Work for any purpose, including
8
- production use, EXCEPT for building or offering a product
9
- or service that competes with ohwow.fun or its features.
10
- Change Date: March 2, 2030
11
- Change License: Apache License, Version 2.0
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:
12
11
 
13
- For the full BSL 1.1 license text, see https://mariadb.com/bsl11/
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
14
 
15
- Notice
16
-
17
- The Licensed Work is (c) 2024-2026 ohwow.
18
-
19
- The full text of the Business Source License 1.1 is incorporated by reference
20
- from the URL above. This file states only the parameters specific to this
21
- project. In the event of any conflict, the full license text governs.
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 CHANGED
@@ -1,224 +1,288 @@
1
1
  # ohwow
2
2
 
3
- Send me a message for support at ogsus@ohwow.fun
3
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
4
+ [![npm version](https://img.shields.io/npm/v/ohwow)](https://www.npmjs.com/package/ohwow)
5
+ [![CI](https://github.com/ohwow-fun/ohwow/actions/workflows/ci.yml/badge.svg)](https://github.com/ohwow-fun/ohwow/actions/workflows/ci.yml)
6
+ [![npm downloads](https://img.shields.io/npm/dm/ohwow)](https://www.npmjs.com/package/ohwow)
7
+ [![Discord](https://img.shields.io/badge/Discord-join-5865F2)](https://discord.gg/WUGnGqceeY)
4
8
 
5
- A free and open-source local AI agent runtime. Full-featured out of the box with [Ollama](https://ollama.com) for local models. Cloud features (sync, OAuth integrations, cloud task dispatch, webhook relay) available with an [ohwow.fun](https://ohwow.fun) subscription.
9
+ **An AI team that runs on your laptop. Agents that learn your patterns, message your customers, automate your operations, and actually understand what your business needs right now. Free. Open source. Your data stays on your machine.**
6
10
 
7
- ## Getting Started
8
-
9
- ### Install
11
+ <p align="center">
12
+ <img src="docs/demo.gif" alt="ohwow demo" width="800">
13
+ </p>
10
14
 
11
15
  ```bash
12
16
  npm install ohwow -g
17
+ ohwow
13
18
  ```
14
19
 
15
- ### Requirements
20
+ Running in under 5 minutes. A setup wizard connects to [Ollama](https://ollama.com), picks a model, and builds an AI team for your business type.
16
21
 
17
- - Node.js 20+
18
- - [Ollama](https://ollama.com) for local models
19
- - Optional: Anthropic API key (for Claude models)
20
- - Optional: Playwright browsers (`npx playwright install chromium`) for browser automation
21
- - Optional: C++ compiler may be needed on some platforms for `better-sqlite3`
22
+ ---
22
23
 
23
- ### Launch
24
+ ## What a day looks like with ohwow
24
25
 
25
- ```bash
26
- ohwow
27
- ```
26
+ **7:45 AM** — You open your laptop. ohwow noticed you always start around this time. Your morning briefing is ready: "3 tasks completed overnight. 1 needs your eye (a customer contract with unusual terms). 2 leads replied to yesterday's outreach. Your Sales Agent's follow-up is queued for 9am."
28
27
 
29
- ## First Launch
28
+ **8:00 AM** — You say: "What should I focus on today?" ohwow knows you're at growth stage 2 (Attract). It responds: "You're over-indexing on content creation this week. Your growth stage needs more outreach. Your Sales Agent has 3 warm leads that haven't been contacted. Want me to draft follow-ups?"
30
29
 
31
- A setup wizard appears in your terminal. Point it at your Ollama instance to get started. To connect to ohwow.fun cloud, enter your license key (from the ohwow.fun dashboard, under Settings > License).
30
+ **8:15 AM** You approve the follow-ups. The Sales Agent sends personalized WhatsApp messages to each lead, referencing their specific context from your CRM. No templates. Each message reads like you wrote it.
32
31
 
33
- Config is saved to `~/.ohwow/config.json`. You only do this once.
32
+ **10:30 AM** You're deep in product work. A customer emails with a support question. ohwow detects it, routes it to the Support Agent, which drafts a response. Because your cognitive load is high (3 open approvals, deep work mode), it batches the notification instead of interrupting. You'll see it at your next natural break.
34
33
 
35
- ## What Happens at Startup
34
+ **2:00 PM** ohwow notices your energy dips after lunch (it learned this from 30 days of watching your activity patterns). It holds the complex research report that just completed, knowing you'll evaluate it better in the morning. Instead, it surfaces a simple approval that takes 10 seconds.
36
35
 
37
- Once configured, the runtime:
36
+ **4:00 PM** — A lead responds positively on WhatsApp. ohwow's Sales Agent wants to send a pricing proposal. It could auto-send (it's earned that trust after 47 successful outreach tasks with 94% approval), but the amount is above the auto-approve threshold. You get a one-line notification: "Ready to send pricing to Acme Corp. $4,500/mo proposal. Approve?"
38
37
 
39
- 1. Loads config from `~/.ohwow/config.json`
40
- 2. Spawns the daemon process
41
- 3. Initializes the local SQLite database
42
- 4. Starts the execution engine, orchestrator, and model router
43
- 5. Connects messaging channels (WhatsApp, Telegram) if configured
44
- 6. Starts the scheduler, proactive engine, and trigger evaluator
45
- 7. Launches the HTTP server (default port 7700)
46
- 8. Connects to the ohwow.fun control plane (enterprise)
47
- 9. Opens a WebSocket for real-time updates
38
+ **6:15 PM** — You close your laptop. ohwow stops all non-critical notifications. Your agents keep working: the Content Writer drafts tomorrow's blog post, the Researcher compiles a competitive analysis you asked for this morning. Results will be waiting when you open up tomorrow.
48
39
 
49
- From here, agents execute tasks on your hardware using your own API keys. The dashboard sends the work, your machine does the thinking.
40
+ **End of day**: 12 tasks completed across 4 agents. 3 leads contacted. 1 support ticket resolved. 1 blog draft ready. You spent 20 minutes on approvals. The rest was your work.
50
41
 
51
- ## CLI Commands
42
+ ---
52
43
 
53
- | Command | What it does |
54
- |---|---|
55
- | `ohwow` | Start the TUI (default) |
56
- | `ohwow --daemon` | Start daemon in foreground (for systemd/launchd/Docker) |
57
- | `ohwow stop` | Stop the daemon |
58
- | `ohwow status` | Check daemon status (PID and port) |
59
- | `ohwow logs` | Tail daemon logs |
60
- | `ohwow restart` | Restart the daemon |
44
+ ## How it actually works
61
45
 
62
- ## TUI
46
+ ### Talk to it like a person
63
47
 
64
- The terminal UI opens into a chat interface with tab navigation. Use arrow keys or tab to switch between:
48
+ The orchestrator understands natural language with 150+ tools behind it:
65
49
 
66
- - **Dashboard** overview of your workspace
67
- - **Agents** — manage agent configs, memory, and capabilities
68
- - **Tasks** view and manage running/completed tasks
69
- - **Approvals** review pending items before execution
70
- - **Activity** live feed of everything happening
71
- - **Automations** webhook-based automation triggers
72
- - **Contacts** CRM with leads, customers, partners
73
- - **Settings** config, connections, license
50
+ | What you say | What happens |
51
+ |---|---|
52
+ | "Follow up with everyone who opened my last email" | Finds contacts with email opens, drafts personalized follow-ups, sends via WhatsApp or email |
53
+ | "Research our top 5 competitors and create a comparison" | Launches the Research Agent with deep web search, compiles findings into a structured report |
54
+ | "Schedule outreach every weekday at 9am" | Creates a recurring schedule. The agent picks leads from your CRM, personalizes messages, and sends them on time |
55
+ | "Open Figma and export the hero banner as PNG" | Takes over your desktop, opens the app, navigates to the file, exports it, saves to your folder |
56
+ | "How's the business doing?" | Shows your eudaimonia score (workspace flourishing), task stats, lead pipeline, agent efficiency, and growth stage guidance |
57
+ | "Create a project for the website redesign" | Creates a Kanban board, suggests task breakdown, assigns agents to each phase |
58
+ | "Send a WhatsApp to the team: launching Friday" | Sends through your connected WhatsApp. No API needed. Uses your actual WhatsApp number |
59
+ | "What should I focus on this week?" | Analyzes your growth stage, current work balance, goal velocity, and team capacity. Gives specific, actionable recommendations |
74
60
 
75
- Everything you see in the web dashboard is also here, running locally.
61
+ ### Your agents learn and improve
76
62
 
77
- ## Web UI
63
+ ohwow agents aren't stateless. They remember what worked and what didn't:
78
64
 
79
- The runtime serves a built-in React app at `http://localhost:7700`. Same capabilities as the TUI. Useful if you prefer a graphical interface or want to share access with your team on the local network. Override the port with the `OHWOW_PORT` env var.
65
+ - After the Content Writer produces 50 blog posts, it knows your brand voice, preferred structure, and which topics get approved immediately vs revised
66
+ - After the Sales Agent sends 200 outreach messages, it knows which opening lines get responses and which get ignored
67
+ - After the Researcher completes 30 deep dives, it knows which sources you trust and how detailed you want the analysis
80
68
 
81
- ## Orchestrator
69
+ This isn't "fine-tuning." It's persistent memory, skill synthesis, and pattern mining that builds real expertise over time. Each agent develops its own character: some become meticulous researchers, others become fast-moving closers.
82
70
 
83
- The orchestrator is a conversational assistant built into the runtime with 40+ tools. Open the Chat tab in the TUI, or use the web UI.
71
+ ### It knows your business stage
84
72
 
85
- You can talk to it naturally:
73
+ A startup just launching needs different work than an established company scaling. ohwow knows the difference:
86
74
 
87
- | What you say | What happens |
88
- |---|---|
89
- | "Run the content writer on this week's blog post" | Dispatches a task to that agent immediately |
90
- | "What failed today?" | Lists recent failed tasks with details |
91
- | "Schedule outreach every weekday at 9am" | Creates a cron schedule for the agent |
92
- | "Send a WhatsApp to the team: launching Friday" | Sends the message through your connected WhatsApp |
93
- | "Plan out researching 5 new leads this week" | Creates a multi-step plan with agent assignments, waits for your approval |
94
- | "Show me the business pulse" | Returns task stats, contact pipeline, costs, and streaks |
95
- | "Create a project for the website redesign" | Creates a project with a Kanban board |
96
- | "Move that task to review" | Moves a task between board columns |
75
+ | Growth Stage | Revenue | What ohwow prioritizes |
76
+ |---|---|---|
77
+ | **Launch** | $0-$1K | Selling. Not building more features. Not researching competitors. Getting first customers |
78
+ | **Attract** | $1K-$10K | Lead flow. Content that brings people in. One channel, mastered |
79
+ | **Systemize** | $10K-$25K | Automating what works. SOPs. Reducing founder dependency |
80
+ | **Focus** | $25K-$50K | Cutting the bottom 20%. Serving ideal customers. Unit economics |
81
+ | **Expand** | $50K-$100K | Second product or market. Validated before scaled |
82
+ | **Structure** | $250K-$500K | Delegation. The founder stops doing execution work |
97
83
 
98
- The orchestrator covers: agents, tasks, projects, CRM (contacts, pipeline, events), scheduling, messaging (WhatsApp + Telegram), A2A connections, goal planning, deep research, analytics, and workflows. It can also switch your TUI tabs if you ask ("go to approvals").
84
+ When you ask "what should I focus on?", the answer comes from practical wisdom about your specific stage, not generic advice.
99
85
 
100
- ## Features
86
+ ### It respects that you're human
101
87
 
102
- ### Agent Memory
88
+ Most productivity tools treat you like a machine that processes tasks. ohwow doesn't.
103
89
 
104
- After each task, key facts, skills, and feedback are extracted and stored locally. Memories are periodically consolidated to keep context sharp. On future tasks, relevant memories are retrieved via RAG and compiled into the agent's context. Agents improve the more they work. View any agent's memory from the Agents tab.
90
+ - **It learns your rhythm.** Morning person? Complex approvals arrive at 9am. Afternoon slump? Only quick tasks surface after 2pm.
91
+ - **It detects overload.** When you have too many open decisions, it stops adding work and starts batching, prioritizing, and filtering.
92
+ - **It respects boundaries.** If you always stop responding at 6pm, ohwow stops notifying. No setting required. It learns by watching.
93
+ - **It suggests rest.** After a week of sprinting, it shifts work toward reflective tasks and away from high-pressure action items.
105
94
 
106
- ### Browser Automation
95
+ ---
107
96
 
108
- Agents can browse the web using Playwright. Navigation, clicking, form filling, screenshots, and content extraction. The browser launches on first use and runs headless by default. Set `OHWOW_BROWSER_HEADLESS=false` to watch it work.
97
+ ## Real scenarios
109
98
 
110
- ### WhatsApp and Telegram
99
+ ### For a solo e-commerce founder
111
100
 
112
- Connect WhatsApp through a QR code scan in Settings (no Meta business API needed). Connect Telegram with a bot token. Once connected, incoming messages route to the orchestrator automatically. Your agents can reply, take action, or flag things for your attention. You control which chats are allowed.
101
+ You sell handmade candles on Shopify. You spend 3 hours a day on customer emails, social media, and supplier follow-ups.
113
102
 
114
- ### Voice
103
+ With ohwow: the Support Agent handles customer questions via WhatsApp (you approve the first few, then trust builds and it handles most autonomously). The Content Writer creates daily Instagram captions and weekly blog posts about your craft. The Sales Agent follows up with wholesale leads from your last trade show. You focus on making candles.
115
104
 
116
- Full voice pipeline with local and cloud options:
105
+ ### For a SaaS founder with a small team
117
106
 
118
- - **Speech-to-Text**: Voicebox (Whisper via local FastAPI server), WhisperLocal (via Ollama), or WhisperAPI (OpenAI cloud fallback)
119
- - **Text-to-Speech**: VoiceboxTTS (local), Piper (local), or OpenAI TTS (cloud fallback)
107
+ You and 2 engineers are building a developer tool. Marketing, support, and sales fall on you.
120
108
 
121
- ### A2A Protocol
109
+ With ohwow: agents handle lead outreach, support ticket triage, competitive research, and content creation. The system knows you're at stage 2 (Attract) and pushes outreach over feature building. When a lead responds on WhatsApp, the Sales Agent drafts a response referencing their specific use case from your CRM. Your team reviews agent output in the dashboard. Trust builds per domain: the Content Writer runs autonomously, the Sales Agent still needs approval for pricing discussions.
122
110
 
123
- Connect to external agents using the [A2A protocol](https://google.github.io/A2A/) over JSON-RPC 2.0. Each agent publishes a card at `/.well-known/agent-card.json` describing its capabilities. Trust levels (`read_only`, `execute`, `autonomous`, `admin`) control what external agents can do. Scopes cover tasks, agents, results, and file access. Managed from the A2A tab or through the orchestrator.
111
+ ### For an agency managing multiple clients
124
112
 
125
- ### Scheduling and Proactive Engine
113
+ You run a marketing agency with 10 clients. Each needs weekly reports, social posts, and campaign analysis.
126
114
 
127
- Set agents or workflows to run on cron schedules. Create schedules through conversation ("schedule the analyst every Monday at 8am") or from the Schedules tab.
115
+ With ohwow: each client gets dedicated agents. The Researcher pulls analytics. The Content Writer drafts social posts in each client's brand voice. The Reporter compiles weekly performance reports. Agents learn each client's preferences separately. Desktop automation exports graphics from Canva, screenshots from analytics dashboards. Multi-device mesh lets your office Mac Mini run overnight while you review results on your MacBook in the morning.
128
116
 
129
- The proactive engine runs every 30 minutes and checks for overdue tasks, aging approvals, and idle agents. It generates nudges (suggestions, not auto-executions) so nothing falls through the cracks.
117
+ ### For a privacy-focused business
130
118
 
131
- ### Goal Planning and Approvals
119
+ You handle sensitive customer data and can't use cloud AI platforms.
132
120
 
133
- For complex goals, the orchestrator breaks them into multi-step plans with agent assignments and dependencies. Plans start as drafts. You review the steps, approve or reject, and track execution from the Plans tab. Rejected tasks can retry with your feedback included.
121
+ With ohwow: everything runs locally with Ollama. No data leaves your machine. No API calls to external LLMs if you don't want them. Local SQLite database. Local model inference. WhatsApp messages stay on your device. You get full AI automation with zero cloud dependency.
134
122
 
135
- ### Projects and CRM
123
+ ---
136
124
 
137
- Organize tasks into projects with Kanban boards (backlog, todo, in progress, review, done). The built-in CRM tracks contacts (leads, customers, partners), logs events (calls, emails, meetings), and gives you pipeline analytics. All stored locally.
125
+ ## Features
138
126
 
139
- ### Automations and Triggers
127
+ | Category | What you get |
128
+ |---|---|
129
+ | **AI Agents** | 48 pre-built agents across 6 business types. Persistent memory. Tool mastery. Real expertise over time |
130
+ | **Orchestrator** | 150+ tools. Natural language interface. Growth-stage-aware recommendations |
131
+ | **Desktop Control** | Full macOS automation: mouse, keyboard, screen capture. Your agents operate any app on your computer |
132
+ | **Messaging** | WhatsApp + Telegram built in. Uses your real number. Auto-routing to the right agent |
133
+ | **Browser** | Local Chromium automation: navigate, click, fill forms, screenshot, extract data |
134
+ | **CRM** | Contacts, pipeline, events, analytics. All stored locally. Agents use it to personalize outreach |
135
+ | **Scheduling** | Cron schedules + smart timing based on opportunity detection |
136
+ | **Workflows** | Multi-step automation graphs. Parallel execution. Conditions and branching |
137
+ | **Multi-device** | Zero-config mesh across your machines. Tasks route to the best device. Self-healing if one goes down |
138
+ | **Physical I/O** | Connect Arduino, ESP32, sensors, actuators. Your office becomes smart |
139
+ | **MCP** | External tool integration via Model Context Protocol |
140
+ | **A2A** | Agent-to-Agent protocol for connecting with other AI systems |
141
+ | **Cognitive Architecture** | 7-layer philosophical system powering everything under the hood |
142
+
143
+ ## Use with Claude Code
144
+
145
+ ohwow works as a Claude Code plugin. 25 tools become available in your Claude conversations.
140
146
 
141
- Webhook-based automations that fire on external events. Configure field mapping to extract data from incoming payloads and route it to agents or workflows. Managed from the Automations tab.
147
+ ```bash
148
+ claude plugin install ohwow-fun/ohwow
149
+ ```
142
150
 
143
- ### Workflows
151
+ Or add to any project's `.mcp.json`:
152
+
153
+ ```json
154
+ {
155
+ "mcpServers": {
156
+ "ohwow": {
157
+ "command": "npx",
158
+ "args": ["-y", "ohwow", "mcp-server"]
159
+ }
160
+ }
161
+ }
162
+ ```
144
163
 
145
- DAG-based multi-agent execution graphs. Define sequences of agent tasks with conditions and branches. Workflows can be triggered manually, on a schedule, or via automation triggers.
164
+ **Example**: "Research the top 5 competitors in our space, add the findings to the knowledge base, then create a contact for each CEO." Claude uses ohwow's research, knowledge, and CRM tools seamlessly.
146
165
 
147
- ### MCP Servers
166
+ ## Desktop Control
148
167
 
149
- Integrate external tools via the [Model Context Protocol](https://modelcontextprotocol.io/). Supports stdio (subprocess) and HTTP (Streamable HTTP) transports. Authentication via OAuth 2.1, bearer tokens, or API keys. MCP tools are auto-adapted to the Anthropic SDK format and can be assigned per-agent or globally.
168
+ Your agents aren't trapped in a chat window. They operate your computer.
150
169
 
151
- ### Code Sandbox
170
+ ```
171
+ You: "Fill out the Q1 expense report in Google Sheets using last month's receipts folder"
172
+
173
+ ohwow:
174
+ 1. Opens Finder, navigates to receipts
175
+ 2. Opens Google Sheets in Chrome
176
+ 3. Reads each receipt, types amounts into the right cells
177
+ 4. Double-checks totals
178
+ 5. Done. You were making coffee the whole time.
179
+ ```
152
180
 
153
- Agents can execute JavaScript in an isolated sandbox (Node.js `vm` module). No filesystem, network, or process access. 5-second default timeout, 30-second maximum. Safe globals only (Math, JSON, Date, Array, Object, Map, Set, etc.).
181
+ The agent takes a screenshot, analyzes it with a vision model, decides the next action, executes it, then screenshots again to see the result. This perception/reasoning/action loop repeats until the task is done.
154
182
 
155
- ### Web Search
183
+ **Safety first.** Desktop control requires explicit permission. Emergency stop halts everything instantly. Dangerous actions (Terminal, system settings) trigger additional approval.
156
184
 
157
- Agents with web search enabled can search the web during task execution, powered by Anthropic's built-in search tool.
185
+ ## Multi-device Mesh
158
186
 
159
- ### Local Models with Ollama
187
+ ```
188
+ Mac Mini (home office) MacBook (on the go) Raspberry Pi (warehouse)
189
+ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐
190
+ │ WhatsApp Agent │◄─mesh──►│ Research Agent │◄─mesh──►│ Temp Sensor │
191
+ │ Desktop Tasks │ │ Browser Auto │ │ Motion Detect │
192
+ │ Overnight Work │ │ Mobile Review │ │ Inventory Scan │
193
+ └────────────────┘ └────────────────┘ └────────────────┘
194
+ ```
160
195
 
161
- If you run [Ollama](https://ollama.com) locally, the runtime routes lightweight tasks (orchestration, memory extraction) to your local model instead of Claude. The model catalog includes 25+ models across 5 memory tiers with device-aware recommendations. Complex work (planning, agent tasks, browser automation) still goes to Claude. If Ollama goes down, everything falls back to Anthropic automatically.
196
+ Zero configuration. Devices discover each other on your network. Tasks go to the best device for the job. If your Mac Mini discovers that a lead's website is down, your MacBook knows instantly. If one device goes offline, another takes over its responsibilities.
162
197
 
163
- ### Offline Mode
198
+ ## Why ohwow?
164
199
 
165
- If ohwow.fun becomes unreachable, the runtime continues with cached agent configs. Tasks still execute, results still store locally. When connectivity returns, everything syncs back up.
200
+ | | Zapier | n8n | Make | **ohwow** |
201
+ |---|---|---|---|---|
202
+ | Runs on your machine | No | Self-host option | No | **Yes, always** |
203
+ | Desktop control | No | No | No | **Yes, with safety guards** |
204
+ | AI agents with real memory | No | Partial | No | **Yes, agents build expertise** |
205
+ | Cost to start | $20+/mo | Free (self-host) | $10+/mo | **$0 with Ollama** |
206
+ | Pre-built business agents | No | No | No | **48 agents, 6 business types** |
207
+ | WhatsApp + Telegram | Plugin | Plugin | Plugin | **Built in** |
208
+ | CRM + contacts | No | No | No | **Built in** |
209
+ | Multi-device mesh | No | No | No | **Zero-config** |
210
+ | Knows your growth stage | No | No | No | **Yes, adapts priorities** |
211
+ | Respects your energy/stress | No | No | No | **Yes, bio-aware** |
212
+ | Your data stays local | No | Optional | No | **Always** |
166
213
 
167
- ## Connected Mode (Cloud)
214
+ ## Cloud (optional)
168
215
 
169
- Connect to ohwow.fun to add cloud features on top of the free local runtime.
216
+ Connect to [ohwow.fun](https://ohwow.fun) for cloud features on top of the free local runtime:
170
217
 
171
- **Cloud features (require connection):**
172
- - Cloud sync: agent configs sync from your dashboard
173
- - Cloud task dispatch: receive tasks dispatched from the web
174
- - OAuth integrations: Gmail, Slack, and other cloud-based integrations
175
- - Webhook relay: cloud-proxied webhooks for external services
176
- - Heartbeats and health monitoring
218
+ - **Phone dispatch**: assign tasks to your computer from your phone
219
+ - **OAuth integrations**: Gmail, Slack, and more
220
+ - **AI site generator**: with hosting and custom domains
221
+ - **Fleet dashboard**: manage all your devices from one place
222
+ - **Collective intelligence**: visualize what your agents have learned
223
+ - **Work ontology dashboard**: eudaimonia score, growth stage guidance
177
224
 
178
- **What stays local (always):**
179
- - Prompts and system instructions
180
- - Agent outputs and full conversations
181
- - Long-term agent memory
182
- - CRM contacts and activity history
183
- - WhatsApp and Telegram message history
184
- - Browser session data and screenshots
225
+ All local features work without cloud. See [pricing](https://ohwow.fun/pricing) for plans starting at $29/mo.
185
226
 
186
- **How it works:**
227
+ ## Under the Hood
187
228
 
188
- Activate with a license key from the ohwow.fun dashboard (Settings > License). The runtime connects to the control plane via long-polling, receives task dispatches, and sends back status updates. Heartbeats confirm the device is online. Each license is locked to a single device. The cloud dashboard gives you a web interface for managing agents, reviewing tasks, and monitoring your workspace without touching the terminal.
229
+ For those who want to understand the architecture: ohwow is built on a seven-layer philosophical cognitive architecture. Each layer addresses a distinct dimension of intelligence, grounded in philosophy from Aristotle to modern cognitive science.
189
230
 
190
- All local features (agents, scheduling, WhatsApp, Telegram, A2A, browser automation, voice, CRM, automations, approvals) work without a cloud connection.
231
+ ```
232
+ Layer 7: BIOS — Respects human biology (energy, stress, boundaries)
233
+ Layer 6: Symbiosis — Models human-AI collaboration (trust, handoffs, mutual learning)
234
+ Layer 5: Soul — Tracks identity for agents and humans (values, blind spots, growth)
235
+ Persona — Real-time behavioral profiling (circadian, load, communication style)
236
+ Layer 4: Mesh — Distributed consciousness across devices (propagation, shared body, self-healing)
237
+ Layer 3: Work — Purpose-driven execution (growth stage wisdom, work classification, flourishing)
238
+ Layer 2: Body — Physical + digital embodiment (organs, nervous systems, affordances, PID controllers)
239
+ Layer 1: Brain — Cognitive cycle: perceive → deliberate → act (prediction, reflection, dialectic)
240
+ Layer 0: Runtime — Orchestrator, engine, 150+ tools, DB, API, scheduling, messaging
241
+ ```
242
+
243
+ 115+ modules. 28,000+ lines. Every philosophical concept is load-bearing architecture: remove any one and the system degrades measurably. See [ARCHITECTURE.md](./ARCHITECTURE.md) for the full technical breakdown.
191
244
 
192
- ## Headless / Daemon Mode
245
+ ## Self-hosting
246
+
247
+ | Command | What it does |
248
+ |---|---|
249
+ | `ohwow` | Start the TUI (default) |
250
+ | `ohwow --daemon` | Start daemon in foreground (for systemd/launchd/Docker) |
251
+ | `ohwow stop` | Stop the daemon |
252
+ | `ohwow status` | Check daemon status |
253
+ | `ohwow logs` | Tail daemon logs |
193
254
 
194
- For servers, containers, or always-on deployments:
255
+ Docker:
195
256
 
196
257
  ```bash
197
- ohwow --daemon
258
+ docker run -d --name ohwow -p 7700:7700 -v ~/.ohwow:/root/.ohwow ohwow
198
259
  ```
199
260
 
200
- Runs the daemon in the foreground (no TUI). Suitable for systemd, launchd, or Docker. Set `OHWOW_HEADLESS=1` as an alternative. The web UI still runs normally. Configure through environment variables.
261
+ ## Requirements
201
262
 
202
- ## Configuration
263
+ - Node.js 20+
264
+ - [Ollama](https://ollama.com) for local models
265
+ - Optional: Anthropic API key (for Claude models)
266
+ - Optional: Playwright browsers (`npx playwright install chromium`) for browser automation
267
+ - Optional: macOS Accessibility permission for desktop control
203
268
 
204
- Config lives at `~/.ohwow/config.json`. Key environment variables:
269
+ ## Troubleshooting
205
270
 
206
- | Variable | Purpose |
207
- |---|---|
208
- | `OHWOW_PORT` | HTTP server port (default 7700) |
209
- | `OHWOW_HEADLESS` | Set to `1` for headless mode |
210
- | `OHWOW_BROWSER_HEADLESS` | Set to `false` to show the browser |
211
- | `ANTHROPIC_API_KEY` | Anthropic API key for Claude models |
271
+ | Problem | Solution |
272
+ |---------|----------|
273
+ | `better-sqlite3` build fails | Install build tools: `xcode-select --install` (macOS), `sudo apt install build-essential python3` (Linux) |
274
+ | Ollama not detected | Ensure Ollama is running (`ollama serve`) and accessible at `http://localhost:11434` |
275
+ | Port 7700 in use | Set `OHWOW_PORT=7701` or any free port |
276
+ | WhatsApp QR expired | Restart ohwow and scan the new QR within 60 seconds |
212
277
 
213
- ## Supported Models
278
+ ## Community
214
279
 
215
- | Model | Provider |
216
- |---|---|
217
- | Claude Opus 4.6 | Anthropic |
218
- | Claude Sonnet 4.6 | Anthropic |
219
- | Claude Haiku 4.5 | Anthropic |
220
- | Any Ollama model | Local |
280
+ - [Discord](https://discord.gg/WUGnGqceeY)
281
+ - [Contributing](./CONTRIBUTING.md)
282
+ - [Architecture](./ARCHITECTURE.md)
283
+ - [Security](./SECURITY.md)
284
+ - Email: ogsus@ohwow.fun
221
285
 
222
286
  ## License
223
287
 
224
- BSL 1.1 (Business Source License). Free to use, including production. You can't use it to build a competing product. Converts to Apache 2.0 on March 2, 2030. See [LICENSE](./LICENSE) for details.
288
+ [MIT](./LICENSE)
package/dist/api.d.ts ADDED
@@ -0,0 +1,91 @@
1
+ import Database from 'better-sqlite3';
2
+
3
+ /**
4
+ * DatabaseAdapter Interface (Runtime Copy)
5
+ *
6
+ * Abstracts the query builder pattern used by Supabase's PostgREST client.
7
+ * Both the Supabase adapter (cloud) and SQLite adapter (local runtime)
8
+ * implement this interface, allowing all agent services to work with either backend.
9
+ *
10
+ * Mirrors the SupabaseClient chaining API: .from(table).select().eq().single()
11
+ */
12
+ interface DbResult<T> {
13
+ data: T | null;
14
+ error: DbError | null;
15
+ count?: number | null;
16
+ }
17
+ interface DbError {
18
+ message: string;
19
+ code?: string;
20
+ details?: string;
21
+ hint?: string;
22
+ }
23
+ interface FilterBuilder<T> {
24
+ eq(column: string, value: unknown): FilterBuilder<T>;
25
+ neq(column: string, value: unknown): FilterBuilder<T>;
26
+ gt(column: string, value: unknown): FilterBuilder<T>;
27
+ gte(column: string, value: unknown): FilterBuilder<T>;
28
+ lt(column: string, value: unknown): FilterBuilder<T>;
29
+ lte(column: string, value: unknown): FilterBuilder<T>;
30
+ in(column: string, values: unknown[]): FilterBuilder<T>;
31
+ is(column: string, value: null | boolean): FilterBuilder<T>;
32
+ or(filters: string, options?: {
33
+ foreignTable?: string;
34
+ }): FilterBuilder<T>;
35
+ not(column: string, operator: string, value: unknown): FilterBuilder<T>;
36
+ order(column: string, options?: {
37
+ ascending?: boolean;
38
+ }): FilterBuilder<T>;
39
+ limit(count: number): FilterBuilder<T>;
40
+ range(from: number, to: number): FilterBuilder<T>;
41
+ single(): PromiseLike<DbResult<T>>;
42
+ maybeSingle(): PromiseLike<DbResult<T | null>>;
43
+ then<TResult1 = DbResult<T[]>, TResult2 = never>(onfulfilled?: ((value: DbResult<T[]>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): PromiseLike<TResult1 | TResult2>;
44
+ }
45
+ type SelectBuilder<T> = FilterBuilder<T>;
46
+ interface InsertBuilder<T> {
47
+ select(columns?: string): FilterBuilder<T>;
48
+ then<TResult1 = DbResult<null>, TResult2 = never>(onfulfilled?: ((value: DbResult<null>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): PromiseLike<TResult1 | TResult2>;
49
+ }
50
+ interface UpdateBuilder<T> extends FilterBuilder<T> {
51
+ eq(column: string, value: unknown): UpdateBuilder<T>;
52
+ neq(column: string, value: unknown): UpdateBuilder<T>;
53
+ select(columns?: string): FilterBuilder<T>;
54
+ }
55
+ type DeleteBuilder<T> = FilterBuilder<T>;
56
+ interface TableBuilder<T = Record<string, unknown>> {
57
+ select(columns?: string, options?: {
58
+ count?: 'exact';
59
+ head?: boolean;
60
+ }): SelectBuilder<T>;
61
+ insert(data: Partial<T> | Partial<T>[]): InsertBuilder<T>;
62
+ update(data: Partial<T>): UpdateBuilder<T>;
63
+ delete(): DeleteBuilder<T>;
64
+ }
65
+ interface DatabaseAdapter {
66
+ from<T = Record<string, unknown>>(table: string): TableBuilder<T>;
67
+ rpc<T = unknown>(fn: string, params?: Record<string, unknown>): PromiseLike<DbResult<T>>;
68
+ }
69
+
70
+ /**
71
+ * SQLite Adapter
72
+ *
73
+ * Implements the DatabaseAdapter interface using better-sqlite3.
74
+ * Translates the SupabaseClient-shaped query builder API into SQL queries
75
+ * against a local SQLite database.
76
+ *
77
+ * Used by the local runtime for local data plane storage.
78
+ */
79
+
80
+ /**
81
+ * Map of registered RPC functions for the SQLite adapter.
82
+ * In Supabase, .rpc() calls server-side Postgres functions.
83
+ * In SQLite, we register JS functions that perform the same logic.
84
+ */
85
+ type RpcHandler = (params: Record<string, unknown>) => unknown;
86
+ interface SqliteAdapterOptions {
87
+ rpcHandlers?: Record<string, RpcHandler>;
88
+ }
89
+ declare function createSqliteAdapter(db: Database.Database, options?: SqliteAdapterOptions): DatabaseAdapter;
90
+
91
+ export { type SqliteAdapterOptions, createSqliteAdapter };
package/dist/api.js ADDED
@@ -0,0 +1,2 @@
1
+ import { createRequire } from 'module'; const require = createRequire(import.meta.url);
2
+ function F(s,e){return{message:s,code:e}}function q(s,e){return{data:s,error:null,count:e}}function f(s,e){return{data:null,error:F(s,e)}}function A(s){let e=s.split(","),i=[],o=[];for(let p of e){let c=p.trim().split(".");if(c.length<3)continue;let l=c[0],t=c[1],r=c.slice(2).join(".");switch(t){case"eq":i.push(`${l} = ?`),o.push(r);break;case"neq":i.push(`${l} != ?`),o.push(r);break;case"gt":i.push(`${l} > ?`),o.push(r);break;case"gte":i.push(`${l} >= ?`),o.push(r);break;case"lt":i.push(`${l} < ?`),o.push(r);break;case"lte":i.push(`${l} <= ?`),o.push(r);break;case"is":r==="null"?i.push(`${l} IS NULL`):r==="true"?i.push(`${l} = 1`):r==="false"&&i.push(`${l} = 0`);break;case"ilike":i.push(`${l} LIKE ? COLLATE NOCASE`),o.push(r.replace(/%25/g,"%"));break;case"like":i.push(`${l} LIKE ?`),o.push(r);break;case"in":{let n=r.replace(/^\(/,"").replace(/\)$/,"").split(",");i.push(`${l} IN (${n.map(()=>"?").join(",")})`),o.push(...n)}break;default:i.push(`${l} ${t} ?`),o.push(r)}}return{sql:`(${i.join(" OR ")})`,params:o}}function O(s){if(s.conditions.length===0)return{sql:"",params:[]};let e=[],i=[];for(let o of s.conditions)e.push(o.sql),i.push(...o.params);return{sql:` WHERE ${e.join(" AND ")}`,params:i}}function B(s){return s.orderClauses.length===0?"":` ORDER BY ${s.orderClauses.join(", ")}`}function C(s){if(s.rangeFrom!==void 0&&s.rangeTo!==void 0)return` LIMIT ${s.rangeTo-s.rangeFrom+1} OFFSET ${s.rangeFrom}`;if(s.limitValue!==void 0){let e=s.offsetValue?` OFFSET ${s.offsetValue}`:"";return` LIMIT ${s.limitValue}${e}`}return""}function S(s){if(!s)return s;let e={...s};for(let[i,o]of Object.entries(e))if(typeof o=="string"&&(o.startsWith("{")&&o.endsWith("}")||o.startsWith("[")&&o.endsWith("]")))try{e[i]=JSON.parse(o)}catch{}return e}function y(s,e,i,o,p,c,l){let t={eq(r,n){return e.conditions.push({sql:`${r} = ?`,params:[n]}),t},neq(r,n){return e.conditions.push({sql:`${r} != ?`,params:[n]}),t},gt(r,n){return e.conditions.push({sql:`${r} > ?`,params:[n]}),t},gte(r,n){return e.conditions.push({sql:`${r} >= ?`,params:[n]}),t},lt(r,n){return e.conditions.push({sql:`${r} < ?`,params:[n]}),t},lte(r,n){return e.conditions.push({sql:`${r} <= ?`,params:[n]}),t},in(r,n){if(n.length===0)e.conditions.push({sql:"1 = 0",params:[]});else{let a=n.map(()=>"?").join(", ");e.conditions.push({sql:`${r} IN (${a})`,params:n})}return t},is(r,n){return n===null?e.conditions.push({sql:`${r} IS NULL`,params:[]}):e.conditions.push({sql:`${r} = ?`,params:[n?1:0]}),t},or(r){let n=A(r);return e.conditions.push(n),t},not(r,n,a){switch(n){case"eq":e.conditions.push({sql:`${r} != ?`,params:[a]});break;case"is":a===null&&e.conditions.push({sql:`${r} IS NOT NULL`,params:[]});break;default:e.conditions.push({sql:`NOT (${r} ${n} ?)`,params:[a]})}return t},order(r,n){let a=n?.ascending===!1?"DESC":"ASC";return e.orderClauses.push(`${r} ${a}`),t},limit(r){return e.limitValue=r,t},range(r,n){return e.rangeFrom=r,e.rangeTo=n,t},single(){return{then(r,n){try{let a=w(s,e,i,o,p,c,l),u=a.data;if(!u||Array.isArray(u)&&u.length===0){let d=f("Row not found","PGRST116");return Promise.resolve(d).then(r,n)}if(Array.isArray(u)&&u.length>1){let d=f("Multiple rows returned","PGRST116");return Promise.resolve(d).then(r,n)}let m=Array.isArray(u)?u[0]:u;return Promise.resolve(q(m,a.count)).then(r,n)}catch(a){let u=f(a.message);return n?Promise.resolve(u).then(r,n):Promise.resolve(u).then(r)}}}},maybeSingle(){return{then(r,n){try{let a=w(s,e,i,o,p,c,l),u=a.data;if(!u||Array.isArray(u)&&u.length===0)return Promise.resolve(q(null,a.count)).then(r,n);let m=Array.isArray(u)?u[0]:u;return Promise.resolve(q(m,a.count)).then(r,n)}catch(a){let u=f(a.message);return Promise.resolve(u).then(r,n)}}}},then(r,n){try{let a=w(s,e,i,o,p,c,l);return Promise.resolve(a).then(r,n)}catch(a){let u=f(a.message);return Promise.resolve(u).then(r,n)}}};return t}function w(s,e,i,o,p,c,l){let t=O(e),r=B(e),n=C(e);switch(i){case"select":{let a=o||"*";if(p?.head===!0&&p?.count==="exact"){let g=`SELECT COUNT(*) as count FROM ${e.table}${t.sql}`,h=s.prepare(g).get(...t.params);return{data:[],error:null,count:h.count}}let m=`SELECT ${a} FROM ${e.table}${t.sql}${r}${n}`,d=s.prepare(m).all(...t.params);d=d.map(g=>S(g));let T=null;if(p?.count==="exact"){let g=`SELECT COUNT(*) as count FROM ${e.table}${t.sql}`;T=s.prepare(g).get(...t.params).count}return{data:d,error:null,count:T}}case"insert":{let a=Array.isArray(c)?c:[c],u=[];for(let m of a){let d=m,T=Object.keys(d),g=T.map(R=>{let k=d[R];return k!==null&&typeof k=="object"?JSON.stringify(k):k}),h=T.map(()=>"?").join(", "),$=`INSERT INTO ${e.table} (${T.join(", ")}) VALUES (${h})`;s.prepare($).run(...g);let b=s.prepare("SELECT last_insert_rowid() as id").get(),E=s.prepare(`SELECT * FROM ${e.table} WHERE rowid = ?`).get(b.id);E&&u.push(S(E))}return{data:u,error:null}}case"update":{let a=l,u=Object.keys(a),m=u.map($=>`${$} = ?`).join(", "),d=u.map($=>{let b=a[$];return b!==null&&typeof b=="object"?JSON.stringify(b):b}),T=`UPDATE ${e.table} SET ${m}${t.sql}`;s.prepare(T).run(...d,...t.params);let g=`SELECT * FROM ${e.table}${t.sql}${r}${n}`,h=s.prepare(g).all(...t.params);return h=h.map($=>S($)),{data:h,error:null}}case"delete":{let a=`DELETE FROM ${e.table}${t.sql}`;return s.prepare(a).run(...t.params),{data:[],error:null}}}}function P(s,e){let i=e?.rpcHandlers??{};return{from(o){return{select(p,c){return y(s,{table:o,conditions:[],orderClauses:[]},"select",p,c)},insert(p){let c={table:o,conditions:[],orderClauses:[]};return{select(t){return y(s,c,"insert",t,void 0,p)},then(t,r){try{let n=w(s,c,"insert",void 0,void 0,p);return Promise.resolve({data:null,error:n.error}).then(t,r)}catch(n){let a=f(n.message);return Promise.resolve(a).then(t,r)}}}},update(p){let c={table:o,conditions:[],orderClauses:[]},t=y(s,c,"update",void 0,void 0,void 0,p);return t.select=r=>y(s,c,"update",r,void 0,void 0,p),t},delete(){return y(s,{table:o,conditions:[],orderClauses:[]},"delete")}}},rpc(o,p){let c=i[o];if(!c)return Promise.resolve(f(`RPC function '${o}' not registered`));try{let l=c(p??{});return Promise.resolve(q(l))}catch(l){return Promise.resolve(f(l.message))}}}}export{P as createSqliteAdapter};