coding-tool-x 3.7.0 → 3.7.2

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 (79) hide show
  1. package/README.md +10 -11
  2. package/dist/web/assets/{Analytics-Dma_j2Rq.js → Analytics-D5kLOhUo.js} +1 -1
  3. package/dist/web/assets/{ConfigTemplates-C49Y1PLH.js → ConfigTemplates-D_-16blp.js} +1 -1
  4. package/dist/web/assets/Home-DM_56Fyr.js +1 -0
  5. package/dist/web/assets/Home-Jom_ZcdY.css +1 -0
  6. package/dist/web/assets/{PluginManager-B1ECTHyY.js → PluginManager-Cv_rv8Dh.js} +1 -1
  7. package/dist/web/assets/{ProjectList-B_L55-l9.css → ProjectList-D3a0oRum.css} +1 -1
  8. package/dist/web/assets/ProjectList-H_m4Tx4E.js +1 -0
  9. package/dist/web/assets/{SessionList-CH5GwwiJ.js → SessionList-DcUQvsbR.js} +1 -1
  10. package/dist/web/assets/{SkillManager-CRyVhjYQ.js → SkillManager-CRav3m2a.js} +1 -1
  11. package/dist/web/assets/{WorkspaceManager-CO9tclVt.js → WorkspaceManager-B3f8R4EF.js} +1 -1
  12. package/dist/web/assets/index-Bnni1zPN.js +2 -0
  13. package/dist/web/assets/index-CfMuHG8u.css +1 -0
  14. package/dist/web/index.html +2 -2
  15. package/package.json +2 -1
  16. package/src/commands/channels.js +8 -8
  17. package/src/commands/daemon.js +4 -4
  18. package/src/commands/doctor.js +1 -1
  19. package/src/commands/logs.js +1 -3
  20. package/src/commands/port-config.js +4 -4
  21. package/src/commands/proxy-control.js +13 -13
  22. package/src/commands/stats.js +6 -6
  23. package/src/commands/toggle-proxy.js +8 -8
  24. package/src/commands/ui.js +1 -0
  25. package/src/config/default.js +3 -3
  26. package/src/config/paths.js +46 -49
  27. package/src/index.js +7 -7
  28. package/src/server/api/commands.js +1 -1
  29. package/src/server/api/config-export.js +2 -2
  30. package/src/server/api/config-registry.js +1 -1
  31. package/src/server/api/config.js +1 -1
  32. package/src/server/api/dashboard.js +16 -16
  33. package/src/server/api/mcp.js +2 -2
  34. package/src/server/api/oauth-credentials.js +15 -2
  35. package/src/server/api/{pi-channels.js → omp-channels.js} +115 -53
  36. package/src/server/api/{pi-config.js → omp-config.js} +13 -13
  37. package/src/server/api/{pi-projects.js → omp-projects.js} +5 -5
  38. package/src/server/api/{pi-proxy.js → omp-proxy.js} +18 -18
  39. package/src/server/api/{pi-sessions.js → omp-sessions.js} +21 -21
  40. package/src/server/api/{pi-statistics.js → omp-statistics.js} +1 -1
  41. package/src/server/api/plugins.js +1 -1
  42. package/src/server/api/skills.js +1 -1
  43. package/src/server/api/workspaces.js +1 -1
  44. package/src/server/index.js +23 -15
  45. package/src/server/{pi-proxy-server.js → omp-proxy-server.js} +13 -13
  46. package/src/server/services/channel-balance.js +3 -3
  47. package/src/server/services/channel-scheduler.js +4 -4
  48. package/src/server/services/commands-service.js +5 -5
  49. package/src/server/services/config-export-service.js +53 -53
  50. package/src/server/services/config-registry-service.js +8 -8
  51. package/src/server/services/config-sync-manager.js +26 -26
  52. package/src/server/services/config-templates-service.js +28 -28
  53. package/src/server/services/mcp-service.js +20 -20
  54. package/src/server/services/model-detector.js +15 -2
  55. package/src/server/services/native-oauth-adapters.js +212 -1
  56. package/src/server/services/network-access.js +5 -0
  57. package/src/server/services/notification-hooks.js +138 -6
  58. package/src/server/services/oauth-credentials-service.js +110 -3
  59. package/src/server/services/{pi-auth-providers.js → omp-auth-providers.js} +2 -2
  60. package/src/server/services/{pi-channels.js → omp-channels.js} +10 -5
  61. package/src/server/services/{pi-config.js → omp-config.js} +47 -65
  62. package/src/server/services/{pi-sessions.js → omp-sessions.js} +20 -20
  63. package/src/server/services/{pi-settings-manager.js → omp-settings-manager.js} +422 -18
  64. package/src/server/services/{pi-statistics-service.js → omp-statistics-service.js} +2 -2
  65. package/src/server/services/plugins-service.js +122 -122
  66. package/src/server/services/prompts-service.js +20 -20
  67. package/src/server/services/proxy-log-helper.js +1 -1
  68. package/src/server/services/proxy-runtime.js +1 -1
  69. package/src/server/services/skill-service.js +7 -7
  70. package/src/server/services/speed-test.js +29 -29
  71. package/src/server/services/ui-config.js +3 -3
  72. package/src/server/services/workspace-service.js +8 -8
  73. package/src/server/websocket-server.js +4 -4
  74. package/src/shared/platforms.js +201 -0
  75. package/dist/web/assets/Home-DGGC8H4g.js +0 -1
  76. package/dist/web/assets/Home-ewgeIhF7.css +0 -1
  77. package/dist/web/assets/ProjectList-DyiGyT-H.js +0 -1
  78. package/dist/web/assets/index-CM26UrnJ.css +0 -1
  79. package/dist/web/assets/index-EQq56pRa.js +0 -2
