@raolin2025/claude-code-node 2.6.15 → 2.6.17
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/package.json +1 -1
- package/src/channel/tg-listener.js +5 -3
- package/src/core/cli.js +44 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raolin2025/claude-code-node",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.17",
|
|
4
4
|
"description": "Node.js AI Code Agent CLI - Zero dependencies, pure JavaScript, security hardened, multi-channel notifications, Telegram & QQ Bot remote programming, rich media upload, multi-account management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/core/index.js",
|
|
@@ -118,7 +118,9 @@ export class TelegramBotClient {
|
|
|
118
118
|
const body = {
|
|
119
119
|
chat_id: chatId,
|
|
120
120
|
text: text.slice(0, 4096), // Telegram 消息最大 4096 字符
|
|
121
|
-
|
|
121
|
+
// parseMode: null 表示降级为纯文本(去掉 parse_mode 字段);
|
|
122
|
+
// 否则默认 HTML,或用显式指定的 parseMode。
|
|
123
|
+
...(parseMode === null ? {} : { parse_mode: parseMode || 'HTML' }),
|
|
122
124
|
disable_notification: silent || false,
|
|
123
125
|
disable_web_page_preview: disableWebPreview ?? true,
|
|
124
126
|
}
|
|
@@ -139,9 +141,9 @@ export class TelegramBotClient {
|
|
|
139
141
|
await new Promise(r => setTimeout(r, retryAfter * 1000))
|
|
140
142
|
return this.sendMessage(chatId, text, options)
|
|
141
143
|
}
|
|
142
|
-
// 400 可能是消息太长或格式问题 —
|
|
144
|
+
// 400 可能是消息太长或格式问题 — 降级为纯文本(parseMode: null 去掉 parse_mode)
|
|
143
145
|
if (data.error_code === 400 && parseMode) {
|
|
144
|
-
return this.sendMessage(chatId, text, { ...options, parseMode:
|
|
146
|
+
return this.sendMessage(chatId, text, { ...options, parseMode: null })
|
|
145
147
|
}
|
|
146
148
|
throw new Error(`Telegram API ${data.error_code}: ${data.description?.slice(0, 200) || 'unknown'}`)
|
|
147
149
|
}
|
package/src/core/cli.js
CHANGED
|
@@ -599,6 +599,8 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
599
599
|
let currentSource = 'cli'
|
|
600
600
|
// 等待中的 Telegram 权限确认(resolve 回调)— 远程用户回复 y/n/a 时响应
|
|
601
601
|
let pendingConfirm = null
|
|
602
|
+
// 最近一次 /models 拉取的模型列表(供 /model <编号> 选择)
|
|
603
|
+
let modelList = []
|
|
602
604
|
|
|
603
605
|
// 处理输入行
|
|
604
606
|
// source: 'cli' 来自终端输入, 'telegram' 来自 Telegram
|
|
@@ -634,6 +636,15 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
634
636
|
}
|
|
635
637
|
|
|
636
638
|
if (trimmed.startsWith('/')) {
|
|
639
|
+
// 来自 Telegram 的命令:捕获 console 输出并回发到 Telegram
|
|
640
|
+
const isTgCmd = source === 'telegram' && tgListener?.bot
|
|
641
|
+
let tgOut = ''
|
|
642
|
+
const origLog = console.log
|
|
643
|
+
if (isTgCmd) {
|
|
644
|
+
tgOut = ''
|
|
645
|
+
console.log = (...args) => { tgOut += args.map(String).join(' ') + '\n'; origLog(...args) }
|
|
646
|
+
}
|
|
647
|
+
try {
|
|
637
648
|
const [cmd, ...rest] = trimmed.slice(1).split(' ')
|
|
638
649
|
switch (cmd) {
|
|
639
650
|
case 'help':
|
|
@@ -646,7 +657,16 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
646
657
|
}
|
|
647
658
|
break
|
|
648
659
|
case 'model':
|
|
649
|
-
|
|
660
|
+
// /model <名字或编号> — 支持用 /models 列表里的编号切换
|
|
661
|
+
if (rest[0]) {
|
|
662
|
+
const num = parseInt(rest[0], 10)
|
|
663
|
+
if (!isNaN(num) && modelList.length > 0 && num >= 1 && num <= modelList.length) {
|
|
664
|
+
engine.config.model = modelList[num - 1]
|
|
665
|
+
} else {
|
|
666
|
+
engine.config.model = rest.join(' ')
|
|
667
|
+
}
|
|
668
|
+
console.log(`Model → ${engine.config.model}`)
|
|
669
|
+
}
|
|
650
670
|
else console.log(`Model: ${engine.config.model}`)
|
|
651
671
|
break
|
|
652
672
|
case 'models': {
|
|
@@ -668,17 +688,23 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
668
688
|
const data = await res.json()
|
|
669
689
|
const models = data.data || []
|
|
670
690
|
if (models.length === 0) { console.log('No models returned'); break }
|
|
691
|
+
// 记录模型列表,供 /model <编号> 选择
|
|
692
|
+
modelList = models.map(m => m.id || m)
|
|
671
693
|
console.log(`\nAvailable models (${models.length}):`)
|
|
672
|
-
|
|
673
|
-
const id = m.id || m
|
|
694
|
+
modelList.forEach((id, i) => {
|
|
674
695
|
console.log(` ${(i + 1).toString().padStart(2)}. ${id}`)
|
|
675
696
|
})
|
|
697
|
+
// 来自 Telegram:直接列出,不等待 CLI 交互(用 /model 名字或编号 切换)
|
|
698
|
+
if (source === 'telegram') {
|
|
699
|
+
console.log('\nℹ️ 用 /model 名字或编号 切换模型')
|
|
700
|
+
break
|
|
701
|
+
}
|
|
676
702
|
console.log('\nType a number to select, or model name directly:')
|
|
677
703
|
const answer = await new Promise(resolve => rl.question('> ', resolve))
|
|
678
704
|
const num = parseInt(answer, 10)
|
|
679
705
|
let selected
|
|
680
|
-
if (!isNaN(num) && num >= 1 && num <=
|
|
681
|
-
selected =
|
|
706
|
+
if (!isNaN(num) && num >= 1 && num <= modelList.length) {
|
|
707
|
+
selected = modelList[num - 1]
|
|
682
708
|
} else if (answer.trim()) {
|
|
683
709
|
selected = answer.trim()
|
|
684
710
|
}
|
|
@@ -851,6 +877,13 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
851
877
|
default:
|
|
852
878
|
console.log(`Unknown command: /${cmd}. Type /help for available commands.`)
|
|
853
879
|
}
|
|
880
|
+
} finally {
|
|
881
|
+
// 恢复 console.log 并把命令输出回发到 Telegram
|
|
882
|
+
if (isTgCmd) {
|
|
883
|
+
console.log = origLog
|
|
884
|
+
if (tgOut.trim()) await sendTelegram(tgOut.trim(), tgChatId || null)
|
|
885
|
+
}
|
|
886
|
+
}
|
|
854
887
|
showPrompt()
|
|
855
888
|
return
|
|
856
889
|
}
|
|
@@ -1068,10 +1101,10 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
1068
1101
|
tgReplyTarget = msg.replyTo || null
|
|
1069
1102
|
const text = msg.text || msg.callbackData || ''
|
|
1070
1103
|
if (!text) return
|
|
1071
|
-
//
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1104
|
+
// 普通消息和 / 命令都转给引擎(/命令由 processInputLine 处理)
|
|
1105
|
+
// 注意:tg-listener 已内部处理 /ping /status /run 等自己的命令,
|
|
1106
|
+
// 只有未识别的 / 命令(如 /models /stop /resume)才会到达这里。
|
|
1107
|
+
await processInputLine(text, 'telegram', msg.chatId)
|
|
1075
1108
|
}).catch(e => console.error(`[TG] listener error: ${e.message}`))
|
|
1076
1109
|
console.log(`✅ Telegram channel ready (bot ${tgToken.slice(0, 12)}...)`)
|
|
1077
1110
|
} catch (e) {
|
|
@@ -1094,9 +1127,9 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
1094
1127
|
// 记录全局回复目标,供权限确认 / AI 回复镜像发送到 Telegram 使用
|
|
1095
1128
|
if (msg.chatId) tgChatId = msg.chatId
|
|
1096
1129
|
if (msg.replyTo) tgReplyTarget = msg.replyTo
|
|
1097
|
-
// 来自外部的消息 → 转发到 REPL
|
|
1130
|
+
// 来自外部的消息 → 转发到 REPL 引擎(含 / 命令,由 processInputLine 处理)
|
|
1098
1131
|
const text = msg.text || ''
|
|
1099
|
-
if (text
|
|
1132
|
+
if (text) {
|
|
1100
1133
|
await processInputLine(text, msg.channel || 'external', msg.chatId)
|
|
1101
1134
|
}
|
|
1102
1135
|
},
|