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 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 { isInjectedAuthMode } = require('../lib/core/utils');
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 (isInjectedAuthMode()) {
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
- isInjectedAuthMode,
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 authMode = isInjectedAuthMode() ? 'injected' : 'default';
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: baseDiagnostics.cookieFileFound ? 'cookie_cache_unreadable_or_invalid' : 'cookie_cache_missing',
123
+ failure_reason: envAuthError
124
+ ? envAuthError.failure_reason
125
+ : (baseDiagnostics.cookieFileFound ? 'cookie_cache_unreadable_or_invalid' : 'cookie_cache_missing'),
110
126
  },
111
- message: authMode === 'injected'
112
- ? 'No injected Cookie cache, host page refresh required'
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 === 'injected'
140
- ? 'No csrf_token in injected Cookie cache, host page refresh required'
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: includeSecrets ? csrfToken : `${csrfToken.slice(0, 8)}…`,
149
- corp_id: corpId,
150
- user_id: userId,
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: ${corpId}\n User: ${userId}\n Domain: ${baseUrl}`,
173
+ message: `✅ Valid login credentials found\n Org: ${outputCorpId || ''}\n User: ${outputUserId || ''}\n Domain: ${baseUrl}`,
155
174
  };
156
- if (includeSecrets) {
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 injectedAuth = isInjectedAuthMode();
213
- if (!force || injectedAuth) {
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 (injectedAuth) {
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: cookieDiagnostics.cookieFileFound ? 'cookie_cache_unreadable_or_invalid' : 'cookie_cache_missing',
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
- corpId: loginStatus.corpId,
202
- userId: loginStatus.userId,
203
- csrfToken: maskSecret(loginStatus.csrfToken),
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 (isInjectedAuthMode()) {
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 reason = cookieData && cookieData.cookies
437
- ? 'csrf_token_missing'
438
- : 'cookie_cache_missing';
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: injected cookie is unavailable (${reason}). Refresh the host page so it can inject a fresh Yida cookie cache.`,
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: 'injected',
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
- (responseJson.errorCode === '307' || responseJson.errorCode === '302')
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 (isInjectedAuthMode()) {
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: injected cookie csrf_token expired. Refresh the host page so it can inject a fresh Yida cookie cache.',
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 (isInjectedAuthMode()) {
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: injected cookie missing or expired. Refresh the host page so it can inject a fresh Yida cookie cache.',
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openyida",
3
- "version": "2026.7.6",
3
+ "version": "2026.7.7-1",
4
4
  "description": "OpenYida CLI - 宜搭低代码 AI 开发工具(安装即用,零配置)",
5
5
  "bin": {
6
6
  "openyida": "bin/yida.js",
@@ -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 = rel(s.screenshot);
160
+ const relPath = toMarkdownPath(s.screenshot, workDir);
154
161
  lines.push(`- 截图:\`${relPath}\``);
155
162
  lines.push('');
156
163
  lines.push(`![${s.stage || 'screenshot'}](${relPath})`);
@@ -193,5 +200,6 @@ module.exports = {
193
200
  autoScoreScreenshots,
194
201
  buildHumanScores,
195
202
  renderScoringMarkdown,
203
+ toMarkdownPath,
196
204
  writeScoringDoc,
197
205
  };