@fickydev/pigent 0.1.1 → 0.1.2

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/.env.example CHANGED
@@ -17,6 +17,6 @@ PIGENT_FAKE_AGENT=0
17
17
  # Set to 1 to use fake responses if Pi SDK execution fails.
18
18
  PIGENT_FALLBACK_FAKE_AGENT=1
19
19
  # Set to 1 to auto-create DB chat routing for new Telegram chats.
20
- PIGENT_AUTO_SETUP_CHATS=0
20
+ PIGENT_AUTO_SETUP_CHATS=1
21
21
  # Agent used when auto-creating chat routing. Defaults to first loaded agent.
22
- PIGENT_AUTO_SETUP_DEFAULT_AGENT=coder
22
+ PIGENT_AUTO_SETUP_DEFAULT_AGENT=assistant
package/CHANGELOG.md CHANGED
@@ -12,7 +12,7 @@
12
12
  - Added project planning docs: `PLAN.md`, `TODO.md`, and `AGENTS.md`.
13
13
  - Added Bun TypeScript project skeleton with startup/shutdown flow.
14
14
  - Added config schemas and filesystem config loader.
15
- - Added example coder agent and software engineer profile.
15
+ - Added example generic assistant agent and profile.
16
16
  - Added Drizzle SQLite schema, migration config, and repositories.
17
17
  - Added channel abstraction and Telegram polling adapter skeleton.
18
18
  - Added Telegram Bot API wrapper for `getUpdates` and `sendMessage`.
@@ -27,8 +27,14 @@
27
27
  - Added optional automatic Telegram chat setup via `PIGENT_AUTO_SETUP_CHATS`.
28
28
  - Set default workspace root to `~/.pigent` and added tilde expansion for agent workspaces.
29
29
  - Added npm package metadata and MIT license for publishing.
30
+ - Added automatic user service install/start flow for `bunx @fickydev/pigent`.
31
+ - Added `pigent update` to back up the app, refresh shipped files from the latest package, preserve user config/state, and restart the service.
32
+ - Changed default agent to generic `Assistant` and enabled automatic chat setup by default.
33
+ - Renamed default agent/profile files to `agents/assistant` and `profiles/assistant.yaml`.
34
+ - Added short `pigent` command shim for `status`, `logs`, `start`, `stop`, `restart`, `update`, and `setup`.
30
35
  - Simplified published CLI flow so `bunx @fickydev/pigent` runs setup and starts Pigent without install/start/typecheck prompts.
31
36
  - Added automatic database migrations at daemon startup.
37
+ - Kept daemon process alive after startup so CLI runs do not exit after `pigent ready`.
32
38
 
33
39
  ### Changed
34
40
 
package/README.md CHANGED
@@ -71,24 +71,48 @@ src/
71
71
 
72
72
  ## Setup And Run
73
73
 
74
- From a published package, one command creates a project if needed, runs lightweight setup, applies migrations automatically, and starts the daemon:
74
+ Install and start Pigent as a user service:
75
75
 
76
76
  ```bash
77
- bunx @fickydev/pigent my-pigent
77
+ bunx @fickydev/pigent
78
78
  ```
79
79
 
80
- From a checked-out repo, one command handles setup when needed, then starts the daemon:
80
+ Default app directory:
81
+
82
+ ```text
83
+ ~/.pigent/app
84
+ ```
85
+
86
+ After install, use short commands:
81
87
 
82
88
  ```bash
83
- bun run run
89
+ pigent status
90
+ pigent logs
91
+ pigent stop
92
+ pigent start
93
+ pigent restart
94
+ pigent update
95
+ pigent setup
96
+ ```
97
+
98
+ Update to latest package:
99
+
100
+ ```bash
101
+ pigent update
102
+ ```
103
+
104
+ `pigent update` backs up the app, preserves `.env`, SQLite DB, `pigent.yaml`, `agents/`, and `profiles/`, refreshes shipped files, and restarts the service.
105
+
106
+ Run in foreground instead of installing a service:
107
+
108
+ ```bash
109
+ bunx @fickydev/pigent run
84
110
  ```
