coding-tool-x 3.8.9 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -387
- package/dist/web/assets/AgentsDrawer-DooV5Qhx.js +1 -0
- package/dist/web/assets/Analytics-BXRwqC-P.js +1 -0
- package/dist/web/assets/AssetPathField-B-LHvOxq.js +1 -0
- package/dist/web/assets/{ChatHistoryDrawer-BTmQ1aQr.js → ChatHistoryDrawer-CoHlGAxb.js} +1 -1
- package/dist/web/assets/{CollapseItem-CwqJk3bE.js → CollapseItem-kJkiHxFl.js} +1 -1
- package/dist/web/assets/CommandsDrawer-DLQrikcw.js +1 -0
- package/dist/web/assets/ConfigExportDrawer-BItwo0FQ.js +1 -0
- package/dist/web/assets/{ConfigTemplates-gyERg9iC.js → ConfigTemplates-R3YzzBT3.js} +1 -1
- package/dist/web/assets/{ConfigTemplatesDrawer-B17RqFi4.js → ConfigTemplatesDrawer-C_nPKrhx.js} +1 -1
- package/dist/web/assets/ConfigTemplatesPanel-BiwrNyYN.js +1 -0
- package/dist/web/assets/{Divider-DsdbkHrG.js → Divider-BLLhMTSt.js} +1 -1
- package/dist/web/assets/FavoritesDrawer-BAJ-AOpN.js +1 -0
- package/dist/web/assets/GatewayConvertDrawer-Av3yzwhP.js +1 -0
- package/dist/web/assets/Home-B01aL_SR.js +1 -0
- package/dist/web/assets/{MarkdownEditor-9TTwTS-U.js → MarkdownEditor-D75GGt5X.js} +1 -1
- package/dist/web/assets/McpDrawer-xNzJtT4X.js +1 -0
- package/dist/web/assets/McpFormDrawer-B240mJ5y.js +1 -0
- package/dist/web/assets/{PluginManager-BuRcWuBj.js → PluginManager-CgLjBdlr.js} +1 -1
- package/dist/web/assets/{PluginsDrawer-_zZENaQn.js → PluginsDrawer-DvJdwMXx.js} +1 -1
- package/dist/web/assets/PluginsPanel-kX14E_DT.js +1 -0
- package/dist/web/assets/ProjectList-CRtc3Hhx.js +1 -0
- package/dist/web/assets/PromptsDrawer-CvT9dA2N.js +1 -0
- package/dist/web/assets/RecentSessionsDrawer-DM1gf584.js +1 -0
- package/dist/web/assets/SessionCard-cZR2V4Br.js +1 -0
- package/dist/web/assets/SessionList-D7-P4Zme.js +1 -0
- package/dist/web/assets/SettingsDrawer-BFzaxbgC.css +1 -0
- package/dist/web/assets/SettingsDrawer-gW8kh-S8.js +1 -0
- package/dist/web/assets/{SkillManager-S698Hns8.js → SkillManager-D0BlI7CG.js} +1 -1
- package/dist/web/assets/{SkillsDrawer-Ms4lPCow.js → SkillsDrawer-BMB6uzqP.js} +1 -1
- package/dist/web/assets/SkillsPanel-BzR828De.js +1 -0
- package/dist/web/assets/Upload-3fNyOQrx.js +1 -0
- package/dist/web/assets/{WorkspaceDrawer-L7HJRc6u.js → WorkspaceDrawer-DvtBA58Q.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-DsoNg2z8.js → WorkspaceManager-BW5KtsHO.js} +1 -1
- package/dist/web/assets/WorkspacePanel-BC_xpAEZ.js +1 -0
- package/dist/web/assets/client-BgcNg4Bt.js +1 -0
- package/dist/web/assets/{headers-B5JWGn3v.js → headers-DbowkmZJ.js} +1 -1
- package/dist/web/assets/{icons-DmFe4b5j.js → icons-B-AzZoeE.js} +1 -1
- package/dist/web/assets/index-BFqnddoI.js +2 -0
- package/dist/web/assets/index-Bn8BUnwP.css +1 -0
- package/dist/web/assets/{light-0eavxNvt.js → light-C2X7hegj.js} +1 -1
- package/dist/web/assets/platforms-DrzAtnjY.js +1 -0
- package/dist/web/assets/platforms-mqqe_82d.js +1 -0
- package/dist/web/assets/project-config-BVt5s-pH.js +1 -0
- package/dist/web/assets/sessions-53-Fr68H.js +1 -0
- package/dist/web/assets/{sessions-D4yQtfKb.js → sessions-CaWUaysM.js} +1 -1
- package/dist/web/assets/use-message-DBsCm7FJ.js +1 -0
- package/dist/web/assets/{useResponsiveDrawer-V_onl9NV.js → useResponsiveDrawer-Ckgj760z.js} +1 -1
- package/dist/web/assets/{workspaces-mjyPVGS8.js → workspaces-DQuZd4qw.js} +1 -1
- package/dist/web/index.html +8 -8
- package/docs/analytics.png +0 -0
- package/docs/home.png +0 -0
- package/package.json +4 -2
- package/src/commands/export-config.js +17 -211
- package/src/config/model-metadata.json +180 -16
- package/src/platforms/channel-auth-service.js +1 -1
- package/src/platforms/commands-service.js +28 -0
- package/src/platforms/driver-registry.js +1 -0
- package/src/platforms/drivers/claude/channels-implementation.js +79 -90
- package/src/platforms/drivers/claude/native-config-implementation.js +3 -4
- package/src/platforms/drivers/codex/channels-implementation.js +34 -49
- package/src/platforms/drivers/codex/native-config-implementation.js +3 -51
- package/src/platforms/drivers/dsh/api-operations.js +1 -1
- package/src/platforms/drivers/dsh/channels-implementation.js +28 -8
- package/src/platforms/drivers/dsh/channels.js +0 -18
- package/src/platforms/drivers/dsh/common.js +7 -0
- package/src/platforms/drivers/dsh/native-config.js +7 -2
- package/src/platforms/drivers/gemini/channels-implementation.js +47 -55
- package/src/platforms/drivers/gemini/native-config-implementation.js +8 -20
- package/src/platforms/drivers/generic-native-config.js +20 -0
- package/src/platforms/drivers/native-config-snapshot.js +30 -4
- package/src/platforms/drivers/omp/channels-implementation.js +51 -17
- package/src/platforms/drivers/omp/native-config-implementation.js +10 -17
- package/src/platforms/drivers/opencode/channels-implementation.js +6 -0
- package/src/platforms/drivers/opencode/native-config-implementation.js +3 -67
- package/src/platforms/manifest-schema.js +35 -2
- package/src/platforms/manifests/claude.json +0 -8
- package/src/platforms/manifests/codex.json +0 -8
- package/src/platforms/manifests/dsh.json +6 -9
- package/src/platforms/manifests/gemini.json +0 -8
- package/src/platforms/manifests/omp.json +0 -8
- package/src/platforms/manifests/opencode.json +0 -8
- package/src/platforms/native-oauth-adapters.js +33 -33
- package/src/platforms/remote-notification-providers.js +5 -5
- package/src/server/api/settings.js +6 -5
- package/src/server/index.js +2 -0
- package/src/server/services/bounded-content.js +60 -0
- package/src/server/services/channel-balance.js +10 -4
- package/src/server/services/config-export-service.js +2 -2
- package/src/server/services/config-templates-service.js +5 -1
- package/src/server/services/plugins-service.js +162 -85
- package/src/server/services/session-history-maintenance-worker.js +71 -0
- package/src/server/services/session-history-maintenance.js +166 -0
- package/src/server/services/skill-service.js +23 -3
- package/src/server/services/speed-test.js +0 -72
- package/src/shared/channel-driver.js +16 -0
- package/src/shared/driver-factories/api.js +1 -0
- package/src/utils/native-config-patcher.js +474 -0
- package/dist/web/assets/AgentsDrawer-Cj5CJ4d9.js +0 -1
- package/dist/web/assets/Analytics-1doS-8uC.js +0 -1
- package/dist/web/assets/AssetPathField-C9TOPl7o.js +0 -1
- package/dist/web/assets/CommandsDrawer-CaZWDI_G.js +0 -1
- package/dist/web/assets/ConfigExportDrawer-C3vSZEsS.js +0 -1
- package/dist/web/assets/ConfigTemplatesPanel-DKIC_FqG.js +0 -1
- package/dist/web/assets/FavoritesDrawer-DaziQmBp.js +0 -1
- package/dist/web/assets/GatewayConvertDrawer-OMgWUUSc.js +0 -1
- package/dist/web/assets/Home-DOSUTfrE.js +0 -1
- package/dist/web/assets/McpDrawer-I8rl8lGH.js +0 -1
- package/dist/web/assets/McpFormDrawer-DEP3C7ut.js +0 -1
- package/dist/web/assets/PluginsPanel-Bs5qZ-TK.js +0 -1
- package/dist/web/assets/ProjectList-BSxuL2td.js +0 -1
- package/dist/web/assets/PromptsDrawer-CoZ-ZtsY.js +0 -1
- package/dist/web/assets/RecentSessionsDrawer-B_17aJBG.js +0 -1
- package/dist/web/assets/SessionCard-BL_x0d3t.js +0 -1
- package/dist/web/assets/SessionList-DhRYZ6vl.js +0 -1
- package/dist/web/assets/SettingsDrawer-Dw5NUgHC.css +0 -1
- package/dist/web/assets/SettingsDrawer-fYb0DU7X.js +0 -1
- package/dist/web/assets/SkillsPanel-rqnqAOGL.js +0 -1
- package/dist/web/assets/SpeedTestDrawer-Bbn38SfV.js +0 -1
- package/dist/web/assets/SpeedTestDrawer-Dc0WToJ_.css +0 -1
- package/dist/web/assets/Upload-CdyVHxCI.js +0 -1
- package/dist/web/assets/WorkspacePanel-Be8PVZah.js +0 -1
- package/dist/web/assets/client-UDwXBP9i.js +0 -1
- package/dist/web/assets/index-3Lp6z8TQ.css +0 -1
- package/dist/web/assets/index-BKlAWTH-.js +0 -2
- package/dist/web/assets/platforms-BmzzwnSw.js +0 -1
- package/dist/web/assets/platforms-DWXgmy2w.js +0 -1
- package/dist/web/assets/project-config-B2baPzYL.js +0 -1
- package/dist/web/assets/sessions-CC0j-KH_.js +0 -1
- package/dist/web/assets/use-message-DqCwefG6.js +0 -1
|
@@ -20,7 +20,7 @@ const PROVIDER_METADATA = Object.freeze({
|
|
|
20
20
|
label: '微信',
|
|
21
21
|
legacyName: '微信 Bot',
|
|
22
22
|
description: '使用个人微信 iLink token 发送通知',
|
|
23
|
-
hint: '
|
|
23
|
+
hint: '填写 iLink Token,或提供 token.json 路径。',
|
|
24
24
|
defaults: Object.freeze({ tokenFile: '~/.wxbot/token.json', botToken: '', targetUserId: '', contextToken: '' }),
|
|
25
25
|
fields: Object.freeze([
|
|
26
26
|
Object.freeze({ key: 'tokenFile', label: 'token.json 路径', type: 'input', placeholder: '~/.wxbot/token.json', wide: true }),
|
|
@@ -33,7 +33,7 @@ const PROVIDER_METADATA = Object.freeze({
|
|
|
33
33
|
label: 'QQ',
|
|
34
34
|
legacyName: 'QQ Bot',
|
|
35
35
|
description: '通过 OneBot / NapCat / go-cqhttp 兼容 HTTP 接口发送通知',
|
|
36
|
-
hint: '
|
|
36
|
+
hint: '通过 OneBot 兼容服务发送通知。',
|
|
37
37
|
defaults: Object.freeze({ endpoint: 'http://127.0.0.1:3000', accessToken: '', targetType: 'private', targetId: '' }),
|
|
38
38
|
fields: Object.freeze([
|
|
39
39
|
Object.freeze({ key: 'endpoint', label: 'OneBot HTTP 地址', type: 'input', placeholder: 'http://127.0.0.1:3000', wide: true }),
|
|
@@ -59,7 +59,7 @@ const PROVIDER_METADATA = Object.freeze({
|
|
|
59
59
|
label: '企业微信',
|
|
60
60
|
legacyName: '企业微信 Bot',
|
|
61
61
|
description: '通过企业微信群机器人 Webhook 发送通知',
|
|
62
|
-
hint: '
|
|
62
|
+
hint: '填写企业微信群机器人的 Webhook URL。',
|
|
63
63
|
defaults: Object.freeze({ webhookUrl: '' }),
|
|
64
64
|
fields: Object.freeze([
|
|
65
65
|
Object.freeze({ key: 'webhookUrl', label: 'Webhook URL', type: 'input', placeholder: '企业微信群机器人 Webhook URL', wide: true })
|
|
@@ -68,13 +68,13 @@ const PROVIDER_METADATA = Object.freeze({
|
|
|
68
68
|
dingtalkBot: Object.freeze({
|
|
69
69
|
label: '钉钉',
|
|
70
70
|
legacyName: '钉钉 Bot',
|
|
71
|
-
description: '支持钉钉自定义机器人 Webhook
|
|
71
|
+
description: '支持钉钉自定义机器人 Webhook 和应用模式',
|
|
72
72
|
hint: 'App 模式需要 App Key / App Secret,并填写用户 ID 或群会话 ID。',
|
|
73
73
|
defaults: Object.freeze({ mode: 'webhook', webhookUrl: '', clientId: '', clientSecret: '', targetType: 'group', targetId: '' }),
|
|
74
74
|
fields: Object.freeze([
|
|
75
75
|
Object.freeze({ key: 'mode', label: '接入模式', type: 'select', options: Object.freeze([
|
|
76
76
|
Object.freeze({ label: 'Webhook', value: 'webhook' }),
|
|
77
|
-
Object.freeze({ label: '
|
|
77
|
+
Object.freeze({ label: '应用模式', value: 'app' })
|
|
78
78
|
]) }),
|
|
79
79
|
Object.freeze({ key: 'clientId', label: 'App Key', type: 'input', placeholder: 'Client ID', visibleWhen: Object.freeze({ key: 'mode', equals: 'app' }) }),
|
|
80
80
|
Object.freeze({ key: 'clientSecret', label: 'App Secret', type: 'secret', placeholder: 'Secret', visibleWhen: Object.freeze({ key: 'mode', equals: 'app' }) }),
|
|
@@ -46,9 +46,11 @@ function normalizeSpeedTestModels(value) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
function getModelPlatformEntries(catalog = getPlatformCatalog()) {
|
|
49
|
-
return catalog.list({ capability: 'channels' }).map(manifest => ({
|
|
49
|
+
return catalog.list({ capability: 'channels', enabledOnly: false }).map(manifest => ({
|
|
50
50
|
key: manifest.key,
|
|
51
|
-
|
|
51
|
+
label: manifest.label || manifest.title || manifest.key,
|
|
52
|
+
catalogKey: manifest.modelConfig?.catalogKey || manifest.key,
|
|
53
|
+
models: getModelIdsByToolType(manifest.modelConfig?.catalogKey || manifest.key)
|
|
52
54
|
}));
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -96,9 +98,7 @@ function handleGetModelSettings(req, res) {
|
|
|
96
98
|
const catalog = getPlatformCatalog();
|
|
97
99
|
const platformEntries = getModelPlatformEntries(catalog);
|
|
98
100
|
const defaultSpeedTestModels = resolveDefaultSpeedTestModels(config, catalog);
|
|
99
|
-
const toolModels = Object.fromEntries(
|
|
100
|
-
platformEntries.map(({ key, catalogKey }) => [key, getModelIdsByToolType(catalogKey)])
|
|
101
|
-
);
|
|
101
|
+
const toolModels = Object.fromEntries(platformEntries.map(({ key, models }) => [key, models]));
|
|
102
102
|
|
|
103
103
|
// Build merged table: built-in + user overrides
|
|
104
104
|
const merged = {};
|
|
@@ -128,6 +128,7 @@ function handleGetModelSettings(req, res) {
|
|
|
128
128
|
builtinModelIds: Object.keys(MODEL_METADATA),
|
|
129
129
|
lastUpdated: METADATA_LAST_UPDATED,
|
|
130
130
|
metadataSource: METADATA_SOURCE,
|
|
131
|
+
modelPlatforms: platformEntries,
|
|
131
132
|
toolModels,
|
|
132
133
|
defaultSpeedTestModels
|
|
133
134
|
});
|
package/src/server/index.js
CHANGED
|
@@ -26,6 +26,7 @@ const {
|
|
|
26
26
|
const { createApiRequestLogger } = require('./services/request-logger');
|
|
27
27
|
const { inspectWebBuildState, ensureWebDistReady } = require('./services/web-build');
|
|
28
28
|
const { ensureHttpsCredentials } = require('./services/https-cert');
|
|
29
|
+
const { scheduleSessionHistoryMaintenance } = require('./services/session-history-maintenance');
|
|
29
30
|
const notificationHooks = require('../platforms/notification-hooks');
|
|
30
31
|
const {
|
|
31
32
|
prepareNativeCliLogObserver,
|
|
@@ -323,6 +324,7 @@ async function startServer(port, host = '127.0.0.1', options = {}) {
|
|
|
323
324
|
server.once('listening', onListening);
|
|
324
325
|
server.once('error', onError);
|
|
325
326
|
});
|
|
327
|
+
scheduleSessionHistoryMaintenance(PATHS.sessionHistoryIndex);
|
|
326
328
|
|
|
327
329
|
console.log(`\n[START] Coding-Tool Web UI running at:`);
|
|
328
330
|
const protocol = useHttps ? 'https' : 'http';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
function normalizeLimit(maxBytes) {
|
|
6
|
+
const limit = Number(maxBytes);
|
|
7
|
+
if (!Number.isSafeInteger(limit) || limit <= 0) {
|
|
8
|
+
throw new Error('A positive byte limit is required');
|
|
9
|
+
}
|
|
10
|
+
return limit;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function truncateUtf8(value, maxBytes) {
|
|
14
|
+
const limit = normalizeLimit(maxBytes);
|
|
15
|
+
const text = String(value ?? '');
|
|
16
|
+
const bytes = Buffer.byteLength(text, 'utf8');
|
|
17
|
+
if (bytes <= limit) {
|
|
18
|
+
return { text, bytes, truncated: false };
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
text: Buffer.from(text, 'utf8').subarray(0, limit).toString('utf8'),
|
|
22
|
+
bytes,
|
|
23
|
+
truncated: true
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function readTextFileLimited(filePath, maxBytes, fsImpl = fs) {
|
|
28
|
+
const limit = normalizeLimit(maxBytes);
|
|
29
|
+
const totalBytes = fsImpl.statSync(filePath).size;
|
|
30
|
+
if (totalBytes <= limit) {
|
|
31
|
+
return {
|
|
32
|
+
text: fsImpl.readFileSync(filePath, 'utf8'),
|
|
33
|
+
bytes: totalBytes,
|
|
34
|
+
truncated: false
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const fd = fsImpl.openSync(filePath, 'r');
|
|
39
|
+
try {
|
|
40
|
+
const buffer = Buffer.allocUnsafe(limit);
|
|
41
|
+
let offset = 0;
|
|
42
|
+
while (offset < limit) {
|
|
43
|
+
const bytesRead = fsImpl.readSync(fd, buffer, offset, limit - offset, offset);
|
|
44
|
+
if (!bytesRead) break;
|
|
45
|
+
offset += bytesRead;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
text: buffer.subarray(0, offset).toString('utf8'),
|
|
49
|
+
bytes: totalBytes,
|
|
50
|
+
truncated: true
|
|
51
|
+
};
|
|
52
|
+
} finally {
|
|
53
|
+
fsImpl.closeSync(fd);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = {
|
|
58
|
+
readTextFileLimited,
|
|
59
|
+
truncateUtf8
|
|
60
|
+
};
|
|
@@ -14,6 +14,7 @@ const {
|
|
|
14
14
|
} = require('./snapshot-cache');
|
|
15
15
|
|
|
16
16
|
const CACHE_TTL_MS = 5 * 60 * 1000;
|
|
17
|
+
const OAUTH_QUOTA_CACHE_TTL_MS = 60 * 1000;
|
|
17
18
|
const REQUEST_TIMEOUT_MS = 8000;
|
|
18
19
|
const MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
19
20
|
const QUOTA_UNIT = 500000;
|
|
@@ -124,6 +125,10 @@ function isOAuthChannel(channel = {}) {
|
|
|
124
125
|
return channel?.authMode === 'oauth';
|
|
125
126
|
}
|
|
126
127
|
|
|
128
|
+
function getBalanceCacheTtlMs(channel = {}) {
|
|
129
|
+
return isOAuthChannel(channel) ? OAUTH_QUOTA_CACHE_TTL_MS : CACHE_TTL_MS;
|
|
130
|
+
}
|
|
131
|
+
|
|
127
132
|
function resolveOAuthCacheIdentity(channel = {}) {
|
|
128
133
|
const ref = channel.authRef && typeof channel.authRef === 'object' ? channel.authRef : {};
|
|
129
134
|
return [
|
|
@@ -1581,6 +1586,7 @@ function makeFallbackBalanceSnapshot(currentTime = Date.now()) {
|
|
|
1581
1586
|
async function refreshChannelBalanceSnapshot(source, channel, options = {}) {
|
|
1582
1587
|
const force = options.force === true;
|
|
1583
1588
|
const currentTime = options.now || Date.now();
|
|
1589
|
+
const cacheTtlMs = getBalanceCacheTtlMs(channel);
|
|
1584
1590
|
const key = buildCacheKey(source, channel);
|
|
1585
1591
|
const cached = balanceCache.get(key);
|
|
1586
1592
|
|
|
@@ -1598,7 +1604,7 @@ async function refreshChannelBalanceSnapshot(source, channel, options = {}) {
|
|
|
1598
1604
|
if (snapshot.visible) {
|
|
1599
1605
|
balanceCache.set(key, {
|
|
1600
1606
|
snapshot,
|
|
1601
|
-
expiresAt: currentTime +
|
|
1607
|
+
expiresAt: currentTime + cacheTtlMs
|
|
1602
1608
|
});
|
|
1603
1609
|
return snapshot;
|
|
1604
1610
|
}
|
|
@@ -1613,7 +1619,7 @@ async function refreshChannelBalanceSnapshot(source, channel, options = {}) {
|
|
|
1613
1619
|
};
|
|
1614
1620
|
balanceCache.set(key, {
|
|
1615
1621
|
snapshot: staleSnapshot,
|
|
1616
|
-
expiresAt: currentTime +
|
|
1622
|
+
expiresAt: currentTime + cacheTtlMs
|
|
1617
1623
|
});
|
|
1618
1624
|
return staleSnapshot;
|
|
1619
1625
|
}
|
|
@@ -1621,7 +1627,7 @@ async function refreshChannelBalanceSnapshot(source, channel, options = {}) {
|
|
|
1621
1627
|
const hiddenSnapshot = makeHiddenSnapshot(source, { updatedAt: nowIso(currentTime) });
|
|
1622
1628
|
balanceCache.set(key, {
|
|
1623
1629
|
snapshot: hiddenSnapshot,
|
|
1624
|
-
expiresAt: currentTime +
|
|
1630
|
+
expiresAt: currentTime + cacheTtlMs
|
|
1625
1631
|
});
|
|
1626
1632
|
return hiddenSnapshot;
|
|
1627
1633
|
}
|
|
@@ -1799,7 +1805,7 @@ async function getChannelBalances(source, options = {}) {
|
|
|
1799
1805
|
const currentTime = options.now || Date.now();
|
|
1800
1806
|
const entries = await mapWithConcurrency(channels, 4, async (channel) => {
|
|
1801
1807
|
const snapshot = await getSnapshot(buildBalanceSnapshotKey(normalizedSource, channel), {
|
|
1802
|
-
ttlMs:
|
|
1808
|
+
ttlMs: getBalanceCacheTtlMs(channel),
|
|
1803
1809
|
fallbackValue: makeFallbackBalanceSnapshot(currentTime),
|
|
1804
1810
|
refresh: () => refreshChannelBalanceSnapshot(normalizedSource, channel, { ...options, force: true, now: Date.now() })
|
|
1805
1811
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 配置导出/导入服务
|
|
3
|
-
*
|
|
3
|
+
* 支持配置模板、频道配置及按平台 Manifest 声明的原生配置快照导出与导入
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
@@ -517,7 +517,7 @@ function buildExportReadme(exportData) {
|
|
|
517
517
|
- 插件 (Plugins)
|
|
518
518
|
- MCP 服务器配置
|
|
519
519
|
- OAuth 凭证管理池
|
|
520
|
-
-
|
|
520
|
+
- 各平台原生配置(由平台 Manifest 的 nativeConfigSnapshot 声明决定)
|
|
521
521
|
- UI 配置(主题、面板显示、排序等)
|
|
522
522
|
- Prompts 预设
|
|
523
523
|
- 安全配置
|
|
@@ -429,7 +429,11 @@ function getAvailableConfigs(options = {}) {
|
|
|
429
429
|
const { commands } = service.listCommands();
|
|
430
430
|
for (const command of commands || []) {
|
|
431
431
|
if (command.scope !== 'user') continue;
|
|
432
|
-
const detail = typeof service.
|
|
432
|
+
const detail = typeof service.getCommandByPath === 'function' && command.path
|
|
433
|
+
? (service.getCommandByPath(command.path, 'user') || command)
|
|
434
|
+
: (typeof service.getCommand === 'function'
|
|
435
|
+
? (service.getCommand(command.name, 'user', null, command.namespace) || command)
|
|
436
|
+
: command);
|
|
433
437
|
const normalizedCommand = { name: command.name, namespace: command.namespace, description: command.description, allowedTools: command.allowedTools, argumentHint: command.argumentHint, body: detail.body };
|
|
434
438
|
commandsByPlatform[platform] = commandsByPlatform[platform] || [];
|
|
435
439
|
commandsByPlatform[platform].push(normalizedCommand);
|