@@ -30,7 +30,7 @@ const CLAUDE_CODE_DIR = NATIVE_PATHS.claude.dir || path.dirname(NATIVE_PATHS.cla
30
30
  const CODEX_DIR = path.join(HOME, '.codex');
31
31
  const GEMINI_DIR = path.join(HOME, '.gemini');
32
32
  const OPENCODE_DIR = NATIVE_PATHS.opencode.config;
33
- const PI_AGENT_DIR = NATIVE_PATHS.pi.dir;
33
+ const OMP_AGENT_DIR = NATIVE_PATHS.omp.dir;
34
34
  const CODEX_CONFIG_PATH = NATIVE_PATHS.codex.config;
35
35
 
36
36
  // Config type definitions
@@ -47,8 +47,8 @@ const CONFIG_TYPES = {
47
47
  opencodeTarget: 'skills',
48
48
  opencodeLegacyTarget: 'skill',
49
49
  opencodeSupported: true,
50
- piTarget: 'skills',
51
- piSupported: true
50
+ ompTarget: 'skills',
51
+ ompSupported: true
52
52
  },
53
53
  commands: {
54
54
  isDirectory: false,
@@ -63,8 +63,8 @@ const CONFIG_TYPES = {
63
63
  opencodeTarget: 'commands',
64
64
  opencodeLegacyTarget: 'command',
65
65
  opencodeSupported: true,
66
- piTarget: 'commands',
67
- piSupported: true
66
+ ompTarget: 'commands',
67
+ ompSupported: true
68
68
  },
69
69
  agents: {
70
70
  isDirectory: false,
@@ -76,7 +76,7 @@ const CONFIG_TYPES = {
76
76
  opencodeTarget: 'agents',
77
77
  opencodeLegacyTarget: 'agent',
78
78
  opencodeSupported: true,
79
- piSupported: false
79
+ ompSupported: false
80
80
  },
81
81
  plugins: {
82
82
  isDirectory: true,
@@ -86,8 +86,8 @@ const CONFIG_TYPES = {
86
86
  opencodeTarget: 'plugins',
87
87
  opencodeLegacyTarget: 'plugin',
88
88
  opencodeSupported: true,
89
- piTarget: 'extensions',
90
- piSupported: true
89
+ ompTarget: 'extensions',
90
+ ompSupported: true
91
91
  }
92
92
  };
93
93
 
@@ -99,7 +99,7 @@ class ConfigSyncManager {
99
99
  this.codexDir = CODEX_DIR;
100
100
  this.geminiDir = GEMINI_DIR;
101
101
  this.opencodeDir = OPENCODE_DIR;
102
- this.piDir = PI_AGENT_DIR;
102
+ this.ompDir = OMP_AGENT_DIR;
103
103
  this.configTypes = CONFIG_TYPES;
104
104
  }
105
105
 
@@ -588,13 +588,13 @@ class ConfigSyncManager {
588
588
  * Sync a config item to OMP.
589
589
  * OMP treats commands as slash-command files and plugins as extensions/packages.
590
590
  */
591
- syncToPi(type, name) {
591
+ syncToOmp(type, name) {
592
592
  const config = this.configTypes[type];
593
593
  if (!config) {
594
594
  return { success: false, error: `Unknown config type: ${type}` };
595
595
  }
596
596
 
597
- if (!config.piSupported) {
597
+ if (!config.ompSupported) {
598
598
  console.log(`[ConfigSyncManager] ${type} not supported natively by OMP, skipping`);
599
599
  return { success: true, skipped: true, reason: 'Not supported natively by OMP' };
600
600
  }
@@ -610,7 +610,7 @@ class ConfigSyncManager {
610
610
  return { success: false, error: 'Source not found' };
611
611
  }
612
612
 
613
- const targetPath = path.join(this.piDir, config.piTarget, safeName);
613
+ const targetPath = path.join(this.ompDir, config.ompTarget, safeName);
614
614
  try {
615
615
  if (config.isDirectory) {
616
616
  this._ensureDir(path.dirname(targetPath));
@@ -629,7 +629,7 @@ class ConfigSyncManager {
629
629
  }
630
630
  }
631
631
 
632
- removeFromPi(type, name) {
632
+ removeFromOmp(type, name) {
633
633
  const config = this.configTypes[type];
634
634
  if (!config) {
635
635
  return { success: false, error: `Unknown config type: ${type}` };
@@ -640,11 +640,11 @@ class ConfigSyncManager {
640
640
  return { success: false, error: 'Invalid config item name' };
641
641
  }
642
642
 
643
- if (!config.piSupported) {
643
+ if (!config.ompSupported) {
644
644
  return { success: true, skipped: true, reason: 'Not supported natively by OMP' };
645
645
  }
646
646
 
647
- const targetPath = path.join(this.piDir, config.piTarget, safeName);
647
+ const targetPath = path.join(this.ompDir, config.ompTarget, safeName);
648
648
  if (!fs.existsSync(targetPath)) {
649
649
  return { success: true, message: 'Already removed' };
650
650
  }
@@ -654,7 +654,7 @@ class ConfigSyncManager {
654
654
  this._removeRecursive(targetPath);
655
655
  } else {
656
656
  fs.unlinkSync(targetPath);
657
- this._cleanupEmptyParents(path.dirname(targetPath), path.join(this.piDir, config.piTarget));
657
+ this._cleanupEmptyParents(path.dirname(targetPath), path.join(this.ompDir, config.ompTarget));
658
658
  }
659
659
  console.log(`[ConfigSyncManager] Removed ${type}/${name} from OMP`);
660
660
  return { success: true };
@@ -667,7 +667,7 @@ class ConfigSyncManager {
667
667
  /**
668
668
  * Batch sync based on registry data
669
669
  * @param {string} type - Config type
670
- * @param {Object} registryItems - Registry items { name: { enabled, platforms: { claude, codex, gemini, opencode, pi } } }
670
+ * @param {Object} registryItems - Registry items { name: { enabled, platforms: { claude, codex, gemini, opencode, omp } } }
671
671
  * @returns {Object} Results summary
672
672
  */
673
673
  syncAll(type, registryItems) {
@@ -753,17 +753,17 @@ class ConfigSyncManager {
753
753
  }
754
754
  }
755
755
 
756
- if (platforms.pi) {
757
- const result = this.syncToPi(type, name);
756
+ if (platforms.omp) {
757
+ const result = this.syncToOmp(type, name);
758
758
  if (result.success && !result.skipped) {
759
- results.synced.push({ type, name, platform: 'pi' });
759
+ results.synced.push({ type, name, platform: 'omp' });
760
760
  } else if (!result.success) {
761
- results.errors.push({ type, name, platform: 'pi', error: result.error });
761
+ results.errors.push({ type, name, platform: 'omp', error: result.error });
762
762
  }
763
763
  } else {
764
- const result = this.removeFromPi(type, name);
764
+ const result = this.removeFromOmp(type, name);
765
765
  if (result.success && !result.message && !result.skipped) {
766
- results.removed.push({ type, name, platform: 'pi' });
766
+ results.removed.push({ type, name, platform: 'omp' });
767
767
  }
768
768
  }
769
769
  } else {
@@ -788,9 +788,9 @@ class ConfigSyncManager {
788
788
  results.removed.push({ type, name, platform: 'opencode' });
789
789
  }
790
790
 
791
- const piResult = this.removeFromPi(type, name);
792
- if (piResult.success && !piResult.message && !piResult.skipped) {
793
- results.removed.push({ type, name, platform: 'pi' });
791
+ const ompResult = this.removeFromOmp(type, name);
792
+ if (ompResult.success && !ompResult.message && !ompResult.skipped) {
793
+ results.removed.push({ type, name, platform: 'omp' });
794
794
  }
795
795
  }
796
796
  }
@@ -25,7 +25,7 @@ const AI_CONFIG_MAP = {
25
25
  codex: { fileName: 'AGENTS.md', name: 'Codex' },
26
26
  gemini: { fileName: 'GEMINI.md', name: 'Gemini' },
27
27
  opencode: { fileName: '.opencode/AGENTS.md', name: 'OpenCode' },
28
- pi: { fileName: null, name: 'OMP command templates' }
28
+ omp: { fileName: null, name: 'OMP command templates' }
29
29
  };
30
30
 
31
31
  const CLI_DEFAULT_AI_TYPE = {
@@ -33,7 +33,7 @@ const CLI_DEFAULT_AI_TYPE = {
33
33
  codex: 'codex',
34
34
  gemini: 'gemini',
35
35
  opencode: 'opencode',
36
- pi: 'pi'
36
+ omp: 'omp'
37
37
  };
38
38
 
39
39
  /**
@@ -115,7 +115,7 @@ function normalizeAiConfigs(aiConfigs = {}, claudeMd = null) {
115
115
  codex: { enabled: false, content: '' },
116
116
  gemini: { enabled: false, content: '' },
117
117
  opencode: { enabled: false, content: '' },
118
- pi: { enabled: false, content: '' }
118
+ omp: { enabled: false, content: '' }
119
119
  };
120
120
 
121
121
  for (const key of Object.keys(normalized)) {
@@ -374,7 +374,7 @@ function readCurrentConfig(targetDir) {
374
374
  */
375
375
  function getAvailableConfigs() {
376
376
  const agentPlatforms = ['claude', 'codex', 'gemini', 'opencode'];
377
- const commandPlatforms = ['claude', 'codex', 'gemini', 'opencode', 'pi'];
377
+ const commandPlatforms = ['claude', 'codex', 'gemini', 'opencode', 'omp'];
378
378
  const agentMap = new Map();
379
379
  const commandMap = new Map();
380
380
  const agentsByPlatform = {};
@@ -428,7 +428,7 @@ function getAvailableConfigs() {
428
428
 
429
429
  // 按平台分别获取 skills(每个平台有独立的安装目录)
430
430
  const skillsByPlatform = {};
431
- for (const platform of ['claude', 'codex', 'gemini', 'opencode', 'pi']) {
431
+ for (const platform of ['claude', 'codex', 'gemini', 'opencode', 'omp']) {
432
432
  const service = new SkillService(platform);
433
433
  skillsByPlatform[platform] = service.getInstalledSkills().map(skill => ({
434
434
  directory: skill.directory,
@@ -537,14 +537,14 @@ function writeYamlFile(filePath, data) {
537
537
  }), 'utf-8');
538
538
  }
539
539
 
540
- function mergePiProjectPackages(targetDir, plugins = []) {
540
+ function mergeOmpProjectPackages(targetDir, plugins = []) {
541
541
  const packages = plugins.map(plugin => plugin.name).filter(Boolean);
542
542
  if (packages.length === 0) {
543
543
  return false;
544
544
  }
545
545
 
546
- const piDir = path.join(targetDir, '.omp');
547
- const settingsPath = path.join(piDir, 'config.yml');
546
+ const ompDir = path.join(targetDir, '.omp');
547
+ const settingsPath = path.join(ompDir, 'config.yml');
548
548
  let settings = {};
549
549
  if (fs.existsSync(settingsPath)) {
550
550
  try {
@@ -629,7 +629,7 @@ function convertToOmpMcpSpec(spec = {}) {
629
629
  * @param {string} targetDir - 目标项目目录
630
630
  * @param {string} templateId - 模板 ID
631
631
  * @param {object} options - 可选配置
632
- * @param {string|string[]} options.aiConfigTypes - 选择的 AI 配置类型数组: ['claude', 'codex', 'gemini', 'opencode', 'pi']
632
+ * @param {string|string[]} options.aiConfigTypes - 选择的 AI 配置类型数组: ['claude', 'codex', 'gemini', 'opencode', 'omp']
633
633
  * @param {string} options.aiConfigType - (兼容旧版) 单个 AI 配置类型
634
634
  */
635
635
  function applyTemplateToProject(targetDir, templateId, options = {}) {
@@ -697,7 +697,7 @@ function applyTemplateToProject(targetDir, templateId, options = {}) {
697
697
  if (aiConfigTypes.includes('codex')) {
698
698
  pushSkipped(results.skipped, 'agent', fileName, 'Codex agents 仅支持用户级配置,项目目录应用时已跳过');
699
699
  }
700
- if (aiConfigTypes.includes('pi')) {
700
+ if (aiConfigTypes.includes('omp')) {
701
701
  pushSkipped(results.skipped, 'agent', fileName, 'OMP agents 需通过扩展或包提供,项目目录应用时已跳过');
702
702
  }
703
703
  if (written) {
@@ -720,8 +720,8 @@ function applyTemplateToProject(targetDir, templateId, options = {}) {
720
720
  if (aiConfigTypes.includes('gemini')) {
721
721
  commandTargets.push({ baseDir: path.join(targetDir, '.gemini', 'commands'), prefix: '.gemini/commands', format: 'gemini' });
722
722
  }
723
- if (aiConfigTypes.includes('pi')) {
724
- commandTargets.push({ baseDir: path.join(targetDir, '.omp', 'commands'), prefix: '.omp/commands', format: 'pi' });
723
+ if (aiConfigTypes.includes('omp')) {
724
+ commandTargets.push({ baseDir: path.join(targetDir, '.omp', 'commands'), prefix: '.omp/commands', format: 'omp' });
725
725
  }
726
726
 
727
727
  for (const target of commandTargets) {
@@ -758,7 +758,7 @@ function applyTemplateToProject(targetDir, templateId, options = {}) {
758
758
 
759
759
  if (template.plugins?.length > 0) {
760
760
  results.plugins.items = template.plugins.map(p => p.name);
761
- if (aiConfigTypes.includes('opencode') || aiConfigTypes.includes('pi')) {
761
+ if (aiConfigTypes.includes('opencode') || aiConfigTypes.includes('omp')) {
762
762
  results.plugins.applied = template.plugins.length;
763
763
  } else {
764
764
  for (const plugin of template.plugins) {
@@ -768,11 +768,11 @@ function applyTemplateToProject(targetDir, templateId, options = {}) {
768
768
  }
769
769
 
770
770
  const hasMcp = template.mcpServers?.length > 0;
771
- const writesGenericMcpConfig = hasMcp && aiConfigTypes.some(type => type !== 'pi');
772
- const writesOmpMcpConfig = hasMcp && aiConfigTypes.includes('pi');
771
+ const writesGenericMcpConfig = hasMcp && aiConfigTypes.some(type => type !== 'omp');
772
+ const writesOmpMcpConfig = hasMcp && aiConfigTypes.includes('omp');
773
773
  const hasPluginsForOpenCode = aiConfigTypes.includes('opencode') && template.plugins?.length > 0;
774
- const hasPluginsForPi = aiConfigTypes.includes('pi') && template.plugins?.length > 0;
775
- if (hasMcp || hasPluginsForOpenCode || hasPluginsForPi) {
774
+ const hasPluginsForOmp = aiConfigTypes.includes('omp') && template.plugins?.length > 0;
775
+ if (hasMcp || hasPluginsForOpenCode || hasPluginsForOmp) {
776
776
  const mcpConfig = { mcpServers: {} };
777
777
  const ompMcpConfig = { mcpServers: {} };
778
778
  const opencodeConfig = { mcp: {}, plugin: [] };
@@ -825,8 +825,8 @@ function applyTemplateToProject(targetDir, templateId, options = {}) {
825
825
  writeJsonFile(opencodePath, opencodeConfig);
826
826
  }
827
827
 
828
- if (hasPluginsForPi) {
829
- mergePiProjectPackages(targetDir, template.plugins || []);
828
+ if (hasPluginsForOmp) {
829
+ mergeOmpProjectPackages(targetDir, template.plugins || []);
830
830
  }
831
831
  }
832
832
 
@@ -858,7 +858,7 @@ function applyTemplateToProject(targetDir, templateId, options = {}) {
858
858
  * @param {string} targetDir - 目标项目目录
859
859
  * @param {string} templateId - 模板 ID
860
860
  * @param {object} options - 可选配置
861
- * @param {string|string[]} options.aiConfigTypes - 选择的 AI 配置类型数组: ['claude', 'codex', 'gemini', 'opencode', 'pi']
861
+ * @param {string|string[]} options.aiConfigTypes - 选择的 AI 配置类型数组: ['claude', 'codex', 'gemini', 'opencode', 'omp']
862
862
  * @param {string} options.aiConfigType - (兼容旧版) 单个 AI 配置类型
863
863
  */
864
864
  function previewTemplateApplication(targetDir, templateId, options = {}) {
@@ -930,7 +930,7 @@ function previewTemplateApplication(targetDir, templateId, options = {}) {
930
930
  if (aiConfigTypes.includes('codex')) {
931
931
  pushSkipped(preview.skipped, 'agent', fileName, 'Codex agents 仅支持用户级配置,项目目录预览时已跳过');
932
932
  }
933
- if (aiConfigTypes.includes('pi')) {
933
+ if (aiConfigTypes.includes('omp')) {
934
934
  pushSkipped(preview.skipped, 'agent', fileName, 'OMP agents 需通过扩展或包提供,项目目录预览时已跳过');
935
935
  }
936
936
  if (applicable) {
@@ -945,7 +945,7 @@ function previewTemplateApplication(targetDir, templateId, options = {}) {
945
945
  if (aiConfigTypes.includes('codex')) commandPrefixes.push('.codex/prompts');
946
946
  if (aiConfigTypes.includes('opencode')) commandPrefixes.push('.opencode/commands');
947
947
  if (aiConfigTypes.includes('gemini')) commandPrefixes.push('.gemini/commands');
948
- if (aiConfigTypes.includes('pi')) commandPrefixes.push('.omp/commands');
948
+ if (aiConfigTypes.includes('omp')) commandPrefixes.push('.omp/commands');
949
949
 
950
950
  for (const command of template.commands) {
951
951
  const commandName = resolveItemName(command.name, null, 'command');
@@ -969,8 +969,8 @@ function previewTemplateApplication(targetDir, templateId, options = {}) {
969
969
  }
970
970
  }
971
971
 
972
- const writesGenericMcpConfig = template.mcpServers?.length > 0 && aiConfigTypes.some(type => type !== 'pi');
973
- const writesOmpMcpConfig = template.mcpServers?.length > 0 && aiConfigTypes.includes('pi');
972
+ const writesGenericMcpConfig = template.mcpServers?.length > 0 && aiConfigTypes.some(type => type !== 'omp');
973
+ const writesOmpMcpConfig = template.mcpServers?.length > 0 && aiConfigTypes.includes('omp');
974
974
  const allServers = mcpService.getAllServers();
975
975
  const presets = mcpService.getPresets();
976
976
  let resolvableMcpCount = 0;
@@ -1021,11 +1021,11 @@ function previewTemplateApplication(targetDir, templateId, options = {}) {
1021
1021
  }
1022
1022
 
1023
1023
  if (template.plugins?.length > 0) {
1024
- if (aiConfigTypes.includes('opencode') || aiConfigTypes.includes('pi')) {
1024
+ if (aiConfigTypes.includes('opencode') || aiConfigTypes.includes('omp')) {
1025
1025
  preview.summary.plugins = template.plugins.length;
1026
- if (aiConfigTypes.includes('pi')) {
1027
- const piSettingsPath = path.join(targetDir, '.omp/config.yml');
1028
- if (fs.existsSync(piSettingsPath)) {
1026
+ if (aiConfigTypes.includes('omp')) {
1027
+ const ompSettingsPath = path.join(targetDir, '.omp/config.yml');
1028
+ if (fs.existsSync(ompSettingsPath)) {
1029
1029
  preview.willOverwrite.push('.omp/config.yml');
1030
1030
  } else {
1031
1031
  preview.willCreate.push('.omp/config.yml');
@@ -28,8 +28,8 @@ const OPENCODE_CONFIG_PATHS = {
28
28
  json: path.join(OPENCODE_CONFIG_DIR, 'opencode.json'),
29
29
  legacy: path.join(OPENCODE_CONFIG_DIR, 'config.json')
30
30
  };
31
- const PI_MCP_CONFIG_PATH = NATIVE_PATHS.pi?.mcp
32
- || path.join(NATIVE_PATHS.pi?.dir || path.join(HOME_DIR, '.omp', 'agent'), 'mcp.json');
31
+ const OMP_MCP_CONFIG_PATH = NATIVE_PATHS.omp?.mcp
32
+ || path.join(NATIVE_PATHS.omp?.dir || path.join(HOME_DIR, '.omp', 'agent'), 'mcp.json');
33
33
 
34
34
  // MCP 客户端连接池
35
35
  // serverId -> { client, timestamp }
@@ -38,8 +38,8 @@ const POOL_TTL = 5 * 60 * 1000; // 5 minutes
38
38
  const STREAMABLE_HTTP_TYPE = 'streamable_http';
39
39
  const MCP_SERVER_TYPES = ['stdio', STREAMABLE_HTTP_TYPE, 'sse'];
40
40
  const REMOTE_MCP_SERVER_TYPES = [STREAMABLE_HTTP_TYPE, 'sse'];
41
- const MCP_PLATFORM_KEYS = ['claude', 'codex', 'gemini', 'opencode', 'pi'];
42
- const OMP_MCP_SCHEMA_URL = 'https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/config/mcp-schema.json';
41
+ const MCP_PLATFORM_KEYS = ['claude', 'codex', 'gemini', 'opencode', 'omp'];
42
+ const OMP_MCP_SCHEMA_URL = 'https://raw.githubusercontent.com/can1357/oh-my-omp/main/packages/coding-agent/src/config/mcp-schema.json';
43
43
  const OMP_SERVER_NAME_PATTERN = /^[a-zA-Z0-9_.-]{1,100}$/;
44
44
 
45
45
  function normalizeServerSpec(spec = {}) {
@@ -538,7 +538,7 @@ const DEFAULT_SERVER_APPS = {
538
538
  codex: false,
539
539
  gemini: false,
540
540
  opencode: false,
541
- pi: false
541
+ omp: false
542
542
  };
543
543
 
544
544
  function normalizeServerApps(apps = {}, fallbackApps = DEFAULT_SERVER_APPS) {
@@ -547,7 +547,7 @@ function normalizeServerApps(apps = {}, fallbackApps = DEFAULT_SERVER_APPS) {
547
547
  codex: apps.codex !== undefined ? !!apps.codex : !!fallbackApps.codex,
548
548
  gemini: apps.gemini !== undefined ? !!apps.gemini : !!fallbackApps.gemini,
549
549
  opencode: apps.opencode !== undefined ? !!apps.opencode : !!fallbackApps.opencode,
550
- pi: apps.pi !== undefined ? !!apps.pi : !!fallbackApps.pi
550
+ omp: apps.omp !== undefined ? !!apps.omp: !!fallbackApps.omp
551
551
  };
552
552
  }
553
553
 
@@ -763,7 +763,7 @@ async function syncServerToPlatform(server, platform) {
763
763
  case 'opencode':
764
764
  syncToOpenCodeConfig(server);
765
765
  break;
766
- case 'pi':
766
+ case 'omp':
767
767
  syncToOmpMcpConfig(server);
768
768
  break;
769
769
  }
@@ -792,7 +792,7 @@ async function removeServerFromPlatform(serverId, platform) {
792
792
  case 'opencode':
793
793
  removeFromOpenCodeConfig(serverId);
794
794
  break;
795
- case 'pi':
795
+ case 'omp':
796
796
  removeFromOmpMcpConfig(serverId);
797
797
  break;
798
798
  }
@@ -954,7 +954,7 @@ function validateOmpServerName(serverId) {
954
954
  }
955
955
 
956
956
  function readOmpMcpConfig() {
957
- const config = readJsonFile(PI_MCP_CONFIG_PATH, { mcpServers: {} });
957
+ const config = readJsonFile(OMP_MCP_CONFIG_PATH, { mcpServers: {} });
958
958
  if (!config || typeof config !== 'object' || Array.isArray(config)) {
959
959
  return { mcpServers: {} };
960
960
  }
@@ -1059,14 +1059,14 @@ function syncToOmpMcpConfig(server) {
1059
1059
  validateOmpServerName(server.id);
1060
1060
  const config = readOmpMcpConfig();
1061
1061
  config.mcpServers[server.id] = convertToOmpMcpFormat(server.server);
1062
- writeJsonFile(PI_MCP_CONFIG_PATH, config);
1062
+ writeJsonFile(OMP_MCP_CONFIG_PATH, config);
1063
1063
  }
1064
1064
 
1065
1065
  function removeFromOmpMcpConfig(serverId) {
1066
1066
  const config = readOmpMcpConfig();
1067
1067
  if (config.mcpServers && config.mcpServers[serverId]) {
1068
1068
  delete config.mcpServers[serverId];
1069
- writeJsonFile(PI_MCP_CONFIG_PATH, config);
1069
+ writeJsonFile(OMP_MCP_CONFIG_PATH, config);
1070
1070
  }
1071
1071
  }
1072
1072
 
@@ -1231,7 +1231,7 @@ async function importFromPlatform(platform) {
1231
1231
  case 'opencode':
1232
1232
  importedCount = importFromOpenCode(servers);
1233
1233
  break;
1234
- case 'pi':
1234
+ case 'omp':
1235
1235
  importedCount = importFromOmp(servers);
1236
1236
  break;
1237
1237
  default:
@@ -1389,8 +1389,8 @@ function importFromOmp(servers) {
1389
1389
 
1390
1390
  if (servers[id]) {
1391
1391
  servers[id].apps = normalizeServerApps(servers[id].apps);
1392
- if (!servers[id].apps.pi) {
1393
- servers[id].apps.pi = true;
1392
+ if (!servers[id].apps.omp) {
1393
+ servers[id].apps.omp = true;
1394
1394
  count++;
1395
1395
  }
1396
1396
  } else {
@@ -1398,7 +1398,7 @@ function importFromOmp(servers) {
1398
1398
  id,
1399
1399
  name: id,
1400
1400
  server: convertedSpec,
1401
- apps: { claude: false, codex: false, gemini: false, opencode: false, pi: true },
1401
+ apps: { claude: false, codex: false, gemini: false, opencode: false, omp: true },
1402
1402
  createdAt: Date.now(),
1403
1403
  updatedAt: Date.now()
1404
1404
  };
@@ -1471,7 +1471,7 @@ function getStats() {
1471
1471
  codex: serverList.filter(s => s.apps?.codex).length,
1472
1472
  gemini: serverList.filter(s => s.apps?.gemini).length,
1473
1473
  opencode: serverList.filter(s => s.apps?.opencode).length,
1474
- pi: serverList.filter(s => s.apps?.pi).length
1474
+ omp: serverList.filter(s => s.apps?.omp).length
1475
1475
  };
1476
1476
  }
1477
1477
 
@@ -1923,7 +1923,7 @@ function updateServerOrder(serverIds) {
1923
1923
 
1924
1924
  /**
1925
1925
  * 导出所有 MCP 配置
1926
- * @param {string} format - 导出格式: 'json' | 'claude' | 'codex' | 'opencode' | 'gemini' | 'pi'
1926
+ * @param {string} format - 导出格式: 'json' | 'claude' | 'codex' | 'opencode' | 'gemini' | 'omp'
1927
1927
  */
1928
1928
  function exportServers(format = 'json') {
1929
1929
  const servers = getAllServers();
@@ -1937,7 +1937,7 @@ function exportServers(format = 'json') {
1937
1937
  return exportForOpenCode(servers);
1938
1938
  case 'gemini':
1939
1939
  return exportForGemini(servers);
1940
- case 'pi':
1940
+ case 'omp':
1941
1941
  return exportForOmp(servers);
1942
1942
  case 'json':
1943
1943
  default:
@@ -2045,14 +2045,14 @@ function exportForOmp(servers) {
2045
2045
  const mcpServers = {};
2046
2046
 
2047
2047
  for (const [id, server] of Object.entries(servers)) {
2048
- if (server.apps?.pi) {
2048
+ if (server.apps?.omp) {
2049
2049
  validateOmpServerName(id);
2050
2050
  mcpServers[id] = convertToOmpMcpFormat(server.server);
2051
2051
  }
2052
2052
  }
2053
2053
 
2054
2054
  return {
2055
- format: 'pi',
2055
+ format: 'omp',
2056
2056
  content: JSON.stringify({ $schema: OMP_MCP_SCHEMA_URL, mcpServers }, null, 2),
2057
2057
  filename: 'omp-mcp-config.json'
2058
2058
  };
@@ -95,6 +95,13 @@ function getModelPriority(channelType, options = {}) {
95
95
  console.warn(`[ModelDetector] Failed to load default models config: ${error.message}`);
96
96
  }
97
97
 
98
+ for (const toolType of candidateTypes) {
99
+ const models = MODEL_PRIORITY[toolType];
100
+ if (Array.isArray(models) && models.length > 0) {
101
+ return normalizeModelCandidates(models);
102
+ }
103
+ }
104
+
98
105
  return [];
99
106
  }
100
107
 
@@ -779,6 +786,12 @@ function buildChannelCacheSignature(channel, payload = {}) {
779
786
  return crypto.createHash('sha1').update(raw).digest('hex');
780
787
  }
781
788
 
789
+ function getChannelCacheKey(channel, signature) {
790
+ const id = String(channel?.id || '').trim();
791
+ if (id) return id;
792
+ return `temporary:${signature}`;
793
+ }
794
+
782
795
  function isSignatureCacheValid(cacheEntry, signatureKey, expectedSignature) {
783
796
  if (!cacheEntry || !signatureKey || !expectedSignature) return false;
784
797
  return cacheEntry[signatureKey] === expectedSignature;
@@ -846,7 +859,6 @@ async function probeModelAvailability(channel, channelType, options = {}) {
846
859
  const toolType = options.toolType;
847
860
  const stopOnFirstAvailable = !!options.stopOnFirstAvailable;
848
861
  const cache = loadModelCache();
849
- const cacheKey = channel.id;
850
862
  const preferredModels = normalizeModelCandidates(options.preferredModels);
851
863
  const probeSignature = buildChannelCacheSignature(channel, {
852
864
  type: 'probe',
@@ -855,6 +867,7 @@ async function probeModelAvailability(channel, channelType, options = {}) {
855
867
  stopOnFirstAvailable,
856
868
  preferredModels
857
869
  });
870
+ const cacheKey = getChannelCacheKey(channel, probeSignature);
858
871
 
859
872
  // Return cached result if channel and probe options are unchanged
860
873
  if (!forceRefresh && isSignatureCacheValid(cache[cacheKey], 'probeSignature', probeSignature)) {
@@ -1007,11 +1020,11 @@ async function fetchModelsFromProvider(channel, channelType, options = {}) {
1007
1020
  }
1008
1021
 
1009
1022
  const cache = loadModelCache();
1010
- const cacheKey = channel.id;
1011
1023
  const listSignature = buildChannelCacheSignature(channel, {
1012
1024
  type: 'model-list',
1013
1025
  channelType: String(channelType || '').trim().toLowerCase()
1014
1026
  });
1027
+ const cacheKey = getChannelCacheKey(channel, listSignature);
1015
1028
 
1016
1029
  // Check cache first, and only reuse when channel/list context is unchanged
1017
1030
  if (!forceRefresh