@marcopeg/hal 1.0.18 → 1.0.20

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 (96) hide show
  1. package/README.md +31 -6
  2. package/dist/bot/commands/git/callback.d.ts +8 -0
  3. package/dist/bot/commands/git/callback.d.ts.map +1 -0
  4. package/dist/bot/commands/git/callback.js +72 -0
  5. package/dist/bot/commands/git/callback.js.map +1 -0
  6. package/dist/bot/commands/git/clean.d.ts +4 -0
  7. package/dist/bot/commands/git/clean.d.ts.map +1 -0
  8. package/dist/bot/commands/git/clean.js +50 -0
  9. package/dist/bot/commands/git/clean.js.map +1 -0
  10. package/dist/bot/commands/git/commit.d.ts +4 -0
  11. package/dist/bot/commands/git/commit.d.ts.map +1 -0
  12. package/dist/bot/commands/git/commit.js +72 -0
  13. package/dist/bot/commands/git/commit.js.map +1 -0
  14. package/dist/bot/commands/git/exec.d.ts +6 -0
  15. package/dist/bot/commands/git/exec.d.ts.map +1 -0
  16. package/dist/bot/commands/git/exec.js +16 -0
  17. package/dist/bot/commands/git/exec.js.map +1 -0
  18. package/dist/bot/commands/git/index.d.ts +6 -0
  19. package/dist/bot/commands/git/index.d.ts.map +1 -0
  20. package/dist/bot/commands/git/index.js +6 -0
  21. package/dist/bot/commands/git/index.js.map +1 -0
  22. package/dist/bot/commands/git/init.d.ts +4 -0
  23. package/dist/bot/commands/git/init.d.ts.map +1 -0
  24. package/dist/bot/commands/git/init.js +22 -0
  25. package/dist/bot/commands/git/init.js.map +1 -0
  26. package/dist/bot/commands/git/status.d.ts +4 -0
  27. package/dist/bot/commands/git/status.d.ts.map +1 -0
  28. package/dist/bot/commands/git/status.js +18 -0
  29. package/dist/bot/commands/git/status.js.map +1 -0
  30. package/dist/bot/commands/help.js +1 -1
  31. package/dist/bot/commands/help.js.map +1 -1
  32. package/dist/bot/commands/loader.d.ts +12 -5
  33. package/dist/bot/commands/loader.d.ts.map +1 -1
  34. package/dist/bot/commands/loader.js +73 -15
  35. package/dist/bot/commands/loader.js.map +1 -1
  36. package/dist/bot/commands/message.d.ts.map +1 -1
  37. package/dist/bot/commands/message.js +49 -24
  38. package/dist/bot/commands/message.js.map +1 -1
  39. package/dist/bot/commands/reset.js +1 -1
  40. package/dist/bot/commands/reset.js.map +1 -1
  41. package/dist/bot/commands/session.d.ts +2 -2
  42. package/dist/bot/commands/session.d.ts.map +1 -1
  43. package/dist/bot/commands/session.js +7 -4
  44. package/dist/bot/commands/session.js.map +1 -1
  45. package/dist/bot/commands/start.js +2 -2
  46. package/dist/bot/commands/start.js.map +1 -1
  47. package/dist/bot/commands/watcher.d.ts +2 -1
  48. package/dist/bot/commands/watcher.d.ts.map +1 -1
  49. package/dist/bot/commands/watcher.js +2 -2
  50. package/dist/bot/commands/watcher.js.map +1 -1
  51. package/dist/bot/handlers/text.d.ts.map +1 -1
  52. package/dist/bot/handlers/text.js +7 -0
  53. package/dist/bot/handlers/text.js.map +1 -1
  54. package/dist/bot.d.ts.map +1 -1
  55. package/dist/bot.js +30 -9
  56. package/dist/bot.js.map +1 -1
  57. package/dist/cli.js +49 -19
  58. package/dist/cli.js.map +1 -1
  59. package/dist/config-watcher.d.ts +10 -0
  60. package/dist/config-watcher.d.ts.map +1 -0
  61. package/dist/config-watcher.js +49 -0
  62. package/dist/config-watcher.js.map +1 -0
  63. package/dist/config.d.ts +118 -41
  64. package/dist/config.d.ts.map +1 -1
  65. package/dist/config.js +124 -58
  66. package/dist/config.js.map +1 -1
  67. package/dist/context/resolver.d.ts +4 -0
  68. package/dist/context/resolver.d.ts.map +1 -1
  69. package/dist/context/resolver.js +8 -2
  70. package/dist/context/resolver.js.map +1 -1
  71. package/dist/default-models.d.ts +3 -0
  72. package/dist/default-models.d.ts.map +1 -0
  73. package/dist/default-models.js +16 -0
  74. package/dist/default-models.js.map +1 -0
  75. package/dist/engine/adapters/codex.d.ts.map +1 -1
  76. package/dist/engine/adapters/codex.js +25 -5
  77. package/dist/engine/adapters/codex.js.map +1 -1
  78. package/dist/engine/adapters/cursor.d.ts +3 -0
  79. package/dist/engine/adapters/cursor.d.ts.map +1 -0
  80. package/dist/engine/adapters/cursor.js +103 -0
  81. package/dist/engine/adapters/cursor.js.map +1 -0
  82. package/dist/engine/adapters/opencode.d.ts +2 -2
  83. package/dist/engine/adapters/opencode.d.ts.map +1 -1
  84. package/dist/engine/adapters/opencode.js +27 -11
  85. package/dist/engine/adapters/opencode.js.map +1 -1
  86. package/dist/engine/prompt.d.ts.map +1 -1
  87. package/dist/engine/prompt.js +8 -0
  88. package/dist/engine/prompt.js.map +1 -1
  89. package/dist/engine/registry.d.ts.map +1 -1
  90. package/dist/engine/registry.js +2 -0
  91. package/dist/engine/registry.js.map +1 -1
  92. package/dist/engine/types.d.ts +1 -1
  93. package/dist/engine/types.d.ts.map +1 -1
  94. package/dist/engine/types.js +1 -0
  95. package/dist/engine/types.js.map +1 -1
  96. package/package.json +2 -1
