openyida 2026.7.14 → 2026.7.17-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +15 -22
  2. package/bin/yida.js +66 -226
  3. package/lib/agent-center/api.js +4 -5
  4. package/lib/aggregate-table/aggregate-table.js +8 -10
  5. package/lib/ai/ai.js +17 -27
  6. package/lib/app/app-list.js +4 -6
  7. package/lib/app/canvas-compile.js +2 -2
  8. package/lib/app/create-app.js +6 -21
  9. package/lib/app/create-form.js +54 -80
  10. package/lib/app/create-page.js +5 -22
  11. package/lib/app/er.js +10 -8
  12. package/lib/app/export-app.js +2 -2
  13. package/lib/app/externalize-form.js +12 -11
  14. package/lib/app/get-schema.js +12 -11
  15. package/lib/app/import-app.js +8 -28
  16. package/lib/app/list-forms.js +3 -19
  17. package/lib/app/nav-group.js +7 -21
  18. package/lib/app/publish.js +55 -203
  19. package/lib/app/update-app.js +4 -19
  20. package/lib/app/update-form-config.js +21 -116
  21. package/lib/app-permission/app-permission.js +3 -4
  22. package/lib/auth/oauth-loopback.js +156 -0
  23. package/lib/auth/org.js +169 -322
  24. package/lib/auth/token-auth.js +460 -0
  25. package/lib/auth/token-store.js +216 -0
  26. package/lib/basic-info/basic-info.js +11 -19
  27. package/lib/bridge/bridge.js +30 -28
  28. package/lib/connector/api.js +4 -7
  29. package/lib/core/agent-capabilities.js +92 -8
  30. package/lib/core/batch.js +8 -8
  31. package/lib/core/check-data.js +3 -4
  32. package/lib/core/command-manifest.js +3 -3
  33. package/lib/core/doctor.js +19 -22
  34. package/lib/core/env-cmd.js +1 -3
  35. package/lib/core/env-manager.js +8 -121
  36. package/lib/core/env.js +29 -73
  37. package/lib/core/locales/ar.js +5 -5
  38. package/lib/core/locales/de.js +5 -5
  39. package/lib/core/locales/en.js +26 -26
  40. package/lib/core/locales/es.js +5 -5
  41. package/lib/core/locales/fr.js +5 -5
  42. package/lib/core/locales/hi.js +5 -5
  43. package/lib/core/locales/ja.js +14 -14
  44. package/lib/core/locales/ko.js +5 -5
  45. package/lib/core/locales/pt.js +5 -5
  46. package/lib/core/locales/vi.js +5 -5
  47. package/lib/core/locales/zh-HK.js +15 -15
  48. package/lib/core/locales/zh.js +26 -26
  49. package/lib/core/query-data.js +4 -5
  50. package/lib/core/task-center.js +6 -7
  51. package/lib/core/utils.js +160 -445
  52. package/lib/core/yida-client.js +57 -24
  53. package/lib/corp-efficiency/corp-efficiency.js +5 -6
  54. package/lib/corp-manager/api.js +3 -4
  55. package/lib/db/db-seq-fix.js +20 -32
  56. package/lib/flash-note/flash-to-prd.js +4 -5
  57. package/lib/i18n-management/i18n-management.js +3 -4
  58. package/lib/integration/integration-api.js +9 -15
  59. package/lib/integration/integration-check.js +9 -7
  60. package/lib/integration/integration-create.js +10 -8
  61. package/lib/integration/integration-list.js +10 -8
  62. package/lib/mcp/server.js +5 -55
  63. package/lib/page-config/get-page-config.js +5 -6
  64. package/lib/page-config/save-share-config.js +5 -6
  65. package/lib/page-config/verify-short-url.js +4 -5
  66. package/lib/permission/get-permission.js +4 -5
  67. package/lib/permission/save-permission.js +5 -7
  68. package/lib/process/ai-form-setting.js +9 -10
  69. package/lib/process/configure-process.js +11 -17
  70. package/lib/process/create-process.js +6 -8
  71. package/lib/process/preview-process.js +2 -2
  72. package/lib/report/append.js +5 -6
  73. package/lib/report/http.js +4 -6
  74. package/lib/report/index.js +3 -3
  75. package/package.json +1 -1
  76. package/scripts/check-syntax.js +6 -0
  77. package/scripts/e2e-real/full-runner.js +2 -10
  78. package/scripts/e2e-real/runner.js +0 -31
  79. package/scripts/eval/screenshot.js +27 -69
  80. package/scripts/nightly-smoke.js +16 -34
  81. package/scripts/postinstall.js +6 -2
  82. package/yida-skills/SKILL.md +10 -6
  83. package/yida-skills/references/development-rules.md +2 -2
  84. package/yida-skills/references/setup-and-env.md +10 -9
  85. package/yida-skills/skills/sls-log-workbench/SKILL.md +2 -2
  86. package/yida-skills/skills/sls-log-workbench/sls-query.js +27 -54
  87. package/yida-skills/skills/yida-flash-note-to-prd/SKILL.md +1 -1
  88. package/yida-skills/skills/yida-integration/SKILL.md +3 -3
  89. package/yida-skills/skills/yida-login/SKILL.md +56 -74
  90. package/yida-skills/skills/yida-logout/SKILL.md +13 -12
  91. package/yida-skills/skills/yida-process-rule/SKILL.md +1 -1
  92. package/yida-skills/skills/yida-publish-page/SKILL.md +1 -1
  93. package/yida-skills/skills/yida-report/references/report-api-guide.md +4 -20
  94. package/yida-skills/skills-index.json +4 -4
  95. package/lib/auth/auth.js +0 -313
  96. package/lib/auth/cdp-browser-login.js +0 -390
  97. package/lib/auth/codex-login.js +0 -71
  98. package/lib/auth/login.js +0 -550
  99. package/lib/auth/qr-login.js +0 -1575
