@steerable/agent-shell-web 0.6.53 → 0.6.55

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.
Files changed (90) hide show
  1. package/package.json +4 -4
  2. package/src/brand.ts +1 -1
  3. package/src/components/AgentSidebar.tsx +60 -52
  4. package/src/components/ChatHeader.tsx +41 -25
  5. package/src/components/ConfirmDialog.tsx +4 -3
  6. package/src/components/CreateProjectModal.tsx +29 -19
  7. package/src/components/LocalLlmSettingsModal.tsx +4 -3
  8. package/src/components/SidebarRelease.tsx +2 -1
  9. package/src/components/TerminalPanel.tsx +3 -2
  10. package/src/components/TerminalView.tsx +12 -7
  11. package/src/components/chat/ApprovalModal.tsx +39 -25
  12. package/src/components/chat/ApprovalPromptProvider.tsx +1 -1
  13. package/src/components/chat/AskUserPromptProvider.tsx +1 -1
  14. package/src/components/chat/AskUserQuestionMenu.tsx +19 -14
  15. package/src/components/chat/AssistantMessage.tsx +18 -13
  16. package/src/components/chat/ChatInput.tsx +56 -40
  17. package/src/components/chat/ChatProjectBadge.tsx +24 -19
  18. package/src/components/chat/EmptyChatHero.tsx +2 -1
  19. package/src/components/chat/ExecPolicyPicker.tsx +12 -11
  20. package/src/components/chat/ExecutedActionsCard.tsx +45 -33
  21. package/src/components/chat/FilePathCode.tsx +8 -3
  22. package/src/components/chat/InterruptedTurnCard.tsx +4 -3
  23. package/src/components/chat/LocalChatPanel.tsx +2 -1
  24. package/src/components/chat/Markdown.tsx +2 -1
  25. package/src/components/chat/MessageList.tsx +3 -2
  26. package/src/components/chat/ModelPicker.tsx +25 -16
  27. package/src/components/chat/OrchestrationChildrenCard.tsx +2 -1
  28. package/src/components/chat/OrchestrationFlowCard.tsx +23 -22
  29. package/src/components/chat/PlanTodoList.tsx +2 -1
  30. package/src/components/chat/ProjectTrustBanner.tsx +19 -5
  31. package/src/components/chat/SessionOrchestrationFlow.tsx +27 -26
  32. package/src/components/chat/SessionTodoList.tsx +8 -7
  33. package/src/components/chat/SessionTreeModal.tsx +10 -9
  34. package/src/components/chat/StreamingStatus.tsx +4 -3
  35. package/src/components/chat/SuggestedReplies.tsx +3 -2
  36. package/src/components/chat/TaskOutcomeCards.tsx +8 -5
  37. package/src/components/chat/TaskPanelModal.tsx +31 -21
  38. package/src/components/chat/TaskProcessPanel.tsx +14 -13
  39. package/src/components/chat/TurnFilesCard.tsx +14 -13
  40. package/src/components/chat/UserMessage.tsx +12 -11
  41. package/src/components/chat/executed-actions-model.ts +47 -35
  42. package/src/components/chat/orchestration-flow-model.ts +16 -5
  43. package/src/components/chat/process-status.ts +8 -7
  44. package/src/components/chat/todo-list-model.ts +5 -4
  45. package/src/components/chat/turn-files.ts +8 -8
  46. package/src/components/settings/AgentCapabilityFields.tsx +24 -21
  47. package/src/components/settings/AgentsSettingsPanel.tsx +30 -25
  48. package/src/components/settings/AppUpdateSettingsPanel.tsx +3 -2
  49. package/src/components/settings/AppearanceSettingsPanel.tsx +81 -37
  50. package/src/components/settings/DiagnoseSettingsPanel.tsx +11 -8
  51. package/src/components/settings/InsightsSettingsPanel.tsx +43 -28
  52. package/src/components/settings/LlmSettingsPanel.tsx +104 -83
  53. package/src/components/settings/McpSettingsPanel.tsx +60 -34
  54. package/src/components/settings/ModelIdCombobox.tsx +2 -1
  55. package/src/components/settings/OrchestrationSettingsPanel.tsx +8 -5
  56. package/src/components/settings/PortableSettingsPanel.tsx +83 -55
  57. package/src/components/settings/PythonRunnerSettingsPanel.tsx +22 -19
  58. package/src/components/settings/SecuritySettingsPanel.tsx +55 -31
  59. package/src/components/settings/SettingsNavMenu.tsx +3 -2
  60. package/src/components/settings/SettingsSaveButton.tsx +2 -1
  61. package/src/components/settings/SkillsSettingsPanel.tsx +36 -31
  62. package/src/components/settings/TelemetrySettingsPanel.tsx +15 -12
  63. package/src/components/settings/UsagePanel.tsx +19 -20
  64. package/src/components/settings/WebSearchSettingsPanel.tsx +23 -14
  65. package/src/components/settings/llm-vendors.ts +12 -7
  66. package/src/components/settings/model-capabilities.ts +16 -15
  67. package/src/components/settings/preset-choice-model.ts +6 -3
  68. package/src/fixtures/browser-dev-data.json +24 -24
  69. package/src/hooks/useProjects.ts +1 -1
  70. package/src/i18n/agent-label.ts +15 -0
  71. package/src/i18n/index.tsx +68 -0
  72. package/src/i18n/runtime.ts +117 -0
  73. package/src/i18n/translate.ts +65 -0
  74. package/src/layouts/AgentLayout.tsx +7 -6
  75. package/src/lib/app-release.ts +15 -10
  76. package/src/lib/attachments.ts +16 -7
  77. package/src/lib/browser-dev-electron-mock.ts +34 -34
  78. package/src/lib/chat-title.ts +3 -2
  79. package/src/lib/chat-transport.ts +6 -2
  80. package/src/lib/date-groups.ts +23 -15
  81. package/src/lib/electron-bridge.ts +4 -5
  82. package/src/lib/http-bridge.ts +4 -1
  83. package/src/lib/portable.ts +8 -7
  84. package/src/lib/show-thinking-content.ts +15 -3
  85. package/src/main.tsx +25 -2
  86. package/src/pages/AgentPage.tsx +17 -12
  87. package/src/pages/ChatPanelPreviewPage.tsx +46 -44
  88. package/src/pages/SettingsPage.tsx +48 -42
  89. package/src/vite-env.d.ts +3 -0
  90. package/vite.base.js +6 -2
