ccbot 1.0.0 → 1.2.1

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 (79) hide show
  1. package/dist/channel/telegram/telegram-channel.d.ts +18 -0
  2. package/dist/channel/telegram/telegram-channel.js +148 -0
  3. package/dist/channel/telegram/telegram-channel.js.map +1 -0
  4. package/dist/channel/telegram/telegram-sender.d.ts +2 -0
  5. package/dist/channel/telegram/telegram-sender.js +72 -0
  6. package/dist/channel/telegram/telegram-sender.js.map +1 -0
  7. package/dist/channel/types.d.ts +20 -0
  8. package/dist/channel/types.js +2 -0
  9. package/dist/channel/types.js.map +1 -0
  10. package/dist/commands/help.js +11 -9
  11. package/dist/commands/help.js.map +1 -0
  12. package/dist/commands/setup.js +49 -40
  13. package/dist/commands/setup.js.map +1 -0
  14. package/dist/commands/uninstall.js +15 -13
  15. package/dist/commands/uninstall.js.map +1 -0
  16. package/dist/commands/update.js +90 -39
  17. package/dist/commands/update.js.map +1 -0
  18. package/dist/config-manager.d.ts +7 -2
  19. package/dist/config-manager.js +44 -21
  20. package/dist/config-manager.js.map +1 -0
  21. package/dist/hook/hook-handler.d.ts +8 -7
  22. package/dist/hook/hook-handler.js +53 -100
  23. package/dist/hook/hook-handler.js.map +1 -0
  24. package/dist/hook/hook-installer.d.ts +1 -3
  25. package/dist/hook/hook-installer.js +46 -33
  26. package/dist/hook/hook-installer.js.map +1 -0
  27. package/dist/hook/hook-server.d.ts +2 -1
  28. package/dist/hook/hook-server.js +32 -9
  29. package/dist/hook/hook-server.js.map +1 -0
  30. package/dist/hook/response-store.d.ts +8 -0
  31. package/dist/hook/response-store.js +18 -0
  32. package/dist/i18n/index.d.ts +9 -0
  33. package/dist/i18n/index.js +55 -0
  34. package/dist/i18n/index.js.map +1 -0
  35. package/dist/i18n/locales/en.d.ts +2 -0
  36. package/dist/i18n/locales/en.js +127 -0
  37. package/dist/i18n/locales/en.js.map +1 -0
  38. package/dist/i18n/locales/vi.d.ts +2 -0
  39. package/dist/i18n/locales/vi.js +127 -0
  40. package/dist/i18n/locales/vi.js.map +1 -0
  41. package/dist/i18n/locales/zh.d.ts +2 -0
  42. package/dist/i18n/locales/zh.js +127 -0
  43. package/dist/i18n/locales/zh.js.map +1 -0
  44. package/dist/i18n/types.d.ts +126 -0
  45. package/dist/i18n/types.js +2 -0
  46. package/dist/i18n/types.js.map +1 -0
  47. package/dist/index.js +39 -18
  48. package/dist/index.js.map +1 -0
  49. package/dist/monitor/git-collector.d.ts +2 -0
  50. package/dist/monitor/git-collector.js +88 -0
  51. package/dist/monitor/git-collector.js.map +1 -0
  52. package/dist/monitor/transcript-parser.d.ts +4 -0
  53. package/dist/monitor/transcript-parser.js +35 -14
  54. package/dist/monitor/transcript-parser.js.map +1 -0
  55. package/dist/telegram/bot.d.ts +8 -3
  56. package/dist/telegram/bot.js +69 -18
  57. package/dist/telegram/message-formatter.d.ts +7 -2
  58. package/dist/telegram/message-formatter.js +26 -23
  59. package/dist/telegram/message-sender.d.ts +1 -1
  60. package/dist/telegram/message-sender.js +37 -5
  61. package/dist/utils/constants.d.ts +44 -0
  62. package/dist/utils/constants.js +41 -0
  63. package/dist/utils/constants.js.map +1 -0
  64. package/dist/utils/install-detection.d.ts +2 -1
  65. package/dist/utils/install-detection.js +11 -9
  66. package/dist/utils/install-detection.js.map +1 -0
  67. package/dist/utils/log.d.ts +2 -0
  68. package/dist/utils/log.js +18 -0
  69. package/dist/utils/log.js.map +1 -0
  70. package/dist/utils/paths.d.ts +16 -0
  71. package/dist/utils/paths.js +39 -0
  72. package/dist/utils/paths.js.map +1 -0
  73. package/dist/utils/response-store.d.ts +29 -0
  74. package/dist/utils/response-store.js +100 -0
  75. package/dist/utils/response-store.js.map +1 -0
  76. package/dist/utils/tunnel.d.ts +7 -0
  77. package/dist/utils/tunnel.js +53 -0
  78. package/dist/utils/tunnel.js.map +1 -0
  79. package/package.json +30 -12