package/README.md CHANGED
@@ -55,10 +55,10 @@ If Codex is already installed, OpenYida also imports a local Codex plugin during
55
55
  Run this from the AI coding workspace where you want OpenYida to operate:
56
56
 
57
57
  ```bash
58
- openyida agent-capabilities --json
58
+ openyida agent-capabilities --summary-json
59
59
  ```
60
60
 
61
- OpenYida detects the active agent environment, workspace path, login state, organization context, command manifest, and side-effect hints in one machine-readable snapshot. `openyida commands --json` remains available when an agent only needs the command manifest.
61
+ OpenYida returns a compact machine-readable summary with the version, login state, workspace/cache paths, and command manifest digest. `openyida agent-capabilities --json` is the full diagnostic snapshot, where compact `workdir` maps to `active.projectRoot` and `workdir_exists` maps to `active.projectRootExists`. `openyida commands --json` remains available when an agent only needs the command manifest.
62
62
 
63
63
  ### 3. Log In
64
64
 
@@ -66,27 +66,20 @@ OpenYida detects the active agent environment, workspace path, login state, orga
66
66
  openyida login
67
67
  ```
68
68
 
69
- In Codex, QoderWork, Qoder, Wukong, Claude Code, MuleRun, OpenCode, Cursor, and other detected AI tools, OpenYida first tries local Chrome/Edge/Chromium CDP when no valid cached login exists. If local CDP is unavailable, it falls back to an AI-dialog QR handoff. The agent should render `qr_image_markdown` or paste `agent_response_markdown` directly in the conversation so the QR code is visible, then run `poll_command` after the user scans it with DingTalk. If image rendering is unavailable, fall back to `qr_url`. The explicit `openyida login --browser` command still prefers CDP first and uses Playwright as an optional browser fallback.
69
+ OpenYida login defaults to OAuth token mode. It opens the DingTalk OAuth authorization page, receives the local loopback callback, exchanges `code` / `authCode` with the Yida server, and stores `access_token` / `refresh_token` in the current project cache.
70
70
 
71
- When the user names a target Yida entry URL, pass it to the login command so OpenYida can select the matching environment and cookie file. For example, Alibaba intranet Yida uses `cookies-alibaba.json`:
71
+ When the user names a target Yida entry URL, pass it to the login command so OpenYida can select the matching environment and token session file. For example, Alibaba intranet Yida uses `auth-token-alibaba.json`:
72
72
 
73
73
  ```bash
74
74
  openyida login https://yida-group.alibaba-inc.com/
75
75
  openyida login --alibaba
76
76
  ```
77
77
 
78
- The explicit QR polling command remains available:
78
+ For token status checks, use:
79
79
 
80
80
  ```bash
81
- openyida login --agent-qr
82
- ```
83
-
84
- For terminal QR login, use:
85
-
86
- ```bash
87
- openyida login --qr
88
- openyida login --qr --corp-id dingxxxxxxxx
89
81
  openyida login --check-only --json