@@ -9,6 +9,7 @@ import {
9
9
  LuToggleRight,
10
10
  LuTrash2,
11
11
  } from 'react-icons/lu';
12
+ import { t } from '@/i18n';
12
13
  import { getElectronBridge, isElectron } from '@/lib/electron-bridge';
13
14
 
14
15
  /**
@@ -77,7 +78,7 @@ export function McpSettingsPanel() {
77
78
  });
78
79
  setMcpServers(res.servers || []);
79
80
  } catch (err) {
80
- console.error('获取 MCP 服务列表失败:', err);
81
+ console.error('Failed to load MCP server list:', err);
81
82
  setError(err instanceof Error ? err.message : String(err));
82
83
  } finally {
83
84
  setMcpLoading(false);
@@ -228,7 +229,7 @@ export function McpSettingsPanel() {
228
229
  path: `/api/v2/mcp/servers/${encodeURIComponent(server.id)}/test`,
229
230
  });
230
231
  if (!res.success && res.error) {
231
- setError(`「${server.name}」连接失败:${res.error}`);
232
+ setError(t('"{name}" failed to connect: {error}', { name: server.name, error: res.error }));
232
233
  }
233
234
  await fetchMcpServers();
234
235
  } catch (err) {
@@ -253,9 +254,23 @@ export function McpSettingsPanel() {
253
254
  body: { json },
254
255
  });
255
256
  const parts: string[] = [];
256
- if (res.added.length > 0) parts.push(`已导入 ${res.added.length} 个:${res.added.map((s) => s.name).join('、')}`);
257
- if (res.skipped.length > 0) parts.push(`跳过 ${res.skipped.length} 个(重名或缺 command):${res.skipped.join('、')}`);
258
- setMcpImportStatus(parts.join(';') || '没有可导入的服务');
257
+ if (res.added.length > 0) {
258
+ parts.push(
259
+ t('Imported {count}: {names}', {
260
+ count: res.added.length,
261
+ names: res.added.map((s) => s.name).join(t(', ')),
262
+ }),
263
+ );
264
+ }
265
+ if (res.skipped.length > 0) {
266
+ parts.push(
267
+ t('Skipped {count} (duplicate name or missing command): {names}', {
268
+ count: res.skipped.length,
269
+ names: res.skipped.join(t(', ')),
270
+ }),
271
+ );
272
+ }
273
+ setMcpImportStatus(parts.join(t('; ')) || t('No servers to import'));
259
274
  if (res.added.length > 0) setMcpImportJson('');
260
275
  await fetchMcpServers();
261
276
  } catch (err) {
@@ -271,7 +286,7 @@ export function McpSettingsPanel() {
271
286
  <div className="bg-agent-muted/30 border border-agent-border/60 rounded-agent-md p-2.5 space-y-2">
272
287
  <h4 className="text-xs font-semibold text-agent-foreground flex items-center gap-1.5">
273
288
  <LuPlug className="h-3.5 w-3.5 text-agent-muted-foreground" />
274
- 粘贴 JSON 导入 (Claude Desktop 格式)
289
+ {t('Paste JSON to import (Claude Desktop format)')}
275
290
  </h4>
276
291
  <textarea
277
292
  value={mcpImportJson}
@@ -283,7 +298,7 @@ export function McpSettingsPanel() {
283
298
  />
284
299
  <div className="flex items-center justify-between gap-2">
285
300
  <p className="text-[10px] text-agent-muted-foreground">
286
- 与 Claude Desktop / Cursor 的 mcpServers 配置格式一致,可整段粘贴。
301
+ {t('Same mcpServers format as Claude Desktop / Cursor. You can paste the whole block.')}
287
302
  </p>
288
303
  <button
289
304
  type="button"
@@ -295,7 +310,7 @@ export function McpSettingsPanel() {
295
310
  : 'bg-agent-foreground text-agent-canvas hover:opacity-90'
296
311
  }`}
297
312
  >
298
- {mcpImporting ? <LuLoaderCircle className="h-3 w-3 animate-spin" /> : '导入'}
313
+ {mcpImporting ? <LuLoaderCircle className="h-3 w-3 animate-spin" /> : t('Import')}
299
314
  </button>
300
315
  </div>
301
316
  {mcpImportStatus && (
@@ -309,7 +324,7 @@ export function McpSettingsPanel() {
309
324
  {mcpFormOpen ? (
310
325
  <div className="bg-agent-muted/30 border border-agent-border/60 rounded-agent-md p-2.5 space-y-2.5">
311
326
  <h4 className="text-xs font-semibold text-agent-foreground">
312
- {mcpEditingId ? '编辑 MCP 服务' : '手动添加 MCP 服务'}
327
+ {mcpEditingId ? t('Edit MCP server') : t('Add MCP server manually')}
313
328
  </h4>
314
329
  <select
315
330
  value={mcpFormTransport}
@@ -318,15 +333,15 @@ export function McpSettingsPanel() {
318
333
  }
319
334
  className="h-8 w-full rounded-agent-md border border-agent-border bg-agent-canvas px-3 text-xs text-agent-foreground focus:outline-none focus:ring-2 focus:ring-agent-foreground/30"
320
335
  >
321
- <option value="stdio">本地进程(stdio)</option>
322
- <option value="streamable-http">远程服务(Streamable HTTP)</option>
336
+ <option value="stdio">{t('Local process (stdio)')}</option>
337
+ <option value="streamable-http">{t('Remote server (Streamable HTTP)')}</option>
323
338
  </select>
324
339
  <div className="grid grid-cols-2 gap-2">
325
340
  <input
326
341
  type="text"
327
342
  value={mcpFormName}
328
343
  onChange={(e) => setMcpFormName(e.target.value)}
329
- placeholder="名称,如 filesystem"
344
+ placeholder={t('Name, e.g. filesystem')}
330
345
  className="h-8 rounded-agent-md border border-agent-border bg-agent-canvas px-3 text-xs text-agent-foreground focus:outline-none focus:ring-2 focus:ring-agent-foreground/30"
331
346
  />
332
347
  {mcpFormTransport === 'stdio' ? (
@@ -334,7 +349,7 @@ export function McpSettingsPanel() {
334
349
  type="text"
335
350
  value={mcpFormCommand}
336
351
  onChange={(e) => setMcpFormCommand(e.target.value)}
337
- placeholder="启动命令,如 npx / uvx / node"
352
+ placeholder={t('Launch command, e.g. npx / uvx / node')}
338
353
  className="h-8 rounded-agent-md border border-agent-border bg-agent-canvas px-3 text-xs text-agent-foreground focus:outline-none focus:ring-2 focus:ring-agent-foreground/30"
339
354
  />
340
355
  ) : (
@@ -352,14 +367,18 @@ export function McpSettingsPanel() {
352
367
  <textarea
353
368
  value={mcpFormArgs}
354
369
  onChange={(e) => setMcpFormArgs(e.target.value)}
355
- placeholder="参数(每行一个)"
370
+ placeholder={t('Arguments (one per line)')}
356
371
  rows={3}
357
372
  className="w-full rounded-agent-md border border-agent-border bg-agent-canvas px-3 py-2 font-mono text-[11px] text-agent-foreground focus:outline-none focus:ring-2 focus:ring-agent-foreground/30"
358
373
  />
359
374
  <textarea
360
375
  value={mcpFormEnv}
361
376
  onChange={(e) => setMcpFormEnv(e.target.value)}
362
- placeholder={mcpEditingId ? '环境变量;留空保留现有值' : '环境变量(每行 KEY=VALUE)'}
377
+ placeholder={
378
+ mcpEditingId
379
+ ? t('Environment variables; leave blank to keep current values')
380
+ : t('Environment variables (one KEY=VALUE per line)')
381
+ }
363
382
  rows={2}
364
383
  className="w-full rounded-agent-md border border-agent-border bg-agent-canvas px-3 py-2 font-mono text-[11px] text-agent-foreground focus:outline-none focus:ring-2 focus:ring-agent-foreground/30"
365
384
  />
@@ -367,7 +386,7 @@ export function McpSettingsPanel() {
367
386
  type="text"
368
387
  value={mcpFormCwd}
369
388
  onChange={(e) => setMcpFormCwd(e.target.value)}
370
- placeholder="工作目录(可选)"
389
+ placeholder={t('Working directory (optional)')}
371
390
  className="h-8 w-full rounded-agent-md border border-agent-border bg-agent-canvas px-3 text-xs text-agent-foreground focus:outline-none focus:ring-2 focus:ring-agent-foreground/30"
372
391
  />
373
392
  </>
@@ -376,14 +395,18 @@ export function McpSettingsPanel() {
376
395
  <textarea
377
396
  value={mcpFormHeaders}
378
397
  onChange={(e) => setMcpFormHeaders(e.target.value)}
379
- placeholder={mcpEditingId ? '普通请求头;留空保留现有值' : '普通请求头(每行 Header=Value)'}
398
+ placeholder={
399
+ mcpEditingId
400
+ ? t('Plain headers; leave blank to keep current values')
401
+ : t('Plain headers (one Header=Value per line)')
402
+ }
380
403
  rows={2}
381
404
  className="w-full rounded-agent-md border border-agent-border bg-agent-canvas px-3 py-2 font-mono text-[11px] text-agent-foreground focus:outline-none focus:ring-2 focus:ring-agent-foreground/30"
382
405
  />
383
406
  <textarea
384
407
  value={mcpFormHeadersFromEnv}
385
408
  onChange={(e) => setMcpFormHeadersFromEnv(e.target.value)}
386
- placeholder="环境变量请求头(每行 Header=ENV_NAME)"
409
+ placeholder={t('Headers from environment variables (one Header=ENV_NAME per line)')}
387
410
  rows={2}
388
411
  className="w-full rounded-agent-md border border-agent-border bg-agent-canvas px-3 py-2 font-mono text-[11px] text-agent-foreground focus:outline-none focus:ring-2 focus:ring-agent-foreground/30"
389
412
  />
@@ -391,7 +414,7 @@ export function McpSettingsPanel() {
391
414
  type="text"
392
415
  value={mcpFormBearerEnv}
393
416
  onChange={(e) => setMcpFormBearerEnv(e.target.value)}
394
- placeholder="Bearer token 环境变量名(可选)"
417
+ placeholder={t('Bearer token environment variable name (optional)')}
395
418
  className="h-8 w-full rounded-agent-md border border-agent-border bg-agent-canvas px-3 text-xs text-agent-foreground focus:outline-none focus:ring-2 focus:ring-agent-foreground/30"
396
419
  />
397
420
  </>
@@ -402,7 +425,7 @@ export function McpSettingsPanel() {
402
425
  onClick={() => { resetMcpForm(); setMcpFormOpen(false); }}
403
426
  className="h-8 rounded-full px-4 text-xs font-medium text-agent-muted-foreground transition-colors hover:bg-agent-muted hover:text-agent-foreground"
404
427
  >
405
- 取消
428
+ {t('Cancel')}
406
429
  </button>
407
430
  <button
408
431
  type="button"
@@ -424,7 +447,7 @@ export function McpSettingsPanel() {
424
447
  : 'bg-agent-foreground text-agent-canvas hover:opacity-90'
425
448
  }`}
426
449
  >
427
- {mcpSaving ? <LuLoaderCircle className="h-3 w-3 animate-spin" /> : '保存'}
450
+ {mcpSaving ? <LuLoaderCircle className="h-3 w-3 animate-spin" /> : t('Save')}
428
451
  </button>
429
452
  </div>
430
453
  </div>
@@ -436,23 +459,23 @@ export function McpSettingsPanel() {
436
459
  data-testid="mcp-add-manual"
437
460
  >
438
461
  <LuPlus className="h-3.5 w-3.5" />
439
- 手动添加服务
462
+ {t('Add server manually')}
440
463
  </button>
441
464
  )}
442
465
 
443
466
  {/* 服务列表 */}
