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.
- package/README.md +10 -11
- package/dist/web/assets/{Analytics-Dma_j2Rq.js → Analytics-D5kLOhUo.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-C49Y1PLH.js → ConfigTemplates-D_-16blp.js} +1 -1
- package/dist/web/assets/Home-DM_56Fyr.js +1 -0
- package/dist/web/assets/Home-Jom_ZcdY.css +1 -0
- package/dist/web/assets/{PluginManager-B1ECTHyY.js → PluginManager-Cv_rv8Dh.js} +1 -1
- package/dist/web/assets/{ProjectList-B_L55-l9.css → ProjectList-D3a0oRum.css} +1 -1
- package/dist/web/assets/ProjectList-H_m4Tx4E.js +1 -0
- package/dist/web/assets/{SessionList-CH5GwwiJ.js → SessionList-DcUQvsbR.js} +1 -1
- package/dist/web/assets/{SkillManager-CRyVhjYQ.js → SkillManager-CRav3m2a.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-CO9tclVt.js → WorkspaceManager-B3f8R4EF.js} +1 -1
- package/dist/web/assets/index-Bnni1zPN.js +2 -0
- package/dist/web/assets/index-CfMuHG8u.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +2 -1
- package/src/commands/channels.js +8 -8
- package/src/commands/daemon.js +4 -4
- package/src/commands/doctor.js +1 -1
- package/src/commands/logs.js +1 -3
- package/src/commands/port-config.js +4 -4
- package/src/commands/proxy-control.js +13 -13
- package/src/commands/stats.js +6 -6
- package/src/commands/toggle-proxy.js +8 -8
- package/src/commands/ui.js +1 -0
- package/src/config/default.js +3 -3
- package/src/config/paths.js +46 -49
- package/src/index.js +7 -7
- package/src/server/api/commands.js +1 -1
- package/src/server/api/config-export.js +2 -2
- package/src/server/api/config-registry.js +1 -1
- package/src/server/api/config.js +1 -1
- package/src/server/api/dashboard.js +16 -16
- package/src/server/api/mcp.js +2 -2
- package/src/server/api/oauth-credentials.js +15 -2
- package/src/server/api/{pi-channels.js → omp-channels.js} +115 -53
- package/src/server/api/{pi-config.js → omp-config.js} +13 -13
- package/src/server/api/{pi-projects.js → omp-projects.js} +5 -5
- package/src/server/api/{pi-proxy.js → omp-proxy.js} +18 -18
- package/src/server/api/{pi-sessions.js → omp-sessions.js} +21 -21
- package/src/server/api/{pi-statistics.js → omp-statistics.js} +1 -1
- package/src/server/api/plugins.js +1 -1
- package/src/server/api/skills.js +1 -1
- package/src/server/api/workspaces.js +1 -1
- package/src/server/index.js +23 -15
- package/src/server/{pi-proxy-server.js → omp-proxy-server.js} +13 -13
- package/src/server/services/channel-balance.js +3 -3
- package/src/server/services/channel-scheduler.js +4 -4
- package/src/server/services/commands-service.js +5 -5
- package/src/server/services/config-export-service.js +53 -53
- package/src/server/services/config-registry-service.js +8 -8
- package/src/server/services/config-sync-manager.js +26 -26
- package/src/server/services/config-templates-service.js +28 -28
- package/src/server/services/mcp-service.js +20 -20
- package/src/server/services/model-detector.js +15 -2
- package/src/server/services/native-oauth-adapters.js +212 -1
- package/src/server/services/network-access.js +5 -0
- package/src/server/services/notification-hooks.js +138 -6
- package/src/server/services/oauth-credentials-service.js +110 -3
- package/src/server/services/{pi-auth-providers.js → omp-auth-providers.js} +2 -2
- package/src/server/services/{pi-channels.js → omp-channels.js} +10 -5
- package/src/server/services/{pi-config.js → omp-config.js} +47 -65
- package/src/server/services/{pi-sessions.js → omp-sessions.js} +20 -20
- package/src/server/services/{pi-settings-manager.js → omp-settings-manager.js} +422 -18
- package/src/server/services/{pi-statistics-service.js → omp-statistics-service.js} +2 -2
- package/src/server/services/plugins-service.js +122 -122
- package/src/server/services/prompts-service.js +20 -20
- package/src/server/services/proxy-log-helper.js +1 -1
- package/src/server/services/proxy-runtime.js +1 -1
- package/src/server/services/skill-service.js +7 -7
- package/src/server/services/speed-test.js +29 -29
- package/src/server/services/ui-config.js +3 -3
- package/src/server/services/workspace-service.js +8 -8
- package/src/server/websocket-server.js +4 -4
- package/src/shared/platforms.js +201 -0
- package/dist/web/assets/Home-DGGC8H4g.js +0 -1
- package/dist/web/assets/Home-ewgeIhF7.css +0 -1
- package/dist/web/assets/ProjectList-DyiGyT-H.js +0 -1
- package/dist/web/assets/index-CM26UrnJ.css +0 -1
- 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
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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
|
-
|
|
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
|
-
|
|
90
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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,
|
|
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.
|
|
757
|
-
const result = this.
|
|
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: '
|
|
759
|
+
results.synced.push({ type, name, platform: 'omp' });
|
|
760
760
|
} else if (!result.success) {
|
|
761
|
-
results.errors.push({ type, name, platform: '
|
|
761
|
+
results.errors.push({ type, name, platform: 'omp', error: result.error });
|
|
762
762
|
}
|
|
763
763
|
} else {
|
|
764
|
-
const result = this.
|
|
764
|
+
const result = this.removeFromOmp(type, name);
|
|
765
765
|
if (result.success && !result.message && !result.skipped) {
|
|
766
|
-
results.removed.push({ type, name, platform: '
|
|
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
|
|
792
|
-
if (
|
|
793
|
-
results.removed.push({ type, name, platform: '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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', '
|
|
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', '
|
|
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
|
|
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
|
|
547
|
-
const settingsPath = path.join(
|
|
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', '
|
|
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('
|
|
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('
|
|
724
|
-
commandTargets.push({ baseDir: path.join(targetDir, '.omp', 'commands'), prefix: '.omp/commands', format: '
|
|
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('
|
|
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 !== '
|
|
772
|
-
const writesOmpMcpConfig = hasMcp && aiConfigTypes.includes('
|
|
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
|
|
775
|
-
if (hasMcp || hasPluginsForOpenCode ||
|
|
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 (
|
|
829
|
-
|
|
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', '
|
|
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('
|
|
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('
|
|
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 !== '
|
|
973
|
-
const writesOmpMcpConfig = template.mcpServers?.length > 0 && aiConfigTypes.includes('
|
|
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('
|
|
1024
|
+
if (aiConfigTypes.includes('opencode') || aiConfigTypes.includes('omp')) {
|
|
1025
1025
|
preview.summary.plugins = template.plugins.length;
|
|
1026
|
-
if (aiConfigTypes.includes('
|
|
1027
|
-
const
|
|
1028
|
-
if (fs.existsSync(
|
|
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
|
|
32
|
-
|| path.join(NATIVE_PATHS.
|
|
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', '
|
|
42
|
-
const OMP_MCP_SCHEMA_URL = 'https://raw.githubusercontent.com/can1357/oh-my-
|
|
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
|
-
|
|
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
|
-
|
|
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 '
|
|
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 '
|
|
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(
|
|
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(
|
|
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(
|
|
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 '
|
|
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.
|
|
1393
|
-
servers[id].apps.
|
|
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,
|
|
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
|
-
|
|
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' | '
|
|
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 '
|
|
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?.
|
|
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: '
|
|
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
|