@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.
- package/README.md +655 -0
- package/dist/agent/index.d.ts +17 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +30 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/bot/commands/clear.d.ts +7 -0
- package/dist/bot/commands/clear.d.ts.map +1 -0
- package/dist/bot/commands/clear.js +23 -0
- package/dist/bot/commands/clear.js.map +1 -0
- package/dist/bot/commands/help.d.ts +3 -0
- package/dist/bot/commands/help.d.ts.map +1 -0
- package/dist/bot/commands/help.js +16 -0
- package/dist/bot/commands/help.js.map +1 -0
- package/dist/bot/commands/loader.d.ts +26 -0
- package/dist/bot/commands/loader.d.ts.map +1 -0
- package/dist/bot/commands/loader.js +206 -0
- package/dist/bot/commands/loader.js.map +1 -0
- package/dist/bot/commands/start.d.ts +3 -0
- package/dist/bot/commands/start.d.ts.map +1 -0
- package/dist/bot/commands/start.js +10 -0
- package/dist/bot/commands/start.js.map +1 -0
- package/dist/bot/commands/watcher.d.ts +11 -0
- package/dist/bot/commands/watcher.d.ts.map +1 -0
- package/dist/bot/commands/watcher.js +106 -0
- package/dist/bot/commands/watcher.js.map +1 -0
- package/dist/bot/handlers/document.d.ts +7 -0
- package/dist/bot/handlers/document.d.ts.map +1 -0
- package/dist/bot/handlers/document.js +128 -0
- package/dist/bot/handlers/document.js.map +1 -0
- package/dist/bot/handlers/index.d.ts +5 -0
- package/dist/bot/handlers/index.d.ts.map +1 -0
- package/dist/bot/handlers/index.js +5 -0
- package/dist/bot/handlers/index.js.map +1 -0
- package/dist/bot/handlers/photo.d.ts +7 -0
- package/dist/bot/handlers/photo.d.ts.map +1 -0
- package/dist/bot/handlers/photo.js +87 -0
- package/dist/bot/handlers/photo.js.map +1 -0
- package/dist/bot/handlers/text.d.ts +7 -0
- package/dist/bot/handlers/text.d.ts.map +1 -0
- package/dist/bot/handlers/text.js +186 -0
- package/dist/bot/handlers/text.js.map +1 -0
- package/dist/bot/handlers/voice.d.ts +7 -0
- package/dist/bot/handlers/voice.d.ts.map +1 -0
- package/dist/bot/handlers/voice.js +147 -0
- package/dist/bot/handlers/voice.js.map +1 -0
- package/dist/bot/middleware/auth.d.ts +7 -0
- package/dist/bot/middleware/auth.d.ts.map +1 -0
- package/dist/bot/middleware/auth.js +23 -0
- package/dist/bot/middleware/auth.js.map +1 -0
- package/dist/bot/middleware/rateLimit.d.ts +11 -0
- package/dist/bot/middleware/rateLimit.d.ts.map +1 -0
- package/dist/bot/middleware/rateLimit.js +49 -0
- package/dist/bot/middleware/rateLimit.js.map +1 -0
- package/dist/bot.d.ts +11 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +93 -0
- package/dist/bot.js.map +1 -0
- package/dist/claude/executor.d.ts +21 -0
- package/dist/claude/executor.d.ts.map +1 -0
- package/dist/claude/executor.js +185 -0
- package/dist/claude/executor.js.map +1 -0
- package/dist/claude/parser.d.ts +13 -0
- package/dist/claude/parser.d.ts.map +1 -0
- package/dist/claude/parser.js +63 -0
- package/dist/claude/parser.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +192 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +216 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +396 -0
- package/dist/config.js.map +1 -0
- package/dist/context/resolver.d.ts +19 -0
- package/dist/context/resolver.d.ts.map +1 -0
- package/dist/context/resolver.js +171 -0
- package/dist/context/resolver.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +17 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +44 -0
- package/dist/logger.js.map +1 -0
- package/dist/telegram/chunker.d.ts +10 -0
- package/dist/telegram/chunker.d.ts.map +1 -0
- package/dist/telegram/chunker.js +88 -0
- package/dist/telegram/chunker.js.map +1 -0
- package/dist/telegram/fileSender.d.ts +8 -0
- package/dist/telegram/fileSender.d.ts.map +1 -0
- package/dist/telegram/fileSender.js +46 -0
- package/dist/telegram/fileSender.js.map +1 -0
- package/dist/transcription/whisper.d.ts +11 -0
- package/dist/transcription/whisper.d.ts.map +1 -0
- package/dist/transcription/whisper.js +58 -0
- package/dist/transcription/whisper.js.map +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/user/setup.d.ts +26 -0
- package/dist/user/setup.d.ts.map +1 -0
- package/dist/user/setup.js +73 -0
- package/dist/user/setup.js.map +1 -0
- package/package.json +56 -0
package/dist/logger.d.ts
ADDED
|
@@ -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"}
|
package/dist/types.d.ts
ADDED
|
@@ -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 @@
|
|
|
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
|
+
}
|