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
|
@@ -6,8 +6,8 @@ const {
|
|
|
6
6
|
updateChannel,
|
|
7
7
|
deleteChannel,
|
|
8
8
|
saveChannelOrder
|
|
9
|
-
} = require('../services/
|
|
10
|
-
const {
|
|
9
|
+
} = require('../services/omp-channels');
|
|
10
|
+
const { isOmpInstalled } = require('../services/omp-sessions');
|
|
11
11
|
const { getSchedulerState } = require('../services/channel-scheduler');
|
|
12
12
|
const { getChannelHealthStatus, resetChannelHealth } = require('../services/channel-health');
|
|
13
13
|
const { broadcastSchedulerState } = require('../websocket-server');
|
|
@@ -23,7 +23,7 @@ const {
|
|
|
23
23
|
const {
|
|
24
24
|
findAuthProviderForKey,
|
|
25
25
|
getOmpAuthProviderSnapshot
|
|
26
|
-
} = require('../services/
|
|
26
|
+
} = require('../services/omp-auth-providers');
|
|
27
27
|
|
|
28
28
|
function uniqueModels(models = []) {
|
|
29
29
|
const seen = new Set();
|
|
@@ -61,6 +61,63 @@ function collectPreferredModels(channel = {}) {
|
|
|
61
61
|
]);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
function resolveModelDiscoverySourceType(gatewaySourceType) {
|
|
65
|
+
return gatewaySourceType === 'opencode' ? 'openai_compatible' : gatewaySourceType;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function discoverOmpModels(channel, gatewaySourceType, { forceRefresh = false } = {}) {
|
|
69
|
+
if (channel?.authMode === 'oauth' && !String(channel.apiKey || '').trim()) {
|
|
70
|
+
const preferredModels = collectPreferredModels(channel);
|
|
71
|
+
return {
|
|
72
|
+
models: preferredModels,
|
|
73
|
+
supported: preferredModels.length > 0,
|
|
74
|
+
cached: false,
|
|
75
|
+
fallbackUsed: true,
|
|
76
|
+
fetchedAt: new Date().toISOString(),
|
|
77
|
+
error: preferredModels.length > 0 ? null : 'OAuth 渠道未配置 API Key,无法直接调用远端模型列表接口',
|
|
78
|
+
errorHint: '请手动填写默认模型、测速模型或可用模型;运行时由 OMP 的登录凭证提供访问权限'
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const discoverySourceType = resolveModelDiscoverySourceType(gatewaySourceType);
|
|
83
|
+
const listResult = await fetchModelsFromProvider(channel, discoverySourceType, {
|
|
84
|
+
useV1ModelsEndpoint: true,
|
|
85
|
+
forceRefresh
|
|
86
|
+
});
|
|
87
|
+
const listedModels = Array.isArray(listResult.models) ? uniqueModels(listResult.models) : [];
|
|
88
|
+
|
|
89
|
+
if (listedModels.length > 0) {
|
|
90
|
+
return {
|
|
91
|
+
models: listedModels,
|
|
92
|
+
supported: true,
|
|
93
|
+
cached: !!listResult.cached,
|
|
94
|
+
fallbackUsed: false,
|
|
95
|
+
fetchedAt: listResult.lastChecked || new Date().toISOString(),
|
|
96
|
+
error: null,
|
|
97
|
+
errorHint: null
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const probe = await probeModelAvailability(channel, discoverySourceType, {
|
|
102
|
+
stopOnFirstAvailable: false,
|
|
103
|
+
preferredModels: collectPreferredModels(channel),
|
|
104
|
+
forceRefresh
|
|
105
|
+
});
|
|
106
|
+
const probedModels = Array.isArray(probe.availableModels) ? uniqueModels(probe.availableModels) : [];
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
models: probedModels,
|
|
110
|
+
supported: probedModels.length > 0,
|
|
111
|
+
cached: !!probe.cached || !!listResult.cached,
|
|
112
|
+
fallbackUsed: probedModels.length > 0,
|
|
113
|
+
fetchedAt: probe.lastChecked || listResult.lastChecked || new Date().toISOString(),
|
|
114
|
+
error: probedModels.length > 0 ? null : (listResult.error || '无法获取可用模型'),
|
|
115
|
+
errorHint: probedModels.length > 0
|
|
116
|
+
? '模型列表接口不可用,已自动切换为模型探测结果'
|
|
117
|
+
: (listResult.errorHint || '请手动填写模型名称')
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
64
121
|
function attachAuthProvider(channel, snapshot) {
|
|
65
122
|
const authProvider = findAuthProviderForKey(channel.providerKey || channel.provider || channel.name, snapshot);
|
|
66
123
|
if (!authProvider) return channel;
|
|
@@ -81,14 +138,14 @@ function attachAuthProvider(channel, snapshot) {
|
|
|
81
138
|
module.exports = () => {
|
|
82
139
|
router.get('/', (req, res) => {
|
|
83
140
|
try {
|
|
84
|
-
if (!
|
|
141
|
+
if (!isOmpInstalled()) {
|
|
85
142
|
return res.json({ channels: [], installed: false, error: 'OMP CLI not installed' });
|
|
86
143
|
}
|
|
87
144
|
const data = getChannels();
|
|
88
145
|
const authSnapshot = getOmpAuthProviderSnapshot({ accountCheck: false, includeStatus: false });
|
|
89
146
|
const channels = (data.channels || []).map(ch => ({
|
|
90
147
|
...attachAuthProvider(ch, authSnapshot),
|
|
91
|
-
health: getChannelHealthStatus(ch.id, '
|
|
148
|
+
health: getChannelHealthStatus(ch.id, 'omp')
|
|
92
149
|
}));
|
|
93
150
|
res.json({ channels, installed: true });
|
|
94
151
|
} catch (err) {
|
|
@@ -99,14 +156,14 @@ module.exports = () => {
|
|
|
99
156
|
|
|
100
157
|
router.get('/enabled', (req, res) => {
|
|
101
158
|
try {
|
|
102
|
-
if (!
|
|
159
|
+
if (!isOmpInstalled()) {
|
|
103
160
|
return res.json({ channels: [], installed: false, error: 'OMP CLI not installed' });
|
|
104
161
|
}
|
|
105
162
|
const data = getChannels();
|
|
106
163
|
const authSnapshot = getOmpAuthProviderSnapshot({ accountCheck: false, includeStatus: false });
|
|
107
164
|
const channels = (data.channels || [])
|
|
108
165
|
.filter(ch => ch.enabled !== false)
|
|
109
|
-
.map(ch => ({ ...attachAuthProvider(ch, authSnapshot), health: getChannelHealthStatus(ch.id, '
|
|
166
|
+
.map(ch => ({ ...attachAuthProvider(ch, authSnapshot), health: getChannelHealthStatus(ch.id, 'omp') }));
|
|
110
167
|
res.json({ channels, installed: true });
|
|
111
168
|
} catch (err) {
|
|
112
169
|
console.error('[OMP Channels API] Failed to get enabled channels:', err);
|
|
@@ -116,23 +173,40 @@ module.exports = () => {
|
|
|
116
173
|
|
|
117
174
|
router.post('/probe-models', async (req, res) => {
|
|
118
175
|
try {
|
|
119
|
-
const {
|
|
176
|
+
const {
|
|
177
|
+
baseUrl,
|
|
178
|
+
apiKey,
|
|
179
|
+
gatewaySourceType,
|
|
180
|
+
authMode,
|
|
181
|
+
oauthProviderId,
|
|
182
|
+
model,
|
|
183
|
+
speedTestModel,
|
|
184
|
+
allowedModels,
|
|
185
|
+
modelRedirects
|
|
186
|
+
} = req.body || {};
|
|
120
187
|
if (!baseUrl) {
|
|
121
188
|
return res.status(400).json({ error: 'baseUrl is required' });
|
|
122
189
|
}
|
|
123
|
-
const tempChannel = {
|
|
190
|
+
const tempChannel = {
|
|
191
|
+
name: 'Temporary OMP Channel',
|
|
192
|
+
baseUrl,
|
|
193
|
+
apiKey: apiKey || '',
|
|
194
|
+
gatewaySourceType: gatewaySourceType || 'openai_compatible',
|
|
195
|
+
authMode: authMode === 'oauth' ? 'oauth' : 'api_key',
|
|
196
|
+
oauthProviderId: oauthProviderId || '',
|
|
197
|
+
model: model || null,
|
|
198
|
+
speedTestModel: speedTestModel || null,
|
|
199
|
+
allowedModels: Array.isArray(allowedModels) ? allowedModels : [],
|
|
200
|
+
modelRedirects: Array.isArray(modelRedirects) ? modelRedirects : []
|
|
201
|
+
};
|
|
124
202
|
const resolvedGatewaySourceType = resolveGatewaySourceType(tempChannel);
|
|
125
|
-
const
|
|
126
|
-
const listResult = await fetchModelsFromProvider(tempChannel, modelListSourceType, {
|
|
127
|
-
useV1ModelsEndpoint: true,
|
|
128
|
-
forceRefresh: true
|
|
129
|
-
});
|
|
130
|
-
const models = Array.isArray(listResult.models) ? uniqueModels(listResult.models) : [];
|
|
203
|
+
const result = await discoverOmpModels(tempChannel, resolvedGatewaySourceType, { forceRefresh: true });
|
|
131
204
|
res.json({
|
|
132
|
-
models,
|
|
133
|
-
supported:
|
|
134
|
-
|
|
135
|
-
|
|
205
|
+
models: result.models,
|
|
206
|
+
supported: result.supported,
|
|
207
|
+
fallbackUsed: result.fallbackUsed,
|
|
208
|
+
error: result.error,
|
|
209
|
+
errorHint: result.errorHint
|
|
136
210
|
});
|
|
137
211
|
} catch (error) {
|
|
138
212
|
console.error('[OMP Channels API] Error probing models:', error);
|
|
@@ -150,35 +224,18 @@ module.exports = () => {
|
|
|
150
224
|
}
|
|
151
225
|
const forceRefresh = req.query.forceRefresh === 'true';
|
|
152
226
|
const gatewaySourceType = resolveGatewaySourceType(channel);
|
|
153
|
-
const
|
|
154
|
-
const listResult = await fetchModelsFromProvider(channel, modelListSourceType, {
|
|
155
|
-
useV1ModelsEndpoint: true,
|
|
156
|
-
forceRefresh
|
|
157
|
-
});
|
|
158
|
-
let models = Array.isArray(listResult.models) ? uniqueModels(listResult.models) : [];
|
|
159
|
-
let error = models.length > 0 ? null : listResult.error;
|
|
160
|
-
let errorHint = models.length > 0 ? null : listResult.errorHint;
|
|
161
|
-
|
|
162
|
-
if (models.length === 0) {
|
|
163
|
-
const probe = await probeModelAvailability(channel, gatewaySourceType, {
|
|
164
|
-
stopOnFirstAvailable: false,
|
|
165
|
-
preferredModels: collectPreferredModels(channel)
|
|
166
|
-
});
|
|
167
|
-
models = Array.isArray(probe.availableModels) ? uniqueModels(probe.availableModels) : [];
|
|
168
|
-
error = models.length > 0 ? null : (error || '无法获取可用模型');
|
|
169
|
-
errorHint = models.length > 0 ? '模型列表接口不可用,已自动切换为模型探测结果' : (errorHint || '请手动填写模型名称');
|
|
170
|
-
}
|
|
227
|
+
const result = await discoverOmpModels(channel, gatewaySourceType, { forceRefresh });
|
|
171
228
|
|
|
172
229
|
res.json({
|
|
173
230
|
channelId,
|
|
174
231
|
gatewaySourceType,
|
|
175
|
-
models,
|
|
176
|
-
supported:
|
|
177
|
-
cached:
|
|
178
|
-
fallbackUsed:
|
|
179
|
-
fetchedAt:
|
|
180
|
-
error,
|
|
181
|
-
errorHint
|
|
232
|
+
models: result.models,
|
|
233
|
+
supported: result.supported,
|
|
234
|
+
cached: result.cached,
|
|
235
|
+
fallbackUsed: result.fallbackUsed,
|
|
236
|
+
fetchedAt: result.fetchedAt,
|
|
237
|
+
error: result.error,
|
|
238
|
+
errorHint: result.errorHint
|
|
182
239
|
});
|
|
183
240
|
} catch (error) {
|
|
184
241
|
console.error('[OMP Channels API] Error fetching models:', error);
|
|
@@ -203,6 +260,8 @@ module.exports = () => {
|
|
|
203
260
|
speedTestModel,
|
|
204
261
|
providerKey,
|
|
205
262
|
providerApi,
|
|
263
|
+
authMode,
|
|
264
|
+
oauthProviderId,
|
|
206
265
|
presetId,
|
|
207
266
|
websiteUrl,
|
|
208
267
|
balanceToken,
|
|
@@ -212,7 +271,8 @@ module.exports = () => {
|
|
|
212
271
|
if (!name || !baseUrl) {
|
|
213
272
|
return res.status(400).json({ error: 'Missing required fields: name and baseUrl' });
|
|
214
273
|
}
|
|
215
|
-
|
|
274
|
+
const normalizedAuthMode = authMode === 'oauth' ? 'oauth' : 'api_key';
|
|
275
|
+
if (!apiKey && normalizedAuthMode !== 'oauth') {
|
|
216
276
|
return res.status(400).json({ error: 'API Key is required' });
|
|
217
277
|
}
|
|
218
278
|
|
|
@@ -220,6 +280,8 @@ module.exports = () => {
|
|
|
220
280
|
wireApi: wireApi || 'openai',
|
|
221
281
|
providerApi: providerApi || wireApi || 'openai-completions',
|
|
222
282
|
providerKey,
|
|
283
|
+
authMode: normalizedAuthMode,
|
|
284
|
+
oauthProviderId: oauthProviderId || providerKey || '',
|
|
223
285
|
enabled,
|
|
224
286
|
weight,
|
|
225
287
|
maxConcurrency,
|
|
@@ -234,7 +296,7 @@ module.exports = () => {
|
|
|
234
296
|
balanceUserId: balanceUserId || null
|
|
235
297
|
});
|
|
236
298
|
res.json(channel);
|
|
237
|
-
broadcastSchedulerState('
|
|
299
|
+
broadcastSchedulerState('omp', getSchedulerState('omp'));
|
|
238
300
|
} catch (err) {
|
|
239
301
|
console.error('[OMP Channels API] Failed to create channel:', err);
|
|
240
302
|
res.status(500).json({ error: err.message });
|
|
@@ -245,7 +307,7 @@ module.exports = () => {
|
|
|
245
307
|
try {
|
|
246
308
|
const channel = updateChannel(req.params.channelId, req.body || {});
|
|
247
309
|
res.json(channel);
|
|
248
|
-
broadcastSchedulerState('
|
|
310
|
+
broadcastSchedulerState('omp', getSchedulerState('omp'));
|
|
249
311
|
} catch (err) {
|
|
250
312
|
console.error('[OMP Channels API] Failed to update channel:', err);
|
|
251
313
|
res.status(500).json({ error: err.message });
|
|
@@ -256,7 +318,7 @@ module.exports = () => {
|
|
|
256
318
|
try {
|
|
257
319
|
const result = await deleteChannel(req.params.channelId);
|
|
258
320
|
res.json(result);
|
|
259
|
-
broadcastSchedulerState('
|
|
321
|
+
broadcastSchedulerState('omp', getSchedulerState('omp'));
|
|
260
322
|
} catch (err) {
|
|
261
323
|
console.error('[OMP Channels API] Failed to delete channel:', err);
|
|
262
324
|
res.status(500).json({ error: err.message });
|
|
@@ -271,7 +333,7 @@ module.exports = () => {
|
|
|
271
333
|
}
|
|
272
334
|
saveChannelOrder(order);
|
|
273
335
|
res.json({ success: true });
|
|
274
|
-
broadcastSchedulerState('
|
|
336
|
+
broadcastSchedulerState('omp', getSchedulerState('omp'));
|
|
275
337
|
} catch (err) {
|
|
276
338
|
console.error('[OMP Channels API] Failed to save order:', err);
|
|
277
339
|
res.status(500).json({ error: err.message });
|
|
@@ -280,9 +342,9 @@ module.exports = () => {
|
|
|
280
342
|
|
|
281
343
|
router.post('/:channelId/reset-health', (req, res) => {
|
|
282
344
|
try {
|
|
283
|
-
resetChannelHealth(req.params.channelId, '
|
|
345
|
+
resetChannelHealth(req.params.channelId, 'omp');
|
|
284
346
|
res.json({ success: true });
|
|
285
|
-
broadcastSchedulerState('
|
|
347
|
+
broadcastSchedulerState('omp', getSchedulerState('omp'));
|
|
286
348
|
} catch (err) {
|
|
287
349
|
console.error('[OMP Channels API] Failed to reset health:', err);
|
|
288
350
|
res.status(500).json({ error: err.message });
|
|
@@ -296,7 +358,7 @@ module.exports = () => {
|
|
|
296
358
|
return res.status(404).json({ error: 'Channel not found' });
|
|
297
359
|
}
|
|
298
360
|
const result = await testChannelSpeed(channel, req.body?.timeout || 20000, resolveGatewaySourceType(channel), {
|
|
299
|
-
authSourceType: '
|
|
361
|
+
authSourceType: 'omp'
|
|
300
362
|
});
|
|
301
363
|
res.json(result);
|
|
302
364
|
} catch (error) {
|
|
@@ -314,7 +376,7 @@ module.exports = () => {
|
|
|
314
376
|
channels,
|
|
315
377
|
safeConcurrency,
|
|
316
378
|
channel => testChannelSpeed(channel, timeout, resolveGatewaySourceType(channel), {
|
|
317
|
-
authSourceType: '
|
|
379
|
+
authSourceType: 'omp'
|
|
318
380
|
})
|
|
319
381
|
);
|
|
320
382
|
results.sort((a, b) => {
|
|
@@ -3,15 +3,15 @@ const fs = require('fs');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const router = express.Router();
|
|
5
5
|
const {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
getOmpPaths,
|
|
7
|
+
getOmpStatus,
|
|
8
8
|
readJsonFile,
|
|
9
9
|
readYamlFile,
|
|
10
|
-
|
|
11
|
-
} = require('../services/
|
|
10
|
+
readOmpSettings
|
|
11
|
+
} = require('../services/omp-config');
|
|
12
12
|
const {
|
|
13
13
|
getOmpAuthProviderSnapshot
|
|
14
|
-
} = require('../services/
|
|
14
|
+
} = require('../services/omp-auth-providers');
|
|
15
15
|
|
|
16
16
|
function listDirEntries(dirPath, options = {}) {
|
|
17
17
|
const { extensions = null, includeDirectories = true } = options;
|
|
@@ -46,7 +46,7 @@ function normalizeArray(value) {
|
|
|
46
46
|
|
|
47
47
|
function buildCapabilities() {
|
|
48
48
|
return {
|
|
49
|
-
platform: '
|
|
49
|
+
platform: 'omp',
|
|
50
50
|
runtime: 'omp',
|
|
51
51
|
native: {
|
|
52
52
|
config: true,
|
|
@@ -81,7 +81,7 @@ function buildCapabilities() {
|
|
|
81
81
|
agent: false
|
|
82
82
|
},
|
|
83
83
|
notes: [
|
|
84
|
-
'The
|
|
84
|
+
'The omp channel is backed by OMP and uses omp as its platform key.',
|
|
85
85
|
'Provider channels are enabled by merging managed ctx-* providers into OMP models.yml.'
|
|
86
86
|
]
|
|
87
87
|
};
|
|
@@ -89,8 +89,8 @@ function buildCapabilities() {
|
|
|
89
89
|
|
|
90
90
|
router.get('/', (req, res) => {
|
|
91
91
|
try {
|
|
92
|
-
const paths =
|
|
93
|
-
const settings =
|
|
92
|
+
const paths = getOmpPaths();
|
|
93
|
+
const settings = readOmpSettings();
|
|
94
94
|
const resources = {
|
|
95
95
|
config: readYamlFile(paths.config, {}),
|
|
96
96
|
settings: readYamlFile(paths.settings, {}),
|
|
@@ -110,7 +110,7 @@ router.get('/', (req, res) => {
|
|
|
110
110
|
|
|
111
111
|
res.json({
|
|
112
112
|
success: true,
|
|
113
|
-
status:
|
|
113
|
+
status: getOmpStatus(),
|
|
114
114
|
capabilities: buildCapabilities(),
|
|
115
115
|
resources
|
|
116
116
|
});
|
|
@@ -123,7 +123,7 @@ router.get('/', (req, res) => {
|
|
|
123
123
|
router.get('/capabilities', (req, res) => {
|
|
124
124
|
res.json({
|
|
125
125
|
success: true,
|
|
126
|
-
platform: '
|
|
126
|
+
platform: 'omp',
|
|
127
127
|
capabilities: buildCapabilities()
|
|
128
128
|
});
|
|
129
129
|
});
|
|
@@ -143,8 +143,8 @@ router.get('/auth-providers', (req, res) => {
|
|
|
143
143
|
|
|
144
144
|
router.get('/resources', (req, res) => {
|
|
145
145
|
try {
|
|
146
|
-
const paths =
|
|
147
|
-
const settings =
|
|
146
|
+
const paths = getOmpPaths();
|
|
147
|
+
const settings = readOmpSettings();
|
|
148
148
|
res.json({
|
|
149
149
|
success: true,
|
|
150
150
|
paths,
|
|
@@ -4,8 +4,8 @@ const {
|
|
|
4
4
|
getProjects,
|
|
5
5
|
saveProjectOrder,
|
|
6
6
|
deleteProject,
|
|
7
|
-
|
|
8
|
-
} = require('../services/
|
|
7
|
+
isOmpInstalled
|
|
8
|
+
} = require('../services/omp-sessions');
|
|
9
9
|
|
|
10
10
|
function isNotFoundError(error) {
|
|
11
11
|
return !!(error && error.message === 'Project not found');
|
|
@@ -14,7 +14,7 @@ function isNotFoundError(error) {
|
|
|
14
14
|
module.exports = () => {
|
|
15
15
|
router.get('/', (req, res) => {
|
|
16
16
|
try {
|
|
17
|
-
if (!
|
|
17
|
+
if (!isOmpInstalled()) {
|
|
18
18
|
return res.json({
|
|
19
19
|
projects: [],
|
|
20
20
|
currentProject: null,
|
|
@@ -41,7 +41,7 @@ module.exports = () => {
|
|
|
41
41
|
|
|
42
42
|
router.post('/order', (req, res) => {
|
|
43
43
|
try {
|
|
44
|
-
if (!
|
|
44
|
+
if (!isOmpInstalled()) {
|
|
45
45
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
46
46
|
}
|
|
47
47
|
const { order } = req.body || {};
|
|
@@ -58,7 +58,7 @@ module.exports = () => {
|
|
|
58
58
|
|
|
59
59
|
router.delete('/:projectName', (req, res) => {
|
|
60
60
|
try {
|
|
61
|
-
if (!
|
|
61
|
+
if (!isOmpInstalled()) {
|
|
62
62
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
63
63
|
}
|
|
64
64
|
const result = deleteProject(req.params.projectName);
|
|
@@ -3,15 +3,15 @@ const fs = require('fs');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const router = express.Router();
|
|
5
5
|
const {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} = require('../
|
|
6
|
+
startOmpProxyServer,
|
|
7
|
+
stopOmpProxyServer,
|
|
8
|
+
getOmpProxyStatus
|
|
9
|
+
} = require('../omp-proxy-server');
|
|
10
10
|
const {
|
|
11
11
|
getChannels,
|
|
12
12
|
getEnabledChannels,
|
|
13
13
|
markChannelAsRecentlyUsed
|
|
14
|
-
} = require('../services/
|
|
14
|
+
} = require('../services/omp-channels');
|
|
15
15
|
const { getSchedulerState } = require('../services/channel-scheduler');
|
|
16
16
|
const { PATHS, ensureStorageDirMigrated } = require('../../config/paths');
|
|
17
17
|
|
|
@@ -37,7 +37,7 @@ function selectLatestEnabledChannel(channels) {
|
|
|
37
37
|
|
|
38
38
|
function saveActiveChannelId(channelId) {
|
|
39
39
|
ensureStorageDirMigrated();
|
|
40
|
-
const filePath = PATHS.activeChannel.
|
|
40
|
+
const filePath = PATHS.activeChannel.omp;
|
|
41
41
|
const dir = path.dirname(filePath);
|
|
42
42
|
if (!fs.existsSync(dir)) {
|
|
43
43
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -48,8 +48,8 @@ function saveActiveChannelId(channelId) {
|
|
|
48
48
|
function loadActiveChannelId() {
|
|
49
49
|
ensureStorageDirMigrated();
|
|
50
50
|
try {
|
|
51
|
-
if (!fs.existsSync(PATHS.activeChannel.
|
|
52
|
-
const data = JSON.parse(fs.readFileSync(PATHS.activeChannel.
|
|
51
|
+
if (!fs.existsSync(PATHS.activeChannel.omp)) return null;
|
|
52
|
+
const data = JSON.parse(fs.readFileSync(PATHS.activeChannel.omp, 'utf8'));
|
|
53
53
|
return data.activeChannelId || null;
|
|
54
54
|
} catch {
|
|
55
55
|
return null;
|
|
@@ -58,8 +58,8 @@ function loadActiveChannelId() {
|
|
|
58
58
|
|
|
59
59
|
function removeActiveChannelFile() {
|
|
60
60
|
ensureStorageDirMigrated();
|
|
61
|
-
if (fs.existsSync(PATHS.activeChannel.
|
|
62
|
-
fs.unlinkSync(PATHS.activeChannel.
|
|
61
|
+
if (fs.existsSync(PATHS.activeChannel.omp)) {
|
|
62
|
+
fs.unlinkSync(PATHS.activeChannel.omp);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -77,7 +77,7 @@ function resolveActiveChannel(channels, activeChannelId = null) {
|
|
|
77
77
|
|
|
78
78
|
router.get('/status', (req, res) => {
|
|
79
79
|
try {
|
|
80
|
-
const proxy =
|
|
80
|
+
const proxy = getOmpProxyStatus();
|
|
81
81
|
const { channels } = getChannels();
|
|
82
82
|
const enabledChannels = channels.filter(ch => ch.enabled !== false);
|
|
83
83
|
const activeChannel = resolveActiveChannel(channels, loadActiveChannelId());
|
|
@@ -109,17 +109,17 @@ router.post('/start', async (req, res) => {
|
|
|
109
109
|
currentChannel = markChannelAsRecentlyUsed(currentChannel.id);
|
|
110
110
|
saveActiveChannelId(currentChannel.id);
|
|
111
111
|
|
|
112
|
-
const proxyResult = await
|
|
112
|
+
const proxyResult = await startOmpProxyServer();
|
|
113
113
|
if (!proxyResult.success) {
|
|
114
114
|
return res.status(500).json({ error: 'Failed to enable OMP models.yml provider config' });
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
const { broadcastProxyState, broadcastSchedulerState } = require('../websocket-server');
|
|
118
|
-
const updatedStatus =
|
|
118
|
+
const updatedStatus = getOmpProxyStatus();
|
|
119
119
|
const { channels: latestChannels } = getChannels();
|
|
120
120
|
const activeChannel = latestChannels.find(channel => channel.id === currentChannel.id) || currentChannel;
|
|
121
|
-
broadcastProxyState('
|
|
122
|
-
broadcastSchedulerState('
|
|
121
|
+
broadcastProxyState('omp', updatedStatus, activeChannel, latestChannels);
|
|
122
|
+
broadcastSchedulerState('omp', getSchedulerState('omp'));
|
|
123
123
|
|
|
124
124
|
res.json({
|
|
125
125
|
success: true,
|
|
@@ -138,12 +138,12 @@ router.post('/start', async (req, res) => {
|
|
|
138
138
|
|
|
139
139
|
router.post('/stop', async (req, res) => {
|
|
140
140
|
try {
|
|
141
|
-
const result = await
|
|
141
|
+
const result = await stopOmpProxyServer();
|
|
142
142
|
removeActiveChannelFile();
|
|
143
143
|
const { broadcastProxyState, broadcastSchedulerState } = require('../websocket-server');
|
|
144
144
|
const { channels } = getChannels();
|
|
145
|
-
broadcastProxyState('
|
|
146
|
-
broadcastSchedulerState('
|
|
145
|
+
broadcastProxyState('omp', getOmpProxyStatus(), null, channels);
|
|
146
|
+
broadcastSchedulerState('omp', getSchedulerState('omp'));
|
|
147
147
|
res.json({ success: true, ...result });
|
|
148
148
|
} catch (error) {
|
|
149
149
|
console.error('[OMP Proxy] Stop failed:', error);
|
|
@@ -11,9 +11,9 @@ const {
|
|
|
11
11
|
deleteSession,
|
|
12
12
|
forkSession,
|
|
13
13
|
saveSessionOrder,
|
|
14
|
-
|
|
14
|
+
isOmpInstalled,
|
|
15
15
|
HOME_DIR
|
|
16
|
-
} = require('../services/
|
|
16
|
+
} = require('../services/omp-sessions');
|
|
17
17
|
const { loadAliases } = require('../services/alias');
|
|
18
18
|
const { broadcastLog } = require('../websocket-server');
|
|
19
19
|
|
|
@@ -29,7 +29,7 @@ function quoteForShell(value) {
|
|
|
29
29
|
module.exports = () => {
|
|
30
30
|
router.get('/search/global', (req, res) => {
|
|
31
31
|
try {
|
|
32
|
-
if (!
|
|
32
|
+
if (!isOmpInstalled()) {
|
|
33
33
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
34
34
|
}
|
|
35
35
|
const { keyword } = req.query;
|
|
@@ -40,7 +40,7 @@ module.exports = () => {
|
|
|
40
40
|
}
|
|
41
41
|
const sessions = searchSessions(keyword, contextLength);
|
|
42
42
|
const totalMatches = sessions.reduce((sum, session) => sum + (session.matchCount || 0), 0);
|
|
43
|
-
res.json({ keyword, totalMatches, sessions, source: '
|
|
43
|
+
res.json({ keyword, totalMatches, sessions, source: 'omp' });
|
|
44
44
|
} catch (err) {
|
|
45
45
|
console.error('[OMP API] Failed to search sessions:', err);
|
|
46
46
|
res.status(500).json({ error: err.message });
|
|
@@ -49,11 +49,11 @@ module.exports = () => {
|
|
|
49
49
|
|
|
50
50
|
router.get('/recent/list', (req, res) => {
|
|
51
51
|
try {
|
|
52
|
-
if (!
|
|
52
|
+
if (!isOmpInstalled()) {
|
|
53
53
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
54
54
|
}
|
|
55
55
|
const limit = parseInt(req.query.limit, 10) || 5;
|
|
56
|
-
res.json({ sessions: getRecentSessions(limit), source: '
|
|
56
|
+
res.json({ sessions: getRecentSessions(limit), source: 'omp' });
|
|
57
57
|
} catch (err) {
|
|
58
58
|
console.error('[OMP API] Failed to get recent sessions:', err);
|
|
59
59
|
res.status(500).json({ error: err.message });
|
|
@@ -62,7 +62,7 @@ module.exports = () => {
|
|
|
62
62
|
|
|
63
63
|
router.get('/:projectName/search', (req, res) => {
|
|
64
64
|
try {
|
|
65
|
-
if (!
|
|
65
|
+
if (!isOmpInstalled()) {
|
|
66
66
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
67
67
|
}
|
|
68
68
|
const { projectName } = req.params;
|
|
@@ -83,7 +83,7 @@ module.exports = () => {
|
|
|
83
83
|
|
|
84
84
|
router.get('/:projectName', (req, res) => {
|
|
85
85
|
try {
|
|
86
|
-
if (!
|
|
86
|
+
if (!isOmpInstalled()) {
|
|
87
87
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
88
88
|
}
|
|
89
89
|
const { projectName } = req.params;
|
|
@@ -110,7 +110,7 @@ module.exports = () => {
|
|
|
110
110
|
|
|
111
111
|
router.get('/:projectName/:sessionId/status', (req, res) => {
|
|
112
112
|
try {
|
|
113
|
-
if (!
|
|
113
|
+
if (!isOmpInstalled()) {
|
|
114
114
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
115
115
|
}
|
|
116
116
|
const session = getSessionById(req.params.sessionId);
|
|
@@ -130,7 +130,7 @@ module.exports = () => {
|
|
|
130
130
|
|
|
131
131
|
router.get('/:projectName/:sessionId/outline', (req, res) => {
|
|
132
132
|
try {
|
|
133
|
-
if (!
|
|
133
|
+
if (!isOmpInstalled()) {
|
|
134
134
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
135
135
|
}
|
|
136
136
|
const session = getSessionById(req.params.sessionId);
|
|
@@ -159,7 +159,7 @@ module.exports = () => {
|
|
|
159
159
|
|
|
160
160
|
router.get('/:projectName/:sessionId/messages', (req, res) => {
|
|
161
161
|
try {
|
|
162
|
-
if (!
|
|
162
|
+
if (!isOmpInstalled()) {
|
|
163
163
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
164
164
|
}
|
|
165
165
|
const { sessionId } = req.params;
|
|
@@ -186,7 +186,7 @@ module.exports = () => {
|
|
|
186
186
|
gitRepository: null,
|
|
187
187
|
cwd: session?.directory || null,
|
|
188
188
|
provider: session?.provider || '',
|
|
189
|
-
model: session?.model || '
|
|
189
|
+
model: session?.model || 'omp'
|
|
190
190
|
},
|
|
191
191
|
pagination: {
|
|
192
192
|
page: pageNum,
|
|
@@ -203,7 +203,7 @@ module.exports = () => {
|
|
|
203
203
|
|
|
204
204
|
router.delete('/:projectName/:sessionId', (req, res) => {
|
|
205
205
|
try {
|
|
206
|
-
if (!
|
|
206
|
+
if (!isOmpInstalled()) {
|
|
207
207
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
208
208
|
}
|
|
209
209
|
res.json(deleteSession(req.params.sessionId));
|
|
@@ -218,7 +218,7 @@ module.exports = () => {
|
|
|
218
218
|
|
|
219
219
|
router.post('/:projectName/batch-delete', (req, res) => {
|
|
220
220
|
try {
|
|
221
|
-
if (!
|
|
221
|
+
if (!isOmpInstalled()) {
|
|
222
222
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
223
223
|
}
|
|
224
224
|
const { sessionIds } = req.body || {};
|
|
@@ -259,7 +259,7 @@ module.exports = () => {
|
|
|
259
259
|
|
|
260
260
|
router.post('/:projectName/:sessionId/fork', (req, res) => {
|
|
261
261
|
try {
|
|
262
|
-
if (!
|
|
262
|
+
if (!isOmpInstalled()) {
|
|
263
263
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
264
264
|
}
|
|
265
265
|
res.json(forkSession(req.params.sessionId, req.body || {}));
|
|
@@ -274,7 +274,7 @@ module.exports = () => {
|
|
|
274
274
|
|
|
275
275
|
router.post('/:projectName/order', (req, res) => {
|
|
276
276
|
try {
|
|
277
|
-
if (!
|
|
277
|
+
if (!isOmpInstalled()) {
|
|
278
278
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
279
279
|
}
|
|
280
280
|
const { order } = req.body || {};
|
|
@@ -291,7 +291,7 @@ module.exports = () => {
|
|
|
291
291
|
|
|
292
292
|
router.post('/:projectName/:sessionId/launch', (req, res) => {
|
|
293
293
|
try {
|
|
294
|
-
if (!
|
|
294
|
+
if (!isOmpInstalled()) {
|
|
295
295
|
return res.status(404).json({ error: 'OMP CLI not installed' });
|
|
296
296
|
}
|
|
297
297
|
const { projectName, sessionId } = req.params;
|
|
@@ -309,9 +309,9 @@ module.exports = () => {
|
|
|
309
309
|
action: 'launch_pi_session',
|
|
310
310
|
message: `复制 OMP 会话启动命令 ${sessionId.substring(0, 8)}`,
|
|
311
311
|
sessionId,
|
|
312
|
-
tool: '
|
|
313
|
-
toolType: '
|
|
314
|
-
source: '
|
|
312
|
+
tool: 'omp',
|
|
313
|
+
toolType: 'omp',
|
|
314
|
+
source: 'omp',
|
|
315
315
|
timestamp: Date.now()
|
|
316
316
|
});
|
|
317
317
|
|
|
@@ -320,7 +320,7 @@ module.exports = () => {
|
|
|
320
320
|
cwd,
|
|
321
321
|
sessionFile: session.filePath,
|
|
322
322
|
sessionId,
|
|
323
|
-
tool: '
|
|
323
|
+
tool: 'omp',
|
|
324
324
|
command,
|
|
325
325
|
copyCommand
|
|
326
326
|
});
|