ccbot 1.2.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 (63) 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 +1 -0
  11. package/dist/commands/help.js.map +1 -0
  12. package/dist/commands/setup.js +10 -19
  13. package/dist/commands/setup.js.map +1 -0
  14. package/dist/commands/uninstall.js +3 -3
  15. package/dist/commands/uninstall.js.map +1 -0
  16. package/dist/commands/update.js +69 -20
  17. package/dist/commands/update.js.map +1 -0
  18. package/dist/config-manager.d.ts +5 -2
  19. package/dist/config-manager.js +32 -15
  20. package/dist/config-manager.js.map +1 -0
  21. package/dist/hook/hook-handler.d.ts +3 -7
  22. package/dist/hook/hook-handler.js +28 -110
  23. package/dist/hook/hook-handler.js.map +1 -0
  24. package/dist/hook/hook-installer.d.ts +0 -3
  25. package/dist/hook/hook-installer.js +28 -26
  26. package/dist/hook/hook-installer.js.map +1 -0
  27. package/dist/hook/hook-server.js +13 -14
  28. package/dist/hook/hook-server.js.map +1 -0
  29. package/dist/i18n/index.js +1 -0
  30. package/dist/i18n/index.js.map +1 -0
  31. package/dist/i18n/locales/en.js +18 -12
  32. package/dist/i18n/locales/en.js.map +1 -0
  33. package/dist/i18n/locales/vi.js +18 -12
  34. package/dist/i18n/locales/vi.js.map +1 -0
  35. package/dist/i18n/locales/zh.js +18 -12
  36. package/dist/i18n/locales/zh.js.map +1 -0
  37. package/dist/i18n/types.d.ts +9 -4
  38. package/dist/i18n/types.js +1 -0
  39. package/dist/i18n/types.js.map +1 -0
  40. package/dist/index.js +14 -15
  41. package/dist/index.js.map +1 -0
  42. package/dist/monitor/git-collector.d.ts +2 -0
  43. package/dist/monitor/git-collector.js +88 -0
  44. package/dist/monitor/git-collector.js.map +1 -0
  45. package/dist/monitor/transcript-parser.js +6 -11
  46. package/dist/monitor/transcript-parser.js.map +1 -0
  47. package/dist/utils/constants.d.ts +21 -0
  48. package/dist/utils/constants.js +21 -0
  49. package/dist/utils/constants.js.map +1 -0
  50. package/dist/utils/install-detection.js +6 -5
  51. package/dist/utils/install-detection.js.map +1 -0
  52. package/dist/utils/log.d.ts +1 -1
  53. package/dist/utils/log.js +11 -2
  54. package/dist/utils/log.js.map +1 -0
  55. package/dist/utils/paths.d.ts +16 -0
  56. package/dist/utils/paths.js +39 -0
  57. package/dist/utils/paths.js.map +1 -0
  58. package/dist/utils/response-store.d.ts +4 -2
  59. package/dist/utils/response-store.js +34 -18
  60. package/dist/utils/response-store.js.map +1 -0
  61. package/dist/utils/tunnel.js +5 -3
  62. package/dist/utils/tunnel.js.map +1 -0
  63. package/package.json +29 -12
@@ -1,31 +1,34 @@
1
1
  import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { homedir } from "node:os";
4
2
  import { randomBytes } from "node:crypto";
5
3
  import { isValidLocale, setLocale } from "./i18n/index.js";
6
4
  import { t } from "./i18n/index.js";
