coding-tool-x 3.5.12 → 3.5.14
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-GuTri2mr.js → Analytics-D24Q2IkD.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-DILbDhRj.js → ConfigTemplates-xNm_dyGS.js} +1 -1
- package/dist/web/assets/Home-BeGkC4bb.css +1 -0
- package/dist/web/assets/{Home-ri7cXeJp.js → Home-YQrz9dNs.js} +1 -1
- package/dist/web/assets/{PluginManager-DQPeUFkr.js → PluginManager-7ULrS-17.js} +1 -1
- package/dist/web/assets/{ProjectList-Cpf82Lgb.js → ProjectList-Fy4xyQpg.js} +1 -1
- package/dist/web/assets/{SessionList-DXhPIwJI.js → SessionList-DcLW9x3Z.js} +1 -1
- package/dist/web/assets/{SkillManager-DNVyDlEv.js → SkillManager-RnoRbzHA.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-Cp0t7cjn.js → WorkspaceManager-B_BWS-xG.js} +1 -1
- package/dist/web/assets/index-Bvdezm5-.js +2 -0
- package/dist/web/assets/{index-DfikIh5S.css → index-dzKgnRhx.css} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/commands/daemon.js +256 -80
- package/src/config/channel-preset-websites.js +1 -0
- package/src/server/api/channels.js +62 -17
- package/src/server/api/codex-channels.js +23 -3
- package/src/server/api/pm2-autostart.js +59 -24
- package/src/server/opencode-proxy-server.js +14 -8
- package/src/server/proxy-server.js +97 -5
- package/src/server/services/base/response-usage-parser.js +40 -13
- package/src/server/services/channels.js +62 -4
- package/src/server/services/claude-openai-gateway.js +1259 -0
- package/src/server/services/claude-token-recovery.js +386 -0
- package/src/server/services/codex-channels.js +8 -7
- package/dist/web/assets/Home-Bm7mK2qz.css +0 -1
- package/dist/web/assets/index-C5wcoiDy.js +0 -2
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
|
|
4
|
+
const CLAUDE_COUNT_TOKENS_BETA_HEADER = 'claude-code-20250219,token-counting-2024-11-01';
|
|
5
|
+
const CLAUDE_COUNT_TOKENS_USER_AGENT = 'claude-cli/2.1.59 (external, cli)';
|
|
6
|
+
const DEFAULT_TIMEOUT_MS = 5000;
|
|
7
|
+
|
|
8
|
+
function cloneJsonCompatible(value) {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(JSON.stringify(value));
|
|
11
|
+
} catch {
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function toArrayContent(content) {
|
|
17
|
+
if (Array.isArray(content)) {
|
|
18
|
+
return content.map(item => cloneJsonCompatible(item));
|
|
19
|
+
}
|
|
20
|
+
if (typeof content === 'string') {
|
|
21
|
+
return content.trim() ? [{ type: 'text', text: content }] : [];
|
|
22
|
+
}
|
|
23
|
+
if (content && typeof content === 'object') {
|
|
24
|
+
return [cloneJsonCompatible(content)];
|
|
25
|
+
}
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function createClaudeStreamRecoveryState() {
|
|
30
|
+
return {
|
|
31
|
+
model: '',
|
|
32
|
+
blockTypeByIndex: new Map(),
|
|
33
|
+
textByIndex: new Map(),
|
|
34
|
+
toolUseByIndex: new Map()
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function appendTextDelta(state, index, value) {
|
|
39
|
+
const previous = state.textByIndex.get(index) || '';
|
|
40
|
+
state.textByIndex.set(index, previous + value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function appendToolInputDelta(state, index, value) {
|
|
44
|
+
const current = state.toolUseByIndex.get(index) || {
|
|
45
|
+
id: `toolu_recovered_${index}`,
|
|
46
|
+
name: '',
|
|
47
|
+
inputJson: ''
|
|
48
|
+
};
|
|
49
|
+
current.inputJson = `${current.inputJson || ''}${value}`;
|
|
50
|
+
state.toolUseByIndex.set(index, current);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function mergeClaudeStreamEvent(state, eventType, parsed) {
|
|
54
|
+
if (!state || !parsed || typeof parsed !== 'object') {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (eventType === 'message_start' && parsed.message && typeof parsed.message === 'object') {
|
|
59
|
+
const model = typeof parsed.message.model === 'string' ? parsed.message.model.trim() : '';
|
|
60
|
+
if (model) {
|
|
61
|
+
state.model = model;
|
|
62
|
+
}
|
|
63
|
+
} else if (!state.model && typeof parsed.model === 'string' && parsed.model.trim()) {
|
|
64
|
+
state.model = parsed.model.trim();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (eventType === 'content_block_start') {
|
|
68
|
+
const index = Number(parsed.index);
|
|
69
|
+
const blockIndex = Number.isFinite(index) ? index : 0;
|
|
70
|
+
const block = (parsed.content_block && typeof parsed.content_block === 'object') ? parsed.content_block : {};
|
|
71
|
+
const blockType = typeof block.type === 'string' ? block.type : '';
|
|
72
|
+
if (!blockType) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
state.blockTypeByIndex.set(blockIndex, blockType);
|
|
77
|
+
|
|
78
|
+
if (blockType === 'text' && typeof block.text === 'string') {
|
|
79
|
+
state.textByIndex.set(blockIndex, block.text);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (blockType === 'tool_use') {
|
|
84
|
+
state.toolUseByIndex.set(blockIndex, {
|
|
85
|
+
id: String(block.id || `toolu_recovered_${blockIndex}`),
|
|
86
|
+
name: typeof block.name === 'string' ? block.name : '',
|
|
87
|
+
inputJson: block.input && typeof block.input === 'object' && !Array.isArray(block.input)
|
|
88
|
+
? JSON.stringify(block.input)
|
|
89
|
+
: ''
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (eventType !== 'content_block_delta') {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const index = Number(parsed.index);
|
|
100
|
+
const blockIndex = Number.isFinite(index) ? index : 0;
|
|
101
|
+
const delta = (parsed.delta && typeof parsed.delta === 'object') ? parsed.delta : {};
|
|
102
|
+
|
|
103
|
+
if (delta.type === 'text_delta' && typeof delta.text === 'string') {
|
|
104
|
+
appendTextDelta(state, blockIndex, delta.text);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (delta.type === 'input_json_delta' && typeof delta.partial_json === 'string') {
|
|
109
|
+
appendToolInputDelta(state, blockIndex, delta.partial_json);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function parseToolInput(inputJson) {
|
|
114
|
+
if (typeof inputJson !== 'string' || !inputJson.trim()) {
|
|
115
|
+
return {};
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const parsed = JSON.parse(inputJson);
|
|
119
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
120
|
+
return parsed;
|
|
121
|
+
}
|
|
122
|
+
} catch {
|
|
123
|
+
}
|
|
124
|
+
return {};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function buildAssistantMessageFromStreamState(state) {
|
|
128
|
+
if (!state || !(state.blockTypeByIndex instanceof Map) || state.blockTypeByIndex.size === 0) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const content = [];
|
|
133
|
+
const indexes = Array.from(state.blockTypeByIndex.keys())
|
|
134
|
+
.map(value => Number(value))
|
|
135
|
+
.filter(Number.isFinite)
|
|
136
|
+
.sort((a, b) => a - b);
|
|
137
|
+
|
|
138
|
+
indexes.forEach((index) => {
|
|
139
|
+
const blockType = state.blockTypeByIndex.get(index);
|
|
140
|
+
if (blockType === 'text') {
|
|
141
|
+
const text = state.textByIndex.get(index) || '';
|
|
142
|
+
if (text) {
|
|
143
|
+
content.push({
|
|
144
|
+
type: 'text',
|
|
145
|
+
text
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (blockType === 'tool_use') {
|
|
152
|
+
const toolUse = state.toolUseByIndex.get(index);
|
|
153
|
+
if (!toolUse || !toolUse.name) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
content.push({
|
|
157
|
+
type: 'tool_use',
|
|
158
|
+
id: toolUse.id,
|
|
159
|
+
name: toolUse.name,
|
|
160
|
+
input: parseToolInput(toolUse.inputJson)
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
if (content.length === 0) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
role: 'assistant',
|
|
171
|
+
content
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function buildClaudeCountTokensTargetUrl(baseUrl = '') {
|
|
176
|
+
let targetUrl;
|
|
177
|
+
try {
|
|
178
|
+
targetUrl = new URL(String(baseUrl || '').trim() || 'https://api.anthropic.com');
|
|
179
|
+
} catch {
|
|
180
|
+
targetUrl = new URL('https://api.anthropic.com');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
let pathname = targetUrl.pathname.replace(/\/+$/, '');
|
|
184
|
+
if (!pathname || pathname === '/') {
|
|
185
|
+
pathname = '/v1/messages/count_tokens';
|
|
186
|
+
} else if (pathname.endsWith('/messages/count_tokens')) {
|
|
187
|
+
// noop
|
|
188
|
+
} else if (pathname.endsWith('/messages')) {
|
|
189
|
+
pathname = `${pathname}/count_tokens`;
|
|
190
|
+
} else if (pathname.endsWith('/v1')) {
|
|
191
|
+
pathname = `${pathname}/messages/count_tokens`;
|
|
192
|
+
} else {
|
|
193
|
+
pathname = `${pathname}/v1/messages/count_tokens`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
targetUrl.pathname = pathname;
|
|
197
|
+
targetUrl.searchParams.set('beta', 'true');
|
|
198
|
+
return targetUrl.toString();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function buildClaudeCountTokensHeaders(apiKey) {
|
|
202
|
+
return {
|
|
203
|
+
'x-api-key': apiKey,
|
|
204
|
+
authorization: `Bearer ${apiKey}`,
|
|
205
|
+
'anthropic-version': '2023-06-01',
|
|
206
|
+
'anthropic-beta': CLAUDE_COUNT_TOKENS_BETA_HEADER,
|
|
207
|
+
'content-type': 'application/json',
|
|
208
|
+
accept: 'application/json',
|
|
209
|
+
'accept-encoding': 'gzip, deflate',
|
|
210
|
+
'user-agent': CLAUDE_COUNT_TOKENS_USER_AGENT
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function postJson(url, headers, payload, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
215
|
+
return new Promise((resolve, reject) => {
|
|
216
|
+
const target = new URL(url);
|
|
217
|
+
const isHttps = target.protocol === 'https:';
|
|
218
|
+
const client = isHttps ? https : http;
|
|
219
|
+
const body = JSON.stringify(payload || {});
|
|
220
|
+
const request = client.request({
|
|
221
|
+
hostname: target.hostname,
|
|
222
|
+
port: target.port || (isHttps ? 443 : 80),
|
|
223
|
+
path: `${target.pathname}${target.search}`,
|
|
224
|
+
method: 'POST',
|
|
225
|
+
timeout: timeoutMs,
|
|
226
|
+
headers: {
|
|
227
|
+
...headers,
|
|
228
|
+
'Content-Type': 'application/json',
|
|
229
|
+
'Content-Length': Buffer.byteLength(body)
|
|
230
|
+
}
|
|
231
|
+
}, (response) => {
|
|
232
|
+
let rawBody = '';
|
|
233
|
+
response.on('data', (chunk) => {
|
|
234
|
+
rawBody += chunk.toString('utf8');
|
|
235
|
+
});
|
|
236
|
+
response.on('end', () => {
|
|
237
|
+
resolve({
|
|
238
|
+
statusCode: Number(response.statusCode) || 500,
|
|
239
|
+
headers: response.headers || {},
|
|
240
|
+
rawBody
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
response.on('error', reject);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
request.on('error', reject);
|
|
247
|
+
request.on('timeout', () => {
|
|
248
|
+
request.destroy(new Error('count_tokens request timeout'));
|
|
249
|
+
});
|
|
250
|
+
request.write(body);
|
|
251
|
+
request.end();
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function readCountTokensValue(responseBody) {
|
|
256
|
+
if (!responseBody || typeof responseBody !== 'object') {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const direct = Number(responseBody.input_tokens ?? responseBody.inputTokens);
|
|
261
|
+
if (Number.isFinite(direct)) {
|
|
262
|
+
return direct;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const nested = Number(responseBody.usage?.input_tokens ?? responseBody.usage?.inputTokens);
|
|
266
|
+
if (Number.isFinite(nested)) {
|
|
267
|
+
return nested;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function buildClaudeCountTokensPayload(requestBody = {}) {
|
|
274
|
+
const payload = {
|
|
275
|
+
model: requestBody.model,
|
|
276
|
+
messages: Array.isArray(requestBody.messages)
|
|
277
|
+
? requestBody.messages.map(message => cloneJsonCompatible(message))
|
|
278
|
+
: []
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
if (requestBody.system !== undefined) {
|
|
282
|
+
payload.system = cloneJsonCompatible(requestBody.system);
|
|
283
|
+
}
|
|
284
|
+
if (Array.isArray(requestBody.tools) && requestBody.tools.length > 0) {
|
|
285
|
+
payload.tools = cloneJsonCompatible(requestBody.tools);
|
|
286
|
+
}
|
|
287
|
+
if (requestBody.tool_choice && typeof requestBody.tool_choice === 'object') {
|
|
288
|
+
payload.tool_choice = cloneJsonCompatible(requestBody.tool_choice);
|
|
289
|
+
}
|
|
290
|
+
if (requestBody.metadata && typeof requestBody.metadata === 'object') {
|
|
291
|
+
payload.metadata = cloneJsonCompatible(requestBody.metadata);
|
|
292
|
+
}
|
|
293
|
+
if (requestBody.thinking && typeof requestBody.thinking === 'object') {
|
|
294
|
+
payload.thinking = cloneJsonCompatible(requestBody.thinking);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return payload;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async function countClaudeInputTokens({ baseUrl, apiKey, payload, timeoutMs = DEFAULT_TIMEOUT_MS }) {
|
|
301
|
+
const response = await postJson(
|
|
302
|
+
buildClaudeCountTokensTargetUrl(baseUrl),
|
|
303
|
+
buildClaudeCountTokensHeaders(apiKey),
|
|
304
|
+
payload,
|
|
305
|
+
timeoutMs
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
309
|
+
throw new Error(`count_tokens returned HTTP ${response.statusCode}`);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
let parsedBody = null;
|
|
313
|
+
try {
|
|
314
|
+
parsedBody = response.rawBody ? JSON.parse(response.rawBody) : {};
|
|
315
|
+
} catch {
|
|
316
|
+
parsedBody = null;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const tokens = readCountTokensValue(parsedBody);
|
|
320
|
+
if (!Number.isFinite(tokens)) {
|
|
321
|
+
throw new Error('count_tokens response missing input_tokens');
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return tokens;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function appendAssistantMessage(messages = [], assistantMessage) {
|
|
328
|
+
const normalizedMessages = Array.isArray(messages)
|
|
329
|
+
? messages.map(message => cloneJsonCompatible(message))
|
|
330
|
+
: [];
|
|
331
|
+
|
|
332
|
+
normalizedMessages.push({
|
|
333
|
+
role: 'assistant',
|
|
334
|
+
content: toArrayContent(assistantMessage.content)
|
|
335
|
+
});
|
|
336
|
+
return normalizedMessages;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async function recoverClaudeUsageViaCountTokens({
|
|
340
|
+
baseUrl,
|
|
341
|
+
apiKey,
|
|
342
|
+
requestBody,
|
|
343
|
+
assistantMessage,
|
|
344
|
+
timeoutMs = DEFAULT_TIMEOUT_MS
|
|
345
|
+
}) {
|
|
346
|
+
if (!assistantMessage || !assistantMessage.content || !baseUrl || !apiKey) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const promptPayload = buildClaudeCountTokensPayload(requestBody);
|
|
351
|
+
if (!promptPayload.model || !Array.isArray(promptPayload.messages)) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const promptTokens = await countClaudeInputTokens({
|
|
356
|
+
baseUrl,
|
|
357
|
+
apiKey,
|
|
358
|
+
payload: promptPayload,
|
|
359
|
+
timeoutMs
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
const promptWithAssistantPayload = {
|
|
363
|
+
...promptPayload,
|
|
364
|
+
messages: appendAssistantMessage(promptPayload.messages, assistantMessage)
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
const promptPlusAssistantTokens = await countClaudeInputTokens({
|
|
368
|
+
baseUrl,
|
|
369
|
+
apiKey,
|
|
370
|
+
payload: promptWithAssistantPayload,
|
|
371
|
+
timeoutMs
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
return {
|
|
375
|
+
inputTokens: promptTokens,
|
|
376
|
+
outputTokens: Math.max(promptPlusAssistantTokens - promptTokens, 0)
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
module.exports = {
|
|
381
|
+
createClaudeStreamRecoveryState,
|
|
382
|
+
mergeClaudeStreamEvent,
|
|
383
|
+
buildAssistantMessageFromStreamState,
|
|
384
|
+
buildClaudeCountTokensPayload,
|
|
385
|
+
recoverClaudeUsageViaCountTokens
|
|
386
|
+
};
|
|
@@ -6,7 +6,6 @@ const tomlStringify = require('@iarna/toml').stringify;
|
|
|
6
6
|
const { PATHS } = require('../../config/paths');
|
|
7
7
|
const { getCodexDir } = require('./codex-config');
|
|
8
8
|
const { isProxyConfig, readConfig } = require('./codex-settings-manager');
|
|
9
|
-
const { clearNativeOAuth } = require('./native-oauth-adapters');
|
|
10
9
|
const { syncCodexUserEnvironment } = require('./codex-env-manager');
|
|
11
10
|
const BaseChannelService = require('./base/base-channel-service');
|
|
12
11
|
|
|
@@ -35,13 +34,17 @@ function resolveCurrentManagedChannel(channels = []) {
|
|
|
35
34
|
return allChannels.find(ch => ch.enabled !== false) || null;
|
|
36
35
|
}
|
|
37
36
|
|
|
37
|
+
function channelRequiresOpenaiAuth(channel) {
|
|
38
|
+
return channel?.requiresOpenaiAuth === true;
|
|
39
|
+
}
|
|
40
|
+
|
|
38
41
|
function buildManagedCodexEnvMap(channels = [], { includeProxyKey = false, activeChannel = null } = {}) {
|
|
39
42
|
if (includeProxyKey) {
|
|
40
43
|
return { [CODEX_MANAGED_ENV_KEY]: CODEX_PROXY_ENV_VALUE };
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
const targetChannel = activeChannel || resolveCurrentManagedChannel(channels);
|
|
44
|
-
if (targetChannel?.apiKey) {
|
|
47
|
+
if (!channelRequiresOpenaiAuth(targetChannel) && targetChannel?.apiKey) {
|
|
45
48
|
return { [CODEX_MANAGED_ENV_KEY]: targetChannel.apiKey };
|
|
46
49
|
}
|
|
47
50
|
return {};
|
|
@@ -108,7 +111,7 @@ function writeCodexConfigForMultiChannel(channels) {
|
|
|
108
111
|
base_url: ch.baseUrl,
|
|
109
112
|
wire_api: ch.wireApi || 'responses',
|
|
110
113
|
env_key: CODEX_MANAGED_ENV_KEY,
|
|
111
|
-
requires_openai_auth: ch
|
|
114
|
+
requires_openai_auth: channelRequiresOpenaiAuth(ch)
|
|
112
115
|
};
|
|
113
116
|
if (ch.queryParams && Object.keys(ch.queryParams).length > 0) {
|
|
114
117
|
config.model_providers[ch.providerKey].query_params = ch.queryParams;
|
|
@@ -147,7 +150,7 @@ class CodexChannelService extends BaseChannelService {
|
|
|
147
150
|
ch.speedTestModel = ch.speedTestModel || null;
|
|
148
151
|
ch.modelRedirects = Array.isArray(ch.modelRedirects) ? ch.modelRedirects : [];
|
|
149
152
|
ch.gatewaySourceType = ch.gatewaySourceType || 'codex';
|
|
150
|
-
ch.requiresOpenaiAuth = ch.requiresOpenaiAuth
|
|
153
|
+
ch.requiresOpenaiAuth = ch.requiresOpenaiAuth === true;
|
|
151
154
|
ch.queryParams = ch.queryParams || {};
|
|
152
155
|
return ch;
|
|
153
156
|
}
|
|
@@ -193,12 +196,10 @@ class CodexChannelService extends BaseChannelService {
|
|
|
193
196
|
return;
|
|
194
197
|
}
|
|
195
198
|
}
|
|
196
|
-
clearNativeOAuth('codex');
|
|
197
199
|
syncAllChannelEnvVars();
|
|
198
200
|
}
|
|
199
201
|
|
|
200
202
|
_applyToNativeSettings(channel) {
|
|
201
|
-
clearNativeOAuth('codex');
|
|
202
203
|
const codexDir = getCodexDir();
|
|
203
204
|
const configPath = path.join(codexDir, 'config.toml');
|
|
204
205
|
|
|
@@ -224,7 +225,7 @@ class CodexChannelService extends BaseChannelService {
|
|
|
224
225
|
base_url: channel.baseUrl,
|
|
225
226
|
wire_api: channel.wireApi || 'responses',
|
|
226
227
|
env_key: CODEX_MANAGED_ENV_KEY,
|
|
227
|
-
requires_openai_auth: channel
|
|
228
|
+
requires_openai_auth: channelRequiresOpenaiAuth(channel)
|
|
228
229
|
};
|
|
229
230
|
|
|
230
231
|
if (channel.queryParams && Object.keys(channel.queryParams).length > 0) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.channel-column[data-v-ed1480ec]{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--gradient-card);border:1px solid var(--border-primary);border-radius:8px;overflow:hidden;box-shadow:var(--shadow-sm)}.channel-header[data-v-ed1480ec]{display:flex;align-items:center;gap:10px;padding:12px 14px;background:var(--bg-primary);position:relative}.drag-handle[data-v-ed1480ec]{cursor:grab;color:var(--text-tertiary);display:flex;align-items:center;padding:4px;margin:-4px 0 -4px -4px;border-radius:4px;transition:all .2s}.drag-handle[data-v-ed1480ec]:hover{color:var(--text-secondary);background:var(--bg-tertiary)}.drag-handle[data-v-ed1480ec]:active{cursor:grabbing}.channel-header[data-v-ed1480ec]:after{content:"";position:absolute;bottom:0;left:14px;right:14px;height:2px;border-radius:1px}.channel-header.claude[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(24,160,88,.08) 0%,transparent 100%)}.channel-header.claude[data-v-ed1480ec]:after{background:linear-gradient(90deg,#18a058,#18a0584d)}.channel-header.codex[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(59,130,246,.08) 0%,transparent 100%)}.channel-header.codex[data-v-ed1480ec]:after{background:linear-gradient(90deg,#3b82f6,#3b82f64d)}.channel-header.gemini[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(168,85,247,.08) 0%,transparent 100%)}.channel-header.gemini[data-v-ed1480ec]:after{background:linear-gradient(90deg,#a855f7,#a855f74d)}.channel-header.opencode[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(234,88,12,.08) 0%,transparent 100%)}.channel-header.opencode[data-v-ed1480ec]:after{background:linear-gradient(90deg,#ea580c,#ea580c4d)}.header-icon[data-v-ed1480ec]{width:32px;height:32px;border-radius:6px;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px #0000001a}.channel-header.claude .header-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#18a058,#15803d);color:#fff}.channel-header.codex .header-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff}.channel-header.gemini .header-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#a855f7,#9333ea);color:#fff}.channel-header.opencode .header-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#ea580c,#c2410c);color:#fff}.channel-title[data-v-ed1480ec]{font-size:15px;font-weight:700;margin:0;color:var(--text-primary);letter-spacing:.3px}.channel-content[data-v-ed1480ec]{flex:1;min-height:0;overflow:hidden;padding:10px;display:flex;flex-direction:column;gap:8px}.card[data-v-ed1480ec]{background:var(--bg-primary);border:1px solid var(--border-primary);border-radius:8px;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 12px #0000000d;position:relative}.card[data-v-ed1480ec]:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.1),transparent);opacity:0;transition:opacity .3s ease}.card[data-v-ed1480ec]:hover{box-shadow:0 6px 20px #0000001a;border-color:var(--border-secondary)}.card[data-v-ed1480ec]:hover:before{opacity:1}.card.clickable[data-v-ed1480ec]{cursor:pointer}.card.clickable[data-v-ed1480ec]:hover{border-color:#18a058;transform:translateY(-2px);box-shadow:0 8px 24px #18a0582e}.card.clickable[data-v-ed1480ec]:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(135deg,rgba(24,160,88,.02) 0%,transparent 100%);opacity:0;transition:opacity .3s ease;pointer-events:none}.card.clickable[data-v-ed1480ec]:hover:after{opacity:1}.card-header[data-v-ed1480ec]{display:flex;align-items:center;gap:8px;padding:10px 12px;background:linear-gradient(180deg,var(--bg-secondary) 0%,var(--bg-primary) 100%);border-bottom:1px solid var(--border-primary);position:relative;min-height:24px}.card-header.compact[data-v-ed1480ec]{padding:8px 12px}.card-header .n-icon[data-v-ed1480ec]{color:var(--text-tertiary);transition:color .2s ease}.card:hover .card-header .n-icon[data-v-ed1480ec]{color:var(--text-secondary)}.card-title[data-v-ed1480ec]{font-size:11px;font-weight:700;margin:0;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.8px}.runtime-badge[data-v-ed1480ec]{display:inline-flex;align-items:center;padding:3px 8px;margin-left:8px;font-size:10px;font-weight:600;color:#10b981;background:linear-gradient(135deg,#10b9811a,#34d3991a);border:1px solid rgba(16,185,129,.2);border-radius:4px;white-space:nowrap;animation:pulse-runtime-ed1480ec 2s ease-in-out infinite}@keyframes pulse-runtime-ed1480ec{0%,to{opacity:1;transform:scale(1)}50%{opacity:.8;transform:scale(.98)}}.card-body[data-v-ed1480ec]{padding:12px;background:var(--bg-primary)}.card-body.compact[data-v-ed1480ec]{padding:10px 12px}.proxy-control[data-v-ed1480ec]{display:flex;justify-content:space-between;align-items:center;gap:16px}.proxy-info[data-v-ed1480ec]{display:flex;flex-direction:column;gap:4px}.proxy-info-row[data-v-ed1480ec]{display:flex;align-items:center;justify-content:space-between}.proxy-status[data-v-ed1480ec]{display:flex;align-items:center;gap:6px}.proxy-port[data-v-ed1480ec]{font-size:11px;color:var(--text-secondary);margin-left:6px}.channel-selector[data-v-ed1480ec]{display:flex;align-items:center;padding:4px 8px;background:linear-gradient(135deg,var(--bg-secondary) 0%,var(--bg-tertiary) 100%);border:1px solid var(--border-primary);border-radius:4px;color:var(--text-secondary);transition:all .2s ease}.channel-selector[data-v-ed1480ec]:hover{background:var(--hover-bg);border-color:var(--border-secondary);color:var(--text-primary)}.channel-selector[data-v-ed1480ec]:disabled{opacity:.5;cursor:not-allowed}.channel-name[data-v-ed1480ec]{font-size:11px;font-weight:500;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.status-dot[data-v-ed1480ec]{width:8px;height:8px;border-radius:50%;background:var(--border-secondary);transition:all .3s ease}.status-dot.active[data-v-ed1480ec]{background:#18a058;box-shadow:0 0 8px #18a05880}.quick-stats[data-v-ed1480ec]{display:flex;gap:16px;padding:4px 0}.stat-item[data-v-ed1480ec]{flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;padding:4px 0}.stat-divider[data-v-ed1480ec]{width:1px;background:linear-gradient(180deg,transparent 0%,var(--border-primary) 50%,transparent 100%)}.quick-access-list[data-v-ed1480ec]{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}.access-card[data-v-ed1480ec]{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:6px;background:var(--bg-secondary);border:1px solid var(--border-color);transition:all .3s cubic-bezier(.4,0,.2,1);position:relative;min-height:52px;overflow:hidden}.access-card[data-v-ed1480ec]:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s ease;pointer-events:none}.access-icon[data-v-ed1480ec]{width:32px;height:32px;border-radius:5px;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .3s ease}.access-content[data-v-ed1480ec]{display:flex;flex-direction:column;gap:4px;flex:1}.access-card-projects .access-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#6366f126,#8b5cf626);color:#6366f1}.access-card-projects[data-v-ed1480ec]:before{background:linear-gradient(135deg,#6366f114,#8b5cf614)}.access-card-projects:hover .access-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#6366f140,#8b5cf640);transform:scale(1.1) rotate(-5deg)}.access-card-sessions .access-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#10b98126,#05966926);color:#10b981}.access-card-sessions[data-v-ed1480ec]:before{background:linear-gradient(135deg,#10b98114,#05966914)}.access-card-sessions:hover .access-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#10b98140,#05966940);transform:scale(1.1) rotate(5deg)}.access-card-goto .access-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#f59e0b26,#fb923c26);color:#f59e0b}.access-card-goto[data-v-ed1480ec]:before{background:linear-gradient(135deg,#f59e0b14,#fb923c14)}.access-card-goto:hover .access-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#f59e0b40,#fb923c40);transform:scale(1.1) translate(3px)}.access-card.clickable[data-v-ed1480ec]:hover{transform:translateY(-2px);box-shadow:0 8px 20px #0000001a;border-color:var(--border-secondary)}.access-card.clickable[data-v-ed1480ec]:hover:before{opacity:1}.access-card.clickable[data-v-ed1480ec]:active{transform:translateY(0)}.access-label[data-v-ed1480ec]{display:block;font-size:10px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.3px}.access-value[data-v-ed1480ec]{display:block;font-size:18px;font-weight:800;color:var(--text-primary);line-height:1}.access-goto[data-v-ed1480ec]{display:block;font-size:12px;font-weight:700;color:var(--text-primary);line-height:1.2;white-space:nowrap}.stats-inline[data-v-ed1480ec]{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.stats-inline.stats-3col[data-v-ed1480ec]{grid-template-columns:repeat(3,1fr)}.stat-inline-item[data-v-ed1480ec]{display:flex;align-items:center;gap:8px;padding:10px;background:var(--bg-secondary);border-radius:6px;border:1px solid var(--border-primary);transition:all .2s ease}.stat-inline-item[data-v-ed1480ec]:hover{border-color:var(--border-secondary);background:var(--hover-bg)}.stat-icon-dot[data-v-ed1480ec]{width:8px;height:8px;border-radius:50%;flex-shrink:0}.stat-icon-dot.requests[data-v-ed1480ec]{background:#3b82f6;box-shadow:0 0 6px #3b82f680}.stat-icon-dot.tokens[data-v-ed1480ec]{background:#18a058;box-shadow:0 0 6px #18a05880}.stat-icon-dot.cost[data-v-ed1480ec]{background:#f59e0b;box-shadow:0 0 6px #f59e0b80}.stat-info[data-v-ed1480ec]{display:flex;flex-direction:column;gap:1px;min-width:0}.stat-label[data-v-ed1480ec]{font-size:10px;color:var(--text-tertiary);font-weight:500;text-transform:uppercase;letter-spacing:.2px}.stat-value[data-v-ed1480ec]{font-size:16px;font-weight:700;color:var(--text-primary);line-height:1.2;transition:all .3s ease}.stat-value.animating[data-v-ed1480ec]{animation:numberChange-ed1480ec .6s ease}@keyframes numberChange-ed1480ec{0%{transform:translateY(-6px);opacity:.5}50%{transform:translateY(0);opacity:1;color:var(--primary-color)}to{transform:translateY(0);opacity:1}}.stats-card[data-v-ed1480ec],.chart-card[data-v-ed1480ec]{border-left:2px solid transparent}.stats-card-claude[data-v-ed1480ec],.chart-card[data-v-ed1480ec]:has(+.stats-card-claude),.card[data-v-ed1480ec]:has(.panel-card):nth-child(4){border-left-color:#18a058}.chart-card.chart-card-claude[data-v-ed1480ec]{border-left-color:#18a058}.stats-card-codex[data-v-ed1480ec],.chart-card[data-v-ed1480ec]:has(+.stats-card-codex),.card[data-v-ed1480ec]:has(.panel-card):nth-child(4){border-left-color:#3b82f6}.chart-card.chart-card-codex[data-v-ed1480ec]{border-left-color:#3b82f6}.stats-card-gemini[data-v-ed1480ec],.chart-card[data-v-ed1480ec]:has(+.stats-card-gemini),.card[data-v-ed1480ec]:has(.panel-card):nth-child(4){border-left-color:#a855f7}.chart-card.chart-card-gemini[data-v-ed1480ec]{border-left-color:#a855f7}.stats-card-opencode[data-v-ed1480ec],.chart-card[data-v-ed1480ec]:has(+.stats-card-opencode),.card[data-v-ed1480ec]:has(.panel-card):nth-child(4){border-left-color:#ea580c}.chart-card.chart-card-opencode[data-v-ed1480ec]{border-left-color:#ea580c}.chart-card[data-v-ed1480ec]{padding:0;overflow:hidden}.chart-card[data-v-ed1480ec] .panel-card{border:none;border-radius:0;box-shadow:none;background:transparent}.stat-requests .stat-value[data-v-ed1480ec]{color:#3b82f6}.stat-input .stat-value[data-v-ed1480ec]{color:#18a058}.stat-output .stat-value[data-v-ed1480ec]{color:#f59e0b}.token-label[data-v-ed1480ec]{display:flex;align-items:center;gap:8px}.token-dot[data-v-ed1480ec]{width:8px;height:8px;border-radius:50%}.logs-card[data-v-ed1480ec]{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--border-primary);border-radius:6px}.logs-card-body[data-v-ed1480ec]{flex:1;min-height:0;display:flex;flex-direction:column;padding:0}.logs-card .card-header[data-v-ed1480ec]{background:linear-gradient(135deg,var(--bg-secondary) 0%,var(--bg-tertiary) 100%)}.logs-table-wrapper[data-v-ed1480ec]{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;background:var(--bg-primary)}.logs-table-header[data-v-ed1480ec]{display:flex;padding:10px 12px;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border-bottom:2px solid var(--border-primary);font-size:11px;font-weight:700;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.6px;flex-shrink:0}.logs-header-claude .log-col[data-v-ed1480ec]{color:#18a058b3;font-weight:600}.logs-header-codex .log-col[data-v-ed1480ec]{color:#3b82f6b3;font-weight:600}.logs-header-gemini .log-col[data-v-ed1480ec]{color:#a855f7b3;font-weight:600}.logs-header-opencode .log-col[data-v-ed1480ec]{color:#ea580cb3;font-weight:600}[data-theme=dark] .logs-header-claude .log-col[data-v-ed1480ec]{color:#34d399a6}[data-theme=dark] .logs-header-codex .log-col[data-v-ed1480ec]{color:#60a5faa6}[data-theme=dark] .logs-header-gemini .log-col[data-v-ed1480ec]{color:#c084fca6}[data-theme=dark] .logs-header-opencode .log-col[data-v-ed1480ec]{color:#fb923ca6}.logs-container[data-v-ed1480ec]{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden}.logs-container[data-v-ed1480ec]::-webkit-scrollbar{width:4px}.logs-container[data-v-ed1480ec]::-webkit-scrollbar-thumb{background:#18a0584d;border-radius:2px}.logs-container[data-v-ed1480ec]::-webkit-scrollbar-thumb:hover{background:#18a05880}.empty-logs[data-v-ed1480ec]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;color:var(--text-tertiary);min-height:200px;text-align:center}.log-row[data-v-ed1480ec]{display:flex;align-items:center;padding:10px 12px;min-height:40px;border-bottom:1px solid var(--border-primary);font-size:12px;transition:all .2s ease;background:var(--bg-primary);position:relative}.log-row[data-v-ed1480ec]:nth-child(2n){background:var(--bg-secondary)}.log-row[data-v-ed1480ec]:hover{background:var(--hover-bg);transform:translate(2px)}.log-row.new-log[data-v-ed1480ec]{animation:newLogPulse-ed1480ec 4.5s cubic-bezier(.25,.46,.45,.94) forwards;border-left:3px solid #18a058}@keyframes newLogPulse-ed1480ec{0%{background:linear-gradient(90deg,#18a05826,#18a0580f);box-shadow:0 0 8px #18a05833}5%{background:linear-gradient(90deg,#18a0582e,#18a05814);box-shadow:0 0 12px 1px #18a05840}15%{background:linear-gradient(90deg,#18a05829,#18a05812);box-shadow:0 0 10px 1px #18a05833}30%{background:linear-gradient(90deg,#18a0581f,#18a0580d);box-shadow:0 0 6px #18a05826}50%{background:linear-gradient(90deg,#18a05814,#18a05808);box-shadow:0 0 4px #18a0581a}70%{background:linear-gradient(90deg,#18a0580a,#18a05804);box-shadow:0 0 2px #18a0580f}85%{background:linear-gradient(90deg,#18a05805,#18a05802);box-shadow:0 0 1px #18a05808}to{background:transparent;box-shadow:0 0 #18a05800;border-left-color:transparent}}[data-theme=dark] .log-row.new-log[data-v-ed1480ec]{animation:newLogPulseDark-ed1480ec 4.5s cubic-bezier(.25,.46,.45,.94) forwards}@keyframes newLogPulseDark-ed1480ec{0%{background:linear-gradient(90deg,#18a05833,#18a05814);box-shadow:0 0 10px #18a05840}5%{background:linear-gradient(90deg,#18a0583d,#18a0581a);box-shadow:0 0 14px 2px #18a0584d}15%{background:linear-gradient(90deg,#18a05836,#18a05817);box-shadow:0 0 12px 1px #18a05840}30%{background:linear-gradient(90deg,#18a05829,#18a05812);box-shadow:0 0 8px 1px #18a0582e}50%{background:linear-gradient(90deg,#18a0581c,#18a0580b);box-shadow:0 0 5px #18a0581f}70%{background:linear-gradient(90deg,#18a0580f,#18a05806);box-shadow:0 0 3px #18a05814}85%{background:linear-gradient(90deg,#18a05808,#18a05803);box-shadow:0 0 1px #18a0580a}to{background:transparent;box-shadow:0 0 #18a05800;border-left-color:transparent}}.log-row.new-log.action-row[data-v-ed1480ec]{border-left:3px solid #18a058}.log-row.action-row[data-v-ed1480ec]{background:linear-gradient(90deg,#18a0581f,#18a0580a);border-left:3px solid #18a058;padding-left:8px}.log-row.error-row[data-v-ed1480ec]{background:linear-gradient(90deg,#d0305024,#d030500a);border-left:3px solid #d03050;padding-left:8px}.log-row.action-row[data-v-ed1480ec]:hover{background:linear-gradient(90deg,#18a0582e,#18a05814)}.log-row.error-row[data-v-ed1480ec]:hover{background:linear-gradient(90deg,#d0305033,#d0305014)}.action-content[data-v-ed1480ec]{display:flex;align-items:center;gap:8px;width:100%}.action-msg[data-v-ed1480ec]{flex:1;font-size:11px;color:#18a058;font-weight:600;letter-spacing:.2px}.action-msg.error-msg[data-v-ed1480ec]{color:#d03050}.action-time[data-v-ed1480ec]{font-size:10px;font-family:SF Mono,Monaco,monospace;color:var(--text-tertiary);background:#18a0581a;padding:2px 6px;border-radius:4px}.action-time.error-time[data-v-ed1480ec]{background:#d030501f}.log-col[data-v-ed1480ec]{display:flex;align-items:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-channel[data-v-ed1480ec]{min-width:0}.col-channel .n-tag[data-v-ed1480ec]{max-width:100%;font-size:11px;font-weight:600;border-radius:4px;padding:3px 10px}.col-token[data-v-ed1480ec]{justify-content:center;font-family:SF Mono,Monaco,Consolas,monospace;font-size:12px;font-weight:600;color:var(--text-secondary);background:#00000008;padding:4px 8px;border-radius:4px;margin:0 3px}[data-theme=dark] .col-token[data-v-ed1480ec]{background:#ffffff0f}.col-time[data-v-ed1480ec]{justify-content:flex-end;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px;font-weight:500;color:var(--text-tertiary);padding-right:2px;opacity:.85}.log-row:hover .col-time[data-v-ed1480ec]{opacity:1;color:var(--text-secondary)}.col-channel-claude[data-v-ed1480ec]{flex:2 1 60px;min-width:50px}.col-token-claude[data-v-ed1480ec]{flex:1 1 40px;min-width:35px}.col-time-claude[data-v-ed1480ec]{flex:1.5 1 55px;min-width:50px}.col-channel-codex[data-v-ed1480ec]{flex:2 1 60px;min-width:50px}.col-token-codex[data-v-ed1480ec]{flex:1 1 40px;min-width:35px}.col-time-codex[data-v-ed1480ec]{flex:1.5 1 55px;min-width:50px}.col-channel-gemini[data-v-ed1480ec]{flex:2.5 1 70px;min-width:55px}.col-token-gemini[data-v-ed1480ec]{flex:1.2 1 45px;min-width:40px}.col-time-gemini[data-v-ed1480ec]{flex:1.8 1 60px;min-width:55px}.col-channel-opencode[data-v-ed1480ec]{flex:2.5 1 70px;min-width:55px}.col-token-opencode[data-v-ed1480ec]{flex:1.2 1 45px;min-width:40px}.col-time-opencode[data-v-ed1480ec]{flex:1.8 1 60px;min-width:55px}.claude-extra-area[data-v-ed1480ec]{display:flex;align-items:center;gap:6px;margin-left:auto}.mcp-count-tag[data-v-ed1480ec],.skills-count-tag[data-v-ed1480ec]{font-size:10px;font-weight:500;padding:0 8px;height:22px;line-height:22px;border-radius:4px;cursor:pointer;transition:all .2s ease}.mcp-count-tag.clickable[data-v-ed1480ec]:hover,.skills-count-tag.clickable[data-v-ed1480ec]:hover{transform:scale(1.03);filter:brightness(1.1)}.mcp-quick-panel[data-v-ed1480ec],.skills-quick-panel[data-v-ed1480ec]{padding:2px 0}.mcp-quick-panel .panel-title[data-v-ed1480ec],.skills-quick-panel .panel-title[data-v-ed1480ec]{display:flex;justify-content:space-between;align-items:center;padding:6px 10px 8px;border-bottom:1px solid var(--border-primary);margin-bottom:4px}.mcp-quick-panel .panel-title span[data-v-ed1480ec]:first-child,.skills-quick-panel .panel-title span[data-v-ed1480ec]:first-child{font-size:13px;font-weight:600;color:var(--text-primary)}.no-items[data-v-ed1480ec]{padding:16px 10px;text-align:center}.mcp-quick-list[data-v-ed1480ec],.skills-quick-list[data-v-ed1480ec]{max-height:300px;overflow-y:auto;padding:0 4px 4px}.mcp-quick-item[data-v-ed1480ec],.skill-quick-item[data-v-ed1480ec]{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:5px;margin-bottom:4px;background:var(--bg-secondary);transition:all .2s ease}.mcp-quick-item[data-v-ed1480ec]:hover,.skill-quick-item[data-v-ed1480ec]:hover{background:var(--hover-bg)}.mcp-item-icon[data-v-ed1480ec],.skill-item-icon[data-v-ed1480ec]{width:24px;height:24px;border-radius:5px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.mcp-item-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#3b82f626,#3b82f60d);color:#3b82f6}.skill-item-icon[data-v-ed1480ec]{background:linear-gradient(135deg,#18a05826,#18a0580d);color:#18a058}.mcp-item-info[data-v-ed1480ec],.skill-item-info[data-v-ed1480ec]{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}.mcp-item-name[data-v-ed1480ec],.skill-item-name[data-v-ed1480ec]{font-size:12px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mcp-item-type[data-v-ed1480ec]{font-size:10px;color:var(--text-tertiary);text-transform:uppercase}.skill-item-desc[data-v-ed1480ec]{font-size:10px;color:var(--text-tertiary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mcp-item-status[data-v-ed1480ec]{flex-shrink:0}.mcp-item-status .status-dot[data-v-ed1480ec]{width:8px;height:8px;border-radius:50%;background:var(--border-secondary)}.mcp-item-status.online .status-dot[data-v-ed1480ec]{background:#18a058;box-shadow:0 0 6px #18a05880}.mcp-item-status.error .status-dot[data-v-ed1480ec]{background:#d03050;box-shadow:0 0 6px #d0305080}.mcp-quick-list[data-v-ed1480ec]::-webkit-scrollbar,.skills-quick-list[data-v-ed1480ec]::-webkit-scrollbar{width:4px}.mcp-quick-list[data-v-ed1480ec]::-webkit-scrollbar-thumb,.skills-quick-list[data-v-ed1480ec]::-webkit-scrollbar-thumb{background:#00000026;border-radius:2px}[data-theme=dark] .mcp-quick-list[data-v-ed1480ec]::-webkit-scrollbar-thumb,[data-theme=dark] .skills-quick-list[data-v-ed1480ec]::-webkit-scrollbar-thumb{background:#ffffff26}.skills-button[data-v-ed1480ec]{padding:6px!important;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:5px;background:var(--bg-secondary);border:1px solid var(--border-primary);transition:all .25s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 4px #0000000d}.skills-button .n-icon[data-v-ed1480ec]{color:var(--text-color-3);transition:all .25s ease}.skills-button[data-v-ed1480ec]:hover{background:linear-gradient(135deg,#18a0581a,#18a0580d);border-color:#18a0584d;box-shadow:0 4px 12px #18a05826;transform:translateY(-1px)}.skills-button:hover .n-icon[data-v-ed1480ec]{color:#18a058;transform:scale(1.1)}.skills-button[data-v-ed1480ec]:active{transform:translateY(0);box-shadow:0 2px 4px #0000000d}.lock-button[data-v-ed1480ec]{margin-left:6px;padding:6px!important;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:5px;background:var(--bg-secondary);border:1px solid var(--border-primary);transition:all .25s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 4px #0000000d}.lock-button .n-icon[data-v-ed1480ec]{color:var(--text-color-3);transition:all .25s ease}.lock-button[data-v-ed1480ec]:hover{background:linear-gradient(135deg,#6b72801a,#6b72800d);border-color:#6b72804d;box-shadow:0 4px 12px #0000001a;transform:translateY(-1px)}.lock-button:hover .n-icon[data-v-ed1480ec]{color:var(--text-color-1);transform:scale(1.1)}.lock-button[data-v-ed1480ec]:active{transform:translateY(0);box-shadow:0 2px 4px #0000000d}.locked-overlay[data-v-ed1480ec]{flex:1;display:flex;align-items:center;justify-content:center;border-radius:6px;margin:10px;position:relative;overflow:hidden;background:var(--bg-secondary);border:1px solid var(--border-primary);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.locked-overlay[data-v-ed1480ec]:before{content:"";position:absolute;width:400px;height:400px;border-radius:50%;top:50%;left:50%;transform:translate(-50%,-50%);opacity:.4;filter:blur(60px);pointer-events:none}.locked-claude[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(24,160,88,.03) 0%,var(--bg-secondary) 50%,rgba(24,160,88,.02) 100%)}.locked-claude[data-v-ed1480ec]:before{background:radial-gradient(circle,rgba(24,160,88,.15) 0%,transparent 70%)}.locked-codex[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(59,130,246,.03) 0%,var(--bg-secondary) 50%,rgba(59,130,246,.02) 100%)}.locked-codex[data-v-ed1480ec]:before{background:radial-gradient(circle,rgba(59,130,246,.15) 0%,transparent 70%)}.locked-gemini[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(168,85,247,.03) 0%,var(--bg-secondary) 50%,rgba(168,85,247,.02) 100%)}.locked-gemini[data-v-ed1480ec]:before{background:radial-gradient(circle,rgba(168,85,247,.15) 0%,transparent 70%)}.locked-opencode[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(234,88,12,.03) 0%,var(--bg-secondary) 50%,rgba(234,88,12,.02) 100%)}.locked-opencode[data-v-ed1480ec]:before{background:radial-gradient(circle,rgba(234,88,12,.15) 0%,transparent 70%)}.locked-content[data-v-ed1480ec]{display:flex;flex-direction:column;align-items:center;gap:20px;padding:60px 40px;text-align:center;position:relative;z-index:1}.lock-icon[data-v-ed1480ec]{width:96px;height:96px;display:flex;align-items:center;justify-content:center;border-radius:10px;background:var(--bg-primary);border:2px solid var(--border-primary);margin-bottom:8px;position:relative;box-shadow:0 8px 24px #0000001f;animation:lock-float-ed1480ec 3s ease-in-out infinite}@keyframes lock-float-ed1480ec{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}.lock-icon[data-v-ed1480ec]:before{content:"";position:absolute;top:-8px;right:-8px;bottom:-8px;left:-8px;border-radius:20px;opacity:.6;filter:blur(12px)}.locked-claude .lock-icon[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(24,160,88,.12) 0%,var(--bg-primary) 100%);border-color:#18a05840;box-shadow:0 8px 24px #18a05826,0 0 0 1px #18a0581a inset}.locked-claude .lock-icon[data-v-ed1480ec]:before{background:radial-gradient(circle,rgba(24,160,88,.3) 0%,transparent 60%)}.locked-claude .lock-icon .n-icon[data-v-ed1480ec]{color:#18a058;filter:drop-shadow(0 2px 4px rgba(24,160,88,.3))}.locked-codex .lock-icon[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(59,130,246,.12) 0%,var(--bg-primary) 100%);border-color:#3b82f640;box-shadow:0 8px 24px #3b82f626,0 0 0 1px #3b82f61a inset}.locked-codex .lock-icon[data-v-ed1480ec]:before{background:radial-gradient(circle,rgba(59,130,246,.3) 0%,transparent 60%)}.locked-codex .lock-icon .n-icon[data-v-ed1480ec]{color:#3b82f6;filter:drop-shadow(0 2px 4px rgba(59,130,246,.3))}.locked-gemini .lock-icon[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(168,85,247,.12) 0%,var(--bg-primary) 100%);border-color:#a855f740;box-shadow:0 8px 24px #a855f726,0 0 0 1px #a855f71a inset}.locked-gemini .lock-icon[data-v-ed1480ec]:before{background:radial-gradient(circle,rgba(168,85,247,.3) 0%,transparent 60%)}.locked-gemini .lock-icon .n-icon[data-v-ed1480ec]{color:#a855f7;filter:drop-shadow(0 2px 4px rgba(168,85,247,.3))}.locked-opencode .lock-icon[data-v-ed1480ec]{background:linear-gradient(135deg,rgba(234,88,12,.12) 0%,var(--bg-primary) 100%);border-color:#ea580c40;box-shadow:0 8px 24px #ea580c26,0 0 0 1px #ea580c1a inset}.locked-opencode .lock-icon[data-v-ed1480ec]:before{background:radial-gradient(circle,rgba(234,88,12,.3) 0%,transparent 60%)}.locked-opencode .lock-icon .n-icon[data-v-ed1480ec]{color:#ea580c;filter:drop-shadow(0 2px 4px rgba(234,88,12,.3))}.lock-icon .n-icon[data-v-ed1480ec]{opacity:.85;position:relative;z-index:1}.locked-title[data-v-ed1480ec]{font-size:17px;font-weight:600;color:var(--text-color-1);margin:0;letter-spacing:.3px}.locked-hint[data-v-ed1480ec]{font-size:13px;color:var(--text-color-3);max-width:220px;line-height:1.7;opacity:.9}.channel-status[data-v-ed1480ec]{cursor:pointer;padding:4px 8px!important;border-radius:4px;transition:all .2s ease}.channel-status[data-v-ed1480ec]:hover{background:var(--hover-bg)}.channel-quick-panel[data-v-ed1480ec]{padding:4px 0}.panel-title[data-v-ed1480ec]{display:flex;justify-content:space-between;align-items:center;padding:8px 12px 12px;border-bottom:1px solid var(--border-primary);margin-bottom:8px}.panel-title span[data-v-ed1480ec]:first-child{font-size:13px;font-weight:600;color:var(--text-primary)}.no-channels[data-v-ed1480ec]{padding:24px 12px;text-align:center}.channel-quick-list[data-v-ed1480ec]{max-height:360px;overflow-y:auto}.channel-quick-item[data-v-ed1480ec]{display:flex;flex-direction:column;gap:8px;padding:10px 12px;border-radius:6px;margin:0 4px 6px;background:var(--bg-secondary);transition:all .2s ease}.channel-quick-item[data-v-ed1480ec]:hover{background:var(--hover-bg)}.channel-quick-item.disabled[data-v-ed1480ec]{opacity:.6}.channel-quick-info[data-v-ed1480ec]{display:flex;align-items:center;gap:8px;width:100%}.channel-quick-name[data-v-ed1480ec]{font-size:13px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.channel-metrics[data-v-ed1480ec]{display:flex;gap:6px;width:100%}.channel-metrics .metric-item[data-v-ed1480ec]{flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;padding:6px 4px;background:var(--bg-primary);border-radius:4px;border:1px solid var(--border-primary)}.channel-metrics .metric-label[data-v-ed1480ec]{font-size:10px;color:var(--text-tertiary);font-weight:500}.channel-metrics .metric-value[data-v-ed1480ec]{font-size:12px;font-weight:700;color:var(--text-primary);font-family:SF Mono,Monaco,monospace}.channel-metrics .metric-value.active[data-v-ed1480ec]{color:#f59e0b}.channel-switching-tip[data-v-ed1480ec]{font-size:11px;color:var(--text-tertiary);padding:0 2px}.channel-quick-item.disabled .channel-metrics .metric-value[data-v-ed1480ec]{color:var(--text-tertiary)}.channel-quick-list[data-v-ed1480ec]::-webkit-scrollbar{width:4px}.channel-quick-list[data-v-ed1480ec]::-webkit-scrollbar-thumb{background:#00000026;border-radius:2px}[data-theme=dark] .channel-quick-list[data-v-ed1480ec]::-webkit-scrollbar-thumb{background:#ffffff26}@media (max-width: 1024px){.channel-column[data-v-ed1480ec]{border-radius:6px}.card-header[data-v-ed1480ec]{padding:8px 10px}.card-title[data-v-ed1480ec]{font-size:13px}.stats-inline[data-v-ed1480ec]{gap:6px}.stat-inline-item[data-v-ed1480ec]{padding:8px}.stat-value[data-v-ed1480ec]{font-size:14px}.stat-label[data-v-ed1480ec]{font-size:9px}.logs-table-header[data-v-ed1480ec]{padding:8px 10px;font-size:10px}.log-row[data-v-ed1480ec]{padding:8px 10px;font-size:11px}}@media (max-width: 768px){.channel-column[data-v-ed1480ec]{border-radius:6px;min-height:300px;height:auto;max-height:400px}.card-header[data-v-ed1480ec]{padding:8px;gap:6px}.card-title[data-v-ed1480ec]{font-size:12px}.stats-inline[data-v-ed1480ec]{gap:4px}.stat-inline-item[data-v-ed1480ec]{padding:6px;gap:6px}.stat-icon-dot[data-v-ed1480ec]{width:6px;height:6px}.stat-value[data-v-ed1480ec]{font-size:13px}.stat-label[data-v-ed1480ec]{font-size:8px}.logs-card[data-v-ed1480ec]{min-height:150px}.logs-table-header[data-v-ed1480ec]{padding:6px 8px;font-size:9px}.log-row[data-v-ed1480ec]{padding:6px 8px;font-size:10px;min-height:32px}.col-token[data-v-ed1480ec]{font-size:10px;padding:2px 4px}.col-time[data-v-ed1480ec]{font-size:9px}.mcp-count-tag[data-v-ed1480ec],.skills-count-tag[data-v-ed1480ec]{font-size:9px;padding:0 6px;height:18px;line-height:18px}.skills-button[data-v-ed1480ec]{padding:4px 8px;font-size:10px;gap:4px}.lock-button[data-v-ed1480ec]{width:26px;height:26px}}@media (max-width: 640px){.channel-column[data-v-ed1480ec]{min-height:250px;max-height:350px}.card-header[data-v-ed1480ec]{padding:6px;gap:4px;flex-wrap:wrap}.card-title[data-v-ed1480ec]{font-size:11px}.stats-card .card-content[data-v-ed1480ec]{padding:6px}.stats-inline[data-v-ed1480ec]{gap:3px;flex-wrap:wrap}.stat-inline-item[data-v-ed1480ec]{padding:5px;gap:4px;min-width:calc(33% - 3px);flex:1 1 auto}.stat-icon-dot[data-v-ed1480ec]{width:5px;height:5px}.stat-value[data-v-ed1480ec]{font-size:12px}.stat-label[data-v-ed1480ec]{font-size:7px}.logs-card[data-v-ed1480ec]{min-height:120px}.logs-table-header[data-v-ed1480ec]{padding:5px 6px;font-size:8px;letter-spacing:.3px}.log-row[data-v-ed1480ec]{padding:5px 6px;font-size:9px;min-height:28px}.col-channel .n-tag[data-v-ed1480ec]{font-size:9px;padding:2px 6px}.col-token[data-v-ed1480ec]{font-size:9px;padding:2px 3px;margin:0 1px}.col-time[data-v-ed1480ec]{font-size:8px}.claude-extra-area[data-v-ed1480ec]{gap:4px}.mcp-count-tag[data-v-ed1480ec],.skills-count-tag[data-v-ed1480ec]{font-size:8px;padding:0 4px;height:16px;line-height:16px}.skills-button[data-v-ed1480ec]{padding:3px 6px;font-size:9px;gap:3px}.skills-button .n-icon[data-v-ed1480ec]{font-size:12px!important}.lock-button[data-v-ed1480ec]{width:24px;height:24px;margin-left:4px}.lock-button .n-icon[data-v-ed1480ec]{font-size:12px!important}.locked-content[data-v-ed1480ec]{padding:30px 20px;gap:12px}.lock-icon[data-v-ed1480ec]{width:64px;height:64px}.lock-icon .n-icon[data-v-ed1480ec]{font-size:28px!important}.lock-title[data-v-ed1480ec]{font-size:14px}.lock-subtitle[data-v-ed1480ec]{font-size:10px}.unlock-btn[data-v-ed1480ec]{padding:8px 16px;font-size:11px}}@media (max-width: 480px){.channel-column[data-v-ed1480ec]{min-height:220px;max-height:300px}.card-header[data-v-ed1480ec]{padding:5px}.card-title[data-v-ed1480ec]{font-size:10px}.stats-inline[data-v-ed1480ec]{gap:2px}.stat-inline-item[data-v-ed1480ec]{padding:4px;gap:3px}.stat-value[data-v-ed1480ec]{font-size:11px}.stat-label[data-v-ed1480ec]{font-size:6px}.logs-table-header[data-v-ed1480ec]{padding:4px 5px;font-size:7px}.log-row[data-v-ed1480ec]{padding:4px 5px;font-size:8px;min-height:24px}.col-token[data-v-ed1480ec]{font-size:8px}.col-time[data-v-ed1480ec]{font-size:7px}}.card[data-v-ed1480ec]:not(.logs-card) .n-collapse{background:transparent}.card[data-v-ed1480ec]:not(.logs-card) .n-collapse-item{background:transparent}.card[data-v-ed1480ec] .n-collapse-item__header{padding:12px 16px;background:transparent;transition:all .3s ease}.card[data-v-ed1480ec] .n-collapse-item__header:hover{background:#00000005}.card[data-v-ed1480ec] .n-collapse-item__header-main{width:100%}.card[data-v-ed1480ec]:not(.logs-card) .n-collapse-item__content-wrapper{padding:0 16px 12px}.card[data-v-ed1480ec]:not(.logs-card) .n-collapse-item__content-inner{padding-top:0}.chart-card[data-v-ed1480ec]:has(.n-collapse){padding:0}.dashboard-container[data-v-06100f0f]{height:100%;background:var(--bg-primary);overflow:hidden;padding:12px;box-sizing:border-box;display:flex;flex-direction:column}.dashboard-toolbar[data-v-06100f0f]{display:flex;justify-content:flex-end;margin-bottom:8px;flex-shrink:0}.analytics-link[data-v-06100f0f]{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--primary-color, #18a058);text-decoration:none;padding:4px 10px;border-radius:4px;background:#18a05814;transition:background .2s}.analytics-link[data-v-06100f0f]:hover{background:#18a05826}.analytics-link-icon[data-v-06100f0f]{font-size:14px}.dashboard-grid[data-v-06100f0f]{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;flex:1;min-height:0;overflow:hidden;box-sizing:border-box}.dashboard-grid[data-v-06100f0f] .sortable-ghost{opacity:.4}.dashboard-grid[data-v-06100f0f] .sortable-chosen{box-shadow:0 8px 24px #00000026}@media (max-width: 1600px){.dashboard-grid[data-v-06100f0f]{grid-template-columns:repeat(3,1fr)}}@media (max-width: 1200px){.dashboard-grid[data-v-06100f0f]{grid-template-columns:repeat(2,1fr)}}@media (max-width: 1024px){.dashboard-container[data-v-06100f0f]{padding:10px}.dashboard-grid[data-v-06100f0f]{gap:10px}}@media (max-width: 900px){.dashboard-grid[data-v-06100f0f]{grid-template-columns:1fr}}@media (max-width: 768px){.dashboard-container[data-v-06100f0f]{padding:8px;overflow-y:auto}.dashboard-grid[data-v-06100f0f]{gap:8px;overflow:visible;min-height:auto}}@media (max-width: 640px){.dashboard-container[data-v-06100f0f]{padding:6px}.dashboard-grid[data-v-06100f0f]{gap:6px}}@media (max-width: 480px){.dashboard-container[data-v-06100f0f]{padding:4px}.dashboard-grid[data-v-06100f0f]{gap:4px}}
|