@raolin2025/claude-code-node 2.6.18 → 2.7.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raolin2025/claude-code-node",
3
- "version": "2.6.18",
3
+ "version": "2.7.0",
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
@@ -18,6 +18,7 @@ import { CostTracker } from './cost-tracker.js'
18
18
  import { autoCompact } from './compact.js'
19
19
  import { isLocalLlmServer } from '../utils/index.js'
20
20
  import { SOCK_DIR, SOCK_PATH, CC_NODE_PID } from './paths.js'
21
+ import { renderHeadpiece } from './headpiece.js'
21
22
  import { TelegramListener } from '../channel/tg-listener.js'
22
23
  import { fetchViaSocks5 } from '../channel/tg-proxy.js'
23
24
 
@@ -147,48 +148,16 @@ function buildBanner({ model, permissionMode, session, maxTokens }) {
147
148
  const top = `╭${leftLabel}${'─'.repeat(inner - leftLabel.length)}╮`
148
149
  const bottom = `╰${'─'.repeat(inner)}╯`
149
150
 
150
- const col1 = 24 // 左侧机器人列(19字符+边距)
151
+ const col1 = 24 // 左侧头标列(头标宽度 20 + 边距)
151
152
  const col2 = 50 // 标题列
152
153
  const col3 = inner - col1 - col2 - 2 // 信息列
153
154
 
154
- // ANSI 颜色
155
- const BLUE = '\x1b[34m'
156
- const CYAN = '\x1b[36m'
157
- const RESET = '\x1b[0m'
158
- const RED = '\x1b[31m'
159
-
160
- // 像素风格 CC 机器人(19字符宽,带颜色边框)
161
- const robotRaw = [
162
- ' ┌───────────────┐ ',
163
- ' │ ██ ██ │ ',
164
- ' │ ██████ │ ',
165
- ' │ ██ ██ │ ',
166
- ' │ │ ',
167
- ' │ ███████ │ ',
168
- ' │ ██ ██ │ ',
169
- ' │ ██████ │ ',
170
- ' │ ██ ██ ██ │ ',
171
- ' └───────────────┘ ',
172
- ]
173
-
174
- // 颜色化:边框蓝,眼睛/嘴巴青
175
- const colorize = (line) =>
176
- line
177
- .replace(/[┌└─╭╮┐┘│]/g, BLUE + '$&' + RESET)
178
- .replace(/[█]/g, RED + '$&' + RESET)
179
-
180
- const robotColored = robotRaw.map(colorize)
155
+ // 头标(独立模块 headpiece.js 提供,替换只需改该文件)
156
+ const headpiece = renderHeadpiece({ colWidth: col1 })
157
+ const robotLines = headpiece.lines
181
158
 
182
- // 机器人列:先去掉 ANSI(保证 pad 长度准确),再填充
159
+ // 去掉 ANSI 转义码,返回真实可见长度
183
160
  const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, '')
184
- const robotPlain = robotColored.map(line => stripAnsi(line))
185
-
186
- // 在 col1 内居中(按最大可见长度 21 计算,短的自动靠右)
187
- const visibleWidth = 21
188
- const totalCol1 = 24
189
- const leftPad = Math.floor((totalCol1 - visibleWidth) / 2)
190
- const rightPad = totalCol1 - visibleWidth - leftPad
191
- const robotLines = robotPlain.map(line => ' '.repeat(leftPad) + line + ' '.repeat(rightPad))
192
161
 
193
162
  // 辅助函数:字符串填充(忽略 ANSI 颜色码计算真实长度,正确处理嵌入在字符串中的 ANSI)
194
163
  const realLen = (s) => stripAnsi(s).length
