@fickydev/pigent 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.env.example +22 -0
  2. package/AGENTS.md +242 -0
  3. package/CHANGELOG.md +35 -0
  4. package/LICENSE +21 -0
  5. package/PLAN.md +369 -0
  6. package/README.md +369 -0
  7. package/TODO.md +183 -0
  8. package/agents/coder/SYSTEM.md +3 -0
  9. package/agents/coder/agent.yaml +20 -0
  10. package/drizzle/migrations/0000_great_daredevil.sql +78 -0
  11. package/drizzle/migrations/meta/0000_snapshot.json +505 -0
  12. package/drizzle/migrations/meta/_journal.json +13 -0
  13. package/drizzle.config.ts +13 -0
  14. package/package.json +66 -0
  15. package/pigent.yaml +12 -0
  16. package/profiles/software-engineer.yaml +11 -0
  17. package/src/agents/AgentRunner.ts +112 -0
  18. package/src/agents/BotCommandHandler.ts +65 -0
  19. package/src/agents/MessageRouter.ts +106 -0
  20. package/src/channels/telegram/TelegramApi.ts +67 -0
  21. package/src/channels/telegram/TelegramPollingAdapter.ts +123 -0
  22. package/src/channels/telegram/types.ts +50 -0
  23. package/src/channels/types.ts +29 -0
  24. package/src/cli/run.ts +77 -0
  25. package/src/cli/setup.ts +261 -0
  26. package/src/config/loadConfig.ts +115 -0
  27. package/src/config/schemas.ts +92 -0
  28. package/src/daemon/AgentDaemon.ts +161 -0
  29. package/src/db/client.ts +23 -0
  30. package/src/db/repositories/AgentRepository.ts +45 -0
  31. package/src/db/repositories/MessageRepository.ts +45 -0
  32. package/src/db/repositories/RuntimeKvRepository.ts +27 -0
  33. package/src/db/repositories/SessionRepository.ts +65 -0
  34. package/src/db/repositories/TelegramRepository.ts +98 -0
  35. package/src/db/repositories/index.ts +18 -0
  36. package/src/db/schema.ts +106 -0
  37. package/src/logging/logger.ts +45 -0
  38. package/src/main.ts +37 -0
  39. package/src/pi/PiAgentRunner.ts +73 -0
  40. package/tsconfig.json +17 -0