82
+ openyida auth status
90
83
  ```
91
84
 
92
85
  OpenYida does not install Playwright by default.
@@ -239,7 +232,7 @@ OPENYIDA_E2E=1 OPENYIDA_E2E_FULL_STAGES=auth,app,form,process npm run test:e2e:r
239
232
  npm run test:e2e:real:skills
240
233
  ```
241
234
 
242
- The runner creates a disposable app, form, and custom page with an `OY_E2E_*` prefix, then verifies login, app listing, schema fetch, data query, and page publish. It writes a registry to `project/.cache/e2e-real/` so created resources can be audited later. To inject CI cookies without relying on a local login cache, pass `OPENYIDA_E2E_COOKIES_BASE64` as a base64 encoded cookie array or `{ "cookies": [...] }` object.
235
+ The runner creates a disposable app, form, and custom page with an `OY_E2E_*` prefix, then verifies token login, app listing, schema fetch, data query, and page publish. It writes a registry to `project/.cache/e2e-real/` so created resources can be audited later. Run `openyida login` for the target environment before starting the real E2E runner.
243
236
 
244
237
  `test:e2e:real:full` extends the smoke path into a broad deterministic feature matrix: auth/env, app update, form update and option mutation, page build/compile/generate/publish, data create/get/update/query, permission read, page config and short URL check, report create/append, dashboard skill verification, export/import, batch, task-center, formula/doctor/sample/CDN config, and local connector parsing/template generation. AI-backed commands such as `flash-to-prd` are available as the optional `ai` stage because they depend on remote model availability. Workflow mutation is available as the opt-in `process` stage; it creates and republishes a workflow on the disposable E2E form and records advanced official-node fixtures for review.
245
238
 
@@ -339,11 +332,11 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
339
332
 
340
333
  | Command | Description |
341
334
  |---------|-------------|
342
- | `openyida login [target-url] [--qr\|--agent-qr\|--codex\|--browser] [--env <name>\|--intl\|--overseas\|--global\|--yidaapps\|--alibaba] [--corp-id <corpId>]` | Login (cache first, --browser or --agent-qr when needed) |
343
- | `openyida logout` | Logout / switch account |
344
- | `openyida auth <status\|login\|refresh\|logout>` | Login state management |
345
- | `openyida org <list\|switch>` | Organization management (list / switch) |
346
- | `openyida env [--json\|setup\|list\|show\|switch\|add\|remove] [options]` | Detect AI tool environment & login state |
335
+ | `openyida login [target-url] [--env <name>\|--intl\|--overseas\|--global\|--yidaapps\|--alibaba] [--client-id <clientId>] [--endpoint <url>]` | Login with OAuth token mode |
336
+ | `openyida logout` | Logout / clear token |
337
+ | `openyida auth <status\|login\|refresh\|logout>` | Token login state management |
338
+ | `openyida org <list\|switch> [--json] [--corp-id <corpId>]` | Organization management (list / switch by OAuth re-login) |
339
+ | `openyida env [--json\|setup\|list\|show\|switch\|add\|remove] [options]` | Detect AI tool environment & token login state |
347
340
 
348
341
  ### App Management
349
342
 
@@ -457,7 +450,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
457
450
  | Command | Description |
458
451
  |---------|-------------|
459
452
  | `openyida commands [--json]` | Output machine-readable command manifest |
460
- | `openyida agent-capabilities [--json]` | Output one-shot agent capability snapshot |
453
+ | `openyida agent-capabilities [--json] [--summary-json\|--compact]` | Output one-shot agent capability snapshot |
461
454
  | `openyida a2a <serve\|agent-card> [options]` | Start local read-only A2A adapter or print Agent Card |
462
455
  | `openyida bridge start [--token <pair-token>] [--port 6736] [--origin https://demo.aliwork.com] [--open\|--no-open]` | Start OpenYida local web bridge service |
463
456
  | `openyida copy [--force]` | Copy project working directory |
