heyio 0.42.1 → 1.0.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 (100) hide show
  1. package/README.md +40 -52
  2. package/dist/api/auth.js +35 -38
  3. package/dist/api/server.js +157 -1134
  4. package/dist/config.js +49 -32
  5. package/dist/copilot/agents.js +72 -1055
  6. package/dist/copilot/client.js +6 -17
  7. package/dist/copilot/io-scheduler.js +55 -139
  8. package/dist/copilot/model-router.js +100 -72
  9. package/dist/copilot/orchestrator.js +91 -515
  10. package/dist/copilot/scheduler.js +67 -189
  11. package/dist/copilot/skills.js +41 -366
  12. package/dist/copilot/system-message.js +40 -200
  13. package/dist/copilot/tools.js +191 -2042
  14. package/dist/daemon.js +54 -201
  15. package/dist/index.js +15 -133
  16. package/dist/mcp/config.js +23 -31
  17. package/dist/mcp/index.js +2 -3
  18. package/dist/mcp/registry.js +33 -88
  19. package/dist/notify.js +18 -100
  20. package/dist/paths.js +13 -24
  21. package/dist/setup.js +35 -0
  22. package/dist/store/db.js +111 -297
  23. package/dist/store/feed.js +29 -97
  24. package/dist/store/instances.js +56 -121
  25. package/dist/store/schedules.js +21 -73
  26. package/dist/store/squads.js +35 -186
  27. package/dist/store/tasks.js +25 -168
  28. package/dist/telegram/bot.js +20 -312
  29. package/dist/telegram/handlers.js +39 -3
  30. package/dist/watchdog.js +31 -45
  31. package/dist/wiki/fs.js +38 -155
  32. package/dist/wiki/search.js +31 -44
  33. package/package.json +5 -8
  34. package/web-dist/assets/ChatView-EFFiln1H.js +11 -0
  35. package/web-dist/assets/FeedView-bN4NMOL7.js +6 -0
  36. package/web-dist/assets/LoginView-CNtasq3n.js +1 -0
  37. package/web-dist/assets/McpView-C2CHiwsi.js +1 -0
  38. package/web-dist/assets/SchedulesView-CyilLban.js +1 -0
  39. package/web-dist/assets/SettingsView-1wLXKEF4.js +1 -0
  40. package/web-dist/assets/SkillsView-BLsD-0u0.js +1 -0
  41. package/web-dist/assets/SquadDetailView-CsCw2ZLp.js +21 -0
  42. package/web-dist/assets/SquadsView-DQ3vFlyO.js +6 -0
  43. package/web-dist/assets/WikiView-19M3oqnq.js +21 -0
  44. package/web-dist/assets/api-WGvTsXaE.js +1 -0
  45. package/web-dist/assets/index-D7M5O-_l.css +1 -0
  46. package/web-dist/assets/index-DZOS9syn.js +95 -0
  47. package/web-dist/assets/plus-BOvyX1BC.js +6 -0
  48. package/web-dist/assets/trash-2-DHoetkC4.js +6 -0
  49. package/web-dist/favicon.svg +4 -1
  50. package/web-dist/index.html +7 -10
  51. package/dist/api/logout.test.js +0 -128
  52. package/dist/api/mcp.test.js +0 -285
  53. package/dist/api/wiki.test.js +0 -283
  54. package/dist/auth/session-logic.js +0 -79
  55. package/dist/auth/session-logic.test.js +0 -201
  56. package/dist/copilot/auto-complete-instance.test.js +0 -104
  57. package/dist/copilot/cron.js +0 -136
  58. package/dist/copilot/event-summary.js +0 -286
  59. package/dist/copilot/instance-deactivate.test.js +0 -119
  60. package/dist/copilot/model-router.test.js +0 -71
  61. package/dist/copilot/review-backfill.js +0 -57
  62. package/dist/copilot/session-timeout.js +0 -112
  63. package/dist/copilot/session-timeout.test.js +0 -372
  64. package/dist/copilot/skills.test.js +0 -55
  65. package/dist/copilot/universes.js +0 -469
  66. package/dist/instance-watchdog.js +0 -104
  67. package/dist/instance-watchdog.test.js +0 -183
  68. package/dist/mcp/client.js +0 -109
  69. package/dist/mcp/client.test.js +0 -99
  70. package/dist/mcp/config.test.js +0 -49
  71. package/dist/mcp/registry.test.js +0 -79
  72. package/dist/notify.test.js +0 -232
  73. package/dist/store/feed.test.js +0 -279
  74. package/dist/store/instances.test.js +0 -310
  75. package/dist/store/io-schedules.js +0 -63
  76. package/dist/store/notifications.js +0 -79
  77. package/dist/store/notifications.test.js +0 -197
  78. package/dist/store/schedule-runs.js +0 -46
  79. package/dist/store/squads.test.js +0 -405
  80. package/dist/store/tasks.test.js +0 -150
  81. package/dist/store/worktrees.js +0 -83
  82. package/dist/tui/index.js +0 -286
  83. package/dist/update.js +0 -81
  84. package/dist/watchdog.test.js +0 -83
  85. package/dist/wiki/wiki-squad.test.js +0 -54
  86. package/web-dist/assets/AgentActivityView-B1PaNYy8.js +0 -1
  87. package/web-dist/assets/ChatView-BbpWnrtC.js +0 -4
  88. package/web-dist/assets/FeedView-B5LaMV0I.js +0 -1
  89. package/web-dist/assets/InboxView-Cwqt8rH7.js +0 -1
  90. package/web-dist/assets/LoginView-refmPLKT.js +0 -1
  91. package/web-dist/assets/McpView-B1w0dRFY.js +0 -1
  92. package/web-dist/assets/SchedulesView-D9l2DI7X.js +0 -1
  93. package/web-dist/assets/SettingsTabs.vue_vue_type_script_setup_true_lang-DncOVVEB.js +0 -1
  94. package/web-dist/assets/SkillsView-uFX0q1mV.js +0 -1
  95. package/web-dist/assets/SquadsView-B1nZW4ml.js +0 -1
  96. package/web-dist/assets/StatusIndicator.vue_vue_type_script_setup_true_lang-pTrJJwX1.js +0 -1
  97. package/web-dist/assets/WikiView-B54cCKIK.js +0 -1
  98. package/web-dist/assets/index-C0VEUWQ1.js +0 -81
  99. package/web-dist/assets/index-eluTyieM.css +0 -10
  100. package/web-dist/icons.svg +0 -24
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 🤖 IO
2
2
 
