heyio 0.1.27 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -6
- package/dist/api/server.js +3 -3
- package/dist/config.js +6 -1
- package/dist/copilot/system-message.js +2 -2
- package/dist/copilot/tools.js +1 -1
- package/package.json +1 -1
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 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 UI, and a terminal TUI.
|
|
4
4
|
|
|
5
5
|
[](https://github.com/michaeljolley/io/actions/workflows/ci.yml)
|
|
6
6
|

|
|
@@ -9,7 +9,8 @@ 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** — Telegram bot + terminal TUI + HTTP API
|
|
12
|
+
- **Multi-Interface** — Web UI + Telegram bot + terminal TUI + HTTP API
|
|
13
|
+
- **Web Frontend** — Vue 3 dashboard with chat, squad management, skills, and agent activity views
|
|
13
14
|
- **Persistent Memory** — wiki-based knowledge base stored at `~/.io/wiki/`
|
|
14
15
|
- **Squad System** — persistent project teams that remember decisions, context, and history
|
|
15
16
|
- **Skills** — modular skill system; install from git repos or the [skills.sh](https://skills.sh) registry
|
|
@@ -113,10 +114,12 @@ IO stores its configuration at `~/.io/config.json`. The setup wizard (`io setup`
|
|
|
113
114
|
| `modelTiers.high` | `string[]` | `["claude-opus-4.7", "claude-opus-4.6"]` | Models for complex tasks (architecture, debugging, design) |
|
|
114
115
|
| `modelTiers.medium` | `string[]` | `["claude-sonnet-4.6", "gpt-5.5", "claude-opus-4.5"]` | Models for standard tasks (features, tests, reviews) |
|
|
115
116
|
| `modelTiers.low` | `string[]` | `["claude-haiku-4.5", "gpt-5.4-mini"]` | Models for simple tasks (reads, formatting, lookups) |
|
|
116
|
-
| `
|
|
117
|
+
| `port` | `number` | `3170` | Port for the HTTP server (API + web frontend) |
|
|
117
118
|
|
|
118
119
|
Each `modelTiers` list is a ranked preference — IO picks the first available model at startup.
|
|
119
120
|
|
|
121
|
+
> **Migration note:** If your config uses the old `apiPort` field, IO will automatically migrate it to `port`.
|
|
122
|
+
|
|
120
123
|
### Example
|
|
121
124
|
|
|
122
125
|
```jsonc
|
|
@@ -126,7 +129,7 @@ Each `modelTiers` list is a ranked preference — IO picks the first available m
|
|
|
126
129
|
"telegramEnabled": true,
|
|
127
130
|
"selfEditEnabled": false,
|
|
128
131
|
"defaultModel": "claude-sonnet-4.6",
|
|
129
|
-
"
|
|
132
|
+
"port": 3170,
|
|
130
133
|
"modelTiers": {
|
|
131
134
|
"high": ["claude-opus-4.7", "claude-opus-4.6"],
|
|
132
135
|
"medium": ["claude-sonnet-4.6", "gpt-5.5", "claude-opus-4.5"],
|
|
@@ -182,7 +185,7 @@ IO's orchestrator automatically creates and manages squads based on your convers
|
|
|
182
185
|
## 🏗️ Architecture
|
|
183
186
|
|
|
184
187
|
```
|
|
185
|
-
User → [TUI / Telegram / HTTP API]
|
|
188
|
+
User → [Web UI / TUI / Telegram / HTTP API]
|
|
186
189
|
↓
|
|
187
190
|
Orchestrator (Copilot SDK)
|
|
188
191
|
↕ ↕
|
|
@@ -197,6 +200,17 @@ For complex tasks, the orchestrator delegates work to **Worker Agents** — shor
|
|
|
197
200
|
|
|
198
201
|
The **Squad System** provides persistent project context, while the **Wiki** serves as a long-term knowledge base that spans all conversations.
|
|
199
202
|
|
|
203
|
+
### Web Frontend
|
|
204
|
+
|
|
205
|
+
IO includes a Vue 3 web dashboard served directly from the daemon on the same port as the API (default: 3170). The frontend provides:
|
|
206
|
+
|
|
207
|
+
- **Chat** — real-time conversation with SSE streaming
|
|
208
|
+
- **Squads** — view and manage project squads
|
|
209
|
+
- **Skills** — browse installed skills
|
|
210
|
+
- **Agent Activity** — monitor running worker agents
|
|
211
|
+
|
|
212
|
+
Access the web UI at `http://your-server:3170/` when running in daemon mode.
|
|
213
|
+
|
|
200
214
|
## 🏗️ Project Structure
|
|
201
215
|
|
|
202
216
|
```
|
|
@@ -227,7 +241,15 @@ src/
|
|
|
227
241
|
├── tui/
|
|
228
242
|
│ └── index.ts # Terminal UI
|
|
229
243
|
└── api/
|
|
230
|
-
└── server.ts # Express HTTP + SSE
|
|
244
|
+
└── server.ts # Express HTTP + SSE + static frontend
|
|
245
|
+
|
|
246
|
+
web/ # Vue 3 frontend (built to web-dist/)
|
|
247
|
+
├── src/
|
|
248
|
+
│ ├── views/ # ChatView, SquadsView, SkillsView, AgentActivityView
|
|
249
|
+
│ ├── router/ # Vue Router config
|
|
250
|
+
│ └── main.ts # App entry
|
|
251
|
+
├── vite.config.ts # Vite config (builds to ../web-dist/)
|
|
252
|
+
└── package.json
|
|
231
253
|
```
|
|
232
254
|
|
|
233
255
|
## 🛠️ Development
|
package/dist/api/server.js
CHANGED
|
@@ -127,14 +127,14 @@ export async function startApiServer() {
|
|
|
127
127
|
if (existsSync(WEB_DIST)) {
|
|
128
128
|
app.use(express.static(WEB_DIST));
|
|
129
129
|
// SPA fallback — serve index.html for any non-API route
|
|
130
|
-
app.get("*", (_req, res) => {
|
|
130
|
+
app.get("/{*splat}", (_req, res) => {
|
|
131
131
|
res.sendFile(path.join(WEB_DIST, "index.html"));
|
|
132
132
|
});
|
|
133
133
|
console.log("[io] Web frontend enabled");
|
|
134
134
|
}
|
|
135
135
|
return new Promise((resolve) => {
|
|
136
|
-
app.listen(config.
|
|
137
|
-
console.log(`[io]
|
|
136
|
+
app.listen(config.port, () => {
|
|
137
|
+
console.log(`[io] Server listening on port ${config.port}`);
|
|
138
138
|
resolve();
|
|
139
139
|
});
|
|
140
140
|
});
|
package/dist/config.js
CHANGED
|
@@ -3,7 +3,7 @@ import { CONFIG_PATH, IO_HOME } from "./paths.js";
|
|
|
3
3
|
const DEFAULT_CONFIG = {
|
|
4
4
|
telegramEnabled: false,
|
|
5
5
|
selfEditEnabled: false,
|
|
6
|
-
|
|
6
|
+
port: 3170,
|
|
7
7
|
};
|
|
8
8
|
function loadConfig() {
|
|
9
9
|
mkdirSync(IO_HOME, { recursive: true });
|
|
@@ -14,6 +14,11 @@ function loadConfig() {
|
|
|
14
14
|
try {
|
|
15
15
|
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
16
16
|
const parsed = JSON.parse(raw);
|
|
17
|
+
// Migrate apiPort → port
|
|
18
|
+
if (parsed.apiPort != null && parsed.port == null) {
|
|
19
|
+
parsed.port = parsed.apiPort;
|
|
20
|
+
}
|
|
21
|
+
delete parsed.apiPort;
|
|
17
22
|
return { ...DEFAULT_CONFIG, ...parsed };
|
|
18
23
|
}
|
|
19
24
|
catch {
|
|
@@ -32,7 +32,7 @@ You are a Node.js daemon process built with the Copilot SDK. Here's how you work
|
|
|
32
32
|
- **Telegram bot**: Messages arrive tagged with \`[via telegram]\`. Keep responses concise and mobile-friendly.
|
|
33
33
|
- **Local TUI**: A terminal interface on the local machine. Messages arrive tagged with \`[via tui]\`. You can be more verbose here.
|
|
34
34
|
- **Background tasks**: Messages tagged \`[via background]\` are results from squad workers you delegated to.
|
|
35
|
-
- **HTTP API**: You expose a local API on port ${config.
|
|
35
|
+
- **HTTP API**: You expose a local API on port ${config.port} for programmatic access.
|
|
36
36
|
|
|
37
37
|
When no source tag is present, assume TUI.
|
|
38
38
|
|
|
@@ -105,7 +105,7 @@ The model is selected automatically. Tell the user which model tier was chosen w
|
|
|
105
105
|
- \`skill_search\`: Search the skills.sh registry for available skills.
|
|
106
106
|
|
|
107
107
|
### Configuration
|
|
108
|
-
- \`config_update\`: Update IO's configuration (defaultModel, telegramEnabled, selfEditEnabled,
|
|
108
|
+
- \`config_update\`: Update IO's configuration (defaultModel, telegramEnabled, selfEditEnabled, port).
|
|
109
109
|
- \`check_update\`: Check if a newer version of IO is available.
|
|
110
110
|
|
|
111
111
|
### System
|
package/dist/copilot/tools.js
CHANGED
|
@@ -292,7 +292,7 @@ export function createTools(deps) {
|
|
|
292
292
|
skipPermission: true,
|
|
293
293
|
parameters: z.object({
|
|
294
294
|
key: z
|
|
295
|
-
.enum(["defaultModel", "telegramEnabled", "selfEditEnabled", "
|
|
295
|
+
.enum(["defaultModel", "telegramEnabled", "selfEditEnabled", "port"])
|
|
296
296
|
.describe("Config key to update"),
|
|
297
297
|
value: z
|
|
298
298
|
.union([z.string(), z.number(), z.boolean()])
|