@@ -0,0 +1,91 @@
1
+ // ============================================================
2
+ // headpiece.js — CC-Node 启动头标(独立模块)
3
+ // ------------------------------------------------------------
4
+ // 只负责「头标」的绘制与配色,与 CLI 框架解耦。
5
+ // 以后要替换/升级头标,只需修改本文件并保持接口不变即可。
6
+ //
7
+ // 头标内容: CC-NODE 艺术字
8
+ // CC : 两个 C, 10列宽 x 4行高 (扁平, 蓝渐变)
9
+ // NODE : 四个字母, 5列宽 x 4行高 (绿渐变)
10
+ // 上下严格对齐 (20列 x 8行)
11
+ //
12
+ // 接口:
13
+ // renderHeadpiece({ colWidth = 24 } = {})
14
+ // -> { lines: string[], height: number, width: number }
15
+ // lines 已上色、并已居中填充到 colWidth 宽度的行数组
16
+ // height 头标实际行数(未填充前的原始行数)
17
+ // width 头标原始可见宽度
18
+ // ============================================================
19
+
20
+ // ---- 头标原始数据(20列 x 8行)----
21
+ // CC 部分(蓝渐变, 4行)
22
+ const CC = [
23
+ '╔════════╗╔════════╗',
24
+ '██║ ██║ ',
25
+ '██║ ██║ ',
26
+ '╚════════╝╚════════╝',
27
+ ]
28
+
29
+ // NODE 部分(绿渐变, 4行)
30
+ const NODE = [
31
+ '╔╗╔═╗╔═══╗╔═══╗╔═══╗',
32
+ '║║║ ║║ ║║ ║║ ║',
33
+ '║╚╝ ║║ ║║ ║╠═══╣',
34
+ '╚═══╝╚═══╝╚═══╝╚═══╝',
35
+ ]
36
+
37
+ // ---- 配色(渐变)----
38
+ // CC 蓝色渐变(深 → 浅)
39
+ const BLUE = [81, 75, 69, 63]
40
+ // NODE 绿色渐变(深 → 浅)
41
+ const GREEN = [82, 118, 154, 190]
42
+
43
+ // 给每一行按对应色号上色
44
+ function colorize(lines, colors) {
45
+ return lines.map((line, i) => `\x1b[38;5;${colors[i]}m${line}\x1b[0m`)
46
+ }
47
+
48
+ // 去掉 ANSI 转义码,返回真实可见长度
49
+ function stripAnsi(s) {
50
+ return s.replace(/\x1b\[[0-9;]*m/g, '')
51
+ }
52
+
53
+ /**
54
+ * 渲染头标。
55
+ * @param {Object} [opts]
56
+ * @param {number} [opts.colWidth=24] 目标列宽(用于居中填充,须 >= 头标宽度)
57
+ * @returns {{ lines: string[], height: number, width: number }}
58
+ */
59
+ export function renderHeadpiece({ colWidth = 24 } = {}) {
60
+ // 1. 原始可见宽度
61
+ const width = stripAnsi(CC[0]).length // 20
62
+
63
+ // 2. 合并 CC + NODE,分别上色
64
+ const rawLines = [...colorize(CC, BLUE), ...colorize(NODE, GREEN)]
65
+ const height = rawLines.length // 8
66
+
67
+ // 3. 在 colWidth 内居中填充(若 colWidth < width 则不做填充,原样返回)
68
+ if (colWidth <= width) {
69
+ return { lines: rawLines, height, width }
70
+ }
71
+
72
+ const totalPad = colWidth - width
73
+ const leftPad = Math.floor(totalPad / 2)
74
+ const rightPad = totalPad - leftPad
75
+
76
+ const lines = rawLines.map((line) => {
77
+ const leadingAnsi = line.match(/^(\x1b\[[0-9;]*m)+/)?.[0] || ''
78
+ const trailingAnsi = line.match(/(\x1b\[0m)+$/)?.[0] || '\x1b[0m'
79
+ const plain = stripAnsi(line)
80
+ return leadingAnsi + ' '.repeat(leftPad) + plain + ' '.repeat(rightPad) + trailingAnsi
81
+ })
82
+
83
+ return { lines, height, width }
84
+ }
85
+
86
+ // 允许命令行直接预览:node src/core/headpiece.js
87
+ const isDirectRun = process.argv[1] && import.meta.url.endsWith(process.argv[1].split('/').pop())
88
+ if (isDirectRun) {
89
+ const { lines } = renderHeadpiece({ colWidth: 24 })
90
+ console.log(`\n${lines.join('\n')}\n`)
91
+ }