@@ -0,0 +1,127 @@
1
+ export const zh = {
2
+ bot: {
3
+ started: "已启动 (hook端口: {port})",
4
+ shuttingDown: "正在关闭...",
5
+ telegramStarted: "telegram bot 已启动",
6
+ commandsRegistered: "命令已注册",
7
+ commandsRegisterFailed: "注册命令失败",
8
+ menuButtonRegistered: "小程序菜单按钮已注册",
9
+ menuButtonFailed: "注册菜单按钮失败",
10
+ noChatId: "尚无聊天ID — 运行 'ccbot setup' 或向机器人发送 /start",
11
+ notificationFailed: "发送通知失败",
12
+ registeredChatId: "已注册聊天ID {chatId}",
13
+ unauthorizedUser: "未授权用户 {userId} ({username})",
14
+ ready: "✅ *ccbot* 已就绪\\.\n\n当Claude Code完成响应时,您将收到通知\\.",
15
+ alreadyConnected: "✅ ccbot 已连接 — 机器人运行正常。",
16
+ connectionLost: "⚠️ 与 Telegram 连接中断 — 正在重试...",
17
+ connectionRestored: "✅ 已重新连接 Telegram",
18
+ commands: {
19
+ start: "将机器人连接到此聊天",
20
+ },
21
+ viewDetails: "📱 查看详情",
22
+ dashboard: "📱 控制台",
23
+ sendFailed: "发送失败,使用备用方式",
24
+ sendFallbackFailed: "备用方式也失败",
25
+ },
26
+ setup: {
27
+ intro: "🤖 ccbot 设置",
28
+ tokenMessage: "Telegram Bot Token",
29
+ tokenPlaceholder: "从 @BotFather → /newbot 获取",
30
+ tokenRequired: "Bot token 为必填项",
31
+ tokenInvalidFormat: "格式无效 (需要: 123456:ABC-xxx)",
32
+ userIdMessage: "您的 Telegram 用户 ID",
33
+ userIdPlaceholder: "向 @userinfobot 发送 /start",
34
+ userIdRequired: "用户 ID 为必填项",
35
+ userIdMustBeNumber: "必须是数字",
36
+ cancelled: "设置已取消。",
37
+ configSaved: "配置已保存",
38
+ hookInstalled: "Hook 已安装 → ~/.claude/settings.json",
39
+ hookAlreadyInstalled: "Hook 已安装",
40
+ hookFailed: "Hook 安装失败: {error}",
41
+ chatIdRegistered: "聊天 ID 已注册",
42
+ complete: "🎉 设置完成!\n\n 下一步:\n 1. 启动机器人: {command}\n 2. 正常使用 Claude Code → 通知将自动发送",
43
+ languageMessage: "语言",
44
+ },
45
+ uninstall: {
46
+ intro: "🗑️ 卸载 ccbot",
47
+ hookRemoved: "已从 ~/.claude/settings.json 移除 Hook",
48
+ hookNotFound: "未找到 Hook(已移除)",
49
+ configRemoved: "已删除 ~/.ccbot/(配置、状态、钩子)",
50
+ configNotFound: "未找到 ~/.ccbot/(已删除)",
51
+ removeGlobal: "要同时删除包:\n pnpm remove -g ccbot",
52
+ removeGitClone: "要同时删除源代码:\n rm -rf <ccbot-directory>",
53
+ done: "ccbot 已卸载",
54
+ },
55
+ update: {
56
+ intro: "📦 ccbot 更新",
57
+ npxAlreadyLatest: "通过 npx 安装 — 始终使用最新版本,无需更新。",
58
+ npxDone: "已是最新版本",
59
+ checking: "正在检查版本...",
60
+ alreadyLatestNpm: "已是最新版本 (v{version})",
61
+ alreadyLatestGit: "已是最新版本 (commit {hash})",
62
+ updatingNpm: "正在通过 {pm} 更新 (v{from} → v{to})...",
63
+ updating: "正在通过 {pm} 更新...",
64
+ updateSuccess: "更新成功 (v{from} → v{to})",
65
+ updateComplete: "更新完成",
66
+ updateFailed: "更新失败",
67
+ noUpdateNeeded: "✨ 无需更新",
68
+ updateManualGlobal: "请手动尝试: {cmd}",
69
+ pulling: "正在拉取最新代码...",
70
+ pulled: "已拉取最新代码",
71
+ pulledGit: "已拉取最新代码 ({from} → {to})",
72
+ installingDeps: "正在安装依赖...",
73
+ depsInstalled: "依赖已安装",
74
+ building: "正在构建...",
75
+ buildComplete: "构建完成",
76
+ updateManualGit: "请手动尝试: git pull && npm install && npm run build",
77
+ gitRepoNotFound: "找不到 git 仓库根目录。",
78
+ },
79
+ help: {
80
+ intro: "🤖 ccbot — Claude Code ↔ Telegram 通知机器人",
81
+ usage: "用法: {prefix} [命令]",
82
+ commands: "命令:",
83
+ cmdNone: " (无) 启动机器人",
84
+ cmdSetup: " setup 交互式设置(配置 + 钩子)",
85
+ cmdUpdate: " update 更新 ccbot 到最新版本",
86
+ cmdUninstall: " uninstall 删除所有 ccbot 数据和钩子",
87
+ cmdHelp: " help 显示此帮助信息",
88
+ docs: "文档 → https://github.com/palooza-kaida/ccbot",
89
+ },
90
+ hook: {
91
+ serverListening: "hook 服务器正在监听 localhost:{port}",
92
+ invalidPayload: "无效的 stop event 负载 — 缺少必要字段",
93
+ stopEventReceived: "收到 session {sessionId} 的 stop event,位于 {cwd}",
94
+ transcriptFailed: "解析 transcript 失败",
95
+ notificationFailed: "发送通知失败",
96
+ },
97
+ tunnel: {
98
+ installing: "正在安装 cloudflared 二进制文件...",
99
+ installed: "cloudflared 二进制文件已安装",
100
+ started: "🌐 公共 URL: {url}",
101
+ failed: "⚠️ 隧道失败,仅使用 localhost",
102
+ disconnected: "⚠️ 隧道断开连接,正在重新连接...",
103
+ exited: "隧道进程已退出 (代码 {code})",
104
+ timeout: "隧道连接超时 ({seconds}秒)",
105
+ },
106
+ config: {
107
+ notFound: "未找到配置 — 请先运行 'ccbot setup'",
108
+ mustBeObject: "配置必须是 JSON 对象",
109
+ invalidToken: "telegram_bot_token 必须是包含 ':' 的字符串 — 运行 'ccbot setup'",
110
+ invalidUserId: "user_id 必须是整数 — 运行 'ccbot setup'",
111
+ invalidPort: "hook_port 必须是 1 到 65535 之间的整数",
112
+ invalidSecret: "hook_secret 只能包含十六进制字符 (a-f, 0-9)",
113
+ invalidHookPort: "无效的 hook 端口: {port}(必须为 1-65535)",
114
+ hookAlreadyInstalled: "ccbot hook 已安装",
115
+ },
116
+ notification: {
117
+ tokens: "tokens",
118
+ cache: "cache",
119
+ cacheRead: "读取",
120
+ cacheWrite: "写入",
121
+ },
122
+ common: {
123
+ unknownCommand: "未知命令: {command}",
124
+ setupFailed: "setup 失败",
125
+ },
126
+ };
127
+ //# sourceMappingURL=zh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zh.js","sourceRoot":"","sources":["../../../src/i18n/locales/zh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ export interface TranslationKeys {
2
+ bot: {
3
+ started: string;
4
+ shuttingDown: string;
5
+ telegramStarted: string;
6
+ commandsRegistered: string;
7
+ commandsRegisterFailed: string;
8
+ menuButtonRegistered: string;
9
+ menuButtonFailed: string;
10
+ noChatId: string;
11
+ notificationFailed: string;
12
+ registeredChatId: string;
13
+ unauthorizedUser: string;
14
+ ready: string;
15
+ alreadyConnected: string;
16
+ connectionLost: string;
17
+ connectionRestored: string;
18
+ commands: {
19
+ start: string;
20
+ };
21
+ viewDetails: string;
22
+ dashboard: string;
23
+ sendFailed: string;
24
+ sendFallbackFailed: string;
25
+ };
26
+ setup: {
27
+ intro: string;
28
+ tokenMessage: string;
29
+ tokenPlaceholder: string;
30
+ tokenRequired: string;
31
+ tokenInvalidFormat: string;
32
+ userIdMessage: string;
33
+ userIdPlaceholder: string;
34
+ userIdRequired: string;
35
+ userIdMustBeNumber: string;
36
+ cancelled: string;
37
+ configSaved: string;
38
+ hookInstalled: string;
39
+ hookAlreadyInstalled: string;
40
+ hookFailed: string;
41
+ chatIdRegistered: string;
42
+ complete: string;
43
+ languageMessage: string;
44
+ };
45
+ uninstall: {
46
+ intro: string;
47
+ hookRemoved: string;
48
+ hookNotFound: string;
49
+ configRemoved: string;
50
+ configNotFound: string;
51
+ removeGlobal: string;
52
+ removeGitClone: string;
53
+ done: string;
54
+ };
55
+ update: {
56
+ intro: string;
57
+ npxAlreadyLatest: string;
58
+ npxDone: string;
59
+ checking: string;
60
+ alreadyLatestNpm: string;
61
+ alreadyLatestGit: string;
62
+ updatingNpm: string;
63
+ updating: string;
64
+ updateSuccess: string;
65
+ updateComplete: string;
66
+ updateFailed: string;
67
+ noUpdateNeeded: string;
68
+ updateManualGlobal: string;
69
+ pulling: string;
70
+ pulled: string;
71
+ pulledGit: string;
72
+ installingDeps: string;
73
+ depsInstalled: string;
74
+ building: string;
75
+ buildComplete: string;
76
+ updateManualGit: string;
77
+ gitRepoNotFound: string;
78
+ };
79
+ help: {
80
+ intro: string;
81
+ usage: string;
82
+ commands: string;
83
+ cmdNone: string;
84
+ cmdSetup: string;
85
+ cmdUpdate: string;
86
+ cmdUninstall: string;
87
+ cmdHelp: string;
88
+ docs: string;
89
+ };
90
+ hook: {
91
+ serverListening: string;
92
+ invalidPayload: string;
93
+ stopEventReceived: string;
94
+ transcriptFailed: string;
95
+ notificationFailed: string;
96
+ };
97
+ tunnel: {
98
+ installing: string;
99
+ installed: string;
100
+ started: string;
101
+ failed: string;
102
+ disconnected: string;
103
+ exited: string;
104
+ timeout: string;
105
+ };
106
+ config: {
107
+ notFound: string;
108
+ mustBeObject: string;
109
+ invalidToken: string;
110
+ invalidUserId: string;
111
+ invalidPort: string;
112
+ invalidSecret: string;
113
+ invalidHookPort: string;
114
+ hookAlreadyInstalled: string;
115
+ };
116
+ notification: {
117
+ tokens: string;
118
+ cache: string;
119
+ cacheRead: string;
120
+ cacheWrite: string;
121
+ };
122
+ common: {
123
+ unknownCommand: string;
124
+ setupFailed: string;
125
+ };
126
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/i18n/types.ts"],"names":[],"mappings":""}
package/dist/index.js CHANGED
@@ -1,13 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { ConfigManager } from "./config-manager.js";
3
- import { Bot } from "./telegram/bot.js";
3
+ import { TelegramChannel } from "./channel/telegram/telegram-channel.js";
4
4
  import { HookServer } from "./hook/hook-server.js";