package/README.md ADDED
@@ -0,0 +1,369 @@
1
+ # Pigent
2
+
3
+ Pigent is an autonomous multi-agent daemon that uses Pi as its core execution engine. It routes messages from external channels, starting with Telegram, to Pi-backed agents with separate profiles, skills, extensions, permissions, heartbeat behavior, and per-chat sessions.
4
+
5
+ ## Status
6
+
7
+ Early MVP.
8
+
9
+ Current working slice:
10
+
11
+ ```text
12
+ Telegram polling -> MessageRouter -> fake AgentRunner -> SQLite persistence -> Telegram reply
13
+ ```
14
+
15
+ Pi SDK execution is now wired through `PiAgentRunner`. Fake responses can still be forced for transport/routing tests with `PIGENT_FAKE_AGENT=1`.
16
+
17
+ ## Stack
18
+
19
+ - Bun
20
+ - TypeScript
21
+ - Drizzle ORM
22
+ - SQLite now, PostgreSQL later
23
+ - Telegram polling first
24
+ - Pi SDK planned as execution core
25
+ - Hono deferred until webhooks/API are needed
26
+
27
+ ## Architecture
28
+
29
+ ```text
30
+ Channel Adapter -> Message Router -> Agent Orchestrator -> Pi Runner
31
+ -> State Store
32
+ -> Policy Engine
33
+ ```
34
+
35
+ Current modules:
36
+
37
+ ```text
38
+ src/
39
+ main.ts
40
+
41
+ daemon/
42
+ AgentDaemon.ts
43
+
44
+ pi/
45
+ PiAgentRunner.ts
46
+
47
+ channels/
48
+ types.ts
49
+ telegram/
50
+ TelegramApi.ts
51
+ TelegramPollingAdapter.ts
52
+ types.ts
53
+
54
+ agents/
55
+ AgentRunner.ts
56
+ BotCommandHandler.ts
57
+ MessageRouter.ts
58
+
59
+ config/
60
+ loadConfig.ts
61
+ schemas.ts
62
+
63
+ db/
64
+ client.ts
65
+ schema.ts
66
+ repositories/
67
+
68
+ logging/
69
+ logger.ts
70
+ ```
71
+
72
+ ## Setup And Run
73
+
74
+ From a published package, one command can create a project, run setup, and start the daemon:
75
+
76
+ ```bash
77
+ bunx @fickydev/pigent my-pigent
78
+ ```
79
+
80
+ From a checked-out repo, one command handles setup when needed, then starts the daemon:
81
+
82
+ ```bash
83
+ bun run run
84
+ ```
85
+
86
+ Reconfigure anytime:
87
+
88
+ ```bash
89
+ bun run run -- --setup
90
+ # or, with bunx after publish:
91
+ bunx @fickydev/pigent my-pigent --setup
92
+ ```
93
+
94
+ Skip slow setup steps when needed:
95
+
96
+ ```bash
97
+ bun run run -- --skip-install --skip-migrate --skip-typecheck
98
+ ```
99
+
100
+ The setup flow will:
101
+
102
+ - ask for quick or custom mode
103
+ - create `.env` from `.env.example` if missing
104
+ - configure `DATABASE_URL`
105
+ - optionally write or replace `TELEGRAM_BOT_TOKEN`
106
+ - optionally enable automatic Telegram chat setup
107
+ - optionally configure Telegram chat routing in `pigent.yaml`
108
+ - optionally configure log level and Telegram polling values in custom mode
109
+ - optionally install dependencies
110
+ - optionally apply database migrations
111
+ - optionally run typecheck
112
+
113
+ Manual setup:
114
+
115
+ ```bash
116
+ bun install
117
+ cp .env.example .env
118
+ bun run db:migrate
119
+ bun run typecheck
120
+ ```
121
+
122
+ Configure `.env`:
123
+
124
+ ```env
125
+ DATABASE_URL=file:./pigent.db
126
+ TELEGRAM_BOT_TOKEN=
127
+ PIGENT_WORKSPACE_ROOT=~/.pigent
128
+ PIGENT_FAKE_AGENT=0
129
+ PIGENT_FALLBACK_FAKE_AGENT=1
130
+ PIGENT_AUTO_SETUP_CHATS=0
131
+ PIGENT_AUTO_SETUP_DEFAULT_AGENT=coder
132
+ ```
133
+
134
+ Start daemon directly after setup:
135
+
136
+ ```bash
137
+ bun run start
138
+ ```
139
+
140
+ Development watch mode:
141
+
142
+ ```bash
143
+ bun run dev
144
+ ```
145
+
146
+ Typecheck:
147
+
148
+ ```bash
149
+ bun run typecheck
150
+ ```
151
+
152
+ ## Telegram Testing
153
+
154
+ ### 1. Create bot
155
+
156
+ Use Telegram `@BotFather`:
157
+
158
+ ```text
159
+ /newbot
160
+ ```
161
+
162
+ Copy token into `.env`:
163
+
164
+ ```env
165
+ TELEGRAM_BOT_TOKEN=123456:abc...
166
+ ```
167
+
168
+ ### 2. Discover chat id
169
+
170
+ Run daemon:
171
+
172
+ ```bash
173
+ bun run start
174
+ ```
175
+
176
+ Message bot in private chat or add bot to a group and send `/help`.
177
+
178
+ Logs will include:
179
+
180
+ ```json
181
+ {"message":"inbound message received","chatId":"123456"}
182
+ ```
183
+
184
+ Group chat ids usually look like:
185
+
186
+ ```text
187
+ -1001234567890
188
+ ```
189
+
190
+ ### 3. Configure chat
191
+
192
+ Edit `pigent.yaml`:
193
+
194
+ ```yaml
195
+ telegramChats:
196
+ - chatId: "123456"
197
+ title: Ficky Private Chat
198
+ defaultAgent: coder
199
+ allowedAgents:
200
+ - coder
201
+ instructions: |
202
+ Be concise.
203
+ ```
204
+
205
+ Restart daemon after editing config.
206
+
207
+ ### 4. Test commands
208
+
209
+ In Telegram:
210
+
211
+ ```text
212
+ /help
213
+ ```
214
+
215
+ ```text
216
+ /agents
217
+ ```
218
+
219
+ ```text
220
+ hello
221
+ ```
222
+
223
+ ```text
224
+ @coder review this
225
+ ```
226
+
227
+ ```text
228
+ /agent coder write a test
229
+ ```
230
+
231
+ With `PIGENT_FAKE_AGENT=1`, expected fake runner response:
232
+
233
+ ```text
234
+ [Code Agent] fake runner received: hello
235
+ ```
236
+
237
+ With `PIGENT_FAKE_AGENT=0`, Pigent calls the Pi SDK and returns the Pi assistant response.
238
+
239
+ ## Agent Config
240
+
241
+ Example agent lives at:
242
+
243
+ ```text
244
+ agents/coder/agent.yaml
245
+ agents/coder/SYSTEM.md
246
+ ```
247
+
248
+ Example profile:
249
+
250
+ ```text
251
+ profiles/software-engineer.yaml
252
+ ```
253
+
254
+ Agent config shape:
255
+
256
+ ```yaml
257
+ id: coder
258
+ name: Code Agent
259
+ profile: software-engineer
260
+ workspace: ~/.pigent/workspaces/coder
261
+ systemPromptFile: ./SYSTEM.md
262
+ skills: []
263
+ extensions: []
264
+ channels:
265
+ telegram:
266
+ enabled: false
267
+ heartbeat:
268
+ enabled: false
269
+ intervalMs: 600000
270
+ prompt: |
271
+ Check assigned tasks. If no useful action is needed, reply exactly: NOOP.
272
+ permissions:
273
+ canRunShell: false
274
+ canEditFiles: false
275
+ allowedPaths: []
276
+ blockedTools: []
277
+ ```
278
+
279
+ ## Automatic Chat Setup
280
+
281
+ For easier Telegram testing, Pigent can auto-create DB routing for new Telegram chats.
282
+
283
+ Enable in `.env`:
284
+
285
+ ```env
286
+ PIGENT_AUTO_SETUP_CHATS=1
287
+ PIGENT_AUTO_SETUP_DEFAULT_AGENT=coder
288
+ ```
289
+
290
+ When a new Telegram chat sends any message Pigent receives, the daemon inserts a chat config into SQLite with:
291
+
292
+ - `defaultAgent: coder`
293
+ - `allowedAgents: [coder]`
294
+ - `enabled: true`
295
+
296
+ This does not write to `pigent.yaml`; it creates runtime DB config only. Keep it off for stricter production setups.
297
+
298
+ ## Routing
299
+
300
+ One Telegram bot can serve many agents.
301
+
302
+ Routing priority:
303
+
304
+ 1. `@agentId <message>`
305
+ 2. `/agent <agentId> <message>`
306
+ 3. chat default agent
307
+ 4. no-route error
308
+
309
+ Session key:
310
+
311
+ ```text
312
+ agentId + channel + chatId + threadId
313
+ ```
314
+
315
+ ## Database
316
+
317
+ Drizzle schema currently includes:
318
+
319
+ - `agents`
320
+ - `agent_sessions`
321
+ - `telegram_chats`
322
+ - `telegram_chat_agents`
323
+ - `messages`
324
+ - `heartbeats`
325
+ - `runtime_kv`
326
+
327
+ SQLite database path is controlled by:
328
+
329
+ ```env
330
+ DATABASE_URL=file:./pigent.db
331
+ ```
332
+
333
+ ## Commands
334
+
335
+ Available Telegram commands:
336
+
337
+ ```text
338
+ /help
339
+ /start
340
+ /agents
341
+ /agent <agentId> <message>
342
+ ```
343
+
344
+ Planned commands:
345
+
346
+ ```text
347
+ /default-agent <agentId>
348
+ /instructions <text>
349
+ /sessions
350
+ /reset-session <agentId>
351
+ /heartbeat status
352
+ ```
353
+
354
+ ## Development Notes
355
+
356
+ - Do not add Hono until webhook/API needs exist.
357
+ - Keep Telegram-specific logic inside `src/channels/telegram` or routing config.
358
+ - Channel adapters must not call Pi directly.
359
+ - Pi runner must not know channel secrets.
360
+ - Use repositories for database access.
361
+ - Keep SQLite/PostgreSQL portability in mind.
362
+ - Never inject secrets or raw `.env` values into model prompts.
363
+
364
+ See also:
365
+
366
+ - `PLAN.md` — architecture and milestones
367
+ - `TODO.md` — task checklist
368
+ - `AGENTS.md` — coding rules and project instructions
369
+ - `CHANGELOG.md` — project changes
package/TODO.md ADDED
@@ -0,0 +1,183 @@
1
+ # Pigent TODO
2
+
3
+ ## Now
4
+
5
+ - [x] Add `bunx @fickydev/pigent <dir>` scaffold/setup/run command
6
+ - [x] Add one-command setup-and-run CLI
7
+ - [x] Add interactive setup CLI
8
+ - [x] Add quick/custom setup modes
9
+ - [x] Create `README.md`
10
+ - [x] Initialize Bun TypeScript project
11
+ - [x] Add npm publish metadata
12
+ - [x] Add package metadata
13
+ - [x] Add `tsconfig.json`
14
+ - [x] Set default workspace to `~/.pigent`
15
+ - [x] Add `.env.example`
16
+ - [x] Add `.gitignore`
17
+ - [x] Add basic `src/main.ts`
18
+ - [x] Add graceful shutdown handling
19
+
20
+ ## Dependencies
21
+
22
+ - [x] Add runtime dependencies
23
+ - [x] `drizzle-orm`
24
+ - [x] `zod`
25
+ - [x] `yaml`
26
+ - [x] `nanoid`
27
+ - [x] Pi SDK package
28
+ - [x] Add dev dependencies
29
+ - [x] `drizzle-kit`
30
+ - [x] `@types/bun`
31
+ - [x] Pick SQLite driver compatible with Bun and Drizzle
32
+ - [ ] Document PostgreSQL migration path
33
+
34
+ ## Config
35
+
36
+ - [x] Define root config format
37
+ - [x] Define `AgentConfig`
38
+ - [x] Define `ProfileConfig`
39
+ - [x] Define `TelegramChatConfig`
40
+ - [x] Add Zod schemas
41
+ - [x] Implement config loader
42
+ - [x] Load configs from `agents/*/agent.yaml`
43
+ - [x] Load profiles from `profiles/*.yaml`
44
+ - [x] Add example `agents/coder/agent.yaml`
45
+ - [x] Add example `agents/coder/SYSTEM.md`
46
+ - [x] Add example `profiles/software-engineer.yaml`
47
+
48
+ ## Database
49
+
50
+ - [x] Create `src/db/schema.ts`
51
+ - [x] Create `src/db/client.ts`
52
+ - [x] Configure Drizzle Kit
53
+ - [x] Add SQLite database path env var
54
+ - [x] Create migrations folder
55
+ - [x] Define `agents` table
56
+ - [x] Define `agent_sessions` table
57
+ - [x] Define `telegram_chats` table
58
+ - [x] Define `telegram_chat_agents` table
59
+ - [x] Define `messages` table
60
+ - [x] Define `heartbeats` table
61
+ - [x] Define `runtime_kv` table for offsets and daemon state
62
+ - [ ] Implement repositories
63
+ - [x] `AgentRepository`
64
+ - [x] `SessionRepository`
65
+ - [x] `MessageRepository`
66
+ - [x] `TelegramRepository`
67
+ - [ ] `HeartbeatRepository`
68
+
69
+ ## Channel Layer
70
+
71
+ - [x] Define `InboundMessage`
72
+ - [x] Define `OutboundMessage`
73
+ - [x] Define `ChannelAdapter`
74
+ - [x] Define Telegram normalized types
75
+ - [ ] Implement `TelegramApi`
76
+ - [x] `getUpdates`
77
+ - [x] `sendMessage`
78
+ - [x] error handling
79
+ - [ ] retry/backoff
80
+ - [x] Implement `TelegramPollingAdapter`
81
+ - [x] polling loop
82
+ - [x] offset tracking
83
+ - [x] graceful stop
84
+ - [x] update normalization
85
+ - [x] Persist Telegram offset in DB
86
+
87
+ ## Routing
88
+
89
+ - [x] Implement `MessageRouter`
90
+ - [x] Route by explicit `@agentId`
91
+ - [x] Route by `/agent <agentId>` command
92
+ - [x] Route to chat default agent
93
+ - [x] Enforce allowed agents per chat
94
+ - [x] Auto-configure new Telegram chats when enabled
95
+ - [x] Ignore bot's own messages
96
+ - [x] Ignore unsupported message types initially
97
+ - [x] Add helpful error reply for unknown agent
98
+ - [x] Add helpful error reply for disallowed agent
99
+
100
+ ## Agent Runtime
101
+
102
+ - [ ] Implement `AgentRegistry`
103
+ - [x] Implement `AgentDaemon`
104
+ - [x] Implement `AgentRunner`
105
+ - [ ] Implement `PiSessionFactory`
106
+ - [x] Implement `PiAgentRunner`
107
+ - [x] Create/get session by `agentId + channel + chatId + threadId`
108
+ - [ ] Compose prompt with chat instructions
109
+ - [x] Compose basic channel/chat/user prompt for Pi runner
110
+ - [x] Persist inbound message before Pi run
111
+ - [x] Persist outbound response after Pi run
112
+ - [ ] Handle Pi errors and send safe error reply
113
+ - [ ] Add per-session lock to prevent concurrent Pi runs
114
+
115
+ ## Pi Integration
116
+
117
+ - [x] Confirm SDK APIs needed for session creation
118
+ - [ ] Confirm persistent session manager approach
119
+ - [ ] Confirm per-agent system prompt injection
120
+ - [ ] Confirm per-agent skills loading
121
+ - [ ] Confirm per-agent extensions loading
122
+ - [x] Prototype one prompt through Pi SDK
123
+ - [x] Decide CLI fallback strategy if SDK gaps appear
124
+
125
+ ## Heartbeat
126
+
127
+ - [ ] Define heartbeat config
128
+ - [ ] Implement scheduler
129
+ - [ ] Add per-agent heartbeat lock
130
+ - [ ] Add heartbeat prompt composition
131
+ - [ ] Add `NOOP` handling
132
+ - [ ] Persist heartbeat start/result/failure
133
+ - [ ] Add notification cooldown
134
+ - [ ] Add max heartbeat messages per hour
135
+ - [ ] Send heartbeat output to configured channel only when useful
136
+
137
+ ## Policy And Safety
138
+
139
+ - [ ] Define permission config
140
+ - [ ] Implement `PolicyEngine`
141
+ - [ ] Add default deny for dangerous tools/actions
142
+ - [ ] Add allowed path checks
143
+ - [ ] Add blocked path checks
144
+ - [ ] Add shell command policy design
145
+ - [ ] Add approval workflow design
146
+ - [ ] Prevent secrets from being injected into prompts
147
+ - [ ] Add audit log for risky actions
148
+
149
+ ## Commands UX
150
+
151
+ - [x] `/agents` list agents available in chat
152
+ - [ ] `/agent <id> <message>` route message
153
+ - [ ] `/default-agent <id>` set chat default
154
+ - [ ] `/instructions <text>` set chat instructions
155
+ - [ ] `/sessions` list active sessions for chat
156
+ - [ ] `/reset-session <agentId>` clear chat session
157
+ - [ ] `/heartbeat status` show heartbeat state
158
+ - [x] `/help` show bot commands
159
+
160
+ ## Tests
161
+
162
+ - [ ] Unit test config validation
163
+ - [ ] Unit test Telegram update normalization
164
+ - [ ] Unit test routing rules
165
+ - [ ] Unit test session key generation
166
+ - [ ] Unit test heartbeat `NOOP` behavior
167
+ - [ ] Repository tests against temp SQLite DB
168
+ - [ ] Integration test fake Telegram update to fake Pi runner
169
+
170
+ ## Later
171
+
172
+ - [ ] Add Hono HTTP server
173
+ - [ ] Add Telegram webhook transport
174
+ - [ ] Add Slack adapter
175
+ - [ ] Add WhatsApp Cloud API adapter
176
+ - [ ] Add admin API
177
+ - [ ] Add dashboard
178
+ - [ ] Add PostgreSQL client/schema variant
179
+ - [ ] Add multi-agent delegation
180
+ - [ ] Add dynamic agent creation with approval
181
+ - [ ] Publish npm package for `bunx @fickydev/pigent`
182
+ - [ ] Add package install support for Pi skills/extensions
183
+ - [ ] Add semantic memory
@@ -0,0 +1,3 @@
1
+ You are coder agent.
2
+
3
+ Focus on implementation, debugging, and code review. Keep responses concise. Ask before risky changes.
@@ -0,0 +1,20 @@
1
+ id: coder
2
+ name: Code Agent
3
+ profile: software-engineer
4
+ workspace: ~/.pigent/workspaces/coder
5
+ systemPromptFile: ./SYSTEM.md
6
+ skills: []
7
+ extensions: []
8
+ channels:
9
+ telegram:
10
+ enabled: false
11
+ heartbeat:
12
+ enabled: false
13
+ intervalMs: 600000
14
+ prompt: |
15
+ Check assigned tasks. If no useful action is needed, reply exactly: NOOP.
16
+ permissions:
17
+ canRunShell: false
18
+ canEditFiles: false
19
+ allowedPaths: []
20
+ blockedTools: []
@@ -0,0 +1,78 @@
1
+ CREATE TABLE `agent_sessions` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `agent_id` text NOT NULL,
4
+ `channel` text NOT NULL,
5
+ `chat_id` text NOT NULL,
6
+ `thread_id` text,
7
+ `user_id` text,
8
+ `pi_session_id` text,
9
+ `instructions_hash` text,
10
+ `created_at` integer NOT NULL,
11
+ `updated_at` integer NOT NULL
12
+ );
13
+ --> statement-breakpoint
14
+ CREATE UNIQUE INDEX `agent_sessions_key_unique` ON `agent_sessions` (`agent_id`,`channel`,`chat_id`,`thread_id`);--> statement-breakpoint
15
+ CREATE TABLE `agents` (
16
+ `id` text PRIMARY KEY NOT NULL,
17
+ `name` text NOT NULL,
18
+ `profile` text NOT NULL,
19
+ `workspace` text NOT NULL,
20
+ `config_json` text NOT NULL,
21
+ `system_prompt` text DEFAULT '' NOT NULL,
22
+ `created_at` integer NOT NULL,
23
+ `updated_at` integer NOT NULL
24
+ );
25
+ --> statement-breakpoint
26
+ CREATE TABLE `heartbeats` (
27
+ `id` text PRIMARY KEY NOT NULL,
28
+ `agent_id` text NOT NULL,
29
+ `session_id` text,
30
+ `status` text NOT NULL,
31
+ `prompt` text NOT NULL,
32
+ `result` text,
33
+ `error` text,
34
+ `started_at` integer,
35
+ `finished_at` integer,
36
+ `created_at` integer NOT NULL
37
+ );
38
+ --> statement-breakpoint
39
+ CREATE TABLE `messages` (
40
+ `id` text PRIMARY KEY NOT NULL,
41
+ `agent_id` text NOT NULL,
42
+ `session_id` text,
43
+ `channel` text NOT NULL,
44
+ `direction` text NOT NULL,
45
+ `sender_id` text,
46
+ `chat_id` text,
47
+ `thread_id` text,
48
+ `content` text NOT NULL,
49
+ `raw_json` text,
50
+ `created_at` integer NOT NULL
51
+ );
52
+ --> statement-breakpoint
53
+ CREATE TABLE `runtime_kv` (
54
+ `key` text PRIMARY KEY NOT NULL,
55
+ `value` text NOT NULL,
56
+ `updated_at` integer NOT NULL
57
+ );
58
+ --> statement-breakpoint
59
+ CREATE TABLE `telegram_chat_agents` (
60
+ `id` text PRIMARY KEY NOT NULL,
61
+ `chat_id` text NOT NULL,
62
+ `agent_id` text NOT NULL,
63
+ `enabled` integer DEFAULT true NOT NULL,
64
+ `custom_instructions` text DEFAULT '' NOT NULL,
65
+ `created_at` integer NOT NULL,
66
+ `updated_at` integer NOT NULL
67
+ );
68
+ --> statement-breakpoint
69
+ CREATE UNIQUE INDEX `telegram_chat_agents_chat_agent_unique` ON `telegram_chat_agents` (`chat_id`,`agent_id`);--> statement-breakpoint
70
+ CREATE TABLE `telegram_chats` (
71
+ `chat_id` text PRIMARY KEY NOT NULL,
72
+ `title` text,
73
+ `default_agent_id` text,
74
+ `instructions` text DEFAULT '' NOT NULL,
75
+ `enabled` integer DEFAULT true NOT NULL,
76
+ `created_at` integer NOT NULL,
77
+ `updated_at` integer NOT NULL
78
+ );