dsh-cliworker-now 0.7.6 → 0.7.8
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 +53 -11
- package/README.md +56 -11
- package/lib/account-models.mjs +49 -18
- package/lib/client.js +1221 -151
- package/lib/client.js.map +1 -1
- package/lib/grok-catalog.mjs +2 -2
- package/lib/hermes-native-entry.py +48 -13
- package/lib/hermes-nous-refresh.py +331 -0
- package/lib/index.js +9469 -6030
- package/lib/index.js.map +1 -1
- package/lib/native-launch.mjs +62 -7
- package/lib/native-spawn.mjs +32 -0
- package/lib/pi-installation.mjs +27 -3
- package/lib/pi-native-catalog.mjs +17 -7
- package/lib/pi-omp-bridge.mjs +2 -2
- package/lib/pi-omp-refresh.mjs +3 -3
- package/lib/private-launch.mjs +6 -2
- package/lib/terminal-bridge.mjs +2 -2
- package/lib/typert.host.js +265 -25
- package/lib/typert.remote-client.d.ts +8 -0
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +241 -25
- package/lib/types/client/account-query-queue.d.ts +16 -0
- package/lib/types/client/account-query-queue.js +61 -0
- package/lib/types/client/account-query-queue.js.map +1 -0
- package/lib/types/client/account-terminal.d.ts +6 -2
- package/lib/types/client/account-terminal.js +260 -31
- package/lib/types/client/account-terminal.js.map +1 -1
- package/lib/types/client/cli-executable-settings.d.ts +13 -0
- package/lib/types/client/cli-executable-settings.js +128 -0
- package/lib/types/client/cli-executable-settings.js.map +1 -0
- package/lib/types/client/management-styles.d.ts +1 -1
- package/lib/types/client/management-styles.js +4 -0
- package/lib/types/client/management-styles.js.map +1 -1
- package/lib/types/client/settings-dialog.js +196 -80
- package/lib/types/client/settings-dialog.js.map +1 -1
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/client/styles.js +18 -16
- package/lib/types/client/styles.js.map +1 -1
- package/lib/types/client/zcode-login-link-provider.d.ts +9 -0
- package/lib/types/client/zcode-login-link-provider.js +105 -0
- package/lib/types/client/zcode-login-link-provider.js.map +1 -0
- package/lib/types/client/zcode-login-link.d.ts +16 -0
- package/lib/types/client/zcode-login-link.js +194 -0
- package/lib/types/client/zcode-login-link.js.map +1 -0
- package/lib/types/host/account-models.d.mts +10 -2
- package/lib/types/host/account-models.mjs +49 -18
- package/lib/types/host/accounts.d.ts +3 -2
- package/lib/types/host/accounts.js +168 -29
- package/lib/types/host/accounts.js.map +1 -1
- package/lib/types/host/adapters.d.ts +3 -1
- package/lib/types/host/adapters.js +138 -11
- package/lib/types/host/adapters.js.map +1 -1
- package/lib/types/host/agy-background-environment.d.ts +2 -0
- package/lib/types/host/agy-background-environment.js +7 -0
- package/lib/types/host/agy-background-environment.js.map +1 -0
- package/lib/types/host/agy-models.d.ts +2 -1
- package/lib/types/host/agy-models.js +6 -6
- package/lib/types/host/agy-models.js.map +1 -1
- package/lib/types/host/agy-windows-account.d.ts +14 -0
- package/lib/types/host/agy-windows-account.js +104 -0
- package/lib/types/host/agy-windows-account.js.map +1 -0
- package/lib/types/host/authorized-catalog.js +13 -4
- package/lib/types/host/authorized-catalog.js.map +1 -1
- package/lib/types/host/claude-native-oauth.d.ts +17 -0
- package/lib/types/host/claude-native-oauth.js +274 -0
- package/lib/types/host/claude-native-oauth.js.map +1 -0
- package/lib/types/host/claude-own-route.d.ts +45 -0
- package/lib/types/host/claude-own-route.js +375 -0
- package/lib/types/host/claude-own-route.js.map +1 -0
- package/lib/types/host/cli-account-binding.d.ts +2 -1
- package/lib/types/host/cli-account-binding.js +64 -21
- package/lib/types/host/cli-account-binding.js.map +1 -1
- package/lib/types/host/cli-executable-paths.d.ts +30 -0
- package/lib/types/host/cli-executable-paths.js +272 -0
- package/lib/types/host/cli-executable-paths.js.map +1 -0
- package/lib/types/host/codex-models.d.ts +3 -1
- package/lib/types/host/codex-models.js +41 -4
- package/lib/types/host/codex-models.js.map +1 -1
- package/lib/types/host/extended-adapters.d.ts +3 -2
- package/lib/types/host/extended-adapters.js +9 -7
- package/lib/types/host/extended-adapters.js.map +1 -1
- package/lib/types/host/first-party-models.d.ts +5 -0
- package/lib/types/host/first-party-models.js +173 -50
- package/lib/types/host/first-party-models.js.map +1 -1
- package/lib/types/host/hermes-accounts.js +68 -9
- package/lib/types/host/hermes-accounts.js.map +1 -1
- package/lib/types/host/hermes-adapter.d.ts +3 -0
- package/lib/types/host/hermes-adapter.js +13 -4
- package/lib/types/host/hermes-adapter.js.map +1 -1
- package/lib/types/host/hermes-installation.js +54 -35
- package/lib/types/host/hermes-installation.js.map +1 -1
- package/lib/types/host/hermes-models.js +21 -2
- package/lib/types/host/hermes-models.js.map +1 -1
- package/lib/types/host/hermes-native-entry.py +48 -13
- package/lib/types/host/hermes-nous-refresh.py +331 -0
- package/lib/types/host/hermes-nous.d.ts +5 -1
- package/lib/types/host/hermes-nous.js +5 -5
- package/lib/types/host/hermes-nous.js.map +1 -1
- package/lib/types/host/hermes-renewal.d.ts +27 -0
- package/lib/types/host/hermes-renewal.js +292 -0
- package/lib/types/host/hermes-renewal.js.map +1 -0
- package/lib/types/host/hermes-windows-installation.d.ts +5 -0
- package/lib/types/host/hermes-windows-installation.js +91 -0
- package/lib/types/host/hermes-windows-installation.js.map +1 -0
- package/lib/types/host/index.d.ts +12 -0
- package/lib/types/host/index.js +138 -8
- package/lib/types/host/index.js.map +1 -1
- package/lib/types/host/kimi-accounts.d.ts +2 -0
- package/lib/types/host/kimi-accounts.js +4 -2
- package/lib/types/host/kimi-accounts.js.map +1 -1
- package/lib/types/host/kimi-oauth-models.d.ts +14 -0
- package/lib/types/host/kimi-oauth-models.js +246 -0
- package/lib/types/host/kimi-oauth-models.js.map +1 -0
- package/lib/types/host/mimo-metadata-cache.d.ts +22 -0
- package/lib/types/host/mimo-metadata-cache.js +121 -0
- package/lib/types/host/mimo-metadata-cache.js.map +1 -0
- package/lib/types/host/native-capability-cache.d.ts +11 -0
- package/lib/types/host/native-capability-cache.js +94 -0
- package/lib/types/host/native-capability-cache.js.map +1 -0
- package/lib/types/host/native-launch.mjs +62 -7
- package/lib/types/host/native-process.d.ts +3 -1
- package/lib/types/host/native-process.js +30 -5
- package/lib/types/host/native-process.js.map +1 -1
- package/lib/types/host/native-spawn.mjs +32 -0
- package/lib/types/host/opencode-native.js +13 -0
- package/lib/types/host/opencode-native.js.map +1 -1
- package/lib/types/host/pi-installation.d.mts +1 -1
- package/lib/types/host/pi-installation.mjs +27 -3
- package/lib/types/host/pi-omp-adapter.js +17 -3
- package/lib/types/host/pi-omp-adapter.js.map +1 -1
- package/lib/types/host/pi-omp-native.js +5 -3
- package/lib/types/host/pi-omp-native.js.map +1 -1
- package/lib/types/host/pi-omp-refresh.mjs +3 -3
- package/lib/types/host/private-launch.mjs +23 -0
- package/lib/types/host/process.d.ts +3 -0
- package/lib/types/host/process.js +3 -1
- package/lib/types/host/process.js.map +1 -1
- package/lib/types/host/routing.js +25 -2
- package/lib/types/host/routing.js.map +1 -1
- package/lib/types/host/runtime.js +21 -5
- package/lib/types/host/runtime.js.map +1 -1
- package/lib/types/host/settings-catalog-cache.d.ts +28 -0
- package/lib/types/host/settings-catalog-cache.js +189 -0
- package/lib/types/host/settings-catalog-cache.js.map +1 -0
- package/lib/types/host/windows-account-bootstrap.ps1 +44 -0
- package/lib/types/host/windows-account-launch.mjs +47 -0
- package/lib/types/host/windows-account-owner.ps1 +137 -0
- package/lib/types/host/windows-account-stdio.mjs +19 -0
- package/lib/types/host/windows-account-terminal.d.ts +17 -0
- package/lib/types/host/windows-account-terminal.js +208 -0
- package/lib/types/host/windows-account-terminal.js.map +1 -0
- package/lib/types/host/windows-agy-account.ps1 +81 -0
- package/lib/types/host/windows-cli-installation.d.ts +35 -0
- package/lib/types/host/windows-cli-installation.js +164 -0
- package/lib/types/host/windows-cli-installation.js.map +1 -0
- package/lib/types/host/windows-codex-launch.d.ts +9 -0
- package/lib/types/host/windows-codex-launch.js +216 -0
- package/lib/types/host/windows-codex-launch.js.map +1 -0
- package/lib/types/host/windows-desktop-cli-installation.d.ts +20 -0
- package/lib/types/host/windows-desktop-cli-installation.js +420 -0
- package/lib/types/host/windows-desktop-cli-installation.js.map +1 -0
- package/lib/types/host/windows-hidden-launch.mjs +51 -0
- package/lib/types/host/windows-hidden-process.d.ts +12 -0
- package/lib/types/host/windows-hidden-process.js +116 -0
- package/lib/types/host/windows-hidden-process.js.map +1 -0
- package/lib/types/host/zcode-adapter.js +5 -1
- package/lib/types/host/zcode-adapter.js.map +1 -1
- package/lib/types/host/zcode-grok-accounts.d.ts +3 -1
- package/lib/types/host/zcode-grok-accounts.js +60 -11
- package/lib/types/host/zcode-grok-accounts.js.map +1 -1
- package/lib/types/shared/accounts.d.ts +4 -0
- package/lib/types/shared/cli-settings.d.ts +8 -0
- package/lib/windows-account-bootstrap.ps1 +44 -0
- package/lib/windows-account-launch.mjs +47 -0
- package/lib/windows-account-owner.ps1 +137 -0
- package/lib/windows-account-stdio.mjs +19 -0
- package/lib/windows-agy-account.ps1 +81 -0
- package/lib/windows-hidden-launch.mjs +51 -0
- package/lib/zcode-resume.mjs +2 -2
- package/package.json +2 -2
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { isAbsolute, join } from 'node:path';
|
|
3
|
+
import { readKimiOwnToken } from "./kimi-accounts.js";
|
|
4
|
+
const record = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
5
|
+
const id = (value) => typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/.test(value);
|
|
6
|
+
const BASES = new Set(['https://api.kimi.com/coding/v1', 'https://api.kimi.ai/coding/v1']);
|
|
7
|
+
const PROVIDER = 'managed:kimi-code';
|
|
8
|
+
const nearExpiry = (expires, now) => typeof expires !== 'number' || !Number.isFinite(expires) || expires <= now + 30_000;
|
|
9
|
+
export class KimiOAuthModelError extends Error {
|
|
10
|
+
code = 'KIMI_OAUTH_UNAVAILABLE';
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'KimiOAuthModelError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const unavailable = () => new KimiOAuthModelError('Kimi OAuth 配置来源暂无法核验,请检查该 CLI 配置');
|
|
17
|
+
const expired = () => new KimiOAuthModelError('Kimi 登录凭据已过期或即将过期,请打开账号终端完成原生续期或重新登录');
|
|
18
|
+
/** JWT fields label the stable account only. The server must independently accept this token. */
|
|
19
|
+
function ownPrincipal(access) {
|
|
20
|
+
const parts = access.split('.');
|
|
21
|
+
if (parts.length !== 3 ||
|
|
22
|
+
parts[1].length > 16 * 1024 ||
|
|
23
|
+
!parts.every((part) => /^[A-Za-z0-9_-]+$/.test(part)))
|
|
24
|
+
return;
|
|
25
|
+
const bytes = Buffer.from(parts[1], 'base64url');
|
|
26
|
+
try {
|
|
27
|
+
if (bytes.toString('base64url') !== parts[1])
|
|
28
|
+
return;
|
|
29
|
+
const claims = JSON.parse(bytes.toString('utf8'));
|
|
30
|
+
if (!record(claims) || claims.iss !== 'kimi-auth')
|
|
31
|
+
return;
|
|
32
|
+
const subject = claims.sub ?? claims.user_id;
|
|
33
|
+
if (typeof subject !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9_-]{6,127}$/.test(subject))
|
|
34
|
+
return;
|
|
35
|
+
if (claims.sub !== undefined && claims.user_id !== undefined && claims.sub !== claims.user_id)
|
|
36
|
+
return;
|
|
37
|
+
return subject;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
bytes.fill(0);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** This is host-only credential material. Do not return it through Gateway or persist it. */
|
|
47
|
+
export async function readKimiOAuthModelSources(raw, sourceId, signal, options = {}) {
|
|
48
|
+
signal.throwIfAborted();
|
|
49
|
+
if (!record(raw) || !record(raw.providers) || !record(raw.models))
|
|
50
|
+
return [];
|
|
51
|
+
const provider = raw.providers[PROVIDER];
|
|
52
|
+
if (!record(provider) || provider.oauth === undefined)
|
|
53
|
+
return [];
|
|
54
|
+
const baseUrl = typeof provider.baseUrl === 'string' ? provider.baseUrl.replace(/\/+$/, '') : '';
|
|
55
|
+
if (provider.type !== 'kimi' ||
|
|
56
|
+
!BASES.has(baseUrl) ||
|
|
57
|
+
!record(provider.oauth) ||
|
|
58
|
+
provider.oauth.storage !== 'file' ||
|
|
59
|
+
!['oauth/kimi-code', 'kimi-code'].includes(provider.oauth.key) ||
|
|
60
|
+
(provider.oauth.oauthHost !== undefined && provider.oauth.oauthHost !== 'https://auth.kimi.com') ||
|
|
61
|
+
provider.apiKey ||
|
|
62
|
+
provider.apiKeyEnv ||
|
|
63
|
+
provider.env ||
|
|
64
|
+
provider.customHeaders ||
|
|
65
|
+
['KIMI_CODE_BASE_URL', 'KIMI_CODE_OAUTH_HOST', 'KIMI_OAUTH_HOST', 'KIMI_CODE_CUSTOM_HEADERS'].some((key) => process.env[key]))
|
|
66
|
+
throw unavailable();
|
|
67
|
+
const home = options.home ?? process.env.KIMI_CODE_HOME ?? join(homedir(), '.kimi-code');
|
|
68
|
+
if (!isAbsolute(home))
|
|
69
|
+
throw unavailable();
|
|
70
|
+
let token;
|
|
71
|
+
try {
|
|
72
|
+
token = await readKimiOwnToken(join(home, 'credentials'), 'kimi-code', signal);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
signal.throwIfAborted();
|
|
76
|
+
throw unavailable();
|
|
77
|
+
}
|
|
78
|
+
if (!token || typeof token.access_token !== 'string' || !token.access_token.trim())
|
|
79
|
+
throw new KimiOAuthModelError('Kimi OAuth 尚未登录或已退出,请打开账号终端登录');
|
|
80
|
+
const expires = typeof token.expires_at === 'number' ? token.expires_at * 1000 : undefined;
|
|
81
|
+
if (nearExpiry(expires, options.now ?? Date.now()))
|
|
82
|
+
throw expired();
|
|
83
|
+
const accountId = ownPrincipal(token.access_token);
|
|
84
|
+
if (!accountId || (token.token_type !== undefined && String(token.token_type).toLowerCase() !== 'bearer'))
|
|
85
|
+
throw unavailable();
|
|
86
|
+
const nativeModels = [];
|
|
87
|
+
for (const [alias, model] of Object.entries(raw.models)) {
|
|
88
|
+
if (!record(model) ||
|
|
89
|
+
model.provider !== PROVIDER ||
|
|
90
|
+
!id(model.model) ||
|
|
91
|
+
alias !== `kimi-code/${model.model}`)
|
|
92
|
+
continue;
|
|
93
|
+
if (model.oauth || model.providerId || model.apiKey || model.baseUrl || model.customHeaders)
|
|
94
|
+
continue;
|
|
95
|
+
if (model.protocol !== undefined &&
|
|
96
|
+
!['kimi', 'openai', 'openai_responses', 'anthropic'].includes(model.protocol))
|
|
97
|
+
continue;
|
|
98
|
+
nativeModels.push({
|
|
99
|
+
remoteId: model.model,
|
|
100
|
+
choice: {
|
|
101
|
+
id: alias,
|
|
102
|
+
label: typeof model.displayName === 'string' ? model.displayName : alias,
|
|
103
|
+
efforts: ['default'],
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
signal.throwIfAborted();
|
|
108
|
+
return nativeModels.length
|
|
109
|
+
? [
|
|
110
|
+
{
|
|
111
|
+
provider: PROVIDER,
|
|
112
|
+
credential: { type: 'oauth', access: token.access_token, expires, accountId },
|
|
113
|
+
baseUrl,
|
|
114
|
+
apiType: 'kimi-managed-oauth',
|
|
115
|
+
sourceIds: [sourceId, join(home, 'credentials/kimi-code.json'), 'native:kimi-managed-oauth'],
|
|
116
|
+
nativeModels,
|
|
117
|
+
},
|
|
118
|
+
]
|
|
119
|
+
: [];
|
|
120
|
+
}
|
|
121
|
+
async function responseJson(response, signal) {
|
|
122
|
+
if (!response.body)
|
|
123
|
+
throw new KimiOAuthModelError('Kimi 模型或额度响应格式无法确认,请稍后刷新');
|
|
124
|
+
const reader = response.body.getReader(), chunks = [];
|
|
125
|
+
let bytes = 0;
|
|
126
|
+
try {
|
|
127
|
+
while (true) {
|
|
128
|
+
signal.throwIfAborted();
|
|
129
|
+
const item = await reader.read();
|
|
130
|
+
if (item.done)
|
|
131
|
+
break;
|
|
132
|
+
bytes += item.value.byteLength;
|
|
133
|
+
if (bytes > 1_048_576)
|
|
134
|
+
throw new KimiOAuthModelError('Kimi 模型或额度响应过大,请稍后刷新');
|
|
135
|
+
chunks.push(item.value);
|
|
136
|
+
}
|
|
137
|
+
const buffer = Buffer.concat(chunks);
|
|
138
|
+
try {
|
|
139
|
+
return JSON.parse(buffer.toString('utf8'));
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
buffer.fill(0);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
await reader.cancel().catch(() => undefined);
|
|
147
|
+
reader.releaseLock();
|
|
148
|
+
for (const chunk of chunks)
|
|
149
|
+
chunk.fill(0);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Current native subscription quota is required; a public models list is never sufficient. */
|
|
153
|
+
export function kimiQuotaRemaining(raw) {
|
|
154
|
+
if (!record(raw) || !record(raw.usages))
|
|
155
|
+
return 'unknown';
|
|
156
|
+
const entries = ['limit_5h', 'limit_7d', 'limit_month_total', 'limit_month_code']
|
|
157
|
+
.filter((key) => raw.usages[key] !== undefined)
|
|
158
|
+
.map((key) => raw.usages[key]);
|
|
159
|
+
if (!entries.length)
|
|
160
|
+
return 'unknown';
|
|
161
|
+
const ratios = entries.map((entry) => {
|
|
162
|
+
if (!record(entry) || (typeof entry.used_ratio !== 'number' && typeof entry.used_ratio !== 'string'))
|
|
163
|
+
return NaN;
|
|
164
|
+
if (typeof entry.used_ratio === 'string' && !entry.used_ratio.trim())
|
|
165
|
+
return NaN;
|
|
166
|
+
return Number(entry.used_ratio);
|
|
167
|
+
});
|
|
168
|
+
if (ratios.some((ratio) => !Number.isFinite(ratio) || ratio < 0))
|
|
169
|
+
return 'unknown';
|
|
170
|
+
return ratios.some((ratio) => ratio >= 1) ? 'exhausted' : 'available';
|
|
171
|
+
}
|
|
172
|
+
export async function probeKimiOAuthModels(source, options = {}) {
|
|
173
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
174
|
+
signal.throwIfAborted();
|
|
175
|
+
if (source.provider !== PROVIDER ||
|
|
176
|
+
source.apiType !== 'kimi-managed-oauth' ||
|
|
177
|
+
!BASES.has(source.baseUrl || '') ||
|
|
178
|
+
source.credential.type !== 'oauth' ||
|
|
179
|
+
typeof source.credential.access !== 'string' ||
|
|
180
|
+
!source.credential.accountId ||
|
|
181
|
+
ownPrincipal(source.credential.access) !== source.credential.accountId)
|
|
182
|
+
throw unavailable();
|
|
183
|
+
if (nearExpiry(source.credential.expires, Date.now()))
|
|
184
|
+
throw expired();
|
|
185
|
+
const cancel = new AbortController();
|
|
186
|
+
const control = AbortSignal.any([signal, cancel.signal, AbortSignal.timeout(options.timeoutMs ?? 8_000)]);
|
|
187
|
+
const request = async (name) => {
|
|
188
|
+
try {
|
|
189
|
+
const response = await (options.fetch ?? fetch)(`${source.baseUrl}/${name}`, {
|
|
190
|
+
headers: { Authorization: `Bearer ${source.credential.access}`, Accept: 'application/json' },
|
|
191
|
+
redirect: 'error',
|
|
192
|
+
signal: control,
|
|
193
|
+
});
|
|
194
|
+
if (!response.ok) {
|
|
195
|
+
await response.body?.cancel();
|
|
196
|
+
if ([401, 403].includes(response.status))
|
|
197
|
+
throw new KimiOAuthModelError('Kimi 登录或订阅授权未通过,请打开账号终端检查登录与额度');
|
|
198
|
+
throw new KimiOAuthModelError('Kimi 模型或额度查询暂不可用,请稍后刷新');
|
|
199
|
+
}
|
|
200
|
+
return await responseJson(response, control);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
signal.throwIfAborted();
|
|
204
|
+
if (error instanceof KimiOAuthModelError)
|
|
205
|
+
throw error;
|
|
206
|
+
throw new KimiOAuthModelError('Kimi 模型或额度查询失败,请检查网络后刷新');
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const requests = [request('models'), request('usages')];
|
|
210
|
+
try {
|
|
211
|
+
const [models, usages] = await Promise.all(requests);
|
|
212
|
+
signal.throwIfAborted();
|
|
213
|
+
if (nearExpiry(source.credential.expires, Date.now()))
|
|
214
|
+
throw expired();
|
|
215
|
+
const quota = kimiQuotaRemaining(usages);
|
|
216
|
+
if (quota === 'exhausted')
|
|
217
|
+
throw new KimiOAuthModelError('Kimi 当前账号额度已用尽,请等待重置或检查订阅');
|
|
218
|
+
if (quota !== 'available')
|
|
219
|
+
throw new KimiOAuthModelError('Kimi 当前账号剩余额度暂无法确认,请在账号终端检查后刷新');
|
|
220
|
+
if (!record(models) || !Array.isArray(models.data))
|
|
221
|
+
throw new KimiOAuthModelError('Kimi 模型目录格式无法确认,请稍后刷新');
|
|
222
|
+
return {
|
|
223
|
+
state: 'supported',
|
|
224
|
+
source: 'account-models',
|
|
225
|
+
models: models.data
|
|
226
|
+
.filter((model) => record(model) &&
|
|
227
|
+
id(model.id) &&
|
|
228
|
+
Number.isInteger(Number(model.context_length)) &&
|
|
229
|
+
Number(model.context_length) > 0 &&
|
|
230
|
+
model.available !== false &&
|
|
231
|
+
model.allowed !== false &&
|
|
232
|
+
model.disabled !== true &&
|
|
233
|
+
model.entitled !== false)
|
|
234
|
+
.map((model) => ({
|
|
235
|
+
id: model.id,
|
|
236
|
+
name: typeof model.display_name === 'string' ? model.display_name : undefined,
|
|
237
|
+
cost: 'unknown',
|
|
238
|
+
})),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
cancel.abort();
|
|
243
|
+
await Promise.allSettled(requests);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=kimi-oauth-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kimi-oauth-models.js","sourceRoot":"","sources":["../../../src/host/kimi-oauth-models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAIrD,MAAM,MAAM,GAAG,CAAC,KAAc,EAAgC,EAAE,CAC9D,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC/D,MAAM,EAAE,GAAG,CAAC,KAAc,EAAmB,EAAE,CAC7C,OAAO,KAAK,KAAK,QAAQ,IAAI,gCAAgC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAC3E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,gCAAgC,EAAE,+BAA+B,CAAC,CAAC,CAAA;AAC1F,MAAM,QAAQ,GAAG,mBAAmB,CAAA;AACpC,MAAM,UAAU,GAAG,CAAC,OAAgB,EAAE,GAAW,EAAW,EAAE,CAC5D,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,GAAG,GAAG,MAAM,CAAA;AAErF,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,GAAG,wBAAwB,CAAA;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAA;IACnC,CAAC;CACF;AACD,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,IAAI,mBAAmB,CAAC,kCAAkC,CAAC,CAAA;AACrF,MAAM,OAAO,GAAG,GAAG,EAAE,CACnB,IAAI,mBAAmB,CAAC,sCAAsC,CAAC,CAAA;AAEjE,iGAAiG;AACjG,SAAS,YAAY,CAAC,MAAc;IAClC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC/B,IACE,KAAK,CAAC,MAAM,KAAK,CAAC;QAClB,KAAK,CAAC,CAAC,CAAE,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI;QAC5B,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAErD,OAAM;IACR,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,WAAW,CAAC,CAAA;IACjD,IAAI,CAAC;QACH,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC;YAAE,OAAM;QACpD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;QAC1D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,GAAG,KAAK,WAAW;YAAE,OAAM;QACzD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,CAAA;QAC5C,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,mCAAmC,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAM;QAC7F,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,OAAO;YAAE,OAAM;QACrG,OAAO,OAAO,CAAA;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAM;IACR,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACf,CAAC;AACH,CAAC;AAED,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,GAAY,EACZ,QAAgB,EAChB,MAAmB,EACnB,UAA2C,EAAE;IAE7C,MAAM,CAAC,cAAc,EAAE,CAAA;IACvB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAA;IAC5E,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IACxC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IAChE,MAAM,OAAO,GAAG,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAChG,IACE,QAAQ,CAAC,IAAI,KAAK,MAAM;QACxB,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;QACnB,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACvB,QAAQ,CAAC,KAAK,CAAC,OAAO,KAAK,MAAM;QACjC,CAAC,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;QAC9D,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,SAAS,KAAK,uBAAuB,CAAC;QAChG,QAAQ,CAAC,MAAM;QACf,QAAQ,CAAC,SAAS;QAClB,QAAQ,CAAC,GAAG;QACZ,QAAQ,CAAC,aAAa;QACtB,CAAC,oBAAoB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,0BAA0B,CAAC,CAAC,IAAI,CAChG,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAC1B;QAED,MAAM,WAAW,EAAE,CAAA;IACrB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAA;IACxF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,WAAW,EAAE,CAAA;IAC1C,IAAI,KAAsC,CAAA;IAC1C,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,cAAc,EAAE,CAAA;QACvB,MAAM,WAAW,EAAE,CAAA;IACrB,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE;QAChF,MAAM,IAAI,mBAAmB,CAAC,+BAA+B,CAAC,CAAA;IAChE,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;IAC1F,IAAI,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QAAE,MAAM,OAAO,EAAE,CAAA;IACnE,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IAClD,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC;QACvG,MAAM,WAAW,EAAE,CAAA;IACrB,MAAM,YAAY,GAA0C,EAAE,CAAA;IAC9D,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,IACE,CAAC,MAAM,CAAC,KAAK,CAAC;YACd,KAAK,CAAC,QAAQ,KAAK,QAAQ;YAC3B,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;YAChB,KAAK,KAAK,aAAa,KAAK,CAAC,KAAK,EAAE;YAEpC,SAAQ;QACV,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,aAAa;YAAE,SAAQ;QACrG,IACE,KAAK,CAAC,QAAQ,KAAK,SAAS;YAC5B,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;YAE7E,SAAQ;QACV,YAAY,CAAC,IAAI,CAAC;YAChB,QAAQ,EAAE,KAAK,CAAC,KAAK;YACrB,MAAM,EAAE;gBACN,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK;gBACxE,OAAO,EAAE,CAAC,SAAS,CAAC;aACrB;SACF,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,CAAC,cAAc,EAAE,CAAA;IACvB,OAAO,YAAY,CAAC,MAAM;QACxB,CAAC,CAAC;YACE;gBACE,QAAQ,EAAE,QAAQ;gBAClB,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE;gBAC7E,OAAO;gBACP,OAAO,EAAE,oBAAoB;gBAC7B,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,4BAA4B,CAAC,EAAE,2BAA2B,CAAC;gBAC5F,YAAY;aACb;SACF;QACH,CAAC,CAAC,EAAE,CAAA;AACR,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,QAAkB,EAAE,MAAmB;IACjE,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,MAAM,IAAI,mBAAmB,CAAC,0BAA0B,CAAC,CAAA;IAC7E,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,EACtC,MAAM,GAAiB,EAAE,CAAA;IAC3B,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,CAAC,cAAc,EAAE,CAAA;YACvB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;YAChC,IAAI,IAAI,CAAC,IAAI;gBAAE,MAAK;YACpB,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAA;YAC9B,IAAI,KAAK,GAAG,SAAS;gBAAE,MAAM,IAAI,mBAAmB,CAAC,sBAAsB,CAAC,CAAA;YAC5E,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACzB,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACpC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;QAC5C,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;QAC5C,MAAM,CAAC,WAAW,EAAE,CAAA;QACpB,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC3C,CAAC;AACH,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC7C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAA;IACzD,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,mBAAmB,EAAE,kBAAkB,CAAC;SAC9E,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;SAC9C,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;IAChC,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IACrC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC;YAClG,OAAO,GAAG,CAAA;QACZ,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE;YAAE,OAAO,GAAG,CAAA;QAChF,OAAO,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IACF,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAClF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAA;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAA6B,EAC7B,UAAoD,EAAE;IAEtD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC,MAAM,CAAA;IAC7D,MAAM,CAAC,cAAc,EAAE,CAAA;IACvB,IACE,MAAM,CAAC,QAAQ,KAAK,QAAQ;QAC5B,MAAM,CAAC,OAAO,KAAK,oBAAoB;QACvC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QAChC,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK,OAAO;QAClC,OAAO,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,QAAQ;QAC5C,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS;QAC5B,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,UAAU,CAAC,SAAS;QAEtE,MAAM,WAAW,EAAE,CAAA;IACrB,IAAI,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;QAAE,MAAM,OAAO,EAAE,CAAA;IACtE,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAA;IACpC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,CAAA;IACzG,MAAM,OAAO,GAAG,KAAK,EAAE,IAAyB,EAAE,EAAE;QAClD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,EAAE,EAAE;gBAC3E,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;gBAC5F,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,OAAO;aAChB,CAAC,CAAA;YACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;gBAC7B,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;oBACtC,MAAM,IAAI,mBAAmB,CAAC,gCAAgC,CAAC,CAAA;gBACjE,MAAM,IAAI,mBAAmB,CAAC,wBAAwB,CAAC,CAAA;YACzD,CAAC;YACD,OAAO,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAC9C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,cAAc,EAAE,CAAA;YACvB,IAAI,KAAK,YAAY,mBAAmB;gBAAE,MAAM,KAAK,CAAA;YACrD,MAAM,IAAI,mBAAmB,CAAC,yBAAyB,CAAC,CAAA;QAC1D,CAAC;IACH,CAAC,CAAA;IACD,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IACvD,IAAI,CAAC;QACH,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACpD,MAAM,CAAC,cAAc,EAAE,CAAA;QACvB,IAAI,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;YAAE,MAAM,OAAO,EAAE,CAAA;QACtE,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;QACxC,IAAI,KAAK,KAAK,WAAW;YAAE,MAAM,IAAI,mBAAmB,CAAC,2BAA2B,CAAC,CAAA;QACrF,IAAI,KAAK,KAAK,WAAW;YACvB,MAAM,IAAI,mBAAmB,CAAC,gCAAgC,CAAC,CAAA;QACjE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;YAChD,MAAM,IAAI,mBAAmB,CAAC,uBAAuB,CAAC,CAAA;QACxD,OAAO;YACL,KAAK,EAAE,WAAW;YAClB,MAAM,EAAE,gBAAgB;YACxB,MAAM,EAAE,MAAM,CAAC,IAAI;iBAChB,MAAM,CACL,CAAC,KAAK,EAAE,EAAE,CACR,MAAM,CAAC,KAAK,CAAC;gBACb,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;gBACZ,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;gBAC9C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC;gBAChC,KAAK,CAAC,SAAS,KAAK,KAAK;gBACzB,KAAK,CAAC,OAAO,KAAK,KAAK;gBACvB,KAAK,CAAC,QAAQ,KAAK,IAAI;gBACvB,KAAK,CAAC,QAAQ,KAAK,KAAK,CAC3B;iBACA,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACf,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,IAAI,EAAE,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;gBAC7E,IAAI,EAAE,SAAkB;aACzB,CAAC,CAAC;SACN,CAAA;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,KAAK,EAAE,CAAA;QACd,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;IACpC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { FirstPartyModelSource } from './first-party-models.ts';
|
|
2
|
+
export interface MimoOwnSnapshot {
|
|
3
|
+
authPath: string;
|
|
4
|
+
auth: Record<string, any>;
|
|
5
|
+
configurations: {
|
|
6
|
+
path: string;
|
|
7
|
+
value: Record<string, any>;
|
|
8
|
+
}[];
|
|
9
|
+
}
|
|
10
|
+
/** No raw environment, configuration or account material is retained in the cache key. */
|
|
11
|
+
export declare function nativeMetadataKey(executable: string, project: string, snapshot: unknown, signal: AbortSignal): Promise<string | undefined>;
|
|
12
|
+
export declare const mimoMetadataKey: typeof nativeMetadataKey;
|
|
13
|
+
/** Only native capabilities are reused. Remote entitlement discovery must still run on every call. */
|
|
14
|
+
export declare class MimoMetadataCache {
|
|
15
|
+
private readonly ttlMs;
|
|
16
|
+
private readonly limit;
|
|
17
|
+
private readonly entries;
|
|
18
|
+
constructor(ttlMs?: number, limit?: number);
|
|
19
|
+
get(key: string | undefined, own: MimoOwnSnapshot): FirstPartyModelSource[] | undefined;
|
|
20
|
+
set(key: string | undefined, sources: FirstPartyModelSource[], own: MimoOwnSnapshot): void;
|
|
21
|
+
}
|
|
22
|
+
export declare const mimoMetadataCache: MimoMetadataCache;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute } from 'node:path';
|
|
4
|
+
import { nativeLaunchArgv } from './native-launch.mjs';
|
|
5
|
+
const digest = (value) => createHash('sha256').update(JSON.stringify(value)).digest('hex');
|
|
6
|
+
/** No raw environment, configuration or account material is retained in the cache key. */
|
|
7
|
+
export async function nativeMetadataKey(executable, project, snapshot, signal) {
|
|
8
|
+
signal.throwIfAborted();
|
|
9
|
+
try {
|
|
10
|
+
// Use the same static launch plan as the process boundary. A fixed Bun shim
|
|
11
|
+
// can stay unchanged while its actual runtime or script is upgraded.
|
|
12
|
+
const launch = nativeLaunchArgv([executable]);
|
|
13
|
+
const identities = [];
|
|
14
|
+
for (const path of new Set([executable, ...launch.filter(isAbsolute)])) {
|
|
15
|
+
const entry = await realpath(path), identity = await stat(entry);
|
|
16
|
+
signal.throwIfAborted();
|
|
17
|
+
if (!identity.isFile())
|
|
18
|
+
return;
|
|
19
|
+
identities.push([entry, identity.dev, identity.ino, identity.size, identity.mtimeMs, identity.ctimeMs]);
|
|
20
|
+
}
|
|
21
|
+
const physicalProject = await realpath(project);
|
|
22
|
+
signal.throwIfAborted();
|
|
23
|
+
return digest({
|
|
24
|
+
launch,
|
|
25
|
+
project,
|
|
26
|
+
physicalProject,
|
|
27
|
+
identities,
|
|
28
|
+
environment: Object.entries(process.env).sort(([a], [b]) => a.localeCompare(b)),
|
|
29
|
+
snapshot,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
signal.throwIfAborted();
|
|
34
|
+
// An unverifiable executable still follows the uncached native validation path.
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export const mimoMetadataKey = nativeMetadataKey;
|
|
39
|
+
function currentCredential(source, own) {
|
|
40
|
+
for (const path of source.sourceIds) {
|
|
41
|
+
const value = path === own.authPath
|
|
42
|
+
? own.auth[source.provider]
|
|
43
|
+
: {
|
|
44
|
+
type: 'api',
|
|
45
|
+
key: own.configurations.find((item) => item.path === path)?.value.provider?.[source.provider]
|
|
46
|
+
?.options?.apiKey,
|
|
47
|
+
};
|
|
48
|
+
if (value?.type !== 'api' || typeof value.key !== 'string' || !value.key)
|
|
49
|
+
continue;
|
|
50
|
+
const credential = { type: 'api', key: value.key };
|
|
51
|
+
if (digest(credential) === source.credentialHash)
|
|
52
|
+
return credential;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Only native capabilities are reused. Remote entitlement discovery must still run on every call. */
|
|
56
|
+
export class MimoMetadataCache {
|
|
57
|
+
ttlMs;
|
|
58
|
+
limit;
|
|
59
|
+
entries = new Map();
|
|
60
|
+
constructor(ttlMs = 30_000, limit = 16) {
|
|
61
|
+
this.ttlMs = ttlMs;
|
|
62
|
+
this.limit = limit;
|
|
63
|
+
}
|
|
64
|
+
get(key, own) {
|
|
65
|
+
if (!key)
|
|
66
|
+
return;
|
|
67
|
+
const entry = this.entries.get(key), now = Date.now();
|
|
68
|
+
if (!entry)
|
|
69
|
+
return;
|
|
70
|
+
if (now < entry.created || now - entry.created >= this.ttlMs) {
|
|
71
|
+
this.entries.delete(key);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const sources = [];
|
|
75
|
+
for (const metadata of entry.sources) {
|
|
76
|
+
const credential = currentCredential(metadata, own);
|
|
77
|
+
if (!credential) {
|
|
78
|
+
this.entries.delete(key);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const { credentialHash: _, ...source } = metadata;
|
|
82
|
+
sources.push({ ...structuredClone(source), credential });
|
|
83
|
+
}
|
|
84
|
+
return sources;
|
|
85
|
+
}
|
|
86
|
+
set(key, sources, own) {
|
|
87
|
+
if (!key || !sources.length)
|
|
88
|
+
return;
|
|
89
|
+
const metadata = [];
|
|
90
|
+
for (const source of sources) {
|
|
91
|
+
if (source.credential.type !== 'api')
|
|
92
|
+
return;
|
|
93
|
+
// A user-defined URL may itself carry a credential; such sources stay uncached.
|
|
94
|
+
try {
|
|
95
|
+
const url = new URL(source.baseUrl || '');
|
|
96
|
+
if (url.username || url.password || url.search || url.hash)
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const { credential, ...capabilities } = source;
|
|
103
|
+
if (credential.key && JSON.stringify(capabilities).includes(credential.key))
|
|
104
|
+
return;
|
|
105
|
+
const entry = { ...structuredClone(capabilities), credentialHash: digest(credential) };
|
|
106
|
+
if (!currentCredential(entry, own))
|
|
107
|
+
return;
|
|
108
|
+
metadata.push(entry);
|
|
109
|
+
}
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
for (const [id, entry] of this.entries)
|
|
112
|
+
if (now < entry.created || now - entry.created >= this.ttlMs)
|
|
113
|
+
this.entries.delete(id);
|
|
114
|
+
this.entries.delete(key);
|
|
115
|
+
this.entries.set(key, { created: now, sources: metadata });
|
|
116
|
+
while (this.entries.size > this.limit)
|
|
117
|
+
this.entries.delete(this.entries.keys().next().value);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export const mimoMetadataCache = new MimoMetadataCache();
|
|
121
|
+
//# sourceMappingURL=mimo-metadata-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mimo-metadata-cache.js","sourceRoot":"","sources":["../../../src/host/mimo-metadata-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Hash current bounded own files without retaining file content or following links. */
|
|
2
|
+
export declare function metadataFileFingerprint(path: string, signal: AbortSignal): Promise<string | undefined>;
|
|
3
|
+
/** Callers admit only validated public capabilities, never account status or raw CLI output. */
|
|
4
|
+
export declare class NativeCapabilityCache<T> {
|
|
5
|
+
private readonly ttlMs;
|
|
6
|
+
private readonly limit;
|
|
7
|
+
private readonly entries;
|
|
8
|
+
constructor(ttlMs?: number, limit?: number);
|
|
9
|
+
get(key: string | undefined): T | undefined;
|
|
10
|
+
set(key: string | undefined, value: T): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { lstat, open } from 'node:fs/promises';
|
|
4
|
+
import { dirname } from 'node:path';
|
|
5
|
+
import { safePiOmpAncestors } from "./pi-omp-native.js";
|
|
6
|
+
/** Hash current bounded own files without retaining file content or following links. */
|
|
7
|
+
export async function metadataFileFingerprint(path, signal) {
|
|
8
|
+
let file;
|
|
9
|
+
let bytes;
|
|
10
|
+
try {
|
|
11
|
+
signal.throwIfAborted();
|
|
12
|
+
await safePiOmpAncestors(dirname(path));
|
|
13
|
+
const before = await lstat(path);
|
|
14
|
+
if (before.isSymbolicLink() || !before.isFile() || before.nlink !== 1 || before.size > 1_048_576)
|
|
15
|
+
return;
|
|
16
|
+
file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
17
|
+
const opened = await file.stat();
|
|
18
|
+
if (!opened.isFile() ||
|
|
19
|
+
opened.dev !== before.dev ||
|
|
20
|
+
opened.ino !== before.ino ||
|
|
21
|
+
opened.nlink !== 1 ||
|
|
22
|
+
opened.size !== before.size ||
|
|
23
|
+
opened.size > 1_048_576 ||
|
|
24
|
+
opened.mtimeMs !== before.mtimeMs)
|
|
25
|
+
return;
|
|
26
|
+
bytes = Buffer.alloc(opened.size + 1);
|
|
27
|
+
let offset = 0;
|
|
28
|
+
while (offset < bytes.length) {
|
|
29
|
+
signal.throwIfAborted();
|
|
30
|
+
const read = await file.read(bytes, offset, bytes.length - offset, offset);
|
|
31
|
+
if (!read.bytesRead)
|
|
32
|
+
break;
|
|
33
|
+
offset += read.bytesRead;
|
|
34
|
+
}
|
|
35
|
+
const after = await file.stat(), current = await lstat(path);
|
|
36
|
+
signal.throwIfAborted();
|
|
37
|
+
if (current.isSymbolicLink() ||
|
|
38
|
+
current.dev !== opened.dev ||
|
|
39
|
+
current.ino !== opened.ino ||
|
|
40
|
+
current.nlink !== 1 ||
|
|
41
|
+
offset !== opened.size ||
|
|
42
|
+
after.size !== opened.size ||
|
|
43
|
+
current.size !== opened.size ||
|
|
44
|
+
after.mtimeMs !== opened.mtimeMs ||
|
|
45
|
+
current.mtimeMs !== opened.mtimeMs ||
|
|
46
|
+
after.ctimeMs !== opened.ctimeMs ||
|
|
47
|
+
current.ctimeMs !== opened.ctimeMs)
|
|
48
|
+
return;
|
|
49
|
+
return createHash('sha256').update(bytes.subarray(0, offset)).digest('hex');
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
signal.throwIfAborted();
|
|
53
|
+
return error.code === 'ENOENT' ? 'missing' : undefined;
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
bytes?.fill(0);
|
|
57
|
+
await file?.close();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Callers admit only validated public capabilities, never account status or raw CLI output. */
|
|
61
|
+
export class NativeCapabilityCache {
|
|
62
|
+
ttlMs;
|
|
63
|
+
limit;
|
|
64
|
+
entries = new Map();
|
|
65
|
+
constructor(ttlMs = 30_000, limit = 16) {
|
|
66
|
+
this.ttlMs = ttlMs;
|
|
67
|
+
this.limit = limit;
|
|
68
|
+
}
|
|
69
|
+
get(key) {
|
|
70
|
+
if (!key)
|
|
71
|
+
return;
|
|
72
|
+
const entry = this.entries.get(key), now = Date.now();
|
|
73
|
+
if (!entry)
|
|
74
|
+
return;
|
|
75
|
+
if (now < entry.created || now - entry.created >= this.ttlMs) {
|
|
76
|
+
this.entries.delete(key);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
return structuredClone(entry.value);
|
|
80
|
+
}
|
|
81
|
+
set(key, value) {
|
|
82
|
+
if (!key)
|
|
83
|
+
return;
|
|
84
|
+
const now = Date.now();
|
|
85
|
+
for (const [id, entry] of this.entries)
|
|
86
|
+
if (now < entry.created || now - entry.created >= this.ttlMs)
|
|
87
|
+
this.entries.delete(id);
|
|
88
|
+
this.entries.delete(key);
|
|
89
|
+
this.entries.set(key, { created: now, value: structuredClone(value) });
|
|
90
|
+
while (this.entries.size > this.limit)
|
|
91
|
+
this.entries.delete(this.entries.keys().next().value);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=native-capability-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-capability-cache.js","sourceRoot":"","sources":["../../../src/host/native-capability-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// Inspect fixed launcher data; never ask a shell to interpret CLI arguments.
|
|
2
2
|
import { openSync, readSync, fstatSync, closeSync, realpathSync, statSync, existsSync } from 'node:fs'
|
|
3
|
-
import { dirname, extname, isAbsolute, resolve, sep, delimiter, join } from 'node:path'
|
|
3
|
+
import { basename, dirname, extname, isAbsolute, relative, resolve, sep, delimiter, join } from 'node:path'
|
|
4
4
|
import { homedir, userInfo } from 'node:os'
|
|
5
5
|
|
|
6
|
-
const invalid = () =>
|
|
6
|
+
const invalid = () => Object.assign(
|
|
7
|
+
new Error('CLI 启动入口无法确认,请配置原生程序或固定 Node/Bun 入口'),
|
|
8
|
+
{ code: 'CLI_LAUNCHER_UNSUPPORTED' },
|
|
9
|
+
)
|
|
7
10
|
const batch = (value) => /\.(?:cmd|bat)$/i.test(value)
|
|
8
11
|
function text(path, limit = 128 * 1024) {
|
|
9
12
|
const descriptor = openSync(path, 'r')
|
|
@@ -73,6 +76,45 @@ function runtimeProgram(runtime, platform, launcherDirectory) {
|
|
|
73
76
|
if (!candidate) throw new Error('未找到 Bun,请安装该 CLI 所需的 Bun 运行时')
|
|
74
77
|
return file(candidate)
|
|
75
78
|
}
|
|
79
|
+
/** npm's native bin shim is data, not a batch program to execute. */
|
|
80
|
+
function nativePackageBin(shim, suffix) {
|
|
81
|
+
const parts = suffix.replace(/\\/g, '/').split('/')
|
|
82
|
+
if (parts[0] !== 'node_modules' || parts.some((part) => !part || part === '.' || part === '..'))
|
|
83
|
+
throw invalid()
|
|
84
|
+
const scoped = parts[1]?.startsWith('@')
|
|
85
|
+
const name = parts.slice(1, scoped ? 3 : 2).join('/')
|
|
86
|
+
if (!/^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/.test(name)) throw invalid()
|
|
87
|
+
const root = fileDirectory(resolve(dirname(shim), ...parts.slice(0, scoped ? 3 : 2)))
|
|
88
|
+
const entry = file(resolve(dirname(shim), ...parts))
|
|
89
|
+
const inside = relative(root, entry)
|
|
90
|
+
if (!inside || inside === '..' || inside.startsWith('..' + sep) || isAbsolute(inside)) throw invalid()
|
|
91
|
+
const manifest = JSON.parse(text(join(root, 'package.json')))
|
|
92
|
+
const command = basename(shim, extname(shim))
|
|
93
|
+
const declared = typeof manifest.bin === 'string'
|
|
94
|
+
? name.split('/').at(-1) === command ? manifest.bin : undefined
|
|
95
|
+
: manifest.bin?.[command]
|
|
96
|
+
if (manifest.name !== name || typeof declared !== 'string' || isAbsolute(declared) ||
|
|
97
|
+
declared.replace(/\\/g, '/').split('/').includes('..') || file(resolve(root, declared)) !== entry)
|
|
98
|
+
throw invalid()
|
|
99
|
+
const descriptor = openSync(entry, 'r')
|
|
100
|
+
try {
|
|
101
|
+
const header = Buffer.alloc(64), signature = Buffer.alloc(4)
|
|
102
|
+
const size = fstatSync(descriptor).size
|
|
103
|
+
if (readSync(descriptor, header, 0, 64, 0) !== 64 || header.toString('ascii', 0, 2) !== 'MZ')
|
|
104
|
+
throw invalid()
|
|
105
|
+
const offset = header.readUInt32LE(0x3c)
|
|
106
|
+
if (offset < 64 || offset + 4 > size || readSync(descriptor, signature, 0, 4, offset) !== 4 ||
|
|
107
|
+
signature.toString('hex') !== '50450000') throw invalid()
|
|
108
|
+
} finally {
|
|
109
|
+
closeSync(descriptor)
|
|
110
|
+
}
|
|
111
|
+
return entry
|
|
112
|
+
}
|
|
113
|
+
function fileDirectory(path) {
|
|
114
|
+
const canonical = realpathSync(path)
|
|
115
|
+
if (!statSync(canonical).isDirectory()) throw invalid()
|
|
116
|
+
return canonical
|
|
117
|
+
}
|
|
76
118
|
function inspectBatch(executable, platform) {
|
|
77
119
|
const source = text(file(executable)).trim().replace(/\r\n/g, '\n')
|
|
78
120
|
// Nous' official fallback contains just a fixed interpreter and its encoded
|
|
@@ -101,8 +143,14 @@ function inspectBatch(executable, platform) {
|
|
|
101
143
|
// npm cmd-shim's standard final control prefix is launcher boilerplate;
|
|
102
144
|
// it is discarded, and nothing from it is executed by this module.
|
|
103
145
|
line = line.replace(/^endLocal & goto #_undefined_# 2>NUL \|\| title [^&\n]+ & /i, '')
|
|
146
|
+
const native = /^@?"%(?:~dp0[\\/]?|dp0%[\\/])([^"\n%]+\.exe)"\s+%\*$/i.exec(line)
|
|
147
|
+
if (native) {
|
|
148
|
+
entries.add(nativePackageBin(executable, native[1]))
|
|
149
|
+
runtimes.add('native')
|
|
150
|
+
continue
|
|
151
|
+
}
|
|
104
152
|
const command =
|
|
105
|
-
/^@?(?:(node|bun)|"%_prog%"|"%(?:~dp0
|
|
153
|
+
/^@?(?:(node|bun)|"%_prog%"|"%(?:~dp0[\\/]?|dp0%[\\/])(node|bun)\.exe")\s+"%(?:~dp0[\\/]?|dp0%[\\/])([^"\n%]+)"\s+%\*$/i.exec(
|
|
106
154
|
line,
|
|
107
155
|
)
|
|
108
156
|
if (command) {
|
|
@@ -112,7 +160,7 @@ function inspectBatch(executable, platform) {
|
|
|
112
160
|
if (command[1] || command[2]) runtimes.add((command[1] || command[2]).toLowerCase())
|
|
113
161
|
continue
|
|
114
162
|
}
|
|
115
|
-
const program = /^@?set "?_prog=(?:%(?:~dp0
|
|
163
|
+
const program = /^@?set "?_prog=(?:%(?:~dp0[\\/]?|dp0%[\\/]))?(node|bun)(?:\.exe)?"?$/i.exec(line)
|
|
116
164
|
if (program) {
|
|
117
165
|
runtimes.add(program[1].toLowerCase())
|
|
118
166
|
continue
|
|
@@ -121,7 +169,7 @@ function inspectBatch(executable, platform) {
|
|
|
121
169
|
/^@?(?:goto start|:find_dp0|:start|set dp0=%~dp0|exit \/b|setlocal|endlocal|call :find_dp0)$/i.test(
|
|
122
170
|
line,
|
|
123
171
|
) ||
|
|
124
|
-
/^@?if (?:not )?exist "%(?:~dp0
|
|
172
|
+
/^@?if (?:not )?exist "%(?:~dp0[\\/]?|dp0%[\\/])(?:node|bun)\.exe" \($/i.test(line) ||
|
|
125
173
|
/^\)(?: else \()?$/i.test(line) ||
|
|
126
174
|
/^@?set pathext=%pathext:;\.js;=;%$/i.test(line) ||
|
|
127
175
|
/^@?if (?:not )?defined node_path \($/i.test(line) ||
|
|
@@ -133,6 +181,7 @@ function inspectBatch(executable, platform) {
|
|
|
133
181
|
if (entries.size !== 1 || runtimes.size !== 1) throw invalid()
|
|
134
182
|
const entry = [...entries][0],
|
|
135
183
|
runtime = [...runtimes][0]
|
|
184
|
+
if (runtime === 'native') return { kind: 'native', argv: [entry] }
|
|
136
185
|
if (scriptRuntime(entry) !== runtime) throw invalid()
|
|
137
186
|
return { kind: runtime, argv: [runtimeProgram(runtime, platform, dirname(executable)), entry] }
|
|
138
187
|
}
|
|
@@ -151,10 +200,16 @@ export function resolveNativeEntry(executable, platform = process.platform) {
|
|
|
151
200
|
if (candidate) executable = candidate
|
|
152
201
|
}
|
|
153
202
|
if (!batch(executable)) return executable
|
|
154
|
-
|
|
203
|
+
let inspected
|
|
204
|
+
try {
|
|
205
|
+
inspected = inspectBatch(executable, platform)
|
|
206
|
+
} catch {
|
|
207
|
+
// A present but invalid shim is not an absent CLI. Never forward raw paths or script text.
|
|
208
|
+
throw invalid()
|
|
209
|
+
}
|
|
155
210
|
// Keep Bun's fixed shim identity: it may pin a bundled bun.exe beside the
|
|
156
211
|
// shim which cannot be recovered from only the package's JS path.
|
|
157
|
-
return inspected.kind === 'node' ? inspected.argv[1] : executable
|
|
212
|
+
return inspected.kind === 'node' ? inspected.argv[1] : inspected.kind === 'native' ? inspected.argv[0] : executable
|
|
158
213
|
}
|
|
159
214
|
|
|
160
215
|
/** Windows CreateProcess accepts real programs, not npm command files. */
|