85
111
 
86
- Reconfigure anytime:
112
+ From a checked-out repo:
87
113
 
88
114
  ```bash
89
- bun run run -- --setup
90
- # or, with bunx after publish:
91
- bunx @fickydev/pigent my-pigent --setup
115
+ bun run run
92
116
  ```
93
117
 
94
118
  The setup flow will:
@@ -119,8 +143,8 @@ TELEGRAM_BOT_TOKEN=
119
143
  PIGENT_WORKSPACE_ROOT=~/.pigent
120
144
  PIGENT_FAKE_AGENT=0
121
145
  PIGENT_FALLBACK_FAKE_AGENT=1
122
- PIGENT_AUTO_SETUP_CHATS=0
123
- PIGENT_AUTO_SETUP_DEFAULT_AGENT=coder
146
+ PIGENT_AUTO_SETUP_CHATS=1
147
+ PIGENT_AUTO_SETUP_DEFAULT_AGENT=assistant
124
148
  ```
125
149
 
126
150
  Start daemon directly after setup:
@@ -187,9 +211,9 @@ Edit `pigent.yaml`:
187
211
  telegramChats:
188
212
  - chatId: "123456"
189
213
  title: Ficky Private Chat
190
- defaultAgent: coder
214
+ defaultAgent: assistant
191
215
  allowedAgents:
192
- - coder
216
+ - assistant
193
217
  instructions: |
194
218
  Be concise.
195
219
  ```
@@ -213,17 +237,17 @@ hello
213
237
  ```
214
238
 
215
239
  ```text
216
- @coder review this
240
+ @assistant review this
217
241
  ```
218
242
 
219
243
  ```text
220
- /agent coder write a test
244
+ /agent assistant write a test
221
245
  ```
222
246
 
223
247
  With `PIGENT_FAKE_AGENT=1`, expected fake runner response:
224
248
 
225
249
  ```text
226
- [Code Agent] fake runner received: hello
250
+ [Assistant] fake runner received: hello
227
251
  ```
228
252
 
229
253
  With `PIGENT_FAKE_AGENT=0`, Pigent calls the Pi SDK and returns the Pi assistant response.
@@ -233,23 +257,23 @@ With `PIGENT_FAKE_AGENT=0`, Pigent calls the Pi SDK and returns the Pi assistant
233
257
  Example agent lives at:
234
258
 
235
259
  ```text
236
- agents/coder/agent.yaml
237
- agents/coder/SYSTEM.md
260
+ agents/assistant/agent.yaml
261
+ agents/assistant/SYSTEM.md
238
262
  ```
239
263
 
240
264
  Example profile:
241
265
 
242
266
  ```text
243
- profiles/software-engineer.yaml
267
+ profiles/assistant.yaml
244
268
  ```
245
269
 
246
270
  Agent config shape:
247
271
 
248
272
  ```yaml
249
- id: coder
250
- name: Code Agent
251
- profile: software-engineer
252
- workspace: ~/.pigent/workspaces/coder
273
+ id: assistant
274
+ name: Assistant
275
+ profile: generic-assistant
276
+ workspace: ~/.pigent/workspaces/assistant
253
277
  systemPromptFile: ./SYSTEM.md
254
278
  skills: []
255
279
  extensions: []
@@ -276,13 +300,13 @@ Enable in `.env`:
276
300
 
277
301
  ```env
278
302
  PIGENT_AUTO_SETUP_CHATS=1
279
- PIGENT_AUTO_SETUP_DEFAULT_AGENT=coder
303
+ PIGENT_AUTO_SETUP_DEFAULT_AGENT=assistant
280
304
  ```
281
305
 
282
306
  When a new Telegram chat sends any message Pigent receives, the daemon inserts a chat config into SQLite with:
283
307
 
284
- - `defaultAgent: coder`
285
- - `allowedAgents: [coder]`
308
+ - `defaultAgent: assistant`
309
+ - `allowedAgents: [assistant]`
286
310
  - `enabled: true`
287
311
 
288
312
  This does not write to `pigent.yaml`; it creates runtime DB config only. Keep it off for stricter production setups.
