@fanchao8609/agent_brain_sync 1.31.0 → 1.31.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.
|
@@ -20,13 +20,36 @@ export function shortTokens(n: number | null | undefined): string {
|
|
|
20
20
|
return String(n)
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/**
|
|
24
|
-
|
|
23
|
+
/** 推理档位 → 一个大写字母(用户 2026-11-09 要求:右下角只用一个大写字母表示强度)。
|
|
24
|
+
*
|
|
25
|
+
* 为何不取首字母:minimal / medium / max 三个都是 M。这套是手选的无重写法:
|
|
26
|
+
* off=O、miNimal=N、Low=L、Medium=M、High=H、Xhigh=X、max=MX(用户指定,其余均单字母)。
|
|
27
|
+
* 改映射只改这里,并把测试里的表一起改。 */
|
|
28
|
+
export const LEVEL_LETTER: Record<string, string> = {
|
|
29
|
+
off: 'O',
|
|
30
|
+
minimal: 'N',
|
|
31
|
+
low: 'L',
|
|
32
|
+
medium: 'M',
|
|
33
|
+
high: 'H',
|
|
34
|
+
xhigh: 'X',
|
|
35
|
+
max: 'MX',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** 档位 → 字母;空值或认不得的档位返回空串(那时不显示)。 */
|
|
39
|
+
export function levelLetter(level: string | null | undefined): string {
|
|
40
|
+
return LEVEL_LETTER[String(level || '').trim().toLowerCase()] || ''
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** 拼右下角状态:`8.0%/1.0M 模型名 · H`。缺哪段就省哪段。
|
|
44
|
+
* 第三段是推理档位的一个大写字母(见 LEVEL_LETTER);模型不支持推理时不显。 */
|
|
45
|
+
export function buildStatus(usage: any, modelId: string, level = ''): string {
|
|
25
46
|
const parts: string[] = []
|
|
26
47
|
if (usage && usage.percent != null) parts.push(`${usage.percent.toFixed(1)}%`)
|
|
27
48
|
if (usage && usage.contextWindow) parts.push(`/${shortTokens(usage.contextWindow)}`)
|
|
28
49
|
const model = shortenModel(modelId)
|
|
29
|
-
|
|
50
|
+
const head = [parts.join(''), model].filter(Boolean).join(' ')
|
|
51
|
+
const letter = levelLetter(level)
|
|
52
|
+
return letter ? (head ? `${head} · ${letter}` : letter) : head
|
|
30
53
|
}
|
|
31
54
|
|
|
32
55
|
export function stripAnsi(s: string): string {
|
|
@@ -102,15 +125,6 @@ export function effortAnsi(level: string | null | undefined, colorMode = 'trueco
|
|
|
102
125
|
return colorMode === 'truecolor' ? `38;2;${g.rgb}` : `38;5;${g.ansi256}`
|
|
103
126
|
}
|
|
104
127
|
|
|
105
|
-
/** 「擱置」橙 #F59E0B —— 与 todo 面板的 `[擱置]`、面板大标题同色(abs.pi.ts 的 `C.hold`/`C.title`)。
|
|
106
|
-
* 用途(2026-11-09 用户要求):输入框**右下角的状态文字**(如 `30.0%/1.0M DeepSeek-V4.1-Flash`)。
|
|
107
|
-
* ★ 色值在 abs.pi.ts 里也有一份,不抽公共模块是故意的(见 EFFORT_COLOR 的注释)。 */
|
|
108
|
-
export const HOLD_COLOR = { rgb: '245;158;11', ansi256: 214 }
|
|
109
|
-
|
|
110
|
-
export function holdAnsi(colorMode = 'truecolor'): string {
|
|
111
|
-
return colorMode === 'truecolor' ? `38;2;${HOLD_COLOR.rgb}` : `38;5;${HOLD_COLOR.ansi256}`
|
|
112
|
-
}
|
|
113
|
-
|
|
114
128
|
/** 用 effortAnsi 的结果包一段文字;空串原样返回(off 时不着色)。 */
|
|
115
129
|
export function paintAnsi(ansi: string, text: string): string {
|
|
116
130
|
return ansi ? `\x1b[${ansi}m${text}\x1b[39m` : text
|
|
@@ -126,7 +140,7 @@ export function paintAnsi(ansi: string, text: string): string {
|
|
|
126
140
|
* (宁可没有,也不让边框溢出折行)。
|
|
127
141
|
*
|
|
128
142
|
* opts.labelFg:只给右边那个标签(右下角的状态文字)换个色,其余(圆角、虚线)仍用 fg。
|
|
129
|
-
* 2026-11-09
|
|
143
|
+
* 当前调用方不传(状态文字跟框线同色,2026-11-09 用户定);机制留着,要染色时传一个即可。
|
|
130
144
|
*
|
|
131
145
|
* 历史(别再重走):2026-11-08~09 曾有个 leadFg 开关,用来把 pi 嵌进上边框的
|
|
132
146
|
* `⠼ Working` 那段单独染色(橙)。现在 working 已还原成 pi 原版(不嵌边框),
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
* ② 右下角显示「上下文百分比/上限 模型名」,如 `8.0%/1.0M deepseek-v4.1-flash`
|
|
7
7
|
* ③ 输入框下方原有 footer 两行全部隐藏
|
|
8
8
|
*
|
|
9
|
-
* 2026-11-09
|
|
10
|
-
* ① working
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* 2026-11-09 定案(用户来回试过好几版):
|
|
10
|
+
* ① working 状态交给 pi 嵌在上边框(`embedWorkingStatus: true`)—— 就是 pi 原本那个样子:
|
|
11
|
+
* 左上角 `⠇ Working` + 动画,颜色随整行走框线色。本扩展**不搬不改字**。
|
|
12
|
+
* 试过并作废的:搬到右下角居中、正文最右一列、右上角单字符 —— 用户看完都要回左上角。
|
|
13
|
+
* ② 边框**和框内文字**都用 pi 给的 `editor.borderColor`(即原版那七档 thinking 色)。
|
|
13
14
|
*
|
|
14
15
|
* 为什么要覆写 render():
|
|
15
16
|
* pi 的 Editor.render() 只画上下两条 `─`,每行是「左 padding + 文本 + 右 padding」,
|
|
@@ -22,15 +23,15 @@
|
|
|
22
23
|
* 注意:自动补全菜单行排在底边之下、且自带内容宽度,不套竖线(否则菜单被框住会错位)。
|
|
23
24
|
*/
|
|
24
25
|
import { CustomEditor } from '@earendil-works/pi-coding-agent'
|
|
25
|
-
import { buildStatus,
|
|
26
|
+
import { buildStatus, roundBorder, shortenModel } from './format.ts'
|
|
26
27
|
|
|
27
28
|
const SIDE = '│'
|
|
28
29
|
|
|
29
|
-
/** 右下角状态文本,如 `8.0%/1.0M deepseek-v4.1-flash`。render() 拿不到 ctx,故由事件回调维护。 */
|
|
30
|
+
/** 右下角状态文本,如 `8.0%/1.0M deepseek-v4.1-flash · H`。render() 拿不到 ctx,故由事件回调维护。 */
|
|
30
31
|
let statusLabel = ''
|
|
31
32
|
|
|
32
|
-
/**
|
|
33
|
-
let
|
|
33
|
+
/** 当前推理档位(off/minimal/…/max)。也只是为了拼状态文字 —— 边框颜色是 pi 自己上的。 */
|
|
34
|
+
let effortLevel = ''
|
|
34
35
|
|
|
35
36
|
export class RoundedEditor extends CustomEditor {
|
|
36
37
|
render(width: number): string[] {
|
|
@@ -43,28 +44,29 @@ export class RoundedEditor extends CustomEditor {
|
|
|
43
44
|
// pi 的 interactive-mode 在 updateEditorBorderColor() 里把 editor.borderColor 设成
|
|
44
45
|
// theme.getThinkingBorderColor(档位),bash 模式另给一套 —— 直接复用就等于原版那套
|
|
45
46
|
// (含 off 的暗灰),而且 /theme、切档、切 bash 模式时 pi 自己会换并请求重绘。
|
|
46
|
-
//
|
|
47
|
+
// 光标色 / 输入框背景 / 聚焦外发光是 pi 内部画的,接管不了。
|
|
47
48
|
const border = (this as any).borderColor
|
|
48
49
|
const wrap = typeof border === 'function' ? border.bind(this) : (s: string) => s
|
|
49
50
|
const out: string[] = []
|
|
50
51
|
|
|
51
|
-
// 上边框:原本是整行
|
|
52
|
+
// 上边框:原本是整行 `─`(含 pi 嵌进来的 working 状态与滚动提示),两端换圆角。
|
|
53
|
+
// working 就是 pi 嵌的那个样子(左上角 `⠇ Working` + 动画),不搬不改字(2026-11-09 定稿)。
|
|
54
|
+
// 整行会被 roundBorder 重上一次框线色,所以它跟边框同色。
|
|
52
55
|
out.push(roundBorder(lines[0], wrap, '╭', '╮'))
|
|
53
56
|
// 下边框在原结果的倒数第 (1 + 自动补全行数) 位 —— 补全菜单排在它后面。
|
|
54
57
|
const autocompleteHeight = (this as any).renderedAutocompleteHeight ?? 0
|
|
55
58
|
const bottomIdx = lines.length - 1 - autocompleteHeight
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
// 正文行:两端各包一根竖线,文字也上推理色(2026-11-09 用户要求「输入框文字颜色与推理一致」)。
|
|
61
|
+
// 先剥掉 pi 原生文字色再包 —— 否则内层色码会提前收色,看着像只有前半行有颜色。
|
|
62
|
+
for (const body of lines.slice(1, bottomIdx)) {
|
|
63
|
+
out.push(wrap(SIDE) + wrap(body.replace(/\x1b\[[0-9;]*m/g, '')) + wrap(SIDE))
|
|
60
64
|
}
|
|
61
65
|
// 下边框(2026-11-07 还原:左下角的 fanchao·昵称已去掉 —— 用户嫌难看,
|
|
62
66
|
// 回 todo 面板标题;roundBorder 的 leftLabel 参数保留备用)。
|
|
63
|
-
// 状态文字(`
|
|
64
|
-
//
|
|
65
|
-
out.push(roundBorder(lines[bottomIdx], wrap, '╰', '╯', statusLabel
|
|
66
|
-
labelFg: (s: string) => paintAnsi(holdAnsi(colorMode), s),
|
|
67
|
-
}))
|
|
67
|
+
// 状态文字(`31.8%/1.0M 模型名`)2026-11-09 从右上角搬到右下角,颜色跟框线一致
|
|
68
|
+
// (用户当日先要搁置橙、看完又要改回推理色 —— 以最新为准)。
|
|
69
|
+
out.push(roundBorder(lines[bottomIdx], wrap, '╰', '╯', statusLabel))
|
|
68
70
|
// 自动补全行原样透传(不套竖线)。
|
|
69
71
|
for (let i = bottomIdx + 1; i < lines.length; i++) out.push(lines[i])
|
|
70
72
|
return out
|
|
@@ -74,7 +76,12 @@ export class RoundedEditor extends CustomEditor {
|
|
|
74
76
|
/** 刷新右下角状态文本(每次渲染前由事件与定时器调用)。 */
|
|
75
77
|
function refreshStatus(ctx: any): void {
|
|
76
78
|
try {
|
|
77
|
-
|
|
79
|
+
effortLevel = String(ctx?.thinkingLevel || '')
|
|
80
|
+
} catch {
|
|
81
|
+
effortLevel = ''
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
statusLabel = buildStatus(ctx?.getContextUsage?.(), ctx?.model?.id ?? '', effortLevel)
|
|
78
85
|
} catch {
|
|
79
86
|
statusLabel = shortenModel(ctx?.model?.id ?? '')
|
|
80
87
|
}
|
|
@@ -83,8 +90,6 @@ function refreshStatus(ctx: any): void {
|
|
|
83
90
|
export default function piRoundedEditor(pi: any): void {
|
|
84
91
|
pi.on('session_start', (_event: unknown, ctx: any) => {
|
|
85
92
|
if (!ctx?.ui?.setEditorComponent) return
|
|
86
|
-
// 终端色模式(256 色档位用);取不到就当真彩。
|
|
87
|
-
try { colorMode = String(ctx.ui?.theme?.getColorMode?.() || 'truecolor') } catch { colorMode = 'truecolor' }
|
|
88
93
|
refreshStatus(ctx)
|
|
89
94
|
// 第四个参数 embedWorkingStatus: true —— working 状态进上边框,不单独占一行(2026-11-09 用户定案)。
|
|
90
95
|
// 颜色不用管:pi 嵌入时用 editor.borderColor,本扩展又把整行重上一次框线色,两边同为档位色。
|
|
@@ -104,7 +109,11 @@ export default function piRoundedEditor(pi: any): void {
|
|
|
104
109
|
ctx?.ui?.requestRender?.()
|
|
105
110
|
})
|
|
106
111
|
|
|
107
|
-
//
|
|
112
|
+
// 切推理强度:档位字母要跟着变(边框色是 pi 自己换并重绘的,不用管)。
|
|
113
|
+
pi.on('thinking_level_select', (_event: any, ctx: any) => {
|
|
114
|
+
refreshStatus(ctx)
|
|
115
|
+
ctx?.ui?.requestRender?.()
|
|
116
|
+
})
|
|
108
117
|
|
|
109
118
|
// 上下文占用随每轮对话变化 —— 轮次结束与消息结束时刷新。
|
|
110
119
|
for (const ev of ['turn_end', 'message_end', 'tool_execution_end']) {
|