heyio 1.12.1 → 3.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.
- package/dist/api/middleware/auth.d.ts +14 -0
- package/dist/api/middleware/auth.d.ts.map +1 -0
- package/dist/api/middleware/auth.js +66 -0
- package/dist/api/middleware/auth.js.map +1 -0
- package/dist/api/notifications.d.ts +14 -0
- package/dist/api/notifications.d.ts.map +1 -0
- package/dist/api/notifications.js +112 -0
- package/dist/api/notifications.js.map +1 -0
- package/dist/api/routes/activity.d.ts +3 -0
- package/dist/api/routes/activity.d.ts.map +1 -0
- package/dist/api/routes/activity.js +28 -0
- package/dist/api/routes/activity.js.map +1 -0
- package/dist/api/routes/attachments.d.ts +3 -0
- package/dist/api/routes/attachments.d.ts.map +1 -0
- package/dist/api/routes/attachments.js +83 -0
- package/dist/api/routes/attachments.js.map +1 -0
- package/dist/api/routes/config.d.ts +3 -0
- package/dist/api/routes/config.d.ts.map +1 -0
- package/dist/api/routes/config.js +106 -0
- package/dist/api/routes/config.js.map +1 -0
- package/dist/api/routes/conversations.d.ts +3 -0
- package/dist/api/routes/conversations.d.ts.map +1 -0
- package/dist/api/routes/conversations.js +69 -0
- package/dist/api/routes/conversations.js.map +1 -0
- package/dist/api/routes/health.d.ts +3 -0
- package/dist/api/routes/health.d.ts.map +1 -0
- package/dist/api/routes/health.js +16 -0
- package/dist/api/routes/health.js.map +1 -0
- package/dist/api/routes/inbox.d.ts +3 -0
- package/dist/api/routes/inbox.d.ts.map +1 -0
- package/dist/api/routes/inbox.js +88 -0
- package/dist/api/routes/inbox.js.map +1 -0
- package/dist/api/routes/schedules.d.ts +3 -0
- package/dist/api/routes/schedules.d.ts.map +1 -0
- package/dist/api/routes/schedules.js +96 -0
- package/dist/api/routes/schedules.js.map +1 -0
- package/dist/api/routes/skills.d.ts +2 -0
- package/dist/api/routes/skills.d.ts.map +1 -0
- package/dist/api/routes/skills.js +85 -0
- package/dist/api/routes/skills.js.map +1 -0
- package/dist/api/routes/squads.d.ts +3 -0
- package/dist/api/routes/squads.d.ts.map +1 -0
- package/dist/api/routes/squads.js +129 -0
- package/dist/api/routes/squads.js.map +1 -0
- package/dist/api/routes/usage.d.ts +3 -0
- package/dist/api/routes/usage.d.ts.map +1 -0
- package/dist/api/routes/usage.js +55 -0
- package/dist/api/routes/usage.js.map +1 -0
- package/dist/api/routes/wiki.d.ts +2 -0
- package/dist/api/routes/wiki.d.ts.map +1 -0
- package/dist/api/routes/wiki.js +43 -0
- package/dist/api/routes/wiki.js.map +1 -0
- package/dist/api/server.d.ts +7 -0
- package/dist/api/server.d.ts.map +1 -0
- package/dist/api/server.js +136 -634
- package/dist/api/server.js.map +1 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +2 -91
- package/dist/config.js.map +1 -0
- package/dist/copilot/client.d.ts +5 -0
- package/dist/copilot/client.d.ts.map +1 -0
- package/dist/copilot/client.js +19 -11
- package/dist/copilot/client.js.map +1 -0
- package/dist/copilot/health-monitor.d.ts +14 -0
- package/dist/copilot/health-monitor.d.ts.map +1 -0
- package/dist/copilot/health-monitor.js +70 -0
- package/dist/copilot/health-monitor.js.map +1 -0
- package/dist/copilot/orchestrator.d.ts +5 -0
- package/dist/copilot/orchestrator.d.ts.map +1 -0
- package/dist/copilot/orchestrator.js +127 -123
- package/dist/copilot/orchestrator.js.map +1 -0
- package/dist/copilot/tools.d.ts +49 -0
- package/dist/copilot/tools.d.ts.map +1 -0
- package/dist/copilot/tools.js +545 -321
- package/dist/copilot/tools.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -26
- package/dist/index.js.map +1 -0
- package/dist/logging/logger.d.ts +6 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +21 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/models/index.d.ts +6 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +4 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/pricing.d.ts +25 -0
- package/dist/models/pricing.d.ts.map +1 -0
- package/dist/models/pricing.js +96 -0
- package/dist/models/pricing.js.map +1 -0
- package/dist/models/registry.d.ts +34 -0
- package/dist/models/registry.d.ts.map +1 -0
- package/dist/models/registry.js +109 -0
- package/dist/models/registry.js.map +1 -0
- package/dist/models/token-tracker.d.ts +40 -0
- package/dist/models/token-tracker.d.ts.map +1 -0
- package/dist/models/token-tracker.js +102 -0
- package/dist/models/token-tracker.js.map +1 -0
- package/dist/scheduler/engine.d.ts +9 -0
- package/dist/scheduler/engine.d.ts.map +1 -0
- package/dist/scheduler/engine.js +127 -0
- package/dist/scheduler/engine.js.map +1 -0
- package/dist/skills/index.d.ts +3 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +2 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/store.d.ts +52 -0
- package/dist/skills/store.d.ts.map +1 -0
- package/dist/skills/store.js +148 -0
- package/dist/skills/store.js.map +1 -0
- package/dist/squad/agent.d.ts +46 -0
- package/dist/squad/agent.d.ts.map +1 -0
- package/dist/squad/agent.js +261 -0
- package/dist/squad/agent.js.map +1 -0
- package/dist/squad/autonomy.d.ts +16 -0
- package/dist/squad/autonomy.d.ts.map +1 -0
- package/dist/squad/autonomy.js +63 -0
- package/dist/squad/autonomy.js.map +1 -0
- package/dist/squad/event-bus.d.ts +22 -0
- package/dist/squad/event-bus.d.ts.map +1 -0
- package/dist/squad/event-bus.js +56 -0
- package/dist/squad/event-bus.js.map +1 -0
- package/dist/squad/execution/index.d.ts +12 -0
- package/dist/squad/execution/index.d.ts.map +1 -0
- package/dist/squad/execution/index.js +7 -0
- package/dist/squad/execution/index.js.map +1 -0
- package/dist/squad/execution/instance.d.ts +40 -0
- package/dist/squad/execution/instance.d.ts.map +1 -0
- package/dist/squad/execution/instance.js +138 -0
- package/dist/squad/execution/instance.js.map +1 -0
- package/dist/squad/execution/meeting.d.ts +25 -0
- package/dist/squad/execution/meeting.d.ts.map +1 -0
- package/dist/squad/execution/meeting.js +140 -0
- package/dist/squad/execution/meeting.js.map +1 -0
- package/dist/squad/execution/pr.d.ts +15 -0
- package/dist/squad/execution/pr.d.ts.map +1 -0
- package/dist/squad/execution/pr.js +93 -0
- package/dist/squad/execution/pr.js.map +1 -0
- package/dist/squad/execution/runner.d.ts +22 -0
- package/dist/squad/execution/runner.d.ts.map +1 -0
- package/dist/squad/execution/runner.js +68 -0
- package/dist/squad/execution/runner.js.map +1 -0
- package/dist/squad/execution/tasks.d.ts +11 -0
- package/dist/squad/execution/tasks.d.ts.map +1 -0
- package/dist/squad/execution/tasks.js +85 -0
- package/dist/squad/execution/tasks.js.map +1 -0
- package/dist/squad/execution/worktree.d.ts +26 -0
- package/dist/squad/execution/worktree.d.ts.map +1 -0
- package/dist/squad/execution/worktree.js +111 -0
- package/dist/squad/execution/worktree.js.map +1 -0
- package/dist/squad/hiring.d.ts +32 -0
- package/dist/squad/hiring.d.ts.map +1 -0
- package/dist/squad/hiring.js +200 -0
- package/dist/squad/hiring.js.map +1 -0
- package/dist/squad/index.d.ts +8 -0
- package/dist/squad/index.d.ts.map +1 -0
- package/dist/squad/index.js +6 -0
- package/dist/squad/index.js.map +1 -0
- package/dist/squad/manager.d.ts +48 -0
- package/dist/squad/manager.d.ts.map +1 -0
- package/dist/squad/manager.js +274 -0
- package/dist/squad/manager.js.map +1 -0
- package/dist/squad/name-generator.d.ts +16 -0
- package/dist/squad/name-generator.d.ts.map +1 -0
- package/dist/squad/name-generator.js +113 -0
- package/dist/squad/name-generator.js.map +1 -0
- package/dist/squad/roles/templates.d.ts +5 -0
- package/dist/squad/roles/templates.d.ts.map +1 -0
- package/dist/squad/roles/templates.js +102 -0
- package/dist/squad/roles/templates.js.map +1 -0
- package/dist/squad/skill-parser.d.ts +36 -0
- package/dist/squad/skill-parser.d.ts.map +1 -0
- package/dist/squad/skill-parser.js +83 -0
- package/dist/squad/skill-parser.js.map +1 -0
- package/dist/squad/source-resolver.d.ts +20 -0
- package/dist/squad/source-resolver.d.ts.map +1 -0
- package/dist/squad/source-resolver.js +52 -0
- package/dist/squad/source-resolver.js.map +1 -0
- package/dist/store/activity.d.ts +43 -0
- package/dist/store/activity.d.ts.map +1 -0
- package/dist/store/activity.js +131 -0
- package/dist/store/activity.js.map +1 -0
- package/dist/store/db.d.ts +5 -0
- package/dist/store/db.d.ts.map +1 -0
- package/dist/store/db.js +209 -248
- package/dist/store/db.js.map +1 -0
- package/dist/store/inbox.d.ts +53 -0
- package/dist/store/inbox.d.ts.map +1 -0
- package/dist/store/inbox.js +151 -0
- package/dist/store/inbox.js.map +1 -0
- package/dist/store/schedules.d.ts +53 -0
- package/dist/store/schedules.d.ts.map +1 -0
- package/dist/store/schedules.js +149 -54
- package/dist/store/schedules.js.map +1 -0
- package/dist/wiki/index.d.ts +3 -0
- package/dist/wiki/index.d.ts.map +1 -0
- package/dist/wiki/index.js +2 -0
- package/dist/wiki/index.js.map +1 -0
- package/dist/wiki/store.d.ts +49 -0
- package/dist/wiki/store.d.ts.map +1 -0
- package/dist/wiki/store.js +115 -0
- package/dist/wiki/store.js.map +1 -0
- package/package.json +52 -56
- package/src/api/middleware/auth.ts +76 -0
- package/src/api/notifications.ts +122 -0
- package/src/api/routes/activity.ts +29 -0
- package/src/api/routes/attachments.ts +93 -0
- package/src/api/routes/config.ts +115 -0
- package/src/api/routes/conversations.ts +87 -0
- package/src/api/routes/health.ts +18 -0
- package/src/api/routes/inbox.ts +98 -0
- package/src/api/routes/schedules.ts +121 -0
- package/src/api/routes/skills.ts +105 -0
- package/src/api/routes/squads.ts +145 -0
- package/src/api/routes/usage.ts +57 -0
- package/src/api/routes/wiki.ts +49 -0
- package/src/api/server.ts +186 -0
- package/src/config.ts +3 -0
- package/src/copilot/client.ts +42 -0
- package/src/copilot/health-monitor.ts +85 -0
- package/src/copilot/orchestrator.ts +222 -0
- package/src/copilot/tools.ts +707 -0
- package/src/index.ts +112 -0
- package/src/logging/logger.ts +26 -0
- package/src/models/index.ts +11 -0
- package/src/models/pricing.ts +121 -0
- package/src/models/registry.ts +131 -0
- package/src/models/token-tracker.ts +151 -0
- package/src/scheduler/engine.ts +146 -0
- package/src/skills/index.ts +13 -0
- package/src/skills/store.ts +188 -0
- package/src/squad/agent.ts +326 -0
- package/src/squad/autonomy.ts +78 -0
- package/src/squad/event-bus.ts +71 -0
- package/src/squad/execution/index.ts +17 -0
- package/src/squad/execution/instance.ts +186 -0
- package/src/squad/execution/meeting.ts +191 -0
- package/src/squad/execution/pr.ts +127 -0
- package/src/squad/execution/runner.ts +97 -0
- package/src/squad/execution/tasks.ts +111 -0
- package/src/squad/execution/worktree.ts +138 -0
- package/src/squad/hiring.ts +222 -0
- package/src/squad/index.ts +17 -0
- package/src/squad/manager.ts +337 -0
- package/src/squad/name-generator.ts +135 -0
- package/src/squad/roles/templates.ts +104 -0
- package/src/squad/skill-parser.ts +120 -0
- package/src/squad/source-resolver.ts +57 -0
- package/src/store/activity.ts +176 -0
- package/src/store/db.ts +237 -0
- package/src/store/inbox.ts +199 -0
- package/src/store/schedules.ts +199 -0
- package/src/wiki/index.ts +12 -0
- package/src/wiki/store.ts +139 -0
- package/tsconfig.json +9 -0
- package/LICENSE +0 -21
- package/README.md +0 -333
- package/dist/api/auth.js +0 -46
- package/dist/chat/attachments.js +0 -112
- package/dist/copilot/agents.js +0 -309
- package/dist/copilot/ceremonies.js +0 -174
- package/dist/copilot/gh-token.js +0 -64
- package/dist/copilot/io-scheduler.js +0 -79
- package/dist/copilot/model-router.js +0 -114
- package/dist/copilot/scheduler.js +0 -88
- package/dist/copilot/skills.js +0 -246
- package/dist/copilot/specialist-runner.js +0 -191
- package/dist/copilot/squad-tools.js +0 -258
- package/dist/copilot/system-message.js +0 -86
- package/dist/copilot/token-tracker.js +0 -98
- package/dist/copilot/trigger-schedule.js +0 -33
- package/dist/daemon.js +0 -67
- package/dist/logging.js +0 -27
- package/dist/mcp/config.js +0 -29
- package/dist/mcp/index.js +0 -3
- package/dist/mcp/registry.js +0 -42
- package/dist/notify.js +0 -25
- package/dist/paths.js +0 -17
- package/dist/setup.js +0 -35
- package/dist/store/agent-events.js +0 -19
- package/dist/store/audit-log.js +0 -71
- package/dist/store/conversations.js +0 -164
- package/dist/store/feed.js +0 -44
- package/dist/store/instances.js +0 -75
- package/dist/store/squad-colors.js +0 -23
- package/dist/store/squads.js +0 -60
- package/dist/store/tasks.js +0 -78
- package/dist/store/token-usage.js +0 -94
- package/dist/telegram/bot.js +0 -41
- package/dist/telegram/handlers.js +0 -42
- package/dist/watchdog.js +0 -37
- package/dist/wiki/backlinks.js +0 -51
- package/dist/wiki/fs.js +0 -108
- package/dist/wiki/search.js +0 -47
- package/web-dist/assets/AuditLogView-C5QtUQBq.js +0 -6
- package/web-dist/assets/ChatView-DLu9BMg8.js +0 -1
- package/web-dist/assets/FeedView-6OV-l6Gl.js +0 -6
- package/web-dist/assets/HistoryView-DizPqv0y.js +0 -1
- package/web-dist/assets/LoginView-CG1O9fmR.js +0 -1
- package/web-dist/assets/McpView-TJN-fZvI.js +0 -1
- package/web-dist/assets/SchedulesView-BDFpImX6.js +0 -6
- package/web-dist/assets/SettingsView-D-K1iC1c.js +0 -1
- package/web-dist/assets/SkillsView-DnNmO192.js +0 -15
- package/web-dist/assets/SquadDetailView-BBvrgHzn.js +0 -26
- package/web-dist/assets/SquadHealthView-DF2zF9D3.js +0 -11
- package/web-dist/assets/SquadsView-CPVzko7k.js +0 -6
- package/web-dist/assets/ToggleSwitch.vue_vue_type_script_setup_true_lang-Bk_t9_Rn.js +0 -1
- package/web-dist/assets/UsageView-OcyM5k14.js +0 -16
- package/web-dist/assets/WikiView-KhFqBZI0.js +0 -26
- package/web-dist/assets/api-BiDVwQrs.js +0 -1
- package/web-dist/assets/arrow-left-DFbf2tii.js +0 -6
- package/web-dist/assets/git-branch-BLstr_Gr.js +0 -6
- package/web-dist/assets/index-B-o45ao1.css +0 -1
- package/web-dist/assets/index-DCJUYZtV.js +0 -269
- package/web-dist/assets/pencil-D4Zz_t0y.js +0 -6
- package/web-dist/assets/plus-gmwiZVfr.js +0 -6
- package/web-dist/assets/save-BvtAs5WB.js +0 -6
- package/web-dist/assets/search-BabUvoGD.js +0 -6
- package/web-dist/assets/squad-colors-B8B_Y-lz.js +0 -1
- package/web-dist/assets/trash-2-C21cNLJl.js +0 -6
- package/web-dist/assets/triangle-alert-BrzY_E1n.js +0 -6
- package/web-dist/assets/x-xgLSmc9e.js +0 -6
- package/web-dist/favicon.svg +0 -10
- package/web-dist/index.html +0 -14
- package/web-dist/logo.svg +0 -10
package/README.md
DELETED
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
<img src="assets/IO-logo.svg" width="120"/>
|
|
2
|
-
|
|
3
|
-
IO is a personal AI assistant daemon built on the GitHub Copilot SDK. It runs 24/7 on your machine, reachable via Telegram, a web dashboard, and an HTTP API.
|
|
4
|
-
|
|
5
|
-
[](https://github.com/michaeljolley/io/actions/workflows/ci.yml)
|
|
6
|
-

|
|
7
|
-

|
|
8
|
-
|
|
9
|
-
## ✨ Features
|
|
10
|
-
|
|
11
|
-
- **Copilot SDK Integration** — powered by GitHub's Copilot SDK for LLM conversations with tool calling
|
|
12
|
-
- **Multi-Interface** — Web dashboard + Telegram bot + HTTP API
|
|
13
|
-
- **Web Frontend** — Vue 3 dashboard with chat, squad management, skills, and agent activity views
|
|
14
|
-
- **Web Chat Attachments** — Attach images/files in web chat (10MB per file, 25MB per message) with multimodal handoff
|
|
15
|
-
- **Persistent Memory** — wiki-based knowledge base stored at `~/.io/wiki/`
|
|
16
|
-
- **Squad System** — persistent project teams with **named specialist agents** themed from pop culture universes (dynamically selected at squad creation)
|
|
17
|
-
- **Skills** — modular skill system; install from git repos or the [skills.sh](https://skills.sh) registry
|
|
18
|
-
- **Adaptive Sessions** — infinite sessions with automatic context compaction
|
|
19
|
-
- **Named Agent Personas** — each squad agent gets a character persona with personality, dynamic role title, and specialized charter
|
|
20
|
-
- **GitHub Integration** — create, list, view, and comment on issues and PRs via the `github` tool
|
|
21
|
-
- **Smart Model Routing** — automatically selects the best model for each task based on complexity
|
|
22
|
-
- **Self-Updating** — checks for updates and can apply them automatically
|
|
23
|
-
- **MCP Integration** — Connect to external MCP servers for additional tools (Figma, databases, APIs)
|
|
24
|
-
- **Scheduling** — Cron-based scheduling for recurring tasks and squad stand-ups
|
|
25
|
-
- **Squad Instances** — Parallel worktrees for concurrent work within a single squad
|
|
26
|
-
- **Unified Feed** — Consolidated inbox and notification feed with web UI
|
|
27
|
-
- **Telegram Attachments** — Send images/files via Telegram for vision-capable model processing
|
|
28
|
-
- **Agent Preview** — Live streaming preview of any squad agent's activity in the web UI
|
|
29
|
-
- **Squad Wiki** — Per-squad wiki context included in agent prompts and instance snapshots
|
|
30
|
-
- **Instance Watchdog** — Monitors active/merging instances and auto-aborts stale ones
|
|
31
|
-
|
|
32
|
-
## 📋 Prerequisites
|
|
33
|
-
|
|
34
|
-
- **Node.js** >= 22
|
|
35
|
-
- **GitHub Copilot subscription** — IO uses the Copilot SDK, which requires an active Copilot license
|
|
36
|
-
- **GitHub CLI** (`gh`) — required for the `github` tool (issue/PR management). Install from [cli.github.com](https://cli.github.com/) and authenticate with `gh auth login`
|
|
37
|
-
|
|
38
|
-
## 🚀 Quick Start
|
|
39
|
-
|
|
40
|
-
### Install
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
npm install -g heyio
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Setup
|
|
47
|
-
|
|
48
|
-
Run the setup wizard to configure your Telegram bot token and user ID:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
io setup
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
This creates a config file at `~/.io/config.json`.
|
|
55
|
-
|
|
56
|
-
### Run
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
# Background daemon (Telegram + HTTP API + Web)
|
|
60
|
-
io --daemon
|
|
61
|
-
|
|
62
|
-
# Allow IO to modify its own source code
|
|
63
|
-
io --self-edit
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### Headless Server (systemd)
|
|
67
|
-
|
|
68
|
-
To run IO as a background service on a headless server:
|
|
69
|
-
|
|
70
|
-
1. Authenticate the Copilot SDK: `copilot login`
|
|
71
|
-
2. Authenticate the GitHub CLI: `gh auth login`
|
|
72
|
-
3. Create a systemd service file at `/etc/systemd/system/io.service`:
|
|
73
|
-
|
|
74
|
-
```ini
|
|
75
|
-
[Unit]
|
|
76
|
-
Description=IO Personal Assistant
|
|
77
|
-
After=network-online.target
|
|
78
|
-
Wants=network-online.target
|
|
79
|
-
|
|
80
|
-
[Service]
|
|
81
|
-
Type=simple
|
|
82
|
-
ExecStart=/usr/bin/env io --daemon
|
|
83
|
-
Restart=always
|
|
84
|
-
RestartSec=10
|
|
85
|
-
Environment=NODE_ENV=production
|
|
86
|
-
|
|
87
|
-
[Install]
|
|
88
|
-
WantedBy=multi-user.target
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
4. Enable and start: `systemctl enable --now io`
|
|
92
|
-
|
|
93
|
-
## 💬 CLI Usage
|
|
94
|
-
|
|
95
|
-
| Command | Description |
|
|
96
|
-
| --- | --- |
|
|
97
|
-
| `io --daemon` | Run as background daemon (Telegram + API + Web) |
|
|
98
|
-
| `io --self-edit` | Allow IO to modify its own source |
|
|
99
|
-
| `io setup` | Configure Telegram bot token and user ID |
|
|
100
|
-
|
|
101
|
-
Skills are managed via the web dashboard.
|
|
102
|
-
|
|
103
|
-
## ⚙️ Configuration
|
|
104
|
-
|
|
105
|
-
IO stores its configuration at `~/.io/config.json`. The setup wizard (`io setup`) handles initial configuration, but you can also edit the file directly.
|
|
106
|
-
|
|
107
|
-
### Parameters
|
|
108
|
-
|
|
109
|
-
| Parameter | Type | Default | Description |
|
|
110
|
-
| --- | --- | --- | --- |
|
|
111
|
-
| `telegramBotToken` | `string` | — | Telegram bot token from [@BotFather](https://t.me/BotFather) |
|
|
112
|
-
| `authorizedUserId` | `number` | — | Your Telegram user ID (only this user can interact with the bot) |
|
|
113
|
-
| `telegramEnabled` | `boolean` | `false` | Enable the Telegram bot interface |
|
|
114
|
-
| `selfEditEnabled` | `boolean` | `false` | Allow IO to modify its own source code |
|
|
115
|
-
| `defaultModel` | `string` | `"gpt-4.1"` | LLM model for the main orchestrator session |
|
|
116
|
-
| `port` | `number` | `3170` | Port for the HTTP server (API + web frontend) |
|
|
117
|
-
| `supabaseUrl` | `string` | — | Supabase project URL (enables web portal authentication) |
|
|
118
|
-
| `supabaseAnonKey` | `string` | — | Supabase anon/public API key |
|
|
119
|
-
| `authorizedEmail` | `string` | — | Email address allowed to access the web portal |
|
|
120
|
-
| `backgroundNotifyMode` | `string` | `"meaningful"` | Background task notification frequency: `"all"`, `"meaningful"`, or `"off"` |
|
|
121
|
-
| `backgroundNotifyTelegram` | `boolean` | `true` | Send background task notifications via Telegram |
|
|
122
|
-
| `watchdogEnabled` | `boolean` | `true` | Enable the daemon event loop watchdog |
|
|
123
|
-
|
|
124
|
-
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.
|
|
125
|
-
|
|
126
|
-
> **Migration note:** If your config uses the old `apiPort` field, IO will automatically migrate it to `port`.
|
|
127
|
-
|
|
128
|
-
### Example
|
|
129
|
-
|
|
130
|
-
```jsonc
|
|
131
|
-
{
|
|
132
|
-
"telegramBotToken": "123456:ABC-DEF...",
|
|
133
|
-
"authorizedUserId": 123456789,
|
|
134
|
-
"telegramEnabled": true,
|
|
135
|
-
"selfEditEnabled": false,
|
|
136
|
-
"defaultModel": "claude-sonnet-4.6",
|
|
137
|
-
"port": 3170,
|
|
138
|
-
"supabaseUrl": "https://your-project.supabase.co",
|
|
139
|
-
"supabaseAnonKey": "eyJhbGciOiJIUzI1NiIs...",
|
|
140
|
-
"authorizedEmail": "you@example.com"
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
All persistent data is stored under `~/.io/`:
|
|
145
|
-
|
|
146
|
-
| Path | Purpose |
|
|
147
|
-
| --- | --- |
|
|
148
|
-
| `~/.io/config.json` | User configuration |
|
|
149
|
-
| `~/.io/wiki/` | Knowledge base (markdown files) |
|
|
150
|
-
| `~/.io/io.db` | SQLite database (squads, tasks) |
|
|
151
|
-
| `~/.io/skills/` | Installed skills |
|
|
152
|
-
| `~/.io/mcp.json` | MCP server configuration |
|
|
153
|
-
|
|
154
|
-
## 🧩 Skills System
|
|
155
|
-
|
|
156
|
-
Skills are modular extensions that add new tools and capabilities to IO. Each skill is a directory containing a `SKILL.md` manifest and tool definitions.
|
|
157
|
-
|
|
158
|
-
### Managing Skills
|
|
159
|
-
|
|
160
|
-
Skills are managed through the web dashboard:
|
|
161
|
-
|
|
162
|
-
- **View** all installed skills with name, description, and slug
|
|
163
|
-
- **Install** new skills by providing a git repository URL
|
|
164
|
-
- **Remove** skills you no longer need
|
|
165
|
-
|
|
166
|
-
### Creating a Skill
|
|
167
|
-
|
|
168
|
-
A skill is a directory with a `SKILL.md` file that describes the skill and its tools. See the [Contributing Guide](CONTRIBUTING.md) for details on the skill format.
|
|
169
|
-
|
|
170
|
-
## 👥 Squad System
|
|
171
|
-
|
|
172
|
-
Squads are persistent project teams with **named specialist agents**. Each squad:
|
|
173
|
-
|
|
174
|
-
- Has a pop culture **universe theme** (dynamically researched at creation time — never hardcoded)
|
|
175
|
-
- Contains dynamically-created **specialist agents** with roles tailored to the project (e.g., "Express API Engineer", "Vue.js Frontend Dev")
|
|
176
|
-
- Each agent is assigned a **character persona** with personality traits that color their work style
|
|
177
|
-
- Remembers decisions, context, and conversation history across sessions
|
|
178
|
-
- Persists across sessions in the SQLite database
|
|
179
|
-
|
|
180
|
-
### How Squads Work
|
|
181
|
-
|
|
182
|
-
1. **Create** — `squad_create` assigns a random pop culture universe (or user picks one)
|
|
183
|
-
2. **Analyze** — `squad_analyze` scans the project to determine languages, frameworks, and tools
|
|
184
|
-
3. **Build the team** — `squad_add_agent` for each specialist the project needs; characters are drawn from the universe pool
|
|
185
|
-
4. **Delegate** — `squad_delegate` sends tasks to specific agents by character name
|
|
186
|
-
5. **Track** — `squad_task_status` monitors progress and retrieves results
|
|
187
|
-
|
|
188
|
-
## 🏗️ Architecture
|
|
189
|
-
|
|
190
|
-
```
|
|
191
|
-
User → [Web Dashboard / Telegram / HTTP API]
|
|
192
|
-
↓
|
|
193
|
-
Orchestrator (Copilot SDK)
|
|
194
|
-
↕ ↕ ↕
|
|
195
|
-
Squad Manager Wiki/Memory MCP Servers
|
|
196
|
-
↓
|
|
197
|
-
Named Agents (Pop Culture Characters)
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
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.
|
|
201
|
-
|
|
202
|
-
For complex tasks, the orchestrator delegates work to **Named Agents** — persistent agent sessions with character personas, specialized roles, and per-agent system prompts. Each agent works autonomously within their squad's project context.
|
|
203
|
-
|
|
204
|
-
The **Squad System** provides persistent project context, while the **Wiki** serves as a long-term knowledge base that spans all conversations.
|
|
205
|
-
|
|
206
|
-
### Web Frontend
|
|
207
|
-
|
|
208
|
-
IO includes a Vue 3 web dashboard served directly from the daemon on the same port as the API (default: 3170). The frontend provides:
|
|
209
|
-
|
|
210
|
-
- **Chat** — real-time conversation with SSE streaming
|
|
211
|
-
- **Squads** — view and manage project squads
|
|
212
|
-
- **Skills** — browse installed skills
|
|
213
|
-
- **Agent Activity** — monitor running worker agents
|
|
214
|
-
|
|
215
|
-
Access the web UI at `http://your-server:3170/` when running in daemon mode.
|
|
216
|
-
|
|
217
|
-
### Authentication
|
|
218
|
-
|
|
219
|
-
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.
|
|
220
|
-
|
|
221
|
-
**Setup:**
|
|
222
|
-
|
|
223
|
-
1. Create a [Supabase](https://supabase.com) project (or use an existing one)
|
|
224
|
-
2. Enable the **Email** auth provider in Supabase → Authentication → Providers
|
|
225
|
-
3. Create your user account in Supabase → Authentication → Users
|
|
226
|
-
4. Add the following to `~/.io/config.json`:
|
|
227
|
-
|
|
228
|
-
```jsonc
|
|
229
|
-
{
|
|
230
|
-
"supabaseUrl": "https://your-project.supabase.co",
|
|
231
|
-
"supabaseAnonKey": "eyJhbGciOiJIUzI1NiIs...",
|
|
232
|
-
"authorizedEmail": "you@example.com"
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
5. Restart IO — the web portal will now require login
|
|
237
|
-
|
|
238
|
-
## 🏗️ Project Structure
|
|
239
|
-
|
|
240
|
-
```
|
|
241
|
-
src/
|
|
242
|
-
├── index.ts # CLI entry (commander)
|
|
243
|
-
├── daemon.ts # Daemon startup/shutdown
|
|
244
|
-
├── config.ts # Config loading
|
|
245
|
-
├── paths.ts # Path constants
|
|
246
|
-
├── notify.ts # Notification routing
|
|
247
|
-
├── watchdog.ts # Event loop stall + zombie detection
|
|
248
|
-
├── copilot/
|
|
249
|
-
│ ├── client.ts # CopilotClient singleton
|
|
250
|
-
│ ├── orchestrator.ts # Main session management
|
|
251
|
-
│ ├── agents.ts # Named agent sessions & personas
|
|
252
|
-
│ ├── tools.ts # Tool definitions
|
|
253
|
-
│ ├── model-router.ts # Complexity-based model selection
|
|
254
|
-
│ ├── skills.ts # Skills loader
|
|
255
|
-
│ ├── scheduler.ts # Squad cron scheduler
|
|
256
|
-
│ ├── io-scheduler.ts # IO-level cron scheduler
|
|
257
|
-
│ └── system-message.ts # System prompt builder
|
|
258
|
-
├── store/
|
|
259
|
-
│ ├── db.ts # SQLite database
|
|
260
|
-
│ ├── squads.ts # Squad & agent CRUD
|
|
261
|
-
│ ├── tasks.ts # Agent task tracking
|
|
262
|
-
│ ├── instances.ts # Squad instance management
|
|
263
|
-
│ ├── feed.ts # Unified feed/inbox
|
|
264
|
-
│ └── schedules.ts # Schedule persistence
|
|
265
|
-
├── wiki/
|
|
266
|
-
│ ├── fs.ts # Wiki filesystem
|
|
267
|
-
│ └── search.ts # Wiki search
|
|
268
|
-
├── telegram/
|
|
269
|
-
│ ├── bot.ts # Grammy Telegram bot
|
|
270
|
-
│ └── handlers.ts # Command handlers
|
|
271
|
-
├── mcp/
|
|
272
|
-
│ ├── config.ts # MCP server config
|
|
273
|
-
│ ├── registry.ts # Module-level tool registry
|
|
274
|
-
│ └── index.ts # MCP exports
|
|
275
|
-
└── api/
|
|
276
|
-
├── auth.ts # Supabase JWT auth middleware
|
|
277
|
-
└── server.ts # Express HTTP + SSE + static frontend
|
|
278
|
-
|
|
279
|
-
web/ # Vue 3 frontend (built to web-dist/)
|
|
280
|
-
├── src/
|
|
281
|
-
│ ├── lib/ # supabase.ts, api.ts (auth helpers)
|
|
282
|
-
│ ├── stores/ # Pinia stores (chat, auth)
|
|
283
|
-
│ ├── views/ # ChatView, SquadsView, FeedView, SkillsView, McpView, etc.
|
|
284
|
-
│ ├── router/ # Vue Router config + auth guard
|
|
285
|
-
│ └── main.ts # App entry
|
|
286
|
-
├── vite.config.ts # Vite config (builds to ../web-dist/)
|
|
287
|
-
└── package.json
|
|
288
|
-
|
|
289
|
-
docs/ # VitePress documentation site
|
|
290
|
-
├── .vitepress/config.ts # Site configuration
|
|
291
|
-
├── guide/ # Getting started, configuration, etc.
|
|
292
|
-
├── architecture/ # System design documentation
|
|
293
|
-
├── reference/ # CLI, API, and tools reference
|
|
294
|
-
└── package.json
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
## 🛠️ Development
|
|
298
|
-
|
|
299
|
-
```bash
|
|
300
|
-
# Clone the repository
|
|
301
|
-
git clone https://github.com/michaeljolley/io.git
|
|
302
|
-
cd io
|
|
303
|
-
|
|
304
|
-
# Install dependencies
|
|
305
|
-
npm install
|
|
306
|
-
|
|
307
|
-
# Run in development mode (watch)
|
|
308
|
-
npm run dev
|
|
309
|
-
|
|
310
|
-
# Build for production
|
|
311
|
-
npm run build
|
|
312
|
-
|
|
313
|
-
# Build everything (backend + web)
|
|
314
|
-
npm run build:all
|
|
315
|
-
|
|
316
|
-
# Run the daemon directly
|
|
317
|
-
npm run daemon
|
|
318
|
-
|
|
319
|
-
# Run the test suite
|
|
320
|
-
npm test
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
Tests use the Node.js built-in test runner with [tsx](https://github.com/privatenumber/tsx) for TypeScript support. Test files live alongside source files as `*.test.ts`.
|
|
324
|
-
|
|
325
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed development guidelines.
|
|
326
|
-
|
|
327
|
-
## 📄 License
|
|
328
|
-
|
|
329
|
-
This project is licensed under the [MIT License](LICENSE).
|
|
330
|
-
|
|
331
|
-
## 🤝 Contributing
|
|
332
|
-
|
|
333
|
-
Contributions are welcome! Please read the [Contributing Guide](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md) before submitting a pull request.
|
package/dist/api/auth.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export function createAuthMiddleware(config) {
|
|
2
|
-
return async (req, res, next) => {
|
|
3
|
-
// Public endpoints that don't require auth
|
|
4
|
-
if (req.path === "/auth/config") {
|
|
5
|
-
next();
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
// All other API routes require authentication
|
|
9
|
-
const authHeader = req.headers.authorization;
|
|
10
|
-
if (!authHeader?.startsWith("Bearer ")) {
|
|
11
|
-
res.status(401).json({ error: "Missing or invalid authorization header" });
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
const token = authHeader.slice(7);
|
|
15
|
-
if (!config.supabaseUrl || !config.supabaseAnonKey) {
|
|
16
|
-
res.status(500).json({ error: "Supabase auth not configured" });
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
try {
|
|
20
|
-
// Validate JWT with Supabase
|
|
21
|
-
const response = await fetch(`${config.supabaseUrl}/auth/v1/user`, {
|
|
22
|
-
headers: {
|
|
23
|
-
Authorization: `Bearer ${token}`,
|
|
24
|
-
apikey: config.supabaseAnonKey,
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
if (!response.ok) {
|
|
28
|
-
res.status(401).json({ error: "Invalid or expired token" });
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const user = (await response.json());
|
|
32
|
-
// Check authorized email
|
|
33
|
-
if (config.authorizedEmail && user.email !== config.authorizedEmail) {
|
|
34
|
-
res.status(403).json({ error: "Unauthorized user" });
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
// Attach user to request
|
|
38
|
-
req.user = user;
|
|
39
|
-
next();
|
|
40
|
-
}
|
|
41
|
-
catch (err) {
|
|
42
|
-
res.status(401).json({ error: "Authentication failed" });
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=auth.js.map
|
package/dist/chat/attachments.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { randomUUID } from "node:crypto";
|
|
4
|
-
import { PATHS } from "../paths.js";
|
|
5
|
-
export const MAX_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
6
|
-
export const MAX_TOTAL_ATTACHMENT_BYTES = 25 * 1024 * 1024;
|
|
7
|
-
const BASE64_RE = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
8
|
-
function isValidBase64(value) {
|
|
9
|
-
if (!value || value.length % 4 !== 0)
|
|
10
|
-
return false;
|
|
11
|
-
return BASE64_RE.test(value);
|
|
12
|
-
}
|
|
13
|
-
function isMessageAttachment(value) {
|
|
14
|
-
if (!value || typeof value !== "object")
|
|
15
|
-
return false;
|
|
16
|
-
const candidate = value;
|
|
17
|
-
return (typeof candidate.name === "string" &&
|
|
18
|
-
candidate.name.trim().length > 0 &&
|
|
19
|
-
typeof candidate.mimeType === "string" &&
|
|
20
|
-
candidate.mimeType.trim().length > 0 &&
|
|
21
|
-
typeof candidate.size === "number" &&
|
|
22
|
-
Number.isFinite(candidate.size) &&
|
|
23
|
-
candidate.size >= 0 &&
|
|
24
|
-
typeof candidate.content === "string");
|
|
25
|
-
}
|
|
26
|
-
export function validateMessageAttachments(input) {
|
|
27
|
-
if (input === undefined || input === null) {
|
|
28
|
-
return { ok: true, attachments: [] };
|
|
29
|
-
}
|
|
30
|
-
if (!Array.isArray(input)) {
|
|
31
|
-
return { ok: false, error: "attachments must be an array" };
|
|
32
|
-
}
|
|
33
|
-
let totalSize = 0;
|
|
34
|
-
const attachments = [];
|
|
35
|
-
for (const raw of input) {
|
|
36
|
-
if (!isMessageAttachment(raw)) {
|
|
37
|
-
return {
|
|
38
|
-
ok: false,
|
|
39
|
-
error: "each attachment must include name, mimeType, size, and content",
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
if (raw.size > MAX_ATTACHMENT_BYTES) {
|
|
43
|
-
return { ok: false, error: "each attachment must be 10MB or smaller" };
|
|
44
|
-
}
|
|
45
|
-
if (!isValidBase64(raw.content)) {
|
|
46
|
-
return { ok: false, error: `attachment "${raw.name}" has invalid base64 content` };
|
|
47
|
-
}
|
|
48
|
-
const trimmedName = raw.name.trim();
|
|
49
|
-
const trimmedMimeType = raw.mimeType.trim();
|
|
50
|
-
if (!trimmedName || !trimmedMimeType) {
|
|
51
|
-
return { ok: false, error: "attachment name and mimeType are required" };
|
|
52
|
-
}
|
|
53
|
-
totalSize += raw.size;
|
|
54
|
-
attachments.push({
|
|
55
|
-
name: trimmedName,
|
|
56
|
-
mimeType: trimmedMimeType,
|
|
57
|
-
size: raw.size,
|
|
58
|
-
content: raw.content,
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
if (totalSize > MAX_TOTAL_ATTACHMENT_BYTES) {
|
|
62
|
-
return { ok: false, error: "total attachment size must be 25MB or smaller" };
|
|
63
|
-
}
|
|
64
|
-
return { ok: true, attachments };
|
|
65
|
-
}
|
|
66
|
-
export function toCopilotBlobAttachments(attachments) {
|
|
67
|
-
return attachments.map((attachment) => ({
|
|
68
|
-
type: "blob",
|
|
69
|
-
data: attachment.content,
|
|
70
|
-
mimeType: attachment.mimeType,
|
|
71
|
-
displayName: attachment.name,
|
|
72
|
-
}));
|
|
73
|
-
}
|
|
74
|
-
export function buildAttachmentSummary(attachments) {
|
|
75
|
-
if (attachments.length === 0)
|
|
76
|
-
return "";
|
|
77
|
-
const lines = attachments.map((attachment) => `- ${attachment.name} (${attachment.mimeType}, ${Math.round(attachment.size / 1024)}KB)`);
|
|
78
|
-
return `\n\n[Attachments]\n${lines.join("\n")}`;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Save attachments to disk at ~/.io/attachments/{batchId}/{filename}
|
|
82
|
-
* Returns the saved paths so they can be referenced by the orchestrator and squads.
|
|
83
|
-
*/
|
|
84
|
-
export function saveAttachmentsToDisk(attachments) {
|
|
85
|
-
if (attachments.length === 0)
|
|
86
|
-
return [];
|
|
87
|
-
const batchId = randomUUID();
|
|
88
|
-
const batchDir = join(PATHS.attachments, batchId);
|
|
89
|
-
if (!existsSync(PATHS.attachments))
|
|
90
|
-
mkdirSync(PATHS.attachments, { recursive: true });
|
|
91
|
-
mkdirSync(batchDir, { recursive: true });
|
|
92
|
-
return attachments.map((attachment) => {
|
|
93
|
-
const filePath = join(batchDir, attachment.name);
|
|
94
|
-
writeFileSync(filePath, Buffer.from(attachment.content, "base64"));
|
|
95
|
-
return {
|
|
96
|
-
name: attachment.name,
|
|
97
|
-
mimeType: attachment.mimeType,
|
|
98
|
-
size: attachment.size,
|
|
99
|
-
path: filePath,
|
|
100
|
-
};
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Build a summary that includes file paths on disk for tool access.
|
|
105
|
-
*/
|
|
106
|
-
export function buildAttachmentPathSummary(saved) {
|
|
107
|
-
if (saved.length === 0)
|
|
108
|
-
return "";
|
|
109
|
-
const lines = saved.map((s) => `- ${s.name} (${s.mimeType}, ${Math.round(s.size / 1024)}KB) → ${s.path}`);
|
|
110
|
-
return `\n\n[Attached files saved to disk]\n${lines.join("\n")}`;
|
|
111
|
-
}
|
|
112
|
-
//# sourceMappingURL=attachments.js.map
|