@@ -44,10 +44,44 @@ export class EngineManager {
4444 private _engineProc : child_process . ChildProcess | null = null ;
4545 private _storageDir : string ;
4646 private _outputChannel : vscode . OutputChannel ;
47+ private _statusBar : vscode . StatusBarItem ;
4748
4849 constructor ( private _context : vscode . ExtensionContext ) {
4950 this . _storageDir = _context . globalStorageUri . fsPath ;
5051 this . _outputChannel = vscode . window . createOutputChannel ( "TestPilot 引擎" ) ;
52+
53+ // 状态栏项(右侧显示,点击打开引擎日志)
54+ this . _statusBar = vscode . window . createStatusBarItem (
55+ vscode . StatusBarAlignment . Right , 100
56+ ) ;
57+ this . _statusBar . command = "testpilot-ai.showEngineLog" ;
58+ this . _setStatus ( "offline" ) ;
59+ this . _statusBar . show ( ) ;
60+ _context . subscriptions . push ( this . _statusBar ) ;
61+
62+ // 注册点击状态栏打开日志的命令
63+ _context . subscriptions . push (
64+ vscode . commands . registerCommand ( "testpilot-ai.showEngineLog" , ( ) => {
65+ this . _outputChannel . show ( true ) ;
66+ } )
67+ ) ;
68+ }
69+
70+ /** 更新状态栏显示 */
71+ private _setStatus ( state : "downloading" | "starting" | "ready" | "offline" , extra ?: string ) : void {
72+ const labels : Record < string , string > = {
73+ downloading : "$(cloud-download~spin) TestPilot: 下载中" ,
74+ starting : "$(sync~spin) TestPilot: 启动中" ,
75+ ready : "$(check) TestPilot: 就绪" ,
76+ offline : "$(error) TestPilot: 离线" ,
77+ } ;
78+ this . _statusBar . text = extra ? `${ labels [ state ] } ${ extra } ` : labels [ state ] ;
79+ this . _statusBar . tooltip = state === "ready"
80+ ? `TestPilot AI 引擎运行中\n点击查看日志`
81+ : `点击查看 TestPilot AI 引擎日志` ;
82+ this . _statusBar . backgroundColor = state === "offline"
83+ ? new vscode . ThemeColor ( "statusBarItem.errorBackground" )
84+ : undefined ;
5185 }
5286
5387 /** 引擎二进制的完整本地路径 */
@@ -77,6 +111,7 @@ export class EngineManager {
77111 // 1. 已有引擎在跑,直接复用
78112 if ( await this . isEngineRunning ( ) ) {
79113 this . _outputChannel . appendLine ( "[引擎] 检测到引擎已运行,直接连接" ) ;
114+ this . _setStatus ( "ready" ) ;
80115 return ;
81116 }
82117
@@ -87,11 +122,14 @@ export class EngineManager {
87122
88123 // 3. 没有缓存的二进制,先下载
89124 if ( ! fs . existsSync ( this . binaryPath ) ) {
125+ this . _setStatus ( "downloading" ) ;
90126 await this . _downloadBinary ( ) ;
91127 }
92128
93129 // 4. 启动引擎进程
130+ this . _setStatus ( "starting" ) ;
94131 await this . _spawnEngine ( ) ;
132+ this . _setStatus ( "ready" ) ;
95133 }
96134
97135 /** 从 GitHub Release 下载二进制(带进度条通知) */
@@ -141,10 +179,9 @@ export class EngineManager {
141179 if ( total > 0 ) {
142180 const pct = Math . floor ( ( received / total ) * 100 ) ;
143181 if ( pct >= lastPercent + 5 ) {
144- progress . report ( {
145- message : `${ pct } %(${ Math . round ( received / 1024 / 1024 ) } MB / ${ Math . round ( total / 1024 / 1024 ) } MB)` ,
146- increment : pct - lastPercent ,
147- } ) ;
182+ const msg = `${ pct } %(${ Math . round ( received / 1024 / 1024 ) } MB / ${ Math . round ( total / 1024 / 1024 ) } MB)` ;
183+ progress . report ( { message : msg , increment : pct - lastPercent } ) ;
184+ this . _setStatus ( "downloading" , `${ pct } %` ) ;
148185 lastPercent = pct ;
149186 }
150187 }
@@ -205,6 +242,7 @@ export class EngineManager {
205242 this . _engineProc . on ( "exit" , ( code ) => {
206243 this . _outputChannel . appendLine ( `[引擎] 进程已退出,退出码=${ code } ` ) ;
207244 this . _engineProc = null ;
245+ this . _setStatus ( "offline" ) ;
208246 } ) ;
209247
210248 // 超时保护:30 秒内未就绪视为失败
@@ -219,5 +257,6 @@ export class EngineManager {
219257 this . _engineProc . kill ( ) ;
220258 this . _engineProc = null ;
221259 }
260+ this . _setStatus ( "offline" ) ;
222261 }
223262}
0 commit comments