openyida 2026.7.13 → 2026.7.14-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 (95) hide show
  1. package/README.md +15 -22
  2. package/bin/yida.js +72 -220
  3. package/lib/agent-center/api.js +2 -2
  4. package/lib/aggregate-table/aggregate-table.js +2 -2
  5. package/lib/ai/ai.js +7 -12
  6. package/lib/app/canvas-compile.js +2 -2
  7. package/lib/app/create-app.js +5 -19
  8. package/lib/app/create-form.js +54 -76
  9. package/lib/app/create-page.js +4 -19
  10. package/lib/app/er.js +11 -8
  11. package/lib/app/export-app.js +2 -2
  12. package/lib/app/externalize-form.js +12 -10
  13. package/lib/app/get-schema.js +12 -10
  14. package/lib/app/import-app.js +6 -22
  15. package/lib/app/list-forms.js +3 -19
  16. package/lib/app/nav-group.js +6 -19
  17. package/lib/app/publish.js +60 -198
  18. package/lib/app/update-app.js +4 -18
  19. package/lib/app/update-form-config.js +20 -113
  20. package/lib/app-permission/app-permission.js +2 -2
  21. package/lib/auth/oauth-loopback.js +156 -0
  22. package/lib/auth/org.js +169 -322
  23. package/lib/auth/token-auth.js +346 -0
  24. package/lib/auth/token-store.js +174 -0
  25. package/lib/basic-info/basic-info.js +11 -12
  26. package/lib/bridge/bridge.js +29 -27
  27. package/lib/connector/api.js +4 -4
  28. package/lib/core/agent-capabilities.js +92 -8
  29. package/lib/core/batch.js +8 -8
  30. package/lib/core/check-data.js +2 -2
  31. package/lib/core/command-manifest.js +3 -3
  32. package/lib/core/doctor.js +19 -22
  33. package/lib/core/env-cmd.js +1 -3
  34. package/lib/core/env-manager.js +8 -121
  35. package/lib/core/env.js +30 -72
  36. package/lib/core/locales/ar.js +5 -5
  37. package/lib/core/locales/de.js +5 -5
  38. package/lib/core/locales/en.js +26 -26
  39. package/lib/core/locales/es.js +5 -5
  40. package/lib/core/locales/fr.js +5 -5
  41. package/lib/core/locales/hi.js +5 -5
  42. package/lib/core/locales/ja.js +14 -14
  43. package/lib/core/locales/ko.js +5 -5
  44. package/lib/core/locales/pt.js +5 -5
  45. package/lib/core/locales/vi.js +5 -5
  46. package/lib/core/locales/zh-HK.js +15 -15
  47. package/lib/core/locales/zh.js +26 -26
  48. package/lib/core/query-data.js +2 -2
  49. package/lib/core/task-center.js +2 -2
  50. package/lib/core/utils.js +156 -400
  51. package/lib/core/yida-client.js +57 -22
  52. package/lib/corp-efficiency/corp-efficiency.js +3 -3
  53. package/lib/corp-manager/api.js +2 -2
  54. package/lib/db/db-seq-fix.js +20 -25
  55. package/lib/flash-note/flash-to-prd.js +2 -2
  56. package/lib/i18n-management/i18n-management.js +2 -2
  57. package/lib/integration/integration-check.js +10 -7
  58. package/lib/integration/integration-create.js +11 -8
  59. package/lib/integration/integration-list.js +11 -8
  60. package/lib/mcp/server.js +5 -54
  61. package/lib/page-config/get-page-config.js +2 -2
  62. package/lib/page-config/save-share-config.js +2 -2
  63. package/lib/page-config/verify-short-url.js +2 -2
  64. package/lib/permission/get-permission.js +2 -2
  65. package/lib/permission/save-permission.js +2 -2
  66. package/lib/process/ai-form-setting.js +2 -2
  67. package/lib/process/create-process.js +2 -2
  68. package/lib/process/preview-process.js +2 -2
  69. package/lib/report/append.js +3 -3
  70. package/lib/report/index.js +3 -3
  71. package/package.json +1 -1
  72. package/scripts/check-syntax.js +6 -0
  73. package/scripts/e2e-real/full-runner.js +2 -10
  74. package/scripts/e2e-real/runner.js +0 -31
  75. package/scripts/eval/screenshot.js +27 -69
  76. package/scripts/nightly-smoke.js +16 -34
  77. package/scripts/postinstall.js +6 -2
  78. package/yida-skills/SKILL.md +10 -6
  79. package/yida-skills/references/development-rules.md +2 -2
  80. package/yida-skills/references/setup-and-env.md +10 -9
  81. package/yida-skills/skills/sls-log-workbench/SKILL.md +2 -2
  82. package/yida-skills/skills/sls-log-workbench/sls-query.js +27 -54
  83. package/yida-skills/skills/yida-flash-note-to-prd/SKILL.md +1 -1
  84. package/yida-skills/skills/yida-integration/SKILL.md +3 -3
  85. package/yida-skills/skills/yida-login/SKILL.md +56 -74
  86. package/yida-skills/skills/yida-logout/SKILL.md +13 -12
  87. package/yida-skills/skills/yida-process-rule/SKILL.md +1 -1
  88. package/yida-skills/skills/yida-publish-page/SKILL.md +1 -1
  89. package/yida-skills/skills/yida-report/references/report-api-guide.md +4 -20
  90. package/yida-skills/skills-index.json +4 -4
  91. package/lib/auth/auth.js +0 -313
  92. package/lib/auth/cdp-browser-login.js +0 -390
  93. package/lib/auth/codex-login.js +0 -71
  94. package/lib/auth/login.js +0 -550
  95. 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,38 @@ 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