5
5
  import { HookHandler } from "./hook/hook-handler.js";
6
6
  import { runSetup } from "./commands/setup.js";
7
7
  import { runUpdate } from "./commands/update.js";
8
8
  import { runUninstall } from "./commands/uninstall.js";
9
9
  import { runHelp } from "./commands/help.js";
10
- import { formatError } from "./utils/error-utils.js";
10
+ import { CliCommand } from "./utils/constants.js";
11
+ import { t } from "./i18n/index.js";
12
+ import { TunnelManager } from "./utils/tunnel.js";
13
+ import { log, logError } from "./utils/log.js";
11
14
  const args = process.argv.slice(2);
12
15
  if (args.length > 0) {
13
16
  handleSubcommand(args);
@@ -15,17 +18,28 @@ if (args.length > 0) {
15
18
  else {
16
19
  startBot();
17
20
  }
18
- function startBot() {
21
+ async function startBot() {
19
22
  const cfg = ConfigManager.load();
20
- const bot = new Bot(cfg);
21
- const handler = new HookHandler((text) => bot.sendNotification(text));
22
- const hookServer = new HookServer(cfg.hook_port, cfg.hook_secret, handler);
23
+ const hookServer = new HookServer(cfg.hook_port, cfg.hook_secret);
23
24
  hookServer.start();
24
- console.log(`ccbot: started (hook port: ${cfg.hook_port})`);
25
- bot.start();
25
+ log(`ccbot: ${t("bot.started", { port: cfg.hook_port })}`);
26
+ const tunnelManager = new TunnelManager();
27
+ let tunnelUrl = null;
28
+ try {
29
+ tunnelUrl = await tunnelManager.start(cfg.hook_port);
30
+ log(t("tunnel.started", { url: tunnelUrl }));
31
+ }
32
+ catch (err) {
33
+ logError(t("tunnel.failed"), err);
34
+ }
35
+ const channel = new TelegramChannel(cfg, tunnelUrl);
36
+ const handler = new HookHandler(channel, cfg.hook_port, tunnelManager);
37
+ hookServer.setHandler(handler);
38
+ await channel.initialize();
26
39
  const shutdown = async () => {
27
- console.log("\nccbot: shutting down...");
28
- bot.stop();
40
+ log(t("bot.shuttingDown"));
41
+ tunnelManager.stop();
42
+ await channel.shutdown();
29
43
  await hookServer.stop();
30
44
  process.exit(0);
31
45
  };
@@ -33,27 +47,34 @@ function startBot() {
33
47
  process.on("SIGTERM", shutdown);
34
48
  }
35
49
  function handleSubcommand(args) {
50
+ try {
51
+ ConfigManager.load();
52
+ }
53
+ catch {
54
+ // config not yet created, subcommands handle this
55
+ }
36
56
  switch (args[0]) {
37
- case "setup":
57
+ case CliCommand.Setup:
38
58
  runSetup().catch((err) => {
39
- console.error(`ccbot: setup failed: ${formatError(err)}`);
59
+ logError(t("common.setupFailed"), err);
40
60
  process.exit(1);
41
61
  });
42
62
  break;
43
- case "update":
63
+ case CliCommand.Update:
44
64
  runUpdate();
45
65
  break;
46
- case "uninstall":
66
+ case CliCommand.Uninstall:
47
67
  runUninstall();
48
68
  break;
49
- case "help":
50
- case "--help":
51
- case "-h":
69
+ case CliCommand.Help:
70
+ case CliCommand.HelpFlag:
71
+ case CliCommand.HelpShort:
52
72
  runHelp();
53
73
  break;
54
74
  default:
55
- console.error(`unknown command: ${args[0]}`);
75
+ logError(t("common.unknownCommand", { command: args[0] }));
56
76
  runHelp();
57
77
  process.exit(1);
58
78
  }
59
79
  }
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { GitChange } from "../channel/types.js";
2
+ export declare function collectGitChanges(cwd: string): GitChange[];
@@ -0,0 +1,88 @@
1
+ import { execSync } from "node:child_process";
2
+ import { GitChangeStatus, GIT_TIMEOUT_MS } from "../utils/constants.js";
3
+ export function collectGitChanges(cwd) {
4
+ try {
5
+ const diffOutput = execSync("git diff --name-status HEAD", {
6
+ cwd,
7
+ encoding: "utf-8",
8
+ timeout: GIT_TIMEOUT_MS,
9
+ });
10
+ const changes = parseGitDiffOutput(diffOutput);
11
+ try {
12
+ const untrackedOutput = execSync("git ls-files --others --exclude-standard", {
13
+ cwd,
14
+ encoding: "utf-8",
15
+ timeout: GIT_TIMEOUT_MS,
16
+ });
17
+ for (const file of untrackedOutput.trim().split("\n")) {
18
+ if (file)
19
+ changes.push({ file, status: GitChangeStatus.Added });
20
+ }
21
+ }
22
+ catch {
23
+ // untracked files collection is optional
24
+ }
25
+ return changes;
26
+ }
27
+ catch {
28
+ try {
29
+ const porcelainOutput = execSync("git status --porcelain", {
30
+ cwd,
31
+ encoding: "utf-8",
32
+ timeout: GIT_TIMEOUT_MS,
33
+ });
34
+ return parsePorcelainOutput(porcelainOutput);
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ }
40
+ }
41
+ function parseGitDiffOutput(output) {
42
+ const changes = [];
43
+ for (const line of output.trim().split("\n")) {
44
+ if (!line)
45
+ continue;
46
+ const parts = line.split("\t");
47
+ if (parts.length < 2)
48
+ continue;
49
+ const statusCode = parts[0];
50
+ const filePath = parts[1];
51
+ if (!statusCode || !filePath)
52
+ continue;
53
+ let status = GitChangeStatus.Modified;
54
+ if (statusCode.startsWith("A"))
55
+ status = GitChangeStatus.Added;
56
+ else if (statusCode.startsWith("D"))
57
+ status = GitChangeStatus.Deleted;
58
+ else if (statusCode.startsWith("R"))
59
+ status = GitChangeStatus.Renamed;
60
+ changes.push({ file: filePath, status });
61
+ }
62
+ return changes;
63
+ }
64
+ function parsePorcelainOutput(output) {
65
+ const changes = [];
66
+ for (const line of output.trim().split("\n")) {
67
+ if (line.length < 4)
68
+ continue;
69
+ const statusCode = line.slice(0, 2).trim();
70
+ const file = line.slice(3).trim();
71
+ let status = GitChangeStatus.Modified;
72
+ switch (statusCode) {
73
+ case "??":
74
+ case "A":
75
+ status = GitChangeStatus.Added;
76
+ break;
77
+ case "D":
78
+ status = GitChangeStatus.Deleted;
79
+ break;
80
+ case "R":
81
+ status = GitChangeStatus.Renamed;
82
+ break;
83
+ }
84
+ changes.push({ file, status });
85
+ }
86
+ return changes;
87
+ }
88
+ //# sourceMappingURL=git-collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-collector.js","sourceRoot":"","sources":["../../src/monitor/git-collector.ts"],"names":[],"mappings":"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"}
@@ -2,5 +2,9 @@ export interface TranscriptSummary {
2
2
  lastAssistantMessage: string;
3
3
  durationMs: number;
4
4
  totalCostUSD: number;
5
+ inputTokens: number;
6
+ outputTokens: number;
7
+ cacheCreationTokens: number;
8
+ cacheReadTokens: number;
5
9
  }
6
10
  export declare function parseTranscript(transcriptPath: string): TranscriptSummary;
@@ -1,13 +1,18 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { homedir } from "node:os";
2
+ import { expandHome } from "../utils/paths.js";
3
3
  export function parseTranscript(transcriptPath) {
4
4
  const expandedPath = expandHome(transcriptPath);
5
5
  const raw = readFileSync(expandedPath, "utf-8");
6
6
  const lines = raw.split("\n");
7
7
  let lastAssistantText = "";
8
+ let summaryText = "";
8
9
  let totalCost = 0;
9
10
  let firstTimestamp = null;
10
11
  let lastTimestamp = null;
12
+ let inputTokens = 0;
13
+ let outputTokens = 0;
14
+ let cacheCreationTokens = 0;
15
+ let cacheReadTokens = 0;
11
16
  for (const line of lines) {
12
17
  if (!line.trim())
13
18
  continue;
@@ -19,20 +24,32 @@ export function parseTranscript(transcriptPath) {
19
24
  continue;
20
25
  }
21
26
  if (entry.timestamp) {
22
- const t = new Date(entry.timestamp);
23
- if (!isNaN(t.getTime())) {
27
+ const entryDate = new Date(entry.timestamp);
28
+ if (!isNaN(entryDate.getTime())) {
24
29
  if (!firstTimestamp)
25
- firstTimestamp = t;
26
- lastTimestamp = t;
30
+ firstTimestamp = entryDate;
31
+ lastTimestamp = entryDate;
27
32
  }
28
33
  }
29
34
  totalCost += entry.costUSD ?? 0;
35
+ if (entry.type === "summary" && entry.summary) {
36
+ summaryText = entry.summary;
37
+ }
30
38
  if (entry.type === "assistant" || entry.message) {
31
39
  const msg = entry.message;
32
40
  if (msg?.role === "assistant") {
33
- const text = extractTextFromContent(msg.content ?? []);
34
- if (text)
41
+ const rawContent = msg.content ?? [];
42
+ const contentArray = Array.isArray(rawContent) ? rawContent : [];
43
+ const text = extractTextFromContent(contentArray);
44
+ if (text) {
35
45
  lastAssistantText = text;
46
+ }
47
+ if (msg.usage) {
48
+ inputTokens += msg.usage.input_tokens ?? 0;
49
+ outputTokens += msg.usage.output_tokens ?? 0;
50
+ cacheCreationTokens += msg.usage.cache_creation_input_tokens ?? 0;
51
+ cacheReadTokens += msg.usage.cache_read_input_tokens ?? 0;
52
+ }
36
53
  }
37
54
  }
38
55
  }
@@ -40,7 +57,16 @@ export function parseTranscript(transcriptPath) {
40
57
  if (firstTimestamp && lastTimestamp) {
41
58
  durationMs = lastTimestamp.getTime() - firstTimestamp.getTime();
42
59
  }
43
- return { lastAssistantMessage: lastAssistantText, durationMs, totalCostUSD: totalCost };
60
+ const finalMessage = lastAssistantText || summaryText;
61
+ return {
62
+ lastAssistantMessage: finalMessage,
63
+ durationMs,
64
+ totalCostUSD: totalCost,
65
+ inputTokens,
66
+ outputTokens,
67
+ cacheCreationTokens,
68
+ cacheReadTokens,
69
+ };
44
70
  }
45
71
  function extractTextFromContent(parts) {
46
72
  return parts
@@ -48,9 +74,4 @@ function extractTextFromContent(parts) {
48
74
  .map((p) => p.text)
49
75
  .join("\n");
50
76
  }
51
- function expandHome(path) {
52
- if (path.startsWith("~/")) {
53
- return homedir() + path.slice(1);
54
- }
55
- return path;
56
- }
77
+ //# sourceMappingURL=transcript-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-parser.js","sourceRoot":"","sources":["../../src/monitor/transcript-parser.ts"],"names":[],"mappings":"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"}
@@ -3,13 +3,18 @@ export declare class Bot {
3
3
  private bot;
4
4
  private cfg;
5
5
  private chatId;
6
+ private isDisconnected;
7
+ private tunnelUrl;
6
8
  private static readonly STATE_DIR;
7
9
  private static readonly STATE_FILE;
8
- constructor(cfg: Config);
9
- start(): void;
10
+ constructor(cfg: Config, tunnelUrl?: string | null);
11
+ start(): Promise<void>;
10
12
  stop(): Promise<void>;
11
- sendNotification(text: string): Promise<void>;
13
+ sendNotification(text: string, responseUrl?: string): Promise<void>;
14
+ private registerCommands;
15
+ private registerMenuButton;
12
16
  private registerHandlers;
13
17
  private loadState;
14
18
  private saveState;
19
+ private registerPollingErrorHandler;
15
20
  }