@marcopeg/hal 1.0.11 → 1.0.15

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 (76) hide show
  1. package/README.md +151 -32
  2. package/dist/agent/index.d.ts +5 -7
  3. package/dist/agent/index.d.ts.map +1 -1
  4. package/dist/agent/index.js +15 -9
  5. package/dist/agent/index.js.map +1 -1
  6. package/dist/bot/commands/loader.d.ts +5 -0
  7. package/dist/bot/commands/loader.d.ts.map +1 -1
  8. package/dist/bot/commands/loader.js +31 -0
  9. package/dist/bot/commands/loader.js.map +1 -1
  10. package/dist/bot/commands/session.d.ts +11 -0
  11. package/dist/bot/commands/session.d.ts.map +1 -0
  12. package/dist/bot/commands/session.js +65 -0
  13. package/dist/bot/commands/session.js.map +1 -0
  14. package/dist/bot/handlers/document.d.ts.map +1 -1
  15. package/dist/bot/handlers/document.js +8 -8
  16. package/dist/bot/handlers/document.js.map +1 -1
  17. package/dist/bot/handlers/photo.d.ts.map +1 -1
  18. package/dist/bot/handlers/photo.js +8 -8
  19. package/dist/bot/handlers/photo.js.map +1 -1
  20. package/dist/bot/handlers/text.d.ts.map +1 -1
  21. package/dist/bot/handlers/text.js +14 -8
  22. package/dist/bot/handlers/text.js.map +1 -1
  23. package/dist/bot/handlers/voice.d.ts.map +1 -1
  24. package/dist/bot/handlers/voice.js +8 -8
  25. package/dist/bot/handlers/voice.js.map +1 -1
  26. package/dist/bot.d.ts.map +1 -1
  27. package/dist/bot.js +10 -21
  28. package/dist/bot.js.map +1 -1
  29. package/dist/cli.js +65 -17
  30. package/dist/cli.js.map +1 -1
  31. package/dist/config.d.ts +66 -19
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js +25 -5
  34. package/dist/config.js.map +1 -1
  35. package/dist/context/resolver.d.ts.map +1 -1
  36. package/dist/context/resolver.js +6 -5
  37. package/dist/context/resolver.js.map +1 -1
  38. package/dist/engine/adapters/claude.d.ts +3 -0
  39. package/dist/engine/adapters/claude.d.ts.map +1 -0
  40. package/dist/engine/adapters/claude.js +241 -0
  41. package/dist/engine/adapters/claude.js.map +1 -0
  42. package/dist/engine/adapters/codex.d.ts +9 -0
  43. package/dist/engine/adapters/codex.d.ts.map +1 -0
  44. package/dist/engine/adapters/codex.js +109 -0
  45. package/dist/engine/adapters/codex.js.map +1 -0
  46. package/dist/engine/adapters/copilot.d.ts +3 -0
  47. package/dist/engine/adapters/copilot.d.ts.map +1 -0
  48. package/dist/engine/adapters/copilot.js +109 -0
  49. package/dist/engine/adapters/copilot.js.map +1 -0
  50. package/dist/engine/adapters/opencode.d.ts +7 -0
  51. package/dist/engine/adapters/opencode.d.ts.map +1 -0
  52. package/dist/engine/adapters/opencode.js +94 -0
  53. package/dist/engine/adapters/opencode.js.map +1 -0
  54. package/dist/engine/index.d.ts +4 -0
  55. package/dist/engine/index.d.ts.map +1 -0
  56. package/dist/engine/index.js +3 -0
  57. package/dist/engine/index.js.map +1 -0
  58. package/dist/engine/prompt.d.ts +9 -0
  59. package/dist/engine/prompt.d.ts.map +1 -0
  60. package/dist/engine/prompt.js +29 -0
  61. package/dist/engine/prompt.js.map +1 -0
  62. package/dist/engine/registry.d.ts +9 -0
  63. package/dist/engine/registry.d.ts.map +1 -0
  64. package/dist/engine/registry.js +24 -0
  65. package/dist/engine/registry.js.map +1 -0
  66. package/dist/engine/types.d.ts +45 -0
  67. package/dist/engine/types.d.ts.map +1 -0
  68. package/dist/engine/types.js +7 -0
  69. package/dist/engine/types.js.map +1 -0
  70. package/dist/types.d.ts +5 -1
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/user/setup.d.ts +5 -0
  73. package/dist/user/setup.d.ts.map +1 -1
  74. package/dist/user/setup.js +13 -0
  75. package/dist/user/setup.js.map +1 -1
  76. package/package.json +1 -1
package/README.md CHANGED
@@ -1,38 +1,55 @@
1
1
  # HAL
2
2
 
