heyio 0.42.1 → 1.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 +40 -52
- package/dist/api/auth.js +35 -38
- package/dist/api/server.js +157 -1134
- package/dist/config.js +49 -32
- package/dist/copilot/agents.js +72 -1055
- package/dist/copilot/client.js +6 -17
- package/dist/copilot/io-scheduler.js +55 -139
- package/dist/copilot/model-router.js +100 -72
- package/dist/copilot/orchestrator.js +91 -515
- package/dist/copilot/scheduler.js +67 -189
- package/dist/copilot/skills.js +41 -366
- package/dist/copilot/system-message.js +40 -200
- package/dist/copilot/tools.js +191 -2042
- package/dist/daemon.js +54 -201
- package/dist/index.js +15 -133
- package/dist/mcp/config.js +23 -31
- package/dist/mcp/index.js +2 -3
- package/dist/mcp/registry.js +33 -88
- package/dist/notify.js +18 -100
- package/dist/paths.js +13 -24
- package/dist/setup.js +35 -0
- package/dist/store/db.js +111 -297
- package/dist/store/feed.js +29 -97
- package/dist/store/instances.js +56 -121
- package/dist/store/schedules.js +21 -73
- package/dist/store/squads.js +35 -186
- package/dist/store/tasks.js +25 -168
- package/dist/telegram/bot.js +20 -312
- package/dist/telegram/handlers.js +39 -3
- package/dist/watchdog.js +31 -45
- package/dist/wiki/fs.js +38 -155
- package/dist/wiki/search.js +31 -44
- package/package.json +5 -8
- package/web-dist/assets/ChatView-EFFiln1H.js +11 -0
- package/web-dist/assets/FeedView-bN4NMOL7.js +6 -0
- package/web-dist/assets/LoginView-CNtasq3n.js +1 -0
- package/web-dist/assets/McpView-C2CHiwsi.js +1 -0
- package/web-dist/assets/SchedulesView-CyilLban.js +1 -0
- package/web-dist/assets/SettingsView-1wLXKEF4.js +1 -0
- package/web-dist/assets/SkillsView-BLsD-0u0.js +1 -0
- package/web-dist/assets/SquadDetailView-CsCw2ZLp.js +21 -0
- package/web-dist/assets/SquadsView-DQ3vFlyO.js +6 -0
- package/web-dist/assets/WikiView-19M3oqnq.js +21 -0
- package/web-dist/assets/api-WGvTsXaE.js +1 -0
- package/web-dist/assets/index-D7M5O-_l.css +1 -0
- package/web-dist/assets/index-DZOS9syn.js +95 -0
- package/web-dist/assets/plus-BOvyX1BC.js +6 -0
- package/web-dist/assets/trash-2-DHoetkC4.js +6 -0
- package/web-dist/favicon.svg +4 -1
- package/web-dist/index.html +7 -10
- package/dist/api/logout.test.js +0 -128
- package/dist/api/mcp.test.js +0 -285
- package/dist/api/wiki.test.js +0 -283
- package/dist/auth/session-logic.js +0 -79
- package/dist/auth/session-logic.test.js +0 -201
- package/dist/copilot/auto-complete-instance.test.js +0 -104
- package/dist/copilot/cron.js +0 -136
- package/dist/copilot/event-summary.js +0 -286
- package/dist/copilot/instance-deactivate.test.js +0 -119
- package/dist/copilot/model-router.test.js +0 -71
- package/dist/copilot/review-backfill.js +0 -57
- package/dist/copilot/session-timeout.js +0 -112
- package/dist/copilot/session-timeout.test.js +0 -372
- package/dist/copilot/skills.test.js +0 -55
- package/dist/copilot/universes.js +0 -469
- package/dist/instance-watchdog.js +0 -104
- package/dist/instance-watchdog.test.js +0 -183
- package/dist/mcp/client.js +0 -109
- package/dist/mcp/client.test.js +0 -99
- package/dist/mcp/config.test.js +0 -49
- package/dist/mcp/registry.test.js +0 -79
- package/dist/notify.test.js +0 -232
- package/dist/store/feed.test.js +0 -279
- package/dist/store/instances.test.js +0 -310
- package/dist/store/io-schedules.js +0 -63
- package/dist/store/notifications.js +0 -79
- package/dist/store/notifications.test.js +0 -197
- package/dist/store/schedule-runs.js +0 -46
- package/dist/store/squads.test.js +0 -405
- package/dist/store/tasks.test.js +0 -150
- package/dist/store/worktrees.js +0 -83
- package/dist/tui/index.js +0 -286
- package/dist/update.js +0 -81
- package/dist/watchdog.test.js +0 -83
- package/dist/wiki/wiki-squad.test.js +0 -54
- package/web-dist/assets/AgentActivityView-B1PaNYy8.js +0 -1
- package/web-dist/assets/ChatView-BbpWnrtC.js +0 -4
- package/web-dist/assets/FeedView-B5LaMV0I.js +0 -1
- package/web-dist/assets/InboxView-Cwqt8rH7.js +0 -1
- package/web-dist/assets/LoginView-refmPLKT.js +0 -1
- package/web-dist/assets/McpView-B1w0dRFY.js +0 -1
- package/web-dist/assets/SchedulesView-D9l2DI7X.js +0 -1
- package/web-dist/assets/SettingsTabs.vue_vue_type_script_setup_true_lang-DncOVVEB.js +0 -1
- package/web-dist/assets/SkillsView-uFX0q1mV.js +0 -1
- package/web-dist/assets/SquadsView-B1nZW4ml.js +0 -1
- package/web-dist/assets/StatusIndicator.vue_vue_type_script_setup_true_lang-pTrJJwX1.js +0 -1
- package/web-dist/assets/WikiView-B54cCKIK.js +0 -1
- package/web-dist/assets/index-C0VEUWQ1.js +0 -81
- package/web-dist/assets/index-eluTyieM.css +0 -10
- 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
|
|
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
|
[](https://github.com/michaeljolley/io/actions/workflows/ci.yml)
|
|
6
6
|

|
|
@@ -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
|
|
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
|
|
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
|
-
#
|
|
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` |
|
|
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
|
-
|
|
104
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
183
|
-
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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
|
-
├──
|
|
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
|
-
│
|
|
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
|
-
├──
|
|
292
|
-
│
|
|
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,
|
|
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
|
-
#
|
|
325
|
-
npm run
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|