@@ -253,87 +253,141 @@ export const DraftLauncher: FC<DraftLauncherProps> = ({
253253
254254 < div className = "agent-draft-launcher" >
255255 < div className = "agent-draft-content" >
256- < span className = "agent-draft-kicker" > SESSION LAUNCHER</ span >
257- < p className = "agent-draft-description" >
258- 选择一个 AI 会话,在当前 workspace 里继续查看文件、运行命令和推进代码修改。
259- </ p >
260- < div className = "agent-draft-providers" >
261- { (
262- [
263- {
264- id : "claude" ,
265- title : "Claude" ,
266- meta : "analysis" ,
267- icon : < ThemedIcon semantic = "agent.provider.claude" size = { 18 } /> ,
268- description : "更适合长上下文梳理、方案分析和代码审查。" ,
269- className : "agent-provider-card-claude" ,
270- } ,
271- {
272- id : "codex" ,
273- title : "Codex" ,
274- meta : "workspace" ,
275- icon : < ThemedIcon semantic = "agent.provider.codex" size = { 18 } /> ,
276- description : "更适合终端操作、直接改文件和逐步修复问题。" ,
277- className : "agent-provider-card-codex" ,
278- } ,
279- ] as const
280- ) . map ( ( provider ) => {
281- const state = states [ provider . id ] ;
282- const guide = getProviderGuide ( provider . id ) ;
283- const isBusy =
284- state . loading ||
285- state . installJob ?. status === "queued" ||
286- state . installJob ?. status === "running" ;
287-
288- return (
289- < Button
290- key = { provider . id }
291- className = { `agent-provider-card ${ provider . className } ` }
292- disabled = { isAnyProviderBusy }
293- leadingIcon = { < span className = "agent-provider-card-icon" > { provider . icon } </ span > }
294- onClick = { ( ) => {
295- void launch ( provider . id ) ;
296- } }
297- trailingIcon = { < ArrowRight size = { 16 } className = "agent-provider-card-arrow" /> }
298- variant = "secondary"
299- >
300- < span className = "agent-provider-card-body" >
301- < span className = "agent-provider-card-title-row" >
302- < span className = "agent-provider-card-title" > { provider . title } </ span >
303- < span className = "agent-provider-card-meta" > { provider . meta } </ span >
304- </ span >
305- < span className = "agent-provider-card-desc" > { provider . description } </ span >
306- < span className = "agent-provider-card-cta" > { getProviderCta ( provider . id ) } </ span >
307- { isBusy ? (
308- < span className = "agent-provider-card-status" >
309- { t ( "provider.install.status.installing" ) }
310- </ span >
311- ) : null }
312- { guide . message ? (
313- < span className = "agent-provider-card-guide" >
314- < span > { guide . message } </ span >
315- { guide . docUrl ? (
316- < a
317- href = { guide . docUrl }
318- onClick = { ( event ) => event . stopPropagation ( ) }
319- rel = "noreferrer"
320- target = "_blank"
321- >
322- { t ( "provider.install.open_docs" ) }
323- </ a >
324- ) : null }
325- < a
326- href = { buildProviderDiagnosticsPath ( provider . id ) }
327- onClick = { ( event ) => event . stopPropagation ( ) }
328- >
329- { t ( "diagnostics.actions.open_diagnostics" ) }
330- </ a >
331- </ span >
332- ) : null }
256+ < div className = "agent-draft-component" >
257+ < div className = "agent-draft-component-row" >
258+ { /* Agent panel */ }
259+ < div className = "agent-draft-panel" >
260+ < div className = "agent-draft-panel-header" >
261+ < span className = "agent-draft-panel-icon" >
262+ < ThemedIcon semantic = "agent.provider.claude" size = { 13 } />
333263 </ span >
334- </ Button >
335- ) ;
336- } ) }
264+ < span className = "agent-draft-panel-label" > Agent</ span >
265+ </ div >
266+
267+ < div className = "agent-draft-panel-list" >
268+ { (
269+ [
270+ {
271+ id : "claude" ,
272+ title : "Claude" ,
273+ icon : < ThemedIcon semantic = "agent.provider.claude" size = { 18 } /> ,
274+ className : "agent-provider-card-claude" ,
275+ } ,
276+ {
277+ id : "codex" ,
278+ title : "Codex" ,
279+ icon : < ThemedIcon semantic = "agent.provider.codex" size = { 18 } /> ,
280+ className : "agent-provider-card-codex" ,
281+ } ,
282+ ] as const
283+ ) . map ( ( provider ) => {
284+ const state = states [ provider . id ] ;
285+ const guide = getProviderGuide ( provider . id ) ;
286+ const isBusy =
287+ state . loading ||
288+ state . installJob ?. status === "queued" ||
289+ state . installJob ?. status === "running" ;
290+
291+ return (
292+ < Button
293+ key = { provider . id }
294+ className = { `agent-provider-card ${ provider . className } ` }
295+ disabled = { isAnyProviderBusy }
296+ leadingIcon = {
297+ < span className = "agent-provider-card-icon" > { provider . icon } </ span >
298+ }
299+ onClick = { ( ) => {
300+ void launch ( provider . id ) ;
301+ } }
302+ trailingIcon = {
303+ < ArrowRight size = { 16 } className = "agent-provider-card-arrow" />
304+ }
305+ variant = "secondary"
306+ >
307+ < span className = "agent-provider-card-body" >
308+ < span className = "agent-provider-card-title-row" >
309+ < span className = "agent-provider-card-title" > { provider . title } </ span >
310+ </ span >
311+ < span className = "agent-provider-card-cta" >
312+ { getProviderCta ( provider . id ) }
313+ </ span >
314+ { isBusy ? (
315+ < span className = "agent-provider-card-status" >
316+ { t ( "provider.install.status.installing" ) }
317+ </ span >
318+ ) : null }
319+ { guide . message ? (
320+ < span className = "agent-provider-card-guide" >
321+ < span > { guide . message } </ span >
322+ { guide . docUrl ? (
323+ < a
324+ href = { guide . docUrl }
325+ onClick = { ( event ) => event . stopPropagation ( ) }
326+ rel = "noreferrer"
327+ target = "_blank"
328+ >
329+ { t ( "provider.install.open_docs" ) }
330+ </ a >
331+ ) : null }
332+ < a
333+ href = { buildProviderDiagnosticsPath ( provider . id ) }
334+ onClick = { ( event ) => event . stopPropagation ( ) }
335+ >
336+ { t ( "diagnostics.actions.open_diagnostics" ) }
337+ </ a >
338+ </ span >
339+ ) : null }
340+ </ span >
341+ </ Button >
342+ ) ;
343+ } ) }
344+ </ div >
345+ </ div >
346+
347+ { /* File Editor panel */ }
348+ < div className = "agent-draft-panel" >
349+ < div className = "agent-draft-panel-header" >
350+ < span className = "agent-draft-panel-icon" >
351+ < svg
352+ width = "13"
353+ height = "13"
354+ viewBox = "0 0 24 24"
355+ fill = "none"
356+ stroke = "currentColor"
357+ strokeWidth = "2"
358+ strokeLinecap = "round"
359+ strokeLinejoin = "round"
360+ >
361+ < path d = "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" />
362+ < polyline points = "14 2 14 8 20 8" />
363+ </ svg >
364+ </ span >
365+ < span className = "agent-draft-panel-label" > File Editor</ span >
366+ </ div >
367+
368+ < div className = "agent-draft-drop-zone" >
369+ < div className = "agent-draft-drop-zone-icon" >
370+ < svg
371+ width = "16"
372+ height = "16"
373+ viewBox = "0 0 24 24"
374+ fill = "none"
375+ stroke = "currentColor"
376+ strokeWidth = "1.5"
377+ strokeLinecap = "round"
378+ strokeLinejoin = "round"
379+ >
380+ < path d = "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
381+ < polyline points = "7 10 12 15 17 10" />
382+ < line x1 = "12" y1 = "15" x2 = "12" y2 = "3" />
383+ </ svg >
384+ </ div >
385+ < span className = "agent-draft-drop-zone-title" > 拖入文件打开</ span >
386+ </ div >
387+ </ div >
388+ </ div >
389+
390+ < div className = "agent-draft-footer" > 点击启动 Agent 或直接拖拽文件到右侧区域打开</ div >
337391 </ div >
338392 </ div >
339393 </ div >
0 commit comments