@jingyi0605/codingns4dsh 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +306 -0
- package/README.md +190 -993
- package/data/build/dist/client/account-bar.d.ts +2 -2
- package/data/build/dist/client/account-bar.js +96 -39
- package/data/build/dist/client/bundle.js +13722 -3611
- package/data/build/dist/client/cli-catalog.js +20 -3
- package/data/build/dist/client/cli-slots.d.ts +5 -0
- package/data/build/dist/client/cli-slots.js +57 -7
- package/data/build/dist/client/debug/ui.d.ts +1 -1
- package/data/build/dist/client/debug/ui.js +62 -32
- package/data/build/dist/client/dsh-runtime-version.d.ts +9 -2
- package/data/build/dist/client/dsh-runtime-version.js +24 -2
- package/data/build/dist/client/features/cli-adapters.d.ts +1 -1
- package/data/build/dist/client/features/cli-adapters.js +19 -16
- package/data/build/dist/client/features/debug.js +2 -2
- package/data/build/dist/client/features/index.d.ts +2 -1
- package/data/build/dist/client/features/index.js +3 -1
- package/data/build/dist/client/features/lan-access-panel.d.ts +1 -1
- package/data/build/dist/client/features/lan-access-panel.js +8 -10
- package/data/build/dist/client/features/lan-access.js +1 -1
- package/data/build/dist/client/features/login-protection-panel.d.ts +1 -1
- package/data/build/dist/client/features/login-protection-panel.js +7 -9
- package/data/build/dist/client/features/reverse-proxy-panel.d.ts +1 -1
- package/data/build/dist/client/features/reverse-proxy-panel.js +99 -11
- package/data/build/dist/client/features/reverse-proxy.d.ts +1 -1
- package/data/build/dist/client/features/reverse-proxy.js +19 -18
- package/data/build/dist/client/features/terminal-enhancement-panel.d.ts +1 -1
- package/data/build/dist/client/features/terminal-enhancement-panel.js +62 -55
- package/data/build/dist/client/features/terminal-enhancement.d.ts +1 -1
- package/data/build/dist/client/features/terminal-enhancement.js +3 -3
- package/data/build/dist/client/features/types.d.ts +14 -3
- package/data/build/dist/client/features/workspace-session-enhancement-panel.d.ts +1 -1
- package/data/build/dist/client/features/workspace-session-enhancement-panel.js +31 -9
- package/data/build/dist/client/features/workspace-session-enhancement.js +72 -11
- package/data/build/dist/client/git-management.d.ts +16 -0
- package/data/build/dist/client/git-management.js +757 -0
- package/data/build/dist/client/index.d.ts +3 -2
- package/data/build/dist/client/index.js +152 -27
- package/data/build/dist/client/locale.js +91 -29
- package/data/build/dist/client/quick-phrase-layout.d.ts +49 -0
- package/data/build/dist/client/quick-phrase-layout.js +95 -0
- package/data/build/dist/client/quick-phrase-slot.d.ts +7 -0
- package/data/build/dist/client/quick-phrase-slot.js +370 -0
- package/data/build/dist/client/remote-web-context.js +1 -1
- package/data/build/dist/client/settings-bridge.d.ts +9 -6
- package/data/build/dist/client/settings-bridge.js +51 -27
- package/data/build/dist/client/settings-section.d.ts +3 -2
- package/data/build/dist/client/settings-section.js +33 -19
- package/data/build/dist/client/subscription-slot.d.ts +3 -0
- package/data/build/dist/client/subscription-slot.js +108 -16
- package/data/build/dist/client/terminal/model.d.ts +14 -2
- package/data/build/dist/client/terminal/model.js +109 -21
- package/data/build/dist/client/terminal/recovery.d.ts +50 -0
- package/data/build/dist/client/terminal/recovery.js +101 -0
- package/data/build/dist/client/terminal/ui.d.ts +2 -2
- package/data/build/dist/client/terminal/ui.js +49 -11
- package/data/build/dist/client/terminal/xterm-view.d.ts +2 -2
- package/data/build/dist/client/terminal/xterm-view.js +2 -1
- package/data/build/dist/client/theme.d.ts +6 -1
- package/data/build/dist/client/theme.js +32 -1
- package/data/build/dist/client/workspace-session-archive-dom.d.ts +12 -0
- package/data/build/dist/client/workspace-session-archive-dom.js +27 -5
- package/data/build/dist/client/workspace-session-visibility-dom.d.ts +30 -0
- package/data/build/dist/client/workspace-session-visibility-dom.js +604 -0
- package/data/build/dist/dsh-capabilities/client/config-forms-adapter.d.ts +50 -0
- package/data/build/dist/dsh-capabilities/client/config-forms-adapter.js +139 -0
- package/data/build/dist/dsh-capabilities/client/conversation-adapter.d.ts +7 -0
- package/data/build/dist/dsh-capabilities/client/conversation-adapter.js +6 -0
- package/data/build/dist/dsh-capabilities/client/locale-adapter.d.ts +9 -0
- package/data/build/dist/dsh-capabilities/client/locale-adapter.js +4 -0
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.d.ts +10 -0
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.js +14 -0
- package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.d.ts +8 -0
- package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.js +16 -0
- package/data/build/dist/dsh-capabilities/client/sidebar-adapter.d.ts +7 -0
- package/data/build/dist/dsh-capabilities/client/sidebar-adapter.js +5 -0
- package/data/build/dist/dsh-capabilities/client/theme-adapter.d.ts +6 -0
- package/data/build/dist/dsh-capabilities/client/theme-adapter.js +4 -0
- package/data/build/dist/dsh-capabilities/client/typert-adapter.d.ts +5 -0
- package/data/build/dist/dsh-capabilities/client/typert-adapter.js +4 -0
- package/data/build/dist/dsh-capabilities/host/config-forms-adapter.d.ts +19 -0
- package/data/build/dist/dsh-capabilities/host/config-forms-adapter.js +45 -0
- package/data/build/dist/dsh-capabilities/host/connection-rpc-adapter.d.ts +19 -0
- package/data/build/dist/dsh-capabilities/host/connection-rpc-adapter.js +13 -0
- package/data/build/dist/dsh-capabilities/host/settings-scope-adapter.d.ts +8 -0
- package/data/build/dist/dsh-capabilities/host/settings-scope-adapter.js +47 -0
- package/data/build/dist/dsh-capabilities/host/typert-adapter.d.ts +6 -0
- package/data/build/dist/dsh-capabilities/host/typert-adapter.js +4 -0
- package/data/build/dist/dsh-capabilities/index.d.ts +6 -0
- package/data/build/dist/dsh-capabilities/index.js +6 -0
- package/data/build/dist/dsh-capabilities/matrix.d.ts +15 -0
- package/data/build/dist/dsh-capabilities/matrix.js +32 -0
- package/data/build/dist/dsh-capabilities/registry.d.ts +22 -0
- package/data/build/dist/dsh-capabilities/registry.js +196 -0
- package/data/build/dist/dsh-capabilities/routes.d.ts +10 -0
- package/data/build/dist/dsh-capabilities/routes.js +34 -0
- package/data/build/dist/dsh-capabilities/settings-store.d.ts +29 -0
- package/data/build/dist/dsh-capabilities/settings-store.js +5 -0
- package/data/build/dist/dsh-capabilities/types.d.ts +50 -0
- package/data/build/dist/dsh-capabilities/types.js +23 -0
- package/data/build/dist/features/registry.d.ts +8 -2
- package/data/build/dist/features/registry.js +104 -1
- package/data/build/dist/host/auth-session.d.ts +8 -1
- package/data/build/dist/host/auth-session.js +28 -6
- package/data/build/dist/host/cli-adapters/claude-driver.d.ts +2 -0
- package/data/build/dist/host/cli-adapters/claude-driver.js +19 -4
- package/data/build/dist/host/cli-adapters/claude-model-options.d.ts +14 -0
- package/data/build/dist/host/cli-adapters/claude-model-options.js +157 -0
- package/data/build/dist/host/cli-adapters/codex-driver.d.ts +11 -0
- package/data/build/dist/host/cli-adapters/codex-driver.js +166 -14
- package/data/build/dist/host/cli-adapters/driver.d.ts +2 -0
- package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts +15 -0
- package/data/build/dist/host/cli-adapters/dsh-message-projector.js +120 -29
- package/data/build/dist/host/cli-adapters/dsh-tool-history.d.ts +4 -1
- package/data/build/dist/host/cli-adapters/dsh-tool-history.js +25 -7
- package/data/build/dist/host/cli-adapters/feature.js +74 -8
- package/data/build/dist/host/cli-adapters/gemini-driver.js +2 -2
- package/data/build/dist/host/cli-adapters/grok-driver.js +2 -2
- package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts +4 -2
- package/data/build/dist/host/cli-adapters/json-rpc-process.js +8 -9
- package/data/build/dist/host/cli-adapters/kimi-driver.js +1 -1
- package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts +17 -0
- package/data/build/dist/host/cli-adapters/legacy-session-adapter.js +88 -0
- package/data/build/dist/host/cli-adapters/legacy-session-settings.d.ts +24 -0
- package/data/build/dist/host/cli-adapters/legacy-session-settings.js +162 -0
- package/data/build/dist/host/cli-adapters/official-provider-subscription.d.ts +29 -0
- package/data/build/dist/host/cli-adapters/official-provider-subscription.js +361 -0
- package/data/build/dist/host/cli-adapters/opencode-driver.d.ts +2 -0
- package/data/build/dist/host/cli-adapters/opencode-driver.js +97 -12
- package/data/build/dist/host/cli-adapters/pi-driver.js +69 -23
- package/data/build/dist/host/cli-adapters/provider-registry.d.ts +33 -0
- package/data/build/dist/host/cli-adapters/provider-registry.js +83 -0
- package/data/build/dist/host/cli-adapters/provider-subscription.d.ts +25 -3
- package/data/build/dist/host/cli-adapters/provider-subscription.js +346 -30
- package/data/build/dist/host/cli-adapters/registry.d.ts +6 -0
- package/data/build/dist/host/cli-adapters/registry.js +170 -13
- package/data/build/dist/host/cli-adapters/rpc-driver-utils.js +10 -0
- package/data/build/dist/host/cli-adapters/session-store.d.ts +7 -0
- package/data/build/dist/host/cli-adapters/session-store.js +39 -1
- package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +3 -0
- package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts +3 -0
- package/data/build/dist/host/cli-adapters/stream-normalizer.js +22 -2
- package/data/build/dist/host/control-api-client.d.ts +3 -3
- package/data/build/dist/host/control-api-client.js +2 -1
- package/data/build/dist/host/credential-store.js +11 -1
- package/data/build/dist/host/dsh-device-runtime.d.ts +4 -0
- package/data/build/dist/host/dsh-device-runtime.js +20 -9
- package/data/build/dist/host/features/auth.js +8 -5
- package/data/build/dist/host/features/debug.js +1 -1
- package/data/build/dist/host/features/git-management.d.ts +5 -0
- package/data/build/dist/host/features/git-management.js +290 -0
- package/data/build/dist/host/features/host-status.js +1 -1
- package/data/build/dist/host/features/index.d.ts +1 -0
- package/data/build/dist/host/features/index.js +3 -0
- package/data/build/dist/host/features/terminal-process.js +1 -1
- package/data/build/dist/host/features/terminal-status.d.ts +3 -1
- package/data/build/dist/host/features/terminal-status.js +3 -1
- package/data/build/dist/host/index.d.ts +7 -3
- package/data/build/dist/host/index.js +76 -11
- package/data/build/dist/host/lan-access-dsh.js +18 -5
- package/data/build/dist/host/native-session-bridge.d.ts +23 -1
- package/data/build/dist/host/native-session-bridge.js +157 -10
- package/data/build/dist/host/rpc-table.d.ts +1 -1
- package/data/build/dist/host/rpc.js +60 -10
- package/data/build/dist/host/session-migration-repair.d.ts +19 -0
- package/data/build/dist/host/session-migration-repair.js +395 -0
- package/data/build/dist/host/settings.d.ts +8 -1
- package/data/build/dist/host/settings.js +94 -3
- package/data/build/dist/host/terminal/backends/tmux-backend.d.ts +1 -0
- package/data/build/dist/host/terminal/backends/tmux-backend.js +4 -2
- package/data/build/dist/host/terminal/controller-factory.d.ts +4 -0
- package/data/build/dist/host/terminal/controller-factory.js +26 -7
- package/data/build/dist/host/terminal/runtime-manager.d.ts +2 -1
- package/data/build/dist/host/terminal/runtime-manager.js +3 -0
- package/data/build/dist/host/terminal/startup.d.ts +2 -0
- package/data/build/dist/host/terminal/startup.js +2 -1
- package/data/build/dist/host/terminal/terminal-controller.d.ts +10 -3
- package/data/build/dist/host/terminal/terminal-controller.js +101 -15
- package/data/build/dist/host/terminal/terminal-process-service.js +3 -1
- package/data/build/dist/host/terminal/terminal-service.d.ts +2 -0
- package/data/build/dist/host/terminal/terminal-service.js +10 -0
- package/data/build/dist/index.d.ts +6 -2
- package/data/build/dist/index.js +8 -2
- package/data/build/dist/shared/contracts/cli-adapter.d.ts +14 -0
- package/data/build/dist/shared/contracts/config.d.ts +31 -1
- package/data/build/dist/shared/contracts/config.js +25 -0
- package/data/build/dist/shared/contracts/dsh-device.d.ts +13 -1
- package/data/build/dist/shared/contracts/errors.d.ts +1 -1
- package/data/build/dist/shared/contracts/feature.d.ts +6 -0
- package/data/build/dist/shared/contracts/git.d.ts +82 -0
- package/data/build/dist/shared/contracts/git.js +3 -0
- package/data/build/dist/shared/contracts/subscription.d.ts +46 -0
- package/data/build/dist/shared/contracts/terminal.d.ts +4 -1
- package/data/build/dist/shared/contracts/version.d.ts +2 -2
- package/data/build/dist/shared/contracts/version.js +4 -6
- package/data/build/dist/shared/debug.d.ts +14 -0
- package/data/build/dist/shared/debug.js +53 -0
- package/data/build/dist/shared/index.d.ts +7 -4
- package/data/build/dist/shared/index.js +2 -1
- package/data/build/dist/transport/debug.d.ts +1 -1
- package/data/build/dist/transport/debug.js +3 -30
- package/data/build/dist/transport/dsh-session.js +3 -3
- package/data/build/dist/typert.host.js +4 -2
- package/data/build/dist/typert.remote-client.d.ts +11 -0
- package/data/build/dist/typert.remote-client.js +7 -0
- package/dsh.bundle.patch +1 -1
- package/package.json +17 -5
- package/profile/README.md +4 -4
- package/profile/package.json +6 -4
- package/profile/scripts/check-dsh-install.mjs +2 -2
- package/profile/version.json +2 -2
- package/scripts/check-dsh-install.mjs +2 -2
- package/version.json +2 -2
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** 当前插件注册的适配器;旧日志只能从这些稳定 ID 中选择,不能猜测任意品牌。 */
|
|
2
|
+
export const KNOWN_CLI_ADAPTER_IDS = new Set([
|
|
3
|
+
'command-code',
|
|
4
|
+
'claude-code',
|
|
5
|
+
'codex',
|
|
6
|
+
'gemini',
|
|
7
|
+
'kimi',
|
|
8
|
+
'pi',
|
|
9
|
+
'opencode',
|
|
10
|
+
'grok',
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* 从 DSH 原生会话快照读取旧版外部 Agent 的适配器证据。
|
|
14
|
+
* `codingns-external` 只能证明消息来自外部 Agent;只有 source/provider 或
|
|
15
|
+
* request/context 中出现当前已知适配器 ID 时才回填,避免把 DSH 模型提供方误认成 CLI。
|
|
16
|
+
*/
|
|
17
|
+
export function inspectLegacySessionAdapter(value) {
|
|
18
|
+
const record = asRecord(value);
|
|
19
|
+
if (record === null)
|
|
20
|
+
return undefined;
|
|
21
|
+
const header = asRecord(record.header);
|
|
22
|
+
const sessionId = firstString(record.id, record.sessionId, header?.id);
|
|
23
|
+
if (sessionId === undefined)
|
|
24
|
+
return undefined;
|
|
25
|
+
const events = snapshotEvents(record);
|
|
26
|
+
let external = false;
|
|
27
|
+
const candidates = new Set();
|
|
28
|
+
for (const event of events) {
|
|
29
|
+
const eventRecord = asRecord(event);
|
|
30
|
+
if (eventRecord === null)
|
|
31
|
+
continue;
|
|
32
|
+
const data = asRecord(eventRecord.data);
|
|
33
|
+
const message = data === null ? null : asRecord(data.message);
|
|
34
|
+
const source = message === null ? null : asRecord(message.source);
|
|
35
|
+
const sourceProvider = firstString(source?.adapterId, source?.provider);
|
|
36
|
+
const pluginSource = source?.plugin === 'codingns4dsh';
|
|
37
|
+
if (sourceProvider === 'codingns-external' || pluginSource)
|
|
38
|
+
external = true;
|
|
39
|
+
// 只有显式 adapterId 或插件自写的 source 才能作为来源证据;DSH 自己的
|
|
40
|
+
// model provider 不能因为名字碰巧叫 codex 就被绑定到 Codex 适配器。
|
|
41
|
+
addCandidate(candidates, firstString(source?.adapterId));
|
|
42
|
+
if (pluginSource)
|
|
43
|
+
addCandidate(candidates, sourceProvider);
|
|
44
|
+
if (eventRecord.type === 'request/context')
|
|
45
|
+
addCandidate(candidates, firstString(data?.adapterId, data?.provider));
|
|
46
|
+
}
|
|
47
|
+
if (!external)
|
|
48
|
+
return undefined;
|
|
49
|
+
const adapterId = candidates.size === 1 ? [...candidates][0] : undefined;
|
|
50
|
+
return {
|
|
51
|
+
sessionId,
|
|
52
|
+
...(adapterId === undefined ? {} : { adapterId }),
|
|
53
|
+
...(typeof header?.cwd === 'string' && header.cwd.trim() ? { cwd: header.cwd.trim() } : {}),
|
|
54
|
+
...(typeof header?.createdAt === 'number' ? { createdAt: new Date(header.createdAt).toISOString() } : {}),
|
|
55
|
+
...(typeof header?.createdAt === 'string' && header.createdAt.trim() ? { createdAt: header.createdAt } : {}),
|
|
56
|
+
external: true,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function snapshotEvents(record) {
|
|
60
|
+
const snapshot = record.snapshotEvents;
|
|
61
|
+
if (typeof snapshot === 'function') {
|
|
62
|
+
try {
|
|
63
|
+
const result = snapshot();
|
|
64
|
+
if (Array.isArray(result))
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// 单个损坏会话不能阻断其余会话迁移。
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return Array.isArray(record.events) ? record.events : [];
|
|
72
|
+
}
|
|
73
|
+
function addCandidate(candidates, value) {
|
|
74
|
+
if (value !== undefined && KNOWN_CLI_ADAPTER_IDS.has(value))
|
|
75
|
+
candidates.add(value);
|
|
76
|
+
}
|
|
77
|
+
function firstString(...values) {
|
|
78
|
+
for (const value of values)
|
|
79
|
+
if (typeof value === 'string' && value.trim() !== '')
|
|
80
|
+
return value.trim();
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
function asRecord(value) {
|
|
84
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
85
|
+
? value
|
|
86
|
+
: null;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=legacy-session-adapter.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CodingNsCliSessionRecord } from '../../shared/contracts/cli-adapter.js';
|
|
2
|
+
import type { CodingNsCliAdapterPreference } from '../../shared/contracts/config.js';
|
|
3
|
+
/** DSH 旧版设置导入文件的默认位置。 */
|
|
4
|
+
export declare function defaultLegacySettingsPath(): string;
|
|
5
|
+
/**
|
|
6
|
+
* 读取旧版 `codingns.cliSessions` 索引。
|
|
7
|
+
*
|
|
8
|
+
* DSH 没有向插件暴露旧设置文档的结构化读取接口,这里只解析稳定的
|
|
9
|
+
* `cliSessions` 子集,避免引入 YAML 解析器或把旧设置的其它字段带入运行时。
|
|
10
|
+
*/
|
|
11
|
+
export declare function readLegacyImportedSessionRecords(path?: string): readonly CodingNsCliSessionRecord[];
|
|
12
|
+
/**
|
|
13
|
+
* 读取旧版 `codingns.agentAdapterPreferences` 偏好。
|
|
14
|
+
*
|
|
15
|
+
* DSH 0.1.7 会把旧 `settings.yaml` 重命名为 `settings.yaml.imported`,但
|
|
16
|
+
* ConfigForms 只按新的 scoped entry id 导入。模型和思考强度因此不能依赖
|
|
17
|
+
* DSH 自己的导入器,必须在 Host 启动时从旧文档补回。
|
|
18
|
+
*/
|
|
19
|
+
export declare function readLegacyImportedAdapterPreferences(path?: string): Readonly<Record<string, CodingNsCliAdapterPreference>>;
|
|
20
|
+
/** 解析旧版设置文本,单独导出以便用固定 fixture 验证迁移规则。 */
|
|
21
|
+
export declare function parseLegacyImportedSessionRecords(text: string): readonly CodingNsCliSessionRecord[];
|
|
22
|
+
/** 解析旧设置中按适配器分组的最近模型与思考强度。 */
|
|
23
|
+
export declare function parseLegacyImportedAdapterPreferences(text: string): Readonly<Record<string, CodingNsCliAdapterPreference>>;
|
|
24
|
+
//# sourceMappingURL=legacy-session-settings.d.ts.map
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
/** DSH 旧版设置导入文件的默认位置。 */
|
|
5
|
+
export function defaultLegacySettingsPath() {
|
|
6
|
+
return join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'settings.yaml.imported');
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* 读取旧版 `codingns.cliSessions` 索引。
|
|
10
|
+
*
|
|
11
|
+
* DSH 没有向插件暴露旧设置文档的结构化读取接口,这里只解析稳定的
|
|
12
|
+
* `cliSessions` 子集,避免引入 YAML 解析器或把旧设置的其它字段带入运行时。
|
|
13
|
+
*/
|
|
14
|
+
export function readLegacyImportedSessionRecords(path = defaultLegacySettingsPath()) {
|
|
15
|
+
const text = readLegacySettingsText(path);
|
|
16
|
+
if (text === undefined)
|
|
17
|
+
return [];
|
|
18
|
+
return parseLegacyImportedSessionRecords(text);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 读取旧版 `codingns.agentAdapterPreferences` 偏好。
|
|
22
|
+
*
|
|
23
|
+
* DSH 0.1.7 会把旧 `settings.yaml` 重命名为 `settings.yaml.imported`,但
|
|
24
|
+
* ConfigForms 只按新的 scoped entry id 导入。模型和思考强度因此不能依赖
|
|
25
|
+
* DSH 自己的导入器,必须在 Host 启动时从旧文档补回。
|
|
26
|
+
*/
|
|
27
|
+
export function readLegacyImportedAdapterPreferences(path = defaultLegacySettingsPath()) {
|
|
28
|
+
const text = readLegacySettingsText(path);
|
|
29
|
+
if (text === undefined)
|
|
30
|
+
return {};
|
|
31
|
+
return parseLegacyImportedAdapterPreferences(text);
|
|
32
|
+
}
|
|
33
|
+
function readLegacySettingsText(path) {
|
|
34
|
+
try {
|
|
35
|
+
return readFileSync(path, 'utf8');
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// ConfigForms 的异步迁移尚未完成时,旧文件仍可能保持原名。
|
|
39
|
+
if (!path.endsWith('.imported'))
|
|
40
|
+
return undefined;
|
|
41
|
+
try {
|
|
42
|
+
return readFileSync(path.slice(0, -'.imported'.length), 'utf8');
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** 解析旧版设置文本,单独导出以便用固定 fixture 验证迁移规则。 */
|
|
50
|
+
export function parseLegacyImportedSessionRecords(text) {
|
|
51
|
+
const lines = text.replaceAll('\r\n', '\n').split('\n');
|
|
52
|
+
const records = [];
|
|
53
|
+
let inSessions = false;
|
|
54
|
+
let current;
|
|
55
|
+
const flush = () => {
|
|
56
|
+
if (current !== undefined && isSessionRecord(current))
|
|
57
|
+
records.push(current);
|
|
58
|
+
current = undefined;
|
|
59
|
+
};
|
|
60
|
+
for (const line of lines) {
|
|
61
|
+
if (/^ cliSessions:\s*$/u.test(line)) {
|
|
62
|
+
flush();
|
|
63
|
+
inSessions = true;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (inSessions && /^ [A-Za-z][\w-]*:\s*/u.test(line)) {
|
|
67
|
+
flush();
|
|
68
|
+
inSessions = false;
|
|
69
|
+
}
|
|
70
|
+
if (!inSessions)
|
|
71
|
+
continue;
|
|
72
|
+
const item = /^ - dshSessionId:\s*(.*)$/u.exec(line);
|
|
73
|
+
if (item !== null) {
|
|
74
|
+
flush();
|
|
75
|
+
current = { dshSessionId: parseScalar(item[1]) };
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const field = /^ ([A-Za-z][\w-]*):\s*(.*)$/u.exec(line);
|
|
79
|
+
if (field !== null && current !== undefined)
|
|
80
|
+
current[field[1]] = parseScalar(field[2]);
|
|
81
|
+
}
|
|
82
|
+
flush();
|
|
83
|
+
return records;
|
|
84
|
+
}
|
|
85
|
+
/** 解析旧设置中按适配器分组的最近模型与思考强度。 */
|
|
86
|
+
export function parseLegacyImportedAdapterPreferences(text) {
|
|
87
|
+
const lines = text.replaceAll('\r\n', '\n').split('\n');
|
|
88
|
+
const preferences = {};
|
|
89
|
+
let inPreferences = false;
|
|
90
|
+
let adapterId;
|
|
91
|
+
let current;
|
|
92
|
+
const flush = () => {
|
|
93
|
+
if (adapterId === undefined || current === undefined)
|
|
94
|
+
return;
|
|
95
|
+
if (current.modelId === undefined && current.effortId === undefined)
|
|
96
|
+
return;
|
|
97
|
+
preferences[adapterId] = { ...current };
|
|
98
|
+
};
|
|
99
|
+
for (const line of lines) {
|
|
100
|
+
if (/^ agentAdapterPreferences:\s*$/u.test(line)) {
|
|
101
|
+
flush();
|
|
102
|
+
inPreferences = true;
|
|
103
|
+
adapterId = undefined;
|
|
104
|
+
current = undefined;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (inPreferences && /^ [A-Za-z][\w-]*:\s*/u.test(line)) {
|
|
108
|
+
flush();
|
|
109
|
+
inPreferences = false;
|
|
110
|
+
adapterId = undefined;
|
|
111
|
+
current = undefined;
|
|
112
|
+
}
|
|
113
|
+
if (!inPreferences)
|
|
114
|
+
continue;
|
|
115
|
+
const adapter = /^ ([A-Za-z][\w-]*):\s*$/u.exec(line);
|
|
116
|
+
if (adapter !== null) {
|
|
117
|
+
flush();
|
|
118
|
+
adapterId = adapter[1];
|
|
119
|
+
current = {};
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (adapterId === undefined || current === undefined)
|
|
123
|
+
continue;
|
|
124
|
+
const field = /^ (modelId|effortId):\s*(.*)$/u.exec(line);
|
|
125
|
+
if (field === null)
|
|
126
|
+
continue;
|
|
127
|
+
const value = parseScalar(field[2]);
|
|
128
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
129
|
+
continue;
|
|
130
|
+
current[field[1]] = value.trim();
|
|
131
|
+
}
|
|
132
|
+
flush();
|
|
133
|
+
return preferences;
|
|
134
|
+
}
|
|
135
|
+
function isSessionRecord(value) {
|
|
136
|
+
return typeof value.dshSessionId === 'string'
|
|
137
|
+
&& value.dshSessionId.trim() !== ''
|
|
138
|
+
&& typeof value.adapterId === 'string'
|
|
139
|
+
&& value.adapterId.trim() !== ''
|
|
140
|
+
&& isStatus(value.status)
|
|
141
|
+
&& typeof value.createdAt === 'string'
|
|
142
|
+
&& typeof value.updatedAt === 'string';
|
|
143
|
+
}
|
|
144
|
+
function isStatus(value) {
|
|
145
|
+
return value === 'active' || value === 'idle' || value === 'error' || value === 'archived';
|
|
146
|
+
}
|
|
147
|
+
function parseScalar(value) {
|
|
148
|
+
const trimmed = value.trim();
|
|
149
|
+
if (trimmed === '' || trimmed === 'null' || trimmed === '~')
|
|
150
|
+
return undefined;
|
|
151
|
+
if (trimmed === 'true')
|
|
152
|
+
return true;
|
|
153
|
+
if (trimmed === 'false')
|
|
154
|
+
return false;
|
|
155
|
+
if (/^-?\d+(?:\.\d+)?$/u.test(trimmed))
|
|
156
|
+
return Number(trimmed);
|
|
157
|
+
if ((trimmed.startsWith("'") && trimmed.endsWith("'")) || (trimmed.startsWith('"') && trimmed.endsWith('"'))) {
|
|
158
|
+
return trimmed.slice(1, -1);
|
|
159
|
+
}
|
|
160
|
+
return trimmed;
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=legacy-session-settings.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CliSubscriptionUsage } from '../../shared/contracts/subscription.js';
|
|
2
|
+
import type { Sub2ApiSource } from './provider-subscription.js';
|
|
3
|
+
type FetchLike = typeof fetch;
|
|
4
|
+
/**
|
|
5
|
+
* 读取模型厂商自己的账户接口。
|
|
6
|
+
*
|
|
7
|
+
* 这里不把管理后台的 Cookie 或组织管理员令牌当成普通模型 API key;
|
|
8
|
+
* 只有供应商文档明确允许 API key 调用的接口才在此登记。
|
|
9
|
+
*/
|
|
10
|
+
export interface OfficialProviderSubscriptionOptions {
|
|
11
|
+
readonly fetch?: FetchLike;
|
|
12
|
+
readonly timeoutMs?: number;
|
|
13
|
+
/** GitHub Copilot 管理 API 所需的组织名;普通 Copilot 用户没有可查询的个人余额接口。 */
|
|
14
|
+
readonly githubCopilotOrganization?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class OfficialProviderSubscriptionService {
|
|
17
|
+
private readonly request;
|
|
18
|
+
private readonly timeoutMs;
|
|
19
|
+
private readonly githubCopilotOrganization;
|
|
20
|
+
constructor(options?: OfficialProviderSubscriptionOptions);
|
|
21
|
+
read(providerId: string | undefined, source: Sub2ApiSource | null): Promise<CliSubscriptionUsage | null>;
|
|
22
|
+
private readOpenRouter;
|
|
23
|
+
private readMiniMax;
|
|
24
|
+
private readZai;
|
|
25
|
+
private readGithubCopilot;
|
|
26
|
+
private getJson;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=official-provider-subscription.d.ts.map
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { identifyModelProvider } from './provider-registry.js';
|
|
2
|
+
export class OfficialProviderSubscriptionService {
|
|
3
|
+
request;
|
|
4
|
+
timeoutMs;
|
|
5
|
+
githubCopilotOrganization;
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
this.request = options.fetch ?? fetch;
|
|
8
|
+
this.timeoutMs = options.timeoutMs ?? 8_000;
|
|
9
|
+
this.githubCopilotOrganization = options.githubCopilotOrganization?.trim()
|
|
10
|
+
|| process.env.GITHUB_COPILOT_ORGANIZATION?.trim()
|
|
11
|
+
|| undefined;
|
|
12
|
+
}
|
|
13
|
+
async read(providerId, source) {
|
|
14
|
+
if (providerId === undefined || source === null || source.apiKey.trim() === '')
|
|
15
|
+
return null;
|
|
16
|
+
const definition = identifyModelProvider({ name: providerId, baseUrl: source.baseUrl });
|
|
17
|
+
if (definition === undefined)
|
|
18
|
+
return null;
|
|
19
|
+
const usage = definition.id === 'openrouter'
|
|
20
|
+
? await this.readOpenRouter(source)
|
|
21
|
+
: definition.id === 'minimax' || definition.id === 'minimax-cn'
|
|
22
|
+
? await this.readMiniMax(source)
|
|
23
|
+
: definition.id === 'zai' || definition.id === 'zai-coding-cn'
|
|
24
|
+
? await this.readZai(source, definition.id)
|
|
25
|
+
: definition.id === 'github-copilot'
|
|
26
|
+
? await this.readGithubCopilot(source)
|
|
27
|
+
: null;
|
|
28
|
+
if (usage === null)
|
|
29
|
+
return null;
|
|
30
|
+
const logoDataUrl = await readLogoDataUrl(definition.logoUrl, this.request, this.timeoutMs);
|
|
31
|
+
return {
|
|
32
|
+
authenticated: true,
|
|
33
|
+
planType: usage.planName,
|
|
34
|
+
primary: null,
|
|
35
|
+
secondary: null,
|
|
36
|
+
monthly: null,
|
|
37
|
+
rateLimitReachedType: null,
|
|
38
|
+
resetCredits: null,
|
|
39
|
+
capturedAt: new Date().toISOString(),
|
|
40
|
+
provider: {
|
|
41
|
+
id: definition.id,
|
|
42
|
+
displayName: definition.displayName,
|
|
43
|
+
baseUrl: sanitizeUrl(source.baseUrl),
|
|
44
|
+
capability: definition.capability,
|
|
45
|
+
logoUrl: definition.logoUrl,
|
|
46
|
+
...(logoDataUrl === '' ? {} : { logoDataUrl }),
|
|
47
|
+
},
|
|
48
|
+
providerBalance: usage,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async readOpenRouter(source) {
|
|
52
|
+
const root = openRouterRoot(source.baseUrl);
|
|
53
|
+
if (root === '')
|
|
54
|
+
return null;
|
|
55
|
+
const key = await this.getJson(`${root}/api/v1/key`, source, true);
|
|
56
|
+
const credits = await this.getJson(`${root}/api/v1/credits`, source, true);
|
|
57
|
+
if (key === null && credits === null)
|
|
58
|
+
return null;
|
|
59
|
+
const keyData = recordValue(key?.data);
|
|
60
|
+
const creditData = recordValue(credits?.data);
|
|
61
|
+
const limit = numberValue(keyData?.limit);
|
|
62
|
+
const keyUsage = numberValue(keyData?.usage);
|
|
63
|
+
const keyRemaining = numberValue(keyData?.limit_remaining);
|
|
64
|
+
const totalCredits = numberValue(creditData?.total_credits);
|
|
65
|
+
const totalUsage = numberValue(creditData?.total_usage);
|
|
66
|
+
const total = limit ?? totalCredits;
|
|
67
|
+
const used = keyUsage ?? totalUsage;
|
|
68
|
+
const remaining = keyRemaining ?? (total !== null && used !== null ? Math.max(0, total - used) : null);
|
|
69
|
+
if (total === null && used === null && remaining === null)
|
|
70
|
+
return null;
|
|
71
|
+
const details = [];
|
|
72
|
+
const label = textValue(keyData?.label);
|
|
73
|
+
if (label !== null)
|
|
74
|
+
details.push({ label: 'Key', value: label });
|
|
75
|
+
if (keyData?.is_free_tier === true)
|
|
76
|
+
details.push({ label: '免费层', value: '是' });
|
|
77
|
+
return {
|
|
78
|
+
upstreamUrl: sanitizeUrl(root),
|
|
79
|
+
currency: 'USD',
|
|
80
|
+
unit: 'USD',
|
|
81
|
+
balance: remaining,
|
|
82
|
+
remaining,
|
|
83
|
+
used,
|
|
84
|
+
total,
|
|
85
|
+
requests: null,
|
|
86
|
+
inputTokens: null,
|
|
87
|
+
outputTokens: null,
|
|
88
|
+
planName: keyData?.is_free_tier === true ? 'Free' : null,
|
|
89
|
+
details,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async readMiniMax(source) {
|
|
93
|
+
// Coding Plan 文档:/v1/coding_plan/remains;旧版国内文档曾使用
|
|
94
|
+
// /v1/api/openplatform/coding_plan/remains,因此保留一次兼容回退。
|
|
95
|
+
const root = miniMaxRoot(source.baseUrl);
|
|
96
|
+
if (root === '')
|
|
97
|
+
return null;
|
|
98
|
+
const paths = ['/v1/coding_plan/remains', '/v1/api/openplatform/coding_plan/remains'];
|
|
99
|
+
for (const path of paths) {
|
|
100
|
+
const response = await this.getJson(`${root}${path}`, source, true);
|
|
101
|
+
const usage = normalizeMiniMax(response, root);
|
|
102
|
+
if (usage !== null)
|
|
103
|
+
return usage;
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
async readZai(source, providerId) {
|
|
108
|
+
const root = zaiRoot(source.baseUrl);
|
|
109
|
+
if (root === '')
|
|
110
|
+
return null;
|
|
111
|
+
// Coding Plan 使用额度窗口接口;通用 Z.ai 使用官方账户余额接口。
|
|
112
|
+
if (providerId === 'zai-coding-cn') {
|
|
113
|
+
const value = await this.getJson(`${root}/api/monitor/usage/quota/limit`, source, false);
|
|
114
|
+
const quota = normalizeZai(value, root);
|
|
115
|
+
if (quota !== null)
|
|
116
|
+
return quota;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const value = await this.getJson(`${root}/api/paas/v4/balance`, source, true);
|
|
120
|
+
const balance = normalizeZaiAccount(value, root);
|
|
121
|
+
if (balance !== null)
|
|
122
|
+
return balance;
|
|
123
|
+
}
|
|
124
|
+
// 通用 Zhipu 账户余额接口来自社区对官方控制台请求的逆向记录;
|
|
125
|
+
// 仅在 Coding Plan quota 不可用时尝试,接口变化时安全返回 null。
|
|
126
|
+
const accountRoot = root.includes('bigmodel.cn') ? root : 'https://open.bigmodel.cn';
|
|
127
|
+
const account = await this.getJson(`${accountRoot}/api/biz/account/query-customer-account-report`, source, true);
|
|
128
|
+
return normalizeZaiAccount(account, accountRoot);
|
|
129
|
+
}
|
|
130
|
+
async readGithubCopilot(source) {
|
|
131
|
+
const organization = this.githubCopilotOrganization;
|
|
132
|
+
if (organization === undefined)
|
|
133
|
+
return null;
|
|
134
|
+
const value = await this.getJson(`https://api.github.com/orgs/${encodeURIComponent(organization)}/copilot/billing`, source, true);
|
|
135
|
+
const seats = numberValue(value?.seat_management_setting?.total_seats)
|
|
136
|
+
?? numberValue(value?.total_seats)
|
|
137
|
+
?? numberValue(value?.totalSeats);
|
|
138
|
+
const occupied = numberValue(value?.seat_management_setting?.occupied_seats)
|
|
139
|
+
?? numberValue(value?.occupied_seats)
|
|
140
|
+
?? numberValue(value?.occupiedSeats);
|
|
141
|
+
if (seats === null && occupied === null)
|
|
142
|
+
return null;
|
|
143
|
+
return {
|
|
144
|
+
upstreamUrl: 'https://api.github.com',
|
|
145
|
+
currency: null,
|
|
146
|
+
unit: 'seats',
|
|
147
|
+
balance: seats !== null && occupied !== null ? Math.max(0, seats - occupied) : null,
|
|
148
|
+
remaining: seats !== null && occupied !== null ? Math.max(0, seats - occupied) : null,
|
|
149
|
+
used: occupied,
|
|
150
|
+
total: seats,
|
|
151
|
+
requests: null,
|
|
152
|
+
inputTokens: null,
|
|
153
|
+
outputTokens: null,
|
|
154
|
+
planName: textValue(value?.plan_type ?? value?.planType),
|
|
155
|
+
details: [
|
|
156
|
+
...(seats === null ? [] : [{ label: '总席位', value: seats }]),
|
|
157
|
+
...(occupied === null ? [] : [{ label: '已分配席位', value: occupied }]),
|
|
158
|
+
],
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
async getJson(url, source, bearer) {
|
|
162
|
+
const controller = new AbortController();
|
|
163
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
164
|
+
try {
|
|
165
|
+
const key = source.apiKey.trim();
|
|
166
|
+
const response = await this.request(url, {
|
|
167
|
+
headers: {
|
|
168
|
+
Authorization: bearer ? (key.startsWith('Bearer ') ? key : `Bearer ${key}`) : key,
|
|
169
|
+
Accept: 'application/json',
|
|
170
|
+
},
|
|
171
|
+
signal: controller.signal,
|
|
172
|
+
});
|
|
173
|
+
if (!response.ok)
|
|
174
|
+
return null;
|
|
175
|
+
return recordValue(await response.json());
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
clearTimeout(timer);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function normalizeMiniMax(value, baseUrl) {
|
|
186
|
+
if (value === null || numberValue(recordValue(value.base_resp)?.status_code) === -1)
|
|
187
|
+
return null;
|
|
188
|
+
const models = Array.isArray(value.model_remains) ? value.model_remains : [];
|
|
189
|
+
const model = models.map(recordValue).find((item) => textValue(item?.model_name) === 'general') ?? models.map(recordValue).find(Boolean);
|
|
190
|
+
if (model === undefined || model === null)
|
|
191
|
+
return null;
|
|
192
|
+
const remaining = numberValue(model.current_interval_remaining_percent)
|
|
193
|
+
?? numberValue(model.remaining_percent);
|
|
194
|
+
if (remaining === null)
|
|
195
|
+
return null;
|
|
196
|
+
const details = [{ label: '滚动窗口剩余', value: `${remaining}%` }];
|
|
197
|
+
const weekly = numberValue(model.current_weekly_remaining_percent);
|
|
198
|
+
const weeklyEnabled = numberValue(model.current_weekly_status) === 1;
|
|
199
|
+
if (weekly !== null && weeklyEnabled)
|
|
200
|
+
details.push({ label: '周窗口剩余', value: `${weekly}%` });
|
|
201
|
+
const intervalReset = numberValue(model.end_time) ?? numberValue(model.remains_time);
|
|
202
|
+
if (intervalReset !== null)
|
|
203
|
+
details.push({ label: '滚动窗口重置', value: timestampFromMillis(intervalReset) ?? intervalReset });
|
|
204
|
+
const weeklyReset = numberValue(model.weekly_end_time) ?? numberValue(model.weekly_remains_time);
|
|
205
|
+
if (weeklyReset !== null && weeklyEnabled)
|
|
206
|
+
details.push({ label: '周窗口重置', value: timestampFromMillis(weeklyReset) ?? weeklyReset });
|
|
207
|
+
return {
|
|
208
|
+
upstreamUrl: sanitizeUrl(baseUrl),
|
|
209
|
+
currency: null,
|
|
210
|
+
unit: '%',
|
|
211
|
+
balance: remaining,
|
|
212
|
+
remaining,
|
|
213
|
+
used: 100 - remaining,
|
|
214
|
+
total: 100,
|
|
215
|
+
requests: null,
|
|
216
|
+
inputTokens: null,
|
|
217
|
+
outputTokens: null,
|
|
218
|
+
planName: textValue(model.plan_name),
|
|
219
|
+
details,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function normalizeZai(value, baseUrl) {
|
|
223
|
+
const data = recordValue(value?.data);
|
|
224
|
+
const limits = Array.isArray(data?.limits) ? data.limits : [];
|
|
225
|
+
const usable = limits.map(recordValue).filter((item) => item !== null && ['TOKENS_LIMIT', 'CREDIT_LIMIT'].includes(String(item.type ?? '').toUpperCase()));
|
|
226
|
+
if (usable.length === 0)
|
|
227
|
+
return null;
|
|
228
|
+
const details = usable.map((item) => ({
|
|
229
|
+
label: String(item.type ?? '额度'),
|
|
230
|
+
value: `${numberValue(item.percentage) ?? 0}%${timestampValue(item.nextResetTime) === null ? '' : `,重置于 ${timestampValue(item.nextResetTime)}`}`,
|
|
231
|
+
}));
|
|
232
|
+
const remaining = Math.max(...usable.map((item) => numberValue(item.percentage) ?? 0));
|
|
233
|
+
return {
|
|
234
|
+
upstreamUrl: sanitizeUrl(baseUrl),
|
|
235
|
+
currency: null,
|
|
236
|
+
unit: '%',
|
|
237
|
+
balance: remaining,
|
|
238
|
+
remaining,
|
|
239
|
+
used: 100 - remaining,
|
|
240
|
+
total: 100,
|
|
241
|
+
requests: null,
|
|
242
|
+
inputTokens: null,
|
|
243
|
+
outputTokens: null,
|
|
244
|
+
planName: textValue(data?.level),
|
|
245
|
+
details,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function normalizeZaiAccount(value, baseUrl) {
|
|
249
|
+
const data = recordValue(value?.data);
|
|
250
|
+
const available = numberValue(data?.availableBalance ?? data?.balance ?? data?.remainBalance);
|
|
251
|
+
if (available === null)
|
|
252
|
+
return null;
|
|
253
|
+
const recharge = numberValue(data?.rechargeAmount);
|
|
254
|
+
const spent = numberValue(data?.totalSpendAmount);
|
|
255
|
+
const frozen = numberValue(data?.frozenBalance);
|
|
256
|
+
return {
|
|
257
|
+
upstreamUrl: sanitizeUrl(baseUrl),
|
|
258
|
+
currency: 'CNY',
|
|
259
|
+
unit: 'CNY',
|
|
260
|
+
balance: available,
|
|
261
|
+
remaining: available,
|
|
262
|
+
used: spent,
|
|
263
|
+
total: recharge,
|
|
264
|
+
requests: null,
|
|
265
|
+
inputTokens: null,
|
|
266
|
+
outputTokens: null,
|
|
267
|
+
planName: null,
|
|
268
|
+
details: [
|
|
269
|
+
...(recharge === null ? [] : [{ label: '累计充值', value: recharge }]),
|
|
270
|
+
...(spent === null ? [] : [{ label: '累计消费', value: spent }]),
|
|
271
|
+
...(frozen === null ? [] : [{ label: '冻结余额', value: frozen }]),
|
|
272
|
+
],
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function openRouterRoot(value) { return rootForHost(value, 'openrouter.ai'); }
|
|
276
|
+
function miniMaxRoot(value) {
|
|
277
|
+
let international = false;
|
|
278
|
+
try {
|
|
279
|
+
international = new URL(value).hostname.includes('minimax.io');
|
|
280
|
+
}
|
|
281
|
+
catch { /* 使用国内默认地址 */ }
|
|
282
|
+
return rootForHost(value, international ? 'api.minimax.io' : 'api.minimaxi.com');
|
|
283
|
+
}
|
|
284
|
+
function zaiRoot(value) {
|
|
285
|
+
let mainland = false;
|
|
286
|
+
try {
|
|
287
|
+
mainland = new URL(value).hostname.includes('bigmodel.cn');
|
|
288
|
+
}
|
|
289
|
+
catch { /* 使用国际默认地址 */ }
|
|
290
|
+
return rootForHost(value, mainland ? 'open.bigmodel.cn' : 'api.z.ai');
|
|
291
|
+
}
|
|
292
|
+
function rootForHost(value, fallbackHost) {
|
|
293
|
+
try {
|
|
294
|
+
const url = new URL(value);
|
|
295
|
+
url.pathname = '';
|
|
296
|
+
url.search = '';
|
|
297
|
+
url.hash = '';
|
|
298
|
+
return url.toString().replace(/\/$/u, '');
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
return `https://${fallbackHost}`;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function recordValue(value) { return typeof value === 'object' && value !== null && !Array.isArray(value) ? value : null; }
|
|
305
|
+
function numberValue(value) { const result = typeof value === 'number' ? value : Number(value); return Number.isFinite(result) ? result : null; }
|
|
306
|
+
function textValue(value) { return typeof value === 'string' && value.trim() !== '' ? value.trim() : null; }
|
|
307
|
+
function timestampValue(value) { const n = numberValue(value); return n === null ? null : Math.round(n > 10_000_000_000 ? n / 1000 : n); }
|
|
308
|
+
function timestampFromMillis(value) {
|
|
309
|
+
if (value <= 0)
|
|
310
|
+
return null;
|
|
311
|
+
// MiniMax 新接口返回 Unix 毫秒;旧接口的 remains_time 是剩余毫秒,兼容两种格式。
|
|
312
|
+
return value >= 100_000_000_000 ? Math.round(value / 1000) : Math.round(Date.now() / 1000 + value / 1000);
|
|
313
|
+
}
|
|
314
|
+
function sanitizeUrl(value) { try {
|
|
315
|
+
const url = new URL(value);
|
|
316
|
+
url.username = '';
|
|
317
|
+
url.password = '';
|
|
318
|
+
url.search = '';
|
|
319
|
+
url.hash = '';
|
|
320
|
+
return url.toString().replace(/\/$/u, '');
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
return '';
|
|
324
|
+
} }
|
|
325
|
+
/** 获取官方提供商 Logo 并内联,避免远程 Web 页面被 CSP 拦截。 */
|
|
326
|
+
async function readLogoDataUrl(url, request, timeoutMs) {
|
|
327
|
+
let parsed;
|
|
328
|
+
try {
|
|
329
|
+
parsed = new URL(url);
|
|
330
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
|
|
331
|
+
return '';
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
return '';
|
|
335
|
+
}
|
|
336
|
+
const controller = new AbortController();
|
|
337
|
+
const timer = setTimeout(() => controller.abort(), Math.min(timeoutMs, 3_000));
|
|
338
|
+
try {
|
|
339
|
+
const response = await request(parsed.toString(), { headers: { Accept: 'image/*' }, signal: controller.signal });
|
|
340
|
+
if (!response.ok)
|
|
341
|
+
return '';
|
|
342
|
+
const contentType = (response.headers.get('content-type') ?? '').split(';', 1)[0]?.trim().toLowerCase() ?? '';
|
|
343
|
+
if (!['image/svg+xml', 'image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/avif', 'image/x-icon', 'image/vnd.microsoft.icon'].includes(contentType))
|
|
344
|
+
return '';
|
|
345
|
+
if (response.url !== '' && new URL(response.url).origin !== parsed.origin)
|
|
346
|
+
return '';
|
|
347
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
348
|
+
if (bytes.byteLength > 64 * 1024)
|
|
349
|
+
return '';
|
|
350
|
+
if (contentType === 'image/svg+xml' && !/<svg[\s>]/iu.test(new TextDecoder().decode(bytes)))
|
|
351
|
+
return '';
|
|
352
|
+
return `data:${contentType};base64,${Buffer.from(bytes).toString('base64')}`;
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
return '';
|
|
356
|
+
}
|
|
357
|
+
finally {
|
|
358
|
+
clearTimeout(timer);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=official-provider-subscription.js.map
|
|
@@ -30,6 +30,7 @@ export declare class OpenCodeDriver implements CodingNsCliDriver {
|
|
|
30
30
|
/** Provider 会话的实际工作目录;目录变化时禁止复用旧会话。 */
|
|
31
31
|
private readonly sessionCwds;
|
|
32
32
|
private readonly interactionTargets;
|
|
33
|
+
private readonly modelContextWindows;
|
|
33
34
|
constructor(options?: OpenCodeDriverOptions);
|
|
34
35
|
detect(): Promise<{
|
|
35
36
|
installed: boolean;
|
|
@@ -46,6 +47,7 @@ export declare class OpenCodeDriver implements CodingNsCliDriver {
|
|
|
46
47
|
private createSession;
|
|
47
48
|
private providerSessionMatchesDirectory;
|
|
48
49
|
private abortSession;
|
|
50
|
+
private resolveModelContextWindow;
|
|
49
51
|
private ensureServer;
|
|
50
52
|
private startServer;
|
|
51
53
|
private stopManagedServer;
|