+ 'ai_app_user_auth_token',
220
+ 'aiAppUserAuthToken',
221
+ 'tianshu_csrf_token',
222
+ 'tianshuCsrfToken',
223
+ 'csrf_token',
224
+ 'csrfToken',
225
+ ]);
226
+
227
+ function maskSensitiveAuthOutput(value) {
228
+ if (!value || typeof value !== 'object') {
229
+ return value;
230
+ }
231
+ const { maskToken } = require('../lib/auth/token-store');
232
+ if (Array.isArray(value)) {
233
+ return value.map((item) => maskSensitiveAuthOutput(item));
234
+ }
235
+ const output = {};
236
+ Object.entries(value).forEach(([key, item]) => {
237
+ if (TOKEN_OUTPUT_SECRET_KEYS.has(key)) {
238
+ output[key] = maskToken(item);
239
+ } else {
240
+ output[key] = maskSensitiveAuthOutput(item);
241
+ }
242
+ });
243
+ return output;
244
+ }
245
+
214
246
  function printLoginResult(result) {
215
247
  noteLoginCommandResult(result);
216
248
 
@@ -224,49 +256,21 @@ function printLoginResult(result) {
224
256
  return;
225
257
  }
226
258
 
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
-
259
+ const tokenUsable = result.can_auto_use !== false && !!result.access_token;
263
260
  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),
261
+ ok: tokenUsable,
262
+ status: result.status || (tokenUsable ? 'ok' : 'token_not_issued'),
263
+ auth_mode: 'token',
264
+ can_auto_use: tokenUsable,
265
+ token_type: result.token_type || 'Bearer',
266
+ access_token: maskSensitiveAuthOutput({ access_token: result.access_token }).access_token,
267
+ expires_at: result.expires_at ? new Date(result.expires_at).toISOString() : undefined,
268
+ base_url: result.base_url,
269
+ corp_id: result.corp_id,
270
+ user_id: result.user_id,
271
+ user_name: result.user_name,
272
+ message: result.message,
273
+ raw: tokenUsable ? undefined : result.raw,
270
274
  };
271
275
  console.log(JSON.stringify(summary));
272
276
  }
