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
@@ -6,8 +6,8 @@ const {
6
6
  updateChannel,
7
7
  deleteChannel,
8
8
  saveChannelOrder
9
- } = require('../services/pi-channels');
10
- const { isPiInstalled } = require('../services/pi-sessions');
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/pi-auth-providers');
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 (!isPiInstalled()) {
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, 'pi')
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 (!isPiInstalled()) {
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, 'pi') }));
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 { baseUrl, apiKey, gatewaySourceType } = req.body || {};
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 = { baseUrl, apiKey: apiKey || '', gatewaySourceType: gatewaySourceType || 'openai_compatible' };
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 modelListSourceType = resolvedGatewaySourceType === 'opencode' ? 'openai_compatible' : resolvedGatewaySourceType;
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: models.length > 0,
134
- error: models.length > 0 ? null : (listResult.error || '未返回可用模型列表'),
135
- errorHint: models.length > 0 ? null : (listResult.errorHint || '请手动填写模型名称')
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 modelListSourceType = gatewaySourceType === 'opencode' ? 'openai_compatible' : gatewaySourceType;
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: models.length > 0,
177
- cached: !!listResult.cached,
178
- fallbackUsed: false,
179
- fetchedAt: listResult.lastChecked || new Date().toISOString(),
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
- if (!apiKey) {
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('pi', getSchedulerState('pi'));
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('pi', getSchedulerState('pi'));
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('pi', getSchedulerState('pi'));
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('pi', getSchedulerState('pi'));
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, 'pi');
345
+ resetChannelHealth(req.params.channelId, 'omp');
284
346
  res.json({ success: true });
285
- broadcastSchedulerState('pi', getSchedulerState('pi'));
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: 'pi'
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: 'pi'
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
- getPiPaths,
7
- getPiStatus,
6
+ getOmpPaths,
7
+ getOmpStatus,
8
8
  readJsonFile,
9
9
  readYamlFile,
10
- readPiSettings
11
- } = require('../services/pi-config');
10
+ readOmpSettings
11
+ } = require('../services/omp-config');
12
12
  const {
13
13
  getOmpAuthProviderSnapshot
14
- } = require('../services/pi-auth-providers');
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: 'pi',
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 pi channel is backed by OMP. coding-tool-x keeps the pi route/key for compatibility.',
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 = getPiPaths();
93
- const settings = readPiSettings();
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: getPiStatus(),
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: 'pi',
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 = getPiPaths();
147
- const settings = readPiSettings();
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
- isPiInstalled
8
- } = require('../services/pi-sessions');
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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
- startPiProxyServer,
7
- stopPiProxyServer,
8
- getPiProxyStatus
9
- } = require('../pi-proxy-server');
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/pi-channels');
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.pi;
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.pi)) return null;
52
- const data = JSON.parse(fs.readFileSync(PATHS.activeChannel.pi, 'utf8'));
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.pi)) {
62
- fs.unlinkSync(PATHS.activeChannel.pi);
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 = getPiProxyStatus();
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 startPiProxyServer();
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 = getPiProxyStatus();
118
+ const updatedStatus = getOmpProxyStatus();
119
119
  const { channels: latestChannels } = getChannels();
120
120
  const activeChannel = latestChannels.find(channel => channel.id === currentChannel.id) || currentChannel;
121
- broadcastProxyState('pi', updatedStatus, activeChannel, latestChannels);
122
- broadcastSchedulerState('pi', getSchedulerState('pi'));
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 stopPiProxyServer();
141
+ const result = await stopOmpProxyServer();
142
142
  removeActiveChannelFile();
143
143
  const { broadcastProxyState, broadcastSchedulerState } = require('../websocket-server');
144
144
  const { channels } = getChannels();
145
- broadcastProxyState('pi', getPiProxyStatus(), null, channels);
146
- broadcastSchedulerState('pi', getSchedulerState('pi'));
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
- isPiInstalled,
14
+ isOmpInstalled,
15
15
  HOME_DIR
16
- } = require('../services/pi-sessions');
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 (!isPiInstalled()) {
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: 'pi' });
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 (!isPiInstalled()) {
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: 'pi' });
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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 || 'pi'
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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 (!isPiInstalled()) {
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: 'pi',
313
- toolType: 'pi',
314
- source: 'pi',
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: 'pi',
323
+ tool: 'omp',
324
324
  command,
325
325
  copyCommand
326
326
  });