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
@@ -240,6 +240,70 @@ function parseOpenCodeImport(rawText) {
240
240
  };
241
241
  }
242
242
 
243
+ function pickOmpCredentialEntry(parsed) {
244
+ if (Array.isArray(parsed)) {
245
+ return parsed.find(item => item && typeof item === 'object') || null;
246
+ }
247
+ if (!parsed || typeof parsed !== 'object') {
248
+ return null;
249
+ }
250
+ if (parsed.provider || parsed.providerId || parsed.provider_id || parsed.providerKey || parsed.credential_type || parsed.data) {
251
+ return parsed;
252
+ }
253
+ const entry = Object.entries(parsed).find(([, value]) => value && typeof value === 'object');
254
+ return entry ? { provider: entry[0], ...entry[1] } : parsed;
255
+ }
256
+
257
+ function parseOmpImport(rawText) {
258
+ const parsed = tryParseJson(rawText);
259
+ if (!parsed || typeof parsed !== 'object') {
260
+ throw new Error('OMP OAuth 仅支持 JSON 导入。');
261
+ }
262
+
263
+ const entry = pickOmpCredentialEntry(parsed);
264
+ if (!entry || typeof entry !== 'object') {
265
+ throw new Error('OMP OAuth 导入缺少 provider。');
266
+ }
267
+
268
+ const data = entry.data && typeof entry.data === 'object' ? entry.data : entry;
269
+ const providerId = safeString(
270
+ entry.providerId
271
+ || entry.provider_id
272
+ || entry.providerKey
273
+ || entry.provider
274
+ || data.providerId
275
+ || data.provider
276
+ );
277
+ if (!providerId) {
278
+ throw new Error('OMP OAuth 导入缺少 providerId。');
279
+ }
280
+
281
+ const accessToken = safeString(
282
+ data.accessToken
283
+ || data.access_token
284
+ || data.access
285
+ || data.token
286
+ || data.authToken
287
+ );
288
+ const credentialType = safeString(entry.credentialType || entry.credential_type || data.type || 'oauth') || 'oauth';
289
+ if (credentialType === 'oauth' && !accessToken && !entry.data) {
290
+ throw new Error('OMP OAuth 导入缺少 access/accessToken。');
291
+ }
292
+
293
+ return {
294
+ providerId,
295
+ credentialType,
296
+ accessToken,
297
+ refreshToken: safeString(data.refreshToken || data.refresh_token || data.refresh),
298
+ expiresAt: safeNumber(data.expiresAt || data.expiry_date || data.expiryDate || data.expires),
299
+ accountId: safeString(data.accountId || data.account_id || entry.accountId || entry.account_id),
300
+ accountEmail: safeString(data.accountEmail || data.email || entry.accountEmail || entry.email),
301
+ identityKey: safeString(entry.identityKey || entry.identity_key || data.identityKey || data.identity_key),
302
+ importPayload: parsed,
303
+ primaryToken: accessToken
304
+ };
305
+ }
306
+
243
307
  function parseCredentialInput(tool, rawText) {
244
308
  switch (tool) {
245
309
  case 'claude':
@@ -250,6 +314,8 @@ function parseCredentialInput(tool, rawText) {
250
314
  return parseGeminiImport(rawText);
251
315
  case 'opencode':
252
316
  return parseOpenCodeImport(rawText);
317
+ case 'omp':
318
+ return parseOmpImport(rawText);
253
319
  default:
254
320
  throw new Error(`Unsupported OAuth tool: ${tool}`);
255
321
  }
@@ -261,7 +327,7 @@ function buildCredentialName(tool, metadata, providedName = '') {
261
327
  return explicit;
262
328
  }
263
329
 
264
- if (tool === 'opencode' && safeString(metadata.providerId)) {
330
+ if ((tool === 'opencode' || tool === 'omp') && safeString(metadata.providerId)) {
265
331
  const accountLabel = safeString(metadata.accountId || metadata.accountEmail);
266
332
  return accountLabel
267
333
  ? `${tool} - ${metadata.providerId} - ${accountLabel}`
@@ -386,6 +452,19 @@ function extractSecrets(tool, metadata) {
386
452
  enterpriseUrl: metadata.enterpriseUrl || '',
387
453
  primaryToken: metadata.primaryToken || metadata.accessToken || ''
388
454
  };
455
+ case 'omp':
456
+ return {
457
+ providerId: metadata.providerId || '',
458
+ credentialType: metadata.credentialType || 'oauth',
459
+ accessToken: metadata.accessToken || '',
460
+ refreshToken: metadata.refreshToken || '',
461
+ expiresAt: metadata.expiresAt || null,
462
+ accountId: metadata.accountId || '',
463
+ accountEmail: metadata.accountEmail || '',
464
+ identityKey: metadata.identityKey || '',
465
+ importPayload: metadata.importPayload || null,
466
+ primaryToken: metadata.primaryToken || metadata.accessToken || ''
467
+ };
389
468
  default:
390
469
  return { primaryToken: metadata.primaryToken || metadata.accessToken || '' };
391
470
  }
@@ -395,7 +474,7 @@ function stableFingerprintValue(tool, metadata) {
395
474
  // 优先使用稳定标识符,避免 access token 轮换导致重复记录
396
475
  const stableId = metadata.accountEmail
397
476
  || metadata.accountId
398
- || (tool === 'opencode' ? metadata.providerId : '')
477
+ || ((tool === 'opencode' || tool === 'omp') ? metadata.providerId : '')
399
478
  || metadata.refreshToken
400
479
  || metadata.primaryToken
401
480
  || metadata.accessToken
@@ -559,6 +638,11 @@ function cleanupManagedArtifacts(tool) {
559
638
 
560
639
  if (tool === 'opencode') {
561
640
  opencodeSettingsManager.deleteBackup?.();
641
+ return;
642
+ }
643
+
644
+ if (tool === 'omp') {
645
+ return;
562
646
  }
563
647
  }
564
648
 
@@ -597,6 +681,14 @@ async function stopProxyIfRunning(tool) {
597
681
  }
598
682
  return false;
599
683
  }
684
+ case 'omp': {
685
+ const { stopOmpProxyServer, getOmpProxyStatus } = require('../omp-proxy-server');
686
+ if (getOmpProxyStatus().running) {
687
+ await stopOmpProxyServer();
688
+ return true;
689
+ }
690
+ return false;
691
+ }
600
692
  default:
601
693
  throw new Error(`Unsupported OAuth tool: ${tool}`);
602
694
  }
@@ -625,6 +717,11 @@ function disableAllChannelsForTool(tool) {
625
717
  disableAllChannels();
626
718
  break;
627
719
  }
720
+ case 'omp': {
721
+ const { disableAllChannels } = require('./omp-channels');
722
+ disableAllChannels();
723
+ break;
724
+ }
628
725
  }
629
726
  } catch (err) {
630
727
  console.warn(`[OAuth] Failed to disable channels for ${tool}:`, err.message);
@@ -635,7 +732,7 @@ async function applyStoredCredential(tool, credentialId) {
635
732
  const entry = findStoredCredential(tool, credentialId);
636
733
  const proxyStopped = await stopProxyIfRunning(tool);
637
734
  cleanupManagedArtifacts(tool);
638
- if (tool !== 'opencode') {
735
+ if (tool !== 'opencode' && tool !== 'omp') {
639
736
  disableAllChannelsForTool(tool);
640
737
  }
641
738
  applyOAuthCredential(tool, entry.secrets);
@@ -818,6 +915,16 @@ async function fetchCredentialUsage(tool, credentialId) {
818
915
  return await fetchCodexUsage(accessToken);
819
916
  }
820
917
  }
918
+ case 'omp': {
919
+ const providerId = entry.providerId || secrets.providerId || '';
920
+ if (providerId.includes('claude') || providerId.includes('anthropic')) {
921
+ return await fetchClaudeUsage(accessToken);
922
+ } else if (providerId.includes('gemini') || providerId.includes('google')) {
923
+ return await fetchGeminiUsage(accessToken);
924
+ } else {
925
+ return await fetchCodexUsage(accessToken);
926
+ }
927
+ }
821
928
  default:
822
929
  return { error: `不支持的工具: ${tool}` };
823
930
  }
@@ -1,5 +1,5 @@
1
1
  const { spawnSync } = require('child_process');
2
- const piConfig = require('./pi-config');
2
+ const ompConfig = require('./omp-config');
3
3
 
4
4
  const COMMAND_TIMEOUT_MS = 5000;
5
5
  const TOKEN_LIST_TIMEOUT_MS = 3000;
@@ -214,7 +214,7 @@ function getOmpAuthProviderSnapshot(options = {}) {
214
214
  }
215
215
 
216
216
  const env = options.env || process.env;
217
- const runtime = options.runtime || piConfig.resolvePiRuntime(env, options.runtimeOptions || {});
217
+ const runtime = options.runtime || ompConfig.resolveOmpRuntime(env, options.runtimeOptions || {});
218
218
  if (!runtime || runtime.runtime !== 'omp' || !runtime.installed) {
219
219
  const value = buildEmptySnapshot(runtime || null, 'omp-not-available');
220
220
  snapshotCache[cacheKey] = { loadedAt: now, value };
@@ -5,13 +5,13 @@ const {
5
5
  removeManagedOmpProviders,
6
6
  isManagedOmpProvidersActive,
7
7
  getLastManagedOmpSyncResult
8
- } = require('./pi-settings-manager');
8
+ } = require('./omp-settings-manager');
9
9
 
10
- class PiChannelService extends BaseChannelService {
10
+ class OmpChannelService extends BaseChannelService {
11
11
  constructor() {
12
12
  super({
13
- platform: 'pi',
14
- channelsFilePath: PATHS.channels.pi,
13
+ platform: 'omp',
14
+ channelsFilePath: PATHS.channels.omp,
15
15
  defaultGatewaySource: 'openai_compatible',
16
16
  isProxyRunning: () => isManagedOmpProvidersActive()
17
17
  });
@@ -21,6 +21,11 @@ class PiChannelService extends BaseChannelService {
21
21
  const normalized = super._applyDefaults(channel);
22
22
  normalized.providerKey = normalized.providerKey || normalized.provider || normalized.name || normalized.id;
23
23
  normalized.providerApi = normalized.providerApi || normalized.api || normalized.wireApi || 'openai-completions';
24
+ normalized.authMode = normalized.authMode === 'oauth' ? 'oauth' : 'api_key';
25
+ normalized.oauthProviderId = normalized.oauthProviderId || (normalized.authMode === 'oauth' ? normalized.providerKey : '');
26
+ if (normalized.authMode === 'oauth') {
27
+ normalized.apiKey = normalized.apiKey || '';
28
+ }
24
29
  normalized.model = normalized.model || null;
25
30
  normalized.models = Array.isArray(normalized.models) ? normalized.models : [];
26
31
  normalized.allowedModels = Array.isArray(normalized.allowedModels) ? normalized.allowedModels : [];
@@ -69,7 +74,7 @@ class PiChannelService extends BaseChannelService {
69
74
  }
70
75
  }
71
76
 
72
- const service = new PiChannelService();
77
+ const service = new OmpChannelService();
73
78
 
74
79
  module.exports = {
75
80
  getChannels: () => service.getChannels(),
@@ -2,10 +2,9 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const { execFileSync } = require('child_process');
4
4
  const yaml = require('js-yaml');
5
- const { HOME_DIR } = require('../../config/paths');
5
+ const { HOME_DIR, PATHS = {} } = require('../../config/paths');
6
6
 
7
7
  const DEFAULT_OMP_COMMAND = 'omp';
8
- const LEGACY_PI_COMMAND = 'pi';
9
8
 
10
9
  function expandHome(input = '') {
11
10
  const value = String(input || '').trim();
@@ -22,10 +21,7 @@ function normalizeProfileName(profile = '') {
22
21
  }
23
22
 
24
23
  function getOmpProfile(env = process.env) {
25
- if (env.OMP_PROFILE !== undefined) {
26
- return normalizeProfileName(env.OMP_PROFILE);
27
- }
28
- return normalizeProfileName(env.PI_PROFILE);
24
+ return normalizeProfileName(env.OMP_PROFILE);
29
25
  }
30
26
 
31
27
  function isAbsolutePathLike(value = '') {
@@ -33,7 +29,7 @@ function isAbsolutePathLike(value = '') {
33
29
  }
34
30
 
35
31
  function getOmpConfigRoot(env = process.env) {
36
- const configured = expandHome(env.PI_CONFIG_DIR || '');
32
+ const configured = expandHome(env.OMP_CONFIG_DIR || '');
37
33
  if (!configured) return path.join(HOME_DIR, '.omp');
38
34
  return isAbsolutePathLike(configured) ? configured : path.join(HOME_DIR, configured);
39
35
  }
@@ -46,14 +42,10 @@ function getDefaultOmpAgentDir(env = process.env) {
46
42
  : path.join(configRoot, 'agent');
47
43
  }
48
44
 
49
- function getLegacyPiAgentDir() {
50
- return path.join(HOME_DIR, '.pi', 'agent');
51
- }
52
-
53
- function getFallbackPiAgentDir(runtime, env = process.env) {
54
- const configured = expandHome(env.PI_CODING_AGENT_DIR || '');
45
+ function getFallbackOmpAgentDir(runtime, env = process.env) {
46
+ const configured = expandHome(env.OMP_CODING_AGENT_DIR || '');
55
47
  if (configured) return configured;
56
- return runtime?.runtime === 'pi' ? getLegacyPiAgentDir(env) : getDefaultOmpAgentDir(env);
48
+ return getDefaultOmpAgentDir(env);
57
49
  }
58
50
 
59
51
  function buildCommandEnv(env = process.env) {
@@ -63,7 +55,7 @@ function buildCommandEnv(env = process.env) {
63
55
  };
64
56
  }
65
57
 
66
- function runPiCommand(command, args = [], env = process.env, options = {}, stdio = ['ignore', 'pipe', 'pipe']) {
58
+ function runOmpCommand(command, args = [], env = process.env, options = {}, stdio = ['ignore', 'pipe', 'pipe']) {
67
59
  const runner = options.commandRunner || execFileSync;
68
60
  return runner(command, args, {
69
61
  encoding: 'utf8',
@@ -75,7 +67,7 @@ function runPiCommand(command, args = [], env = process.env, options = {}, stdio
75
67
 
76
68
  function readOmpAgentDirFromCommand(command, env = process.env, options = {}) {
77
69
  try {
78
- const output = runPiCommand(command, ['config', 'path'], env, options);
70
+ const output = runOmpCommand(command, ['config', 'path'], env, options);
79
71
  const agentDir = String(output || '').trim().split(/\r?\n/).find(Boolean);
80
72
  return agentDir ? path.resolve(expandHome(agentDir)) : '';
81
73
  } catch {
@@ -83,20 +75,20 @@ function readOmpAgentDirFromCommand(command, env = process.env, options = {}) {
83
75
  }
84
76
  }
85
77
 
86
- function getPiAgentDir(env = process.env, options = {}) {
87
- const runtime = options.runtime || resolvePiRuntime(env, options);
78
+ function getOmpAgentDir(env = process.env, options = {}) {
79
+ const runtime = options.runtime || resolveOmpRuntime(env, options);
88
80
  if (runtime.runtime === 'omp' && runtime.installed) {
89
81
  const commandAgentDir = readOmpAgentDirFromCommand(runtime.command, env, options);
90
82
  if (commandAgentDir) {
91
83
  return commandAgentDir;
92
84
  }
93
85
  }
94
- return path.resolve(expandHome(getFallbackPiAgentDir(runtime, env)));
86
+ return path.resolve(expandHome(getFallbackOmpAgentDir(runtime, env)));
95
87
  }
96
88
 
97
- function getPiPaths(env = process.env, options = {}) {
98
- const runtime = options.runtime || resolvePiRuntime(env, options);
99
- const agentDir = getPiAgentDir(env, { ...options, runtime });
89
+ function getOmpPaths(env = process.env, options = {}) {
90
+ const runtime = options.runtime || resolveOmpRuntime(env, options);
91
+ const agentDir = getOmpAgentDir(env, { ...options, runtime });
100
92
  return {
101
93
  agentDir,
102
94
  config: path.join(agentDir, 'config.yml'),
@@ -115,11 +107,12 @@ function getPiPaths(env = process.env, options = {}) {
115
107
  extensions: path.join(agentDir, 'extensions'),
116
108
  themes: path.join(agentDir, 'themes'),
117
109
  packages: path.join(agentDir, 'packages'),
118
- managedProviderExtension: path.join(agentDir, 'extensions', 'coding-tool-x-provider.ts')
110
+ managedProviderExtension: path.join(agentDir, 'extensions', 'coding-tool-x-provider.ts'),
111
+ managedVisibilityState: path.join(PATHS.storage || path.join(HOME_DIR, '.cc-tool', 'storage'), 'omp-managed-visibility.json')
119
112
  };
120
113
  }
121
114
 
122
- function ensurePiDir(dirPath) {
115
+ function ensureOmpDir(dirPath) {
123
116
  if (!fs.existsSync(dirPath)) {
124
117
  fs.mkdirSync(dirPath, { recursive: true });
125
118
  }
@@ -136,7 +129,7 @@ function readJsonFile(filePath, fallback = {}) {
136
129
  }
137
130
 
138
131
  function writeJsonFile(filePath, data) {
139
- ensurePiDir(path.dirname(filePath));
132
+ ensureOmpDir(path.dirname(filePath));
140
133
  fs.writeFileSync(filePath, JSON.stringify(data || {}, null, 2), 'utf8');
141
134
  }
142
135
 
@@ -153,7 +146,7 @@ function readYamlFile(filePath, fallback = {}) {
153
146
  }
154
147
 
155
148
  function writeYamlFile(filePath, data) {
156
- ensurePiDir(path.dirname(filePath));
149
+ ensureOmpDir(path.dirname(filePath));
157
150
  fs.writeFileSync(filePath, yaml.dump(data || {}, {
158
151
  lineWidth: 120,
159
152
  noRefs: true,
@@ -161,39 +154,38 @@ function writeYamlFile(filePath, data) {
161
154
  }), 'utf8');
162
155
  }
163
156
 
164
- function readPiSettings() {
165
- const paths = getPiPaths();
157
+ function readOmpSettings() {
158
+ const paths = getOmpPaths();
166
159
  return readYamlFile(paths.settings, readJsonFile(paths.settingsJsonLegacy, {}));
167
160
  }
168
161
 
169
- function writePiSettings(settings) {
170
- writeYamlFile(getPiPaths().settings, settings || {});
162
+ function writeOmpSettings(settings) {
163
+ writeYamlFile(getOmpPaths().settings, settings || {});
171
164
  }
172
165
 
173
- function getPiCommand(env = process.env) {
174
- return String(env.OMP_COMMAND || env.PI_COMMAND || DEFAULT_OMP_COMMAND).trim() || DEFAULT_OMP_COMMAND;
166
+ function getOmpCommand(env = process.env) {
167
+ return String(env.OMP_COMMAND || DEFAULT_OMP_COMMAND).trim() || DEFAULT_OMP_COMMAND;
175
168
  }
176
169
 
177
170
  function commandExists(command, env = process.env, options = {}) {
178
171
  try {
179
- runPiCommand(command, ['--version'], env, options, 'ignore');
172
+ runOmpCommand(command, ['--version'], env, options, 'ignore');
180
173
  return true;
181
174
  } catch {
182
175
  return false;
183
176
  }
184
177
  }
185
178
 
186
- function resolvePiRuntime(env = process.env, options = {}) {
187
- const configured = env.OMP_COMMAND || env.PI_COMMAND;
179
+ function resolveOmpRuntime(env = process.env, options = {}) {
180
+ const configured = env.OMP_COMMAND;
188
181
  if (configured) {
189
- const command = getPiCommand(env);
190
- const source = env.OMP_COMMAND ? 'OMP_COMMAND' : 'PI_COMMAND';
182
+ const command = getOmpCommand(env);
191
183
  return {
192
184
  command,
193
- runtime: command === LEGACY_PI_COMMAND ? 'pi' : 'omp',
185
+ runtime: 'omp',
194
186
  installed: commandExists(command, env, options),
195
187
  configured: true,
196
- commandSource: source
188
+ commandSource: 'OMP_COMMAND'
197
189
  };
198
190
  }
199
191
 
@@ -207,16 +199,6 @@ function resolvePiRuntime(env = process.env, options = {}) {
207
199
  };
208
200
  }
209
201
 
210
- if (commandExists(LEGACY_PI_COMMAND, env, options)) {
211
- return {
212
- command: LEGACY_PI_COMMAND,
213
- runtime: 'pi',
214
- installed: true,
215
- configured: false,
216
- commandSource: 'path'
217
- };
218
- }
219
-
220
202
  return {
221
203
  command: DEFAULT_OMP_COMMAND,
222
204
  runtime: 'omp',
@@ -226,12 +208,12 @@ function resolvePiRuntime(env = process.env, options = {}) {
226
208
  };
227
209
  }
228
210
 
229
- function isPiInstalled(env = process.env, options = {}) {
230
- const runtime = options.runtime || resolvePiRuntime(env, options);
211
+ function isOmpInstalled(env = process.env, options = {}) {
212
+ const runtime = options.runtime || resolveOmpRuntime(env, options);
231
213
  if (runtime.installed) {
232
214
  return true;
233
215
  }
234
- return fs.existsSync(getPiPaths(env, { ...options, runtime }).agentDir);
216
+ return fs.existsSync(getOmpPaths(env, { ...options, runtime }).agentDir);
235
217
  }
236
218
 
237
219
  function readTextFile(filePath, fallback = '') {
@@ -243,11 +225,11 @@ function readTextFile(filePath, fallback = '') {
243
225
  }
244
226
  }
245
227
 
246
- function getPiStatus(env = process.env, options = {}) {
247
- const runtime = resolvePiRuntime(env, options);
248
- const paths = getPiPaths(env, { ...options, runtime });
228
+ function getOmpStatus(env = process.env, options = {}) {
229
+ const runtime = resolveOmpRuntime(env, options);
230
+ const paths = getOmpPaths(env, { ...options, runtime });
249
231
  return {
250
- installed: isPiInstalled(env, { ...options, runtime }),
232
+ installed: isOmpInstalled(env, { ...options, runtime }),
251
233
  runtime: runtime.runtime,
252
234
  command: runtime.command,
253
235
  commandSource: runtime.commandSource,
@@ -269,19 +251,19 @@ function getPiStatus(env = process.env, options = {}) {
269
251
 
270
252
  module.exports = {
271
253
  expandHome,
272
- getPiAgentDir,
273
- getPiPaths,
274
- ensurePiDir,
254
+ getOmpAgentDir,
255
+ getOmpPaths,
256
+ ensureOmpDir,
275
257
  readJsonFile,
276
258
  readYamlFile,
277
259
  readTextFile,
278
260
  writeJsonFile,
279
261
  writeYamlFile,
280
- readPiSettings,
281
- writePiSettings,
282
- getPiCommand,
262
+ readOmpSettings,
263
+ writeOmpSettings,
264
+ getOmpCommand,
283
265
  getOmpProfile,
284
- resolvePiRuntime,
285
- isPiInstalled,
286
- getPiStatus
266
+ resolveOmpRuntime,
267
+ isOmpInstalled,
268
+ getOmpStatus
287
269
  };
@@ -2,10 +2,10 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const { execFileSync } = require('child_process');
4
4
  const { PATHS, HOME_DIR } = require('../../config/paths');
5
- const { getPiCommand, getPiPaths, isPiInstalled, resolvePiRuntime } = require('./pi-config');
5
+ const { getOmpCommand, getOmpPaths, isOmpInstalled, resolveOmpRuntime } = require('./omp-config');
6
6
 
7
- const PROJECT_ORDER_FILE = PATHS.piProjectOrder;
8
- const SESSION_ORDER_FILE = PATHS.piSessionOrder;
7
+ const PROJECT_ORDER_FILE = PATHS.ompProjectOrder;
8
+ const SESSION_ORDER_FILE = PATHS.ompSessionOrder;
9
9
 
10
10
  function ensureDir(dirPath) {
11
11
  if (!fs.existsSync(dirPath)) {
@@ -52,7 +52,7 @@ function getDisplayName(cwd = '') {
52
52
  return path.basename(normalized) || normalized;
53
53
  }
54
54
 
55
- function parsePiSessionId(filePath = '') {
55
+ function parseOmpSessionId(filePath = '') {
56
56
  const base = path.basename(filePath, '.jsonl');
57
57
  const match = base.match(/([0-9a-f]{8}-[0-9a-f-]{8,})$/i);
58
58
  if (match) return match[1];
@@ -138,7 +138,7 @@ function readJsonLines(filePath) {
138
138
  }
139
139
  }
140
140
 
141
- function convertPiEntry(entry = {}, index = 0) {
141
+ function convertOmpEntry(entry = {}, index = 0) {
142
142
  if (!entry || entry.type !== 'message') {
143
143
  return null;
144
144
  }
@@ -174,12 +174,12 @@ function parseSessionFile(filePath) {
174
174
  const stat = fs.statSync(filePath);
175
175
  const entries = readJsonLines(filePath);
176
176
  const header = entries.find(entry => entry?.type === 'session') || {};
177
- const messages = entries.map(convertPiEntry).filter(Boolean);
177
+ const messages = entries.map(convertOmpEntry).filter(Boolean);
178
178
  const modelChange = [...entries].reverse().find(entry => entry?.type === 'model_change');
179
179
  const firstUser = messages.find(message => message.type === 'user');
180
180
  const lastAssistant = [...messages].reverse().find(message => message.type === 'assistant') || {};
181
181
  const cwd = header.cwd || messages.find(message => message.cwd)?.cwd || path.dirname(filePath);
182
- const sessionId = header.id || parsePiSessionId(filePath);
182
+ const sessionId = header.id || parseOmpSessionId(filePath);
183
183
  const usage = messages.reduce((acc, message) => {
184
184
  if (message.type !== 'assistant') return acc;
185
185
  const current = parseUsage(message.usage || {});
@@ -207,11 +207,11 @@ function parseSessionFile(filePath) {
207
207
  mtime: new Date(stat.mtimeMs).toISOString(),
208
208
  mtimeMs: stat.mtimeMs,
209
209
  timestamp: header.timestamp || null,
210
- source: 'pi'
210
+ source: 'omp'
211
211
  };
212
212
  }
213
213
 
214
- function scanSessionFiles(rootDir = getPiPaths().sessions) {
214
+ function scanSessionFiles(rootDir = getOmpPaths().sessions) {
215
215
  if (!fs.existsSync(rootDir)) {
216
216
  return [];
217
217
  }
@@ -273,7 +273,7 @@ function getProjects() {
273
273
  latestSession: null,
274
274
  mtime: session.mtime,
275
275
  mtimeMs: 0,
276
- source: 'pi'
276
+ source: 'omp'
277
277
  };
278
278
  existing.sessionCount += 1;
279
279
  if ((session.mtimeMs || 0) > (existing.mtimeMs || 0)) {
@@ -324,7 +324,7 @@ function normalizeSession(session) {
324
324
  firstMessage: session.firstMessage || null,
325
325
  gitBranch: null,
326
326
  forkedFrom: null,
327
- source: 'pi',
327
+ source: 'omp',
328
328
  provider: session.provider || '',
329
329
  model: session.model || '',
330
330
  size: session.size || 0,
@@ -345,7 +345,7 @@ function getSessionMessages(sessionId) {
345
345
  if (!session) {
346
346
  throw new Error('Session not found');
347
347
  }
348
- return readJsonLines(session.filePath).map(convertPiEntry).filter(Boolean);
348
+ return readJsonLines(session.filePath).map(convertOmpEntry).filter(Boolean);
349
349
  }
350
350
 
351
351
  function getRecentSessions(limit = 5) {
@@ -359,7 +359,7 @@ function searchSessions(keyword, contextLength = 35, projectName = null) {
359
359
  return getAllSessions()
360
360
  .filter(session => !projectName || session.projectName === projectName)
361
361
  .map((session) => {
362
- const messages = readJsonLines(session.filePath).map(convertPiEntry).filter(Boolean);
362
+ const messages = readJsonLines(session.filePath).map(convertOmpEntry).filter(Boolean);
363
363
  const matches = [];
364
364
  messages.forEach((message) => {
365
365
  const text = String(message.content || '');
@@ -412,7 +412,7 @@ function forkSession(sessionId) {
412
412
  const forkId = `fork-${Date.now()}`;
413
413
  const targetPath = path.join(parsed.dir, `${parsed.name}-${forkId}${parsed.ext}`);
414
414
  fs.copyFileSync(session.filePath, targetPath);
415
- return { success: true, newSessionId: parsePiSessionId(targetPath), filePath: targetPath };
415
+ return { success: true, newSessionId: parseOmpSessionId(targetPath), filePath: targetPath };
416
416
  }
417
417
 
418
418
  function saveProjectOrder(order) {
@@ -446,19 +446,19 @@ function buildLaunchCommand(sessionId, cwd, options = {}) {
446
446
  } else {
447
447
  args.push('--session', shellQuote(sessionId));
448
448
  }
449
- return `${getPiCommand()} ${args.join(' ')}`;
449
+ return `${getOmpCommand()} ${args.join(' ')}`;
450
450
  }
451
451
 
452
452
  function shellQuote(value) {
453
453
  return `"${String(value).replace(/"/g, '\\"')}"`;
454
454
  }
455
455
 
456
- function isPiCliInstalled() {
457
- if (isPiInstalled()) return true;
458
- const runtime = resolvePiRuntime();
456
+ function isOmpCliInstalled() {
457
+ if (isOmpInstalled()) return true;
458
+ const runtime = resolveOmpRuntime();
459
459
  if (runtime.installed) return true;
460
460
  try {
461
- execFileSync(getPiCommand(), ['--version'], { stdio: 'ignore', timeout: 3000 });
461
+ execFileSync(getOmpCommand(), ['--version'], { stdio: 'ignore', timeout: 3000 });
462
462
  return true;
463
463
  } catch {
464
464
  return false;
@@ -479,7 +479,7 @@ module.exports = {
479
479
  getSessionById,
480
480
  getSessionMessages,
481
481
  getSessionsByProject,
482
- isPiInstalled: isPiCliInstalled,
482
+ isOmpInstalled: isOmpCliInstalled,
483
483
  normalizeSession,
484
484
  parseSessionFile,
485
485
  scanSessionFiles,