@marcopeg/hal 1.0.11

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 (106) hide show
  1. package/README.md +655 -0
  2. package/dist/agent/index.d.ts +17 -0
  3. package/dist/agent/index.d.ts.map +1 -0
  4. package/dist/agent/index.js +30 -0
  5. package/dist/agent/index.js.map +1 -0
  6. package/dist/bot/commands/clear.d.ts +7 -0
  7. package/dist/bot/commands/clear.d.ts.map +1 -0
  8. package/dist/bot/commands/clear.js +23 -0
  9. package/dist/bot/commands/clear.js.map +1 -0
  10. package/dist/bot/commands/help.d.ts +3 -0
  11. package/dist/bot/commands/help.d.ts.map +1 -0
  12. package/dist/bot/commands/help.js +16 -0
  13. package/dist/bot/commands/help.js.map +1 -0
  14. package/dist/bot/commands/loader.d.ts +26 -0
  15. package/dist/bot/commands/loader.d.ts.map +1 -0
  16. package/dist/bot/commands/loader.js +206 -0
  17. package/dist/bot/commands/loader.js.map +1 -0
  18. package/dist/bot/commands/start.d.ts +3 -0
  19. package/dist/bot/commands/start.d.ts.map +1 -0
  20. package/dist/bot/commands/start.js +10 -0
  21. package/dist/bot/commands/start.js.map +1 -0
  22. package/dist/bot/commands/watcher.d.ts +11 -0
  23. package/dist/bot/commands/watcher.d.ts.map +1 -0
  24. package/dist/bot/commands/watcher.js +106 -0
  25. package/dist/bot/commands/watcher.js.map +1 -0
  26. package/dist/bot/handlers/document.d.ts +7 -0
  27. package/dist/bot/handlers/document.d.ts.map +1 -0
  28. package/dist/bot/handlers/document.js +128 -0
  29. package/dist/bot/handlers/document.js.map +1 -0
  30. package/dist/bot/handlers/index.d.ts +5 -0
  31. package/dist/bot/handlers/index.d.ts.map +1 -0
  32. package/dist/bot/handlers/index.js +5 -0
  33. package/dist/bot/handlers/index.js.map +1 -0
  34. package/dist/bot/handlers/photo.d.ts +7 -0
  35. package/dist/bot/handlers/photo.d.ts.map +1 -0
  36. package/dist/bot/handlers/photo.js +87 -0
  37. package/dist/bot/handlers/photo.js.map +1 -0
  38. package/dist/bot/handlers/text.d.ts +7 -0
  39. package/dist/bot/handlers/text.d.ts.map +1 -0
  40. package/dist/bot/handlers/text.js +186 -0
  41. package/dist/bot/handlers/text.js.map +1 -0
  42. package/dist/bot/handlers/voice.d.ts +7 -0
  43. package/dist/bot/handlers/voice.d.ts.map +1 -0
  44. package/dist/bot/handlers/voice.js +147 -0
  45. package/dist/bot/handlers/voice.js.map +1 -0
  46. package/dist/bot/middleware/auth.d.ts +7 -0
  47. package/dist/bot/middleware/auth.d.ts.map +1 -0
  48. package/dist/bot/middleware/auth.js +23 -0
  49. package/dist/bot/middleware/auth.js.map +1 -0
  50. package/dist/bot/middleware/rateLimit.d.ts +11 -0
  51. package/dist/bot/middleware/rateLimit.d.ts.map +1 -0
  52. package/dist/bot/middleware/rateLimit.js +49 -0
  53. package/dist/bot/middleware/rateLimit.js.map +1 -0
  54. package/dist/bot.d.ts +11 -0
  55. package/dist/bot.d.ts.map +1 -0
  56. package/dist/bot.js +93 -0
  57. package/dist/bot.js.map +1 -0
  58. package/dist/claude/executor.d.ts +21 -0
  59. package/dist/claude/executor.d.ts.map +1 -0
  60. package/dist/claude/executor.js +185 -0
  61. package/dist/claude/executor.js.map +1 -0
  62. package/dist/claude/parser.d.ts +13 -0
  63. package/dist/claude/parser.d.ts.map +1 -0
  64. package/dist/claude/parser.js +63 -0
  65. package/dist/claude/parser.js.map +1 -0
  66. package/dist/cli.d.ts +3 -0
  67. package/dist/cli.d.ts.map +1 -0
  68. package/dist/cli.js +192 -0
  69. package/dist/cli.js.map +1 -0
  70. package/dist/config.d.ts +216 -0
  71. package/dist/config.d.ts.map +1 -0
  72. package/dist/config.js +396 -0
  73. package/dist/config.js.map +1 -0
  74. package/dist/context/resolver.d.ts +19 -0
  75. package/dist/context/resolver.d.ts.map +1 -0
  76. package/dist/context/resolver.js +171 -0
  77. package/dist/context/resolver.js.map +1 -0
  78. package/dist/index.d.ts +7 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +5 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/logger.d.ts +17 -0
  83. package/dist/logger.d.ts.map +1 -0
  84. package/dist/logger.js +44 -0
  85. package/dist/logger.js.map +1 -0
  86. package/dist/telegram/chunker.d.ts +10 -0
  87. package/dist/telegram/chunker.d.ts.map +1 -0
  88. package/dist/telegram/chunker.js +88 -0
  89. package/dist/telegram/chunker.js.map +1 -0
  90. package/dist/telegram/fileSender.d.ts +8 -0
  91. package/dist/telegram/fileSender.d.ts.map +1 -0
  92. package/dist/telegram/fileSender.js +46 -0
  93. package/dist/telegram/fileSender.js.map +1 -0
  94. package/dist/transcription/whisper.d.ts +11 -0
  95. package/dist/transcription/whisper.d.ts.map +1 -0
  96. package/dist/transcription/whisper.js +58 -0
  97. package/dist/transcription/whisper.js.map +1 -0
  98. package/dist/types.d.ts +22 -0
  99. package/dist/types.d.ts.map +1 -0
  100. package/dist/types.js +2 -0
  101. package/dist/types.js.map +1 -0
  102. package/dist/user/setup.d.ts +26 -0
  103. package/dist/user/setup.d.ts.map +1 -0
  104. package/dist/user/setup.js +73 -0
  105. package/dist/user/setup.js.map +1 -0
  106. package/package.json +56 -0
