openyida 2026.7.6 → 2026.7.7-1
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/bin/yida.js +3 -3
- package/lib/auth/auth.js +11 -3
- package/lib/auth/login.js +34 -15
- package/lib/core/env.js +19 -4
- package/lib/core/utils.js +195 -15
- package/package.json +1 -1
- package/scripts/eval/score.js +14 -6
package/bin/yida.js
CHANGED
|
@@ -266,7 +266,7 @@ function printLoginResult(result) {
|
|
|
266
266
|
corp_id: result && result.corp_id,
|
|
267
267
|
user_id: result && result.user_id,
|
|
268
268
|
csrf_token: result && result.csrf_token ? `${result.csrf_token.slice(0, 16)}...` : undefined,
|
|
269
|
-
cookies_count: Array.isArray(result && result.cookies) ? result.cookies.length : 0,
|
|
269
|
+
cookies_count: Array.isArray(result && result.cookies) ? result.cookies.length : (result.cookies_count || 0),
|
|
270
270
|
};
|
|
271
271
|
console.log(JSON.stringify(summary));
|
|
272
272
|
}
|
|
@@ -559,7 +559,7 @@ async function main() {
|
|
|
559
559
|
case 'login': {
|
|
560
560
|
const { checkLoginOnly } = require('../lib/auth/login');
|
|
561
561
|
const loginArgs = applyLoginEnvironmentFlags(args, { inferTargetUrl: true });
|
|
562
|
-
const {
|
|
562
|
+
const { isEnvAuthMode } = require('../lib/core/utils');
|
|
563
563
|
if (loginArgs.includes('--agent-poll') || loginArgs.includes('--codex-poll')) {
|
|
564
564
|
const sessionFile = getArgValue(loginArgs, '--agent-poll') || getArgValue(loginArgs, '--codex-poll');
|
|
565
565
|
const { pollCodexQrLogin } = require('../lib/auth/qr-login');
|
|
@@ -577,7 +577,7 @@ async function main() {
|
|
|
577
577
|
} else if (loginArgs.includes('--check-only')) {
|
|
578
578
|
const result = checkLoginOnly({ includeSecrets: loginArgs.includes('--with-cookies') });
|
|
579
579
|
console.log(JSON.stringify(result, null, 2));
|
|
580
|
-
} else if (
|
|
580
|
+
} else if (isEnvAuthMode()) {
|
|
581
581
|
const result = checkLoginOnly({ includeSecrets: true });
|
|
582
582
|
printLoginResult(result);
|
|
583
583
|
} else if (shouldUseCodexQrLogin(loginArgs)) {
|
package/lib/auth/auth.js
CHANGED
|
@@ -32,6 +32,13 @@ const { t } = require('../core/i18n');
|
|
|
32
32
|
|
|
33
33
|
const AUTH_CACHE_FILE = '.cache/auth.json';
|
|
34
34
|
|
|
35
|
+
function maskIdentifier(value) {
|
|
36
|
+
const text = String(value || '');
|
|
37
|
+
if (!text) {return null;}
|
|
38
|
+
if (text.length <= 8) {return `${text.slice(0, 2)}***${text.slice(-1)}`;}
|
|
39
|
+
return `${text.slice(0, 4)}***${text.slice(-4)}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
35
42
|
// ── 配置读取 ──────────────────────────────────────────
|
|
36
43
|
|
|
37
44
|
function loadAuthConfig() {
|
|
@@ -90,6 +97,7 @@ function authStatus() {
|
|
|
90
97
|
const userId = cookieData.user_id || cookieData.userId || cookieData.staffId || cookieInfo.userId;
|
|
91
98
|
const baseUrl = resolveBaseUrl(cookieData);
|
|
92
99
|
const authConfig = loadAuthConfig();
|
|
100
|
+
const isEnvAuth = cookieData.auth_source === 'env';
|
|
93
101
|
|
|
94
102
|
if (!csrfToken) {
|
|
95
103
|
warn(t('auth.no_csrf_token'), false);
|
|
@@ -105,12 +113,12 @@ function authStatus() {
|
|
|
105
113
|
chalkSuccess(t('auth.logged_in'), false);
|
|
106
114
|
label('Base URL', baseUrl, { stderr: false });
|
|
107
115
|
if (corpId) {
|
|
108
|
-
label('Corp ID', corpId, { stderr: false });
|
|
116
|
+
label('Corp ID', isEnvAuth ? maskIdentifier(corpId) : corpId, { stderr: false });
|
|
109
117
|
}
|
|
110
118
|
if (userId) {
|
|
111
|
-
label('User ID', userId, { stderr: false });
|
|
119
|
+
label('User ID', isEnvAuth ? maskIdentifier(userId) : userId, { stderr: false });
|
|
112
120
|
}
|
|
113
|
-
label('CSRF', `${csrfToken.slice(0, 16)}…`, { stderr: false });
|
|
121
|
+
label('CSRF', isEnvAuth ? '<redacted>' : `${csrfToken.slice(0, 16)}…`, { stderr: false });
|
|
114
122
|
|
|
115
123
|
// 显示登录信息
|
|
116
124
|
if (authConfig) {
|
package/lib/auth/login.js
CHANGED
|
@@ -27,7 +27,8 @@ const {
|
|
|
27
27
|
loadCookieData,
|
|
28
28
|
resolveBaseUrl,
|
|
29
29
|
detectActiveTool,
|
|
30
|
-
|
|
30
|
+
isEnvAuthMode,
|
|
31
|
+
getLastEnvAuthError,
|
|
31
32
|
} = require('../core/utils');
|
|
32
33
|
const { t } = require('../core/i18n');
|
|
33
34
|
|
|
@@ -48,6 +49,9 @@ function loadConfig() {
|
|
|
48
49
|
// ── Cookie 持久化 ─────────────────────────────────────
|
|
49
50
|
|
|
50
51
|
function saveCookieCache(cookies, baseUrl) {
|
|
52
|
+
if (isEnvAuthMode()) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
51
55
|
const projectRoot = findProjectRoot();
|
|
52
56
|
const cacheDir = path.join(projectRoot, '.cache');
|
|
53
57
|
|
|
@@ -61,6 +65,13 @@ function saveCookieCache(cookies, baseUrl) {
|
|
|
61
65
|
process.stderr.write(` ${c.green}✔${c.reset} Cookie saved to ${c.dim}${cookieFile}${c.reset}\n`);
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
function maskIdentifier(value) {
|
|
69
|
+
const text = String(value || '');
|
|
70
|
+
if (!text) {return null;}
|
|
71
|
+
if (text.length <= 8) {return `${text.slice(0, 2)}***${text.slice(-1)}`;}
|
|
72
|
+
return `${text.slice(0, 4)}***${text.slice(-4)}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
64
75
|
// ── 仅检查登录态 ──────────────────────────────────────
|
|
65
76
|
|
|
66
77
|
/**
|
|
@@ -79,9 +90,12 @@ function checkLoginOnly(options = {}) {
|
|
|
79
90
|
const legacyCookieFile = path.join(projectRoot, '.cache', 'cookies.json');
|
|
80
91
|
const cookieData = loadCookieData(projectRoot);
|
|
81
92
|
const cookies = cookieData && Array.isArray(cookieData.cookies) ? cookieData.cookies : [];
|
|
82
|
-
const
|
|
93
|
+
const envAuthError = getLastEnvAuthError();
|
|
94
|
+
const isEnvAuth = !!(cookieData && cookieData.auth_source === 'env');
|
|
95
|
+
const authMode = isEnvAuth || isEnvAuthMode() ? 'env' : 'default';
|
|
83
96
|
const baseDiagnostics = {
|
|
84
97
|
authMode,
|
|
98
|
+
authSource: authMode === 'env' ? 'env' : 'cache',
|
|
85
99
|
activeTool: activeTool ? activeTool.tool : null,
|
|
86
100
|
isWukong: !!(activeTool && activeTool.tool === 'wukong'),
|
|
87
101
|
projectRoot,
|
|
@@ -106,10 +120,12 @@ function checkLoginOnly(options = {}) {
|
|
|
106
120
|
corp_id_found: false,
|
|
107
121
|
user_id_found: false,
|
|
108
122
|
base_url_found: false,
|
|
109
|
-
failure_reason:
|
|
123
|
+
failure_reason: envAuthError
|
|
124
|
+
? envAuthError.failure_reason
|
|
125
|
+
: (baseDiagnostics.cookieFileFound ? 'cookie_cache_unreadable_or_invalid' : 'cookie_cache_missing'),
|
|
110
126
|
},
|
|
111
|
-
message: authMode === '
|
|
112
|
-
? 'No
|
|
127
|
+
message: authMode === 'env'
|
|
128
|
+
? 'No env Cookie, host page refresh required'
|
|
113
129
|
: 'No local Cookie cache, QR scan login required',
|
|
114
130
|
};
|
|
115
131
|
}
|
|
@@ -119,6 +135,9 @@ function checkLoginOnly(options = {}) {
|
|
|
119
135
|
const corpId = cookieData.corp_id || cookieData.corpId || cookieInfo.corpId;
|
|
120
136
|
const userId = cookieData.user_id || cookieData.userId || cookieData.staffId || cookieInfo.userId;
|
|
121
137
|
const baseUrl = resolveBaseUrl(cookieData);
|
|
138
|
+
const canIncludeSecrets = includeSecrets && !isEnvAuth;
|
|
139
|
+
const outputCorpId = isEnvAuth ? maskIdentifier(corpId) : corpId;
|
|
140
|
+
const outputUserId = isEnvAuth ? maskIdentifier(userId) : userId;
|
|
122
141
|
const diagnostics = {
|
|
123
142
|
...baseDiagnostics,
|
|
124
143
|
cache_readable: true,
|
|
@@ -136,8 +155,8 @@ function checkLoginOnly(options = {}) {
|
|
|
136
155
|
status: 'not_logged_in',
|
|
137
156
|
can_auto_use: false,
|
|
138
157
|
diagnostics,
|
|
139
|
-
message: authMode === '
|
|
140
|
-
? 'No csrf_token in
|
|
158
|
+
message: authMode === 'env'
|
|
159
|
+
? 'No csrf_token in env Cookie, host page refresh required'
|
|
141
160
|
: 'No tianshu_csrf_token in Cookie, re-login required',
|
|
142
161
|
};
|
|
143
162
|
}
|
|
@@ -145,15 +164,15 @@ function checkLoginOnly(options = {}) {
|
|
|
145
164
|
const result = {
|
|
146
165
|
status: 'ok',
|
|
147
166
|
can_auto_use: true,
|
|
148
|
-
csrf_token:
|
|
149
|
-
corp_id:
|
|
150
|
-
user_id:
|
|
167
|
+
csrf_token: canIncludeSecrets ? csrfToken : `${csrfToken.slice(0, 8)}…`,
|
|
168
|
+
corp_id: outputCorpId,
|
|
169
|
+
user_id: outputUserId,
|
|
151
170
|
base_url: baseUrl,
|
|
152
171
|
cookies_count: cookies.length,
|
|
153
172
|
diagnostics,
|
|
154
|
-
message: `✅ Valid login credentials found\n Org: ${
|
|
173
|
+
message: `✅ Valid login credentials found\n Org: ${outputCorpId || ''}\n User: ${outputUserId || ''}\n Domain: ${baseUrl}`,
|
|
155
174
|
};
|
|
156
|
-
if (
|
|
175
|
+
if (canIncludeSecrets) {
|
|
157
176
|
result.cookies = cookies;
|
|
158
177
|
}
|
|
159
178
|
return result;
|
|
@@ -209,8 +228,8 @@ function refreshCsrfFromCache() {
|
|
|
209
228
|
*/
|
|
210
229
|
function ensureLogin(options = {}) {
|
|
211
230
|
const force = !!options.force;
|
|
212
|
-
const
|
|
213
|
-
if (!force ||
|
|
231
|
+
const envAuth = isEnvAuthMode();
|
|
232
|
+
if (!force || envAuth) {
|
|
214
233
|
const cookieData = loadCookieData();
|
|
215
234
|
|
|
216
235
|
if (cookieData && cookieData.cookies) {
|
|
@@ -235,7 +254,7 @@ function ensureLogin(options = {}) {
|
|
|
235
254
|
}
|
|
236
255
|
}
|
|
237
256
|
|
|
238
|
-
if (
|
|
257
|
+
if (envAuth) {
|
|
239
258
|
return null;
|
|
240
259
|
}
|
|
241
260
|
|
package/lib/core/env.js
CHANGED
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
resolveBaseUrl,
|
|
17
17
|
extractInfoFromCookies,
|
|
18
18
|
resolveWukongWorkspaceRoot,
|
|
19
|
+
getLastEnvAuthError,
|
|
19
20
|
} = require('./utils');
|
|
20
21
|
const { t } = require('./i18n');
|
|
21
22
|
|
|
@@ -110,6 +111,7 @@ function detectLoginStatus(projectRoot) {
|
|
|
110
111
|
const cookieDiagnostics = getCookieDiagnostics(projectRoot);
|
|
111
112
|
const cookieData = loadCookieData(projectRoot);
|
|
112
113
|
const cookies = cookieData && Array.isArray(cookieData.cookies) ? cookieData.cookies : [];
|
|
114
|
+
const envAuthError = getLastEnvAuthError();
|
|
113
115
|
|
|
114
116
|
if (!cookieData || !cookieData.cookies) {
|
|
115
117
|
return {
|
|
@@ -128,7 +130,9 @@ function detectLoginStatus(projectRoot) {
|
|
|
128
130
|
corpIdFound: false,
|
|
129
131
|
userIdFound: false,
|
|
130
132
|
baseUrlFound: false,
|
|
131
|
-
failureReason:
|
|
133
|
+
failureReason: envAuthError
|
|
134
|
+
? envAuthError.failure_reason
|
|
135
|
+
: (cookieDiagnostics.cookieFileFound ? 'cookie_cache_unreadable_or_invalid' : 'cookie_cache_missing'),
|
|
132
136
|
},
|
|
133
137
|
};
|
|
134
138
|
}
|
|
@@ -139,6 +143,7 @@ function detectLoginStatus(projectRoot) {
|
|
|
139
143
|
const userId = cookieData.user_id || cookieData.userId || cookieData.staffId || cookieInfo.userId;
|
|
140
144
|
const baseUrl = resolveBaseUrl(cookieData);
|
|
141
145
|
const loggedIn = !!csrfToken;
|
|
146
|
+
const isEnvAuth = cookieData.auth_source === 'env';
|
|
142
147
|
|
|
143
148
|
return {
|
|
144
149
|
loggedIn,
|
|
@@ -148,8 +153,10 @@ function detectLoginStatus(projectRoot) {
|
|
|
148
153
|
userId,
|
|
149
154
|
baseUrl,
|
|
150
155
|
cookiesCount: cookies.length,
|
|
156
|
+
authSource: isEnvAuth ? 'env' : 'cache',
|
|
151
157
|
diagnostics: {
|
|
152
158
|
...cookieDiagnostics,
|
|
159
|
+
authSource: isEnvAuth ? 'env' : 'cache',
|
|
153
160
|
cacheReadable: true,
|
|
154
161
|
cookiesArrayFound: Array.isArray(cookieData.cookies),
|
|
155
162
|
csrfTokenFound: !!csrfToken,
|
|
@@ -166,6 +173,13 @@ function maskSecret(value) {
|
|
|
166
173
|
return `${value.slice(0, 16)}...`;
|
|
167
174
|
}
|
|
168
175
|
|
|
176
|
+
function maskIdentifier(value) {
|
|
177
|
+
const text = String(value || '');
|
|
178
|
+
if (!text) {return null;}
|
|
179
|
+
if (text.length <= 8) {return `${text.slice(0, 2)}***${text.slice(-1)}`;}
|
|
180
|
+
return `${text.slice(0, 4)}***${text.slice(-4)}`;
|
|
181
|
+
}
|
|
182
|
+
|
|
169
183
|
/**
|
|
170
184
|
* 构建适合 AI agent 读取的环境快照。
|
|
171
185
|
*/
|
|
@@ -198,9 +212,10 @@ function buildEnvironmentSnapshot() {
|
|
|
198
212
|
loggedIn: loginStatus.loggedIn,
|
|
199
213
|
canAutoUse: loginStatus.canAutoUse,
|
|
200
214
|
baseUrl: loginStatus.baseUrl,
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
215
|
+
authSource: loginStatus.authSource || null,
|
|
216
|
+
corpId: loginStatus.authSource === 'env' ? maskIdentifier(loginStatus.corpId) : loginStatus.corpId,
|
|
217
|
+
userId: loginStatus.authSource === 'env' ? maskIdentifier(loginStatus.userId) : loginStatus.userId,
|
|
218
|
+
csrfToken: loginStatus.authSource === 'env' ? null : maskSecret(loginStatus.csrfToken),
|
|
204
219
|
cookiesCount: loginStatus.cookiesCount,
|
|
205
220
|
diagnostics: loginStatus.diagnostics,
|
|
206
221
|
},
|
package/lib/core/utils.js
CHANGED
|
@@ -264,6 +264,43 @@ function isInjectedAuthMode(env = process.env) {
|
|
|
264
264
|
return ['1', 'true', 'yes', 'on'].includes(authEnabled);
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
+
function hasEnvCookieAuth(env = process.env) {
|
|
268
|
+
return !!String(env.OPENYIDA_COOKIE_B64 || '').trim();
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function isEnvAuthMode(env = process.env) {
|
|
272
|
+
return isInjectedAuthMode(env) || hasEnvCookieAuth(env);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
let lastEnvAuthError = null;
|
|
276
|
+
|
|
277
|
+
function getLastEnvAuthError() {
|
|
278
|
+
return lastEnvAuthError;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function setLastEnvAuthError(code, failureReason, message) {
|
|
282
|
+
lastEnvAuthError = {
|
|
283
|
+
code,
|
|
284
|
+
failure_reason: failureReason,
|
|
285
|
+
message,
|
|
286
|
+
authMode: 'env',
|
|
287
|
+
};
|
|
288
|
+
return lastEnvAuthError;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function normalizeEnvBaseUrl(baseUrl, fallbackBaseUrl) {
|
|
292
|
+
const raw = String(baseUrl || fallbackBaseUrl || 'https://www.aliwork.com').trim();
|
|
293
|
+
try {
|
|
294
|
+
const parsed = new URL(raw);
|
|
295
|
+
if (!['http:', 'https:'].includes(parsed.protocol)) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
return raw.replace(/\/+$/, '');
|
|
299
|
+
} catch {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
267
304
|
/**
|
|
268
305
|
* 查找项目根目录(project 工作区)。
|
|
269
306
|
*
|
|
@@ -354,6 +391,123 @@ function extractInfoFromCookies(cookies) {
|
|
|
354
391
|
return { csrfToken, corpId, userId };
|
|
355
392
|
}
|
|
356
393
|
|
|
394
|
+
function parseCookieHeader(rawCookieHeader, options = {}) {
|
|
395
|
+
const raw = String(rawCookieHeader || '').trim();
|
|
396
|
+
if (!raw) {
|
|
397
|
+
return [];
|
|
398
|
+
}
|
|
399
|
+
let domain = '';
|
|
400
|
+
if (options.baseUrl) {
|
|
401
|
+
try {
|
|
402
|
+
domain = new URL(options.baseUrl).hostname;
|
|
403
|
+
} catch {
|
|
404
|
+
domain = '';
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return raw
|
|
408
|
+
.split(';')
|
|
409
|
+
.map((part) => {
|
|
410
|
+
const trimmed = part.trim();
|
|
411
|
+
const equalsIndex = trimmed.indexOf('=');
|
|
412
|
+
if (equalsIndex <= 0) {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
const name = trimmed.slice(0, equalsIndex).trim();
|
|
416
|
+
const value = trimmed.slice(equalsIndex + 1).trim();
|
|
417
|
+
if (!name) {
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
const cookie = { name, value };
|
|
421
|
+
if (domain) {
|
|
422
|
+
cookie.domain = domain;
|
|
423
|
+
}
|
|
424
|
+
return cookie;
|
|
425
|
+
})
|
|
426
|
+
.filter(Boolean);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function decodeCookieHeaderFromBase64(encodedCookie) {
|
|
430
|
+
const normalized = String(encodedCookie || '').trim().replace(/\s+/g, '');
|
|
431
|
+
if (!normalized) {
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) {
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
try {
|
|
438
|
+
const decoded = Buffer.from(normalized, 'base64').toString('utf8').trim();
|
|
439
|
+
return decoded && decoded.includes('=') ? decoded : null;
|
|
440
|
+
} catch {
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function loadEnvCookieData(defaultBaseUrl, env = process.env) {
|
|
446
|
+
lastEnvAuthError = null;
|
|
447
|
+
const encodedCookie = String(env.OPENYIDA_COOKIE_B64 || '').trim();
|
|
448
|
+
const envAuthEnabled = isInjectedAuthMode(env);
|
|
449
|
+
if (!encodedCookie) {
|
|
450
|
+
if (envAuthEnabled) {
|
|
451
|
+
setLastEnvAuthError(
|
|
452
|
+
'not_logged_in',
|
|
453
|
+
'env_cookie_missing',
|
|
454
|
+
'OPENYIDA_COOKIE_B64 is required when YIDA_AUTH_ENABLED=true'
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const baseUrl = normalizeEnvBaseUrl(env.OPENYIDA_BASE_URL, defaultBaseUrl);
|
|
461
|
+
if (!baseUrl) {
|
|
462
|
+
setLastEnvAuthError(
|
|
463
|
+
'not_logged_in',
|
|
464
|
+
'base_url_invalid',
|
|
465
|
+
'OPENYIDA_BASE_URL is invalid'
|
|
466
|
+
);
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const rawCookieHeader = decodeCookieHeaderFromBase64(encodedCookie);
|
|
471
|
+
if (!rawCookieHeader) {
|
|
472
|
+
setLastEnvAuthError(
|
|
473
|
+
'not_logged_in',
|
|
474
|
+
'env_cookie_decode_failed',
|
|
475
|
+
'OPENYIDA_COOKIE_B64 is not a valid base64 encoded Cookie header'
|
|
476
|
+
);
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const cookies = parseCookieHeader(rawCookieHeader, { baseUrl });
|
|
481
|
+
if (cookies.length === 0) {
|
|
482
|
+
setLastEnvAuthError(
|
|
483
|
+
'not_logged_in',
|
|
484
|
+
'env_cookie_parse_failed',
|
|
485
|
+
'OPENYIDA_COOKIE_B64 decoded to an empty or invalid Cookie header'
|
|
486
|
+
);
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const { csrfToken, corpId, userId } = extractInfoFromCookies(cookies);
|
|
491
|
+
if (!csrfToken) {
|
|
492
|
+
setLastEnvAuthError(
|
|
493
|
+
'csrf_missing',
|
|
494
|
+
'csrf_token_missing',
|
|
495
|
+
'Env Cookie header does not contain tianshu_csrf_token'
|
|
496
|
+
);
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return {
|
|
501
|
+
cookies,
|
|
502
|
+
csrf_token: csrfToken,
|
|
503
|
+
corp_id: corpId,
|
|
504
|
+
user_id: userId,
|
|
505
|
+
base_url: baseUrl,
|
|
506
|
+
auth_source: 'env',
|
|
507
|
+
auth_mode: 'env',
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
|
|
357
511
|
// ── 登录态缓存读取 ────────────────────────────────────
|
|
358
512
|
|
|
359
513
|
/**
|
|
@@ -368,6 +522,14 @@ function loadCookieData(projectRoot, defaultBaseUrl) {
|
|
|
368
522
|
const root = projectRoot || findProjectRoot();
|
|
369
523
|
const fallbackBaseUrl = defaultBaseUrl || 'https://www.aliwork.com';
|
|
370
524
|
|
|
525
|
+
const envCookieData = loadEnvCookieData(fallbackBaseUrl);
|
|
526
|
+
if (envCookieData) {
|
|
527
|
+
return envCookieData;
|
|
528
|
+
}
|
|
529
|
+
if (lastEnvAuthError && isEnvAuthMode()) {
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
|
|
371
533
|
// 尝试迁移旧版 cookies.json(仅在首次使用多环境功能时执行一次)
|
|
372
534
|
const { migrateOldCookieFile, getCookieFilePath } = require('./env-manager');
|
|
373
535
|
migrateOldCookieFile(root);
|
|
@@ -428,21 +590,22 @@ function loadCookieData(projectRoot, defaultBaseUrl) {
|
|
|
428
590
|
* @returns {object} loginResult
|
|
429
591
|
*/
|
|
430
592
|
function triggerLogin(options = {}) {
|
|
431
|
-
if (
|
|
593
|
+
if (isEnvAuthMode()) {
|
|
432
594
|
const cookieData = loadCookieData();
|
|
433
595
|
if (cookieData && cookieData.cookies && cookieData.cookies.length > 0 && cookieData.csrf_token) {
|
|
434
596
|
return cookieData;
|
|
435
597
|
}
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
598
|
+
const envAuthError = getLastEnvAuthError();
|
|
599
|
+
const reason = envAuthError
|
|
600
|
+
? envAuthError.failure_reason
|
|
601
|
+
: (cookieData && cookieData.cookies ? 'csrf_token_missing' : 'env_cookie_missing');
|
|
439
602
|
const { CliError } = require('./cli-error');
|
|
440
603
|
throw new CliError(
|
|
441
|
-
`not_logged_in:
|
|
604
|
+
`not_logged_in: env cookie is unavailable (${reason}). Refresh the host page so it can inject a fresh Yida cookie.`,
|
|
442
605
|
{
|
|
443
606
|
code: 'INJECTED_AUTH_REQUIRED',
|
|
444
607
|
details: {
|
|
445
|
-
authMode: '
|
|
608
|
+
authMode: 'env',
|
|
446
609
|
failure_reason: reason,
|
|
447
610
|
},
|
|
448
611
|
}
|
|
@@ -499,10 +662,16 @@ function refreshCsrfToken() {
|
|
|
499
662
|
* @returns {boolean}
|
|
500
663
|
*/
|
|
501
664
|
function isLoginExpired(responseJson) {
|
|
665
|
+
if (!responseJson) {return false;}
|
|
666
|
+
const status = String(responseJson.status || '').toLowerCase();
|
|
667
|
+
const errorCode = String(responseJson.errorCode || responseJson.code || '').toLowerCase();
|
|
668
|
+
const errorMsg = String(responseJson.errorMsg || responseJson.message || '').toLowerCase();
|
|
669
|
+
if (status === 'not_logged_in' || errorCode === 'not_logged_in' || errorMsg.includes('not_logged_in')) {
|
|
670
|
+
return true;
|
|
671
|
+
}
|
|
502
672
|
return (
|
|
503
|
-
responseJson &&
|
|
504
673
|
responseJson.success === false &&
|
|
505
|
-
|
|
674
|
+
['307', '302', '401', '403'].includes(errorCode)
|
|
506
675
|
);
|
|
507
676
|
}
|
|
508
677
|
|
|
@@ -523,6 +692,10 @@ function isHttpRedirectStatus(statusCode) {
|
|
|
523
692
|
return [301, 302, 303, 307, 308].includes(Number(statusCode));
|
|
524
693
|
}
|
|
525
694
|
|
|
695
|
+
function isHttpAuthStatus(statusCode) {
|
|
696
|
+
return [401, 403].includes(Number(statusCode));
|
|
697
|
+
}
|
|
698
|
+
|
|
526
699
|
// ── base_url 解析 ─────────────────────────────────────
|
|
527
700
|
|
|
528
701
|
/**
|
|
@@ -612,7 +785,7 @@ function httpPost(baseUrl, requestPath, postData, cookies, optionsOverride = {})
|
|
|
612
785
|
if (!optionsOverride.silentStatus) {
|
|
613
786
|
warn(t('common.http_status', res.statusCode));
|
|
614
787
|
}
|
|
615
|
-
if (isHttpRedirectStatus(res.statusCode)) {
|
|
788
|
+
if (isHttpRedirectStatus(res.statusCode) || isHttpAuthStatus(res.statusCode)) {
|
|
616
789
|
resolve({
|
|
617
790
|
__needLogin: true,
|
|
618
791
|
__httpStatus: res.statusCode,
|
|
@@ -694,7 +867,7 @@ function httpPostJson(baseUrl, requestPath, payload, cookies, optionsOverride =
|
|
|
694
867
|
if (!optionsOverride.silentStatus) {
|
|
695
868
|
warn(t('common.http_status', res.statusCode));
|
|
696
869
|
}
|
|
697
|
-
if (isHttpRedirectStatus(res.statusCode)) {
|
|
870
|
+
if (isHttpRedirectStatus(res.statusCode) || isHttpAuthStatus(res.statusCode)) {
|
|
698
871
|
resolve({
|
|
699
872
|
__needLogin: true,
|
|
700
873
|
__httpStatus: res.statusCode,
|
|
@@ -784,7 +957,7 @@ function httpGet(baseUrl, requestPath, queryParams, cookies, optionsOverride = {
|
|
|
784
957
|
if (!optionsOverride.silentStatus) {
|
|
785
958
|
warn(t('common.http_status', res.statusCode));
|
|
786
959
|
}
|
|
787
|
-
if (isHttpRedirectStatus(res.statusCode)) {
|
|
960
|
+
if (isHttpRedirectStatus(res.statusCode) || isHttpAuthStatus(res.statusCode)) {
|
|
788
961
|
resolve({
|
|
789
962
|
__needLogin: true,
|
|
790
963
|
__httpStatus: res.statusCode,
|
|
@@ -830,14 +1003,16 @@ function httpGet(baseUrl, requestPath, queryParams, cookies, optionsOverride = {
|
|
|
830
1003
|
*/
|
|
831
1004
|
async function requestWithAutoLogin(requestFn, authRef) {
|
|
832
1005
|
let result = await requestFn(authRef);
|
|
1006
|
+
const usingEnvAuth = isEnvAuthMode()
|
|
1007
|
+
|| !!(authRef && authRef.cookieData && authRef.cookieData.auth_source === 'env');
|
|
833
1008
|
|
|
834
1009
|
if (result && result.__csrfExpired) {
|
|
835
|
-
if (
|
|
1010
|
+
if (usingEnvAuth) {
|
|
836
1011
|
return {
|
|
837
1012
|
success: false,
|
|
838
1013
|
__needLogin: true,
|
|
839
1014
|
errorCode: 'INJECTED_AUTH_REQUIRED',
|
|
840
|
-
errorMsg: 'not_logged_in:
|
|
1015
|
+
errorMsg: 'not_logged_in: env cookie csrf_token expired. Refresh the host page so it can inject a fresh Yida cookie.',
|
|
841
1016
|
};
|
|
842
1017
|
}
|
|
843
1018
|
const refreshedData = refreshCsrfToken();
|
|
@@ -854,12 +1029,12 @@ async function requestWithAutoLogin(requestFn, authRef) {
|
|
|
854
1029
|
}
|
|
855
1030
|
|
|
856
1031
|
if (result && result.__needLogin) {
|
|
857
|
-
if (
|
|
1032
|
+
if (usingEnvAuth) {
|
|
858
1033
|
return {
|
|
859
1034
|
success: false,
|
|
860
1035
|
__needLogin: true,
|
|
861
1036
|
errorCode: 'INJECTED_AUTH_REQUIRED',
|
|
862
|
-
errorMsg: 'not_logged_in:
|
|
1037
|
+
errorMsg: 'not_logged_in: env cookie missing or expired. Refresh the host page so it can inject a fresh Yida cookie.',
|
|
863
1038
|
};
|
|
864
1039
|
}
|
|
865
1040
|
const newCookieData = triggerLogin({ force: true });
|
|
@@ -886,6 +1061,9 @@ module.exports = {
|
|
|
886
1061
|
hasDesktopEnvironment,
|
|
887
1062
|
findProjectRoot,
|
|
888
1063
|
extractInfoFromCookies,
|
|
1064
|
+
parseCookieHeader,
|
|
1065
|
+
loadEnvCookieData,
|
|
1066
|
+
getLastEnvAuthError,
|
|
889
1067
|
loadCookieData,
|
|
890
1068
|
triggerLogin,
|
|
891
1069
|
refreshCsrfToken,
|
|
@@ -901,4 +1079,6 @@ module.exports = {
|
|
|
901
1079
|
getNodeExecutable,
|
|
902
1080
|
resolveWukongWorkspaceRoot,
|
|
903
1081
|
isInjectedAuthMode,
|
|
1082
|
+
hasEnvCookieAuth,
|
|
1083
|
+
isEnvAuthMode,
|
|
904
1084
|
};
|
package/package.json
CHANGED
package/scripts/eval/score.js
CHANGED
|
@@ -108,6 +108,18 @@ function buildHumanScores(screenshots = []) {
|
|
|
108
108
|
}));
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
function toMarkdownPath(abs, workDir) {
|
|
112
|
+
if (!abs) {return null;}
|
|
113
|
+
if (!workDir) {return abs.replace(/\\/g, '/');}
|
|
114
|
+
|
|
115
|
+
const isWindowsPath = /^[a-zA-Z]:[\\/]/.test(abs) || /^[a-zA-Z]:[\\/]/.test(workDir);
|
|
116
|
+
const relPath = isWindowsPath
|
|
117
|
+
? path.win32.relative(workDir, abs)
|
|
118
|
+
: path.relative(workDir, abs);
|
|
119
|
+
|
|
120
|
+
return (relPath || abs).replace(/\\/g, '/');
|
|
121
|
+
}
|
|
122
|
+
|
|
111
123
|
/**
|
|
112
124
|
* 生成人工打分文档(Markdown),内嵌截图与链接。
|
|
113
125
|
* @param {object} options
|
|
@@ -118,11 +130,6 @@ function buildHumanScores(screenshots = []) {
|
|
|
118
130
|
*/
|
|
119
131
|
function renderScoringMarkdown(options = {}) {
|
|
120
132
|
const { config = {}, scores = [], workDir, rubric = DEFAULT_RUBRIC } = options;
|
|
121
|
-
const rel = (abs) => {
|
|
122
|
-
if (!abs) {return null;}
|
|
123
|
-
if (!workDir) {return abs;}
|
|
124
|
-
return path.relative(workDir, abs) || abs;
|
|
125
|
-
};
|
|
126
133
|
|
|
127
134
|
const lines = [];
|
|
128
135
|
lines.push('# 宜搭应用效果 · 人工打分表');
|
|
@@ -150,7 +157,7 @@ function renderScoringMarkdown(options = {}) {
|
|
|
150
157
|
lines.push('');
|
|
151
158
|
if (s.url) {lines.push(`- 链接:${s.url}`);}
|
|
152
159
|
if (s.screenshot) {
|
|
153
|
-
const relPath =
|
|
160
|
+
const relPath = toMarkdownPath(s.screenshot, workDir);
|
|
154
161
|
lines.push(`- 截图:\`${relPath}\``);
|
|
155
162
|
lines.push('');
|
|
156
163
|
lines.push(``);
|
|
@@ -193,5 +200,6 @@ module.exports = {
|
|
|
193
200
|
autoScoreScreenshots,
|
|
194
201
|
buildHumanScores,
|
|
195
202
|
renderScoringMarkdown,
|
|
203
|
+
toMarkdownPath,
|
|
196
204
|
writeScoringDoc,
|
|
197
205
|
};
|