claude-telegram-bot 0.2.4 → 0.2.5

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.ko.md CHANGED
@@ -92,7 +92,7 @@ claude-telegram-bot ~/botconfigs/myproj/config.json
92
92
  | `projectDir` | Claude가 작업할 폴더의 절대경로 |
93
93
  | `claudeBin` | `which claude` 결과 (절대경로 권장) |
94
94
  | `permissionMode` | `plan`(읽기·계획만) / `acceptEdits`(편집 자동 승인) / `bypassPermissions`(쉘 포함 전부 자동) |
95
- | `model` | 비우면 기본 모델. `opus`, `sonnet` |
95
+ | `model` | 비우면 기본 모델. `opus`, `sonnet` 등. 런타임에 `/model`로 전환 가능(state에 저장) |
96
96
  | `lang` | (선택) UI 언어. 비우면 사용자별 자동 판별(기본 영어, 텔레그램이 한국어면 한국어). `"en"`/`"ko"`로 고정 가능 |
97
97
  | `name` | (선택) `/help`에 표시되는 봇 이름. 여러 봇 구분용 |
98
98
  | `persona` | (선택) 역할 시스템 프롬프트. 페르소나 봇 정의용 |
@@ -110,7 +110,7 @@ claude-telegram-bot ~/botconfigs/myproj/config.json
110
110
  - `테스트 돌려보고 통과하면 커밋하고 push 해줘`
111
111
  - `api.ts 에 에러 핸들링 추가해줘`
112
112
 
113
- 명령어: `/new`(맥락 초기화) · `/cron`(예약 작업 보기·추가·삭제) · `/restart`(문법 검사 후 재시작) · `/status`(봇 상태·버전) · `/id`(채팅 ID 확인) · `/help`(도움말)
113
+ 명령어: `/new`(맥락 초기화) · `/cron`(예약 작업 보기·추가·삭제) · `/restart`(문법 검사 후 재시작) · `/status`(봇 상태·버전) · `/model`(모델 보기·전환) · `/id`(채팅 ID 확인) · `/help`(도움말)
114
114
 
115
115
  > **`/restart`** 는 먼저 `bot.mjs` 에 `node --check` 를 돌려 **문법 오류가 있으면 재시작을 취소**합니다(잘못된 수정이 봇을 크래시 루프에 빠뜨리는 것 방지). 통과하면 프로세스를 종료하고, 다시 띄우는 건 프로세스 관리자에게 맡깁니다. [launchd 설정](#상시-실행-launchd)(`KeepAlive`)이면 바로 동작하고, 관리자 없이 `node bot.mjs` 로만 돌리면 그냥 멈춥니다. 재시작 후 대화 세션은 `state.json` 의 ID로 이어집니다.
116
116
 
package/README.md CHANGED
@@ -154,7 +154,7 @@ auth layer.)
154
154
  - `run the solver tests and commit + push if they pass`
155
155
  - `add an edge case to solve-2nd-floor-edges.ts`
156
156
 
157
- Commands: `/new` (reset context / new session) · `/cron` (list / add / remove scheduled tasks) · `/restart` (syntax-check & restart the bot) · `/status` (bot status & version) · `/id` (show chat ID) · `/help`.
157
+ Commands: `/new` (reset context / new session) · `/cron` (list / add / remove scheduled tasks) · `/restart` (syntax-check & restart the bot) · `/status` (bot status & version) · `/model` (view / switch the model) · `/id` (show chat ID) · `/help`.
158
158
 
159
159
  > **`/restart`** runs `node --check` on `bot.mjs` first and **aborts the restart if it has a syntax