@@ -0,0 +1,17 @@
1
+ import pino from "pino";
2
+ import type { ResolvedProjectConfig } from "./config.js";
3
+ /**
4
+ * A startup logger for CLI-level messages. Always writes to stdout at info level.
5
+ * Used before per-project loggers are created, and for process-level notices.
6
+ */
7
+ export declare function createStartupLogger(): pino.Logger;
8
+ /**
9
+ * Create a per-project logger that respects flow and persist settings.
10
+ *
11
+ * - flow: false → no terminal output
12
+ * - persist: true → append to <logDir>/YYYY-MM-DD.txt
13
+ *
14
+ * If both are false/disabled, a no-op stream is used to keep the logger valid.
15
+ */
16
+ export declare function createProjectLogger(config: ResolvedProjectConfig): pino.Logger;
17
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAGA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAAC,MAAM,CAEjD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,qBAAqB,GAC5B,IAAI,CAAC,MAAM,CA4Bb"}
package/dist/logger.js ADDED
@@ -0,0 +1,44 @@
1
+ import { createWriteStream, mkdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { Writable } from "node:stream";
4
+ import pino from "pino";
5
+ /**
6
+ * A startup logger for CLI-level messages. Always writes to stdout at info level.
7
+ * Used before per-project loggers are created, and for process-level notices.
8
+ */
9
+ export function createStartupLogger() {
10
+ return pino({ level: "info" });
11
+ }
12
+ /**
13
+ * Create a per-project logger that respects flow and persist settings.
14
+ *
15
+ * - flow: false → no terminal output
16
+ * - persist: true → append to <logDir>/YYYY-MM-DD.txt
17
+ *
18
+ * If both are false/disabled, a no-op stream is used to keep the logger valid.
19
+ */
20
+ export function createProjectLogger(config) {
21
+ const { level, flow, persist } = config.logging;
22
+ const streams = [];
23
+ if (flow) {
24
+ streams.push({ stream: process.stdout });
25
+ }
26
+ if (persist) {
27
+ mkdirSync(config.logDir, { recursive: true });
28
+ const date = new Date().toISOString().slice(0, 10); // YYYY-MM-DD
29
+ const logFile = join(config.logDir, `${date}.txt`);
30
+ streams.push({ stream: createWriteStream(logFile, { flags: "a" }) });
31
+ }
32
+ if (streams.length === 0) {
33
+ // Both flow and persist are off — use a no-op sink so the logger is valid
34
+ streams.push({
35
+ stream: new Writable({
36
+ write(_chunk, _enc, cb) {
37
+ cb();
38
+ },
39
+ }),
40
+ });
41
+ }
42
+ return pino({ level }, pino.multistream(streams));
43
+ }
44
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAA6B;IAE7B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC;IAEhD,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa;QACjE,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,0EAA0E;QAC1E,OAAO,CAAC,IAAI,CAAC;YACX,MAAM,EAAE,IAAI,QAAQ,CAAC;gBACnB,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;oBACpB,EAAE,EAAE,CAAC;gBACP,CAAC;aACF,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Context } from "grammy";
2
+ /**
3
+ * Split a long message into chunks that fit Telegram's limits
4
+ */
5
+ export declare function chunkMessage(text: string): string[];
6
+ /**
7
+ * Send a potentially long response as multiple messages
8
+ */
9
+ export declare function sendChunkedResponse(ctx: Context, text: string): Promise<void>;
10
+ //# sourceMappingURL=chunker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunker.d.ts","sourceRoot":"","sources":["../../src/telegram/chunker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAqCtC;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBnD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAmCf"}
@@ -0,0 +1,88 @@
1
+ const TELEGRAM_MAX_LENGTH = 4096;
2
+ /**
3
+ * Find a safe split point in text, trying to avoid breaking code blocks
4
+ */
5
+ function findSafeSplitPoint(text, maxLength) {
6
+ if (text.length <= maxLength) {
7
+ return text.length;
8
+ }
9
+ // Try to find a good split point
10
+ const searchText = text.slice(0, maxLength);
11
+ // Try to split at a double newline (paragraph break)
12
+ const doubleNewline = searchText.lastIndexOf("\n\n");
13
+ if (doubleNewline > maxLength * 0.5) {
14
+ return doubleNewline + 2;
15
+ }
16
+ // Try to split at a single newline
17
+ const newline = searchText.lastIndexOf("\n");
18
+ if (newline > maxLength * 0.5) {
19
+ return newline + 1;
20
+ }
21
+ // Try to split at a space
22
+ const space = searchText.lastIndexOf(" ");
23
+ if (space > maxLength * 0.5) {
24
+ return space + 1;
25
+ }
26
+ // Fall back to hard split at max length
27
+ return maxLength;
28
+ }
29
+ /**
30
+ * Split a long message into chunks that fit Telegram's limits
31
+ */
32
+ export function chunkMessage(text) {
33
+ if (text.length <= TELEGRAM_MAX_LENGTH) {
34
+ return [text];
35
+ }
36
+ const chunks = [];
37
+ let remaining = text;
38
+ while (remaining.length > 0) {
39
+ if (remaining.length <= TELEGRAM_MAX_LENGTH) {
40
+ chunks.push(remaining);
41
+ break;
42
+ }
43
+ const splitPoint = findSafeSplitPoint(remaining, TELEGRAM_MAX_LENGTH);
44
+ chunks.push(remaining.slice(0, splitPoint));
45
+ remaining = remaining.slice(splitPoint);
46
+ }
47
+ return chunks;
48
+ }
49
+ /**
50
+ * Send a potentially long response as multiple messages
51
+ */
52
+ export async function sendChunkedResponse(ctx, text) {
53
+ const chunks = chunkMessage(text);
54
+ for (let i = 0; i < chunks.length; i++) {
55
+ const chunk = chunks[i];
56
+ // Add continuation indicator for multi-part messages
57
+ let messageText = chunk;
58
+ if (chunks.length > 1) {
59
+ if (i === 0) {
60
+ messageText = `${chunk}\n\n_(continued...)_`;
61
+ }
62
+ else if (i < chunks.length - 1) {
63
+ messageText = `_(part ${i + 1})_\n\n${chunk}\n\n_(continued...)_`;
64
+ }
65
+ else {
66
+ messageText = `_(part ${i + 1})_\n\n${chunk}`;
67
+ }
68
+ }
69
+ try {
70
+ await ctx.reply(messageText, { parse_mode: "Markdown" });
71
+ }
72
+ catch {
73
+ // If Markdown fails, try without parsing
74
+ try {
75
+ await ctx.reply(chunk);
76
+ }
77
+ catch (_error) {
78
+ // Last resort: send error message
79
+ await ctx.reply(`Error sending message part ${i + 1}`);
80
+ }
81
+ }
82
+ // Small delay between chunks to avoid rate limiting
83
+ if (i < chunks.length - 1) {
84
+ await new Promise((resolve) => setTimeout(resolve, 500));
85
+ }
86
+ }
87
+ }
88
+ //# sourceMappingURL=chunker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunker.js","sourceRoot":"","sources":["../../src/telegram/chunker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Context } from "grammy";
2
+ import type { ProjectContext } from "../types.js";
3
+ /**
4
+ * Send all files from the user's downloads folder and delete them after sending.
5
+ * Returns the number of files sent.
6
+ */
7
+ export declare function sendDownloadFiles(gramCtx: Context, userDir: string, ctx: ProjectContext): Promise<number>;
8
+ //# sourceMappingURL=fileSender.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileSender.d.ts","sourceRoot":"","sources":["../../src/telegram/fileSender.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,MAAM,CAAC,CA8CjB"}
@@ -0,0 +1,46 @@
1
+ import { readdir, unlink } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { InputFile } from "grammy";
4
+ import { getDownloadsPath } from "../user/setup.js";
5
+ /**
6
+ * Send all files from the user's downloads folder and delete them after sending.
7
+ * Returns the number of files sent.
8
+ */
9
+ export async function sendDownloadFiles(gramCtx, userDir, ctx) {
10
+ const { logger } = ctx;
11
+ const downloadsPath = getDownloadsPath(userDir);
12
+ let files;
13
+ try {
14
+ files = await readdir(downloadsPath);
15
+ }
16
+ catch {
17
+ // Directory doesn't exist or can't be read
18
+ return 0;
19
+ }
20
+ if (files.length === 0) {
21
+ return 0;
22
+ }
23
+ let sentCount = 0;
24
+ for (const fileName of files) {
25
+ const filePath = join(downloadsPath, fileName);
26
+ try {
27
+ // Send the file
28
+ await gramCtx.replyWithDocument(new InputFile(filePath, fileName));
29
+ logger.info({ fileName }, "Sent file to user");
30
+ // Delete the file after successful send
31
+ await unlink(filePath);
32
+ logger.debug({ fileName }, "Deleted sent file");
33
+ sentCount++;
34
+ }
35
+ catch (error) {
36
+ logger.error({ error, fileName }, "Failed to send file, keeping it for retry");
37
+ // Don't delete on failure - keep for potential retry
38
+ }
39
+ // Small delay between files to avoid rate limiting
40
+ if (sentCount < files.length) {
41
+ await new Promise((resolve) => setTimeout(resolve, 500));
42
+ }
43
+ }
44
+ return sentCount;
45
+ }
46
+ //# sourceMappingURL=fileSender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileSender.js","sourceRoot":"","sources":["../../src/telegram/fileSender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAgB,EAChB,OAAe,EACf,GAAmB;IAEnB,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IACvB,MAAM,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAEhD,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,2CAA2C;QAC3C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAE/C,IAAI,CAAC;YACH,gBAAgB;YAChB,MAAM,OAAO,CAAC,iBAAiB,CAAC,IAAI,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;YACnE,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,mBAAmB,CAAC,CAAC;YAE/C,wCAAwC;YACxC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;YACvB,MAAM,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,mBAAmB,CAAC,CAAC;YAEhD,SAAS,EAAE,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CACV,EAAE,KAAK,EAAE,QAAQ,EAAE,EACnB,2CAA2C,CAC5C,CAAC;YACF,qDAAqD;QACvD,CAAC;QAED,mDAAmD;QACnD,IAAI,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC7B,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { ProjectContext } from "../types.js";
2
+ export interface TranscriptionResult {
3
+ text: string;
4
+ language?: string;
5
+ duration?: number;
6
+ }
7
+ /**
8
+ * Transcribe audio file using local Whisper model
9
+ */
10
+ export declare function transcribeAudio(audioPath: string, ctx: ProjectContext): Promise<TranscriptionResult>;
11
+ //# sourceMappingURL=whisper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whisper.d.ts","sourceRoot":"","sources":["../../src/transcription/whisper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAkBlD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,mBAAmB,CAAC,CAiD9B"}
@@ -0,0 +1,58 @@
1
+ import { existsSync } from "node:fs";
2
+ // Dynamic import for optional dependency
3
+ let whisperModule = null;
4
+ async function getWhisper() {
5
+ if (!whisperModule) {
6
+ try {
7
+ whisperModule = await import("nodejs-whisper");
8
+ }
9
+ catch {
10
+ throw new Error("nodejs-whisper is not installed. Run: pnpm add nodejs-whisper");
11
+ }
12
+ }
13
+ return whisperModule;
14
+ }
15
+ /**
16
+ * Transcribe audio file using local Whisper model
17
+ */
18
+ export async function transcribeAudio(audioPath, ctx) {
19
+ const { config, logger } = ctx;
20
+ if (!existsSync(audioPath)) {
21
+ throw new Error(`Audio file not found: ${audioPath}`);
22
+ }
23
+ const whisper = await getWhisper();
24
+ const modelName = config.transcription?.model ?? "base.en";
25
+ logger.debug({ audioPath, model: modelName }, "Starting transcription");
26
+ const startTime = Date.now();
27
+ try {
28
+ const transcript = await whisper.nodewhisper(audioPath, {
29
+ modelName,
30
+ autoDownloadModelName: modelName,
31
+ removeWavFileAfterTranscription: false,
32
+ withCuda: false,
33
+ whisperOptions: {
34
+ outputInText: true,
35
+ language: "auto",
36
+ },
37
+ logger: {
38
+ debug: (message) => logger.debug(message),
39
+ error: (message) => logger.error(message),
40
+ log: (message) => logger.info(message),
41
+ },
42
+ });
43
+ const duration = (Date.now() - startTime) / 1000;
44
+ const text = Array.isArray(transcript)
45
+ ? transcript.map((t) => t.speech).join(" ")
46
+ : String(transcript);
47
+ logger.debug({ duration: `${duration.toFixed(2)}s`, textLength: text.length }, "Transcription complete");
48
+ return {
49
+ text: text.trim(),
50
+ duration,
51
+ };
52
+ }
53
+ catch (error) {
54
+ logger.error({ error, audioPath }, "Transcription failed");
55
+ throw error;
56
+ }
57
+ }
58
+ //# sourceMappingURL=whisper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whisper.js","sourceRoot":"","sources":["../../src/transcription/whisper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGrC,yCAAyC;AACzC,IAAI,aAAa,GAA2C,IAAI,CAAC;AAEjE,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,+DAA+D,CAChE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAQD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAAiB,EACjB,GAAmB;IAEnB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IAE/B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,yBAAyB,SAAS,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,MAAM,CAAC,aAAa,EAAE,KAAK,IAAI,SAAS,CAAC;IAE3D,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,wBAAwB,CAAC,CAAC;IAExE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE;YACtD,SAAS;YACT,qBAAqB,EAAE,SAAS;YAChC,+BAA+B,EAAE,KAAK;YACtC,QAAQ,EAAE,KAAK;YACf,cAAc,EAAE;gBACd,YAAY,EAAE,IAAI;gBAClB,QAAQ,EAAE,MAAM;aACjB;YACD,MAAM,EAAE;gBACN,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;gBACjD,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;gBACjD,GAAG,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;aAC/C;SACF,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;YACpC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YAC3C,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAEvB,MAAM,CAAC,KAAK,CACV,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,EAChE,wBAAwB,CACzB,CAAC;QAEF,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;YACjB,QAAQ;SACT,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,sBAAsB,CAAC,CAAC;QAC3D,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type pino from "pino";
2
+ import type { ResolvedProjectConfig } from "./config.js";
3
+ import type { BootContext } from "./context/resolver.js";
4
+ /**
5
+ * Engine-agnostic interface for making one-shot AI calls from command handlers.
6
+ * The underlying provider (Claude Code, Codex, etc.) is an implementation detail.
7
+ */
8
+ export interface Agent {
9
+ call(prompt: string, options?: {
10
+ onProgress?: (message: string) => void;
11
+ }): Promise<string>;
12
+ }
13
+ /**
14
+ * Per-project context object threaded through all bot internals.
15
+ * Replaces the former global singletons (getConfig / getLogger).
16
+ */
17
+ export interface ProjectContext {
18
+ config: ResolvedProjectConfig;
19
+ logger: pino.Logger;
20
+ bootContext: BootContext;
21
+ }
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;;GAGG;AACH,MAAM,WAAW,KAAK;IACpB,IAAI,CACF,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,GACnD,OAAO,CAAC,MAAM,CAAC,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;CAC1B"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Initialize a new user directory
3
+ * Creates uploads and downloads folders - Claude config is read from working directory
4
+ */
5
+ export declare function ensureUserSetup(userDir: string): Promise<void>;
6
+ /**
7
+ * Clear a user's directory (for /clear command)
8
+ */
9
+ export declare function clearUserData(userDir: string): Promise<void>;
10
+ /**
11
+ * Get the path to user's uploads directory
12
+ */
13
+ export declare function getUploadsPath(userDir: string): string;
14
+ /**
15
+ * Get the path to user's downloads directory (for sending files to user)
16
+ */
17
+ export declare function getDownloadsPath(userDir: string): string;
18
+ /**
19
+ * Save session ID for a user
20
+ */
21
+ export declare function saveSessionId(userDir: string, sessionId: string): Promise<void>;
22
+ /**
23
+ * Get saved session ID for a user
24
+ */
25
+ export declare function getSessionId(userDir: string): Promise<string | null>;
26
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/user/setup.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWpE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAS1E"}
@@ -0,0 +1,73 @@
1
+ import { constants } from "node:fs";
2
+ import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ /**
5
+ * Check if a directory exists
6
+ */
7
+ async function directoryExists(path) {
8
+ try {
9
+ await access(path, constants.F_OK);
10
+ return true;
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ }
16
+ /**
17
+ * Initialize a new user directory
18
+ * Creates uploads and downloads folders - Claude config is read from working directory
19
+ */
20
+ export async function ensureUserSetup(userDir) {
21
+ const uploadsDir = join(userDir, "uploads");
22
+ const downloadsDir = join(userDir, "downloads");
23
+ // Create user directory, uploads and downloads folders
24
+ if (!(await directoryExists(uploadsDir))) {
25
+ await mkdir(uploadsDir, { recursive: true });
26
+ }
27
+ if (!(await directoryExists(downloadsDir))) {
28
+ await mkdir(downloadsDir, { recursive: true });
29
+ }
30
+ }
31
+ /**
32
+ * Clear a user's directory (for /clear command)
33
+ */
34
+ export async function clearUserData(userDir) {
35
+ if (await directoryExists(userDir)) {
36
+ await rm(userDir, { recursive: true, force: true });
37
+ }
38
+ }
39
+ /**
40
+ * Get the path to user's uploads directory
41
+ */
42
+ export function getUploadsPath(userDir) {
43
+ return join(userDir, "uploads");
44
+ }
45
+ /**
46
+ * Get the path to user's downloads directory (for sending files to user)
47
+ */
48
+ export function getDownloadsPath(userDir) {
49
+ return join(userDir, "downloads");
50
+ }
51
+ /**
52
+ * Save session ID for a user
53
+ */
54
+ export async function saveSessionId(userDir, sessionId) {
55
+ const sessionFile = join(userDir, "session.json");
56
+ const sessionData = { currentSessionId: sessionId };
57
+ await writeFile(sessionFile, JSON.stringify(sessionData, null, 2), "utf-8");
58
+ }
59
+ /**
60
+ * Get saved session ID for a user
61
+ */
62
+ export async function getSessionId(userDir) {
63
+ const sessionFile = join(userDir, "session.json");
64
+ try {
65
+ const content = await readFile(sessionFile, "utf-8");
66
+ const sessionData = JSON.parse(content);
67
+ return sessionData.currentSessionId || null;
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ }
73
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/user/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAMjC;;GAEG;AACH,KAAK,UAAU,eAAe,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAe;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAEhD,uDAAuD;IACvD,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACzC,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QAC3C,MAAM,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAe;IACjD,IAAI,MAAM,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,SAAiB;IAEjB,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAClD,MAAM,WAAW,GAAgB,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC;IACjE,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe;IAChD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,WAAW,GAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrD,OAAO,WAAW,CAAC,gBAAgB,IAAI,IAAI,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@marcopeg/hal",
3
+ "version": "1.0.11",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "hal": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "packageManager": "pnpm@10.13.1",
14
+ "scripts": {
15
+ "start": "tsx watch src/cli.ts start --cwd examples",
16
+ "build": "tsc && chmod +x dist/cli.js",
17
+ "typecheck": "tsc --noEmit",
18
+ "lint": "biome check src",
19
+ "lint:fix": "biome check --write src",
20
+ "prepublishOnly": "pnpm run build",
21
+ "prepare": "husky",
22
+ "deploy": "npm version patch && npm publish --access public"
23
+ },
24
+ "keywords": [
25
+ "telegram",
26
+ "claude",
27
+ "bot",
28
+ "ai",
29
+ "assistant"
30
+ ],
31
+ "author": "",
32
+ "license": "ISC",
33
+ "description": "Telegram bot that invokes Claude Code as a personal assistant",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": ""
37
+ },
38
+ "dependencies": {
39
+ "chokidar": "^5.0.0",
40
+ "dotenv": "^17.2.3",
41
+ "grammy": "^1.39.2",
42
+ "nodejs-whisper": "^0.2.9",
43
+ "pino": "^10.2.0",
44
+ "zod": "^4.3.5"
45
+ },
46
+ "devDependencies": {
47
+ "@biomejs/biome": "^2.3.11",
48
+ "@types/node": "^25.0.8",
49
+ "husky": "^9.1.7",
50
+ "tsx": "^4.21.0",
51
+ "typescript": "^5.9.3"
52
+ },
53
+ "engines": {
54
+ "node": ">=18"
55
+ }
56
+ }