package/TODO.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  ## Now
4
4
 
5
+ - [x] Add `pigent update` command
6
+ - [x] Add user service install/start/status/logs CLI
7
+ - [x] Add `pigent` command shim
5
8
  - [x] Remove install/migrate/typecheck prompts from published run flow
6
9
  - [x] Add automatic startup migrations
7
10
  - [x] Add `bunx @fickydev/pigent <dir>` scaffold/setup/run command
@@ -17,6 +20,7 @@
17
20
  - [x] Add `.env.example`
18
21
  - [x] Add `.gitignore`
19
22
  - [x] Add basic `src/main.ts`
23
+ - [x] Keep daemon alive after startup
20
24
  - [x] Add graceful shutdown handling
21
25
 
22
26
  ## Dependencies
@@ -43,9 +47,10 @@
43
47
  - [x] Implement config loader
44
48
  - [x] Load configs from `agents/*/agent.yaml`
45
49
  - [x] Load profiles from `profiles/*.yaml`
46
- - [x] Add example `agents/coder/agent.yaml`
47
- - [x] Add example `agents/coder/SYSTEM.md`
48
- - [x] Add example `profiles/software-engineer.yaml`
50
+ - [x] Rename default agent/profile files to assistant
51
+ - [x] Add example generic assistant agent config
52
+ - [x] Add example generic assistant system prompt
53
+ - [x] Add example generic assistant profile
49
54
 
50
55
  ## Database
51
56
 
@@ -0,0 +1,3 @@
1
+ You are Assistant, a helpful general-purpose agent.
2
+
3
+ Be concise, practical, and friendly. Help with questions, planning, writing, debugging, and everyday tasks. Ask before risky or destructive actions.
@@ -1,7 +1,7 @@
1
- id: coder
2
- name: Code Agent
3
- profile: software-engineer
4
- workspace: ~/.pigent/workspaces/coder
1
+ id: assistant
2
+ name: Assistant
3
+ profile: generic-assistant
4
+ workspace: ~/.pigent/workspaces/assistant
5
5
  systemPromptFile: ./SYSTEM.md
6
6
  skills: []
7
7
  extensions: []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fickydev/pigent",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Autonomous multi-agent daemon using Pi as core execution engine.",
package/pigent.yaml CHANGED
@@ -5,8 +5,8 @@ telegramChats: []
5
5
  # telegramChats:
6
6
  # - chatId: "123456"
7
7
  # title: Example Private Chat
8
- # defaultAgent: coder
8
+ # defaultAgent: assistant
9
9
  # allowedAgents:
10
- # - coder
10
+ # - assistant
11
11
  # instructions: |
12
12
  # Be concise.
@@ -0,0 +1,11 @@
1
+ id: generic-assistant
2
+ name: Generic Assistant
3
+ model: null
4
+ instructions: |
5
+ You are a helpful general-purpose assistant.
6
+ Prefer concise, useful answers. Ask clarifying questions only when needed.
7
+ defaultSkills: []
8
+ defaultExtensions: []
9
+ permissions:
10
+ canRunShell: false
11
+ canEditFiles: false
package/src/cli/run.ts CHANGED
@@ -1,47 +1,153 @@
1
1
  #!/usr/bin/env bun
2
+ import { $ } from "bun";
2
3
  import { existsSync } from "node:fs";