5
+ import { paths } from "./utils/paths.js";
6
+ import { DEFAULT_HOOK_PORT } from "./utils/constants.js";
7
7
  export class ConfigManager {
8
- static CONFIG_DIR = join(homedir(), ".ccbot");
9
- static CONFIG_FILE = join(ConfigManager.CONFIG_DIR, "config.json");
10
8
  static load() {
11
9
  let data;
12
10
  try {
13
- data = readFileSync(ConfigManager.CONFIG_FILE, "utf-8");
11
+ data = readFileSync(paths.configFile, "utf-8");
14
12
  }
15
13
  catch (err) {
16
- if (err instanceof Error && "code" in err && err.code === "ENOENT") {
17
- throw new Error(t("config.notFound"));
14
+ if (err instanceof Error &&
15
+ "code" in err &&
16
+ err.code === "ENOENT") {
17
+ throw new Error(t("config.notFound"), { cause: err });
18
18
  }
19
- throw new Error(t("config.readError", { error: err instanceof Error ? err.message : String(err) }));
19
+ throw err;
20
20
  }
21
21
  const raw = JSON.parse(data);
22
22
  const cfg = ConfigManager.validate(raw);
23
+ if (cfg.hook_secret !== raw.hook_secret) {
24
+ ConfigManager.save(cfg);
25
+ }
23
26
  setLocale(cfg.locale);
24
27
  return cfg;
25
28
  }
26
29
  static save(cfg) {
27
- mkdirSync(ConfigManager.CONFIG_DIR, { recursive: true });
28
- writeFileSync(ConfigManager.CONFIG_FILE, JSON.stringify(cfg, null, 2), { mode: 0o600 });
30
+ mkdirSync(paths.ccbotDir, { recursive: true });
31
+ writeFileSync(paths.configFile, JSON.stringify(cfg, null, 2), { mode: 0o600 });
29
32
  }
30
33
  static isOwner(cfg, userId) {
31
34
  return cfg.user_id === userId;
@@ -33,6 +36,19 @@ export class ConfigManager {
33
36
  static generateSecret() {
34
37
  return randomBytes(32).toString("hex");
35
38
  }
39
+ static loadChatState() {
40
+ try {
41
+ const data = readFileSync(paths.stateFile, "utf-8");
42
+ return JSON.parse(data);
43
+ }
44
+ catch {
45
+ return { chat_id: null };
46
+ }
47
+ }
48
+ static saveChatState(state) {
49
+ mkdirSync(paths.ccbotDir, { recursive: true });
50
+ writeFileSync(paths.stateFile, JSON.stringify(state, null, 2), { mode: 0o600 });
51
+ }
36
52
  static validate(data) {
37
53
  if (typeof data !== "object" || data === null) {
38
54
  throw new Error(t("config.mustBeObject"));
@@ -44,9 +60,12 @@ export class ConfigManager {
44
60
  if (typeof obj.user_id !== "number" || !Number.isInteger(obj.user_id)) {
45
61
  throw new Error(t("config.invalidUserId"));
46
62
  }
47
- let hookPort = 9377;
63
+ let hookPort = DEFAULT_HOOK_PORT;
48
64
  if (obj.hook_port !== undefined) {
49
- if (typeof obj.hook_port !== "number" || !Number.isInteger(obj.hook_port) || obj.hook_port < 1 || obj.hook_port > 65535) {
65
+ if (typeof obj.hook_port !== "number" ||
66
+ !Number.isInteger(obj.hook_port) ||
67
+ obj.hook_port < 1 ||
68
+ obj.hook_port > 65535) {
50
69
  throw new Error(t("config.invalidPort"));
51
70
  }
52
71
  hookPort = obj.hook_port;
@@ -69,9 +88,7 @@ export class ConfigManager {
69
88
  hook_secret: hookSecret,
70
89
  locale,
71
90
  };
72
- if (typeof obj.hook_secret !== "string" || obj.hook_secret.length === 0) {
73
- ConfigManager.save(cfg);
74
- }
75
91
  return cfg;
76
92
  }
77
93
  }
94
+ //# sourceMappingURL=config-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../src/config-manager.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,10 @@
1
+ import type { NotificationChannel } from "../channel/types.js";
1
2
  import type { TunnelManager } from "../utils/tunnel.js";
2
- type NotifyFunc = (text: string, responseUrl?: string) => Promise<void>;
3
3
  export declare class HookHandler {
4
- private notify;
4
+ private channel;
5
5
  private hookPort;
6
6
  private tunnelManager;
7
- constructor(notify: NotifyFunc, hookPort: number, tunnelManager: TunnelManager);
7
+ constructor(channel: NotificationChannel, hookPort: number, tunnelManager: TunnelManager);
8
8
  handleStopEvent(event: unknown): Promise<void>;
9
9
  private buildResponseUrl;
10
- private collectGitChanges;
11
- private parseGitDiffOutput;
12
- private parsePorcelainOutput;
13
10
  }
14
- export {};
@@ -1,26 +1,24 @@
1
- import { execSync } from "node:child_process";
2
1
  import { parseTranscript } from "../monitor/transcript-parser.js";
3
- import { formatNotification, extractProjectName, } from "../telegram/message-formatter.js";
4
- import { formatError } from "../utils/error-utils.js";
5
- import { GitChangeStatus, MINI_APP_BASE_URL } from "../utils/constants.js";
2
+ import { collectGitChanges } from "../monitor/git-collector.js";
3
+ import { MINI_APP_BASE_URL, TRANSCRIPT_SETTLE_DELAY_MS, DEFAULT_FALLBACK_DURATION_MS, } from "../utils/constants.js";
6
4
  import { t } from "../i18n/index.js";
7
5
  import { responseStore } from "../utils/response-store.js";
8
- import { log } from "../utils/log.js";
9
- const GIT_TIMEOUT_MS = 10_000;
6
+ import { log, logError } from "../utils/log.js";
7
+ import { extractProjectName } from "../utils/paths.js";
10
8
  function isValidStopEvent(data) {
11
9
  if (typeof data !== "object" || data === null)
12
10
  return false;
13
11
  const obj = data;
14
- return typeof obj.session_id === "string"
15
- && typeof obj.transcript_path === "string"
16
- && typeof obj.cwd === "string";
12
+ return (typeof obj.session_id === "string" &&
13
+ typeof obj.transcript_path === "string" &&
14
+ typeof obj.cwd === "string");
17
15
  }
18
16
  export class HookHandler {
19
- notify;
17
+ channel;
20
18
  hookPort;
21
19
  tunnelManager;
22
- constructor(notify, hookPort, tunnelManager) {
23
- this.notify = notify;
20
+ constructor(channel, hookPort, tunnelManager) {
21
+ this.channel = channel;
24
22
  this.hookPort = hookPort;
25
23
  this.tunnelManager = tunnelManager;
26
24
  }
@@ -30,18 +28,26 @@ export class HookHandler {
30
28
  return;
31
29
  }
32
30
  log(t("hook.stopEventReceived", { sessionId: event.session_id, cwd: event.cwd }));
33
- await new Promise((resolve) => setTimeout(resolve, 500));
34
- let summary = { lastAssistantMessage: "", durationMs: 0, totalCostUSD: 0, inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
31
+ await new Promise((resolve) => setTimeout(resolve, TRANSCRIPT_SETTLE_DELAY_MS));
32
+ let summary = {
33
+ lastAssistantMessage: "",
34
+ durationMs: 0,
35
+ totalCostUSD: 0,
36
+ inputTokens: 0,
37
+ outputTokens: 0,
38
+ cacheCreationTokens: 0,
39
+ cacheReadTokens: 0,
40
+ };
35
41
  try {
36
42
  summary = parseTranscript(event.transcript_path);
37
43
  }
38
44
  catch (err) {
39
- log(t("hook.transcriptFailed", { error: formatError(err) }));
45
+ logError(t("hook.transcriptFailed"), err);
40
46
  }
41
- const gitChanges = this.collectGitChanges(event.cwd);
42
- let durationMs = summary.durationMs;
47
+ const gitChanges = collectGitChanges(event.cwd);
48
+ let durationMs = Math.max(0, summary.durationMs);
43
49
  if (durationMs === 0 && summary.lastAssistantMessage) {
44
- durationMs = 1000;
50
+ durationMs = DEFAULT_FALLBACK_DURATION_MS;
45
51
  }
46
52
  const data = {
47
53
  projectName: extractProjectName(event.cwd),
@@ -53,23 +59,13 @@ export class HookHandler {
53
59
  cacheCreationTokens: summary.cacheCreationTokens,
54
60
  cacheReadTokens: summary.cacheReadTokens,
55
61
  };
56
- const notification = formatNotification(data);
57
62
  const responseUrl = this.buildResponseUrl(data);
58
- this.notify(notification, responseUrl).catch((err) => {
59
- log(t("hook.notificationFailed", { error: formatError(err) }));
63
+ this.channel.sendNotification(data, responseUrl).catch((err) => {
64
+ logError(t("hook.notificationFailed"), err);
60
65
  });
61
66
  }
62
67
  buildResponseUrl(data) {
63
- const id = responseStore.save({
64
- projectName: data.projectName,
65
- responseSummary: data.responseSummary,
66
- durationMs: data.durationMs,
67
- gitChanges: data.gitChanges,
68
- inputTokens: data.inputTokens,
69
- outputTokens: data.outputTokens,
70
- cacheCreationTokens: data.cacheCreationTokens,
71
- cacheReadTokens: data.cacheReadTokens,
72
- });
68
+ const id = responseStore.save(data);
73
69
  const apiBase = this.tunnelManager.getPublicUrl() || `http://localhost:${this.hookPort}`;
74
70
  const params = new URLSearchParams({
75
71
  id,
@@ -79,83 +75,5 @@ export class HookHandler {
79
75
  });
80
76
  return `${MINI_APP_BASE_URL}/response.html?${params.toString()}`;
81
77
  }
82
- collectGitChanges(cwd) {
83
- try {
84
- const diffOutput = execSync("git diff --name-status HEAD", {
85
- cwd,
86
- encoding: "utf-8",
87
- timeout: GIT_TIMEOUT_MS,
88
- });
89
- const changes = this.parseGitDiffOutput(diffOutput);
90
- try {
91
- const untrackedOutput = execSync("git ls-files --others --exclude-standard", {
92
- cwd,
93
- encoding: "utf-8",
94
- timeout: GIT_TIMEOUT_MS,
95
- });
96
- for (const file of untrackedOutput.trim().split("\n")) {
97
- if (file)
98
- changes.push({ file, status: GitChangeStatus.Added });
99
- }
100
- }
101
- catch { }
102
- return changes;
103
- }
104
- catch {
105
- try {
106
- const porcelainOutput = execSync("git status --porcelain", {
107
- cwd,
108
- encoding: "utf-8",
109
- timeout: GIT_TIMEOUT_MS,
110
- });
111
- return this.parsePorcelainOutput(porcelainOutput);
112
- }
113
- catch {
114
- return [];
115
- }
116
- }
117
- }
118
- parseGitDiffOutput(output) {
119
- const changes = [];
120
- for (const line of output.trim().split("\n")) {
121
- if (!line)
122
- continue;
123
- const parts = line.split("\t");
124
- if (parts.length < 2)
125
- continue;
126
- let status = GitChangeStatus.Modified;
127
- if (parts[0].startsWith("A"))
128
- status = GitChangeStatus.Added;
129
- else if (parts[0].startsWith("D"))
130
- status = GitChangeStatus.Deleted;
131
- else if (parts[0].startsWith("R"))
132
- status = GitChangeStatus.Renamed;
133
- changes.push({ file: parts[1], status });
134
- }
135
- return changes;
136
- }
137
- parsePorcelainOutput(output) {
138
- const changes = [];
139
- for (const line of output.trim().split("\n")) {
140
- if (line.length < 4)
141
- continue;
142
- const statusCode = line.slice(0, 2).trim();
143
- const file = line.slice(3).trim();
144
- let status = GitChangeStatus.Modified;
145
- switch (statusCode) {
146
- case "??":
147
- case "A":
148
- status = GitChangeStatus.Added;
149
- break;
150
- case "D":
151
- status = GitChangeStatus.Deleted;
152
- break;
153
- case "R":
154
- status = GitChangeStatus.Renamed;
155
- break;
156
- }
157
- changes.push({ file, status });
158
- }
159
- return changes;
160
- }
161
78
  }
79
+ //# sourceMappingURL=hook-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-handler.js","sourceRoot":"","sources":["../../src/hook/hook-handler.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,4 @@
1
1
  export declare class HookInstaller {
2
- private static readonly HOOKS_DIR;
3
- private static readonly SCRIPT_PATH;
4
- private static readonly SETTINGS_PATH;
5
2
  static isInstalled(): boolean;
6
3
  static install(hookPort: number, hookSecret: string): void;
7
4
  static uninstall(): void;
@@ -1,11 +1,8 @@
1
- import { readFileSync, writeFileSync, mkdirSync, unlinkSync, rmdirSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { homedir } from "node:os";
1
+ import { readFileSync, writeFileSync, mkdirSync, unlinkSync, rmSync } from "node:fs";
4
2
  import { t } from "../i18n/index.js";
3
+ import { paths } from "../utils/paths.js";
4
+ import { ApiRoute } from "../utils/constants.js";
5
5
  export class HookInstaller {
6
- static HOOKS_DIR = join(homedir(), ".ccbot", "hooks");
7
- static SCRIPT_PATH = join(HookInstaller.HOOKS_DIR, "stop-notify.sh");
8
- static SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
9
6
  static isInstalled() {
10
7
  try {
11
8
  const settings = HookInstaller.readSettings();
@@ -31,12 +28,12 @@ export class HookInstaller {
31
28
  throw new Error(t("config.hookAlreadyInstalled"));
32
29
  }
33
30
  existingStop.push({
34
- hooks: [{ type: "command", command: HookInstaller.SCRIPT_PATH, timeout: 10 }],
31
+ hooks: [{ type: "command", command: paths.hookScript, timeout: 10 }],
35
32
  });
36
33
  hooks.Stop = existingStop;
37
34
  settings.hooks = hooks;
38
- mkdirSync(join(homedir(), ".claude"), { recursive: true });
39
- writeFileSync(HookInstaller.SETTINGS_PATH, JSON.stringify(settings, null, 2));
35
+ mkdirSync(paths.claudeDir, { recursive: true });
36
+ writeFileSync(paths.claudeSettings, JSON.stringify(settings, null, 2));
40
37
  HookInstaller.installScript(hookPort, hookSecret);
41
38
  }
42
39
  static uninstall() {
@@ -44,29 +41,31 @@ export class HookInstaller {
44
41
  HookInstaller.removeScript();
45
42
  }
46
43
  static installScript(hookPort, hookSecret) {
47
- mkdirSync(HookInstaller.HOOKS_DIR, { recursive: true });
48
- const script = `#!/bin/bash
49
- curl -s -X POST http://localhost:${hookPort}/hook/stop \\
50
- -H "Content-Type: application/json" \\
51
- -H "X-CCBot-Secret: ${hookSecret}" \\
52
- --data-binary @- > /dev/null 2>&1 || true
53
- `;
54
- writeFileSync(HookInstaller.SCRIPT_PATH, script, { mode: 0o755 });
44
+ mkdirSync(paths.hooksDir, { recursive: true });
45
+ const isWindows = process.platform === "win32";
46
+ const script = isWindows
47
+ ? `@echo off\ncurl -s -X POST http://localhost:${hookPort}${ApiRoute.HookStop} -H "Content-Type: application/json" -H "X-CCBot-Secret: ${hookSecret}" --data-binary @- > nul 2>&1\n`
48
+ : `#!/bin/bash\ncurl -s -X POST http://localhost:${hookPort}${ApiRoute.HookStop} \\\n -H "Content-Type: application/json" \\\n -H "X-CCBot-Secret: ${hookSecret}" \\\n --data-binary @- > /dev/null 2>&1 || true\n`;
49
+ writeFileSync(paths.hookScript, script, { mode: isWindows ? 0o644 : 0o755 });
55
50
  }
56
51
  static removeScript() {
57
52
  try {
58
- unlinkSync(HookInstaller.SCRIPT_PATH);
53
+ unlinkSync(paths.hookScript);
54
+ }
55
+ catch {
56
+ // script file may not exist
59
57
  }
60
- catch { }
61
58
  try {
62
- rmdirSync(HookInstaller.HOOKS_DIR);
59
+ rmSync(paths.hooksDir, { recursive: true, force: true });
60
+ }
61
+ catch {
62
+ // hooks directory may not exist
63
63
  }
64
- catch { }
65
64
  }
66
65
  static removeFromSettings() {
67
66
  let data;
68
67
  try {
69
- data = readFileSync(HookInstaller.SETTINGS_PATH, "utf-8");
68
+ data = readFileSync(paths.claudeSettings, "utf-8");
70
69
  }
71
70
  catch {
72
71
  return;
@@ -91,18 +90,21 @@ curl -s -X POST http://localhost:${hookPort}/hook/stop \\
91
90
  if (Object.keys(hooks).length === 0) {
92
91
  delete settings.hooks;
93
92
  }
94
- writeFileSync(HookInstaller.SETTINGS_PATH, JSON.stringify(settings, null, 2));
93
+ writeFileSync(paths.claudeSettings, JSON.stringify(settings, null, 2));
95
94
  }
96
95
  static readSettings() {
97
96
  try {
98
- const data = readFileSync(HookInstaller.SETTINGS_PATH, "utf-8");
97
+ const data = readFileSync(paths.claudeSettings, "utf-8");
99
98
  return JSON.parse(data);
100
99
  }
101
100
  catch (err) {
102
- if (err instanceof Error && "code" in err && err.code === "ENOENT") {
101
+ if (err instanceof Error &&
102
+ "code" in err &&
103
+ err.code === "ENOENT") {
103
104
  return {};
104
105
  }
105
- throw new Error(t("config.readSettingsError", { error: err instanceof Error ? err.message : String(err) }));
106
+ throw err;
106
107
  }
107
108
  }
108
109
  }
110
+ //# sourceMappingURL=hook-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-installer.js","sourceRoot":"","sources":["../../src/hook/hook-installer.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,11 @@
1
- import express from "express";
2
- import { join, dirname } from "node:path";
3
- import { fileURLToPath } from "node:url";
1
+ import express, {} from "express";
2
+ import { HookHandler } from "./hook-handler.js";
4
3
  import { responseStore } from "../utils/response-store.js";
5
- import { MINI_APP_BASE_URL } from "../utils/constants.js";
4
+ import { MINI_APP_BASE_URL, ApiRoute } from "../utils/constants.js";
6
5
  import { t } from "../i18n/index.js";
7
6
  import { log } from "../utils/log.js";
8
- const __dirname = dirname(fileURLToPath(import.meta.url));
9
- const PUBLIC_DIR = join(__dirname, "../../public");
7
+ import { paths } from "../utils/paths.js";
8
+ const ALLOWED_CORS_ORIGIN = new URL(MINI_APP_BASE_URL).origin;
10
9
  export class HookServer {
11
10
  app;
12
11
  server = null;
@@ -38,9 +37,11 @@ export class HookServer {
38
37
  createApp() {
39
38
  const app = express();
40
39
  app.use(express.json({ limit: "10mb" }));
41
- app.use(express.static(PUBLIC_DIR));
42
- app.get("/api/responses/:id", (req, res) => {
43
- res.header("Access-Control-Allow-Origin", new URL(MINI_APP_BASE_URL).origin);
40
+ app.use(express.static(paths.publicDir));
41
+ app.get(ApiRoute.ResponseData, (req, res) => {
42
+ const requestOrigin = req.headers.origin ?? "";
43
+ const isTunnel = requestOrigin.endsWith(".trycloudflare.com");
44
+ res.header("Access-Control-Allow-Origin", isTunnel ? requestOrigin : ALLOWED_CORS_ORIGIN);
44
45
  const data = responseStore.get(req.params.id);
45
46
  if (!data) {
46
47
  res.status(404).json({ error: "not_found" });
@@ -48,10 +49,7 @@ export class HookServer {
48
49
  }
49
50
  res.json(data);
50
51
  });
51
- app.get("/response/:id", (_req, res) => {
52
- res.sendFile(join(PUBLIC_DIR, "response.html"));
53
- });
54
- app.post("/hook/stop", (req, res) => {
52
+ app.post(ApiRoute.HookStop, (req, res) => {
55
53
  const receivedSecret = req.headers["x-ccbot-secret"];
56
54
  if (receivedSecret !== this.secret) {
57
55
  res.status(403).send("forbidden");
@@ -60,9 +58,10 @@ export class HookServer {
60
58
  setImmediate(() => this.handler?.handleStopEvent(req.body));
61
59
  res.status(200).send("ok");
62
60
  });
63
- app.get("/health", (_req, res) => {
61
+ app.get(ApiRoute.Health, (_req, res) => {
64
62
  res.status(200).send("healthy");
65
63
  });
66
64
  return app;
67
65
  }
68
66
  }
67
+ //# sourceMappingURL=hook-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-server.js","sourceRoot":"","sources":["../../src/hook/hook-server.ts"],"names":[],"mappings":"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"}
@@ -52,3 +52,4 @@ export function t(key, params) {
52
52
  export function getTranslations() {
53
53
  return localeMap[currentLocale];
54
54
  }
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/i18n/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAIrC,MAAM,CAAC,MAAM,iBAAiB,GAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAEhF,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,IAAI;CACT,CAAC;AAEF,MAAM,SAAS,GAAoC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;AAElE,IAAI,aAAa,GAAW,IAAI,CAAC;AAEjC,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,aAAa,GAAG,MAAM,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,iBAAiB,CAAC,QAAQ,CAAC,KAAe,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,UAAU,CAAC,YAA6B,EAAE,GAAW;IAC5D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,MAAM,GAAY,YAAY,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1E,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,GAAI,MAAkC,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,CAAC,CAAC,GAAW,EAAE,MAAwC;IACrE,IAAI,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,GAAG,CAAC,CAAC;IAEtD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,KAAK,GAAG,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,KAAK,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5D,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,QAAQ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,SAAS,CAAC,aAAa,CAAC,CAAC;AAClC,CAAC"}
@@ -4,11 +4,11 @@ export const en = {
4
4
  shuttingDown: "shutting down...",
5
5
  telegramStarted: "telegram bot started",
6
6
  commandsRegistered: "commands registered",
7
- commandsRegisterFailed: "failed to register commands: {error}",
7
+ commandsRegisterFailed: "failed to register commands",
8
8
  menuButtonRegistered: "mini app menu button registered",
9
- menuButtonFailed: "failed to register menu button: {error}",
9
+ menuButtonFailed: "failed to register menu button",
10
10
  noChatId: "no chat ID yet — run 'ccbot setup' or send /start to the bot",
11
- notificationFailed: "failed to send notification: {error}",
11
+ notificationFailed: "failed to send notification",
12
12
  registeredChatId: "registered chat ID {chatId}",
13
13
  unauthorizedUser: "unauthorized user {userId} ({username})",
14
14
  ready: "✅ *ccbot* is ready\\.\n\nYou will receive notifications when Claude Code completes a response\\.",
@@ -20,6 +20,8 @@ export const en = {
20
20
  },
21
21
  viewDetails: "📱 View details",
22
22
  dashboard: "📱 Dashboard",
23
+ sendFailed: "send failed, falling back",
24
+ sendFallbackFailed: "fallback also failed",
23
25
  },
24
26
  setup: {
25
27
  intro: "🤖 ccbot setup",
@@ -54,13 +56,19 @@ export const en = {
54
56
  intro: "📦 ccbot update",
55
57
  npxAlreadyLatest: "Installed via npx — always uses latest version, no update needed.",
56
58
  npxDone: "Already up to date",
59
+ checking: "Checking version...",
60
+ alreadyLatestNpm: "Already up to date (v{version})",
61
+ alreadyLatestGit: "Already up to date (commit {hash})",
62
+ updatingNpm: "Updating via {pm} (v{from} → v{to})...",
57
63
  updating: "Updating via {pm}...",
58
- updateSuccess: "Updated successfully",
64
+ updateSuccess: "Updated successfully (v{from} → v{to})",
59
65
  updateComplete: "Update complete",
60
66
  updateFailed: "Update failed",
67
+ noUpdateNeeded: "✨ No update needed",
61
68
  updateManualGlobal: "Try manually: {cmd}",
62
69
  pulling: "Pulling latest changes...",
63
70
  pulled: "Pulled latest changes",
71
+ pulledGit: "Pulled latest changes ({from} → {to})",
64
72
  installingDeps: "Installing dependencies...",
65
73
  depsInstalled: "Dependencies installed",
66
74
  building: "Building...",
@@ -83,20 +91,20 @@ export const en = {
83
91
  serverListening: "hook server listening on localhost:{port}",
84
92
  invalidPayload: "invalid stop event payload — missing required fields",
85
93
  stopEventReceived: "stop event received for session {sessionId} at {cwd}",
86
- transcriptFailed: "failed to parse transcript: {error}",
87
- notificationFailed: "failed to send notification: {error}",
94
+ transcriptFailed: "failed to parse transcript",
95
+ notificationFailed: "failed to send notification",
88
96
  },
89
97
  tunnel: {
90
98
  installing: "installing cloudflared binary...",
91
99
  installed: "cloudflared binary installed",
92
100
  started: "🌐 public URL: {url}",
93
- failed: "⚠️ tunnel failed, using localhost only. {error}",
101
+ failed: "⚠️ tunnel failed, using localhost only",
94
102
  disconnected: "⚠️ tunnel disconnected, reconnecting...",
95
103
  exited: "tunnel process exited (code {code})",
104
+ timeout: "tunnel connection timeout ({seconds}s)",
96
105
  },
97
106
  config: {
98
107
  notFound: "config not found — run 'ccbot setup' first",
99
- readError: "read config: {error}",
100
108
  mustBeObject: "config must be a JSON object",
101
109
  invalidToken: "telegram_bot_token must be a string containing ':' — run 'ccbot setup'",
102
110
  invalidUserId: "user_id must be an integer — run 'ccbot setup'",
@@ -104,11 +112,8 @@ export const en = {
104
112
  invalidSecret: "hook_secret must contain only hex characters (a-f, 0-9)",
105
113
  invalidHookPort: "invalid hook port: {port} (must be 1-65535)",
106
114
  hookAlreadyInstalled: "ccbot hook already installed",
107
- readSettingsError: "read settings: {error}",
108
115
  },
109
116
  notification: {
110
- title: "🤖 *Claude Code Response*",
111
- changes: "📂 *Changes:*",
112
117
  tokens: "tokens",
113
118
  cache: "cache",
114
119
  cacheRead: "read",
@@ -116,6 +121,7 @@ export const en = {
116
121
  },
117
122
  common: {
118
123
  unknownCommand: "unknown command: {command}",
119
- setupFailed: "setup failed: {error}",
124
+ setupFailed: "setup failed",
120
125
  },
121
126
  };
127
+ //# sourceMappingURL=en.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en.js","sourceRoot":"","sources":["../../../src/i18n/locales/en.ts"],"names":[],"mappings":"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"}