openyida 2026.5.26 → 2026.5.27-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/yida.js CHANGED
@@ -27,6 +27,7 @@ function isAgentEnvironment(env) {
27
27
  env.CLAUDE_CODE ||
28
28
  env.CLAUDE_CODE_ENTRYPOINT ||
29
29
  env.OPENCODE ||
30
+ env.OPENCODE_CLIENT ||
30
31
  env.QODER_IDE ||
31
32
  env.QODER_AGENT ||
32
33
  env.QODERCLI_INTEGRATION_MODE ||
@@ -287,7 +288,7 @@ function noteLoginCommandResult(result) {
287
288
 
288
289
  function isAgentConversationEnvironment() {
289
290
  const { detectActiveTool } = require('../lib/core/utils');
290
- return !!detectActiveTool();
291
+ return !!detectActiveTool() || process.env.OPENYIDA_AGENT_MODE === '1';
291
292
  }
292
293
 
293
294
  function shouldUseBrowserHandoffLogin(cliArgs) {
@@ -303,12 +304,13 @@ function shouldUseAgentLogin(cliArgs) {
303
304
  }
304
305
 
305
306
  function shouldUsePlaywrightFallbackInAgentLogin() {
306
- const { detectActiveTool } = require('../lib/core/utils');
307
- const activeTool = detectActiveTool();
308
- if (activeTool && activeTool.tool === 'wukong') {
309
- return false;
310
- }
311
- return process.env.OPENYIDA_AGENT_PLAYWRIGHT_FALLBACK === '1';
307
+ const { hasDesktopEnvironment } = require('../lib/core/utils');
308
+ return hasDesktopEnvironment() || process.env.OPENYIDA_AGENT_PLAYWRIGHT_FALLBACK === '1';
309
+ }
310
+
311
+ function shouldUseDesktopBrowserLogin() {
312
+ const { hasDesktopEnvironment } = require('../lib/core/utils');
313
+ return hasDesktopEnvironment();
312
314
  }
313
315
 
314
316
  function shouldUseCodexQrLogin(cliArgs) {
@@ -479,12 +481,6 @@ async function main() {
479
481
  } else {
480
482
  const { detectActiveTool } = require('../lib/core/utils');
481
483
  const activeTool = detectActiveTool();
482
- if (activeTool && activeTool.tool === 'wukong') {
483
- const { codexLogin } = require('../lib/auth/codex-login');
484
- const result = await codexLogin({ tool: 'wukong' });
485
- printLoginResult(result);
486
- break;
487
- }
488
484
  const { interactiveLogin } = require('../lib/auth/login');
489
485
  const browserResult = interactiveLogin({
490
486
  playwrightFallback: shouldUsePlaywrightFallbackInAgentLogin(),
@@ -493,10 +489,10 @@ async function main() {
493
489
  printLoginResult(browserResult);
494
490
  } else {
495
491
  // CDP/Playwright 失败后的兜底策略:
496
- // QoderWork 有 in-app browser,优先使用 browser handoff;其余走终端二维码
497
- if (activeTool && activeTool.tool === 'qoderwork') {
492
+ // Wukong/QoderWork 有 in-app browser,优先使用 browser handoff;其余走 AI 对话框 QR handoff。
493
+ if (activeTool && (activeTool.tool === 'wukong' || activeTool.tool === 'qoderwork')) {
498
494
  const { codexLogin } = require('../lib/auth/codex-login');
499
- const result = await codexLogin({ tool: 'qoderwork' });
495
+ const result = await codexLogin({ tool: activeTool.tool });
500
496
  printLoginResult(result);
501
497
  } else {
502
498
  const { startCodexQrLogin } = require('../lib/auth/qr-login');
@@ -520,6 +516,14 @@ async function main() {
520
516
  printLoginResult(cachedResult);
521
517
  break;
522
518
  }
519
+ if (shouldUseDesktopBrowserLogin()) {
520
+ const { interactiveLogin } = require('../lib/auth/login');
521
+ const browserResult = interactiveLogin({ playwrightFallback: true });
522
+ if (browserResult) {
523
+ printLoginResult(browserResult);
524
+ break;
525
+ }
526
+ }
523
527
  const { qrLogin } = require('../lib/auth/qr-login');
524
528
  const result = await qrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
525
529
  printLoginResult(result);
@@ -540,9 +544,25 @@ async function main() {
540
544
  if (subCommand === 'status') {
541
545
  authStatus();
542
546
  } else if (subCommand === 'login') {
543
- const authArgs = [subCommand, ...applyLoginEnvironmentFlags(args.slice(1))];
544
- const loginType = shouldUseBrowserHandoffLogin(authArgs) ? 'browser' : 'qrcode';
545
- await authLogin({ type: loginType, corpId: getArgValue(authArgs, '--corp-id') });
547
+ const authArgs = applyLoginEnvironmentFlags(args.slice(1));
548
+ let loginType = 'qrcode';
549
+ if (authArgs.includes('--codex')) {
550
+ loginType = 'codex';
551
+ } else if (authArgs.includes('--qoder')) {
552
+ loginType = 'qoder';
553
+ } else if (authArgs.includes('--wukong')) {
554
+ loginType = 'wukong';
555
+ } else if (authArgs.includes('--browser')) {
556
+ loginType = 'browser';
557
+ }
558
+ const result = await authLogin({
559
+ type: loginType,
560
+ corpId: getArgValue(authArgs, '--corp-id'),
561
+ forceTerminalQr: authArgs.includes('--qr'),
562
+ });
563
+ if (result) {
564
+ printLoginResult(result);
565
+ }
546
566
  } else if (subCommand === 'refresh') {
547
567
  authRefresh();
548
568
  } else if (subCommand === 'logout') {
package/lib/auth/auth.js CHANGED
@@ -18,8 +18,8 @@
18
18
 
19
19
  const fs = require('fs');
20
20
  const path = require('path');
21
- const { findProjectRoot, loadCookieData, extractInfoFromCookies, resolveBaseUrl } = require('../core/utils');
22
- const { logout, checkLoginOnly } = require('./login');
21
+ const { findProjectRoot, loadCookieData, extractInfoFromCookies, resolveBaseUrl, detectActiveTool, hasDesktopEnvironment } = require('../core/utils');
22
+ const { logout, checkLoginOnly, interactiveLogin } = require('./login');
23
23
  const { t } = require('../core/i18n');
24
24
 
25
25
  const AUTH_CACHE_FILE = '.cache/auth.json';
@@ -135,7 +135,7 @@ function authStatus() {
135
135
  * @returns {Promise<object>|object} 登录结果
136
136
  */
137
137
  async function authLogin(options = {}) {
138
- const { type = 'qrcode', corpId } = options;
138
+ const { type = 'qrcode', corpId, forceTerminalQr = false } = options;
139
139
 
140
140
  const { c, info, success: chalkSuccess, label } = require('../core/chalk');
141
141
  info(t('auth.login_start', type));
@@ -143,14 +143,21 @@ async function authLogin(options = {}) {
143
143
  // 调用现有的登录逻辑
144
144
  let result;
145
145
  const cachedResult = checkLoginOnly({ includeSecrets: true });
146
- if (type === 'browser' || type === 'codex' || type === 'qoder' || type === 'wukong') {
147
- result = cachedResult.status === 'ok'
148
- ? cachedResult
149
- : await require('./codex-login').codexLogin();
146
+ if (cachedResult.status === 'ok') {
147
+ result = cachedResult;
148
+ } else if (type === 'browser') {
149
+ result = interactiveLogin({ playwrightFallback: true });
150
+ } else if (type === 'codex' || type === 'qoder' || type === 'wukong') {
151
+ result = await require('./codex-login').codexLogin({
152
+ tool: type,
153
+ });
154
+ } else if (type === 'qrcode' && !forceTerminalQr && isAgentConversationEnvironment()) {
155
+ result = await loginInAgentConversation({ corpId });
156
+ } else if (type === 'qrcode' && !forceTerminalQr && hasDesktopEnvironment()) {
157
+ result = interactiveLogin({ playwrightFallback: true }) ||
158
+ await require('./qr-login').qrLogin({ corpId });
150
159
  } else {
151
- result = cachedResult.status === 'ok'
152
- ? cachedResult
153
- : await require('./qr-login').qrLogin({ corpId });
160
+ result = await require('./qr-login').qrLogin({ corpId });
154
161
  }
155
162
 
156
163
  if (!result) {
@@ -178,6 +185,31 @@ async function authLogin(options = {}) {
178
185
  return result;
179
186
  }
180
187
 
188
+ function isAgentConversationEnvironment() {
189
+ return !!detectActiveTool() || process.env.OPENYIDA_AGENT_MODE === '1';
190
+ }
191
+
192
+ function shouldUsePlaywrightFallbackInAgentLogin() {
193
+ return hasDesktopEnvironment() || process.env.OPENYIDA_AGENT_PLAYWRIGHT_FALLBACK === '1';
194
+ }
195
+
196
+ async function loginInAgentConversation(options = {}) {
197
+ const activeTool = detectActiveTool();
198
+
199
+ const browserResult = interactiveLogin({
200
+ playwrightFallback: shouldUsePlaywrightFallbackInAgentLogin(),
201
+ });
202
+ if (browserResult) {
203
+ return browserResult;
204
+ }
205
+
206
+ if (activeTool && (activeTool.tool === 'wukong' || activeTool.tool === 'qoderwork')) {
207
+ return require('./codex-login').codexLogin({ tool: activeTool.tool });
208
+ }
209
+
210
+ return require('./qr-login').startCodexQrLogin({ corpId: options.corpId });
211
+ }
212
+
181
213
  // ── 刷新登录态 ────────────────────────────────────────
182
214
 
183
215
  /**
package/lib/core/utils.js CHANGED
@@ -101,8 +101,9 @@ function detectActiveTool() {
101
101
  }
102
102
 
103
103
  // OpenCode
104
- // Windows 上配置目录为 ~/.config/opencode,macOS/Linux 为 ~/.opencode
105
- if (env.OPENCODE) {
104
+ // Windows 上配置目录为 ~/.config/opencode,macOS/Linux 为 ~/.opencode
105
+ // OpenCode 当前运行时会暴露 OPENCODE_CLIENT;保留 OPENCODE 兼容旧检测。
106
+ if (env.OPENCODE || env.OPENCODE_CLIENT) {
106
107
  const opencodeDirName = process.platform === 'win32'
107
108
  ? path.join('.config', 'opencode')
108
109
  : '.opencode';
@@ -141,6 +142,30 @@ function detectActiveTool() {
141
142
  return null;
142
143
  }
143
144
 
145
+ function hasDesktopEnvironment(env = process.env, platform = process.platform) {
146
+ if (env.OPENYIDA_FORCE_TERMINAL_QR === '1') {
147
+ return false;
148
+ }
149
+ if (env.OPENYIDA_ASSUME_DESKTOP === '1') {
150
+ return true;
151
+ }
152
+ if (env.CI || env.CODEX_CI) {
153
+ return false;
154
+ }
155
+ if (platform === 'darwin' || platform === 'win32') {
156
+ return true;
157
+ }
158
+ if (platform === 'linux') {
159
+ return !!(
160
+ env.DISPLAY ||
161
+ env.WAYLAND_DISPLAY ||
162
+ env.MIR_SOCKET ||
163
+ ['x11', 'wayland'].includes(String(env.XDG_SESSION_TYPE || '').toLowerCase())
164
+ );
165
+ }
166
+ return false;
167
+ }
168
+
144
169
  /**
145
170
  * 解析悟空工作区根目录。
146
171
  *
@@ -700,6 +725,7 @@ async function requestWithAutoLogin(requestFn, authRef) {
700
725
 
701
726
  module.exports = {
702
727
  detectActiveTool,
728
+ hasDesktopEnvironment,
703
729
  findProjectRoot,
704
730
  extractInfoFromCookies,
705
731
  loadCookieData,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openyida",
3
- "version": "2026.5.26",
3
+ "version": "2026.5.27-beta.0",
4
4
  "description": "OpenYida CLI - 宜搭低代码 AI 开发工具(安装即用,零配置)",
5
5
  "bin": {
6
6
  "openyida": "bin/yida.js",