444
467
  <div className="space-y-2">
445
468
  <h4 className="text-xs font-semibold text-agent-muted-foreground uppercase tracking-wide">
446
- 已注册服务
469
+ {t('Registered servers')}
447
470
  </h4>
448
471
  {mcpLoading ? (
449
472
  <div className="flex items-center gap-2 py-4 text-xs text-agent-muted-foreground">
450
473
  <LuLoaderCircle className="h-3.5 w-3.5 animate-spin" />
451
- 获取 MCP 服务...
474
+ {t('Loading MCP servers...')}
452
475
  </div>
453
476
  ) : mcpServers.length === 0 ? (
454
477
  <div className="text-center py-6 text-xs text-agent-muted-foreground">
455
- 暂无 MCP 服务,粘贴 JSON 或手动添加
478
+ {t('No MCP servers yet. Paste JSON or add one manually.')}
456
479
  </div>
457
480
  ) : (
458
481
  <div className="divide-y divide-agent-border/40 pr-1">
@@ -471,11 +494,11 @@ export function McpSettingsPanel() {
471
494
  : 'bg-agent-muted text-agent-muted-foreground'
472
495
  }`}
473
496
  >
474
- {server.enabled ? '已启用' : '已停用'}
497
+ {server.enabled ? t('Enabled') : t('Disabled')}
475
498
  </span>
476
499
  {server.enabled && server.toolCount > 0 && (
477
500
  <span className="px-1 py-0.2 rounded bg-agent-muted text-[9px] text-agent-muted-foreground font-medium flex-shrink-0 scale-95 origin-left">
478
- {server.toolCount} 个工具
501
+ {t('{count} tools', { count: server.toolCount })}
479
502
  </span>
480
503
  )}
481
504
  </div>
@@ -486,12 +509,13 @@ export function McpSettingsPanel() {
486
509
  </p>
487
510
  {server.lastError && (
488
511
  <p className="text-[10px] text-agent-destructive line-clamp-2">
489
- 连接失败:{server.lastError}
512
+ {t('Connection failed: {error}', { error: server.lastError })}
490
513
  </p>
491
514
  )}
492
515
  {!server.lastError && server.toolsPreview.length > 0 && (
493
516
  <p className="text-[10px] text-agent-muted-foreground/80 line-clamp-1">
494
- 工具:{server.toolsPreview.join('、')}{server.toolCount > server.toolsPreview.length ? ' …' : ''}
517
+ {t('Tools: {names}', { names: server.toolsPreview.join(t(', ')) })}
518
+ {server.toolCount > server.toolsPreview.length ? ' …' : ''}
495
519
  </p>
496
520
  )}
497
521
  </div>
@@ -501,7 +525,7 @@ export function McpSettingsPanel() {
501
525
  onClick={() => handleTestMcpServer(server)}
502
526
  disabled={mcpTestingId === server.id}
503
527
  className="text-agent-muted-foreground hover:text-agent-foreground p-1 rounded-full hover:bg-agent-muted transition-colors"
504
- title="测试连接并刷新工具列表"
528
+ title={t('Test connection and refresh tool list')}
505
529
  >
506
530
  {mcpTestingId === server.id ? (
507
531
  <LuLoaderCircle className="h-3.5 w-3.5 animate-spin" />
@@ -513,7 +537,7 @@ export function McpSettingsPanel() {
513
537
  type="button"
514
538
  onClick={() => handleEditMcpServer(server)}
515
539
  className="text-agent-muted-foreground hover:text-agent-foreground p-1 rounded-full hover:bg-agent-muted transition-colors"
516
- title="编辑"
540
+ title={t('Edit')}
517
541
  >
518
542
  <LuPencil className="h-3.5 w-3.5" />
519
543
  </button>
@@ -521,7 +545,7 @@ export function McpSettingsPanel() {
521
545
  type="button"
522
546
  onClick={() => handleToggleMcpServer(server)}
523
547
  className="text-agent-muted-foreground hover:text-agent-foreground p-1 rounded-full hover:bg-agent-muted transition-colors"
524
- title={server.enabled ? '停用' : '启用'}
548
+ title={server.enabled ? t('Disable') : t('Enable')}
525
549
  >
526
550
  {server.enabled ? (
527
551
  <LuToggleRight className="h-3.5 w-3.5" />
@@ -534,7 +558,7 @@ export function McpSettingsPanel() {
534
558
  onClick={() => handleDeleteMcpServer(server)}
535
559
  disabled={mcpDeletingId === server.id}
536
560
  className="text-agent-muted-foreground hover:text-agent-destructive p-1 rounded-full hover:bg-agent-muted transition-colors"
537
- title="删除"
561
+ title={t('Delete')}
538
562
  >
539
563
  {mcpDeletingId === server.id ? (
540
564
  <LuLoaderCircle className="h-3 w-3 animate-spin" />
@@ -549,7 +573,9 @@ export function McpSettingsPanel() {
549
573
  )}
550
574
  </div>
551
575
  <p className="text-[10px] text-agent-muted-foreground">
552
- 支持 stdio 与 Streamable HTTP。密钥请填写环境变量名,不要写进普通请求头;已启用服务的工具通过 tool_search 提供给助手。
576
+ {t(
577
+ 'Supports stdio and Streamable HTTP. Enter secrets as environment variable names, not in plain headers. Tools from enabled servers reach the assistant through tool_search.',
578
+ )}
553
579
  </p>
554
580
 
555
581
  {error && (
@@ -1,6 +1,7 @@
1
1
  import { useEffect, useMemo, useRef, useState } from 'react';
2
2
  import { createPortal } from 'react-dom';
3
3
  import { LuChevronDown } from 'react-icons/lu';
4
+ import { t } from '@/i18n';
4
5
  import { ModelCapabilityChips } from '@/components/settings/ModelCapabilityChips';
5
6
  import type { ModelPickerRow } from '@/components/settings/llm-vendors';
6
7
 
@@ -164,7 +165,7 @@ export function ModelIdCombobox({
164
165
  <button
165
166
  type="button"
166
167
  tabIndex={-1}
167
- aria-label="打开模型列表"
168
+ aria-label={t('Open model list')}
168
169
  onClick={() => {
169
170
  if (open) setOpen(false);
170
171
  else show();
@@ -1,5 +1,6 @@
1
1
  import { LuGitFork } from 'react-icons/lu';
2
2
  import { useOrchestrationSetting } from '@/lib/orchestration-settings';
3
+ import { t } from '@/i18n';
3
4
 
4
5
  /**
5
6
  * OrchestrationSettingsPanel — 多智能体协同编排设置面板。
@@ -17,10 +18,12 @@ export function OrchestrationSettingsPanel() {
17
18
  <div className="space-y-1">
18
19
  <div className="flex items-center gap-1.5 text-xs font-semibold text-agent-foreground">
19
20
  <LuGitFork className="h-3.5 w-3.5 text-violet-600 dark:text-violet-400" />
20
- <span>多智能体协同编排 (Fork-Join)</span>
21
+ <span>{t('Multi-agent orchestration (Fork-Join)')}</span>
21
22
  </div>
22
23
  <p className="text-xs leading-relaxed text-agent-muted-foreground">
23
- 允许主智能体通过派生子任务(agent_spawn)并行推理计算,并在输入框上方呈现流程图与实时协同进度看板。
24
+ {t(
25
+ 'Let the main agent spawn subtasks (agent_spawn) to reason in parallel, and show a flow chart and live progress board above the input box.',
26
+ )}
24
27
  </p>
25
28
  </div>
26
29
 
@@ -28,7 +31,7 @@ export function OrchestrationSettingsPanel() {
28
31
  <div
29
32
  className="flex shrink-0 rounded-full border border-agent-border bg-agent-canvas p-0.5"
30
33
  role="radiogroup"
31
- aria-label="多智能体协同编排功能开关"
34
+ aria-label={t('Multi-agent orchestration toggle')}
32
35
  >
33
36
  <button
34
37
  type="button"
@@ -42,7 +45,7 @@ export function OrchestrationSettingsPanel() {
42
45
  : 'text-agent-muted-foreground hover:text-agent-foreground',
43
46
  ].join(' ')}
44
47
  >
45
- 开启
48
+ {t('On')}
46
49
  </button>
47
50
  <button
48
51
  type="button"
@@ -56,7 +59,7 @@ export function OrchestrationSettingsPanel() {
56
59
  : 'text-agent-muted-foreground hover:text-agent-foreground',
57
60
  ].join(' ')}
58
61
  >
59
- 关闭
62
+ {t('Off')}
60
63
  </button>
61
64
  </div>
62
65
  </div>