package/README.md CHANGED
@@ -182,6 +182,10 @@ These keys are injected for every message, even without any `context` configurat
182
182
  | `sys.time` | Current time, `HH:MM:SS` |
183
183
  | `sys.ts` | Current Unix timestamp (seconds) |
184
184
  | `sys.tz` | Timezone name (e.g. `Europe/Berlin`) |
185
+ | `engine.name` | Engine identifier (e.g. `claude`, `copilot`) |
186
+ | `engine.command` | CLI command used to invoke the engine |
187
+ | `engine.model` | AI model from config (only present when explicitly set) |
188
+ | `engine.defaultModel` | HAL default model applied (only present when `engine.model` is omitted; see [Model defaults](#model-defaults)) |
185
189
 
186
190
  #### Custom context via config
187
191
 
@@ -267,9 +271,10 @@ Default settings applied to all projects. Any setting defined in a project overr
267
271
  |-----|-------------|---------|
268
272
  | `globals.engine.name` | Engine: `claude`, `copilot`, `codex`, `opencode` | `"claude"` |
269
273
  | `globals.engine.command` | Override the CLI command path | _(engine name)_ |
270
- | `globals.engine.model` | Override the AI model | _(engine default)_ |
274
+ | `globals.engine.model` | Override the AI model (see [Model defaults](#model-defaults)) | _(per engine)_ |
271
275
  | `globals.engine.session` | Use persistent sessions (`--resume` / `--continue`) | `true` |
272
276
  | `globals.engine.sessionMsg` | Message sent when renewing session (e.g. `/clean`) | `"hi!"` |
277
+ | `globals.engine.codex.*` | Codex permission flags (see [Engine Configuration](#engine-configuration)) | all `false` |
273
278
  | `globals.logging.level` | Log level: `debug`, `info`, `warn`, `error` | `"info"` |
274
279
  | `globals.logging.flow` | Write logs to terminal | `true` |
275
280
  | `globals.logging.persist` | Write logs to file | `false` |
@@ -294,9 +299,10 @@ Each project entry creates one Telegram bot connected to one directory.
294
299
  | `access.allowedUserIds` | No | Override the global user whitelist for this bot |
295
300
  | `engine.name` | No | Override the engine for this project |
296
301
  | `engine.command` | No | Override the CLI command path |
297
- | `engine.model` | No | Override the AI model |
302
+ | `engine.model` | No | Override the AI model (see [Model defaults](#model-defaults)) |
298
303
  | `engine.session` | No | Use persistent sessions for this project |
299
304
  | `engine.sessionMsg` | No | Message used when renewing session |
305
+ | `engine.codex.*` | No | Codex permission flags (see [Engine Configuration](#engine-configuration)) |
300
306
  | `transcription.showTranscription` | No | Override transcription display |
301
307
  | `dataDir` | No | Override user data directory (see below) |
302
308
  | `context` | No | Per-project context overrides (see [Context Injection](#context-injection)) |
@@ -447,16 +453,24 @@ In this example:
447
453
  - **frontend** uses GitHub Copilot with the `gpt-5-mini` model
448
454
  - **legacy** is inactive and will be skipped at boot
449
455
 
450
- The `engine` object supports five fields:
456
+ The `engine` object supports five fields. Engine-specific sub-objects (e.g. `codex`) can be used to control permissions and behavior per engine.
451
457
 
452
458
  | Field | Description | Default |
453
459
  |-------|-------------|---------|
454
460
  | `name` | Engine identifier: `claude`, `copilot`, `codex`, `opencode` | `"claude"` |
455
461
  | `command` | Custom path to the CLI binary | _(engine name)_ |
456
- | `model` | AI model override (omit to use the engine's default) | _(engine default)_ |
462
+ | `model` | AI model override (omit for engine or HAL default; see [Model defaults](#model-defaults)) | _(per engine)_ |
457
463
  | `session` | Use persistent sessions (`--resume` / `--continue`) | `true` |
458
464
  | `sessionMsg` | Message sent when renewing session (e.g. `/clean`) | `"hi!"` |
459
465
 
466
+ When using the Codex engine, the `engine` object also accepts a `codex` block:
467
+
468
+ | Field | Description | Default |
469
+ |-------|-------------|---------|
470
+ | `codex.networkAccess` | Allow outbound network in shell commands | `false` |
471
+ | `codex.fullDiskAccess` | Unrestricted filesystem access (implies network) | `false` |
472
+ | `codex.dangerouslyEnableYolo` | Disable all sandboxing and approvals | `false` |
473
+
460
474
  #### Claude Code
461
475
 
462
476
  - **CLI:** `claude` — install and authenticate via [Claude Code CLI](https://github.com/anthropics/claude-code) (see [Prerequisites](#prerequisites)).
@@ -475,8 +489,9 @@ The `engine` object supports five fields:
475
489
 
476
490
  - **CLI:** `codex` — install and authenticate via [Codex CLI](https://github.com/openai/codex-cli) (see [Prerequisites](#prerequisites)).
477
491
  - **Project file:** `AGENTS.md`.
478
- - **Config:** `engine.name: "codex"`. Optional: `engine.command`, `engine.model` (e.g. `gpt-5.1-codex-mini`), `engine.session`, `engine.sessionMsg`.
492
+ - **Config:** `engine.name: "codex"`. Optional: `engine.command`, `engine.model` (e.g. `gpt-5.1-codex-mini`), `engine.session`, `engine.sessionMsg`, and the permission flags under `engine.codex` (see table above).
479
493
  - **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. `/clean` sends `engine.sessionMsg` without resuming, so the engine starts a new session; the engine's reply is sent to the user (same behaviour as Copilot).
494
+ - **Permission flags:** HAL always passes `--skip-git-repo-check` so Codex runs without the trusted-directory check. You can escalate via `engine.codex`: `networkAccess` (allow outbound HTTP etc.), `fullDiskAccess` (unrestricted filesystem; implies network), or `dangerouslyEnableYolo` (disable all sandboxing and approvals). Higher tiers supersede lower ones. **Warning:** Use `dangerouslyEnableYolo` only in hardened environments (e.g. Docker, VMs). The example config in `examples/hal.config.json` enables all three codex flags for the Obsidian project so you can try full permissions locally.
480
495
 
481
496
  #### GitHub Copilot Models
482
497
 
@@ -502,7 +517,16 @@ When using the `copilot` engine, the following models are available via `engine.
502
517
  | `gpt-5-mini` | OpenAI GPT-5 Mini |
503
518
  | `gpt-4.1` | OpenAI GPT-4.1 |
504
519
 
505
- If `engine.model` is omitted, the engine uses its own default model.
520
+ #### Model defaults
521
+
522
+ When `engine.model` is omitted (neither in globals nor project config), behavior depends on the engine:
523
+
524
+ - **Engine default** — Codex, Copilot, and Cursor: HAL does not pass a model flag, so the CLI picks its own default (Cursor passes `--model auto`).
525
+ - **HAL default** — Claude Code and OpenCode: HAL passes a built-in default so the engine always receives a model. Defaults are defined in `src/default-models.ts`:
526
+ - Claude Code: `default` (account-recommended model)
527
+ - OpenCode: `opencode/gpt-5-nano` (free Zen model)
528
+
529
+ To change HAL defaults, edit `src/default-models.ts`.
506
530
 
507
531
  ## Directory Structure
508
532
 
@@ -618,6 +642,7 @@ The fully-resolved context that would be sent to the AI for this message — ide
618
642
  | `bot.*` | `bot.userId`, `bot.username`, `bot.firstName`, `bot.chatId`, `bot.messageId`, `bot.timestamp`, `bot.datetime`, `bot.messageType` |
619
643
  | `sys.*` | `sys.date`, `sys.time`, `sys.datetime`, `sys.ts`, `sys.tz` |
620
644
  | `project.*` | `project.name`, `project.cwd`, `project.slug` |
645
+ | `engine.*` | `engine.name`, `engine.command`, `engine.model` (if set), `engine.defaultModel` (if HAL default applied) |
621
646
  | custom | Any keys defined in `context` config blocks, after `${}` / `#{}` / `@{}` substitution and context hook transforms |
622
647
 
623
648
  Use `/context` (the built-in global command) to inspect the exact keys available at runtime.
@@ -0,0 +1,8 @@
1
+ import type { Context, NextFunction } from "grammy";
2
+ import type { ProjectContext } from "../../../types.js";
3
+ /**
4
+ * Callback query handler for `/git_clean` inline keyboard interactions.
5
+ * Recognizes data prefixed with `gc:` and ignores all other callbacks.
6
+ */
7
+ export declare function createGitCallbackHandler(ctx: ProjectContext): (gramCtx: Context, next: NextFunction) => Promise<void>;
8
+ //# sourceMappingURL=callback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["../../../../src/bot/commands/git/callback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,cAAc,IAC5C,SAAS,OAAO,EAAE,MAAM,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CA8EnE"}
@@ -0,0 +1,72 @@
1
+ import { InlineKeyboard } from "grammy";
2
+ import { gitExec } from "./exec.js";
3
+ /**
4
+ * Callback query handler for `/git_clean` inline keyboard interactions.
5
+ * Recognizes data prefixed with `gc:` and ignores all other callbacks.
6
+ */
7
+ export function createGitCallbackHandler(ctx) {
8
+ return async (gramCtx, next) => {
9
+ const data = gramCtx.callbackQuery?.data;
10
+ if (!data?.startsWith("gc:")) {
11
+ return next();
12
+ }
13
+ const { config, logger } = ctx;
14
+ const cwd = config.cwd;
15
+ try {
16
+ if (data.startsWith("gc:select:")) {
17
+ const file = data.slice("gc:select:".length);
18
+ const keyboard = new InlineKeyboard()
19
+ .text("Confirm", `gc:confirm:${file}`)
20
+ .text("Cancel", "gc:cancel");
21
+ await gramCtx.editMessageText(`Revert \`${file}\` and lose the changes?`, { parse_mode: "Markdown", reply_markup: keyboard });
22
+ await gramCtx.answerCallbackQuery();
23
+ return;
24
+ }
25
+ if (data === "gc:all") {
26
+ const keyboard = new InlineKeyboard()
27
+ .text("Confirm", "gc:confirm:__all__")
28
+ .text("Cancel", "gc:cancel");
29
+ await gramCtx.editMessageText("Revert *all* uncommitted changes and lose them?", { parse_mode: "Markdown", reply_markup: keyboard });
30
+ await gramCtx.answerCallbackQuery();
31
+ return;
32
+ }
33
+ if (data.startsWith("gc:confirm:")) {
34
+ const target = data.slice("gc:confirm:".length);
35
+ if (target === "__all__") {
36
+ await gitExec(cwd, ["restore", "."]);
37
+ // Also clean untracked files
38
+ await gitExec(cwd, ["clean", "-fd"]).catch(() => { });
39
+ await gramCtx.editMessageText("All uncommitted changes reverted.", {
40
+ reply_markup: undefined,
41
+ });
42
+ }
43
+ else {
44
+ await gitExec(cwd, ["restore", target]);
45
+ await gramCtx.editMessageText(`Restored \`${target}\`.`, {
46
+ parse_mode: "Markdown",
47
+ reply_markup: undefined,
48
+ });
49
+ }
50
+ await gramCtx.answerCallbackQuery();
51
+ return;
52
+ }
53
+ if (data === "gc:cancel") {
54
+ await gramCtx.editMessageText("Cancelled.", {
55
+ reply_markup: undefined,
56
+ });
57
+ await gramCtx.answerCallbackQuery();
58
+ return;
59
+ }
60
+ }
61
+ catch (err) {
62
+ logger.error({ data, error: err instanceof Error ? err.message : String(err) }, "git_clean callback failed");
63
+ try {
64
+ await gramCtx.answerCallbackQuery({ text: "Operation failed." });
65
+ }
66
+ catch {
67
+ // ignore
68
+ }
69
+ }
70
+ };
71
+ }
72
+ //# sourceMappingURL=callback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callback.js","sourceRoot":"","sources":["../../../../src/bot/commands/git/callback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Context } from "grammy";
2
+ import type { ProjectContext } from "../../../types.js";
3
+ export declare function createGitCleanHandler(ctx: ProjectContext): (gramCtx: Context) => Promise<void>;
4
+ //# sourceMappingURL=clean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["../../../../src/bot/commands/git/clean.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAYxD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,cAAc,IACzC,SAAS,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC,CAkD/C"}
@@ -0,0 +1,50 @@
1
+ import { InlineKeyboard } from "grammy";
2
+ import { gitExec } from "./exec.js";
3
+ /** Parse `git status --short` into a list of file paths. */
4
+ function parseChangedFiles(statusOutput) {
5
+ return statusOutput
6
+ .split("\n")
7
+ .map((line) => line.trim())
8
+ .filter(Boolean)
9
+ .map((line) => line.slice(3)); // strip status flags + space (e.g. " M src/file.ts")
10
+ }
11
+ export function createGitCleanHandler(ctx) {
12
+ return async (gramCtx) => {
13
+ const { config, logger } = ctx;
14
+ const cwd = config.cwd;
15
+ const messageText = gramCtx.message?.text ?? "";
16
+ const fileArg = messageText.replace(/^\/git_clean\s*/, "").trim();
17
+ try {
18
+ const { stdout } = await gitExec(cwd, ["status", "--short"]);
19
+ const files = parseChangedFiles(stdout);
20
+ if (files.length === 0) {
21
+ await gramCtx.reply("Working tree is clean.");
22
+ return;
23
+ }
24
+ if (fileArg) {
25
+ if (!files.includes(fileArg)) {
26
+ await gramCtx.reply(`File \`${fileArg}\` has no uncommitted changes.`, { parse_mode: "Markdown" });
27
+ return;
28
+ }
29
+ await gitExec(cwd, ["restore", fileArg]);
30
+ await gramCtx.reply(`Restored \`${fileArg}\`.`, {
31
+ parse_mode: "Markdown",
32
+ });
33
+ return;
34
+ }
35
+ const keyboard = new InlineKeyboard();
36
+ for (const file of files) {
37
+ keyboard.text(file, `gc:select:${file}`).row();
38
+ }
39
+ keyboard.text("Reset all", "gc:all").row();
40
+ await gramCtx.reply("Select file(s) to revert:", {
41
+ reply_markup: keyboard,
42
+ });
43
+ }
44
+ catch (err) {
45
+ logger.error({ error: err instanceof Error ? err.message : String(err) }, "/git_clean failed");
46
+ await gramCtx.reply(`Failed to check changes: ${err instanceof Error ? err.message : String(err)}`);
47
+ }
48
+ };
49
+ }
50
+ //# sourceMappingURL=clean.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.js","sourceRoot":"","sources":["../../../../src/bot/commands/git/clean.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,4DAA4D;AAC5D,SAAS,iBAAiB,CAAC,YAAoB;IAC7C,OAAO,YAAY;SAChB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qDAAqD;AACxF,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAmB;IACvD,OAAO,KAAK,EAAE,OAAgB,EAAiB,EAAE;QAC/C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;QAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QACvB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAElE,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;YAC7D,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAExC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;gBAC9C,OAAO;YACT,CAAC;YAED,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC7B,MAAM,OAAO,CAAC,KAAK,CACjB,UAAU,OAAO,gCAAgC,EACjD,EAAE,UAAU,EAAE,UAAU,EAAE,CAC3B,CAAC;oBACF,OAAO;gBACT,CAAC;gBAED,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;gBACzC,MAAM,OAAO,CAAC,KAAK,CAAC,cAAc,OAAO,KAAK,EAAE;oBAC9C,UAAU,EAAE,UAAU;iBACvB,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;YACjD,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;YAE3C,MAAM,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE;gBAC/C,YAAY,EAAE,QAAQ;aACvB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CACV,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAC3D,mBAAmB,CACpB,CAAC;YACF,MAAM,OAAO,CAAC,KAAK,CACjB,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC/E,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Context } from "grammy";
2
+ import type { ProjectContext } from "../../../types.js";
3
+ export declare function createGitCommitHandler(ctx: ProjectContext): (gramCtx: Context) => Promise<void>;
4
+ //# sourceMappingURL=commit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../../../../src/bot/commands/git/commit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAOxD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,cAAc,IAC1C,SAAS,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC,CAyF/C"}
@@ -0,0 +1,72 @@
1
+ import { createAgent } from "../../../agent/index.js";
2
+ import { gitExec } from "./exec.js";
3
+ const COMMIT_MSG_PROMPT = `Generate a concise git commit message (one line, max 72 chars) for the following changes. Return ONLY the commit message, no quotes or explanation.
4
+
5
+ `;
6
+ export function createGitCommitHandler(ctx) {
7
+ return async (gramCtx) => {
8
+ const { config, logger } = ctx;
9
+ const cwd = config.cwd;
10
+ const messageText = gramCtx.message?.text ?? "";
11
+ const userMessage = messageText.replace(/^\/git_commit\s*/, "").trim();
12
+ try {
13
+ await gitExec(cwd, ["add", "."]);
14
+ const { stdout: statusOut } = await gitExec(cwd, [
15
+ "status",
16
+ "--porcelain",
17
+ ]);
18
+ if (!statusOut.trim()) {
19
+ await gramCtx.reply("Nothing to commit — working tree is clean.");
20
+ return;
21
+ }
22
+ let commitMessage;
23
+ if (userMessage) {
24
+ commitMessage = userMessage;
25
+ }
26
+ else {
27
+ const statusMsg = await gramCtx.reply("_Generating commit message..._", { parse_mode: "Markdown" });
28
+ try {
29
+ const { stdout: diffOut } = await gitExec(cwd, [
30
+ "diff",
31
+ "--cached",
32
+ "--stat",
33
+ ]);
34
+ const agent = createAgent(ctx);
35
+ const generated = await agent.call(`${COMMIT_MSG_PROMPT}${diffOut || statusOut}`);
36
+ commitMessage = generated.trim().replace(/^["']|["']$/g, "");
37
+ try {
38
+ await gramCtx.api.deleteMessage(gramCtx.chat.id, statusMsg.message_id);
39
+ }
40
+ catch {
41
+ // ignore delete errors
42
+ }
43
+ }
44
+ catch (err) {
45
+ try {
46
+ await gramCtx.api.deleteMessage(gramCtx.chat.id, statusMsg.message_id);
47
+ }
48
+ catch {
49
+ // ignore delete errors
50
+ }
51
+ logger.error({ error: err instanceof Error ? err.message : String(err) }, "AI commit message generation failed");
52
+ await gramCtx.reply("Failed to generate commit message. Please provide one:\n`/git_commit your message here`", { parse_mode: "Markdown" });
53
+ return;
54
+ }
55
+ }
56
+ const { stdout: commitOut } = await gitExec(cwd, [
57
+ "commit",
58
+ "-m",
59
+ commitMessage,
60
+ ]);
61
+ const summary = commitOut.trim().split("\n")[0] ?? "Committed.";
62
+ await gramCtx.reply(`\`\`\`\n${summary}\n\`\`\``, {
63
+ parse_mode: "Markdown",
64
+ });
65
+ }
66
+ catch (err) {
67
+ logger.error({ error: err instanceof Error ? err.message : String(err) }, "/git_commit failed");
68
+ await gramCtx.reply(`Commit failed: ${err instanceof Error ? err.message : String(err)}`);
69
+ }
70
+ };
71
+ }
72
+ //# sourceMappingURL=commit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit.js","sourceRoot":"","sources":["../../../../src/bot/commands/git/commit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function gitExec(cwd: string, args: string[]): Promise<{
2
+ stdout: string;
3
+ stderr: string;
4
+ }>;
5
+ export declare function isGitRepo(cwd: string): Promise<boolean>;
6
+ //# sourceMappingURL=exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../../../src/bot/commands/git/exec.ts"],"names":[],"mappings":"AAKA,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAE7C;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7D"}
@@ -0,0 +1,16 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ const execFileAsync = promisify(execFile);
4
+ export async function gitExec(cwd, args) {
5
+ return execFileAsync("git", args, { cwd, timeout: 30_000 });
6
+ }
7
+ export async function isGitRepo(cwd) {
8
+ try {
9
+ await gitExec(cwd, ["rev-parse", "--is-inside-work-tree"]);
10
+ return true;
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ }
16
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../../src/bot/commands/git/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,GAAW,EACX,IAAc;IAEd,OAAO,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { createGitCallbackHandler } from "./callback.js";
2
+ export { createGitCleanHandler } from "./clean.js";
3
+ export { createGitCommitHandler } from "./commit.js";
4
+ export { createGitInitHandler } from "./init.js";
5
+ export { createGitStatusHandler } from "./status.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/bot/commands/git/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { createGitCallbackHandler } from "./callback.js";
2
+ export { createGitCleanHandler } from "./clean.js";
3
+ export { createGitCommitHandler } from "./commit.js";
4
+ export { createGitInitHandler } from "./init.js";
5
+ export { createGitStatusHandler } from "./status.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/bot/commands/git/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Context } from "grammy";
2
+ import type { ProjectContext } from "../../../types.js";
3
+ export declare function createGitInitHandler(ctx: ProjectContext): (gramCtx: Context) => Promise<void>;
4
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/bot/commands/git/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,cAAc,IACxC,SAAS,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC,CAyB/C"}
@@ -0,0 +1,22 @@
1
+ import { gitExec, isGitRepo } from "./exec.js";
2
+ export function createGitInitHandler(ctx) {
3
+ return async (gramCtx) => {
4
+ const { config, logger } = ctx;
5
+ const cwd = config.cwd;
6
+ try {
7
+ if (await isGitRepo(cwd)) {
8
+ await gramCtx.reply("Already a git repository.");
9
+ return;
10
+ }
11
+ await gitExec(cwd, ["init"]);
12
+ await gitExec(cwd, ["add", "."]);
13
+ await gitExec(cwd, ["commit", "-m", "Initial commit"]);
14
+ await gramCtx.reply("Git repository initialized with initial commit.");
15
+ }
16
+ catch (err) {
17
+ logger.error({ error: err instanceof Error ? err.message : String(err) }, "/git_init failed");
18
+ await gramCtx.reply(`Failed to initialize git repository: ${err instanceof Error ? err.message : String(err)}`);
19
+ }
20
+ };
21
+ }
22
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../src/bot/commands/git/init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,UAAU,oBAAoB,CAAC,GAAmB;IACtD,OAAO,KAAK,EAAE,OAAgB,EAAiB,EAAE;QAC/C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;QAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QAEvB,IAAI,CAAC;YACH,IAAI,MAAM,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;gBACjD,OAAO;YACT,CAAC;YAED,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;YAC7B,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;YACjC,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC;YAEvD,MAAM,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CACV,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAC3D,kBAAkB,CACnB,CAAC;YACF,MAAM,OAAO,CAAC,KAAK,CACjB,wCAAwC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC3F,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Context } from "grammy";
2
+ import type { ProjectContext } from "../../../types.js";
3
+ export declare function createGitStatusHandler(ctx: ProjectContext): (gramCtx: Context) => Promise<void>;
4
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../../src/bot/commands/git/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,cAAc,IAC1C,SAAS,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC,CAmB/C"}
@@ -0,0 +1,18 @@
1
+ import { gitExec } from "./exec.js";
2
+ export function createGitStatusHandler(ctx) {
3
+ return async (gramCtx) => {
4
+ const { config, logger } = ctx;
5
+ try {
6
+ const { stdout } = await gitExec(config.cwd, ["status"]);
7
+ const output = stdout.trim() || "Nothing to report.";
8
+ await gramCtx.reply(`\`\`\`\n${output}\n\`\`\``, {
9
+ parse_mode: "Markdown",
10
+ });
11
+ }
12
+ catch (err) {
13
+ logger.error({ error: err instanceof Error ? err.message : String(err) }, "/git_status failed");
14
+ await gramCtx.reply(`Failed to get git status: ${err instanceof Error ? err.message : String(err)}`);
15
+ }
16
+ };
17
+ }
18
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/bot/commands/git/status.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,UAAU,sBAAsB,CAAC,GAAmB;IACxD,OAAO,KAAK,EAAE,OAAgB,EAAiB,EAAE;QAC/C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;QAE/B,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,oBAAoB,CAAC;YACrD,MAAM,OAAO,CAAC,KAAK,CAAC,WAAW,MAAM,UAAU,EAAE;gBAC/C,UAAU,EAAE,UAAU;aACvB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CACV,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAC3D,oBAAoB,CACrB,CAAC;YACF,MAAM,OAAO,CAAC,KAAK,CACjB,6BAA6B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAChF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -4,7 +4,7 @@ const DEFAULT_TEMPLATE = "${HAL_COMMANDS}";
4
4
  export function createHelpHandler(ctx) {
5
5
  return async (gramCtx) => {
6
6
  const helpCfg = ctx.config.commands.help;
7
- const template = helpCfg?.message ?? DEFAULT_TEMPLATE;
7
+ const template = helpCfg.message ?? DEFAULT_TEMPLATE;
8
8
  const message = await resolveCommandMessage(template, ctx, gramCtx);
9
9
  await gramCtx.reply(message, { parse_mode: "Markdown" });
10
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/bot/commands/help.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,gGAAgG;AAChG,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAE3C,MAAM,UAAU,iBAAiB,CAAC,GAAmB;IACnD,OAAO,KAAK,EAAE,OAAgB,EAAiB,EAAE;QAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAEzC,MAAM,QAAQ,GAAG,OAAO,EAAE,OAAO,IAAI,gBAAgB,CAAC;QACtD,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/bot/commands/help.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,gGAAgG;AAChG,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAE3C,MAAM,UAAU,iBAAiB,CAAC,GAAmB;IACnD,OAAO,KAAK,EAAE,OAAgB,EAAiB,EAAE;QAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAEzC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;QACrD,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC;AACJ,CAAC"}
@@ -1,23 +1,30 @@
1
1
  import type pino from "pino";
2
+ export type CommandSource = "builtin" | "git" | "project" | "system" | "skill";
2
3
  export interface CommandEntry {
3
4
  command: string;
4
5
  description: string;
5
6
  filePath: string;
6
7
  skillPrompt?: string;
7
8
  public?: boolean;
9
+ source: CommandSource;
10
+ }
11
+ export interface CommandEnabledFlags {
12
+ start: boolean;
13
+ help: boolean;
14
+ reset: boolean;
15
+ clean: boolean;
16
+ git: boolean;
8
17
  }
9
- /**
10
- * Commands that are always registered with Telegram, regardless of
11
- * whether custom .mjs files or skills exist.
12
- */
13
18
  export declare const BUILTIN_COMMANDS: CommandEntry[];
19
+ export declare const GIT_COMMANDS: CommandEntry[];
14
20
  /**
15
21
  * Scan command directories and optionally the skills dir, then return the merged list.
22
+ * When `enabled` flags are provided, disabled built-in/git commands are excluded.
16
23
  *
17
24
  * Precedence (lowest → highest):
18
25
  * engine skills < global .hal/commands < project .hal/commands
19
26
  */
20
- export declare function loadCommands(projectCwd: string, configDir: string, logger: pino.Logger, skillsDir?: string): Promise<CommandEntry[]>;
27
+ export declare function loadCommands(projectCwd: string, configDir: string, logger: pino.Logger, skillsDir?: string, enabled?: CommandEnabledFlags): Promise<CommandEntry[]>;
21
28
  /**
22
29
  * Resolve a skill entry by command name from the engine's skills directory.
23
30
  * Returns null if the skill doesn't exist or its SKILL.md can't be parsed.
@@ -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;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAmOD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,YAAY,EAS1C,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
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/bot/commands/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAI7B,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;CACd;AAuOD,eAAO,MAAM,gBAAgB,EAAE,YAAY,EAyB1C,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,YAAY,EAyBtC,CAAC;AAWF;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,YAAY,EAAE,CAAC,CAuCzB;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,CA6B9B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAcf"}