heyio 1.13.0 → 3.0.1
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 +162 -278
- 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/node_modules/@io/shared/dist/config.d.ts +25 -0
- package/node_modules/@io/shared/dist/config.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/config.js +47 -0
- package/node_modules/@io/shared/dist/config.js.map +1 -0
- package/node_modules/@io/shared/dist/constants.d.ts +13 -0
- package/node_modules/@io/shared/dist/constants.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/constants.js +34 -0
- package/node_modules/@io/shared/dist/constants.js.map +1 -0
- package/node_modules/@io/shared/dist/index.d.ts +11 -0
- package/node_modules/@io/shared/dist/index.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/index.js +3 -0
- package/node_modules/@io/shared/dist/index.js.map +1 -0
- package/node_modules/@io/shared/dist/types/agents.d.ts +3 -0
- package/node_modules/@io/shared/dist/types/agents.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/types/agents.js +2 -0
- package/node_modules/@io/shared/dist/types/agents.js.map +1 -0
- package/node_modules/@io/shared/dist/types/api.d.ts +33 -0
- package/node_modules/@io/shared/dist/types/api.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/types/api.js +2 -0
- package/node_modules/@io/shared/dist/types/api.js.map +1 -0
- package/node_modules/@io/shared/dist/types/attachments.d.ts +10 -0
- package/node_modules/@io/shared/dist/types/attachments.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/types/attachments.js +2 -0
- package/node_modules/@io/shared/dist/types/attachments.js.map +1 -0
- package/node_modules/@io/shared/dist/types/events.d.ts +44 -0
- package/node_modules/@io/shared/dist/types/events.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/types/events.js +2 -0
- package/node_modules/@io/shared/dist/types/events.js.map +1 -0
- package/node_modules/@io/shared/dist/types/messages.d.ts +15 -0
- package/node_modules/@io/shared/dist/types/messages.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/types/messages.js +2 -0
- package/node_modules/@io/shared/dist/types/messages.js.map +1 -0
- package/node_modules/@io/shared/dist/types/squads.d.ts +43 -0
- package/node_modules/@io/shared/dist/types/squads.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/types/squads.js +2 -0
- package/node_modules/@io/shared/dist/types/squads.js.map +1 -0
- package/node_modules/@io/shared/dist/types/tokens.d.ts +19 -0
- package/node_modules/@io/shared/dist/types/tokens.d.ts.map +1 -0
- package/node_modules/@io/shared/dist/types/tokens.js +2 -0
- package/node_modules/@io/shared/dist/types/tokens.js.map +1 -0
- package/node_modules/@io/shared/package.json +18 -0
- package/node_modules/@io/shared/src/config.ts +74 -0
- package/node_modules/@io/shared/src/constants.ts +36 -0
- package/node_modules/@io/shared/src/index.ts +37 -0
- package/node_modules/@io/shared/src/types/agents.ts +3 -0
- package/node_modules/@io/shared/src/types/api.ts +35 -0
- package/node_modules/@io/shared/src/types/attachments.ts +9 -0
- package/node_modules/@io/shared/src/types/events.ts +81 -0
- package/node_modules/@io/shared/src/types/messages.ts +15 -0
- package/node_modules/@io/shared/src/types/squads.ts +53 -0
- package/node_modules/@io/shared/src/types/tokens.ts +19 -0
- package/node_modules/@io/shared/tsconfig.json +9 -0
- package/node_modules/@io/shared/tsconfig.tsbuildinfo +1 -0
- package/package.json +56 -59
- 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/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 -252
- 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-BzfjNXBT.js +0 -6
- package/web-dist/assets/ChatView-BdMukPKG.js +0 -1
- package/web-dist/assets/FeedView-BfPIabGr.js +0 -6
- package/web-dist/assets/HistoryView-BmEEk3Rs.js +0 -1
- package/web-dist/assets/LoginView-D7LrkeX7.js +0 -1
- package/web-dist/assets/McpView-BAP_ah3T.js +0 -1
- package/web-dist/assets/SchedulesView-CAtsUPCZ.js +0 -6
- package/web-dist/assets/SettingsView-BovjWZDa.js +0 -1
- package/web-dist/assets/SkillsView-DQSMM5LN.js +0 -16
- package/web-dist/assets/SquadDetailView-DBscu0m2.js +0 -26
- package/web-dist/assets/SquadHealthView-D686BuQo.js +0 -11
- package/web-dist/assets/SquadsView-AzMht2NJ.js +0 -6
- package/web-dist/assets/ToggleSwitch.vue_vue_type_script_setup_true_lang-DtShZAjW.js +0 -1
- package/web-dist/assets/UsageView-DiVn97aI.js +0 -16
- package/web-dist/assets/WikiView-Cn7KipkZ.js +0 -26
- package/web-dist/assets/api-D4mHJ3u0.js +0 -1
- package/web-dist/assets/arrow-left-D_qUNUWW.js +0 -6
- package/web-dist/assets/git-branch-DOM-orcl.js +0 -6
- package/web-dist/assets/index-Bo83B1LR.css +0 -1
- package/web-dist/assets/index-ELvnkQjd.js +0 -273
- package/web-dist/assets/pencil-CFsi7ufI.js +0 -6
- package/web-dist/assets/plus-BAzlGFd_.js +0 -6
- package/web-dist/assets/save-BmgCYJ1g.js +0 -6
- package/web-dist/assets/search-CS9zSIeW.js +0 -6
- package/web-dist/assets/squad-colors-B8B_Y-lz.js +0 -1
- package/web-dist/assets/trash-2-DLveUEsd.js +0 -6
- package/web-dist/assets/triangle-alert-lj4I30rL.js +0 -6
- package/web-dist/assets/x-CjXR97Fa.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
CHANGED
|
@@ -1,333 +1,217 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
- **
|
|
24
|
-
- **
|
|
25
|
-
- **
|
|
26
|
-
- **
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/IO-logo.svg" alt="IO Logo" width="200" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">IO</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>AI Orchestrator Daemon — manage specialized agent squads for your software projects</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://michaeljolley.github.io/io">Documentation</a> •
|
|
13
|
+
<a href="#getting-started">Getting Started</a> •
|
|
14
|
+
<a href="#architecture">Architecture</a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## What is IO?
|
|
20
|
+
|
|
21
|
+
IO is an always-running daemon that acts as your personal AI orchestrator. You talk to IO, and IO manages teams of specialized AI agents ("squads") that work on your codebases.
|
|
22
|
+
|
|
23
|
+
- **One conversation interface** — talk to IO via TUI, Telegram, or the web dashboard
|
|
24
|
+
- **Squad delegation** — IO automatically routes project questions to the right squad
|
|
25
|
+
- **Universe theming** — squads get pop-culture character names and personas via LLM
|
|
26
|
+
- **Web dashboard** — React SPA with real-time chat, squad management, and usage charts
|
|
27
|
+
- **Cron schedules** — automate recurring tasks like daily standups or issue triage
|
|
28
|
+
- **Inbox system** — squads can send you deliverables or ask blocking questions
|
|
29
|
+
- **Model management** — token tracking and configurable model selection per agent
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
```mermaid
|
|
34
|
+
graph TD
|
|
35
|
+
User["🧑 You<br/>(TUI / Telegram / Web)"]
|
|
36
|
+
Orch["🤖 Orchestrator<br/>(Copilot SDK · tool-calling)"]
|
|
37
|
+
Wiki["📚 Wiki<br/>(Knowledge Base)"]
|
|
38
|
+
Skills["🧩 Skills<br/>(SKILL.md)"]
|
|
39
|
+
Sched["⏰ Scheduler<br/>(cron jobs)"]
|
|
40
|
+
SquadA["👥 Squad A<br/>(Team Lead + Agents)"]
|
|
41
|
+
SquadB["👥 Squad B<br/>(Team Lead + Agents)"]
|
|
42
|
+
Web["🌐 Web Dashboard<br/>(React SPA)"]
|
|
43
|
+
|
|
44
|
+
User --> Orch
|
|
45
|
+
User --> Web
|
|
46
|
+
Web --> Orch
|
|
47
|
+
Orch --> SquadA
|
|
48
|
+
Orch --> SquadB
|
|
49
|
+
Orch --> Sched
|
|
50
|
+
Orch --> Wiki
|
|
51
|
+
Orch --> Skills
|
|
52
|
+
SquadA --> Wiki
|
|
53
|
+
SquadB --> Wiki
|
|
44
54
|
```
|
|
45
55
|
|
|
46
|
-
|
|
56
|
+
Each squad has:
|
|
57
|
+
- **Team Lead** — receives objectives, creates plans, coordinates agents
|
|
58
|
+
- **Agents** — specialized workers (developer, reviewer, etc.) with pop-culture character names
|
|
59
|
+
- **Meetings** — structured collaboration between agents for planning and review
|
|
60
|
+
- **QA/Tester** — required veto-holding member who must approve before completion
|
|
47
61
|
|
|
48
|
-
|
|
62
|
+
## Getting Started
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
io setup
|
|
52
|
-
```
|
|
64
|
+
### Prerequisites
|
|
53
65
|
|
|
54
|
-
|
|
66
|
+
- Node.js 22+
|
|
67
|
+
- GitHub Copilot access (the daemon uses `@github/copilot-sdk`)
|
|
68
|
+
- Git
|
|
55
69
|
|
|
56
|
-
###
|
|
70
|
+
### Installation
|
|
57
71
|
|
|
58
72
|
```bash
|
|
59
|
-
|
|
60
|
-
io
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
io --self-edit
|
|
73
|
+
git clone https://github.com/michaeljolley/io.git
|
|
74
|
+
cd io
|
|
75
|
+
npm install
|
|
76
|
+
npm run build
|
|
64
77
|
```
|
|
65
78
|
|
|
66
|
-
###
|
|
67
|
-
|
|
68
|
-
To run IO as a background service on a headless server:
|
|
79
|
+
### Running
|
|
69
80
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
81
|
+
```bash
|
|
82
|
+
# Start the daemon
|
|
83
|
+
npm run dev
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
# Or build and start
|
|
86
|
+
npm run build
|
|
87
|
+
npm start
|
|
89
88
|
```
|
|
90
89
|
|
|
91
|
-
|
|
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
|
|
90
|
+
The daemon starts on port `7777` by default. The web dashboard is served at the same port — open `http://localhost:7777` in your browser.
|
|
104
91
|
|
|
105
|
-
|
|
92
|
+
### Configuration
|
|
106
93
|
|
|
107
|
-
|
|
94
|
+
Create `~/.io/config.json`:
|
|
108
95
|
|
|
109
|
-
|
|
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
|
|
96
|
+
```json
|
|
131
97
|
{
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
"
|
|
98
|
+
"apiPort": 7777,
|
|
99
|
+
"defaultModel": "claude-opus-4.6",
|
|
100
|
+
"logLevel": "info",
|
|
101
|
+
"maxInstancesPerSquad": 3,
|
|
102
|
+
"telegram": {
|
|
103
|
+
"botToken": "your-token-from-botfather",
|
|
104
|
+
"allowedChatIds": [12345678]
|
|
105
|
+
},
|
|
106
|
+
"supabase": {
|
|
107
|
+
"projectUrl": "https://your-project.supabase.co",
|
|
108
|
+
"anonKey": "eyJ...",
|
|
109
|
+
"jwtSecret": "your-jwt-secret"
|
|
110
|
+
}
|
|
141
111
|
}
|
|
142
112
|
```
|
|
143
113
|
|
|
144
|
-
All
|
|
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
|
|
114
|
+
All settings can also be controlled via environment variables (which take priority):
|
|
155
115
|
|
|
156
|
-
|
|
116
|
+
| Variable | Config Key | Default |
|
|
117
|
+
|----------|-----------|---------|
|
|
118
|
+
| `IO_PORT` | `apiPort` | `7777` |
|
|
119
|
+
| `IO_LOG_LEVEL` | `logLevel` | `info` |
|
|
120
|
+
| `IO_MODEL` | `defaultModel` | `claude-opus-4.6` |
|
|
121
|
+
| `IO_DATA_DIR` | `dataDir` | `~/.io` |
|
|
122
|
+
| `TELEGRAM_BOT_TOKEN` | `telegram.botToken` | — |
|
|
123
|
+
| `TELEGRAM_ALLOWED_CHAT_IDS` | `telegram.allowedChatIds` | — |
|
|
124
|
+
| `IO_SUPABASE_URL` | `supabase.projectUrl` | — |
|
|
125
|
+
| `IO_SUPABASE_ANON_KEY` | `supabase.anonKey` | — |
|
|
126
|
+
| `IO_SUPABASE_JWT_SECRET` | `supabase.jwtSecret` | — |
|
|
157
127
|
|
|
158
|
-
|
|
128
|
+
See the [Configuration Guide](https://michaeljolley.github.io/io/guides/configuration/) for full details.
|
|
159
129
|
|
|
160
|
-
|
|
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
|
|
130
|
+
### Authentication
|
|
165
131
|
|
|
166
|
-
|
|
132
|
+
When Supabase is configured, the web dashboard requires login and all API endpoints are secured with JWT verification. If Supabase is **not** configured, the API stays open (suitable for local-only use).
|
|
167
133
|
|
|
168
|
-
|
|
134
|
+
## Key Features
|
|
169
135
|
|
|
170
|
-
|
|
136
|
+
### Squads
|
|
171
137
|
|
|
172
|
-
|
|
138
|
+
Hire a squad for any project:
|
|
173
139
|
|
|
174
|
-
|
|
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
|
|
140
|
+
> "Hire a squad for https://github.com/org/my-app with the Star Wars universe"
|
|
179
141
|
|
|
180
|
-
|
|
142
|
+
IO creates a team with character names from your chosen universe (e.g., "Yoda" as Team Lead, "R2-D2" as DevOps). Each member gets a persona that influences their communication style.
|
|
181
143
|
|
|
182
|
-
|
|
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
|
|
144
|
+
### Web Dashboard
|
|
187
145
|
|
|
188
|
-
|
|
146
|
+
A full React SPA served by the daemon at the API port:
|
|
147
|
+
- **Chat** — real-time streaming conversation with IO
|
|
148
|
+
- **Squads** — view teams, members, active instances, and activity
|
|
149
|
+
- **Feed** — inbox of deliverables and blocking questions
|
|
150
|
+
- **Skills** — manage installed SKILL.md capabilities
|
|
151
|
+
- **Schedules** — CRUD for cron-based automation
|
|
152
|
+
- **Wiki** — knowledge base viewer and editor
|
|
153
|
+
- **Usage** — token and cost charts (by squad, model, time)
|
|
154
|
+
- **Settings** — configure all daemon options from the UI
|
|
189
155
|
|
|
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
|
-
```
|
|
156
|
+
### Schedules
|
|
199
157
|
|
|
200
|
-
|
|
158
|
+
Automate recurring work with cron expressions:
|
|
201
159
|
|
|
202
|
-
|
|
160
|
+
> "Create a daily standup for my-app at 9am on weekdays — have them review open issues and report progress"
|
|
203
161
|
|
|
204
|
-
|
|
162
|
+
### Inbox
|
|
205
163
|
|
|
206
|
-
|
|
164
|
+
Squads communicate back via the inbox:
|
|
165
|
+
- **Deliverables** — status reports, completed summaries
|
|
166
|
+
- **Blocking questions** — the squad pauses and waits for your answer
|
|
207
167
|
|
|
208
|
-
|
|
168
|
+
### Clients
|
|
209
169
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
### Authentication
|
|
170
|
+
| Client | Description |
|
|
171
|
+
|--------|-------------|
|
|
172
|
+
| Web Dashboard | React SPA at `http://localhost:7777` |
|
|
173
|
+
| TUI | Terminal interface built with Ink |
|
|
174
|
+
| Telegram | Bot integration via Grammy |
|
|
175
|
+
| REST API | HTTP endpoints at `/api/*` |
|
|
176
|
+
| WebSocket | Real-time streaming at `/ws` |
|
|
218
177
|
|
|
219
|
-
|
|
178
|
+
## Project Structure
|
|
220
179
|
|
|
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
180
|
```
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
├──
|
|
245
|
-
├──
|
|
246
|
-
|
|
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
|
|
181
|
+
packages/
|
|
182
|
+
├── shared/ # Types, constants, shared utilities
|
|
183
|
+
├── daemon/ # Core daemon (orchestrator, squads, API, scheduler)
|
|
184
|
+
├── web/ # Web dashboard (React + Vite + Tailwind)
|
|
185
|
+
├── tui/ # Terminal UI (Ink/React)
|
|
186
|
+
└── telegram/ # Telegram bot client
|
|
187
|
+
docs/ # Astro Starlight documentation site
|
|
188
|
+
.github/
|
|
189
|
+
└── workflows/
|
|
190
|
+
├── ci.yml # PR validation (lint, build, test)
|
|
191
|
+
├── release.yml # Tag-based release + npm publish
|
|
192
|
+
└── deploy-docs.yml # Docs site deployment
|
|
295
193
|
```
|
|
296
194
|
|
|
297
|
-
##
|
|
195
|
+
## Development
|
|
298
196
|
|
|
299
197
|
```bash
|
|
300
|
-
#
|
|
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
|
|
198
|
+
# Build all packages
|
|
311
199
|
npm run build
|
|
312
200
|
|
|
313
|
-
#
|
|
314
|
-
npm run
|
|
201
|
+
# Run daemon in dev mode (watches for changes)
|
|
202
|
+
npm run dev
|
|
315
203
|
|
|
316
|
-
# Run
|
|
317
|
-
npm run
|
|
204
|
+
# Run web dashboard dev server (with API proxy)
|
|
205
|
+
cd packages/web && npm run dev
|
|
318
206
|
|
|
319
|
-
#
|
|
320
|
-
npm
|
|
207
|
+
# Build documentation
|
|
208
|
+
cd docs && npm run build
|
|
321
209
|
```
|
|
322
210
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed development guidelines.
|
|
326
|
-
|
|
327
|
-
## 📄 License
|
|
211
|
+
## Documentation
|
|
328
212
|
|
|
329
|
-
|
|
213
|
+
Full documentation is available at **[michaeljolley.github.io/io](https://michaeljolley.github.io/io)**.
|
|
330
214
|
|
|
331
|
-
##
|
|
215
|
+
## License
|
|
332
216
|
|
|
333
|
-
|
|
217
|
+
MIT
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
|
+
import type { IOConfig } from '../../config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Express middleware that verifies Supabase JWT tokens.
|
|
5
|
+
* If Supabase is not configured (no jwtSecret), all requests pass through.
|
|
6
|
+
* Exempt routes always pass through regardless of config.
|
|
7
|
+
*/
|
|
8
|
+
export declare function authMiddleware(config: IOConfig): (req: Request, res: Response, next: NextFunction) => void;
|
|
9
|
+
/**
|
|
10
|
+
* Verify a JWT token for WebSocket connections.
|
|
11
|
+
* Returns true if valid or if auth is not configured.
|
|
12
|
+
*/
|
|
13
|
+
export declare function verifyWsToken(config: IOConfig, token: string | null): boolean;
|
|
14
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/api/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAehD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,IACtC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CA+B9D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAe7E"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import jwt from 'jsonwebtoken';
|
|
2
|
+
import { createChildLogger } from '../../logging/logger.js';
|
|
3
|
+
const logger = () => createChildLogger('auth');
|
|
4
|
+
// Routes that don't require authentication
|
|
5
|
+
const EXEMPT_ROUTES = [
|
|
6
|
+
{ method: 'GET', path: '/api/health' },
|
|
7
|
+
{ method: 'GET', path: '/api/config' },
|
|
8
|
+
];
|
|
9
|
+
function isExempt(method, path) {
|
|
10
|
+
return EXEMPT_ROUTES.some((r) => r.method === method.toUpperCase() && path.startsWith(r.path));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Express middleware that verifies Supabase JWT tokens.
|
|
14
|
+
* If Supabase is not configured (no jwtSecret), all requests pass through.
|
|
15
|
+
* Exempt routes always pass through regardless of config.
|
|
16
|
+
*/
|
|
17
|
+
export function authMiddleware(config) {
|
|
18
|
+
return (req, res, next) => {
|
|
19
|
+
// If no Supabase JWT secret configured, skip auth entirely (local-only mode)
|
|
20
|
+
if (!config.supabase.jwtSecret) {
|
|
21
|
+
next();
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// Exempt routes don't require auth
|
|
25
|
+
if (isExempt(req.method, req.path)) {
|
|
26
|
+
next();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const authHeader = req.headers.authorization;
|
|
30
|
+
if (!authHeader?.startsWith('Bearer ')) {
|
|
31
|
+
res.status(401).json({ error: 'Missing or invalid Authorization header' });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const token = authHeader.slice(7);
|
|
35
|
+
try {
|
|
36
|
+
jwt.verify(token, config.supabase.jwtSecret, {
|
|
37
|
+
algorithms: ['HS256'],
|
|
38
|
+
});
|
|
39
|
+
next();
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
logger().debug({ err }, 'JWT verification failed');
|
|
43
|
+
res.status(401).json({ error: 'Invalid or expired token' });
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Verify a JWT token for WebSocket connections.
|
|
49
|
+
* Returns true if valid or if auth is not configured.
|
|
50
|
+
*/
|
|
51
|
+
export function verifyWsToken(config, token) {
|
|
52
|
+
if (!config.supabase.jwtSecret) {
|
|
53
|
+
return true; // No auth configured — allow
|
|
54
|
+
}
|
|
55
|
+
if (!token) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
jwt.verify(token, config.supabase.jwtSecret, { algorithms: ['HS256'] });
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/api/middleware/auth.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,cAAc,CAAC;AAE/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE/C,2CAA2C;AAC3C,MAAM,aAAa,GAA4C;IAC9D,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE;IACtC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE;CACtC,CAAC;AAEF,SAAS,QAAQ,CAAC,MAAc,EAAE,IAAY;IAC7C,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAChG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAgB;IAC9C,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAQ,EAAE;QAChE,6EAA6E;QAC7E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YAChC,IAAI,EAAE,CAAC;YACP,OAAO;QACR,CAAC;QAED,mCAAmC;QACnC,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,IAAI,EAAE,CAAC;YACP,OAAO;QACR,CAAC;QAED,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QAC7C,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACxC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAC,CAAC;YAC3E,OAAO;QACR,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAElC,IAAI,CAAC;YACJ,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE;gBAC5C,UAAU,EAAE,CAAC,OAAO,CAAC;aACrB,CAAC,CAAC;YACH,IAAI,EAAE,CAAC;QACR,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,yBAAyB,CAAC,CAAC;YACnD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;QAC7D,CAAC;IACF,CAAC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAgB,EAAE,KAAoB;IACnE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,CAAC,6BAA6B;IAC3C,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACJ,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { WebSocket } from 'ws';
|
|
2
|
+
/**
|
|
3
|
+
* Register a WebSocket client for event notifications.
|
|
4
|
+
*/
|
|
5
|
+
export declare function subscribeClient(connectionId: string, ws: WebSocket): void;
|
|
6
|
+
/**
|
|
7
|
+
* Unregister a WebSocket client.
|
|
8
|
+
*/
|
|
9
|
+
export declare function unsubscribeClient(connectionId: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Initialize the notification system — subscribes to event bus and broadcasts to clients.
|
|
12
|
+
*/
|
|
13
|
+
export declare function initNotifications(): void;
|
|
14
|
+
//# sourceMappingURL=notifications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/api/notifications.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AASpC;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,GAAG,IAAI,CAEzE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAE5D;AA8DD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAkCxC"}
|