@@ -585,9 +578,9 @@ When adding new CLI commands, register the route in `bin/yida.js`, add it to `li
585
578
 
586
579
  ## Security and Configuration
587
580
 
588
- - Login cookies are cached locally and should never be hard-coded into source files.
581
+ - OAuth token sessions are cached locally and should never be hard-coded into source files.
589
582
  - Private deployment environments are managed through `lib/core/env-manager.js`.
590
- - Yida API requests should use the active environment base URL and authenticated cookies.
583
+ - Yida API requests should use the active environment base URL and Bearer token auth.
591
584
  - For multi-organization accounts, prefer explicit `--corp-id` values in non-interactive automation.
592
585
 
593
586
  ## Community
package/bin/yida.js CHANGED
@@ -211,6 +211,32 @@ function handleFirstRunGuide() {
211
211
  console.log('');
212
212
  }
213
213
 
214
+ const TOKEN_OUTPUT_SECRET_KEYS = new Set([
215
+ 'access_token',
216
+ 'accessToken',
217
+ 'refresh_token',
218
+ 'refreshToken',
219
+ ]);
220
+
221
+ function maskSensitiveAuthOutput(value) {
222
+ if (!value || typeof value !== 'object') {
223
+ return value;
224
+ }
225
+ const { maskToken } = require('../lib/auth/token-store');
226
+ if (Array.isArray(value)) {
227
+ return value.map((item) => maskSensitiveAuthOutput(item));
228
+ }
229
+ const output = {};
230
+ Object.entries(value).forEach(([key, item]) => {
231
+ if (TOKEN_OUTPUT_SECRET_KEYS.has(key)) {
232
+ output[key] = maskToken(item);
233
+ } else {
234
+ output[key] = maskSensitiveAuthOutput(item);
235
+ }
236
+ });
237
+ return output;
238
+ }
239
+
214
240
  function printLoginResult(result) {
215
241
  noteLoginCommandResult(result);
216
242
 
@@ -224,49 +250,21 @@ function printLoginResult(result) {
224
250
  return;
225
251
  }
226
252
 
227
- if (result && (result.status === 'need_qr_scan' || result.status === 'need_corp_selection')) {
228
- console.log(JSON.stringify(result));
229
- return;
230
- }
231
-
232
- if (result && result.status === 'need_codex_browser_login') {
233
- const handoff = {
234
- status: result.status,
235
- handoff_type: result.handoff_type || 'browser',
236
- can_auto_use: false,
237
- browser: result.browser,
238
- login_url: result.login_url,
239
- message: result.message,
240
- };
241
- [
242
- 'agent_action',
243
- 'browser_open_strategy',
244
- 'browser_use_local_redirect_fallback',
245
- 'required_agent_tool',
246
- 'required_runtime_tool',
247
- 'cookie_export_file',
248
- 'cookie_file',
249
- 'post_login_check_command',
250
- 'fallback_command',
251
- ].forEach((key) => {
252
- if (result[key]) {handoff[key] = result[key];}
253
- });
254
- console.log(JSON.stringify(handoff));
255
- return;
256
- }
257
-
258
- if (result.status && result.status !== 'ok' && !result.csrf_token) {
259
- console.log(JSON.stringify(result));
260
- return;
261
- }
262
-
253
+ const tokenUsable = result.can_auto_use !== false && !!result.access_token;
263
254
  const summary = {
264
- ok: true,
265
- base_url: result && result.base_url,
266
- corp_id: result && result.corp_id,
267
- user_id: result && result.user_id,
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 : (result.cookies_count || 0),
255
+ ok: tokenUsable,
256
+ status: result.status || (tokenUsable ? 'ok' : 'token_not_issued'),
257
+ auth_mode: 'token',
258
+ can_auto_use: tokenUsable,
259
+ token_type: result.token_type || 'Bearer',
260
+ access_token: maskSensitiveAuthOutput({ access_token: result.access_token }).access_token,
261
+ expires_at: result.expires_at ? new Date(result.expires_at).toISOString() : undefined,
262
+ base_url: result.base_url,
263
+ corp_id: result.corp_id,
264
+ user_id: result.user_id,
265
+ user_name: result.user_name,
266
+ message: result.message,
267
+ raw: tokenUsable ? undefined : result.raw,
270
268
  };
271
269
  console.log(JSON.stringify(summary));
272
270
  }
@@ -277,15 +275,11 @@ function noteLoginCommandResult(result) {
277
275
  let status = 'failed';
278
276
  let reason = 'login_failed';
279
277
 
280
- if (result && (result.csrf_token || (result.status === 'ok' && result.can_auto_use))) {
278
+ const tokenLoginOk = result && result.auth_mode === 'token' &&
279
+ (result.access_token || (result.status === 'ok' && result.can_auto_use));
280
+ if (result && (tokenLoginOk || (result.status === 'ok' && result.can_auto_use))) {
281
281
  status = 'success';
282
282
  reason = 'login_ok';
283
- } else if (result && result.status === 'need_qr_scan') {
284
- status = 'need_qr_scan';
285
- reason = 'need_qr_scan';
286
- } else if (result && result.status === 'need_codex_browser_login') {
287
- status = 'need_browser_login';
288
- reason = 'need_browser_login';
289
283
  } else if (result && result.status === 'need_corp_selection') {
290
284
  status = 'success';
291
285
  reason = 'need_corp_selection';
@@ -306,40 +300,6 @@ function noteLoginCommandResult(result) {
306
300
  }
307
301
  }
308
302
 
309
- function isAgentConversationEnvironment() {
310
- const { detectActiveTool } = require('../lib/core/utils');
311
- return !!detectActiveTool() || process.env.OPENYIDA_AGENT_MODE === '1';
312
- }
313
-
314
- function shouldUseBrowserHandoffLogin(cliArgs) {
315
- if (cliArgs.includes('--qr') || cliArgs.includes('--codex-qr') || cliArgs.includes('--agent-qr')) {return false;}
316
- if (cliArgs.includes('--browser') || cliArgs.includes('--codex') || cliArgs.includes('--qoder') || cliArgs.includes('--wukong')) {return true;}
317
- return false;
318
- }
319
-
320
- function shouldUseAgentLogin(cliArgs) {
321
- if (cliArgs.includes('--qr') || cliArgs.includes('--codex-qr') || cliArgs.includes('--agent-qr')) {return false;}
322
- if (shouldUseBrowserHandoffLogin(cliArgs)) {return false;}
323
- return isAgentConversationEnvironment();
324
- }
325
-
326
- function shouldUsePlaywrightFallbackInAgentLogin() {
327
- const { hasDesktopEnvironment } = require('../lib/core/utils');
328
- return hasDesktopEnvironment() || process.env.OPENYIDA_AGENT_PLAYWRIGHT_FALLBACK === '1';
329
- }
330
-
331
- function shouldUseLocalBrowserLogin(options = {}) {
332
- const { hasLocalBrowserLoginCapability } = require('../lib/auth/login');
333
- return hasLocalBrowserLoginCapability({
334
- playwrightFallback: options.playwrightFallback,
335
- });
336
- }
337
-
338
- function shouldUseCodexQrLogin(cliArgs) {
339
- if (cliArgs.includes('--codex-qr') || cliArgs.includes('--agent-qr')) {return true;}
340
- return false;
341
- }
342
-
343
303
  function getArgValue(cliArgs, name) {
344
304
  const index = cliArgs.indexOf(name);
345
305
  if (index === -1 || !cliArgs[index + 1] || cliArgs[index + 1].startsWith('--')) {
@@ -414,11 +374,9 @@ function applyLoginEnvironmentFlags(cliArgs, options = {}) {
414
374
  '--intranet': 'alibaba',
415
375
  };
416
376
  const valuePassthroughFlags = new Set([
417
- '--agent-poll',
418
- '--codex-poll',
419
- '--agent-select',
420
- '--codex-select',
421
377
  '--corp-id',
378
+ '--client-id',
379
+ '--user-id',
422
380
  ]);
423
381
  const targetUrlFlags = new Set([
424
382
  '--endpoint',
@@ -487,12 +445,6 @@ function throwCliUsage(...lines) {
487
445
  });
488
446
  }
489
447
 
490
- function throwNeedLogin(message) {
491
- throw new CliError(message, {
492
- code: 'NEED_LOGIN',
493
- });
494
- }
495
-
496
448
  async function main() {
497
449
  applyQuietFlag();
498
450
  applyGlobalEnvironmentFlags();
@@ -563,129 +515,42 @@ async function main() {
563
515
  }
564
516
 
565
517
  case 'login': {
566
- const { checkLoginOnly } = require('../lib/auth/login');
567
518
  const loginArgs = applyLoginEnvironmentFlags(args, { inferTargetUrl: true });
568
- const { isEnvAuthMode } = require('../lib/core/utils');
569
- if (loginArgs.includes('--agent-poll') || loginArgs.includes('--codex-poll')) {
570
- const sessionFile = getArgValue(loginArgs, '--agent-poll') || getArgValue(loginArgs, '--codex-poll');
571
- const { pollCodexQrLogin } = require('../lib/auth/qr-login');
572
- const result = await pollCodexQrLogin(sessionFile, {
573
- corpId: getArgValue(loginArgs, '--corp-id'),
574
- });
575
- printLoginResult(result);
576
- } else if (loginArgs.includes('--agent-select') || loginArgs.includes('--codex-select')) {
577
- const sessionFile = getArgValue(loginArgs, '--agent-select') || getArgValue(loginArgs, '--codex-select');
578
- const { selectCodexQrCorp } = require('../lib/auth/qr-login');
579
- const result = await selectCodexQrCorp(sessionFile, {
580
- corpId: getArgValue(loginArgs, '--corp-id'),
581
- });
582
- printLoginResult(result);
583
- } else if (loginArgs.includes('--check-only')) {
584
- const result = checkLoginOnly({ includeSecrets: loginArgs.includes('--with-cookies') });
585
- console.log(JSON.stringify(result, null, 2));
586
- } else if (isEnvAuthMode()) {
587
- const result = checkLoginOnly({ includeSecrets: true });
588
- printLoginResult(result);
589
- } else if (shouldUseCodexQrLogin(loginArgs)) {
590
- const { startCodexQrLogin } = require('../lib/auth/qr-login');
591
- const result = await startCodexQrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
592
- printLoginResult(result);
593
- } else if (loginArgs.includes('--browser')) {
594
- const { interactiveLogin } = require('../lib/auth/login');
595
- const result = interactiveLogin({ force: true });
596
- printLoginResult(result);
597
- } else if (loginArgs.includes('--qoder') || loginArgs.includes('--wukong')) {
598
- const { codexLogin } = require('../lib/auth/codex-login');
599
- const result = await codexLogin({ tool: loginArgs.includes('--qoder') ? 'qoder' : 'wukong' });
600
- printLoginResult(result);
601
- } else if (loginArgs.includes('--qr')) {
602
- const { qrLogin } = require('../lib/auth/qr-login');
603
- const result = await qrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
604
- printLoginResult(result);
605
- } else if (shouldUseAgentLogin(loginArgs)) {
606
- const cachedResult = checkLoginOnly({ includeSecrets: true });
607
- if (cachedResult.status === 'ok') {
608
- printLoginResult(cachedResult);
609
- } else {
610
- const { interactiveLogin } = require('../lib/auth/login');
611
- const playwrightFallback = shouldUsePlaywrightFallbackInAgentLogin();
612
- const browserResult = shouldUseLocalBrowserLogin({ playwrightFallback })
613
- ? interactiveLogin({ playwrightFallback })
614
- : null;
615
- if (browserResult) {
616
- printLoginResult(browserResult);
617
- } else {
618
- const { startCodexQrLogin } = require('../lib/auth/qr-login');
619
- const result = await startCodexQrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
620
- printLoginResult(result);
621
- }
622
- }
623
- } else if (shouldUseBrowserHandoffLogin(loginArgs)) {
624
- const cachedResult = checkLoginOnly({ includeSecrets: true });
625
- if (cachedResult.status === 'ok') {
626
- printLoginResult(cachedResult);
627
- } else {
628
- const { codexLogin } = require('../lib/auth/codex-login');
629
- const result = await codexLogin({ tool: loginArgs.includes('--codex') ? 'codex' : undefined });
630
- printLoginResult(result);
631
- }
519
+ const { tokenLogin, tokenStatus } = require('../lib/auth/token-auth');
520
+ if (loginArgs.includes('--check-only')) {
521
+ console.log(JSON.stringify(tokenStatus(), null, 2));
632
522
  } else {
633
- const cachedResult = checkLoginOnly({ includeSecrets: true });
634
- if (cachedResult.status === 'ok') {
635
- printLoginResult(cachedResult);
636
- break;
637
- }
638
- if (shouldUseLocalBrowserLogin({ playwrightFallback: true })) {
639
- const { interactiveLogin } = require('../lib/auth/login');
640
- const browserResult = interactiveLogin({ playwrightFallback: true });
641
- if (browserResult) {
642
- printLoginResult(browserResult);
643
- break;
644
- }
645
- }
646
- const { qrLogin } = require('../lib/auth/qr-login');
647
- const result = await qrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
523
+ const result = await tokenLogin({
524
+ clientId: getArgValue(loginArgs, '--client-id'),
525
+ quiet: loginArgs.includes('--quiet'),
526
+ });
648
527
  printLoginResult(result);
649
528
  }
650
529
  break;
651
530
  }
652
531
 
653
532
  case 'logout': {
654
- const { logout } = require('../lib/auth/login');
655
- logout();
533
+ const { tokenLogout } = require('../lib/auth/token-auth');
534
+ console.log(JSON.stringify(await tokenLogout(), null, 2));
656
535
  break;
657
536
  }
658
537
 
659
538
  case 'auth': {
660
539
  const subCommand = args[0];
661
- const { authStatus, authLogin, authRefresh, authLogout } = require('../lib/auth/auth');
662
-
540
+ const authArgs = applyLoginEnvironmentFlags(args.slice(1), { inferTargetUrl: true });
541
+ const { tokenLogin, tokenLogout, tokenRefresh, tokenStatus } = require('../lib/auth/token-auth');
663
542
  if (subCommand === 'status') {
664
- authStatus();
543
+ console.log(JSON.stringify(tokenStatus(), null, 2));
665
544
  } else if (subCommand === 'login') {
666
- const authArgs = applyLoginEnvironmentFlags(args.slice(1), { inferTargetUrl: true });
667
- let loginType = 'qrcode';
668
- if (authArgs.includes('--codex')) {
669
- loginType = 'codex';
670
- } else if (authArgs.includes('--qoder')) {
671
- loginType = 'qoder';
672
- } else if (authArgs.includes('--wukong')) {
673
- loginType = 'wukong';
674
- } else if (authArgs.includes('--browser')) {
675
- loginType = 'browser';
676
- }
677
- const result = await authLogin({
678
- type: loginType,
679
- corpId: getArgValue(authArgs, '--corp-id'),
680
- forceTerminalQr: authArgs.includes('--qr'),
545
+ const result = await tokenLogin({
546
+ clientId: getArgValue(authArgs, '--client-id'),
547
+ quiet: authArgs.includes('--quiet'),
681
548
  });
682
- if (result) {
683
- printLoginResult(result);
684
- }
549
+ printLoginResult(result);
685
550
  } else if (subCommand === 'refresh') {
686
- authRefresh();
551
+ console.log(JSON.stringify(maskSensitiveAuthOutput(await tokenRefresh()), null, 2));
687
552
  } else if (subCommand === 'logout') {
688
- authLogout();
553
+ console.log(JSON.stringify(await tokenLogout(), null, 2));
689
554
  } else {
690
555
  throwCliUsage(t('cli.auth_usage'), t('cli.auth_example'));
691
556
  }
@@ -693,34 +558,9 @@ async function main() {
693
558
  }
694
559
 
695
560
  case 'org': {
696
- const subCommand = args[0];
697
- const { listOrganizations, switchOrganization, interactiveSwitch } = require('../lib/auth/org');
698
- const { loadCookieData } = require('../lib/core/utils');
699
-
700
- if (subCommand === 'list') {
701
- const cookieData = loadCookieData();
702
- if (!cookieData || !cookieData.cookies) {
703
- throwNeedLogin(t('org.no_login'));
704
- }
705
- await listOrganizations(cookieData);
706
- } else if (subCommand === 'switch') {
707
- const cookieData = loadCookieData();
708
- if (!cookieData || !cookieData.cookies) {
709
- throwNeedLogin(t('org.no_login'));
710
- }
711
-
712
- // 解析 --corp-id 参数
713
- const corpIdIndex = args.indexOf('--corp-id');
714
- if (corpIdIndex !== -1 && args[corpIdIndex + 1]) {
715
- const targetCorpId = args[corpIdIndex + 1];
716
- await switchOrganization(targetCorpId, cookieData);
717
- } else {
718
- // 交互式选择
719
- await interactiveSwitch(cookieData);
720
- }
721
- } else {
722
- throwCliUsage(t('cli.org_usage'), t('cli.org_example'));
723
- }
561
+ const orgArgs = applyLoginEnvironmentFlags(args, { inferTargetUrl: true });
562
+ const { run } = require('../lib/auth/org');
563
+ await run(orgArgs);
724
564
  break;
725
565
  }
726
566
 
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { createAuthRef, createYidaClient } = require('../core/yida-client');
3
+ const { createAuthRef, createYidaClient, isAuthRefReady } = require('../core/yida-client');
4
4
 
5
5
  const AGENT_TYPE_ALIASES = {
6
6
  normal: 'NORMAL',
@@ -70,8 +70,8 @@ const AGENT_RANGE_ALIASES = {
70
70
 
71
71
  function getAuthRef() {
72
72
  const authRef = createAuthRef();
73
- if (!authRef.cookies || !authRef.cookies.length || !authRef.csrfToken) {
74
- throw new Error('无法获取有效登录态或 CSRF Token');
73
+ if (!isAuthRefReady(authRef)) {
74
+ throw new Error('无法获取有效 token 登录态');
75
75
  }
76
76
  return authRef;
77
77
  }
@@ -128,7 +128,6 @@ function normalizeYesNo(value, defaultValue = 'n') {
128
128
  function buildCommonParams(authRef, apiName, params = {}) {
129
129
  const base = {
130
130
  _mock: 'false',
131
- _csrf_token: authRef.csrfToken,
132
131
  _locale_time_zone_offset: '28800000',
133
132
  _stamp: String(Date.now()),
134
133
  };
@@ -150,7 +149,7 @@ async function agentPost(path, apiName, params = {}, authRef = getAuthRef()) {
150
149
  }
151
150
 
152
151
  function assertSuccess(result, action) {
153
- if (result && result.success !== false && !result.__needLogin && !result.__csrfExpired) {
152
+ if (result && result.success !== false && !result.__needLogin) {
154
153
  return result;
155
154
  }
156
155
  const message = result && (result.errorMsg || result.message || result.errorCode);
@@ -3,7 +3,7 @@
3
3
  const fs = require('fs');
4
4
  const querystring = require('querystring');
5
5
 
6
- const { createAuthRef: createCoreAuthRef, createYidaClient } = require('../core/yida-client');
6
+ const { createAuthRef: createCoreAuthRef, createYidaClient, isAuthRefReady } = require('../core/yida-client');
7
7
  const { t } = require('../core/i18n');
8
8
  const { buildYidaTitleI18n, normalizeYidaLocale, resolveContentLocale } = require('../core/yida-i18n');
9
9
  const { parseOpenOption, withBrowserHandoff } = require('../core/browser-handoff');
@@ -86,7 +86,7 @@ function unwrapContent(result) {
86
86
  }
87
87
 
88
88
  function assertSuccess(result, action) {
89
- if (!result || result.success === false || result.__needLogin || result.__csrfExpired) {
89
+ if (!result || result.success === false || result.__needLogin) {
90
90
  const message = result
91
91
  ? result.errorMsg || result.error || result.message || t('common.unknown_error')
92
92
  : t('common.request_failed');
@@ -97,15 +97,14 @@ function assertSuccess(result, action) {
97
97
 
98
98
  async function createAuthRef() {
99
99
  const authRef = createCoreAuthRef();
100
- if (!authRef.cookies || authRef.cookies.length === 0) {
100
+ if (!isAuthRefReady(authRef)) {
101
101
  throw new Error(t('aggregate_table.no_login'));
102
102
  }
103
103
  return authRef;
104
104
  }
105
105
 
106
- function buildCreateEmptyPostData(csrfToken, title) {
106
+ function buildCreateEmptyPostData(title) {
107
107
  return querystring.stringify({
108
- _csrf_token: csrfToken,
109
108
  formType: 'receipt',
110
109
  isVirtualView: 'y',
111
110
  title: JSON.stringify(buildYidaTitleI18n(title, {
@@ -115,9 +114,8 @@ function buildCreateEmptyPostData(csrfToken, title) {
115
114
  });
116
115
  }
117
116
 
118
- function buildDesignPostData(csrfToken, formUuid, designInfo, gmtModified) {
117
+ function buildDesignPostData(formUuid, designInfo, gmtModified) {
119
118
  const payload = {
120
- _csrf_token: csrfToken,
121
119
  formUuid,
122
120
  designInfo: JSON.stringify(designInfo),
123
121
  };
@@ -130,14 +128,14 @@ function buildDesignPostData(csrfToken, formUuid, designInfo, gmtModified) {
130
128
  async function checkVirtualViewFeature(authRef, appType) {
131
129
  return createYidaClient({ authRef }).postForm(
132
130
  `/dingtalk/web/${appType}/query/virtualview/show.json`,
133
- auth => ({ _csrf_token: auth.csrfToken })
131
+ {}
134
132
  );
135
133
  }
136
134
 
137
135
  async function createEmptyVirtualView(authRef, appType, title) {
138
136
  return createYidaClient({ authRef }).postForm(
139
137
  `/dingtalk/web/${appType}/query/formdesign/saveFormSchemaInfo.json`,
140
- auth => buildCreateEmptyPostData(auth.csrfToken, title)
138
+ buildCreateEmptyPostData(title)
141
139
  );
142
140
  }
143
141
 
@@ -161,7 +159,7 @@ async function postVirtualViewDesign(authRef, appType, formUuid, designInfo, act
161
159
 
162
160
  return createYidaClient({ authRef }).postForm(
163
161
  `/alibaba/web/${appType}/query/virtualview/${endpoint}`,
164
- auth => buildDesignPostData(auth.csrfToken, formUuid, designInfo, gmtModified)
162
+ buildDesignPostData(formUuid, designInfo, gmtModified)
165
163
  );
166
164
  }
167
165