3
- A Telegram bot that provides access to Claude Code as a personal assistant. Run Claude Code across multiple projects simultaneously, each with its own dedicated Telegram bot.
3
+ A Telegram bot that provides access to AI coding agents as a personal assistant. Run multiple engines (Claude Code, GitHub Copilot, and more) across multiple projects simultaneously, each with its own dedicated Telegram bot.
4
4
 
5
5
  ## Features
6
6
 
7
+ - **Multi-engine support** — use Claude Code, GitHub Copilot, Codex, or OpenCode per project
7
8
  - **Multi-project support** — run multiple bots from a single config, each connected to a different directory
8
- - Chat with Claude Code via Telegram
9
+ - Chat with your AI coding agent via Telegram
9
10
  - Send images and documents for analysis
10
11
  - **Voice message support** with local Whisper transcription
11
- - **File sending** — Claude can send files back to you
12
+ - **File sending** — the engine can send files back to you
12
13
  - **Context injection** — every message includes metadata (timestamps, user info, custom values) and supports hot-reloaded hooks
13
- - **Custom slash commands** — add `.mjs` command files per-project or globally; hot-reloaded so Claude can create new commands at runtime
14
- - **Skills** — Claude Code `.claude/skills/` entries are automatically exposed as Telegram slash commands; no extra setup needed
14
+ - **Custom slash commands** — add `.mjs` command files per-project or globally; hot-reloaded so the engine can create new commands at runtime
15
+ - **Skills** — `.claude/skills/` entries are automatically exposed as Telegram slash commands; no extra setup needed
15
16
  - Persistent conversation sessions per user
16
17
  - Per-project access control, rate limiting, and logging
17
18
  - Log persistence to file with daily rotation support
18
19
 
19
20
  ## How It Works
20
21
 
21
- This tool runs one Claude Code subprocess per project, each in its configured working directory. Claude Code reads all its standard config files from that directory:
22
+ This tool runs one AI coding agent subprocess per project, each in its configured working directory. The default engine is Claude Code, but each project can use a different engine.
22
23
 
23
- - `CLAUDE.md` Project-specific instructions and context
24
- - `.claude/settings.json` — Permissions and tool settings
24
+ The engine reads its standard config files from the project directory:
25
+
26
+ - `CLAUDE.md` / `AGENTS.md` — Project-specific instructions and context (filename depends on engine)
27
+ - `.claude/settings.json` — Permissions and tool settings (Claude Code)
25
28
  - `.claude/commands/` — Custom slash commands
26
29
  - `.mcp.json` — MCP server configurations
27
30
 