@@ -277,15 +281,11 @@ function noteLoginCommandResult(result) {
277
281
  let status = 'failed';
278
282
  let reason = 'login_failed';
279
283
 
280
- if (result && (result.csrf_token || (result.status === 'ok' && result.can_auto_use))) {
284
+ const tokenLoginOk = result && result.auth_mode === 'token' &&
285
+ (result.access_token || (result.status === 'ok' && result.can_auto_use));
286
+ if (result && (tokenLoginOk || (result.status === 'ok' && result.can_auto_use))) {
281
287
  status = 'success';
282
288
  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
289
  } else if (result && result.status === 'need_corp_selection') {
290
290
  status = 'success';
291
291
  reason = 'need_corp_selection';
@@ -306,40 +306,6 @@ function noteLoginCommandResult(result) {
306
306
  }
307
307
  }
308
308
 
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
309
  function getArgValue(cliArgs, name) {
344
310
  const index = cliArgs.indexOf(name);
345
311
  if (index === -1 || !cliArgs[index + 1] || cliArgs[index + 1].startsWith('--')) {
@@ -414,11 +380,9 @@ function applyLoginEnvironmentFlags(cliArgs, options = {}) {
414
380
  '--intranet': 'alibaba',
415
381
  };
416
382
  const valuePassthroughFlags = new Set([
417
- '--agent-poll',
418
- '--codex-poll',
419
- '--agent-select',
420
- '--codex-select',
421
383
  '--corp-id',
384
+ '--client-id',
385
+ '--user-id',
422
386
  ]);
423
387
  const targetUrlFlags = new Set([
424
388
  '--endpoint',
@@ -563,129 +527,42 @@ async function main() {
563
527
  }
564
528
 
565
529
  case 'login': {
566
- const { checkLoginOnly } = require('../lib/auth/login');
567
530
  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
- }
531
+ const { tokenLogin, tokenStatus } = require('../lib/auth/token-auth');
532
+ if (loginArgs.includes('--check-only')) {
533
+ console.log(JSON.stringify(tokenStatus(), null, 2));
632
534
  } 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') });
535
+ const result = await tokenLogin({
536
+ clientId: getArgValue(loginArgs, '--client-id'),
537
+ quiet: loginArgs.includes('--quiet'),
538
+ });
648
539
  printLoginResult(result);
649
540
  }
650
541
  break;
651
542
  }
652
543
 
653
544
  case 'logout': {
654
- const { logout } = require('../lib/auth/login');
655
- logout();
545
+ const { tokenLogout } = require('../lib/auth/token-auth');
546
+ console.log(JSON.stringify(await tokenLogout(), null, 2));
656
547
  break;
657
548
  }
658
549
 
659
550
  case 'auth': {
660
551
  const subCommand = args[0];
661
- const { authStatus, authLogin, authRefresh, authLogout } = require('../lib/auth/auth');
662
-
552
+ const authArgs = applyLoginEnvironmentFlags(args.slice(1), { inferTargetUrl: true });
553
+ const { tokenLogin, tokenLogout, tokenRefresh, tokenStatus } = require('../lib/auth/token-auth');
663
554
  if (subCommand === 'status') {
664
- authStatus();
555
+ console.log(JSON.stringify(tokenStatus(), null, 2));
665
556
  } 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'),
557
+ const result = await tokenLogin({
558
+ clientId: getArgValue(authArgs, '--client-id'),
559
+ quiet: authArgs.includes('--quiet'),
681
560
  });
682
- if (result) {
683
- printLoginResult(result);
684
- }
561
+ printLoginResult(result);
685
562
  } else if (subCommand === 'refresh') {
686
- authRefresh();
563
+ console.log(JSON.stringify(maskSensitiveAuthOutput(await tokenRefresh()), null, 2));
687
564
  } else if (subCommand === 'logout') {
688
- authLogout();
565
+ console.log(JSON.stringify(await tokenLogout(), null, 2));
689
566
  } else {
690
567
  throwCliUsage(t('cli.auth_usage'), t('cli.auth_example'));
691
568
  }
@@ -693,34 +570,9 @@ async function main() {
693
570
  }
694
571
 
695
572
  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
- }
573
+ const orgArgs = applyLoginEnvironmentFlags(args, { inferTargetUrl: true });
574
+ const { run } = require('../lib/auth/org');
575
+ await run(orgArgs);
724
576
  break;
725
577
  }
726
578
 
@@ -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,7 +70,7 @@ const AGENT_RANGE_ALIASES = {
70
70
 
71
71
  function getAuthRef() {
72
72
  const authRef = createAuthRef();
73
- if (!authRef.cookies || !authRef.cookies.length || !authRef.csrfToken) {
73
+ if (!isAuthRefReady(authRef)) {
74
74
  throw new Error('无法获取有效登录态或 CSRF Token');
75
75
  }
76
76
  return authRef;
@@ -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');
@@ -97,7 +97,7 @@ 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;
package/lib/ai/ai.js CHANGED
@@ -15,7 +15,7 @@ const {
15
15
  findProjectRoot,
16
16
  } = require('../core/utils');
17
17
  const { CliError } = require('../core/cli-error');
18
- const { createAuthRef, createYidaClient } = require('../core/yida-client');
18
+ const { createAuthRef, createYidaClient, isAuthRefReady } = require('../core/yida-client');
19
19
 
20
20
  const DEFAULT_MAX_TOKENS = 3000;
21
21
  const DEFAULT_IMAGE_CONNECTOR = {
@@ -46,7 +46,7 @@ function printHelp() {
46
46
  image 上传本地图片并调用识图连接器;也可直接传入 --image-url
47
47
 
48
48
  image 选项:
49
- --app-type <APP_XXX> 上传图片使用的宜搭应用 ID;未传时尝试读取当前 project/config.json 或 Cookie
49
+ --app-type <APP_XXX> 上传图片使用的宜搭应用 ID;未传时尝试读取当前 project/config.json
50
50
  --form-uuid <FORM_XXX> 可选,上传回调关联的表单 ID
51
51
  --connector-id <id> 识图 HTTP 连接器 ID,默认使用 HAR 中的植物识别连接器
52
52
  --action-id <id> 识图动作 ID,默认 flowerrecognize
@@ -146,7 +146,7 @@ function getAuthRef(options = {}) {
146
146
  if (options.baseUrl) {
147
147
  authRef.baseUrl = options.baseUrl;
148
148
  }
149
- if (!authRef.cookies || authRef.cookies.length === 0 || !authRef.csrfToken) {
149
+ if (!isAuthRefReady(authRef)) {
150
150
  throw new CliError('未获取到有效宜搭登录态,请先执行 openyida login', {
151
151
  code: 'NEED_LOGIN',
152
152
  });
@@ -154,12 +154,7 @@ function getAuthRef(options = {}) {
154
154
  return authRef;
155
155
  }
156
156
 
157
- function getCookieValue(authRef, name) {
158
- const matched = (authRef.cookies || []).filter(cookie => cookie.name === name);
159
- return matched.length ? matched[0].value : '';
160
- }
161
-
162
- function inferAppType(options, authRef) {
157
+ function inferAppType(options) {
163
158
  if (options.appType) {
164
159
  return options.appType;
165
160
  }
@@ -173,11 +168,11 @@ function inferAppType(options, authRef) {
173
168
  return config.appType;
174
169
  }
175
170
  } catch {
176
- // ignore invalid local config and continue with cookie fallback
171
+ // ignore invalid local config and continue with explicit appType validation
177
172
  }
178
173
  }
179
174
 
180
- return getCookieValue(authRef, 'tianshu_app_type');
175
+ return '';
181
176
  }
182
177
 
183
178
  function getSuccessContent(response, fallbackMessage, code = 'AI_REQUEST_FAILED') {
@@ -334,7 +329,7 @@ async function uploadImageForAI(filePath, options, authRef) {
334
329
  });
335
330
  }
336
331
 
337
- const appType = inferAppType(options, authRef);
332
+ const appType = inferAppType(options);
338
333
  if (!appType) {
339
334
  throw new CliError('上传图片需要 appType,请传入 --app-type APP_XXX', {
340
335
  code: 'AI_IMAGE_APP_TYPE_REQUIRED',
@@ -273,8 +273,8 @@ function compileCanvasLocal(source) {
273
273
  }
274
274
 
275
275
  /**
276
- * 兼容既有调用方(publish.js `await compileCanvas(src, { cookies })`)的异步入口。
277
- * 本地编译不需要 cookies/endpoint,options 保留但忽略。
276
+ * 兼容既有调用方传入 options 的异步入口。
277
+ * 本地编译不需要 endpoint,options 保留但忽略。
278
278
  * @param {string} source
279
279
  * @param {object} [options] 兼容占位,未使用
280
280
  * @returns {Promise<{ runtimeCode: string, importedModules: string }>}
@@ -10,12 +10,10 @@ const fs = require('fs');
10
10
  const path = require('path');
11
11
  const querystring = require('querystring');
12
12
  const {
13
- loadCookieData,
14
- triggerLogin,
15
- resolveBaseUrl,
16
13
  httpPost,
17
14
  requestWithAutoLogin,
18
15
  } = require('../core/utils');
16
+ const { createAuthRef } = require('../core/yida-client');
19
17
  const { t } = require('../core/i18n');
20
18
  const { buildYidaI18n, normalizeYidaLocale, resolveContentLocale } = require('../core/yida-i18n');
21
19
  const { parseOpenOption, withBrowserHandoff } = require('../core/browser-handoff');
@@ -232,18 +230,7 @@ async function run(args) {
232
230
 
233
231
  // Step 1: 读取登录态
234
232
  step(1, t('common.step_login', 1));
235
- let cookieData = loadCookieData();
236
- if (!cookieData) {
237
- info(t('common.login_no_cache'));
238
- cookieData = triggerLogin();
239
- }
240
-
241
- const authRef = {
242
- csrfToken: cookieData.csrf_token,
243
- cookies: cookieData.cookies,
244
- baseUrl: resolveBaseUrl(cookieData),
245
- cookieData,
246
- };
233
+ const authRef = createAuthRef();
247
234
  chalkSuccess(t('common.login_ready', authRef.baseUrl));
248
235
 
249
236
  const contentLocale = resolveContentLocale({ locale: params.locale, baseUrl: authRef.baseUrl });
@@ -260,8 +247,7 @@ async function run(args) {
260
247
  const corpConfig = await httpPost(
261
248
  authRef.baseUrl,
262
249
  `/query/exclusive/queryCorpAppConfig.json?_api=Global.queryCorpAppConfig&_mock=false&_csrf_token=${authRef.csrfToken}&_locale_time_zone_offset=28800000&_stamp=${Date.now()}`,
263
- '',
264
- authRef.cookies
250
+ ''
265
251
  );
266
252
  if (corpConfig && corpConfig.content) {
267
253
  if (corpConfig.content.forceExclusiveDb === 'y') {openExclusive = 'y';}
@@ -289,14 +275,14 @@ async function run(args) {
289
275
  openExclusiveUnit: 'n',
290
276
  group: 'ALL',
291
277
  });
292
- return httpPost(auth.baseUrl, '/query/app/registerApp.json', postData, auth.cookies);
278
+ return httpPost(auth.baseUrl, '/query/app/registerApp.json', postData);
293
279
  }, authRef);
294
280
 
295
281
  // 输出结果
296
282
  if (response && response.success && response.content) {
297
283
  const appType = response.content;
298
284
  const appUrl = `${authRef.baseUrl}/${appType}/admin`;
299
- const corpId = authRef.cookieData.corp_id || '';
285
+ const corpId = authRef.corpId || (authRef.authData && authRef.authData.corp_id) || '';
300
286
 
301
287
  chalkResult(true, t('create_app.success'), [
302
288
  ['appType', appType],