3
- A personal AI assistant daemon built on the GitHub Copilot SDK. IO runs 24/7 on your machine, reachable via Telegram, a web UI, and a terminal TUI.
3
+ A personal AI assistant daemon built on the GitHub Copilot SDK. IO runs 24/7 on your machine, reachable via Telegram, a web dashboard, and an HTTP API.
4
4
 
5
5
  [![CI](https://github.com/michaeljolley/io/actions/workflows/ci.yml/badge.svg)](https://github.com/michaeljolley/io/actions/workflows/ci.yml)
6
6
  ![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)
@@ -9,10 +9,10 @@ A personal AI assistant daemon built on the GitHub Copilot SDK. IO runs 24/7 on
9
9
  ## ✨ Features
10
10
 
11
11
  - **Copilot SDK Integration** — powered by GitHub's Copilot SDK for LLM conversations with tool calling
12
- - **Multi-Interface** — Web UI + Telegram bot + terminal TUI + HTTP API
12
+ - **Multi-Interface** — Web dashboard + Telegram bot + HTTP API
13
13
  - **Web Frontend** — Vue 3 dashboard with chat, squad management, skills, and agent activity views
14
14
  - **Persistent Memory** — wiki-based knowledge base stored at `~/.io/wiki/`
15
- - **Squad System** — persistent project teams with **named specialist agents** themed from 80s pop culture (A-Team, Transformers, ThunderCats, GI Joe, Aliens, Ghostbusters)
15
+ - **Squad System** — persistent project teams with **named specialist agents** themed from pop culture universes (dynamically selected at squad creation)
16
16
  - **Skills** — modular skill system; install from git repos or the [skills.sh](https://skills.sh) registry
17
17
  - **Adaptive Sessions** — infinite sessions with automatic context compaction
18
18
  - **Named Agent Personas** — each squad agent gets a character persona with personality, dynamic role title, and specialized charter
@@ -55,10 +55,7 @@ This creates a config file at `~/.io/config.json`.
55
55
  ### Run
56
56
 
57
57
  ```bash
58
- # Interactive TUI mode
59
- io
60
-
61
- # Background daemon (Telegram + HTTP API)
58
+ # Background daemon (Telegram + HTTP API + Web)
62
59
  io --daemon
63
60
 
64
61
  # Allow IO to modify its own source code
@@ -96,14 +93,11 @@ WantedBy=multi-user.target
96
93
 
97
94
  | Command | Description |
98
95
  | --- | --- |
99
- | `io` | Start interactive TUI mode |
100
- | `io --daemon` | Run as background daemon (Telegram + API) |
96
+ | `io --daemon` | Run as background daemon (Telegram + API + Web) |
101
97
  | `io --self-edit` | Allow IO to modify its own source |
102
98
  | `io setup` | Configure Telegram bot token and user ID |
103
- | `io skill list` | List installed skills |
104
- | `io skill add <repo-url>` | Install a skill from a git repository |
105
- | `io skill remove <slug>` | Remove an installed skill |
106
- | `io skill search <query>` | Search the skills.sh registry |
99
+
100
+ Skills are managed via the web dashboard.
107
101
 
108
102
  ## ⚙️ Configuration
109
103
 
@@ -118,20 +112,15 @@ IO stores its configuration at `~/.io/config.json`. The setup wizard (`io setup`
118
112
  | `telegramEnabled` | `boolean` | `false` | Enable the Telegram bot interface |
119
113
  | `selfEditEnabled` | `boolean` | `false` | Allow IO to modify its own source code |
120
114
  | `defaultModel` | `string` | `"gpt-4.1"` | LLM model for the main orchestrator session |
121
- | `modelTiers` | `object` | *(see below)* | Per-complexity model preferences for squad agents |
122
- | `modelTiers.high` | `string[]` | `["claude-opus-4.7", "claude-opus-4.6"]` | Models for complex tasks (architecture, debugging, design) |
123
- | `modelTiers.medium` | `string[]` | `["claude-sonnet-4.6", "gpt-5.5", "claude-opus-4.5"]` | Models for standard tasks (features, tests, reviews) |
124
- | `modelTiers.low` | `string[]` | `["claude-haiku-4.5", "gpt-5.4-mini"]` | Models for simple tasks (reads, formatting, lookups) |
125
115
  | `port` | `number` | `3170` | Port for the HTTP server (API + web frontend) |
126
116
  | `supabaseUrl` | `string` | — | Supabase project URL (enables web portal authentication) |
127
117
  | `supabaseAnonKey` | `string` | — | Supabase anon/public API key |
128
118
  | `authorizedEmail` | `string` | — | Email address allowed to access the web portal |
129
119
  | `backgroundNotifyMode` | `string` | `"meaningful"` | Background task notification frequency: `"all"`, `"meaningful"`, or `"off"` |
130
120
  | `backgroundNotifyTelegram` | `boolean` | `true` | Send background task notifications via Telegram |
131
- | `backgroundNotifyTui` | `boolean` | `true` | Show background task notifications in TUI |
132
121
  | `watchdogEnabled` | `boolean` | `true` | Enable the daemon event loop watchdog |
133
122
 
134
- Each `modelTiers` list is a ranked preference IO picks the first available model at startup.
123
+ IO discovers available models from the Copilot SDK at startup and automatically picks the most appropriate model for each task based on complexity and cost.
135
124
 
136
125
  > **Migration note:** If your config uses the old `apiPort` field, IO will automatically migrate it to `port`.
137
126
 
@@ -147,12 +136,7 @@ Each `modelTiers` list is a ranked preference — IO picks the first available m
147
136
  "port": 3170,
148
137
  "supabaseUrl": "https://your-project.supabase.co",
149
138
  "supabaseAnonKey": "eyJhbGciOiJIUzI1NiIs...",
150
- "authorizedEmail": "you@example.com",
151
- "modelTiers": {
152
- "high": ["claude-opus-4.7", "claude-opus-4.6"],
153
- "medium": ["claude-sonnet-4.6", "gpt-5.5", "claude-opus-4.5"],
154
- "low": ["claude-haiku-4.5", "gpt-5.4-mini"]
155
- }
139
+ "authorizedEmail": "you@example.com"
156
140
  }
157
141
  ```
158
142
 
@@ -172,19 +156,11 @@ Skills are modular extensions that add new tools and capabilities to IO. Each sk
172
156
 
173
157
  ### Managing Skills
174
158
 
175
- ```bash
176
- # Search the skills.sh registry
177
- io skill search "github"
178
-
179
- # Install from a git repo
180
- io skill add https://github.com/user/my-skill.git
159
+ Skills are managed through the web dashboard:
181
160
 
182
- # List installed skills
183
- io skill list
184
-
185
- # Remove a skill
186
- io skill remove my-skill
187
- ```
161
+ - **View** all installed skills with name, description, and slug
162
+ - **Install** new skills by providing a git repository URL
163
+ - **Remove** skills you no longer need
188
164
 
189
165
  ### Creating a Skill
190
166
 
@@ -194,7 +170,7 @@ A skill is a directory with a `SKILL.md` file that describes the skill and its t
194
170
 
195
171
  Squads are persistent project teams with **named specialist agents**. Each squad:
196
172
 
197
- - Has an 80s pop culture **universe theme** (A-Team, Transformers, ThunderCats, GI Joe, Aliens, Ghostbusters)
173
+ - Has a pop culture **universe theme** (dynamically researched at creation time never hardcoded)
198
174
  - Contains dynamically-created **specialist agents** with roles tailored to the project (e.g., "Express API Engineer", "Vue.js Frontend Dev")
199
175
  - Each agent is assigned a **character persona** with personality traits that color their work style
200
176
  - Remembers decisions, context, and conversation history across sessions
@@ -202,7 +178,7 @@ Squads are persistent project teams with **named specialist agents**. Each squad
202
178
 
203
179
  ### How Squads Work
204
180
 
205
- 1. **Create** — `squad_create` assigns a random 80s universe (or user picks one)
181
+ 1. **Create** — `squad_create` assigns a random pop culture universe (or user picks one)
206
182
  2. **Analyze** — `squad_analyze` scans the project to determine languages, frameworks, and tools
207
183
  3. **Build the team** — `squad_add_agent` for each specialist the project needs; characters are drawn from the universe pool
208
184
  4. **Delegate** — `squad_delegate` sends tasks to specific agents by character name
@@ -211,13 +187,13 @@ Squads are persistent project teams with **named specialist agents**. Each squad
211
187
  ## 🏗️ Architecture
212
188
 
213
189
  ```
214
- User → [Web UI / TUI / Telegram / HTTP API]
190
+ User → [Web Dashboard / Telegram / HTTP API]
215
191
 
216
192
  Orchestrator (Copilot SDK)
217
193
  ↕ ↕ ↕
218
194
  Squad Manager Wiki/Memory MCP Servers
219
195
 
220
- Named Agents (80s Characters)
196
+ Named Agents (Pop Culture Characters)
221
197
  ```
222
198
 
223
199
  IO is built around the **Copilot SDK** which handles all LLM interactions, including tool calling and context management. The **Orchestrator** manages the primary conversation session with automatic context compaction for infinite-length sessions.
@@ -239,7 +215,7 @@ Access the web UI at `http://your-server:3170/` when running in daemon mode.
239
215
 
240
216
  ### Authentication
241
217
 
242
- The web portal supports optional Supabase email authentication. When enabled, users must sign in with email and password before accessing the dashboard. Only the configured `authorizedEmail` is allowed access.
218
+ The web portal uses Supabase email authentication. All API endpoints (except `/health`) require a valid JWT. Users must sign in with email and password before accessing the dashboard. Only the configured `authorizedEmail` is allowed access.
243
219
 
244
220
  **Setup:**
245
221
 
@@ -258,8 +234,6 @@ The web portal supports optional Supabase email authentication. When enabled, us
258
234
 
259
235
  5. Restart IO — the web portal will now require login
260
236
 
261
- > **Note:** Auth is completely optional. If `supabaseUrl` is not configured, the portal runs without authentication (open access).
262
-
263
237
  ## 🏗️ Project Structure
264
238
 
265
239
  ```
@@ -268,28 +242,35 @@ src/
268
242
  ├── daemon.ts # Daemon startup/shutdown
269
243
  ├── config.ts # Config loading
270
244
  ├── paths.ts # Path constants
271
- ├── update.ts # Self-update checker
245
+ ├── notify.ts # Notification routing
246
+ ├── watchdog.ts # Event loop stall + zombie detection
272
247
  ├── copilot/
273
248
  │ ├── client.ts # CopilotClient singleton
274
249
  │ ├── orchestrator.ts # Main session management
275
250
  │ ├── agents.ts # Named agent sessions & personas
276
- │ ├── universes.ts # 80s universe character data
277
251
  │ ├── tools.ts # Tool definitions
278
252
  │ ├── model-router.ts # Complexity-based model selection
279
253
  │ ├── skills.ts # Skills loader
254
+ │ ├── scheduler.ts # Squad cron scheduler
255
+ │ ├── io-scheduler.ts # IO-level cron scheduler
280
256
  │ └── system-message.ts # System prompt builder
281
257
  ├── store/
282
258
  │ ├── db.ts # SQLite database
283
259
  │ ├── squads.ts # Squad & agent CRUD
284
- └── tasks.ts # Agent task tracking
260
+ ├── tasks.ts # Agent task tracking
261
+ │ ├── instances.ts # Squad instance management
262
+ │ ├── feed.ts # Unified feed/inbox
263
+ │ └── schedules.ts # Schedule persistence
285
264
  ├── wiki/
286
265
  │ ├── fs.ts # Wiki filesystem
287
266
  │ └── search.ts # Wiki search
288
267
  ├── telegram/
289
268
  │ ├── bot.ts # Grammy Telegram bot
290
269
  │ └── handlers.ts # Command handlers
291
- ├── tui/
292
- └── index.ts # Terminal UI
270
+ ├── mcp/
271
+ ├── config.ts # MCP server config
272
+ │ ├── registry.ts # Module-level tool registry
273
+ │ └── index.ts # MCP exports
293
274
  └── api/
294
275
  ├── auth.ts # Supabase JWT auth middleware
295
276
  └── server.ts # Express HTTP + SSE + static frontend
@@ -298,11 +279,18 @@ web/ # Vue 3 frontend (built to web-dist/)
298
279
  ├── src/
299
280
  │ ├── lib/ # supabase.ts, api.ts (auth helpers)
300
281
  │ ├── stores/ # Pinia stores (chat, auth)
301
- │ ├── views/ # ChatView, SquadsView, SkillsView, AgentActivityView, LoginView
282
+ │ ├── views/ # ChatView, SquadsView, FeedView, SkillsView, McpView, etc.
302
283
  │ ├── router/ # Vue Router config + auth guard
303
284
  │ └── main.ts # App entry
304
285
  ├── vite.config.ts # Vite config (builds to ../web-dist/)
305
286
  └── package.json
287
+
288
+ docs/ # VitePress documentation site
289
+ ├── .vitepress/config.ts # Site configuration
290
+ ├── guide/ # Getting started, configuration, etc.
291
+ ├── architecture/ # System design documentation
292
+ ├── reference/ # CLI, API, and tools reference
293
+ └── package.json
306
294
  ```
307
295
 
308
296
  ## 🛠️ Development
@@ -321,8 +309,8 @@ npm run dev
321
309
  # Build for production
322
310
  npm run build
323
311
 
324
- # Run the TUI directly
325
- npm run tui
312
+ # Build everything (backend + web)
313
+ npm run build:all
326
314
 
327
315
  # Run the daemon directly
328
316
  npm run daemon
package/dist/api/auth.js CHANGED
@@ -1,44 +1,41 @@
1
- import { config } from "../config.js";
2
- /**
3
- * Express middleware that validates Supabase JWT tokens.
4
- * If auth is not configured (no supabaseUrl), all requests pass through.
5
- */
6
- export function requireAuth(req, res, next) {
7
- // Auth not configured — pass through
8
- if (!config.supabaseUrl || !config.supabaseAnonKey) {
9
- next();
10
- return;
11
- }
12
- const authHeader = req.headers.authorization;
13
- const queryToken = req.query.token;
14
- const bearerToken = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : undefined;
15
- const token = bearerToken ?? queryToken;
16
- if (!token) {
17
- res.status(401).json({ error: "Missing or invalid authorization" });
18
- return;
19
- }
20
- // Verify token by calling Supabase's /auth/v1/user endpoint
21
- fetch(`${config.supabaseUrl}/auth/v1/user`, {
22
- headers: {
23
- Authorization: `Bearer ${token}`,
24
- apikey: config.supabaseAnonKey,
25
- },
26
- })
27
- .then(async (resp) => {
28
- if (!resp.ok) {
29
- res.status(401).json({ error: "Invalid or expired token" });
1
+ export function createAuthMiddleware(config) {
2
+ return async (req, res, next) => {
3
+ // All API routes require authentication
4
+ const authHeader = req.headers.authorization;
5
+ if (!authHeader?.startsWith("Bearer ")) {
6
+ res.status(401).json({ error: "Missing or invalid authorization header" });
30
7
  return;
31
8
  }
32
- const user = (await resp.json());
33
- // Check authorized email if configured
34
- if (config.authorizedEmail && user.email !== config.authorizedEmail) {
35
- res.status(403).json({ error: "Unauthorized user" });
9
+ const token = authHeader.slice(7);
10
+ if (!config.supabaseUrl || !config.supabaseAnonKey) {
11
+ res.status(500).json({ error: "Supabase auth not configured" });
36
12
  return;
37
13
  }
38
- next();
39
- })
40
- .catch(() => {
41
- res.status(500).json({ error: "Auth verification failed" });
42
- });
14
+ try {
15
+ // Validate JWT with Supabase
16
+ const response = await fetch(`${config.supabaseUrl}/auth/v1/user`, {
17
+ headers: {
18
+ Authorization: `Bearer ${token}`,
19
+ apikey: config.supabaseAnonKey,
20
+ },
21
+ });
22
+ if (!response.ok) {
23
+ res.status(401).json({ error: "Invalid or expired token" });
24
+ return;
25
+ }
26
+ const user = (await response.json());
27
+ // Check authorized email
28
+ if (config.authorizedEmail && user.email !== config.authorizedEmail) {
29
+ res.status(403).json({ error: "Unauthorized user" });
30
+ return;
31
+ }
32
+ // Attach user to request
33
+ req.user = user;
34
+ next();
35
+ }
36
+ catch (err) {
37
+ res.status(401).json({ error: "Authentication failed" });
38
+ }
39
+ };
43
40
  }
44
41
  //# sourceMappingURL=auth.js.map