coding-tool-x 3.7.10 → 3.7.11
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/dist/web/assets/{Analytics-CkUtnoz9.js → Analytics-Ck_00Brj.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-BwPqhE-N.js → ConfigTemplates-Cpw2vUa8.js} +1 -1
- package/dist/web/assets/Home-Bft3Kztl.js +1 -0
- package/dist/web/assets/Home-CHZJkkjH.css +1 -0
- package/dist/web/assets/{PluginManager-JMXWl37b.js → PluginManager-2RlvEJCT.js} +1 -1
- package/dist/web/assets/{ProjectList-CZwDgVvt.js → ProjectList-_ecCngpl.js} +1 -1
- package/dist/web/assets/{SessionList-2fZmN7Au.js → SessionList-DlWcw3hO.js} +1 -1
- package/dist/web/assets/{SkillManager-Bhzhkeis.js → SkillManager-CnY7IXkX.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-B3lhhBD0.js → WorkspaceManager-3mqghi09.js} +1 -1
- package/dist/web/assets/{index-C5nLTbOk.css → index-BceXgSSe.css} +1 -1
- package/dist/web/assets/index-k5oP7c-A.js +2 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/commands/toggle-proxy.js +7 -8
- package/src/commands/ui.js +11 -1
- package/src/config/default.js +1 -1
- package/src/index.js +41 -15
- package/src/server/api/omp-channels.js +6 -4
- package/src/server/api/omp-config.js +1 -1
- package/src/server/api/omp-proxy.js +13 -42
- package/src/server/index.js +3 -3
- package/src/server/omp-proxy-server.js +129 -10
- package/src/server/services/channel-scheduler.js +59 -9
- package/src/server/services/omp-auth-gateway-client.js +62 -0
- package/src/server/services/omp-channels.js +109 -12
- package/src/server/services/omp-gateway-routing.js +295 -0
- package/src/server/services/omp-gateway.js +919 -0
- package/src/server/services/omp-session-log-observer.js +138 -0
- package/src/server/services/omp-sessions.js +80 -0
- package/src/server/services/omp-settings-manager.js +335 -86
- package/dist/web/assets/Home-BANl91zG.js +0 -1
- package/dist/web/assets/Home-CqnBXFxj.css +0 -1
- package/dist/web/assets/index-LYvv7wtx.js +0 -2
|
@@ -3,6 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const { spawnSync } = require('child_process');
|
|
4
4
|
const yaml = require('js-yaml');
|
|
5
5
|
const ompConfig = require('./omp-config');
|
|
6
|
+
const { prepareManagedOmpChannels } = require('./omp-gateway-routing');
|
|
6
7
|
const { MODEL_METADATA, MODEL_ALIASES } = require('../../config/model-metadata');
|
|
7
8
|
const {
|
|
8
9
|
MODEL_METADATA_MODES,
|
|
@@ -15,7 +16,7 @@ const {
|
|
|
15
16
|
|
|
16
17
|
const MANAGED_PROVIDER_PREFIX = 'ctx-';
|
|
17
18
|
const MODELS_BACKUP_MARKER = '.ctx-backup-';
|
|
18
|
-
const VISIBILITY_STATE_VERSION =
|
|
19
|
+
const VISIBILITY_STATE_VERSION = 2;
|
|
19
20
|
const MANAGED_VISIBILITY_STATE_FILE = 'coding-tool-x-omp-managed-visibility.json';
|
|
20
21
|
const NO_MANAGED_MODELS_SELECTOR = `${MANAGED_PROVIDER_PREFIX}coding-tool-x/__no_models_configured__`;
|
|
21
22
|
let lastManagedOmpSyncResult = null;
|
|
@@ -45,6 +46,12 @@ function normalizeProviderId(value = '') {
|
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
function getManagedProviderId(channel = {}) {
|
|
49
|
+
const explicitId = normalizeProviderId(channel.managedProviderId || '');
|
|
50
|
+
if (channel.managedProviderId) {
|
|
51
|
+
return explicitId.startsWith(MANAGED_PROVIDER_PREFIX)
|
|
52
|
+
? explicitId
|
|
53
|
+
: `${MANAGED_PROVIDER_PREFIX}${explicitId}`;
|
|
54
|
+
}
|
|
48
55
|
const baseId = normalizeProviderId(channel.providerKey || channel.provider || channel.name || channel.id);
|
|
49
56
|
return baseId.startsWith(MANAGED_PROVIDER_PREFIX) ? baseId : `${MANAGED_PROVIDER_PREFIX}${baseId}`;
|
|
50
57
|
}
|
|
@@ -116,6 +123,49 @@ function getOwnProperty(object, key) {
|
|
|
116
123
|
: false;
|
|
117
124
|
}
|
|
118
125
|
|
|
126
|
+
function cloneJson(value) {
|
|
127
|
+
if (value === undefined) return undefined;
|
|
128
|
+
return JSON.parse(JSON.stringify(value));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function captureFileSnapshots(filePaths = []) {
|
|
132
|
+
return filePaths.map((filePath) => ({
|
|
133
|
+
filePath,
|
|
134
|
+
existed: Boolean(filePath && fs.existsSync(filePath)),
|
|
135
|
+
content: filePath && fs.existsSync(filePath) ? fs.readFileSync(filePath) : null
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function restoreFileSnapshots(snapshots = []) {
|
|
140
|
+
snapshots.forEach((snapshot) => {
|
|
141
|
+
if (!snapshot.filePath) return;
|
|
142
|
+
if (snapshot.existed) {
|
|
143
|
+
ensureOmpDir(path.dirname(snapshot.filePath));
|
|
144
|
+
writeFileAtomic(snapshot.filePath, snapshot.content);
|
|
145
|
+
} else if (fs.existsSync(snapshot.filePath)) {
|
|
146
|
+
fs.unlinkSync(snapshot.filePath);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function writeFileAtomic(filePath, content) {
|
|
152
|
+
ensureOmpDir(path.dirname(filePath));
|
|
153
|
+
const temporaryPath = `${filePath}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
154
|
+
const mode = fs.existsSync(filePath)
|
|
155
|
+
? fs.statSync(filePath).mode & 0o777
|
|
156
|
+
: 0o600;
|
|
157
|
+
try {
|
|
158
|
+
fs.writeFileSync(temporaryPath, content, { mode });
|
|
159
|
+
fs.chmodSync(temporaryPath, mode);
|
|
160
|
+
fs.renameSync(temporaryPath, filePath);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (fs.existsSync(temporaryPath)) {
|
|
163
|
+
fs.unlinkSync(temporaryPath);
|
|
164
|
+
}
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
119
169
|
function normalizeModels(channel = {}, options = {}) {
|
|
120
170
|
const models = [];
|
|
121
171
|
const catalogIndex = options.catalogIndex instanceof Map ? options.catalogIndex : new Map();
|
|
@@ -277,13 +327,32 @@ function buildProviderEntry(channel = {}, options = {}) {
|
|
|
277
327
|
const providerName = channel.providerKey || channel.provider || channel.name || channel.id || 'provider';
|
|
278
328
|
options.warnings.push(...normalizedProvider.warnings.map(message => `${providerName}: ${message}`));
|
|
279
329
|
}
|
|
330
|
+
let models = normalizeModels(channel, { catalogIndex, warnings: options.warnings });
|
|
331
|
+
if (channel._ompGatewayRoute) {
|
|
332
|
+
models = models.map((model) => {
|
|
333
|
+
const sanitized = { ...model };
|
|
334
|
+
delete sanitized.baseUrl;
|
|
335
|
+
delete sanitized.headers;
|
|
336
|
+
return sanitized;
|
|
337
|
+
});
|
|
338
|
+
}
|
|
280
339
|
const entry = compactObject({
|
|
281
340
|
...normalizedProvider.config,
|
|
282
341
|
baseUrl: String(channel.baseUrl || providerConfig.baseUrl || '').trim(),
|
|
283
342
|
api: normalizeProviderApi(channel.providerApi || channel.api || channel.wireApi || providerConfig.api),
|
|
284
|
-
models
|
|
343
|
+
models
|
|
285
344
|
});
|
|
286
345
|
|
|
346
|
+
if (channel._ompGatewayRoute) {
|
|
347
|
+
delete entry.headers;
|
|
348
|
+
delete entry.apiKey;
|
|
349
|
+
if (channel.authMode === 'none') {
|
|
350
|
+
entry.auth = 'none';
|
|
351
|
+
} else {
|
|
352
|
+
delete entry.auth;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
287
356
|
const apiKey = String(channel.apiKey || providerConfig.apiKey || '').trim();
|
|
288
357
|
if (apiKey) {
|
|
289
358
|
entry.apiKey = apiKey;
|
|
@@ -321,7 +390,7 @@ function writeModelsConfig(config, filePath = getOmpPaths().modelsYml) {
|
|
|
321
390
|
noRefs: true,
|
|
322
391
|
sortKeys: false
|
|
323
392
|
});
|
|
324
|
-
|
|
393
|
+
writeFileAtomic(filePath, doc);
|
|
325
394
|
}
|
|
326
395
|
|
|
327
396
|
function getOmpSettingsPath(paths = getOmpPaths()) {
|
|
@@ -359,7 +428,7 @@ function writeOmpSettingsConfig(config, filePath = getOmpSettingsPath()) {
|
|
|
359
428
|
noRefs: true,
|
|
360
429
|
sortKeys: false
|
|
361
430
|
});
|
|
362
|
-
|
|
431
|
+
writeFileAtomic(filePath, doc);
|
|
363
432
|
}
|
|
364
433
|
|
|
365
434
|
function getModelsBackupPrefix(filePath) {
|
|
@@ -420,7 +489,7 @@ function readManagedVisibilityState(paths = getOmpPaths()) {
|
|
|
420
489
|
function writeManagedVisibilityState(state, paths = getOmpPaths()) {
|
|
421
490
|
const filePath = getManagedVisibilityStatePath(paths);
|
|
422
491
|
ensureOmpDir(path.dirname(filePath));
|
|
423
|
-
|
|
492
|
+
writeFileAtomic(filePath, `${JSON.stringify(state, null, 2)}\n`);
|
|
424
493
|
return filePath;
|
|
425
494
|
}
|
|
426
495
|
|
|
@@ -602,6 +671,9 @@ function buildManagedModelsConfig(channels = [], baseConfig = readModelsConfig()
|
|
|
602
671
|
}
|
|
603
672
|
|
|
604
673
|
function getOriginalProviderId(channel = {}) {
|
|
674
|
+
if (channel.originalProviderId) {
|
|
675
|
+
return normalizeProviderId(channel.originalProviderId);
|
|
676
|
+
}
|
|
605
677
|
const providerId = normalizeProviderId(channel.providerKey || channel.provider || channel.name || channel.id);
|
|
606
678
|
return isManagedProviderId(providerId)
|
|
607
679
|
? providerId.slice(MANAGED_PROVIDER_PREFIX.length)
|
|
@@ -679,11 +751,18 @@ function captureOriginalVisibility(settings = {}) {
|
|
|
679
751
|
const modelRoles = settings.modelRoles && typeof settings.modelRoles === 'object' && !Array.isArray(settings.modelRoles)
|
|
680
752
|
? settings.modelRoles
|
|
681
753
|
: {};
|
|
754
|
+
const fallbackChains = settings.retry && typeof settings.retry === 'object' && !Array.isArray(settings.retry)
|
|
755
|
+
? settings.retry.fallbackChains
|
|
756
|
+
: undefined;
|
|
682
757
|
return {
|
|
683
758
|
enabledModels: getOwnProperty(settings, 'enabledModels') ? uniqueStrings(settings.enabledModels) : null,
|
|
684
759
|
disabledProviders: getOwnProperty(settings, 'disabledProviders') ? uniqueStrings(settings.disabledProviders) : null,
|
|
685
760
|
modelRolesHadDefault: getOwnProperty(modelRoles, 'default'),
|
|
686
|
-
modelRolesDefault: getOwnProperty(modelRoles, 'default') ? String(modelRoles.default || '') : null
|
|
761
|
+
modelRolesDefault: getOwnProperty(modelRoles, 'default') ? String(modelRoles.default || '') : null,
|
|
762
|
+
modelRolesHadValue: getOwnProperty(settings, 'modelRoles'),
|
|
763
|
+
modelRoles: getOwnProperty(settings, 'modelRoles') ? cloneJson(modelRoles) : null,
|
|
764
|
+
retryFallbackChainsHadValue: fallbackChains !== undefined,
|
|
765
|
+
retryFallbackChains: fallbackChains !== undefined ? cloneJson(fallbackChains) : null
|
|
687
766
|
};
|
|
688
767
|
}
|
|
689
768
|
|
|
@@ -701,22 +780,86 @@ function collectUserDisabledProviders(settings = {}, previousState = null) {
|
|
|
701
780
|
return uniqueStrings([...originalDisabled, ...userAddedDuringManagedMode]);
|
|
702
781
|
}
|
|
703
782
|
|
|
704
|
-
function
|
|
705
|
-
const
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
783
|
+
function buildProviderMappings(channels = []) {
|
|
784
|
+
const originalToManaged = {};
|
|
785
|
+
const managedToOriginal = {};
|
|
786
|
+
channels.forEach((channel) => {
|
|
787
|
+
const original = getOriginalProviderId(channel);
|
|
788
|
+
const managed = getManagedProviderId(channel);
|
|
789
|
+
if (!original || !managed) return;
|
|
790
|
+
if (!originalToManaged[original]) {
|
|
791
|
+
originalToManaged[original] = managed;
|
|
792
|
+
}
|
|
793
|
+
managedToOriginal[managed] = original;
|
|
794
|
+
});
|
|
795
|
+
return { originalToManaged, managedToOriginal };
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
function rewriteModelSelector(value, providerMap = {}) {
|
|
799
|
+
if (typeof value !== 'string') return value;
|
|
800
|
+
const index = value.indexOf('/');
|
|
801
|
+
if (index <= 0) return value;
|
|
802
|
+
const providerId = value.slice(0, index);
|
|
803
|
+
const replacement = providerMap[providerId];
|
|
804
|
+
return replacement ? `${replacement}${value.slice(index)}` : value;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
function rewriteSelectorTree(value, providerMap = {}) {
|
|
808
|
+
if (typeof value === 'string') return rewriteModelSelector(value, providerMap);
|
|
809
|
+
if (Array.isArray(value)) return value.map(item => rewriteSelectorTree(item, providerMap));
|
|
810
|
+
if (value && typeof value === 'object') {
|
|
811
|
+
return Object.fromEntries(
|
|
812
|
+
Object.entries(value).map(([key, item]) => [key, rewriteSelectorTree(item, providerMap)])
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
return value;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
function removeManagedSelectorTree(value) {
|
|
819
|
+
if (typeof value === 'string') {
|
|
820
|
+
const providerId = String(value).split('/')[0];
|
|
821
|
+
return isManagedProviderId(providerId) ? undefined : value;
|
|
822
|
+
}
|
|
823
|
+
if (Array.isArray(value)) {
|
|
824
|
+
return value
|
|
825
|
+
.map(removeManagedSelectorTree)
|
|
826
|
+
.filter(item => item !== undefined);
|
|
827
|
+
}
|
|
828
|
+
if (value && typeof value === 'object') {
|
|
829
|
+
return Object.fromEntries(
|
|
830
|
+
Object.entries(value)
|
|
831
|
+
.map(([key, item]) => [key, removeManagedSelectorTree(item)])
|
|
832
|
+
.filter(([, item]) => item !== undefined)
|
|
833
|
+
);
|
|
712
834
|
}
|
|
713
|
-
|
|
714
|
-
|
|
835
|
+
return value;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
function applyManagedModelRoles(settings, visibility, mappings, previousState = null) {
|
|
839
|
+
const originalRoles = previousState?.active && previousState.original?.modelRolesHadValue
|
|
840
|
+
? previousState.original.modelRoles
|
|
841
|
+
: settings.modelRoles;
|
|
842
|
+
const roles = originalRoles && typeof originalRoles === 'object' && !Array.isArray(originalRoles)
|
|
843
|
+
? rewriteSelectorTree(cloneJson(originalRoles), mappings.originalToManaged)
|
|
844
|
+
: {};
|
|
845
|
+
const originalDefault = String(originalRoles?.default || '');
|
|
846
|
+
const mappedDefault = rewriteModelSelector(originalDefault, mappings.originalToManaged);
|
|
847
|
+
const defaultWasMapped = originalDefault && mappedDefault !== originalDefault;
|
|
848
|
+
const defaultIsManaged = isManagedProviderId(String(roles.default || '').split('/')[0]);
|
|
849
|
+
if (visibility.managedDefaultModel && (!roles.default || (!defaultWasMapped && !defaultIsManaged))) {
|
|
715
850
|
roles.default = visibility.managedDefaultModel;
|
|
716
851
|
}
|
|
717
852
|
return roles;
|
|
718
853
|
}
|
|
719
854
|
|
|
855
|
+
function applyManagedFallbackChains(settings, mappings, previousState = null) {
|
|
856
|
+
const source = previousState?.active && previousState.original?.retryFallbackChainsHadValue
|
|
857
|
+
? previousState.original.retryFallbackChains
|
|
858
|
+
: settings.retry?.fallbackChains;
|
|
859
|
+
if (source === undefined) return undefined;
|
|
860
|
+
return rewriteSelectorTree(cloneJson(source), mappings.originalToManaged);
|
|
861
|
+
}
|
|
862
|
+
|
|
720
863
|
function syncManagedOmpVisibility(channels = [], modelsConfig = { providers: {} }, options = {}) {
|
|
721
864
|
const paths = getOmpPaths();
|
|
722
865
|
const settingsPath = getOmpSettingsPath(paths);
|
|
@@ -724,6 +867,7 @@ function syncManagedOmpVisibility(channels = [], modelsConfig = { providers: {}
|
|
|
724
867
|
const settings = readOmpSettingsConfig(settingsPath);
|
|
725
868
|
const previousState = readManagedVisibilityState(paths);
|
|
726
869
|
const visibility = collectManagedVisibility(channels, modelsConfig, options);
|
|
870
|
+
const mappings = buildProviderMappings(channels);
|
|
727
871
|
const original = previousState?.active && previousState.original
|
|
728
872
|
? previousState.original
|
|
729
873
|
: captureOriginalVisibility(settings);
|
|
@@ -735,7 +879,13 @@ function syncManagedOmpVisibility(channels = [], modelsConfig = { providers: {}
|
|
|
735
879
|
...collectUserDisabledProviders(settings, previousState),
|
|
736
880
|
...visibility.managedDisabledProviders
|
|
737
881
|
]);
|
|
738
|
-
settings.modelRoles =
|
|
882
|
+
settings.modelRoles = applyManagedModelRoles(settings, visibility, mappings, previousState);
|
|
883
|
+
const fallbackChains = applyManagedFallbackChains(settings, mappings, previousState);
|
|
884
|
+
if (fallbackChains !== undefined) {
|
|
885
|
+
settings.retry = settings.retry && typeof settings.retry === 'object' && !Array.isArray(settings.retry)
|
|
886
|
+
? { ...settings.retry, fallbackChains }
|
|
887
|
+
: { fallbackChains };
|
|
888
|
+
}
|
|
739
889
|
|
|
740
890
|
const after = JSON.stringify(settings);
|
|
741
891
|
if (before !== after) {
|
|
@@ -750,7 +900,12 @@ function syncManagedOmpVisibility(channels = [], modelsConfig = { providers: {}
|
|
|
750
900
|
managedEnabledModelsForSettings: visibility.managedEnabledModelsForSettings,
|
|
751
901
|
managedDisabledProviders: visibility.managedDisabledProviders,
|
|
752
902
|
managedDefaultModel: visibility.managedDefaultModel,
|
|
903
|
+
providerMappings: mappings,
|
|
753
904
|
original,
|
|
905
|
+
applied: {
|
|
906
|
+
modelRoles: cloneJson(settings.modelRoles),
|
|
907
|
+
retryFallbackChains: cloneJson(settings.retry?.fallbackChains)
|
|
908
|
+
},
|
|
754
909
|
updatedAt: new Date().toISOString()
|
|
755
910
|
};
|
|
756
911
|
writeManagedVisibilityState(state, paths);
|
|
@@ -819,7 +974,39 @@ function removeManagedOmpVisibility(options = {}) {
|
|
|
819
974
|
warnings.push('OMP disabledProviders was changed while coding-tool-x managed visibility was active; removed only managed provider entries.');
|
|
820
975
|
}
|
|
821
976
|
|
|
822
|
-
if (
|
|
977
|
+
if (state.version >= 2 && state.original) {
|
|
978
|
+
const currentRoles = settings.modelRoles && typeof settings.modelRoles === 'object' && !Array.isArray(settings.modelRoles)
|
|
979
|
+
? settings.modelRoles
|
|
980
|
+
: undefined;
|
|
981
|
+
if (JSON.stringify(currentRoles) === JSON.stringify(state.applied?.modelRoles)) {
|
|
982
|
+
if (state.original.modelRolesHadValue) {
|
|
983
|
+
settings.modelRoles = cloneJson(state.original.modelRoles);
|
|
984
|
+
} else {
|
|
985
|
+
delete settings.modelRoles;
|
|
986
|
+
}
|
|
987
|
+
} else if (currentRoles) {
|
|
988
|
+
settings.modelRoles = rewriteSelectorTree(currentRoles, state.providerMappings?.managedToOriginal || {});
|
|
989
|
+
warnings.push('OMP modelRoles was changed while coding-tool-x managed visibility was active; restored managed provider references only.');
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
const currentFallback = settings.retry?.fallbackChains;
|
|
993
|
+
if (JSON.stringify(currentFallback) === JSON.stringify(state.applied?.retryFallbackChains)) {
|
|
994
|
+
if (state.original.retryFallbackChainsHadValue) {
|
|
995
|
+
settings.retry = settings.retry && typeof settings.retry === 'object' && !Array.isArray(settings.retry)
|
|
996
|
+
? { ...settings.retry, fallbackChains: cloneJson(state.original.retryFallbackChains) }
|
|
997
|
+
: { fallbackChains: cloneJson(state.original.retryFallbackChains) };
|
|
998
|
+
} else if (settings.retry && typeof settings.retry === 'object' && !Array.isArray(settings.retry)) {
|
|
999
|
+
delete settings.retry.fallbackChains;
|
|
1000
|
+
if (Object.keys(settings.retry).length === 0) delete settings.retry;
|
|
1001
|
+
}
|
|
1002
|
+
} else if (currentFallback !== undefined) {
|
|
1003
|
+
settings.retry.fallbackChains = rewriteSelectorTree(
|
|
1004
|
+
currentFallback,
|
|
1005
|
+
state.providerMappings?.managedToOriginal || {}
|
|
1006
|
+
);
|
|
1007
|
+
warnings.push('OMP retry.fallbackChains was changed while coding-tool-x managed visibility was active; restored managed provider references only.');
|
|
1008
|
+
}
|
|
1009
|
+
} else if (settings.modelRoles && typeof settings.modelRoles === 'object' && !Array.isArray(settings.modelRoles)) {
|
|
823
1010
|
const roles = { ...settings.modelRoles };
|
|
824
1011
|
if (roles.default === state.managedDefaultModel) {
|
|
825
1012
|
if (state.original?.modelRolesHadDefault) {
|
|
@@ -845,6 +1032,39 @@ function removeManagedOmpVisibility(options = {}) {
|
|
|
845
1032
|
}
|
|
846
1033
|
warnings.push('Removed stale coding-tool-x managed OMP enabledModels entries without a visibility state file.');
|
|
847
1034
|
}
|
|
1035
|
+
|
|
1036
|
+
if (settings.modelRoles && typeof settings.modelRoles === 'object' && !Array.isArray(settings.modelRoles)) {
|
|
1037
|
+
const roles = Object.fromEntries(
|
|
1038
|
+
Object.entries(settings.modelRoles).filter(([, model]) => {
|
|
1039
|
+
const providerId = String(model || '').split('/')[0];
|
|
1040
|
+
return !isManagedProviderId(providerId);
|
|
1041
|
+
})
|
|
1042
|
+
);
|
|
1043
|
+
if (Object.keys(roles).length !== Object.keys(settings.modelRoles).length) {
|
|
1044
|
+
settingsBackupPath = settingsBackupPath || createModelsBackupIfNeeded(settingsPath, options);
|
|
1045
|
+
if (Object.keys(roles).length > 0) {
|
|
1046
|
+
settings.modelRoles = roles;
|
|
1047
|
+
} else {
|
|
1048
|
+
delete settings.modelRoles;
|
|
1049
|
+
}
|
|
1050
|
+
warnings.push('Removed stale coding-tool-x managed OMP modelRoles entries without a visibility state file.');
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
const currentFallback = settings.retry?.fallbackChains;
|
|
1055
|
+
if (currentFallback !== undefined) {
|
|
1056
|
+
const fallbackChains = removeManagedSelectorTree(currentFallback);
|
|
1057
|
+
if (JSON.stringify(fallbackChains) !== JSON.stringify(currentFallback)) {
|
|
1058
|
+
settingsBackupPath = settingsBackupPath || createModelsBackupIfNeeded(settingsPath, options);
|
|
1059
|
+
if (fallbackChains && typeof fallbackChains === 'object' && Object.keys(fallbackChains).length > 0) {
|
|
1060
|
+
settings.retry.fallbackChains = fallbackChains;
|
|
1061
|
+
} else {
|
|
1062
|
+
delete settings.retry.fallbackChains;
|
|
1063
|
+
if (Object.keys(settings.retry).length === 0) delete settings.retry;
|
|
1064
|
+
}
|
|
1065
|
+
warnings.push('Removed stale coding-tool-x managed OMP retry.fallbackChains entries without a visibility state file.');
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
848
1068
|
}
|
|
849
1069
|
|
|
850
1070
|
const after = JSON.stringify(settings);
|
|
@@ -865,81 +1085,110 @@ function removeManagedOmpVisibility(options = {}) {
|
|
|
865
1085
|
|
|
866
1086
|
function writeManagedOmpProviders(channels = [], options = {}) {
|
|
867
1087
|
const paths = getOmpPaths();
|
|
1088
|
+
const settingsPath = getOmpSettingsPath(paths);
|
|
1089
|
+
const statePath = getManagedVisibilityStatePath(paths);
|
|
1090
|
+
const snapshots = captureFileSnapshots([paths.modelsYml, settingsPath, statePath]);
|
|
868
1091
|
const buildWarnings = [];
|
|
869
|
-
const
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
const
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
...(visibility.warnings || []),
|
|
882
|
-
...(validation.warnings || [])
|
|
883
|
-
];
|
|
884
|
-
recordManagedOmpSyncResult({
|
|
885
|
-
path: paths.modelsYml,
|
|
886
|
-
modelsPath: paths.modelsYml,
|
|
887
|
-
settingsPath: visibility.settingsPath,
|
|
888
|
-
statePath: visibility.statePath,
|
|
889
|
-
backupPath,
|
|
890
|
-
modelsBackupPath: backupPath,
|
|
891
|
-
settingsBackupPath: visibility.settingsBackupPath,
|
|
892
|
-
changed: true,
|
|
893
|
-
visibilityChanged: visibility.changed,
|
|
894
|
-
managedEnabledModels: visibility.managedEnabledModels,
|
|
895
|
-
managedEnabledModelsForSettings: visibility.managedEnabledModelsForSettings,
|
|
896
|
-
managedDisabledProviders: visibility.managedDisabledProviders,
|
|
897
|
-
managedDefaultModel: visibility.managedDefaultModel,
|
|
898
|
-
validation,
|
|
899
|
-
warnings
|
|
1092
|
+
const orderedChannels = options.activeChannelId
|
|
1093
|
+
? [
|
|
1094
|
+
...channels.filter(channel => channel?.id === options.activeChannelId),
|
|
1095
|
+
...channels.filter(channel => channel?.id !== options.activeChannelId)
|
|
1096
|
+
]
|
|
1097
|
+
: channels;
|
|
1098
|
+
const prepared = options.gateway
|
|
1099
|
+
? prepareManagedOmpChannels(orderedChannels, options.gateway)
|
|
1100
|
+
: { managedChannels: orderedChannels, unsupportedChannels: [] };
|
|
1101
|
+
const effectiveChannels = prepared.managedChannels;
|
|
1102
|
+
prepared.unsupportedChannels.forEach((channel) => {
|
|
1103
|
+
buildWarnings.push(`OMP channel "${channel.name || channel.id}" was not managed: ${channel.reason}.`);
|
|
900
1104
|
});
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
const config = readModelsConfig(paths.modelsYml);
|
|
908
|
-
const visibility = removeManagedOmpVisibility(options);
|
|
909
|
-
const before = Object.keys(config.providers || {}).length;
|
|
910
|
-
pruneManagedProviders(config.providers);
|
|
911
|
-
const after = Object.keys(config.providers || {}).length;
|
|
912
|
-
let backupPath = null;
|
|
913
|
-
let validation = {
|
|
914
|
-
skipped: true,
|
|
915
|
-
reason: before === after ? 'no-managed-providers' : 'not-run',
|
|
916
|
-
warnings: []
|
|
917
|
-
};
|
|
918
|
-
if (before !== after) {
|
|
919
|
-
backupPath = createModelsBackupIfNeeded(paths.modelsYml, options);
|
|
1105
|
+
try {
|
|
1106
|
+
const config = buildManagedModelsConfig(effectiveChannels, readModelsConfig(paths.modelsYml), {
|
|
1107
|
+
...options,
|
|
1108
|
+
warnings: buildWarnings
|
|
1109
|
+
});
|
|
1110
|
+
const backupPath = createModelsBackupIfNeeded(paths.modelsYml, options);
|
|
920
1111
|
writeModelsConfig(config, paths.modelsYml);
|
|
921
|
-
|
|
1112
|
+
const visibility = syncManagedOmpVisibility(effectiveChannels, config, options);
|
|
1113
|
+
const validation = options.validateWithCli === true
|
|
922
1114
|
? validateOmpModelsConfig(options)
|
|
923
1115
|
: { skipped: true, reason: 'cli-validation-disabled', warnings: [] };
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
path: paths.modelsYml,
|
|
927
|
-
modelsPath: paths.modelsYml,
|
|
928
|
-
settingsPath: visibility.settingsPath,
|
|
929
|
-
statePath: visibility.statePath,
|
|
930
|
-
backupPath,
|
|
931
|
-
modelsBackupPath: backupPath,
|
|
932
|
-
settingsBackupPath: visibility.settingsBackupPath,
|
|
933
|
-
changed: before !== after,
|
|
934
|
-
visibilityChanged: visibility.changed,
|
|
935
|
-
stateRemoved: visibility.stateRemoved,
|
|
936
|
-
validation,
|
|
937
|
-
warnings: [
|
|
1116
|
+
const warnings = [
|
|
1117
|
+
...buildWarnings,
|
|
938
1118
|
...(visibility.warnings || []),
|
|
939
1119
|
...(validation.warnings || [])
|
|
940
|
-
]
|
|
941
|
-
|
|
942
|
-
|
|
1120
|
+
];
|
|
1121
|
+
recordManagedOmpSyncResult({
|
|
1122
|
+
path: paths.modelsYml,
|
|
1123
|
+
modelsPath: paths.modelsYml,
|
|
1124
|
+
settingsPath: visibility.settingsPath,
|
|
1125
|
+
statePath: visibility.statePath,
|
|
1126
|
+
backupPath,
|
|
1127
|
+
modelsBackupPath: backupPath,
|
|
1128
|
+
settingsBackupPath: visibility.settingsBackupPath,
|
|
1129
|
+
changed: true,
|
|
1130
|
+
visibilityChanged: visibility.changed,
|
|
1131
|
+
managedEnabledModels: visibility.managedEnabledModels,
|
|
1132
|
+
managedEnabledModelsForSettings: visibility.managedEnabledModelsForSettings,
|
|
1133
|
+
managedDisabledProviders: visibility.managedDisabledProviders,
|
|
1134
|
+
managedDefaultModel: visibility.managedDefaultModel,
|
|
1135
|
+
validation,
|
|
1136
|
+
warnings
|
|
1137
|
+
});
|
|
1138
|
+
removeLegacyManagedExtension(paths);
|
|
1139
|
+
return paths.modelsYml;
|
|
1140
|
+
} catch (error) {
|
|
1141
|
+
restoreFileSnapshots(snapshots);
|
|
1142
|
+
throw error;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
function removeManagedOmpProviders(options = {}) {
|
|
1147
|
+
const paths = getOmpPaths();
|
|
1148
|
+
const settingsPath = getOmpSettingsPath(paths);
|
|
1149
|
+
const statePath = getManagedVisibilityStatePath(paths);
|
|
1150
|
+
const snapshots = captureFileSnapshots([paths.modelsYml, settingsPath, statePath]);
|
|
1151
|
+
try {
|
|
1152
|
+
const config = readModelsConfig(paths.modelsYml);
|
|
1153
|
+
const visibility = removeManagedOmpVisibility(options);
|
|
1154
|
+
const before = Object.keys(config.providers || {}).length;
|
|
1155
|
+
pruneManagedProviders(config.providers);
|
|
1156
|
+
const after = Object.keys(config.providers || {}).length;
|
|
1157
|
+
let backupPath = null;
|
|
1158
|
+
let validation = {
|
|
1159
|
+
skipped: true,
|
|
1160
|
+
reason: before === after ? 'no-managed-providers' : 'not-run',
|
|
1161
|
+
warnings: []
|
|
1162
|
+
};
|
|
1163
|
+
if (before !== after) {
|
|
1164
|
+
backupPath = createModelsBackupIfNeeded(paths.modelsYml, options);
|
|
1165
|
+
writeModelsConfig(config, paths.modelsYml);
|
|
1166
|
+
validation = options.validateWithCli === true
|
|
1167
|
+
? validateOmpModelsConfig(options)
|
|
1168
|
+
: { skipped: true, reason: 'cli-validation-disabled', warnings: [] };
|
|
1169
|
+
}
|
|
1170
|
+
recordManagedOmpSyncResult({
|
|
1171
|
+
path: paths.modelsYml,
|
|
1172
|
+
modelsPath: paths.modelsYml,
|
|
1173
|
+
settingsPath: visibility.settingsPath,
|
|
1174
|
+
statePath: visibility.statePath,
|
|
1175
|
+
backupPath,
|
|
1176
|
+
modelsBackupPath: backupPath,
|
|
1177
|
+
settingsBackupPath: visibility.settingsBackupPath,
|
|
1178
|
+
changed: before !== after,
|
|
1179
|
+
visibilityChanged: visibility.changed,
|
|
1180
|
+
stateRemoved: visibility.stateRemoved,
|
|
1181
|
+
validation,
|
|
1182
|
+
warnings: [
|
|
1183
|
+
...(visibility.warnings || []),
|
|
1184
|
+
...(validation.warnings || [])
|
|
1185
|
+
]
|
|
1186
|
+
});
|
|
1187
|
+
removeLegacyManagedExtension(paths);
|
|
1188
|
+
} catch (error) {
|
|
1189
|
+
restoreFileSnapshots(snapshots);
|
|
1190
|
+
throw error;
|
|
1191
|
+
}
|
|
943
1192
|
}
|
|
944
1193
|
|
|
945
1194
|
function isManagedOmpProvidersActive() {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{d as e}from"./vendors-DQA4Hw9v.js";import{r as a,a8 as l,f as n,w as s,h as c,K as t,a7 as o,c as i,o as u,a as r,W as d,a0 as v,X as p,Y as h,N as y,a3 as m,_ as g,p as f,R as k,L as T,F as C,$ as b,Z as w,v as x}from"./vue-vendor-B5RqjEjQ.js";import{g as $,u as _,a as S,s as z,D as q,_ as P,b as j,c as L,d as M,R as I,e as O,f as E,h as N,i as F,j as A,n as D}from"./index-LYvv7wtx.js";import{h as U,ar as J,E as V,P as R,as as K,at as B,au as Z,av as G,aa as H,i as W,A as X,aw as Y,ax as Q,T as ee,a as ae,b as le}from"./icons-nGdSKQn2.js";import{L as ne,N as se,B as ce,s as te,b as oe,c as ie,a as ue,Z as re}from"./naive-ui-BALVpMgd.js";import"./markdown-BNJfEgCA.js";const de=a({theme:"light",panelVisibility:{showChannels:!0,showLogs:!0},channelBalance:{showRemaining:!1},channelLocks:{claude:!1,codex:!1,gemini:!1,opencode:!1,omp:!1},channelCollapse:{claude:[],codex:[],gemini:[],opencode:[],omp:[]},channelOrder:{claude:[],codex:[],gemini:[],opencode:[],omp:[]},dashboardChannelOrder:q,homeCliColumns:q,customCliPlatforms:[]});let ve=!1,pe=null;async function he(){return ve?de.value:pe||(pe=(async()=>{try{const e=await $();e.success&&e.config&&(de.value=e.config,ve=!0)}catch(e){}finally{pe=null}return de.value})(),pe)}function ye(){return ve||he(),{uiConfig:de,loadUIConfig:he,saveConfig:async function(e){try{const a=await z(e);return!!a.success&&(de.value=a.config,!0)}catch(a){return!1}},updateConfig:async function(e,a){try{const l=await S(e,a);return!!l.success&&(de.value=l.config,!0)}catch(l){return!1}},updateNestedConfig:async function(e,a,l){try{const n=await _(e,a,l);return!!n.success&&(de.value=n.config,!0)}catch(n){return!1}}}}const me={class:"channel-column"},ge={class:"drag-handle",title:"拖拽排序"},fe={class:"header-icon"},ke={class:"channel-title"},Te={key:0,class:"claude-extra-area"},Ce={key:0,class:"channel-content"},be={key:0,class:"card"},we={class:"card-header"},xe={key:0,class:"runtime-badge"},$e={class:"card-body",style:{padding:"6px 10px"}},_e={class:"proxy-info-row"},Se={class:"proxy-status"},ze={class:"proxy-port"},qe={class:"channel-name"},Pe={class:"channel-quick-panel"},je={class:"panel-title"},Le={key:0,class:"no-channels"},Me={key:1,class:"channel-quick-list"},Ie={class:"channel-quick-info"},Oe={class:"channel-quick-name"},Ee={key:0,class:"channel-switching-tip"},Ne={class:"channel-metrics"},Fe={class:"metric-item"},Ae={class:"metric-value"},De={class:"metric-item"},Ue={class:"metric-value"},Je={class:"metric-item"},Ve={class:"metric-value"},Re={class:"metric-item"},Ke={class:"card"},Be={class:"card-header compact"},Ze={class:"card-body",style:{padding:"8px 10px"}},Ge={class:"quick-access-list"},He={class:"access-icon"},We={class:"access-content"},Xe={class:"access-value"},Ye={class:"access-icon"},Qe={class:"access-content"},ea={class:"access-value"},aa={class:"access-icon"},la={class:"access-content"},na={class:"access-goto"},sa={class:"card-header compact"},ca={class:"card-body",style:{padding:"8px 10px"}},ta={class:"stats-inline stats-3col"},oa={class:"stat-inline-item stat-requests"},ia={class:"stat-info"},ua={class:"stat-inline-item stat-input"},ra={class:"stat-info"},da={class:"stat-inline-item stat-output"},va={class:"stat-info"},pa={key:2,class:"card logs-card"},ha={class:"card-header compact"},ya={class:"card-body logs-card-body"},ma={class:"logs-table-wrapper"},ga={key:0,class:"empty-logs"},fa=["title"],ka={key:0,class:"action-content"},Ta={class:"action-msg"},Ca={class:"action-time"},ba={key:1,class:"action-content"},wa={class:"action-msg error-msg"},xa={class:"action-time error-time"},$a={class:"locked-content"},_a={class:"lock-icon"},Sa="channelLocks",za=P({__name:"ChannelColumn",props:{channelType:{type:String,required:!0}},setup(e){const S=e,z=l(),q=ne(),{uiConfig:P}=ye(),{claudeProxy:D,codexProxy:de,geminiProxy:ve,opencodeProxy:pe,ompProxy:he,claudeChannels:za,codexChannels:qa,geminiChannels:Pa,opencodeChannels:ja,ompChannels:La,schedulerState:Ma,getProxyState:Ia,startProxy:Oa,stopProxy:Ea,getLogs:Na,clearLogsForSource:Fa,loadChannels:Aa,logLimit:Da,statsInterval:Ua}=j(),{dashboardData:Ja,loadDashboard:Va}=L(),Ra=n(()=>M(S.channelType,P.value.customCliPlatforms)),Ka=n(()=>Ra.value.title||Ra.value.label||S.channelType),Ba=n(()=>Ra.value.icon||U),Za=n(()=>Ra.value.color||"#64748b"),Ga=n(()=>"claude"===S.channelType?D.value:"codex"===S.channelType?de.value:"gemini"===S.channelType?ve.value:"opencode"===S.channelType?pe.value:"omp"===S.channelType?he.value:Ra.value.custom?{running:!1,loading:!1,activeChannel:null,port:null,runtime:null,startTime:null}:{}),Ha=n(()=>"claude"===S.channelType?"Claude":"codex"===S.channelType?"Codex":"gemini"===S.channelType?"Gemini":"opencode"===S.channelType?"OpenCode":"omp"===S.channelType?"OMP":Ra.value.label||S.channelType),Wa=a({projects:0,sessions:0}),Xa=a({requests:0,tokens:0,cost:0}),Ya=a({requests:0,tokens:0,cost:0}),Qa={requests:0,tokens:0,cost:3};let el={requests:null,tokens:null,cost:null};const al=a({requests:!1,tokens:!1,cost:!1}),ll=n(()=>{var e,a,l;return(null==(l=null==(a=null==(e=Ja.value)?void 0:e.todayStats)?void 0:a[S.channelType])?void 0:l.byModel)||{}});function nl(e,a,l,n=600){el[e]&&cancelAnimationFrame(el[e]),al.value[e]=!0;const s=Date.now(),c=()=>{const t=Date.now()-s,o=Math.min(t/n,1),i=1-Math.pow(1-o,2),u=a+(l-a)*i,r=Qa[e]??0,d=Math.pow(10,r),v=r>0?Math.round(u*d)/d:Math.round(u);Ya.value[e]=v,o<1?el[e]=requestAnimationFrame(c):al.value[e]=!1};el[e]=requestAnimationFrame(c)}const sl=a(!1),cl={claude:"claudeChannelCollapse",codex:"codexChannelCollapse",gemini:"geminiChannelCollapse",opencode:"opencodeChannelCollapse",omp:"ompChannelCollapse"};function tl(e){try{const a=localStorage.getItem(Sa),l=a?JSON.parse(a):{};l[S.channelType]=e,localStorage.setItem(Sa,JSON.stringify(l))}catch(a){}}const ol=a(function(){try{const e=localStorage.getItem(Sa);if(e){return JSON.parse(e)[S.channelType]||!1}}catch(e){}return!1}());async function il(){ol.value=!ol.value,tl(ol.value);try{if(await _("channelLocks",S.channelType,ol.value),Ja.value){const e=Ja.value.uiConfig||{},a={...e.channelLocks||{}};a[S.channelType]=ol.value,Ja.value={...Ja.value,uiConfig:{...e,channelLocks:a}}}}catch(e){}}const ul=a(!0);function rl(e){e.detail&&void 0!==e.detail.showLogs&&(ul.value=e.detail.showLogs)}const dl=a(Date.now()),vl=n(()=>{if(!Ga.value.running)return"";const e=Ga.value.startTime;if(!e)return"";const a=dl.value-e;if(a<=0)return"";const l=Math.floor(a/1e3),n=Math.floor(l/3600),s=Math.floor(l%3600/60),c=l%60;let t="已运行 ";return n>0&&(t+=`${n}小时`),s>0&&(t+=`${s}分`),(c>0||0===n&&0===s)&&(t+=`${c}秒`),t}),pl=a(null),hl=n(()=>Da.value),yl={claude:Na("claude"),codex:Na("codex"),gemini:Na("gemini"),opencode:Na("opencode"),omp:Na("omp")},ml=n(()=>{if(!zl())return[];const e=yl[S.channelType];if(!e)return[];return(e.value||[]).slice(0,hl.value)});let gl=null,fl=null,kl=null,Tl=!1,Cl=null;const bl=n(()=>{let e=[];"claude"===S.channelType?e=za.value||[]:"codex"===S.channelType?e=qa.value||[]:"gemini"===S.channelType?e=Pa.value||[]:"opencode"===S.channelType?e=ja.value||[]:"omp"===S.channelType&&(e=La.value||[]);return[...e.filter(e=>!1!==e.enabled),...e.filter(e=>!1===e.enabled)]});function wl(e){const a=Ma[S.channelType];if(!a||!a.channels)return 0;const l=a.channels.find(a=>a.id===e);return l?l.inflight:0}const xl=n(()=>{const e=bl.value.filter(e=>!1!==e.enabled).length;return Ga.value.running?`${e}个渠道调度中`:bl.value.length>0?`${e}个渠道已启用`:"无渠道"}),$l=n(()=>{var e,a,l;return(null==(l=null==(a=null==(e=Ja.value)?void 0:e.todayStats)?void 0:a[S.channelType])?void 0:l.byChannel)||{}});function _l(e){return $l.value[e]||{requests:0,tokens:0,cost:0}}function Sl(e,a){var l;return(null==e?void 0:e.usageMissing)?"--":(null==(l=null==e?void 0:e.tokens)?void 0:l[a])||0}function zl(){return["claude","codex","gemini","opencode","omp"].includes(S.channelType)}function ql(e){if(!e||"action"===e.type||"error"===e.status)return"";const a=[];return e.model&&a.push(`模型: ${e.model}`),e.originalModel&&e.originalModel!==e.model&&a.push(`重定向: ${e.originalModel} -> ${e.model}`),e.usageMissing&&a.push("上游响应未返回 usage,当前无法计算 token。"),a.join("\n")}async function Pl(e){var a,l;if(!1===Ra.value.supportsProxy||!zl())return void q.warning(`${Ka.value} 暂未接入动态代理`);const n=Ia(S.channelType);n.value.loading=!0;try{let a;a=e?await Oa(S.channelType):await Ea(S.channelType,{refreshChannelsDrawer:!0}),!1!==a.success?q.success(e?`${Ka.value} 代理已启动`:`${Ka.value} 代理已停止`):(q.error(a.error||"操作失败"),n.value.running=!e)}catch(s){q.error((null==(l=null==(a=s.response)?void 0:a.data)?void 0:l.error)||s.message||"操作失败"),n.value.running=!e}finally{n.value.loading=!1}}function jl(){!1!==Ra.value.supportsProjects&&zl()?z.push({name:`${S.channelType}-projects`}):q.info(`${Ka.value} 当前仅作为首页显示项`)}function Ll(){!1!==Ra.value.supportsProjects&&zl()?z.push({name:`${S.channelType}-projects`}):q.info(`${Ka.value} 当前仅作为首页显示项`)}function Ml(){!1!==Ra.value.supportsSessions&&zl()?sl.value=!0:q.info(`${Ka.value} 当前没有托管会话列表`)}s(ml,e=>{var a;const l=(null==(a=e[0])?void 0:a.id)||null;if(!l||l===gl)return void(gl=l);gl=l,Cl&&clearTimeout(Cl),Cl=setTimeout(()=>{Va(!0,{fresh:!0}).then(()=>Al()).catch(()=>{})},5e3);(!pl.value||pl.value.scrollTop<20)&&x(()=>{pl.value&&(pl.value.scrollTop=0)})}),s(()=>Xa.value.requests,e=>{nl("requests",Ya.value.requests,e,600)}),s(()=>Xa.value.tokens,e=>{nl("tokens",Ya.value.tokens,e,600)}),s(()=>Xa.value.cost,e=>{nl("cost",Ya.value.cost,e,600)}),s(()=>S.channelType,()=>{var e;gl=(null==(e=ml.value[0])?void 0:e.id)||null}),s(()=>{var e,a;return null==(a=null==(e=Ja.value)?void 0:e.counts)?void 0:a[S.channelType]},()=>{Fl()}),s(()=>{var e,a;return null==(a=null==(e=Ja.value)?void 0:e.todayStats)?void 0:a[S.channelType]},()=>{Al()},{deep:!0}),s(Ua,()=>{Tl&&function(){fl&&(clearInterval(fl),fl=null);const e=Ua.value||30,a=Math.max(1e3*e,1e4);fl=setInterval(()=>{Va(!0,{fresh:!0}).then(()=>Al()).catch(()=>{})},a)}()});const Il=a({});function Ol(e){return!!Il.value[e]}function El(e,a){e&&(Il.value={...Il.value,[e]:!!a})}async function Nl(e,a){if(e&&!Ol(e.id)){El(e.id,!0);try{let l;"claude"===S.channelType?l=O:"codex"===S.channelType?l=E:"gemini"===S.channelType?l=N:"opencode"===S.channelType?l=F:"omp"===S.channelType&&(l=A),l&&(await l(e.id,{enabled:a}),await async function(e,a){if(!e)return;const l=cl[S.channelType];let n={};try{const e=l?localStorage.getItem(l):null;n=e?JSON.parse(e):{}}catch(s){n={}}a?delete n[e]:n[e]=!0;try{l&&localStorage.setItem(l,JSON.stringify(n))}catch(s){}try{await _("channelCollapse",S.channelType,n)}catch(s){}}(e.id,a),q.success(a?`渠道「${e.name}」已启用`:`渠道「${e.name}」已停用`),await Aa(),window.dispatchEvent(new CustomEvent("channel-management-refresh",{detail:{channel:S.channelType}})))}catch(l){q.error("操作失败: "+l.message)}finally{El(e.id,!1)}}}function Fl(){var e,a;const l=null==(a=null==(e=Ja.value)?void 0:e.counts)?void 0:a[S.channelType];Wa.value.projects=(null==l?void 0:l.projectCount)||0,Wa.value.sessions=(null==l?void 0:l.sessionCount)||0}async function Al(){if(Ja.value&&Ja.value.todayStats){const e=Ja.value.todayStats[S.channelType];e&&(Xa.value.requests=e.requests||0,Xa.value.tokens=e.tokens||0,Xa.value.cost=e.cost||0)}Fl()}function Dl(){Fa(S.channelType)}function Ul(e){var a,l;null==(l=null==(a=null==e?void 0:e.currentTarget)?void 0:a.blur)||l.call(a)}function Jl(e){window.dispatchEvent(new CustomEvent("open-skills-drawer",{detail:{platform:S.channelType}})),Ul(e)}function Vl(e){window.dispatchEvent(new CustomEvent("open-commands-drawer",{detail:{platform:S.channelType}})),Ul(e)}function Rl(e){if(!1===Ra.value.supportsAgents)return q.info(`${Ka.value} 的 Agent 能力通过插件/扩展提供`),void Ul(e);window.dispatchEvent(new CustomEvent("open-agents-drawer",{detail:{platform:S.channelType}})),Ul(e)}return c(async()=>{await Va().then(()=>Al()),async function(){var e,a;try{if(Ja.value&&Ja.value.uiConfig)ul.value=!1!==(null==(e=Ja.value.uiConfig.panelVisibility)?void 0:e.showLogs);else{const e=await $();e.success&&e.config&&(ul.value=!1!==(null==(a=e.config.panelVisibility)?void 0:a.showLogs))}}catch(l){}}(),async function(){var e,a;try{let l=!1;if(Ja.value&&Ja.value.uiConfig)l=(null==(e=Ja.value.uiConfig.channelLocks)?void 0:e[S.channelType])||!1;else{const e=await $();e.success&&e.config&&(l=(null==(a=e.config.channelLocks)?void 0:a[S.channelType])||!1)}ol.value=l,tl(l)}catch(l){}}(),window.addEventListener("panel-visibility-change",rl),Ya.value={...Xa.value},Tl=!0,kl=setInterval(()=>{dl.value=Date.now()},1e3)}),t(()=>{Tl=!1,fl&&clearInterval(fl),kl&&clearInterval(kl),Cl&&clearTimeout(Cl),window.removeEventListener("panel-visibility-change",rl),Object.values(el).forEach(e=>{e&&cancelAnimationFrame(e)})}),(a,l)=>{const n=o("n-collapse");return u(),i("div",me,[r("div",{class:T(["channel-header",[e.channelType,{"custom-cli":Ra.value.custom}]]),style:k(Ra.value.custom?{"--channel-accent":Za.value}:null)},[r("div",ge,[p(y(se),{size:16},{default:h(()=>[p(y(J))]),_:1})]),r("div",fe,[p(y(se),{size:20},{default:h(()=>[(u(),v(m(Ba.value)))]),_:1})]),r("h2",ke,g(Ka.value),1),!1!==Ra.value.supportsManagedConfig?(u(),i("div",Te,[p(y(te),{trigger:"hover"},{trigger:h(()=>[p(y(ce),{text:"",class:"config-shortcut-button",onClick:Jl,title:"Skills 技能管理"},{icon:h(()=>[p(y(se),{size:18},{default:h(()=>[p(y(V))]),_:1})]),_:1})]),default:h(()=>[l[2]||(l[2]=f(" Skills 技能管理 ",-1))]),_:1}),p(y(te),{trigger:"hover"},{trigger:h(()=>[p(y(ce),{text:"",class:"config-shortcut-button",onClick:Vl,title:"Commands 命令管理"},{icon:h(()=>[p(y(se),{size:18},{default:h(()=>[p(y(U))]),_:1})]),_:1})]),default:h(()=>[l[3]||(l[3]=f(" Commands 命令管理 ",-1))]),_:1}),!1!==Ra.value.supportsAgents?(u(),v(y(te),{key:0,trigger:"hover"},{trigger:h(()=>[p(y(ce),{text:"",class:"config-shortcut-button",onClick:Rl,title:"Agents 代理管理"},{icon:h(()=>[p(y(se),{size:18},{default:h(()=>[p(y(R))]),_:1})]),_:1})]),default:h(()=>[l[4]||(l[4]=f(" Agents 代理管理 ",-1))]),_:1})):d("",!0)])):d("",!0),p(y(ce),{text:"",class:"lock-button",onClick:il,title:ol.value?"解锁此列":"锁定此列"},{icon:h(()=>[p(y(se),{size:18},{default:h(()=>[ol.value?(u(),v(y(K),{key:0})):(u(),v(y(B),{key:1}))]),_:1})]),_:1},8,["title"])],6),ol.value?d("",!0):(u(),i("div",Ce,[!1!==Ra.value.supportsProxy?(u(),i("div",be,[r("div",we,[p(y(se),{size:16},{default:h(()=>[p(y(Z))]),_:1}),l[5]||(l[5]=r("h3",{class:"card-title"},"代理控制",-1)),Ga.value.running&&vl.value?(u(),i("span",xe,g(vl.value),1)):d("",!0),p(y(oe),{value:Ga.value.running,"onUpdate:value":[l[0]||(l[0]=e=>Ga.value.running=e),Pl],loading:Ga.value.loading,size:"small",style:{"margin-left":"auto"}},null,8,["value","loading"])]),r("div",$e,[r("div",_e,[r("div",Se,[r("div",{class:T(["status-dot",{active:Ga.value.running}])},null,2),p(y(ie),{type:Ga.value.running?"success":"default",style:{"font-size":"12px"}},{default:h(()=>[f(g(Ga.value.running?"运行中":"已停止"),1)]),_:1},8,["type"]),r("span",ze,"端口: "+g(Ga.value.port),1)]),p(y(re),{trigger:"click",placement:"bottom",width:320,class:"channel-popover"},{trigger:h(()=>[p(y(ce),{text:"",size:"tiny",class:"channel-status"},{default:h(()=>[r("span",qe,g(xl.value),1)]),_:1})]),default:h(()=>[r("div",Pe,[r("div",je,[l[7]||(l[7]=r("span",null,"渠道快捷管理",-1)),p(y(ie),{depth:"3",style:{"font-size":"11px"}},{default:h(()=>[...l[6]||(l[6]=[f("点击开关切换状态",-1)])]),_:1})]),0===bl.value.length?(u(),i("div",Le,[p(y(ie),{depth:"3"},{default:h(()=>[...l[8]||(l[8]=[f("暂无配置渠道",-1)])]),_:1})])):(u(),i("div",Me,[(u(!0),i(C,null,b(bl.value,e=>{var a,n;return u(),i("div",{key:e.id,class:T(["channel-quick-item",{disabled:!1===e.enabled}])},[r("div",Ie,[r("span",Oe,g(e.name),1),"frozen"===(null==(a=e.health)?void 0:a.status)?(u(),v(y(ue),{key:0,size:"tiny",type:"error",bordered:!1},{default:h(()=>[...l[9]||(l[9]=[f(" 冻结 ",-1)])]),_:1})):d("",!0),p(y(oe),{size:"small",value:!1!==e.enabled,"onUpdate:value":a=>Nl(e,a),loading:Ol(e.id),disabled:Ol(e.id),style:{"margin-left":"auto"}},null,8,["value","onUpdate:value","loading","disabled"])]),Ol(e.id)?(u(),i("div",Ee," 正在切换渠道状态... ")):d("",!0),r("div",Ne,[r("span",Fe,[l[10]||(l[10]=r("span",{class:"metric-label"},"请求",-1)),r("span",Ae,g(_l(e.id).requests),1)]),r("span",De,[l[11]||(l[11]=r("span",{class:"metric-label"},"Tokens",-1)),r("span",Ue,g((n=_l(e.id).tokens,n>=1e6?(n/1e6).toFixed(1)+"M":n>=1e3?(n/1e3).toFixed(1)+"K":n.toString())),1)]),r("span",Je,[l[12]||(l[12]=r("span",{class:"metric-label"},"权重",-1)),r("span",Ve,g(e.weight||1),1)]),r("span",Re,[l[13]||(l[13]=r("span",{class:"metric-label"},"并发",-1)),r("span",{class:T(["metric-value",{active:wl(e.id)>0}])},g(wl(e.id))+g(e.maxConcurrency?`/${e.maxConcurrency}`:""),3)])])],2)}),128))]))])]),_:1})])])])):d("",!0),r("div",Ke,[r("div",Be,[p(y(se),{size:14},{default:h(()=>[p(y(G))]),_:1}),l[14]||(l[14]=r("h3",{class:"card-title"},"快速访问",-1))]),r("div",Ze,[r("div",Ge,[r("div",{class:T(["access-card access-card-projects",{clickable:!1!==Ra.value.supportsProjects,disabled:!1===Ra.value.supportsProjects}]),onClick:jl},[r("div",He,[p(y(se),{size:16},{default:h(()=>[p(y(H))]),_:1})]),r("div",We,[l[15]||(l[15]=r("span",{class:"access-label"},"项目",-1)),r("span",Xe,g(Wa.value.projects),1)])],2),r("div",{class:T(["access-card access-card-sessions",{clickable:!1!==Ra.value.supportsSessions,disabled:!1===Ra.value.supportsSessions}]),onClick:Ml},[r("div",Ye,[p(y(se),{size:16},{default:h(()=>[p(y(W))]),_:1})]),r("div",Qe,[l[16]||(l[16]=r("span",{class:"access-label"},"最新对话",-1)),r("span",ea,g(Wa.value.sessions),1)])],2),r("div",{class:T(["access-card access-card-goto",{clickable:!1!==Ra.value.supportsProjects,disabled:!1===Ra.value.supportsProjects}]),onClick:Ll},[r("div",aa,[p(y(se),{size:16},{default:h(()=>[p(y(X))]),_:1})]),r("div",la,[l[17]||(l[17]=r("span",{class:"access-label"},"前往",-1)),r("span",na,g(Ha.value),1)])],2)])])]),r("div",{class:T(["card stats-card",`stats-card-${e.channelType}`])},[r("div",sa,[p(y(se),{size:14},{default:h(()=>[p(y(Y))]),_:1}),l[18]||(l[18]=r("h3",{class:"card-title"},"今日数据",-1))]),r("div",ca,[r("div",ta,[r("div",oa,[l[20]||(l[20]=r("div",{class:"stat-icon-dot requests"},null,-1)),r("div",ia,[l[19]||(l[19]=r("span",{class:"stat-label"},"请求",-1)),r("span",{class:T(["stat-value",{animating:al.value.requests}])},g(Ya.value.requests),3)])]),r("div",ua,[l[22]||(l[22]=r("div",{class:"stat-icon-dot tokens"},null,-1)),r("div",ra,[l[21]||(l[21]=r("span",{class:"stat-label"},"总 Tokens",-1)),r("span",{class:T(["stat-value",{animating:al.value.tokens}])},g((c=Ya.value.tokens,c>=1e6?(c/1e6).toFixed(1)+"M":c>=1e3?(c/1e3).toFixed(1)+"K":c.toString())),3)])]),r("div",da,[l[24]||(l[24]=r("div",{class:"stat-icon-dot cost"},null,-1)),r("div",va,[l[23]||(l[23]=r("span",{class:"stat-label"},"成本 / USD",-1)),r("span",{class:T(["stat-value",{animating:al.value.cost}])},g((s=Ya.value.cost,!s||Number.isNaN(s)?"$0":"$"+Number(s).toFixed(3))),3)])])])])],2),Object.keys(ll.value).length>0?(u(),i("div",{key:1,class:T(["card chart-card",`chart-card-${e.channelType}`])},[p(n,{"default-expanded-names":[],accordion:""})],2)):d("",!0),ul.value?(u(),i("div",pa,[r("div",ha,[p(y(se),{size:14},{default:h(()=>[p(y(Q))]),_:1}),l[25]||(l[25]=r("h3",{class:"card-title"},"实时日志",-1)),p(y(ce),{text:"",size:"tiny",onClick:w(Dl,["stop"]),style:{"margin-left":"auto"},title:"清空日志"},{icon:h(()=>[p(y(se),{size:14},{default:h(()=>[p(y(ee))]),_:1})]),_:1})]),r("div",ya,[r("div",ma,[r("div",{class:T(["logs-table-header",`logs-header-${e.channelType}`])},[r("div",{class:T(["log-col col-channel",`col-channel-${e.channelType}`])},"渠道",2),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"请求",2),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"回复",2),"claude"===e.channelType?(u(),i(C,{key:0},[r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"写入",2),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"命中",2)],64)):"codex"===e.channelType?(u(),i(C,{key:1},[r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"推理",2),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"缓存",2),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"总计",2)],64)):"gemini"===e.channelType?(u(),i(C,{key:2},[r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"缓存",2),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"总计",2)],64)):"opencode"===e.channelType||"omp"===e.channelType?(u(),i(C,{key:3},[r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"推理",2),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"缓存",2),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},"总计",2)],64)):d("",!0),r("div",{class:T(["log-col col-time",`col-time-${e.channelType}`])},"时间",2)],2),r("div",{class:"logs-container",ref_key:"logsContainer",ref:pl},[0===ml.value.length?(u(),i("div",ga,[p(y(se),{size:32,depth:"3",style:{"margin-bottom":"8px"}},{default:h(()=>[p(y(Q))]),_:1}),p(y(ie),{depth:"3",style:{"font-size":"12px","font-weight":"500"}},{default:h(()=>[...l[26]||(l[26]=[f("暂无实时日志",-1)])]),_:1}),p(y(ie),{depth:"3",style:{"font-size":"11px","margin-top":"4px"}},{default:h(()=>[...l[27]||(l[27]=[f("开启代理后将显示请求记录",-1)])]),_:1})])):d("",!0),(u(!0),i(C,null,b(ml.value,a=>(u(),i("div",{key:a.id,class:T(["log-row",{"action-row":"action"===a.type,"error-row":"error"===a.status,"new-log":a.isNew}]),title:ql(a)},["action"===a.type?(u(),i("div",ka,[p(y(se),{size:12,color:"#18a058"},{default:h(()=>[p(y(ae))]),_:1}),r("span",Ta,g(a.message),1),r("span",Ca,g(a.time),1)])):"error"===a.status?(u(),i("div",ba,[p(y(se),{size:12,color:"#d03050"},{default:h(()=>[p(y(le))]),_:1}),r("span",wa,g(a.channel)+": "+g(a.error||a.message||"请求失败"),1),r("span",xa,g(a.time),1)])):(u(),i(C,{key:2},[r("div",{class:T(["log-col col-channel",`col-channel-${e.channelType}`])},[p(y(ue),{size:"tiny",type:"success"},{default:h(()=>[f(g(a.channel),1)]),_:2},1024)],2),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"input")),3),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"output")),3),"claude"===e.channelType?(u(),i(C,{key:0},[r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"cacheCreation")),3),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"cacheRead")),3)],64)):"codex"===e.channelType?(u(),i(C,{key:1},[r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"reasoning")),3),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"cached")),3),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"total")),3)],64)):"gemini"===e.channelType?(u(),i(C,{key:2},[r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"cached")),3),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"total")),3)],64)):"opencode"===e.channelType||"omp"===e.channelType?(u(),i(C,{key:3},[r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"reasoning")),3),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"cached")),3),r("div",{class:T(["log-col col-token",`col-token-${e.channelType}`])},g(Sl(a,"total")),3)],64)):d("",!0),r("div",{class:T(["log-col col-time",`col-time-${e.channelType}`])},g(a.time),3)],64))],10,fa))),128))],512)])])])):d("",!0)])),ol.value?(u(),i("div",{key:1,class:T(["locked-overlay",`locked-${e.channelType}`])},[r("div",$a,[r("div",_a,[p(y(se),{size:48},{default:h(()=>[p(y(K))]),_:1})]),l[29]||(l[29]=r("h3",{class:"locked-title"},"该渠道已锁定",-1)),p(y(ie),{depth:"3",class:"locked-hint"},{default:h(()=>[...l[28]||(l[28]=[f(" 点击上方按钮解锁以查看内容 ",-1)])]),_:1})])],2)):d("",!0),!1!==Ra.value.supportsSessions?(u(),v(I,{key:2,visible:sl.value,"onUpdate:visible":l[1]||(l[1]=e=>sl.value=e),channel:e.channelType},null,8,["visible","channel"])):d("",!0)]);var s,c}}},[["__scopeId","data-v-8f1f9ae8"]]),qa={class:"dashboard-container"},Pa="dashboardChannelOrder",ja=P({__name:"Home",setup(l){const{uiConfig:n,updateConfig:s,loadUIConfig:o}=ye();function r(e){try{localStorage.setItem(Pa,JSON.stringify(e))}catch(a){}}function d(e,a=n.value.customCliPlatforms){const l=D(e,a);return m.value=l.map(e=>({type:e})),r(l),l}const m=a(function(){try{const e=localStorage.getItem(Pa);if(e){const a=JSON.parse(e);return D(a,n.value.customCliPlatforms)}}catch(e){}return q}().map(e=>({type:e})));async function g(){const e=D(m.value.map(e=>e.type),n.value.customCliPlatforms);m.value=e.map(e=>({type:e})),r(e),await s("homeCliColumns",e),await s("dashboardChannelOrder",e)}function f(e){const a=(null==e?void 0:e.detail)||{};d(a.homeCliColumns,a.customCliPlatforms)}return c(async()=>{window.addEventListener("home-cli-columns-change",f),await o(),d(n.value.homeCliColumns||n.value.dashboardChannelOrder,n.value.customCliPlatforms)}),t(()=>{window.removeEventListener("home-cli-columns-change",f)}),(a,l)=>(u(),i("div",qa,[p(y(e),{modelValue:m.value,"onUpdate:modelValue":l[0]||(l[0]=e=>m.value=e),class:"dashboard-grid","item-key":"type",animation:200,handle:".drag-handle",onEnd:g},{item:h(({element:e})=>[(u(),v(za,{"channel-type":e.type,key:e.type},null,8,["channel-type"]))]),_:1},8,["modelValue"])]))}},[["__scopeId","data-v-276ca51b"]]);export{ja as default};
|