zapmyco 0.7.0 → 0.8.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/dist/cli/index.mjs +549 -116
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.mts +5 -9
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{loader-B5_elj6d.mjs → loader-C_55Y7Q_.mjs} +4 -4
- package/dist/loader-C_55Y7Q_.mjs.map +1 -0
- package/package.json +2 -1
- package/dist/loader-B5_elj6d.mjs.map +0 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { B as APP_NAME, E as createLlmBasedAgent, F as eventBus, H as
|
|
2
|
+
import { B as APP_NAME, E as createLlmBasedAgent, F as eventBus, H as VERSION, I as buildSkillSnapshot, L as loadSkills, S as WebError, U as __require, V as SESSION_DIR_NAME, g as logger, h as configureLogger, i as AgentLlmFacade, n as loadConfig, p as SubAgentManager, t as HOME_CONFIG_PATH, w as ZapmycoErrorCode } from "../loader-C_55Y7Q_.mjs";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { mkdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
@@ -13,6 +13,7 @@ import chalk, { Chalk } from "chalk";
|
|
|
13
13
|
import { Command } from "commander";
|
|
14
14
|
import { spawn, spawnSync } from "node:child_process";
|
|
15
15
|
import { CombinedAutocompleteProvider, Container, Editor, Input, Key, ProcessTerminal, SelectList, TUI, getKeybindings, matchesKey, truncateToWidth, wrapTextWithAnsi } from "@mariozechner/pi-tui";
|
|
16
|
+
import i18next from "i18next";
|
|
16
17
|
import TurndownService from "turndown";
|
|
17
18
|
import { lookup } from "node:dns/promises";
|
|
18
19
|
import { Client } from "@modelcontextprotocol/sdk/client";
|
|
@@ -365,6 +366,391 @@ function createQuitCommand() {
|
|
|
365
366
|
};
|
|
366
367
|
}
|
|
367
368
|
|
|
369
|
+
//#endregion
|
|
370
|
+
//#region src/i18n/locales/en.json
|
|
371
|
+
var en_default = {
|
|
372
|
+
output: {
|
|
373
|
+
"welcome": "Welcome back!",
|
|
374
|
+
"error": {
|
|
375
|
+
"executionFailed": "Execution failed:",
|
|
376
|
+
"detail": "Details:"
|
|
377
|
+
},
|
|
378
|
+
"result": {
|
|
379
|
+
"title": "Execution Complete",
|
|
380
|
+
"goal": "Goal:",
|
|
381
|
+
"status": "Status:",
|
|
382
|
+
"success": "Success",
|
|
383
|
+
"partialSuccess": "Partial Success",
|
|
384
|
+
"failed": "Failed",
|
|
385
|
+
"duration": "Duration:",
|
|
386
|
+
"token": "Token:",
|
|
387
|
+
"cost": "Cost:",
|
|
388
|
+
"taskBreakdown": "Task Breakdown",
|
|
389
|
+
"subtaskCount": "subtasks",
|
|
390
|
+
"artifacts": "Artifacts:",
|
|
391
|
+
"suggestions": "Suggestions:"
|
|
392
|
+
},
|
|
393
|
+
"taskGraph": {
|
|
394
|
+
"title": "Task Breakdown Overview",
|
|
395
|
+
"total": "{{count}} subtasks, {{layers}} parallel layers",
|
|
396
|
+
"layer": "Layer {{index}} (parallel):"
|
|
397
|
+
},
|
|
398
|
+
"agents": {
|
|
399
|
+
"title": "Registered Agents",
|
|
400
|
+
"empty": "No registered agents",
|
|
401
|
+
"id": "ID",
|
|
402
|
+
"status": "Status",
|
|
403
|
+
"load": "Load",
|
|
404
|
+
"capability": "Capabilities"
|
|
405
|
+
},
|
|
406
|
+
"config": {
|
|
407
|
+
"title": "Current Configuration",
|
|
408
|
+
"llm": "LLM:",
|
|
409
|
+
"defaultModel": "Default Model:",
|
|
410
|
+
"provider": "Provider:",
|
|
411
|
+
"modelId": "Model ID:",
|
|
412
|
+
"inputType": "Input Type:",
|
|
413
|
+
"apiKey": "API Key:",
|
|
414
|
+
"apiKeyConfigured": "***Configured***",
|
|
415
|
+
"apiKeyNotConfigured": "(Not configured)",
|
|
416
|
+
"apiFormat": "API Format:",
|
|
417
|
+
"scheduler": "Scheduler:",
|
|
418
|
+
"maxConcurrency": "Max Concurrency:",
|
|
419
|
+
"maxPerAgent": "Max Per Agent:",
|
|
420
|
+
"taskTimeout": "Task Timeout:",
|
|
421
|
+
"maxRetries": "Max Retries:",
|
|
422
|
+
"cli": "CLI:",
|
|
423
|
+
"colorEnabled": "Enabled",
|
|
424
|
+
"colorDisabled": "Disabled",
|
|
425
|
+
"debugEnabled": "Enabled",
|
|
426
|
+
"debugDisabled": "Disabled",
|
|
427
|
+
"outputFormat": "Output Format:",
|
|
428
|
+
"uiLanguage": "UI Language:",
|
|
429
|
+
"agents": "Agents:",
|
|
430
|
+
"minutes": "min"
|
|
431
|
+
},
|
|
432
|
+
"history": {
|
|
433
|
+
"title": "Session History",
|
|
434
|
+
"empty": "No history yet"
|
|
435
|
+
},
|
|
436
|
+
"status": {
|
|
437
|
+
"title": "Session Status",
|
|
438
|
+
"idle": "Idle",
|
|
439
|
+
"executing": "Executing",
|
|
440
|
+
"closing": "Closing",
|
|
441
|
+
"state": "State:",
|
|
442
|
+
"totalRequests": "Total Requests:",
|
|
443
|
+
"success": "Success:",
|
|
444
|
+
"failure": "Failure:",
|
|
445
|
+
"tokenConsumption": "Token Usage:",
|
|
446
|
+
"totalCost": "Total Cost:"
|
|
447
|
+
}
|
|
448
|
+
},
|
|
449
|
+
dialog: {
|
|
450
|
+
"footer": {
|
|
451
|
+
"search": "Type to search · ↑↓ Navigate · Enter Confirm · Esc Cancel",
|
|
452
|
+
"normal": "k/j ↑↓ Navigate · / Search · Enter Select · Esc/q Quit · BS/h Back",
|
|
453
|
+
"searchNarrow": "Enter Confirm · Esc Cancel",
|
|
454
|
+
"normalNarrow": "↑↓=k/j / Enter Esc/q BS/h",
|
|
455
|
+
"textInput": "Enter to confirm · Esc to cancel"
|
|
456
|
+
},
|
|
457
|
+
"configView": {
|
|
458
|
+
"narrow": "q/Esc Back",
|
|
459
|
+
"wide": "q/Esc Back · Enter/BS/h Back to Menu"
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
settings: {
|
|
463
|
+
"mainMenu": {
|
|
464
|
+
"defaultModel": "Default Model",
|
|
465
|
+
"manageProviders": "Manage Providers",
|
|
466
|
+
"viewConfig": "View Config",
|
|
467
|
+
"language": "Language / 语言",
|
|
468
|
+
"notConfigured": "not configured",
|
|
469
|
+
"nConfigured": "{{count}} configured",
|
|
470
|
+
"noneConfigured": "none configured",
|
|
471
|
+
"displayFullConfig": "Display full configuration details"
|
|
472
|
+
},
|
|
473
|
+
"apiKeyConfig": {
|
|
474
|
+
"useEnvVar": "Use env var",
|
|
475
|
+
"useEnvVarDesc": "Recommended — more secure",
|
|
476
|
+
"enterManually": "Enter manually",
|
|
477
|
+
"enterManuallyDesc": "Type the key directly (stored in plaintext in settings.json)",
|
|
478
|
+
"clear": "Clear",
|
|
479
|
+
"clearDesc": "Remove the configured key"
|
|
480
|
+
},
|
|
481
|
+
"providerActions": {
|
|
482
|
+
"configureApiKey": "Configure API Key",
|
|
483
|
+
"selectModel": "Select Model",
|
|
484
|
+
"baseUrl": "Base URL",
|
|
485
|
+
"setAsDefault": "Set as Default"
|
|
486
|
+
},
|
|
487
|
+
"providerEntry": {
|
|
488
|
+
"keyConfigured": "key configured",
|
|
489
|
+
"noKey": "no key",
|
|
490
|
+
"addProvider": "Add Provider",
|
|
491
|
+
"addProviderDesc": "Select from a list of known providers",
|
|
492
|
+
"apiFormat": "API format: {{format}}",
|
|
493
|
+
"openaiCompatible": "OpenAI compatible"
|
|
494
|
+
},
|
|
495
|
+
"addProvider": {
|
|
496
|
+
"yes": "Yes, configure API Key now",
|
|
497
|
+
"yesDesc": "Go to API Key settings",
|
|
498
|
+
"later": "Later",
|
|
499
|
+
"laterDesc": "Return to main menu"
|
|
500
|
+
},
|
|
501
|
+
"messages": {
|
|
502
|
+
"apiKeyCleared": "[ok] Cleared API key for {{provider}}",
|
|
503
|
+
"apiKeySetToEnv": "[ok] Set {{provider}} API key to env var ${ {{envVar}} }",
|
|
504
|
+
"envVarNote": "Make sure {{envVar}} is set in your shell",
|
|
505
|
+
"apiKeyConfigured": "[ok] Configured API key for {{provider}}",
|
|
506
|
+
"modelSelected": "[ok] Selected model: {{model}}",
|
|
507
|
+
"providerAdded": "[ok] Added provider: {{provider}}",
|
|
508
|
+
"baseUrlReset": "[ok] Reset {{provider}} Base URL to default",
|
|
509
|
+
"baseUrlSet": "[ok] Set {{provider}} Base URL: {{url}}",
|
|
510
|
+
"defaultModelSet": "[ok] Default model set to: {{model}}",
|
|
511
|
+
"languageSet": "[ok] Language set to: {{locale}}",
|
|
512
|
+
"restartRequired": "Some changes may require a session restart to take full effect.",
|
|
513
|
+
"noModels": "has no available model list",
|
|
514
|
+
"configureManually": "Configure models manually in settings.json or check the provider name",
|
|
515
|
+
"alreadyExists": "already exists, use the provider entry to configure it",
|
|
516
|
+
"configureFirst": "Configure a model first before setting it as default",
|
|
517
|
+
"checkApiKeyHelpPrefix": " Hint: check"
|
|
518
|
+
},
|
|
519
|
+
"cliMode": {
|
|
520
|
+
"usage": "Usage:",
|
|
521
|
+
"settingsUsage": "/settings — Open interactive configuration menu",
|
|
522
|
+
"listProvidersUsage": "/settings list-providers — List all known providers",
|
|
523
|
+
"listModelsUsage": "/settings list-models <name> — List available models for a provider",
|
|
524
|
+
"knownProviders": "Known providers:",
|
|
525
|
+
"noModelsAvailable": "No models available from pi-ai registry",
|
|
526
|
+
"hintConfigureFirst": "Hint: use /settings to configure this provider first",
|
|
527
|
+
"availableModels": "available models:"
|
|
528
|
+
},
|
|
529
|
+
"modelSelector": { "notConfigured": "Not configured - Enter to set API Key" }
|
|
530
|
+
},
|
|
531
|
+
session: {
|
|
532
|
+
"welcome": "ZapMyco: Welcome back!",
|
|
533
|
+
"errorPrefix": "[Error]",
|
|
534
|
+
"agentErrorMessage": "Agent execution failed (no detailed error information)",
|
|
535
|
+
"noContentError": "Model returned no content, please check your API Key configuration",
|
|
536
|
+
"displayName": "Zapmyco AI Assistant",
|
|
537
|
+
"editorNotFound": "Editor not found: {{cmd}}, please set $EDITOR environment variable",
|
|
538
|
+
"editorFailed": "Failed to open editor: {{message}}",
|
|
539
|
+
"executing": "Executing...",
|
|
540
|
+
"setEnvVarHint": "Set environment variable: export {{envVar}}=<your-api-key>",
|
|
541
|
+
"useConfigHint": "Or use in REPL: /config set llm.providers.{{provider}}.apiKey <your-key>"
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
//#endregion
|
|
546
|
+
//#region src/i18n/locales/zh-CN.json
|
|
547
|
+
var zh_CN_default = {
|
|
548
|
+
output: {
|
|
549
|
+
"welcome": "欢迎回来!",
|
|
550
|
+
"error": {
|
|
551
|
+
"executionFailed": "执行失败:",
|
|
552
|
+
"detail": "详情:"
|
|
553
|
+
},
|
|
554
|
+
"result": {
|
|
555
|
+
"title": "执行完成",
|
|
556
|
+
"goal": "目标:",
|
|
557
|
+
"status": "状态:",
|
|
558
|
+
"success": "成功",
|
|
559
|
+
"partialSuccess": "部分成功",
|
|
560
|
+
"failed": "失败",
|
|
561
|
+
"duration": "耗时:",
|
|
562
|
+
"token": "Token:",
|
|
563
|
+
"cost": "成本:",
|
|
564
|
+
"taskBreakdown": "任务拆分",
|
|
565
|
+
"subtaskCount": "个子任务",
|
|
566
|
+
"artifacts": "制品:",
|
|
567
|
+
"suggestions": "建议:"
|
|
568
|
+
},
|
|
569
|
+
"taskGraph": {
|
|
570
|
+
"title": "任务拆分概览",
|
|
571
|
+
"total": "共 {{count}} 个子任务,{{layers}} 层并行",
|
|
572
|
+
"layer": "第 {{index}} 层 (可并行):"
|
|
573
|
+
},
|
|
574
|
+
"agents": {
|
|
575
|
+
"title": "已注册 Agent",
|
|
576
|
+
"empty": "暂无已注册的 Agent",
|
|
577
|
+
"id": "ID",
|
|
578
|
+
"status": "状态",
|
|
579
|
+
"load": "负载",
|
|
580
|
+
"capability": "能力"
|
|
581
|
+
},
|
|
582
|
+
"config": {
|
|
583
|
+
"title": "当前配置",
|
|
584
|
+
"llm": "LLM:",
|
|
585
|
+
"defaultModel": "默认模型:",
|
|
586
|
+
"provider": "提供商:",
|
|
587
|
+
"modelId": "模型 ID:",
|
|
588
|
+
"inputType": "输入类型:",
|
|
589
|
+
"apiKey": "API Key:",
|
|
590
|
+
"apiKeyConfigured": "***已配置***",
|
|
591
|
+
"apiKeyNotConfigured": "(未配置)",
|
|
592
|
+
"apiFormat": "API 格式:",
|
|
593
|
+
"scheduler": "调度器:",
|
|
594
|
+
"maxConcurrency": "最大并行:",
|
|
595
|
+
"maxPerAgent": "单 Agent 最大并发:",
|
|
596
|
+
"taskTimeout": "任务超时:",
|
|
597
|
+
"maxRetries": "最大重试:",
|
|
598
|
+
"cli": "CLI:",
|
|
599
|
+
"colorEnabled": "开启",
|
|
600
|
+
"colorDisabled": "关闭",
|
|
601
|
+
"debugEnabled": "开启",
|
|
602
|
+
"debugDisabled": "关闭",
|
|
603
|
+
"outputFormat": "输出格式:",
|
|
604
|
+
"uiLanguage": "UI 语言:",
|
|
605
|
+
"agents": "Agents:",
|
|
606
|
+
"minutes": "分钟"
|
|
607
|
+
},
|
|
608
|
+
"history": {
|
|
609
|
+
"title": "会话历史",
|
|
610
|
+
"empty": "暂无历史记录"
|
|
611
|
+
},
|
|
612
|
+
"status": {
|
|
613
|
+
"title": "会话状态",
|
|
614
|
+
"idle": "空闲",
|
|
615
|
+
"executing": "执行中",
|
|
616
|
+
"closing": "关闭中",
|
|
617
|
+
"state": "状态:",
|
|
618
|
+
"totalRequests": "总请求数:",
|
|
619
|
+
"success": "成功:",
|
|
620
|
+
"failure": "失败:",
|
|
621
|
+
"tokenConsumption": "Token 消耗:",
|
|
622
|
+
"totalCost": "总成本:"
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
dialog: {
|
|
626
|
+
"footer": {
|
|
627
|
+
"search": "输入文字搜索 · ↑↓ 导航 · Enter 确认 · Esc 取消",
|
|
628
|
+
"normal": "k/j ↑↓ 导航 · / 搜索 · Enter 选择 · Esc/q 退出 · BS/h 返回",
|
|
629
|
+
"searchNarrow": "Enter 确认 · Esc 取消",
|
|
630
|
+
"normalNarrow": "↑↓=k/j / Enter Esc/q BS/h",
|
|
631
|
+
"textInput": "Enter to confirm · Esc to cancel"
|
|
632
|
+
},
|
|
633
|
+
"configView": {
|
|
634
|
+
"narrow": "q/Esc 返回",
|
|
635
|
+
"wide": "q/Esc 返回 · Enter/BS/h 返回菜单"
|
|
636
|
+
}
|
|
637
|
+
},
|
|
638
|
+
settings: {
|
|
639
|
+
"mainMenu": {
|
|
640
|
+
"defaultModel": "默认模型",
|
|
641
|
+
"manageProviders": "管理提供商",
|
|
642
|
+
"viewConfig": "查看配置",
|
|
643
|
+
"language": "Language / 语言",
|
|
644
|
+
"notConfigured": "未配置",
|
|
645
|
+
"nConfigured": "已配置 {{count}} 个",
|
|
646
|
+
"noneConfigured": "未配置",
|
|
647
|
+
"displayFullConfig": "显示完整配置详情"
|
|
648
|
+
},
|
|
649
|
+
"apiKeyConfig": {
|
|
650
|
+
"useEnvVar": "使用环境变量",
|
|
651
|
+
"useEnvVarDesc": "推荐 — 更安全",
|
|
652
|
+
"enterManually": "手动输入",
|
|
653
|
+
"enterManuallyDesc": "直接输入密钥(以明文存储在 settings.json 中)",
|
|
654
|
+
"clear": "清除",
|
|
655
|
+
"clearDesc": "移除已配置的密钥"
|
|
656
|
+
},
|
|
657
|
+
"providerActions": {
|
|
658
|
+
"configureApiKey": "配置 API Key",
|
|
659
|
+
"selectModel": "选择模型",
|
|
660
|
+
"baseUrl": "Base URL",
|
|
661
|
+
"setAsDefault": "设为默认"
|
|
662
|
+
},
|
|
663
|
+
"providerEntry": {
|
|
664
|
+
"keyConfigured": "已配置密钥",
|
|
665
|
+
"noKey": "无密钥",
|
|
666
|
+
"addProvider": "添加提供商",
|
|
667
|
+
"addProviderDesc": "从已知提供商列表中选择",
|
|
668
|
+
"apiFormat": "API 格式: {{format}}",
|
|
669
|
+
"openaiCompatible": "OpenAI 兼容"
|
|
670
|
+
},
|
|
671
|
+
"addProvider": {
|
|
672
|
+
"yes": "是,立即配置 API Key",
|
|
673
|
+
"yesDesc": "前往 API Key 设置",
|
|
674
|
+
"later": "稍后",
|
|
675
|
+
"laterDesc": "返回主菜单"
|
|
676
|
+
},
|
|
677
|
+
"messages": {
|
|
678
|
+
"apiKeyCleared": "[ok] 已清除 {{provider}} 的 API Key",
|
|
679
|
+
"apiKeySetToEnv": "[ok] {{provider}} 的 API Key 已设置为环境变量 ${ {{envVar}} }",
|
|
680
|
+
"envVarNote": "请确保 {{envVar}} 已在 shell 中设置",
|
|
681
|
+
"apiKeyConfigured": "[ok] 已配置 {{provider}} 的 API Key",
|
|
682
|
+
"modelSelected": "[ok] 已选择模型: {{model}}",
|
|
683
|
+
"providerAdded": "[ok] 已添加提供商: {{provider}}",
|
|
684
|
+
"baseUrlReset": "[ok] 已重置 {{provider}} 的 Base URL 为默认值",
|
|
685
|
+
"baseUrlSet": "[ok] 已设置 {{provider}} 的 Base URL: {{url}}",
|
|
686
|
+
"defaultModelSet": "[ok] 默认模型已设置为: {{model}}",
|
|
687
|
+
"languageSet": "[ok] 语言已设置为: {{locale}}",
|
|
688
|
+
"restartRequired": "部分更改可能需要重启会话才能完全生效。",
|
|
689
|
+
"noModels": "没有可用的模型列表",
|
|
690
|
+
"configureManually": "请在 settings.json 中手动配置模型或检查提供商名称",
|
|
691
|
+
"alreadyExists": "已存在,请使用该提供商条目进行配置",
|
|
692
|
+
"configureFirst": "请先配置模型再设为默认",
|
|
693
|
+
"checkApiKeyHelpPrefix": " 提示: 请检查"
|
|
694
|
+
},
|
|
695
|
+
"cliMode": {
|
|
696
|
+
"usage": "用法:",
|
|
697
|
+
"settingsUsage": "/settings — 打开交互式配置菜单",
|
|
698
|
+
"listProvidersUsage": "/settings list-providers — 列出所有已知提供商",
|
|
699
|
+
"listModelsUsage": "/settings list-models <name> — 列出提供商可用的模型",
|
|
700
|
+
"knownProviders": "已知提供商:",
|
|
701
|
+
"noModelsAvailable": "pi-ai 注册表中没有可用的模型",
|
|
702
|
+
"hintConfigureFirst": "提示: 使用 /settings 先配置此提供商",
|
|
703
|
+
"availableModels": "可用模型:"
|
|
704
|
+
},
|
|
705
|
+
"modelSelector": { "notConfigured": "未配置 - Enter 设置 API Key" }
|
|
706
|
+
},
|
|
707
|
+
session: {
|
|
708
|
+
"welcome": "ZapMyco: 欢迎回来!",
|
|
709
|
+
"errorPrefix": "[错误]",
|
|
710
|
+
"agentErrorMessage": "Agent 执行失败(无详细错误信息)",
|
|
711
|
+
"noContentError": "模型未返回任何内容,请检查 API Key 配置",
|
|
712
|
+
"displayName": "Zapmyco AI 助手",
|
|
713
|
+
"editorNotFound": "未找到编辑器: {{cmd}},请设置 $EDITOR 环境变量",
|
|
714
|
+
"editorFailed": "打开编辑器失败: {{message}}",
|
|
715
|
+
"executing": "正在执行...",
|
|
716
|
+
"setEnvVarHint": "请设置环境变量: export {{envVar}}=<your-api-key>",
|
|
717
|
+
"useConfigHint": "或在 REPL 中使用: /config set llm.providers.{{provider}}.apiKey <your-key>"
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
//#endregion
|
|
722
|
+
//#region src/i18n/index.ts
|
|
723
|
+
/**
|
|
724
|
+
* i18next 国际化模块
|
|
725
|
+
*
|
|
726
|
+
* 使用 i18next 实现国际化支持。
|
|
727
|
+
* 通过传入静态 resources 实现同步初始化,无需 async/await。
|
|
728
|
+
* 翻译文件为标准 JSON 格式,未来 React Web 界面可复用。
|
|
729
|
+
*/
|
|
730
|
+
i18next.init({
|
|
731
|
+
lng: "zh-CN",
|
|
732
|
+
fallbackLng: "zh-CN",
|
|
733
|
+
resources: {
|
|
734
|
+
"zh-CN": { translation: zh_CN_default },
|
|
735
|
+
en: { translation: en_default }
|
|
736
|
+
},
|
|
737
|
+
initAsync: false,
|
|
738
|
+
interpolation: {
|
|
739
|
+
escapeValue: false,
|
|
740
|
+
prefix: "{{",
|
|
741
|
+
suffix: "}}"
|
|
742
|
+
},
|
|
743
|
+
returnNull: false,
|
|
744
|
+
returnEmptyString: true
|
|
745
|
+
});
|
|
746
|
+
const { t } = i18next;
|
|
747
|
+
/**
|
|
748
|
+
* 设置当前语言
|
|
749
|
+
*/
|
|
750
|
+
function setLocale(locale) {
|
|
751
|
+
i18next.changeLanguage(locale).catch(() => {});
|
|
752
|
+
}
|
|
753
|
+
|
|
368
754
|
//#endregion
|
|
369
755
|
//#region src/cli/repl/components/dialogs.ts
|
|
370
756
|
/**
|
|
@@ -479,10 +865,10 @@ var SelectListWithFooter = class {
|
|
|
479
865
|
for (let i = 0; i < padding; i++) lines.push("");
|
|
480
866
|
if (width >= 50) {
|
|
481
867
|
lines.push(chalk.gray(` ${"─".repeat(Math.max(0, width - 4))}`));
|
|
482
|
-
if (this.isFiltering) lines.push(chalk.gray(
|
|
483
|
-
else lines.push(chalk.gray(
|
|
484
|
-
} else if (this.isFiltering) lines.push(chalk.gray(
|
|
485
|
-
else lines.push(chalk.gray(
|
|
868
|
+
if (this.isFiltering) lines.push(chalk.gray(` ${t("dialog.footer.search")}`));
|
|
869
|
+
else lines.push(chalk.gray(` ${t("dialog.footer.normal")}`));
|
|
870
|
+
} else if (this.isFiltering) lines.push(chalk.gray(` ${t("dialog.footer.searchNarrow")}`));
|
|
871
|
+
else lines.push(chalk.gray(` ${t("dialog.footer.normalNarrow")}`));
|
|
486
872
|
lines.push("");
|
|
487
873
|
return lines;
|
|
488
874
|
}
|
|
@@ -551,7 +937,7 @@ var TextInputComponent = class {
|
|
|
551
937
|
` ${this.input.render(width - 4)[0] ?? ""}`,
|
|
552
938
|
c.gray(` ${"─".repeat(Math.min(width - 4, 50))}`),
|
|
553
939
|
"",
|
|
554
|
-
c.gray(
|
|
940
|
+
c.gray(` ${t("dialog.footer.textInput")}`),
|
|
555
941
|
""
|
|
556
942
|
];
|
|
557
943
|
}
|
|
@@ -600,13 +986,13 @@ var ConfigViewComponent = class {
|
|
|
600
986
|
if (width < 50) return [
|
|
601
987
|
...this.lines,
|
|
602
988
|
"",
|
|
603
|
-
chalk.gray(
|
|
989
|
+
chalk.gray(` ${t("dialog.configView.narrow")}`)
|
|
604
990
|
];
|
|
605
991
|
return [
|
|
606
992
|
...this.lines,
|
|
607
993
|
"",
|
|
608
994
|
chalk.gray(` ${"─".repeat(Math.max(0, width - 4))}`),
|
|
609
|
-
chalk.gray(
|
|
995
|
+
chalk.gray(` ${t("dialog.configView.wide")}`),
|
|
610
996
|
""
|
|
611
997
|
];
|
|
612
998
|
}
|
|
@@ -766,6 +1152,16 @@ const KNOWN_PROVIDERS = [
|
|
|
766
1152
|
label: "OpenCode"
|
|
767
1153
|
}
|
|
768
1154
|
];
|
|
1155
|
+
/** Supported language locales */
|
|
1156
|
+
const SUPPORTED_LOCALES = [{
|
|
1157
|
+
value: "zh-CN",
|
|
1158
|
+
label: "简体中文",
|
|
1159
|
+
description: "Chinese (Simplified)"
|
|
1160
|
+
}, {
|
|
1161
|
+
value: "en",
|
|
1162
|
+
label: "English",
|
|
1163
|
+
description: "English"
|
|
1164
|
+
}];
|
|
769
1165
|
/** Set a dot-path value, persist to disk and hot-reload agent */
|
|
770
1166
|
function setConfigValue(session, dotPath, value) {
|
|
771
1167
|
const settings = readSettings();
|
|
@@ -819,7 +1215,7 @@ async function handleCommandLine(args, session, _tui, config) {
|
|
|
819
1215
|
case "list-providers": {
|
|
820
1216
|
const providers = _getByDotPath(config, "llm.providers");
|
|
821
1217
|
const names = providers ? Object.keys(providers) : [];
|
|
822
|
-
const lines = ["", "
|
|
1218
|
+
const lines = ["", t("settings.cliMode.knownProviders")];
|
|
823
1219
|
for (const p of KNOWN_PROVIDERS) {
|
|
824
1220
|
const configured = names.includes(p.id) ? " ✓" : " ";
|
|
825
1221
|
lines.push(` ${configured} ${p.label} (${p.id})`);
|
|
@@ -831,7 +1227,7 @@ async function handleCommandLine(args, session, _tui, config) {
|
|
|
831
1227
|
if (!args[1]) {
|
|
832
1228
|
session.appendOutput([
|
|
833
1229
|
"",
|
|
834
|
-
"
|
|
1230
|
+
`${t("settings.cliMode.usage")} /settings list-models <provider>`,
|
|
835
1231
|
""
|
|
836
1232
|
]);
|
|
837
1233
|
return;
|
|
@@ -840,15 +1236,15 @@ async function handleCommandLine(args, session, _tui, config) {
|
|
|
840
1236
|
if (modelIds.length === 0) {
|
|
841
1237
|
session.appendOutput([
|
|
842
1238
|
"",
|
|
843
|
-
`Provider "${args[1]}"
|
|
844
|
-
"
|
|
1239
|
+
`Provider "${args[1]}" ${t("settings.messages.noModels")}`,
|
|
1240
|
+
t("settings.cliMode.hintConfigureFirst"),
|
|
845
1241
|
""
|
|
846
1242
|
]);
|
|
847
1243
|
return;
|
|
848
1244
|
}
|
|
849
1245
|
session.appendOutput([
|
|
850
1246
|
"",
|
|
851
|
-
`${args[1]}
|
|
1247
|
+
`${args[1]} ${t("settings.cliMode.availableModels")}`,
|
|
852
1248
|
...modelIds.map((id) => ` - ${id}`),
|
|
853
1249
|
""
|
|
854
1250
|
]);
|
|
@@ -856,10 +1252,10 @@ async function handleCommandLine(args, session, _tui, config) {
|
|
|
856
1252
|
}
|
|
857
1253
|
default: session.appendOutput([
|
|
858
1254
|
"",
|
|
859
|
-
"
|
|
860
|
-
"
|
|
861
|
-
"
|
|
862
|
-
"
|
|
1255
|
+
t("settings.cliMode.usage"),
|
|
1256
|
+
` ${t("settings.cliMode.settingsUsage")}`,
|
|
1257
|
+
` ${t("settings.cliMode.listProvidersUsage")}`,
|
|
1258
|
+
` ${t("settings.cliMode.listModelsUsage")}`,
|
|
863
1259
|
""
|
|
864
1260
|
]);
|
|
865
1261
|
}
|
|
@@ -877,18 +1273,18 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
877
1273
|
const choice = await showSelectList(tui, [
|
|
878
1274
|
{
|
|
879
1275
|
value: "env",
|
|
880
|
-
label:
|
|
881
|
-
description: "
|
|
1276
|
+
label: `${t("settings.apiKeyConfig.useEnvVar")} \${${envVarName}}`,
|
|
1277
|
+
description: t("settings.apiKeyConfig.useEnvVarDesc")
|
|
882
1278
|
},
|
|
883
1279
|
{
|
|
884
1280
|
value: "manual",
|
|
885
|
-
label: "
|
|
886
|
-
description: "
|
|
1281
|
+
label: t("settings.apiKeyConfig.enterManually"),
|
|
1282
|
+
description: t("settings.apiKeyConfig.enterManuallyDesc")
|
|
887
1283
|
},
|
|
888
1284
|
{
|
|
889
1285
|
value: "clear",
|
|
890
|
-
label: "
|
|
891
|
-
description: "
|
|
1286
|
+
label: t("settings.apiKeyConfig.clear"),
|
|
1287
|
+
description: t("settings.apiKeyConfig.clearDesc")
|
|
892
1288
|
}
|
|
893
1289
|
], { onExit: exitAll });
|
|
894
1290
|
if (!choice) return;
|
|
@@ -896,15 +1292,18 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
896
1292
|
setConfigValue(session, `llm.providers.${providerName}.apiKey`, "");
|
|
897
1293
|
session.appendOutput([
|
|
898
1294
|
"",
|
|
899
|
-
`
|
|
1295
|
+
` ${t("settings.messages.apiKeyCleared", { provider: providerName })}`,
|
|
900
1296
|
""
|
|
901
1297
|
]);
|
|
902
1298
|
} else if (choice.value === "env") {
|
|
903
1299
|
setConfigValue(session, `llm.providers.${providerName}.apiKey`, `\${${envVarName}}`);
|
|
904
1300
|
session.appendOutput([
|
|
905
1301
|
"",
|
|
906
|
-
`
|
|
907
|
-
|
|
1302
|
+
` ${t("settings.messages.apiKeySetToEnv", {
|
|
1303
|
+
provider: providerName,
|
|
1304
|
+
envVar: envVarName
|
|
1305
|
+
})}`,
|
|
1306
|
+
` ${t("settings.messages.envVarNote", { envVar: envVarName })}`,
|
|
908
1307
|
""
|
|
909
1308
|
]);
|
|
910
1309
|
} else if (choice.value === "manual") {
|
|
@@ -913,7 +1312,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
913
1312
|
setConfigValue(session, `llm.providers.${providerName}.apiKey`, key);
|
|
914
1313
|
session.appendOutput([
|
|
915
1314
|
"",
|
|
916
|
-
`
|
|
1315
|
+
` ${t("settings.messages.apiKeyConfigured", { provider: providerName })}`,
|
|
917
1316
|
""
|
|
918
1317
|
]);
|
|
919
1318
|
}
|
|
@@ -934,14 +1333,17 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
934
1333
|
writeSettings(settings);
|
|
935
1334
|
session.appendOutput([
|
|
936
1335
|
"",
|
|
937
|
-
`
|
|
1336
|
+
` ${t("settings.messages.baseUrlReset", { provider: providerName })}`,
|
|
938
1337
|
""
|
|
939
1338
|
]);
|
|
940
1339
|
} else {
|
|
941
1340
|
setConfigValue(session, configPath, url);
|
|
942
1341
|
session.appendOutput([
|
|
943
1342
|
"",
|
|
944
|
-
`
|
|
1343
|
+
` ${t("settings.messages.baseUrlSet", {
|
|
1344
|
+
provider: providerName,
|
|
1345
|
+
url
|
|
1346
|
+
})}`,
|
|
945
1347
|
""
|
|
946
1348
|
]);
|
|
947
1349
|
}
|
|
@@ -955,8 +1357,8 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
955
1357
|
if (modelIds.length === 0) {
|
|
956
1358
|
session.appendOutput([
|
|
957
1359
|
"",
|
|
958
|
-
` ${providerName}
|
|
959
|
-
"
|
|
1360
|
+
` ${providerName} ${t("settings.messages.noModels")}`,
|
|
1361
|
+
` ${t("settings.messages.configureManually")}`,
|
|
960
1362
|
""
|
|
961
1363
|
]);
|
|
962
1364
|
return;
|
|
@@ -974,7 +1376,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
974
1376
|
_setByDotPath(session.config, `llm.providers.${providerName}.models`, _getByDotPath(settings, `llm.providers.${providerName}.models`) ?? {});
|
|
975
1377
|
session.appendOutput([
|
|
976
1378
|
"",
|
|
977
|
-
`
|
|
1379
|
+
` ${t("settings.messages.modelSelected", { model: `${providerName}/${modelId}` })}`,
|
|
978
1380
|
""
|
|
979
1381
|
]);
|
|
980
1382
|
}
|
|
@@ -987,7 +1389,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
987
1389
|
if (modelIds.length === 0) {
|
|
988
1390
|
session.appendOutput([
|
|
989
1391
|
"",
|
|
990
|
-
|
|
1392
|
+
` ${t("settings.messages.configureFirst")}`,
|
|
991
1393
|
""
|
|
992
1394
|
]);
|
|
993
1395
|
return;
|
|
@@ -996,7 +1398,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
996
1398
|
setConfigValue(session, "llm.defaultModel", modelKey);
|
|
997
1399
|
session.appendOutput([
|
|
998
1400
|
"",
|
|
999
|
-
`
|
|
1401
|
+
` ${t("settings.messages.defaultModelSet", { model: modelKey })}`,
|
|
1000
1402
|
""
|
|
1001
1403
|
]);
|
|
1002
1404
|
};
|
|
@@ -1011,18 +1413,23 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1011
1413
|
const choice = await showSelectList(tui, [
|
|
1012
1414
|
{
|
|
1013
1415
|
value: "default-model",
|
|
1014
|
-
label: "
|
|
1015
|
-
description: String(_getByDotPath(state.current, "llm.defaultModel") ?? "
|
|
1416
|
+
label: t("settings.mainMenu.defaultModel"),
|
|
1417
|
+
description: String(_getByDotPath(state.current, "llm.defaultModel") ?? t("settings.mainMenu.notConfigured"))
|
|
1016
1418
|
},
|
|
1017
1419
|
{
|
|
1018
1420
|
value: "manage-providers",
|
|
1019
|
-
label: "
|
|
1020
|
-
description: providerCount > 0 ?
|
|
1421
|
+
label: t("settings.mainMenu.manageProviders"),
|
|
1422
|
+
description: providerCount > 0 ? t("settings.mainMenu.nConfigured", { count: providerCount }) : t("settings.mainMenu.noneConfigured")
|
|
1021
1423
|
},
|
|
1022
1424
|
{
|
|
1023
1425
|
value: "view-config",
|
|
1024
|
-
label: "
|
|
1025
|
-
description: "
|
|
1426
|
+
label: t("settings.mainMenu.viewConfig"),
|
|
1427
|
+
description: t("settings.mainMenu.displayFullConfig")
|
|
1428
|
+
},
|
|
1429
|
+
{
|
|
1430
|
+
value: "language",
|
|
1431
|
+
label: t("settings.mainMenu.language"),
|
|
1432
|
+
description: String(_getByDotPath(state.current, "locale") ?? "zh-CN")
|
|
1026
1433
|
}
|
|
1027
1434
|
], { onExit: exitAll });
|
|
1028
1435
|
if (!choice) {
|
|
@@ -1049,7 +1456,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1049
1456
|
else disabledItems.push({
|
|
1050
1457
|
value: key,
|
|
1051
1458
|
label: chalk.gray(key),
|
|
1052
|
-
description: chalk.gray("
|
|
1459
|
+
description: chalk.gray(t("settings.modelSelector.notConfigured"))
|
|
1053
1460
|
});
|
|
1054
1461
|
}
|
|
1055
1462
|
}
|
|
@@ -1057,7 +1464,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1057
1464
|
if (modelItems.length === 0) {
|
|
1058
1465
|
session.appendOutput([
|
|
1059
1466
|
"",
|
|
1060
|
-
|
|
1467
|
+
` ${t("settings.cliMode.noModelsAvailable")}`,
|
|
1061
1468
|
""
|
|
1062
1469
|
]);
|
|
1063
1470
|
continue;
|
|
@@ -1071,7 +1478,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1071
1478
|
setConfigValue(session, "llm.defaultModel", selectedKey);
|
|
1072
1479
|
session.appendOutput([
|
|
1073
1480
|
"",
|
|
1074
|
-
`
|
|
1481
|
+
` ${t("settings.messages.defaultModelSet", { model: selectedKey })}`,
|
|
1075
1482
|
""
|
|
1076
1483
|
]);
|
|
1077
1484
|
} else {
|
|
@@ -1091,7 +1498,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1091
1498
|
setConfigValue(session, "llm.defaultModel", selectedKey);
|
|
1092
1499
|
session.appendOutput([
|
|
1093
1500
|
"",
|
|
1094
|
-
`
|
|
1501
|
+
` ${t("settings.messages.defaultModelSet", { model: selectedKey })}`,
|
|
1095
1502
|
""
|
|
1096
1503
|
]);
|
|
1097
1504
|
}
|
|
@@ -1102,12 +1509,12 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1102
1509
|
return {
|
|
1103
1510
|
value: `provider:${name}`,
|
|
1104
1511
|
label: name,
|
|
1105
|
-
description: hasK ? "
|
|
1512
|
+
description: hasK ? t("settings.providerEntry.keyConfigured") : t("settings.providerEntry.noKey")
|
|
1106
1513
|
};
|
|
1107
1514
|
}), {
|
|
1108
1515
|
value: "add-provider",
|
|
1109
|
-
label: "
|
|
1110
|
-
description: "
|
|
1516
|
+
label: t("settings.providerEntry.addProvider"),
|
|
1517
|
+
description: t("settings.providerEntry.addProviderDesc")
|
|
1111
1518
|
}], { onExit: exitAll });
|
|
1112
1519
|
if (!providerChoice) continue;
|
|
1113
1520
|
const providerValue = providerChoice.value;
|
|
@@ -1116,22 +1523,22 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1116
1523
|
const action = await showSelectList(tui, [
|
|
1117
1524
|
{
|
|
1118
1525
|
value: "api-key",
|
|
1119
|
-
label: "
|
|
1526
|
+
label: t("settings.providerActions.configureApiKey"),
|
|
1120
1527
|
description: ""
|
|
1121
1528
|
},
|
|
1122
1529
|
{
|
|
1123
1530
|
value: "model",
|
|
1124
|
-
label: "
|
|
1531
|
+
label: t("settings.providerActions.selectModel"),
|
|
1125
1532
|
description: ""
|
|
1126
1533
|
},
|
|
1127
1534
|
{
|
|
1128
1535
|
value: "base-url",
|
|
1129
|
-
label: "
|
|
1536
|
+
label: t("settings.providerActions.baseUrl"),
|
|
1130
1537
|
description: ""
|
|
1131
1538
|
},
|
|
1132
1539
|
{
|
|
1133
1540
|
value: "set-default",
|
|
1134
|
-
label: "
|
|
1541
|
+
label: t("settings.providerActions.setAsDefault"),
|
|
1135
1542
|
description: ""
|
|
1136
1543
|
}
|
|
1137
1544
|
], { onExit: exitAll });
|
|
@@ -1154,7 +1561,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1154
1561
|
const selected = await showSelectList(tui, KNOWN_PROVIDERS.map((p) => ({
|
|
1155
1562
|
value: p.id,
|
|
1156
1563
|
label: `${p.label} (${p.id})`,
|
|
1157
|
-
description: p.apiFormat ?
|
|
1564
|
+
description: p.apiFormat ? t("settings.providerEntry.apiFormat", { format: p.apiFormat }) : t("settings.providerEntry.openaiCompatible")
|
|
1158
1565
|
})), {
|
|
1159
1566
|
maxVisible: 12,
|
|
1160
1567
|
onExit: exitAll
|
|
@@ -1165,7 +1572,7 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1165
1572
|
if (existingProviders && providerName in existingProviders) {
|
|
1166
1573
|
session.appendOutput([
|
|
1167
1574
|
"",
|
|
1168
|
-
` ${providerName}
|
|
1575
|
+
` ${providerName} ${t("settings.messages.alreadyExists")}`,
|
|
1169
1576
|
""
|
|
1170
1577
|
]);
|
|
1171
1578
|
continue;
|
|
@@ -1179,22 +1586,39 @@ async function handleInteractiveMode(tui, session, config) {
|
|
|
1179
1586
|
_setByDotPath(session.config, `llm.providers.${providerName}`, newProvider);
|
|
1180
1587
|
session.appendOutput([
|
|
1181
1588
|
"",
|
|
1182
|
-
`
|
|
1589
|
+
` ${t("settings.messages.providerAdded", { provider: providerName })}`,
|
|
1183
1590
|
""
|
|
1184
1591
|
]);
|
|
1185
1592
|
if ((await showSelectList(tui, [{
|
|
1186
1593
|
value: "yes",
|
|
1187
|
-
label: "
|
|
1188
|
-
description: "
|
|
1594
|
+
label: t("settings.addProvider.yes"),
|
|
1595
|
+
description: t("settings.addProvider.yesDesc")
|
|
1189
1596
|
}, {
|
|
1190
1597
|
value: "no",
|
|
1191
|
-
label: "
|
|
1192
|
-
description: "
|
|
1598
|
+
label: t("settings.addProvider.later"),
|
|
1599
|
+
description: t("settings.addProvider.laterDesc")
|
|
1193
1600
|
}], { onExit: exitAll }))?.value === "yes") await handleApiKeyConfig(providerName, "");
|
|
1194
1601
|
}
|
|
1195
1602
|
} else if (value === "view-config") {
|
|
1196
1603
|
const renderer = session.getRenderer();
|
|
1197
1604
|
await showConfigView(tui, session.config, renderer);
|
|
1605
|
+
} else if (value === "language") {
|
|
1606
|
+
const currentLocale = String(_getByDotPath(state.current, "locale") ?? "zh-CN");
|
|
1607
|
+
const selected = await showSelectList(tui, SUPPORTED_LOCALES.map((loc) => ({
|
|
1608
|
+
...loc,
|
|
1609
|
+
label: loc.value === currentLocale ? `${loc.label} ✓` : loc.label
|
|
1610
|
+
})), { onExit: exitAll });
|
|
1611
|
+
if (!selected || !selected.value) continue;
|
|
1612
|
+
if (selected.value !== currentLocale) {
|
|
1613
|
+
setConfigValue(session, "locale", selected.value);
|
|
1614
|
+
setLocale(selected.value);
|
|
1615
|
+
session.appendOutput([
|
|
1616
|
+
"",
|
|
1617
|
+
` ${t("settings.messages.languageSet", { locale: selected.value })}`,
|
|
1618
|
+
` ${t("settings.messages.restartRequired")}`,
|
|
1619
|
+
""
|
|
1620
|
+
]);
|
|
1621
|
+
}
|
|
1198
1622
|
}
|
|
1199
1623
|
}
|
|
1200
1624
|
}
|
|
@@ -2198,7 +2622,7 @@ var OutputFormatter = class {
|
|
|
2198
2622
|
"",
|
|
2199
2623
|
` 🍄 ${c.bold(`zapmyco@${version}`)}`,
|
|
2200
2624
|
"",
|
|
2201
|
-
|
|
2625
|
+
` ${t("output.welcome")}`,
|
|
2202
2626
|
"",
|
|
2203
2627
|
c.gray("─".repeat(90)),
|
|
2204
2628
|
""
|
|
@@ -2211,8 +2635,8 @@ var OutputFormatter = class {
|
|
|
2211
2635
|
const zapmycoError = error;
|
|
2212
2636
|
if (zapmycoError.code) {
|
|
2213
2637
|
lines.push(`${c.red.bold(` ✗ [${zapmycoError.code}]`)} ${error.message}`);
|
|
2214
|
-
if (zapmycoError.context && Object.keys(zapmycoError.context).length > 0) lines.push(c.gray(`
|
|
2215
|
-
} else lines.push(`${c.red.bold(
|
|
2638
|
+
if (zapmycoError.context && Object.keys(zapmycoError.context).length > 0) lines.push(c.gray(` ${t("output.error.detail")} ${JSON.stringify(zapmycoError.context)}`));
|
|
2639
|
+
} else lines.push(`${c.red.bold(` ✗ ${t("output.error.executionFailed")}`)} ${error.message}`);
|
|
2216
2640
|
lines.push("");
|
|
2217
2641
|
return lines;
|
|
2218
2642
|
}
|
|
@@ -2223,16 +2647,16 @@ var OutputFormatter = class {
|
|
|
2223
2647
|
const lines = [
|
|
2224
2648
|
"",
|
|
2225
2649
|
c.gray(" ┌────────────────────────────────────────────┐"),
|
|
2226
|
-
` │ ${statusIcon} ${c.bold("
|
|
2650
|
+
` │ ${statusIcon} ${c.bold(t("output.result.title"))}`,
|
|
2227
2651
|
c.gray(" ├────────────────────────────────────────────┤"),
|
|
2228
|
-
` │ ${c.gray("
|
|
2229
|
-
` │ ${c.gray("
|
|
2230
|
-
` │ ${c.gray("
|
|
2231
|
-
` │ ${c.gray("
|
|
2652
|
+
` │ ${c.gray(t("output.result.goal"))} ${result.summary.slice(0, 40)}`,
|
|
2653
|
+
` │ ${c.gray(t("output.result.status"))} ${result.overallStatus === "success" ? c.green(t("output.result.success")) : result.overallStatus === "partial-failure" ? c.yellow(t("output.result.partialSuccess")) : c.red(t("output.result.failed"))}`,
|
|
2654
|
+
` │ ${c.gray(t("output.result.duration"))} ${(result.totalDuration / 1e3).toFixed(1)}s · ${c.gray(t("output.result.token"))} ${result.totalTokenUsage.totalTokens.toLocaleString()}`,
|
|
2655
|
+
` │ ${c.gray(t("output.result.cost"))} $${result.totalTokenUsage.estimatedCostUsd.toFixed(4)}`
|
|
2232
2656
|
];
|
|
2233
2657
|
if (result.taskResults.length > 0) {
|
|
2234
2658
|
lines.push(c.gray(" ├────────────────────────────────────────────┤"));
|
|
2235
|
-
lines.push(` │ ${c.bold("
|
|
2659
|
+
lines.push(` │ ${c.bold(t("output.result.taskBreakdown"))} (${result.taskResults.length} ${t("output.result.subtaskCount")}):`);
|
|
2236
2660
|
for (const tr of result.taskResults) {
|
|
2237
2661
|
const icon = tr.status === "success" ? c.green("✓") : tr.status === "partial" ? c.yellow("~") : c.red("✗");
|
|
2238
2662
|
lines.push(` │ ${icon} ${tr.taskId.slice(0, 12)}...`);
|
|
@@ -2240,7 +2664,7 @@ var OutputFormatter = class {
|
|
|
2240
2664
|
}
|
|
2241
2665
|
if (result.allArtifacts.length > 0) {
|
|
2242
2666
|
lines.push(c.gray(" ├────────────────────────────────────────────┤"));
|
|
2243
|
-
lines.push(` │ ${c.bold("
|
|
2667
|
+
lines.push(` │ ${c.bold(t("output.result.artifacts"))}`);
|
|
2244
2668
|
for (const artifact of result.allArtifacts) {
|
|
2245
2669
|
const icon = artifact.type === "pull-request" ? "🔗" : "📄";
|
|
2246
2670
|
lines.push(` │ ${icon} ${artifact.description} (${artifact.reference})`);
|
|
@@ -2248,7 +2672,7 @@ var OutputFormatter = class {
|
|
|
2248
2672
|
}
|
|
2249
2673
|
if (result.nextSteps && result.nextSteps.length > 0) {
|
|
2250
2674
|
lines.push(c.gray(" ├────────────────────────────────────────────┤"));
|
|
2251
|
-
lines.push(` │ ${c.bold("
|
|
2675
|
+
lines.push(` │ ${c.bold(t("output.result.suggestions"))}`);
|
|
2252
2676
|
for (let i = 0; i < result.nextSteps.length; i++) lines.push(` │ ${i + 1}. ${result.nextSteps[i]}`);
|
|
2253
2677
|
}
|
|
2254
2678
|
lines.push(c.gray(" └────────────────────────────────────────────┘"));
|
|
@@ -2260,14 +2684,17 @@ var OutputFormatter = class {
|
|
|
2260
2684
|
const c = this.getColor();
|
|
2261
2685
|
const lines = [
|
|
2262
2686
|
"",
|
|
2263
|
-
c.bold(
|
|
2264
|
-
c.gray(`
|
|
2687
|
+
c.bold(` 📋 ${t("output.taskGraph.title")}`),
|
|
2688
|
+
c.gray(` ${t("output.taskGraph.total", {
|
|
2689
|
+
count: graph.nodes.size,
|
|
2690
|
+
layers: graph.layers.length
|
|
2691
|
+
})}`),
|
|
2265
2692
|
""
|
|
2266
2693
|
];
|
|
2267
2694
|
for (let layerIdx = 0; layerIdx < graph.layers.length; layerIdx++) {
|
|
2268
2695
|
const layer = graph.layers[layerIdx];
|
|
2269
2696
|
if (!layer) continue;
|
|
2270
|
-
lines.push(c.gray(`
|
|
2697
|
+
lines.push(c.gray(` ${t("output.taskGraph.layer", { index: layerIdx + 1 })}`));
|
|
2271
2698
|
for (const taskId of layer) {
|
|
2272
2699
|
const task = graph.nodes.get(taskId);
|
|
2273
2700
|
if (task) {
|
|
@@ -2284,15 +2711,15 @@ var OutputFormatter = class {
|
|
|
2284
2711
|
const c = this.getColor();
|
|
2285
2712
|
const lines = [
|
|
2286
2713
|
"",
|
|
2287
|
-
c.bold(
|
|
2714
|
+
c.bold(` 🤖 ${t("output.agents.title")}`),
|
|
2288
2715
|
""
|
|
2289
2716
|
];
|
|
2290
2717
|
if (agents.length === 0) {
|
|
2291
|
-
lines.push(c.gray(
|
|
2718
|
+
lines.push(c.gray(` ${t("output.agents.empty")}`));
|
|
2292
2719
|
lines.push("");
|
|
2293
2720
|
return lines;
|
|
2294
2721
|
}
|
|
2295
|
-
lines.push(` ${c.bold("
|
|
2722
|
+
lines.push(` ${c.bold(t("output.agents.id")).padEnd(20)} ${c.bold(t("output.agents.status")).padEnd(10)} ${c.bold(t("output.agents.load")).padEnd(8)} ${c.bold(t("output.agents.capability"))}`);
|
|
2296
2723
|
lines.push(c.gray(` ${"─".repeat(60)}`));
|
|
2297
2724
|
for (const agent of agents) {
|
|
2298
2725
|
const statusDot = agent.status === "online" ? c.green("●") : agent.status === "busy" ? c.yellow("●") : c.gray("○");
|
|
@@ -2307,32 +2734,33 @@ var OutputFormatter = class {
|
|
|
2307
2734
|
const c = this.getColor();
|
|
2308
2735
|
const lines = [
|
|
2309
2736
|
"",
|
|
2310
|
-
c.bold(
|
|
2737
|
+
c.bold(` ⚙️ ${t("output.config.title")}`),
|
|
2311
2738
|
"",
|
|
2312
|
-
c.bold(
|
|
2739
|
+
c.bold(` ${t("output.config.llm")}`)
|
|
2313
2740
|
];
|
|
2314
|
-
lines.push(`
|
|
2741
|
+
lines.push(` ${t("output.config.defaultModel")} ${config.llm.defaultModel}`);
|
|
2315
2742
|
const defaultModelKey = config.llm.defaultModel;
|
|
2316
2743
|
const slashIdx = defaultModelKey.indexOf("/");
|
|
2317
2744
|
const defaultProvider = slashIdx > 0 ? defaultModelKey.slice(0, slashIdx) : "anthropic";
|
|
2318
2745
|
const defaultModelName = slashIdx > 0 ? defaultModelKey.slice(slashIdx + 1) : defaultModelKey;
|
|
2319
2746
|
const providerConfig = config.llm.providers[defaultProvider];
|
|
2320
2747
|
const modelConfig = providerConfig?.models?.[defaultModelName];
|
|
2321
|
-
lines.push(`
|
|
2322
|
-
lines.push(`
|
|
2323
|
-
if (modelConfig?.input && modelConfig.input.length > 0) lines.push(`
|
|
2324
|
-
lines.push(`
|
|
2325
|
-
if (providerConfig?.apiFormat) lines.push(`
|
|
2326
|
-
lines.push(c.bold(
|
|
2327
|
-
lines.push(`
|
|
2328
|
-
lines.push(`
|
|
2329
|
-
lines.push(`
|
|
2330
|
-
lines.push(`
|
|
2331
|
-
lines.push(c.bold(
|
|
2332
|
-
lines.push(`
|
|
2333
|
-
lines.push(`
|
|
2334
|
-
lines.push(`
|
|
2335
|
-
lines.push(
|
|
2748
|
+
lines.push(` ${t("output.config.provider")} ${defaultProvider}`);
|
|
2749
|
+
lines.push(` ${t("output.config.modelId")} ${modelConfig?.id ?? defaultModelName}`);
|
|
2750
|
+
if (modelConfig?.input && modelConfig.input.length > 0) lines.push(` ${t("output.config.inputType")} ${modelConfig.input.join(", ")}`);
|
|
2751
|
+
lines.push(` ${t("output.config.apiKey")} ${providerConfig?.apiKey ? c.gray(t("output.config.apiKeyConfigured")) : c.red(t("output.config.apiKeyNotConfigured"))}`);
|
|
2752
|
+
if (providerConfig?.apiFormat) lines.push(` ${t("output.config.apiFormat")} ${providerConfig.apiFormat}`);
|
|
2753
|
+
lines.push(c.bold(` ${t("output.config.scheduler")}`));
|
|
2754
|
+
lines.push(` ${t("output.config.maxConcurrency")} ${config.scheduler.maxConcurrency}`);
|
|
2755
|
+
lines.push(` ${t("output.config.maxPerAgent")} ${config.scheduler.maxPerAgent}`);
|
|
2756
|
+
lines.push(` ${t("output.config.taskTimeout")} ${(config.scheduler.taskTimeoutMs / 1e3 / 60).toFixed(0)} ${t("output.config.minutes")}`);
|
|
2757
|
+
lines.push(` ${t("output.config.maxRetries")} ${config.scheduler.maxRetries}`);
|
|
2758
|
+
lines.push(c.bold(` ${t("output.config.cli")}`));
|
|
2759
|
+
lines.push(` ${t("output.config.colorEnabled")}: ${config.cli.color ? c.green(t("output.config.colorEnabled")) : c.gray(t("output.config.colorDisabled"))}`);
|
|
2760
|
+
lines.push(` ${t("output.config.debugEnabled")}: ${config.cli.debug ? c.green(t("output.config.debugEnabled")) : c.gray(t("output.config.debugDisabled"))}`);
|
|
2761
|
+
lines.push(` ${t("output.config.outputFormat")} ${config.cli.outputFormat}`);
|
|
2762
|
+
lines.push(` ${t("output.config.uiLanguage")} ${config.locale ?? "zh-CN"}`);
|
|
2763
|
+
lines.push(c.bold(` ${t("output.config.agents")}`));
|
|
2336
2764
|
for (const agent of config.agents) {
|
|
2337
2765
|
const statusIcon = agent.enabled ? c.green("✓") : c.gray("✗");
|
|
2338
2766
|
lines.push(` ${statusIcon} ${agent.id}`);
|
|
@@ -2345,11 +2773,11 @@ var OutputFormatter = class {
|
|
|
2345
2773
|
const c = this.getColor();
|
|
2346
2774
|
const lines = [
|
|
2347
2775
|
"",
|
|
2348
|
-
c.bold(
|
|
2776
|
+
c.bold(` 📜 ${t("output.history.title")}`),
|
|
2349
2777
|
""
|
|
2350
2778
|
];
|
|
2351
2779
|
if (entries.length === 0) {
|
|
2352
|
-
lines.push(c.gray(
|
|
2780
|
+
lines.push(c.gray(` ${t("output.history.empty")}`));
|
|
2353
2781
|
lines.push("");
|
|
2354
2782
|
return lines;
|
|
2355
2783
|
}
|
|
@@ -2368,16 +2796,16 @@ var OutputFormatter = class {
|
|
|
2368
2796
|
const c = this.getColor();
|
|
2369
2797
|
const lines = [
|
|
2370
2798
|
"",
|
|
2371
|
-
c.bold(
|
|
2799
|
+
c.bold(` 📊 ${t("output.status.title")}`),
|
|
2372
2800
|
""
|
|
2373
2801
|
];
|
|
2374
|
-
const stateLabel = stats.state === "idle" ? c.green("
|
|
2375
|
-
lines.push(`
|
|
2376
|
-
lines.push(`
|
|
2377
|
-
lines.push(`
|
|
2378
|
-
lines.push(`
|
|
2379
|
-
lines.push(`
|
|
2380
|
-
lines.push(`
|
|
2802
|
+
const stateLabel = stats.state === "idle" ? c.green(t("output.status.idle")) : stats.state === "executing" ? c.magenta(t("output.status.executing")) : c.gray(t("output.status.closing"));
|
|
2803
|
+
lines.push(` ${t("output.status.state").padEnd(10)} ${stateLabel}`);
|
|
2804
|
+
lines.push(` ${t("output.status.totalRequests").padEnd(10)} ${stats.totalRequests}`);
|
|
2805
|
+
lines.push(` ${t("output.status.success").padEnd(10)} ${c.green(String(stats.successCount))}`);
|
|
2806
|
+
lines.push(` ${t("output.status.failure").padEnd(10)} ${stats.failureCount > 0 ? c.red(String(stats.failureCount)) : String(stats.failureCount)}`);
|
|
2807
|
+
lines.push(` ${t("output.status.tokenConsumption").padEnd(10)} ${stats.totalTokens.toLocaleString()}`);
|
|
2808
|
+
lines.push(` ${t("output.status.totalCost").padEnd(10)} $${stats.totalCostUsd.toFixed(4)}`);
|
|
2381
2809
|
lines.push("");
|
|
2382
2810
|
return lines;
|
|
2383
2811
|
}
|
|
@@ -7550,8 +7978,8 @@ function getApiKeyErrorHelp(errorMessage) {
|
|
|
7550
7978
|
const envVarName = `${providerName.toUpperCase().replace(/-/g, "_")}_API_KEY`;
|
|
7551
7979
|
return [
|
|
7552
7980
|
"",
|
|
7553
|
-
chalk.yellow(`
|
|
7554
|
-
chalk.yellow(`
|
|
7981
|
+
chalk.yellow(` ${t("session.setEnvVarHint", { envVar: envVarName })}`),
|
|
7982
|
+
chalk.yellow(` ${t("session.useConfigHint", { provider: providerName })}`)
|
|
7555
7983
|
];
|
|
7556
7984
|
}
|
|
7557
7985
|
/**
|
|
@@ -7686,7 +8114,8 @@ var ReplSession = class {
|
|
|
7686
8114
|
async start() {
|
|
7687
8115
|
this._state = "idle";
|
|
7688
8116
|
this.updateStatsState();
|
|
7689
|
-
this.
|
|
8117
|
+
setLocale(this.config.locale ?? "zh-CN");
|
|
8118
|
+
this.outputArea.append([t("session.welcome"), ""]);
|
|
7690
8119
|
this.tui.start();
|
|
7691
8120
|
}
|
|
7692
8121
|
/** 优雅关闭会话 */
|
|
@@ -7696,6 +8125,7 @@ var ReplSession = class {
|
|
|
7696
8125
|
this.updateStatsState();
|
|
7697
8126
|
log.info("REPL 关闭", { reason: reason ?? "未知" });
|
|
7698
8127
|
this.cancelCurrentTask();
|
|
8128
|
+
this.editor.setExecuting(false);
|
|
7699
8129
|
eventBus.emit("system:shutdown", { reason });
|
|
7700
8130
|
if (this.cronScheduler) {
|
|
7701
8131
|
this.cronScheduler.stop();
|
|
@@ -7706,6 +8136,7 @@ var ReplSession = class {
|
|
|
7706
8136
|
this.mcpManager = null;
|
|
7707
8137
|
}
|
|
7708
8138
|
this.tui.stop();
|
|
8139
|
+
process.exit(0);
|
|
7709
8140
|
}
|
|
7710
8141
|
/** 获取渲染器引用 */
|
|
7711
8142
|
getRenderer() {
|
|
@@ -7856,8 +8287,8 @@ var ReplSession = class {
|
|
|
7856
8287
|
clearInterval(spinnerInterval);
|
|
7857
8288
|
if (outputText) this.outputArea.replaceLastLine(responseStyle(ZAPMYCO_PREFIX + outputText));
|
|
7858
8289
|
else if (taskResult.status !== "success") {
|
|
7859
|
-
const errorMsg = taskResult.error?.message ?? "
|
|
7860
|
-
this.outputArea.replaceLastLine(chalk.red(`ZapMyco:
|
|
8290
|
+
const errorMsg = taskResult.error?.message ?? t("session.agentErrorMessage");
|
|
8291
|
+
this.outputArea.replaceLastLine(chalk.red(`ZapMyco: ${t("session.errorPrefix")} ${errorMsg}`));
|
|
7861
8292
|
const helpLines = getApiKeyErrorHelp(errorMsg);
|
|
7862
8293
|
if (helpLines.length > 0) {
|
|
7863
8294
|
this.outputArea.append(helpLines);
|
|
@@ -7893,11 +8324,11 @@ var ReplSession = class {
|
|
|
7893
8324
|
this.outputArea.append([""]);
|
|
7894
8325
|
}
|
|
7895
8326
|
}
|
|
7896
|
-
} else this.outputArea.replaceLastLine(chalk.red(
|
|
8327
|
+
} else this.outputArea.replaceLastLine(chalk.red(`ZapMyco: ${t("session.errorPrefix")} ${t("session.noContentError")}`));
|
|
7897
8328
|
}
|
|
7898
8329
|
if (taskResult.status !== "success") {
|
|
7899
|
-
const errorMsg = taskResult.error?.message ?? "
|
|
7900
|
-
if (!spinnerActive || outputText) this.outputArea.appendText(
|
|
8330
|
+
const errorMsg = taskResult.error?.message ?? t("session.agentErrorMessage");
|
|
8331
|
+
if (!spinnerActive || outputText) this.outputArea.appendText(`${t("session.errorPrefix")} ${errorMsg}`);
|
|
7901
8332
|
log.error("Agent 执行返回 failure", {
|
|
7902
8333
|
taskId,
|
|
7903
8334
|
error: taskResult.error,
|
|
@@ -7951,7 +8382,7 @@ var ReplSession = class {
|
|
|
7951
8382
|
goalId: `goal-${startTime}`,
|
|
7952
8383
|
error: err
|
|
7953
8384
|
});
|
|
7954
|
-
this.outputArea.replaceLastLine(responseStyle(`${ZAPMYCO_PREFIX}
|
|
8385
|
+
this.outputArea.replaceLastLine(responseStyle(`${ZAPMYCO_PREFIX}${t("session.errorPrefix")} ${err.message}`));
|
|
7955
8386
|
const helpLines = getApiKeyErrorHelp(err.message);
|
|
7956
8387
|
if (helpLines.length > 0) {
|
|
7957
8388
|
this.outputArea.append(helpLines);
|
|
@@ -8083,7 +8514,7 @@ var ReplSession = class {
|
|
|
8083
8514
|
createReplAgent() {
|
|
8084
8515
|
const agent = createLlmBasedAgent({
|
|
8085
8516
|
agentId: "repl-chat-agent",
|
|
8086
|
-
displayName: "
|
|
8517
|
+
displayName: t("session.displayName"),
|
|
8087
8518
|
capabilities: [{
|
|
8088
8519
|
id: "chat",
|
|
8089
8520
|
name: "对话",
|
|
@@ -8200,6 +8631,8 @@ var ReplSession = class {
|
|
|
8200
8631
|
}
|
|
8201
8632
|
ctrlCPressCount++;
|
|
8202
8633
|
if (ctrlCPressCount >= 2) {
|
|
8634
|
+
clearTimeout(ctrlCTimer);
|
|
8635
|
+
ctrlCTimer = void 0;
|
|
8203
8636
|
this.shutdown("用户连续按下 Ctrl+C");
|
|
8204
8637
|
return;
|
|
8205
8638
|
}
|
|
@@ -8265,7 +8698,7 @@ var ReplSession = class {
|
|
|
8265
8698
|
const err = result.error;
|
|
8266
8699
|
if (err.code === "ENOENT") this.outputArea.append([
|
|
8267
8700
|
"",
|
|
8268
|
-
|
|
8701
|
+
t("session.editorNotFound", { cmd: editorCmd }),
|
|
8269
8702
|
""
|
|
8270
8703
|
]);
|
|
8271
8704
|
else this.outputArea.append([
|
|
@@ -8278,7 +8711,7 @@ var ReplSession = class {
|
|
|
8278
8711
|
const message = err instanceof Error ? err.message : String(err);
|
|
8279
8712
|
this.outputArea.append([
|
|
8280
8713
|
"",
|
|
8281
|
-
|
|
8714
|
+
t("session.editorFailed", { message }),
|
|
8282
8715
|
""
|
|
8283
8716
|
]);
|
|
8284
8717
|
} finally {
|
|
@@ -8348,7 +8781,7 @@ async function startRepl() {
|
|
|
8348
8781
|
* zapmyco version 显示版本号
|
|
8349
8782
|
*/
|
|
8350
8783
|
const program = new Command();
|
|
8351
|
-
program.name(APP_NAME).description("AI 原生并行任务编排系统 -- AI 总管").version(
|
|
8784
|
+
program.name(APP_NAME).description("AI 原生并行任务编排系统 -- AI 总管").version(VERSION, "-v, --version", "显示版本号").helpOption("-h, --help", "显示帮助信息");
|
|
8352
8785
|
program.action(async () => {
|
|
8353
8786
|
try {
|
|
8354
8787
|
await startRepl();
|