160
160
  > error** (so a bad edit can't crash-loop the bot), then exits — relying on a process supervisor
@@ -184,7 +184,7 @@ Edit `config.json`:
184
184
  | `projectDir` | Absolute path to the working folder Claude runs in |
185
185
  | `claudeBin` | Output of `which claude` (absolute path recommended) |
186
186
  | `permissionMode` | `plan` / `acceptEdits` / `bypassPermissions` — see [Security](#security) |
187
- | `model` | Empty = default. Or `opus` / `sonnet`, etc. |
187
+ | `model` | Empty = default. Or `opus` / `sonnet`, etc. Override at runtime with `/model` (persists in state). |
188
188
  | `lang` | (optional) UI language. Empty = auto-detect per user (English default, Korean for Korean Telegram clients). Force with `"en"` / `"ko"`. |
189
189
  | `name` | (optional) Bot name shown in `/help` — handy for telling multiple bots apart |
190
190
  | `persona` | (optional) Role system prompt — defines a persona (developer/planner/…). See below |
package/bot.mjs CHANGED
@@ -129,6 +129,7 @@ const STR = {
129
129
  "• /cron — list tasks · /cron add <natural language> to add · /cron rm <id> to remove\n" +
130
130
  "• /restart — restart the bot (after a syntax check)\n" +
131
131
  "• /status — bot status & version\n" +
132
+ "• /model — view / switch the model\n" +
132
133
  "• /id — show this chat ID\n" +
133
134
  `\nWorking dir: ${cfg.projectDir}\nPermission mode: ${cfg.permissionMode}`,
134
135
  newSession: "🆕 Started a new conversation (previous context cleared).",
@@ -168,6 +169,12 @@ const STR = {
168
169
  `• Scheduled jobs: ${i.jobs}\n` +
169
170
  `• Project: ${i.projectDir}\n` +
170
171
  `• Permission: ${i.permissionMode}`,
172
+ modelStatus: (cur, list) =>
173
+ `🧠 Model: ${cur}\n` +
174
+ `Switch: ${list.map((x) => `/model ${x}`).join(" · ")} (or a full model id)\n` +
175
+ `/model default — clear the override`,
176
+ modelSet: (m) => `🧠 Model set to: ${m}`,
177
+ modelReset: (def) => `🧠 Model reset to default (${def}).`,
171
178
  },
172
179
  ko: {
173
180
  help: () =>
@@ -177,6 +184,7 @@ const STR = {
177
184
  "• /cron — 예약 작업 보기 · /cron add <자연어>로 추가 · /cron rm <번호>로 삭제\n" +
178
185
  "• /restart — 봇 재시작 (문법 검사 후 안전하게)\n" +
179
186
  "• /status — 봇 상태·버전 보기\n" +
187
+ "• /model — 모델 보기·전환\n" +
180
188
  "• /id — 이 채팅 ID 확인\n" +
181
189
  `\n작업 폴더: ${cfg.projectDir}\n권한 모드: ${cfg.permissionMode}`,
182
190
  newSession: "🆕 새 대화를 시작합니다 (이전 맥락 초기화).",
@@ -215,6 +223,12 @@ const STR = {
215
223
  `• 예약 작업: ${i.jobs}개\n` +
216
224
  `• 작업 폴더: ${i.projectDir}\n` +
217
225
  `• 권한 모드: ${i.permissionMode}`,
226
+ modelStatus: (cur, list) =>
227
+ `🧠 현재 모델: ${cur}\n` +
228
+ `전환: ${list.map((x) => `/model ${x}`).join(" · ")} (또는 전체 모델 ID)\n` +
229
+ `/model default — 오버라이드 해제`,
230
+ modelSet: (m) => `🧠 모델을 ${m} (으)로 설정했습니다.`,
231
+ modelReset: (def) => `🧠 모델을 기본값(${def})으로 되돌렸습니다.`,
218
232
  },
219
233
  };
220
234
  const t = (l, key, ...a) => {
@@ -222,6 +236,9 @@ const t = (l, key, ...a) => {
222
236
  return typeof v === "function" ? v(...a) : v;
223
237
  };
224
238
 
239
+ // /model 에서 보여줄 추천 별칭(claude CLI 가 별칭·전체 모델 ID 모두 허용).
240
+ const MODEL_SUGGESTIONS = ["opus", "sonnet", "haiku"];
241
+
225
242
  // /(슬래시) 자동완성 메뉴용 명령 목록 (언어별). setMyCommands 로 등록.
226
243
  const COMMANDS = {
227
244
  en: [
@@ -229,6 +246,7 @@ const COMMANDS = {
229
246
  { command: "cron", description: "List / add / remove scheduled tasks" },
230
247
  { command: "restart", description: "Restart the bot (after syntax check)" },
231
248
  { command: "status", description: "Bot status / version" },
249
+ { command: "model", description: "View / switch the model" },
232
250
  { command: "id", description: "Show this chat ID" },
233
251
  { command: "help", description: "Help" },
234
252
  ],
@@ -237,6 +255,7 @@ const COMMANDS = {
237
255
  { command: "cron", description: "예약 작업 보기·추가·삭제" },
238
256
  { command: "restart", description: "봇 재시작 (문법 검사 후)" },
239
257
  { command: "status", description: "봇 상태·버전 보기" },
258
+ { command: "model", description: "모델 보기·전환" },
240
259
  { command: "id", description: "이 채팅 ID 확인" },
241
260
  { command: "help", description: "도움말" },
242
261
  ],
@@ -260,7 +279,7 @@ function saveState(s) {
260
279
  }
261
280
  }
262
281
  migrateData(); // 루트 직하 → .claude-bot/ 1회 이주(있으면) 후 state 로드
263
- let state = loadState(); // { sessionId?, cron?: [{ id, cron, prompt, label? }], restartNotify? }
282
+ let state = loadState(); // { sessionId?, cron?: [{ id, cron, prompt, label? }], restartNotify?, model? }
264
283
 
265
284
  // ── 텔레그램 헬퍼 ─────────────────────────────────────────────────────────
266
285
  async function tg(method, body) {
@@ -376,7 +395,8 @@ function runClaude(prompt, sessionId) {
376
395
  // 페르소나(cfg.persona) + 간결 지침을 함께 주입 → 멀티 봇(역할별) 운영용
377
396
  const appendSys = [cfg.persona, brevity].filter(Boolean).join("\n\n");
378
397
  if (appendSys) args.push("--append-system-prompt", appendSys);
379
- if (cfg.model) args.push("--model", cfg.model);
398
+ const model = state.model || cfg.model; // /model 로 바꾸면 state.model 우선
399
+ if (model) args.push("--model", model);
380
400
  if (sessionId) args.push("--resume", sessionId);
381
401
 
382
402
  const child = spawn(cfg.claudeBin || "claude", args, {
@@ -684,7 +704,7 @@ async function handle(msg) {
684
704
  t(l, "status", {
685
705
  version: VERSION,
686
706
  name: cfg.name || "claude-telegram-bot",
687
- model: cfg.model || (l === "ko" ? "(기본값)" : "(default)"),
707
+ model: state.model || cfg.model || (l === "ko" ? "(기본값)" : "(default)"),
688
708
  hasSession: Boolean(state.sessionId),
689
709
  jobs: schedule.length,
690
710
  projectDir: cfg.projectDir,
@@ -693,6 +713,24 @@ async function handle(msg) {
693
713
  );
694
714
  return;
695
715
  }
716
+ if (text === "/model" || text.startsWith("/model ")) {
717
+ const arg = text.slice(6).trim();
718
+ if (!arg) {
719
+ const cur = state.model || cfg.model || (l === "ko" ? "(기본값)" : "(default)");
720
+ await send(chatId, t(l, "modelStatus", cur, MODEL_SUGGESTIONS));
721
+ return;
722
+ }
723
+ if (arg === "default" || arg === "reset") {
724
+ state.model = undefined;
725
+ saveState(state);
726
+ await send(chatId, t(l, "modelReset", cfg.model || (l === "ko" ? "기본값" : "default")));
727
+ return;
728
+ }
729
+ state.model = arg;
730
+ saveState(state);
731
+ await send(chatId, t(l, "modelSet", arg));
732
+ return;
733
+ }
696
734
  if (text === "/cron" || text.startsWith("/cron ")) {
697
735
  await handleCron(chatId, text.slice(5).trim(), l);
698
736
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-telegram-bot",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Drive Claude Code from Telegram — messages run headless `claude -p` in a project dir and replies come back to the chat. Zero dependencies.",
5
5
  "type": "module",
6
6
  "bin": {