3
- import { cp, mkdir } from "node:fs/promises";
4
+ import { chmod, cp, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
4
5
  import { homedir } from "node:os";
5
6
  import { dirname, join, resolve } from "node:path";
6
7
  import { fileURLToPath } from "node:url";
7
8
 
9
+ const packageName = "@fickydev/pigent";
10
+ const serviceName = "pigent";
11
+ const defaultRoot = join(homedir(), ".pigent");
12
+ const defaultAppDir = join(defaultRoot, "app");
13
+ const defaultLogPath = join(defaultRoot, "pigent.log");
8
14
  const args = process.argv.slice(2);
9
- const flags = new Set(args.filter((arg) => arg.startsWith("--")));
10
- const targetDirArg = args.find((arg) => !arg.startsWith("--"));
11
- const forceSetup = flags.has("--setup") || flags.has("--reconfigure");
15
+ const commands = new Set([
16
+ "install",
17
+ "setup",
18
+ "start",
19
+ "stop",
20
+ "restart",
21
+ "status",
22
+ "logs",
23
+ "run",
24
+ "foreground",
25
+ "update",
26
+ "help",
27
+ ]);
28
+ const command = commands.has(args[0] ?? "") ? args[0] : null;
29
+ const targetDirArg = args.find((arg, index) => !arg.startsWith("--") && !(index === 0 && command));
30
+ const appDir = targetDirArg ? resolve(process.cwd(), targetDirArg) : defaultAppDir;
12
31
 
13
32
  async function main(): Promise<void> {
14
- const targetDir = resolveTargetDir();
33
+ switch (command) {
34
+ case "help":
35
+ printHelp();
36
+ return;
37
+ case "setup":
38
+ await ensureConfiguredApp(appDir, true);
39
+ return;
40
+ case "install":
41
+ await installAndStartService(appDir);
42
+ return;
43
+ case "start":
44
+ await startService(appDir);
45
+ return;
46
+ case "stop":
47
+ await systemctl("stop");
48
+ return;
49
+ case "restart":
50
+ await systemctl("restart");
51
+ return;
52
+ case "status":
53
+ await systemctl("status", false);
54
+ return;
55
+ case "logs":
56
+ await showLogs();
57
+ return;
58
+ case "update":
59
+ await updateApp(appDir);
60
+ return;
61
+ case "run":
62
+ case "foreground":
63
+ await runForeground(resolveForegroundDir());
64
+ return;
65
+ default:
66
+ await installAndStartService(appDir);
67
+ }
68
+ }
69
+
70
+ async function installAndStartService(targetDir: string): Promise<void> {
71
+ await ensureConfiguredApp(targetDir, true);
15
72
 
16
- if (targetDir) {
17
- await ensureProject(targetDir);
18
- process.chdir(targetDir);
73
+ if (!(await hasSystemctl())) {
74
+ console.log("[pigent] systemd user service unavailable; running in foreground");
75
+ await runForeground(targetDir);
76
+ return;
19
77
  }
20
78
 
21
- const { runSetup } = await import("./setup");
79
+ await installCommandShim();
80
+ await writeServiceFile(targetDir);
81
+ await systemctl("daemon-reload");
82
+ await systemctl("enable", true, `${serviceName}.service`);
83
+ await systemctl("restart");
22
84
 
23
- if (forceSetup || needsSetup(process.cwd())) {
24
- await runSetup({
25
- skipInstall: true,
26
- skipMigrate: true,
27
- skipTypecheck: true,
28
- });
85
+ console.log("\nPigent installed and running.");
86
+ console.log("Commands:");
87
+ console.log(" pigent status");
88
+ console.log(" pigent logs");
89
+ console.log(" pigent stop");
90
+ console.log(" pigent restart");
91
+ console.log(" pigent update");
92
+ }
93
+
94
+ async function startService(targetDir: string): Promise<void> {
95
+ if (!existsSync(servicePath())) {
96
+ await installAndStartService(targetDir);
97
+ return;
29
98
  }
30
99
 
31
- await import("../main");
100
+ await systemctl("start");
101
+ }
102
+
103
+ async function updateApp(targetDir: string): Promise<void> {
104
+ console.log("[pigent] updating app");
105
+
106
+ if (await hasSystemctl()) {
107
+ await systemctl("stop", true);
108
+ }
109
+
110
+ await mkdir(defaultRoot, { recursive: true });
111
+ await installCommandShim();
112
+ await refreshProject(targetDir);
113
+
114
+ if (await hasSystemctl()) {
115
+ await writeServiceFile(targetDir);
116
+ await systemctl("daemon-reload");
117
+ await systemctl("enable", true, `${serviceName}.service`);
118
+ await systemctl("restart");
119
+ console.log("[pigent] updated and restarted service");
120
+ } else {
121
+ console.log("[pigent] updated. Run `pigent run` to start foreground daemon.");
122
+ }
123
+ }
124
+
125
+ async function ensureConfiguredApp(targetDir: string, interactive: boolean): Promise<void> {
126
+ await ensureProject(targetDir);
127
+ process.chdir(targetDir);
128
+
129
+ if (interactive || needsSetup(targetDir)) {
130
+ const { runSetup } = await import("./setup");
131
+ await runSetup();
132
+ }
32
133
  }
33
134
 
34
- function resolveTargetDir(): string | null {
35
- if (targetDirArg) return resolve(process.cwd(), targetDirArg);
36
- if (looksLikePigentProject(process.cwd())) return null;
37
- return join(homedir(), ".pigent", "app");
135
+ async function runForeground(targetDir: string): Promise<void> {
136
+ await ensureProject(targetDir);
137
+ process.chdir(targetDir);
138
+
139
+ if (needsSetup(targetDir)) {
140
+ const { runSetup } = await import("./setup");
141
+ await runSetup();
142
+ }
143
+
144
+ await import("../main");
38
145
  }
39
146
 
40
147
  async function ensureProject(targetDir: string): Promise<void> {
41
148
  await mkdir(targetDir, { recursive: true });
42
149
 
43
150
  if (existsSync(join(targetDir, "package.json"))) {
44
- console.log(`[pigent] using existing project ${targetDir}`);
45
151
  return;
46
152
  }
47
153
 
@@ -55,6 +161,105 @@ async function ensureProject(targetDir: string): Promise<void> {
55
161
  });
56
162
  }
57
163
 
164
+ async function refreshProject(targetDir: string): Promise<void> {
165
+ const sourceRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
166
+ const backupDir = join(defaultRoot, "backups", `app-${timestamp()}`);
167
+
168
+ if (existsSync(targetDir)) {
169
+ await mkdir(dirname(backupDir), { recursive: true });
170
+ await cp(targetDir, backupDir, { recursive: true, force: false });
171
+ console.log(`[pigent] backup created ${backupDir}`);
172
+ }
173
+
174
+ await mkdir(targetDir, { recursive: true });
175
+
176
+ const preserved = [".env", "pigent.db", "pigent.db-shm", "pigent.db-wal", "pigent.yaml", "agents", "profiles"];
177
+ const tempPreserveDir = join(defaultRoot, ".update-preserve");
178
+ await rm(tempPreserveDir, { recursive: true, force: true });
179
+ await mkdir(tempPreserveDir, { recursive: true });
180
+
181
+ for (const entry of preserved) {
182
+ const source = join(targetDir, entry);
183
+ if (existsSync(source)) {
184
+ await rename(source, join(tempPreserveDir, entry));
185
+ }
186
+ }
187
+
188
+ await cp(sourceRoot, targetDir, {
189
+ recursive: true,
190
+ force: true,
191
+ filter: (source) => shouldCopy(sourceRoot, source),
192
+ });
193
+
194
+ for (const entry of preserved) {
195
+ const source = join(tempPreserveDir, entry);
196
+ if (existsSync(source)) {
197
+ await rm(join(targetDir, entry), { recursive: true, force: true });
198
+ await rename(source, join(targetDir, entry));
199
+ }
200
+ }
201
+
202
+ await rm(tempPreserveDir, { recursive: true, force: true });
203
+ }
204
+
205
+ async function installCommandShim(): Promise<void> {
206
+ const binDir = join(homedir(), ".local", "bin");
207
+ const shimPath = join(binDir, "pigent");
208
+ await mkdir(binDir, { recursive: true });
209
+ await writeFile(shimPath, `#!/usr/bin/env sh\nexec bunx ${packageName}@latest "$@"\n`);
210
+ await chmod(shimPath, 0o755);
211
+
212
+ const pathParts = (process.env.PATH ?? "").split(":");
213
+ if (!pathParts.includes(binDir)) {
214
+ console.log(`[pigent] add ${binDir} to PATH to use the pigent command from new shells`);
215
+ }
216
+ }
217
+
218
+ async function writeServiceFile(targetDir: string): Promise<void> {
219
+ const pathValue = process.env.PATH ?? "";
220
+ const bunPath = process.execPath;
221
+ await mkdir(dirname(servicePath()), { recursive: true });
222
+ await writeFile(
223
+ servicePath(),
224
+ `[Unit]\nDescription=Pigent autonomous agent daemon\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nWorkingDirectory=${targetDir}\nExecStart=${bunPath} run src/main.ts\nRestart=always\nRestartSec=5\nEnvironment=NODE_ENV=production\nEnvironment=PATH=${pathValue}\n\n[Install]\nWantedBy=default.target\n`,
225
+ );
226
+ }
227
+
228
+ async function showLogs(): Promise<void> {
229
+ if (await hasSystemctl()) {
230
+ await $`systemctl --user status ${serviceName}.service`.nothrow().quiet();
231
+ await $`journalctl --user -u ${serviceName}.service -f`;
232
+ return;
233
+ }
234
+
235
+ if (existsSync(defaultLogPath)) {
236
+ console.log(await readFile(defaultLogPath, "utf8"));
237
+ return;
238
+ }
239
+
240
+ console.log("No logs found.");
241
+ }
242
+
243
+ async function systemctl(action: string, nothrow = false, extra?: string): Promise<void> {
244
+ const commandArgs = extra ? [action, extra] : [action, `${serviceName}.service`];
245
+ const proc = $`systemctl --user ${commandArgs}`;
246
+ if (nothrow) {
247
+ await proc.nothrow();
248
+ } else {
249
+ await proc;
250
+ }
251
+ }
252
+
253
+ async function hasSystemctl(): Promise<boolean> {
254
+ if (!existsSync("/bin/systemctl") && !existsSync("/usr/bin/systemctl")) return false;
255
+ const result = await $`systemctl --user show-environment`.nothrow().quiet();
256
+ return result.exitCode === 0;
257
+ }
258
+
259
+ function servicePath(): string {
260
+ return join(homedir(), ".config", "systemd", "user", `${serviceName}.service`);
261
+ }
262
+
58
263
  function shouldCopy(sourceRoot: string, source: string): boolean {
59
264
  const relative = source.slice(sourceRoot.length).replace(/^\/+/, "");
60
265
  if (!relative) return true;
@@ -74,14 +279,27 @@ function shouldCopy(sourceRoot: string, source: string): boolean {
74
279
  }
75
280
 
76
281
  function needsSetup(rootDir: string): boolean {
77
- if (!existsSync(join(rootDir, ".env"))) return true;
78
- return false;
282
+ return !existsSync(join(rootDir, ".env"));
283
+ }
284
+
285
+ function resolveForegroundDir(): string {
286
+ if (targetDirArg) return appDir;
287
+ if (looksLikePigentProject(process.cwd())) return process.cwd();
288
+ return defaultAppDir;
79
289
  }
80
290
 
81
291
  function looksLikePigentProject(rootDir: string): boolean {
82
292
  return existsSync(join(rootDir, "pigent.yaml")) && existsSync(join(rootDir, "agents"));
83
293
  }
84
294
 
295
+ function timestamp(): string {
296
+ return new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
297
+ }
298
+
299
+ function printHelp(): void {
300
+ console.log(`Pigent\n\nUsage:\n pigent Install/start user service in ~/.pigent/app\n pigent install Install/start user service\n pigent setup Reconfigure app\n pigent start Start service\n pigent stop Stop service\n pigent restart Restart service\n pigent status Show service status\n pigent logs Follow service logs\n pigent update Update app from latest package and restart\n pigent run Run foreground daemon\n\nWith bunx:\n bunx ${packageName}\n bunx ${packageName} status\n`);
301
+ }
302
+
85
303
  main().catch((error) => {
86
304
  console.error("[pigent] failed", error instanceof Error ? error.message : error);
87
305
  process.exit(1);
package/src/cli/setup.ts CHANGED
@@ -66,16 +66,8 @@ async function configureEnvironment(isCustom: boolean): Promise<void> {
66
66
  }
67
67
  }
68
68
 
69
- if (confirm("Auto-configure new Telegram chats?", getEnvValue(env, "PIGENT_AUTO_SETUP_CHATS") === "1")) {
70
- env = setEnvValue(env, "PIGENT_AUTO_SETUP_CHATS", "1");
71
- env = setEnvValue(
72
- env,
73
- "PIGENT_AUTO_SETUP_DEFAULT_AGENT",
74
- input("Auto-setup default agent", getEnvValue(env, "PIGENT_AUTO_SETUP_DEFAULT_AGENT") ?? "coder"),
75
- );
76
- } else {
77
- env = setEnvValue(env, "PIGENT_AUTO_SETUP_CHATS", "0");
78
- }
69
+ env = setEnvValue(env, "PIGENT_AUTO_SETUP_CHATS", "1");
70
+ env = setEnvValue(env, "PIGENT_AUTO_SETUP_DEFAULT_AGENT", getEnvValue(env, "PIGENT_AUTO_SETUP_DEFAULT_AGENT") ?? "assistant");
79
71
 
80
72
  if (isCustom) {
81
73
  env = setEnvValue(env, "LOG_LEVEL", select("Log level", ["debug", "info", "warn", "error"], getEnvValue(env, "LOG_LEVEL") ?? "info"));
@@ -112,8 +104,8 @@ async function configureTelegramChat(isCustom: boolean): Promise<void> {
112
104
  return;
113
105
  }
114
106
 
115
- const title = input("Chat title", "");
116
- const defaultAgent = input("Default agent", "coder") || "coder";
107
+ const title = input("Chat title", "Home");
108
+ const defaultAgent = input("Default agent", "assistant") || "assistant";
117
109
  const allowedAgentsInput = input("Allowed agents, comma-separated", defaultAgent);
118
110
  const instructions = isCustom ? inputMultiline("Chat instructions", "") : "";
119
111
  const allowedAgents = allowedAgentsInput
@@ -63,8 +63,8 @@ export class TelegramRepository {
63
63
 
64
64
  const raw = message.raw as { chat?: { title?: string; username?: string; first_name?: string; last_name?: string } } | null;
65
65
  const title = raw?.chat
66
- ? raw.chat.title ?? [raw.chat.first_name, raw.chat.last_name].filter(Boolean).join(" ") ?? raw.chat.username
67
- : undefined;
66
+ ? raw.chat.title ?? [raw.chat.first_name, raw.chat.last_name].filter(Boolean).join(" ") ?? raw.chat.username ?? "Home"
67
+ : "Home";
68
68
 
69
69
  await this.upsertConfiguredChat({
70
70
  chatId: message.chatId,
package/src/main.ts CHANGED
@@ -25,10 +25,19 @@ async function shutdown(signal: string): Promise<void> {
25
25
  process.on("SIGINT", () => void shutdown("SIGINT"));
26
26
  process.on("SIGTERM", () => void shutdown("SIGTERM"));
27
27
 
28
+ function keepAlive(): Promise<never> {
29
+ return new Promise(() => {
30
+ setInterval(() => {
31
+ // Keep daemon process alive even when no adapter currently has an active handle.
32
+ }, 60_000);
33
+ });
34
+ }
35
+
28
36
  try {
29
37
  logger.info("pigent starting");
30
38
  await daemon.start();
31
39
  logger.info("pigent ready");
40
+ await keepAlive();
32
41
  } catch (error) {
33
42
  logger.error("pigent failed to start", {
34
43
  error: error instanceof Error ? error.message : String(error),
@@ -1,3 +0,0 @@
1
- You are coder agent.
2
-
3
- Focus on implementation, debugging, and code review. Keep responses concise. Ask before risky changes.
@@ -1,11 +0,0 @@
1
- id: software-engineer
2
- name: Software Engineer
3
- model: null
4
- instructions: |
5
- You are a pragmatic software engineering agent.
6
- Prefer small safe diffs, clear tests, and stable behavior.
7
- defaultSkills: []
8
- defaultExtensions: []
9
- permissions:
10
- canRunShell: false
11
- canEditFiles: false