@raolin2025/claude-code-node 2.7.4 → 2.7.6
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/core/cli.js +33 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raolin2025/claude-code-node",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.6",
|
|
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",
|
package/src/core/cli.js
CHANGED
|
@@ -590,6 +590,8 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
590
590
|
let pendingConfirm = null
|
|
591
591
|
// 等待中的 Telegram AskUserQuestion 回答(resolve 回调)— 远程用户回复任意文本时响应
|
|
592
592
|
let pendingAskUser = null
|
|
593
|
+
// 取消当前等待中的 AskUserQuestion(用户 /stop 时调用,resolve 为取消标记,避免死锁)
|
|
594
|
+
let cancelAskUser = null
|
|
593
595
|
// 最近一次 /models 拉取的模型列表(供 /model <编号> 选择)
|
|
594
596
|
let modelList = []
|
|
595
597
|
// /models 从 Telegram 发出后,等待用户回复编号/名字来选择模型
|
|
@@ -613,7 +615,8 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
613
615
|
if (source === 'telegram' && pendingAskUser && !trimmed.startsWith('/')) {
|
|
614
616
|
const ask = pendingAskUser
|
|
615
617
|
pendingAskUser = null
|
|
616
|
-
|
|
618
|
+
cancelAskUser = null
|
|
619
|
+
ask.fn(trimmed)
|
|
617
620
|
return
|
|
618
621
|
}
|
|
619
622
|
if (source === 'telegram' && pendingConfirm && !trimmed.startsWith('/')) {
|
|
@@ -808,7 +811,14 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
808
811
|
console.log('Conversation cleared')
|
|
809
812
|
break
|
|
810
813
|
case 'stop':
|
|
811
|
-
// 停止当前正在运行的 AI 工作(如卡死 /
|
|
814
|
+
// 停止当前正在运行的 AI 工作(如卡死 / 长时间无响应时)。
|
|
815
|
+
// 若正在等待 AskUserQuestion 回答,先取消提问(resolve 取消标记),避免引擎挂起。
|
|
816
|
+
if (pendingAskUser) {
|
|
817
|
+
const cancel = cancelAskUser
|
|
818
|
+
pendingAskUser = null
|
|
819
|
+
cancelAskUser = null
|
|
820
|
+
if (cancel) cancel()
|
|
821
|
+
}
|
|
812
822
|
if (engine.state.isRunning) {
|
|
813
823
|
engine.abort()
|
|
814
824
|
console.log('⏹️ 已发送停止信号,正在中止当前工作...')
|
|
@@ -1008,7 +1018,10 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
1008
1018
|
// 让远程用户看到 AI 正在工作,而不是"以为没回应"。
|
|
1009
1019
|
// 采用节流 + 编辑同一消息的方式,避免刷屏和触发速率限制。
|
|
1010
1020
|
// ============================================================
|
|
1011
|
-
const tgThinking = { buffer: '', timer: null, target: null, lastMsgId: null, flushing: false, typingTimer: null }
|
|
1021
|
+
const tgThinking = { buffer: '', timer: null, target: null, lastMsgId: null, flushing: false, typingTimer: null, lastResetAt: 0 }
|
|
1022
|
+
// 周期性重置"🧠 思考中…"消息,避免它无限膨胀成一个无法判断是否仍在工作的静态块。
|
|
1023
|
+
// 每隔 RESET_MS 就删掉旧消息、发一条新的,让用户每隔几秒看到一次明确的活动信号。
|
|
1024
|
+
const TG_THINKING_RESET_MS = 5000
|
|
1012
1025
|
|
|
1013
1026
|
// Telegram 的 typing 提示约 5 秒后自动消失。若 cc-node 处理耗时较长
|
|
1014
1027
|
//(如执行工具、读取文件、多轮思考),单次 sendChatAction 撑不住整个周期,
|
|
@@ -1036,6 +1049,7 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
1036
1049
|
tgThinking.buffer = ''
|
|
1037
1050
|
tgThinking.lastMsgId = null
|
|
1038
1051
|
tgThinking.flushing = false
|
|
1052
|
+
tgThinking.lastResetAt = Date.now()
|
|
1039
1053
|
// 先发送 typing 动作,让 Telegram 立即显示"正在输入",并启动心跳保持持续显示
|
|
1040
1054
|
if (tgListener?.bot && tgThinking.target) {
|
|
1041
1055
|
tgListener.bot.sendChatAction(tgThinking.target, 'typing').catch(() => {})
|
|
@@ -1062,6 +1076,14 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
1062
1076
|
const target = tgThinking.target
|
|
1063
1077
|
const body = `🧠 思考中…\n\n${tgThinking.buffer.slice(-3500)}`
|
|
1064
1078
|
try {
|
|
1079
|
+
// 周期性重置:若已有一条消息且距上次重置超过阈值,删除旧消息并发新消息,
|
|
1080
|
+
// 让用户每隔几秒看到"🧠 思考中…"重新出现,明确 AI 仍在工作(而非已卡死/完成)。
|
|
1081
|
+
const needReset = tgThinking.lastMsgId && (Date.now() - tgThinking.lastResetAt) >= TG_THINKING_RESET_MS
|
|
1082
|
+
if (needReset) {
|
|
1083
|
+
tgListener.bot.deleteMessage(target, tgThinking.lastMsgId).catch(() => {})
|
|
1084
|
+
tgThinking.lastMsgId = null
|
|
1085
|
+
tgThinking.lastResetAt = Date.now()
|
|
1086
|
+
}
|
|
1065
1087
|
if (tgThinking.lastMsgId) {
|
|
1066
1088
|
await tgListener.bot.editMessage(target, tgThinking.lastMsgId, body, { parseMode: 'HTML' })
|
|
1067
1089
|
} else {
|
|
@@ -1140,17 +1162,16 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
|
|
|
1140
1162
|
// - CLI 本地模式:走本地终端交互(inputCtrl.ask)
|
|
1141
1163
|
engine.config.onAskUser = (question) => {
|
|
1142
1164
|
if (currentSource === 'telegram' && tgListener?.bot) {
|
|
1143
|
-
const promptText = `❓ ${question}\n\n
|
|
1165
|
+
const promptText = `❓ ${question}\n\n请直接回复你的回答。\n(发 /stop 可取消本次提问)`
|
|
1144
1166
|
sendTelegram(promptText, null).catch(() => {})
|
|
1145
1167
|
return new Promise((resolve) => {
|
|
1146
|
-
//
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
resolve(val)
|
|
1168
|
+
// 一直等待用户回答——不设超时自行结束(超时会吞掉迟到回答,违背"等待回答"语义)。
|
|
1169
|
+
// 用户回复任意文本即作为回答;用户 /stop 则通过 cancelAskUser 取消(resolve 取消标记,避免死锁)。
|
|
1170
|
+
pendingAskUser = { fn: (val) => resolve(val) }
|
|
1171
|
+
cancelAskUser = () => {
|
|
1172
|
+
if (pendingAskUser) pendingAskUser = null
|
|
1173
|
+
cancelAskUser = null
|
|
1174
|
+
resolve('(提问已取消)')
|
|
1154
1175
|
}
|
|
1155
1176
|
})
|
|
1156
1177
|
}
|