28
- You get the full power of Claude Code — file access, code execution, configured MCP tools — all accessible through Telegram.
31
+ You get the full power of your chosen AI coding agent — file access, code execution, configured MCP tools — all accessible through Telegram.
32
+
33
+ ### Supported Engines
34
+
35
+ | Engine | CLI Command | Status | Instructions File |
36
+ |--------|-------------|--------|-------------------|
37
+ | **Claude Code** | `claude` | Full support | `CLAUDE.md` |
38
+ | **GitHub Copilot** | `copilot` | Full support | `AGENTS.md` |
39
+ | **Codex** | `codex` | Full support | `AGENTS.md` |
40
+ | **OpenCode** | `opencode` | Stub (basic prompt/response) | `AGENTS.md` |
41
+
42
+ See [Engine Configuration](#engine-configuration) for setup details.
29
43
 
30
- See [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code) for details on Claude Code configuration.
44
+ See [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code), [GitHub Copilot CLI documentation](https://docs.github.com/en/copilot/concepts/agents/copilot-cli), and the Codex CLI (`codex --help`) for engine-specific configuration.
31
45
 
32
46
  ## Prerequisites
33
47
 
34
48
  - Node.js 18+
35
- - [Claude Code CLI](https://github.com/anthropics/claude-code) installed and authenticated
49
+ - At least one supported AI coding CLI installed and authenticated:
50
+ - [Claude Code CLI](https://github.com/anthropics/claude-code) — `claude`
51
+ - [GitHub Copilot CLI](https://docs.github.com/en/copilot/concepts/agents/copilot-cli) — `copilot`
52
+ - [Codex CLI](https://github.com/openai/codex-cli) — `codex`
36
53
  - A Telegram bot token per project (from [@BotFather](https://t.me/BotFather)) — see [Creating a Telegram Bot](#creating-a-telegram-bot)
37
54
  - **ffmpeg** (required for voice messages) — `brew install ffmpeg` on macOS
38
55
 
@@ -42,6 +59,9 @@ See [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code)
42
59
  # Create hal.config.json in the current directory
43
60
  npx @marcopeg/hal init
44
61
 
62
+ # Initialize with a specific engine
63
+ npx @marcopeg/hal init --engine copilot
64
+
45
65
  # Edit hal.config.json: add your bot token and project path
46
66
  # then start all bots
47
67
  npx @marcopeg/hal
@@ -66,7 +86,7 @@ Create a `hal.config.json` in your workspace directory (where you run the CLI fr
66
86
  ```json
67
87
  {
68
88
  "globals": {
69
- "claude": { "command": "claude" },
89
+ "engine": { "name": "claude" },
70
90
  "logging": { "level": "info", "flow": true, "persist": false },
71
91
  "rateLimit": { "max": 10, "windowMs": 60000 },
72
92
  "access": { "allowedUserIds": [] }
@@ -82,6 +102,7 @@ Create a `hal.config.json` in your workspace directory (where you run the CLI fr
82
102
  {
83
103
  "name": "frontend",
84
104
  "cwd": "./frontend",
105
+ "engine": { "name": "copilot", "model": "gpt-5-mini" },
85
106
  "telegram": { "botToken": "${FRONTEND_BOT_TOKEN}" },
86
107
  "access": { "allowedUserIds": [123456789] }
87
108
  }
@@ -133,7 +154,7 @@ On every boot an `info`-level log lists all config and env files that were loade
133
154
 
134
155
  ### Context Injection
135
156
 
136
- Every message sent to Claude is automatically enriched with a structured context header. This provides metadata (message info, timestamps, custom values) so Claude can reason about the current request without extra tool calls.
157
+ Every message sent to the engine is automatically enriched with a structured context header. This provides metadata (message info, timestamps, custom values) so the AI can reason about the current request without extra tool calls.
137
158
 
138
159
  #### Implicit context (always-on)
139
160
 
@@ -151,7 +172,7 @@ These keys are injected for every message, even without any `context` configurat
151
172
  | `bot.messageType` | `text` / `photo` / `document` / `voice` |
152
173
  | `project.name` | Project name (falls back to internal slug if not set) |
153
174
  | `project.cwd` | Resolved absolute project working directory |
154
- | `project.slug` | Claude Code-compatible slug (full path with `/` → `-`) |
175
+ | `project.slug` | Project slug (full path with `/` → `-`) |
155
176
  | `sys.datetime` | Current local datetime with timezone |
156
177
  | `sys.date` | Current date, `YYYY-MM-DD` |
157
178
  | `sys.time` | Current time, `HH:MM:SS` |
@@ -205,7 +226,7 @@ For advanced enrichment, you can provide a `context.mjs` hook file that transfor
205
226
  | `{configDir}/.hal/hooks/context.mjs` | Global — runs for all projects |
206
227
  | `{project.cwd}/.hal/hooks/context.mjs` | Project — runs for that project only |
207
228
 
208
- When both exist, they chain: global runs first, its output feeds into the project hook. Both are **hot-reloaded** on every message (no restart needed) — so Claude Code itself can create or modify hooks at runtime.
229
+ When both exist, they chain: global runs first, its output feeds into the project hook. Both are **hot-reloaded** on every message (no restart needed) — so the AI engine itself can create or modify hooks at runtime.
209
230
 
210
231
  ```js
211
232
  // .hal/hooks/context.mjs
@@ -217,12 +238,12 @@ export default async (context) => ({
217
238
  ```
218
239
 
219
240
  - **Input**: fully-resolved `Record<string, string>` context
220
- - **Output**: a `Record<string, string>` — the final context passed to Claude
241
+ - **Output**: a `Record<string, string>` — the final context passed to the engine
221
242
  - If a hook throws, the bot logs the error and falls back to the pre-hook context
222
243
 
223
244
  #### Prompt format
224
245
 
225
- The resolved context is prepended to the user message before passing to Claude:
246
+ The resolved context is prepended to the user message before passing to the engine:
226
247
 
227
248
  ```
228
249
  # Context
@@ -240,7 +261,11 @@ Default settings applied to all projects. Any setting defined in a project overr
240
261
 
241
262
  | Key | Description | Default |
242
263
  |-----|-------------|---------|
243
- | `globals.claude.command` | Claude CLI command | `"claude"` |
264
+ | `globals.engine.name` | Engine: `claude`, `copilot`, `codex`, `opencode` | `"claude"` |
265
+ | `globals.engine.command` | Override the CLI command path | _(engine name)_ |
266
+ | `globals.engine.model` | Override the AI model | _(engine default)_ |
267
+ | `globals.engine.session` | Use persistent sessions (`--resume` / `--continue`) | `true` |
268
+ | `globals.engine.sessionMsg` | Message sent when renewing session (e.g. `/new`, `/clean`) | `"hi!"` |
244
269
  | `globals.logging.level` | Log level: `debug`, `info`, `warn`, `error` | `"info"` |
245
270
  | `globals.logging.flow` | Write logs to terminal | `true` |
246
271
  | `globals.logging.persist` | Write logs to file | `false` |
@@ -258,16 +283,15 @@ Each project entry creates one Telegram bot connected to one directory.
258
283
  | Key | Required | Description |
259
284
  |-----|----------|-------------|
260
285
  | `name` | No | Unique identifier used as a slug for logs/data paths |
286
+ | `active` | No | Set to `false` to skip this project at boot (default: `true`) |
261
287
  | `cwd` | **Yes** | Path to the project directory (relative to config file, or absolute) |
262
288
  | `telegram.botToken` | **Yes** | Telegram bot token from BotFather |
263
289
  | `access.allowedUserIds` | No | Override the global user whitelist for this bot |
264
- | `claude.command` | No | Override the Claude CLI command |
265
- | `logging.level` | No | Override log level |
266
- | `logging.flow` | No | Override terminal logging |
267
- | `logging.persist` | No | Override file logging |
268
- | `rateLimit.max` | No | Override rate limit max |
269
- | `rateLimit.windowMs` | No | Override rate limit window |
270
- | `transcription.model` | No | Override Whisper model |
290
+ | `engine.name` | No | Override the engine for this project |
291
+ | `engine.command` | No | Override the CLI command path |
292
+ | `engine.model` | No | Override the AI model |
293
+ | `engine.session` | No | Use persistent sessions for this project |
294
+ | `engine.sessionMsg` | No | Message used when renewing session |
271
295
  | `transcription.showTranscription` | No | Override transcription display |
272
296
  | `dataDir` | No | Override user data directory (see below) |
273
297
  | `context` | No | Per-project context overrides (see [Context Injection](#context-injection)) |
@@ -294,6 +318,99 @@ When `logging.persist: true`, logs are written to:
294
318
  <config-dir>/.hal/logs/<project-slug>/YYYY-MM-DD.txt
295
319
  ```
296
320
 
321
+ ### Engine Configuration
322
+
323
+ Set the engine globally or per-project. The engine determines which AI coding CLI is invoked for each message.
324
+
325
+ ```json
326
+ {
327
+ "globals": {
328
+ "engine": { "name": "claude" }
329
+ },
330
+ "projects": [
331
+ {
332
+ "name": "backend",
333
+ "cwd": "./backend",
334
+ "telegram": { "botToken": "${BACKEND_BOT_TOKEN}" }
335
+ },
336
+ {
337
+ "name": "frontend",
338
+ "cwd": "./frontend",
339
+ "engine": { "name": "copilot", "model": "gpt-5-mini" },
340
+ "telegram": { "botToken": "${FRONTEND_BOT_TOKEN}" }
341
+ },
342
+ {
343
+ "name": "legacy",
344
+ "active": false,
345
+ "cwd": "./legacy",
346
+ "telegram": { "botToken": "${LEGACY_BOT_TOKEN}" }
347
+ }
348
+ ]
349
+ }
350
+ ```
351
+
352
+ In this example:
353
+ - **backend** inherits the global engine (Claude Code, default model)
354
+ - **frontend** uses GitHub Copilot with the `gpt-5-mini` model
355
+ - **legacy** is inactive and will be skipped at boot
356
+
357
+ The `engine` object supports five fields:
358
+
359
+ | Field | Description | Default |
360
+ |-------|-------------|---------|
361
+ | `name` | Engine identifier: `claude`, `copilot`, `codex`, `opencode` | `"claude"` |
362
+ | `command` | Custom path to the CLI binary | _(engine name)_ |
363
+ | `model` | AI model override (omit to use the engine's default) | _(engine default)_ |
364
+ | `session` | Use persistent sessions (`--resume` / `--continue`) | `true` |
365
+ | `sessionMsg` | Message sent when renewing session (e.g. `/new`, `/clean`) | `"hi!"` |
366
+
367
+ #### Claude Code
368
+
369
+ - **CLI:** `claude` — install and authenticate via [Claude Code CLI](https://github.com/anthropics/claude-code) (see [Prerequisites](#prerequisites)).
370
+ - **Project files:** `CLAUDE.md`, `.claude/settings.json` (see [How It Works](#how-it-works)).
371
+ - **Config:** `engine.name: "claude"`. Optional: `engine.command`, `engine.model` (passed as `--model`), `engine.session`, `engine.sessionMsg`.
372
+ - **Sessions:** When `engine.session` is `true`, the CLI is invoked with `--resume <sessionId>`. `/new` and `/clean` clear the stored session and reply with a static message (no engine call).
373
+
374
+ #### GitHub Copilot
375
+
376
+ - **CLI:** `copilot` — install and authenticate via [GitHub Copilot CLI](https://docs.github.com/en/copilot/concepts/agents/copilot-cli) (see [Prerequisites](#prerequisites)).
377
+ - **Project file:** `AGENTS.md`.
378
+ - **Config:** `engine.name: "copilot"`. Optional: `engine.command`, `engine.model` (see table below), `engine.session`, `engine.sessionMsg`.
379
+ - **Sessions:** When `engine.session` is `true`, the CLI is invoked with `--continue`. `/new` and `/clean` send `engine.sessionMsg` to the engine without `--continue` to start a fresh session; the engine’s reply is sent to the user.
380
+
381
+ #### Codex
382
+
383
+ - **CLI:** `codex` — install and authenticate via [Codex CLI](https://github.com/openai/codex-cli) (see [Prerequisites](#prerequisites)).
384
+ - **Project file:** `AGENTS.md`.
385
+ - **Config:** `engine.name: "codex"`. Optional: `engine.command`, `engine.model` (e.g. `gpt-5.1-codex-mini`), `engine.session`, `engine.sessionMsg`.
386
+ - **Sessions:** When `engine.session` is `true`, the CLI is invoked with `codex exec resume --last` to continue the most recent session; otherwise `codex exec` starts a fresh run. `/new` and `/clean` send `engine.sessionMsg` without resuming, so the engine starts a new session; the engine's reply is sent to the user (same behaviour as Copilot).
387
+
388
+ #### GitHub Copilot Models
389
+
390
+ When using the `copilot` engine, the following models are available via `engine.model`:
391
+
392
+ | Model | Description |
393
+ |-------|-------------|
394
+ | `claude-sonnet-4.6` | Anthropic Claude Sonnet 4.6 |
395
+ | `claude-sonnet-4.5` | Anthropic Claude Sonnet 4.5 |
396
+ | `claude-haiku-4.5` | Anthropic Claude Haiku 4.5 |
397
+ | `claude-opus-4.6` | Anthropic Claude Opus 4.6 |
398
+ | `claude-opus-4.6-fast` | Anthropic Claude Opus 4.6 (fast) |
399
+ | `claude-opus-4.5` | Anthropic Claude Opus 4.5 |
400
+ | `claude-sonnet-4` | Anthropic Claude Sonnet 4 |
401
+ | `gemini-3-pro-preview` | Google Gemini 3 Pro (preview) |
402
+ | `gpt-5.3-codex` | OpenAI GPT-5.3 Codex |
403
+ | `gpt-5.2-codex` | OpenAI GPT-5.2 Codex |
404
+ | `gpt-5.2` | OpenAI GPT-5.2 |
405
+ | `gpt-5.1-codex-max` | OpenAI GPT-5.1 Codex Max |
406
+ | `gpt-5.1-codex` | OpenAI GPT-5.1 Codex |
407
+ | `gpt-5.1` | OpenAI GPT-5.1 |
408
+ | `gpt-5.1-codex-mini` | OpenAI GPT-5.1 Codex Mini |
409
+ | `gpt-5-mini` | OpenAI GPT-5 Mini |
410
+ | `gpt-4.1` | OpenAI GPT-4.1 |
411
+
412
+ If `engine.model` is omitted, the engine uses its own default model.
413
+
297
414
  ## Directory Structure
298
415
 
299
416
  With a config at `~/workspace/hal.config.json`:
@@ -359,6 +476,8 @@ npx @marcopeg/hal --cwd ./workspace
359
476
  | `/start` | Welcome message |
360
477
  | `/help` | Show help information |
361
478
  | `/clear` | Clear conversation history |
479
+ | `/new` | Start a new session |
480
+ | `/clean` | Start a new session |
362
481
 
363
482
  ## Custom Commands
364
483
 
@@ -400,7 +519,7 @@ Tokens following the command name, split on whitespace.
400
519
 
401
520
  #### `ctx: Record<string, string>`
402
521
 
403
- The fully-resolved context that would be sent to the AI for this message — identical to what Claude sees in its `# Context` header. Includes all implicit keys plus any config vars and hook results:
522
+ The fully-resolved context that would be sent to the AI for this message — identical to what the engine sees in its `# Context` header. Includes all implicit keys plus any config vars and hook results:
404
523
 
405
524
  | Key group | Description |
406
525
  |-----------|-------------|
@@ -504,7 +623,7 @@ The project-level context object. Useful fields:
504
623
 
505
624
  ### Skills
506
625
 
507
- [Claude Code skills](https://docs.anthropic.com/en/docs/claude-code/skills) live in `.claude/skills/` inside the project directory. Each skill is a folder containing a `SKILL.md` file with a YAML frontmatter block and a prompt body:
626
+ [Claude Code skills](https://docs.anthropic.com/en/docs/claude-code/skills) live in `.claude/skills/` inside the project directory (shared across all engines). Each skill is a folder containing a `SKILL.md` file with a YAML frontmatter block and a prompt body:
508
627
 
509
628
  ```
510
629
  <project-cwd>/
@@ -544,7 +663,7 @@ See [`examples/obsidian/.claude/skills/chuck/`](examples/obsidian/.claude/skills
544
663
 
545
664
  ### Hot-reload
546
665
 
547
- Commands and skills are **hot-reloaded** — drop a new `.mjs` file or `SKILL.md` into the relevant directory and the bot registers it with Telegram automatically, with no restart. This means Claude can write new command or skill files as part of a task and users see them in the `/` menu immediately.
666
+ Commands and skills are **hot-reloaded** — drop a new `.mjs` file or `SKILL.md` into the relevant directory and the bot registers it with Telegram automatically, with no restart. This means the AI engine can write new command or skill files as part of a task and users see them in the `/` menu immediately.
548
667
 
549
668
  ## Creating a Telegram Bot
550
669
 
@@ -599,10 +718,10 @@ Voice messages are transcribed locally using [Whisper](https://github.com/openai
599
718
 
600
719
  ## Sending Files to Users
601
720
 
602
- Claude can send files back through Telegram. Each user has a `downloads/` folder under their data directory. Claude is informed of this path in every prompt.
721
+ The engine can send files back through Telegram. Each user has a `downloads/` folder under their data directory. The engine is informed of this path in every prompt.
603
722
 
604
- 1. Claude writes a file to the downloads folder
605
- 2. The bot detects it after Claude's response completes
723
+ 1. The engine writes a file to the downloads folder
724
+ 2. The bot detects it after the engine's response completes
606
725
  3. The file is sent via Telegram (as a document)
607
726
  4. The file is deleted from the server after delivery
608
727
 
@@ -624,7 +743,7 @@ The old single-project config format is no longer supported. Migrate by wrapping
624
743
  ```json
625
744
  {
626
745
  "globals": {
627
- "claude": { "command": "claude" },
746
+ "engine": { "name": "claude" },
628
747
  "logging": { "level": "info" }
629
748
  },
630
749
  "projects": [
@@ -1,17 +1,15 @@
1
1
  import type { Agent, ProjectContext } from "../types.js";
2
2
  /**
3
3
  * Return the engine-specific skills directory for the given project.
4
- * Today Claude Code stores skills in `.claude/skills/`.
5
- * When new engines are supported this function will branch on the engine type.
4
+ * Delegates to the engine adapter attached to the project context.
5
+ * Falls back to .claude/skills/ when no engine is available (e.g. during init).
6
6
  */
7
- export declare function getSkillsDir(projectCwd: string): string;
7
+ export declare function getSkillsDir(projectCwd: string, ctx?: ProjectContext): string;
8
8
  /**
9
9
  * Create an Agent for the given project context.
10
10
  *
11
- * This factory is the single place where the underlying AI engine is selected.
12
- * Today it always returns a Claude Code-backed agent. When support for other
13
- * providers (Codex, Copilot, …) is added, engine selection will happen here
14
- * based on project config — command handlers never need to change.
11
+ * This factory delegates to the engine adapter on the project context.
12
+ * Command handlers never need to know which engine is in use.
15
13
  */
16
14
  export declare function createAgent(projectCtx: ProjectContext): Agent;
17
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,cAAc,GAAG,KAAK,CAa7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,cAAc,GAAG,MAAM,CAK7E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,cAAc,GAAG,KAAK,CAmB7D"}
@@ -1,25 +1,31 @@
1
1
  import { join } from "node:path";
2
- import { executeClaudeQuery } from "../claude/executor.js";
3
2
  /**
4
3
  * Return the engine-specific skills directory for the given project.
5
- * Today Claude Code stores skills in `.claude/skills/`.
6
- * When new engines are supported this function will branch on the engine type.
4
+ * Delegates to the engine adapter attached to the project context.
5
+ * Falls back to .claude/skills/ when no engine is available (e.g. during init).
7
6
  */
8
- export function getSkillsDir(projectCwd) {
7
+ export function getSkillsDir(projectCwd, ctx) {
8
+ if (ctx?.engine) {
9
+ return ctx.engine.skillsDir(projectCwd);
10
+ }
9
11
  return join(projectCwd, ".claude", "skills");
10
12
  }
11
13
  /**
12
14
  * Create an Agent for the given project context.
13
15
  *
14
- * This factory is the single place where the underlying AI engine is selected.
15
- * Today it always returns a Claude Code-backed agent. When support for other
16
- * providers (Codex, Copilot, …) is added, engine selection will happen here
17
- * based on project config — command handlers never need to change.
16
+ * This factory delegates to the engine adapter on the project context.
17
+ * Command handlers never need to know which engine is in use.
18
18
  */
19
19
  export function createAgent(projectCtx) {
20
+ const { engine } = projectCtx;
20
21
  return {
21
22
  async call(prompt, options) {
22
- const result = await executeClaudeQuery({ prompt, userDir: "", onProgress: options?.onProgress }, projectCtx);
23
+ const result = await engine.execute({
24
+ prompt,
25
+ userDir: "",
26
+ onProgress: options?.onProgress,
27
+ continueSession: options?.continueSession,
28
+ }, projectCtx);
23
29
  if (!result.success) {
24
30
  throw new Error(result.error ?? "Agent call failed");
25
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,OAAO,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,UAA0B;IACpD,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO;YACxB,MAAM,MAAM,GAAG,MAAM,kBAAkB,CACrC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,EACxD,UAAU,CACX,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,GAAoB;IACnE,IAAI,GAAG,EAAE,MAAM,EAAE,CAAC;QAChB,OAAO,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,UAA0B;IACpD,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IAC9B,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO;YACxB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CACjC;gBACE,MAAM;gBACN,OAAO,EAAE,EAAE;gBACX,UAAU,EAAE,OAAO,EAAE,UAAU;gBAC/B,eAAe,EAAE,OAAO,EAAE,eAAe;aAC1C,EACD,UAAU,CACX,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -5,6 +5,11 @@ export interface CommandEntry {
5
5
  filePath: string;
6
6
  skillPrompt?: string;
7
7
  }
8
+ /**
9
+ * Commands that are always registered with Telegram, regardless of
10
+ * whether custom .mjs files or skills exist.
11
+ */
12
+ export declare const BUILTIN_COMMANDS: CommandEntry[];
8
13
  /**
9
14
  * Scan command directories and optionally the skills dir, then return the merged list.
10
15
  *
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/bot/commands/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAI7B,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAqMD;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CAsBzB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,IAAI,CAAC,MAAM,GAClB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAwB9B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAcf"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/bot/commands/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAI7B,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2ND;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,YAAY,EAM1C,CAAC;AAIF;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CA2BzB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,IAAI,CAAC,MAAM,GAClB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA4B9B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAcf"}
@@ -1,6 +1,10 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { readdir, readFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
+ const TELEGRAM_COMMAND_RE = /^[a-z0-9_]{1,32}$/;
5
+ function isValidTelegramCommandName(name) {
6
+ return TELEGRAM_COMMAND_RE.test(name);
7
+ }
4
8
  // ─── Directory helpers ───────────────────────────────────────────────────────
5
9
  function projectCommandDir(projectCwd) {
6
10
  return join(projectCwd, ".hal", "commands");
@@ -20,6 +24,10 @@ async function importCommandFile(filePath, logger) {
20
24
  // Derive command name from filename (strip .mjs extension)
21
25
  const fileName = filePath.split("/").pop() ?? "";
22
26
  const command = fileName.replace(/\.mjs$/, "");
27
+ if (!isValidTelegramCommandName(command)) {
28
+ logger.warn({ filePath, command }, "Invalid Telegram command name from filename — skipping");
29
+ return null;
30
+ }
23
31
  return {
24
32
  command,
25
33
  description: mod.description,
@@ -127,6 +135,10 @@ async function scanSkillsDir(dir, logger) {
127
135
  if (parsed.name !== folder) {
128
136
  logger.warn({ folder, frontmatterName: parsed.name }, "Skill frontmatter `name` differs from folder name — using folder name as command");
129
137
  }
138
+ if (!isValidTelegramCommandName(folder)) {
139
+ logger.warn({ folder, skillMdPath }, "Invalid Telegram command name from skill folder — skipping");
140
+ continue;
141
+ }
130
142
  skills.push({
131
143
  command: folder,
132
144
  description: parsed.description,
@@ -136,6 +148,18 @@ async function scanSkillsDir(dir, logger) {
136
148
  }
137
149
  return skills;
138
150
  }
151
+ // ─── Built-in commands ───────────────────────────────────────────────────────
152
+ /**
153
+ * Commands that are always registered with Telegram, regardless of
154
+ * whether custom .mjs files or skills exist.
155
+ */
156
+ export const BUILTIN_COMMANDS = [
157
+ { command: "start", description: "Welcome message", filePath: "" },
158
+ { command: "help", description: "Show help", filePath: "" },
159
+ { command: "clear", description: "Clear conversation history", filePath: "" },
160
+ { command: "new", description: "Start a new session", filePath: "" },
161
+ { command: "clean", description: "Start a new session", filePath: "" },
162
+ ];
139
163
  // ─── Public API ──────────────────────────────────────────────────────────────
140
164
  /**
141
165
  * Scan command directories and optionally the skills dir, then return the merged list.
@@ -151,6 +175,10 @@ export async function loadCommands(projectCwd, configDir, logger, skillsDir) {
151
175
  const globalEntries = await scanCommandDir(globalDir, logger);
152
176
  const projectEntries = await scanCommandDir(projectDir, logger);
153
177
  const map = new Map();
178
+ // Seed built-in commands first (lowest precedence)
179
+ for (const entry of BUILTIN_COMMANDS) {
180
+ map.set(entry.command, entry);
181
+ }
154
182
  for (const entry of skillEntries) {
155
183
  map.set(entry.command, entry);
156
184
  }
@@ -167,6 +195,9 @@ export async function loadCommands(projectCwd, configDir, logger, skillsDir) {
167
195
  * Returns null if the skill doesn't exist or its SKILL.md can't be parsed.
168
196
  */
169
197
  export async function resolveSkillEntry(commandName, skillsDir, logger) {
198
+ if (!isValidTelegramCommandName(commandName)) {
199
+ return null;
200
+ }
170
201
  const skillMdPath = join(skillsDir, commandName, "SKILL.md");
171
202
  if (!existsSync(skillMdPath)) {
172
203
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/bot/commands/loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/bot/commands/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Context } from "grammy";
2
+ import type { ProjectContext } from "../../types.js";
3
+ /**
4
+ * Returns a handler for the /new and /clean commands.
5
+ * Resets the session without wiping uploads/downloads.
6
+ *
7
+ * - Claude (and other engines): passive reset — delete session.json, static reply.
8
+ * - Copilot, Codex: active reset — send sessionMsg without continue flag, reply with engine output.
9
+ */
10
+ export declare function createSessionHandler(ctx: ProjectContext): (gramCtx: Context) => Promise<void>;
11
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/bot/commands/session.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,cAAc,IACxC,SAAS,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC,CAkE/C"}
@@ -0,0 +1,65 @@
1
+ import { join } from "node:path";
2
+ import { createAgent } from "../../agent/index.js";
3
+ import { sendChunkedResponse } from "../../telegram/chunker.js";
4
+ import { clearSessionData } from "../../user/setup.js";
5
+ /**
6
+ * Returns a handler for the /new and /clean commands.
7
+ * Resets the session without wiping uploads/downloads.
8
+ *
9
+ * - Claude (and other engines): passive reset — delete session.json, static reply.
10
+ * - Copilot, Codex: active reset — send sessionMsg without continue flag, reply with engine output.
11
+ */
12
+ export function createSessionHandler(ctx) {
13
+ return async (gramCtx) => {
14
+ const { config, logger } = ctx;
15
+ const userId = gramCtx.from?.id;
16
+ if (!userId) {
17
+ await gramCtx.reply("Could not identify user.");
18
+ return;
19
+ }
20
+ const userDir = join(config.dataDir, String(userId));
21
+ try {
22
+ // Always clear local session state
23
+ await clearSessionData(userDir);
24
+ logger.info({ userId }, "Session data cleared");
25
+ if (config.engine === "copilot" || config.engine === "codex") {
26
+ // Active reset: send sessionMsg without --continue to force a new session
27
+ const statusMsg = await gramCtx.reply("_Starting new session..._", {
28
+ parse_mode: "Markdown",
29
+ });
30
+ try {
31
+ const agent = createAgent(ctx);
32
+ const result = await agent.call(config.engineSessionMsg, {
33
+ continueSession: false,
34
+ });
35
+ try {
36
+ await gramCtx.api.deleteMessage(gramCtx.chat.id, statusMsg.message_id);
37
+ }
38
+ catch {
39
+ // Ignore delete errors
40
+ }
41
+ await sendChunkedResponse(gramCtx, result);
42
+ }
43
+ catch (err) {
44
+ try {
45
+ await gramCtx.api.deleteMessage(gramCtx.chat.id, statusMsg.message_id);
46
+ }
47
+ catch {
48
+ // Ignore delete errors
49
+ }
50
+ logger.error({ error: err instanceof Error ? err.message : String(err) }, "Session renewal engine call failed");
51
+ await gramCtx.reply("Failed to start new session. Please try again.");
52
+ }
53
+ }
54
+ else {
55
+ // Passive reset for Claude and other engines
56
+ await gramCtx.reply("New session started.");
57
+ }
58
+ }
59
+ catch (error) {
60
+ logger.error({ error: error instanceof Error ? error.message : String(error) }, "Session renewal failed");
61
+ await gramCtx.reply("Failed to start new session. Please try again.");
62
+ }
63
+ };
64
+ }
65
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/bot/commands/session.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../../src/bot/handlers/document.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAKtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA4CrD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,cAAc,IACzC,SAAS,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC,CAmH/C"}
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../../src/bot/handlers/document.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA4CrD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,cAAc,IACzC,SAAS,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC,CAqH/C"}