openyida 2026.4.1 → 2026.4.2-beta.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.
@@ -148,10 +148,7 @@ class EnvironmentChecker {
148
148
  this.checkNodeVersion(),
149
149
  this.checkNpmVersion(),
150
150
  this.checkPlaywrightInstalled(),
151
- this.checkGhCli(),
152
- this.checkGhAuth(),
153
151
  this.checkConfig(),
154
- this.checkSkills(),
155
152
  this.checkLoginStatus(),
156
153
  await this.checkNetwork(),
157
154
  ];
@@ -220,51 +217,6 @@ class EnvironmentChecker {
220
217
  }
221
218
  }
222
219
 
223
- checkGhCli() {
224
- try {
225
- const ghVersion = execSync('gh --version 2>&1', { encoding: 'utf-8' }).split('\n')[0].trim();
226
- return {
227
- id: 'env-gh',
228
- label: ghVersion,
229
- passed: true,
230
- severity: Severity.INFO,
231
- fixType: null,
232
- };
233
- } catch {
234
- return {
235
- id: 'env-gh',
236
- label: 'gh CLI 安装检测',
237
- passed: false,
238
- severity: Severity.ERROR,
239
- message: 'gh CLI 未安装,请安装:https://cli.github.com/',
240
- fixType: null,
241
- };
242
- }
243
- }
244
-
245
- checkGhAuth() {
246
- try {
247
- execSync('gh auth status 2>&1', { encoding: 'utf-8', stdio: 'pipe' });
248
- return {
249
- id: 'env-gh-auth',
250
- label: 'gh CLI 已登录',
251
- passed: true,
252
- severity: Severity.INFO,
253
- fixType: null,
254
- };
255
- } catch {
256
- return {
257
- id: 'env-gh-auth',
258
- label: 'gh CLI 登录状态',
259
- passed: false,
260
- severity: Severity.WARNING,
261
- message: 'gh CLI 未登录',
262
- fixType: FixType.COMMAND,
263
- fixCommand: 'gh auth login',
264
- };
265
- }
266
- }
267
-
268
220
  checkConfig() {
269
221
  const configPath = path.join(this.projectRoot, 'config.json');
270
222
  if (!fs.existsSync(configPath)) {
@@ -301,30 +253,6 @@ class EnvironmentChecker {
301
253
  }
302
254
  }
303
255
 
304
- checkSkills() {
305
- const skillsPath = path.join(this.projectRoot, '.claude', 'skills', 'skills');
306
- if (fs.existsSync(skillsPath)) {
307
- const skills = fs.readdirSync(skillsPath).filter((name) =>
308
- fs.statSync(path.join(skillsPath, name)).isDirectory()
309
- );
310
- return {
311
- id: 'env-skills',
312
- label: `Skills 已安装(${skills.length} 个)`,
313
- passed: true,
314
- severity: Severity.INFO,
315
- fixType: null,
316
- };
317
- }
318
- return {
319
- id: 'env-skills',
320
- label: 'Skills 安装检测',
321
- passed: false,
322
- severity: Severity.WARNING,
323
- message: 'Skills 未安装,运行 bash install-skills.sh 安装',
324
- fixType: FixType.MANUAL,
325
- };
326
- }
327
-
328
256
  checkLoginStatus() {
329
257
  const cookiePath = path.join(this.projectRoot, '.cache', 'cookies.json');
330
258
  if (!fs.existsSync(cookiePath)) {
@@ -399,6 +327,121 @@ class EnvironmentChecker {
399
327
  }
400
328
  }
401
329
 
330
+ // ── VersionChecker ───────────────────────────────────
331
+
332
+ /**
333
+ * openyida 版本检查器。
334
+ * 检测当前安装版本是否与 SKILL.md 中的 metadata.version 一致,
335
+ * 不一致时在 --fix 模式下自动升级到最新版。
336
+ */
337
+ class VersionChecker {
338
+ constructor({ projectRoot } = {}) {
339
+ this.projectRoot = projectRoot || findProjectRoot();
340
+ }
341
+
342
+ /**
343
+ * 读取 SKILL.md 中 metadata.version 字段。
344
+ * @returns {string|null}
345
+ */
346
+ readSkillVersion() {
347
+ const skillPaths = [
348
+ path.join(this.projectRoot, 'yida-skills', 'SKILL.md'),
349
+ path.join(require('os').homedir(), '.claude', 'yida-skills', 'SKILL.md'),
350
+ path.join(require('os').homedir(), '.aone_copilot', 'yida-skills', 'SKILL.md'),
351
+ ];
352
+ for (const skillPath of skillPaths) {
353
+ if (!fs.existsSync(skillPath)) {continue;}
354
+ const content = fs.readFileSync(skillPath, 'utf-8');
355
+ const match = content.match(/^metadata:\s*\n\s*version:\s*(.+)$/m);
356
+ if (match) {return match[1].trim();}
357
+ }
358
+ return null;
359
+ }
360
+
361
+ /**
362
+ * 获取当前安装的 openyida 版本。
363
+ * @returns {string|null}
364
+ */
365
+ getInstalledVersion() {
366
+ try {
367
+ return execSync('openyida -v 2>/dev/null', { encoding: 'utf-8' }).trim();
368
+ } catch {
369
+ return null;
370
+ }
371
+ }
372
+
373
+ async check() {
374
+ const skillVersion = this.readSkillVersion();
375
+ const installedVersion = this.getInstalledVersion();
376
+
377
+ if (!skillVersion) {
378
+ return [{
379
+ id: 'version-skill',
380
+ label: 'openyida 版本检测',
381
+ passed: true,
382
+ severity: Severity.INFO,
383
+ message: '无法读取 SKILL.md 版本,跳过版本比对',
384
+ fixType: null,
385
+ }];
386
+ }
387
+
388
+ if (!installedVersion) {
389
+ return [{
390
+ id: 'version-installed',
391
+ label: 'openyida 版本检测',
392
+ passed: false,
393
+ severity: Severity.ERROR,
394
+ message: 'openyida 未安装,请运行:npm install -g openyida',
395
+ fixType: FixType.COMMAND,
396
+ fixCommand: 'npm install -g openyida@latest',
397
+ }];
398
+ }
399
+
400
+ // 比较主版本号(忽略 -beta.x 等预发布后缀)
401
+ const installedMain = installedVersion.replace(/-.+$/, '');
402
+ const skillMain = skillVersion.replace(/-.+$/, '');
403
+ const passed = installedMain === skillMain;
404
+
405
+ return [{
406
+ id: 'version-match',
407
+ label: `openyida 版本:${installedVersion}(SKILL 期望:${skillVersion})`,
408
+ passed,
409
+ severity: passed ? Severity.INFO : Severity.WARNING,
410
+ message: passed ? null : `版本不匹配,建议升级到最新版`,
411
+ fixType: passed ? null : FixType.COMMAND,
412
+ fixCommand: passed ? null : 'npm install -g openyida@latest',
413
+ }];
414
+ }
415
+ }
416
+
417
+ // ── ProjectInitChecker ────────────────────────────────
418
+
419
+ /**
420
+ * project 工作目录初始化检查器。
421
+ * 检测 project/ 目录是否存在,不存在时在 --fix 模式下自动执行 openyida copy。
422
+ */
423
+ class ProjectInitChecker {
424
+ constructor({ projectRoot } = {}) {
425
+ this.projectRoot = projectRoot || findProjectRoot();
426
+ }
427
+
428
+ async check() {
429
+ const projectDir = path.join(this.projectRoot, 'project');
430
+ const configPath = path.join(projectDir, 'config.json');
431
+ const passed = fs.existsSync(projectDir) && fs.existsSync(configPath);
432
+
433
+ return [{
434
+ id: 'project-init',
435
+ label: passed ? 'project/ 工作目录已初始化' : `project/ 工作目录检测(检测路径:${projectDir})`,
436
+ passed,
437
+ severity: passed ? Severity.INFO : Severity.WARNING,
438
+ message: passed ? null : 'project/ 目录未初始化,将自动执行 openyida copy',
439
+ fixType: passed ? null : FixType.COMMAND,
440
+ fixCommand: passed ? null : 'openyida copy',
441
+ }];
442
+ }
443
+ }
444
+
402
445
  // ── ApplicationChecker ────────────────────────────────
403
446
 
404
447
  /**
@@ -1410,6 +1453,8 @@ async function run(args) {
1410
1453
 
1411
1454
  // ── 主诊断流程 ──
1412
1455
  const engine = new DiagnosticEngine({ projectRoot });
1456
+ engine.registerChecker(new VersionChecker({ projectRoot }));
1457
+ engine.registerChecker(new ProjectInitChecker({ projectRoot }));
1413
1458
  engine.registerChecker(new EnvironmentChecker({ projectRoot }));
1414
1459
  engine.registerChecker(new ApplicationChecker({ projectRoot, appId: options.app }));
1415
1460
 
@@ -1451,6 +1496,8 @@ async function run(args) {
1451
1496
 
1452
1497
  module.exports = {
1453
1498
  DiagnosticEngine,
1499
+ VersionChecker,
1500
+ ProjectInitChecker,
1454
1501
  EnvironmentChecker,
1455
1502
  ApplicationChecker,
1456
1503
  FixEngine,
package/lib/core/utils.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * findProjectRoot() - 查找项目根目录(兼容悟空环境)
6
6
  * extractInfoFromCookies() - 从 Cookie 列表中提取 csrf_token / corp_id / user_id
7
7
  * loadCookieData() - 读取 .cache/cookies.json 登录态缓存
8
- * triggerLogin() - 触发登录(自动区分标准/悟空环境)
8
+ * triggerLogin() - 触发登录
9
9
  * refreshCsrfToken() - 刷新 csrf_token
10
10
  * resolveBaseUrl() - 从 cookieData 中解析 base_url
11
11
  * isLoginExpired() - 检测响应体是否表示登录过期
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openyida",
3
- "version": "2026.04.01",
3
+ "version": "2026.04.02-beta.1",
4
4
  "description": "OpenYida CLI - 宜搭低代码 AI 开发工具(安装即用,零配置)",
5
5
  "bin": {
6
6
  "openyida": "./bin/yida.js",
@@ -47,19 +47,10 @@
47
47
  },
48
48
  "homepage": "https://github.com/openyida/openyida#readme",
49
49
  "dependencies": {
50
- "@ai-sdk/anthropic": "^3.0.64",
51
- "@ai-sdk/openai": "^3.0.49",
52
50
  "@babel/standalone": "^7.15.1",
53
- "ai": "^6.0.141",
54
- "chalk": "^4.1.2",
55
- "dotenv": "^16.4.0",
56
- "express": "^4.21.0",
57
- "ora": "^5.4.1",
58
51
  "playwright": "^1.58.2",
59
52
  "qrcode": "^1.5.4",
60
- "uglify-js": "^3.19.3",
61
- "ws": "^8.18.0",
62
- "zod": "^3.23.0"
53
+ "uglify-js": "^3.19.3"
63
54
  },
64
55
  "devDependencies": {
65
56
  "eslint": "^8.50.0",
@@ -140,7 +140,39 @@ safeExec(() => {
140
140
  }
141
141
  });
142
142
 
143
- // ── 3. 首次安装欢迎引导 ──────────────────────────────────────────────
143
+ // ── 3. Chromium 按需安装 ─────────────────────────────────────────────
144
+
145
+ safeExec(() => {
146
+ const { execSync } = require('child_process');
147
+
148
+ let chromiumPath = null;
149
+ try {
150
+ // 通过 playwright 内置 API 获取 Chromium 可执行文件路径
151
+ const { chromium } = require('playwright');
152
+ chromiumPath = chromium.executablePath();
153
+ } catch {
154
+ // playwright 未安装或 API 不可用,跳过
155
+ return;
156
+ }
157
+
158
+ if (chromiumPath && fs.existsSync(chromiumPath)) {
159
+ // Chromium 已存在,无需重复安装
160
+ return;
161
+ }
162
+
163
+ console.log('\n 🌐 正在安装 Chromium 浏览器(首次安装需要下载,请稍候)...');
164
+ try {
165
+ execSync('npx playwright install chromium', {
166
+ stdio: 'inherit',
167
+ timeout: 300_000, // 5 分钟超时
168
+ });
169
+ console.log(' ✅ Chromium 安装完成!\n');
170
+ } catch {
171
+ console.warn(' ⚠️ Chromium 安装失败,可手动执行:npx playwright install chromium\n');
172
+ }
173
+ });
174
+
175
+ // ── 4. 首次安装欢迎引导 ──────────────────────────────────────────────
144
176
 
145
177
  safeExec(() => {
146
178
  const FIRST_INSTALL_FLAG = path.join(HOME_DIR, '.openyida', 'installed');
@@ -4,7 +4,7 @@ description: >
4
4
  宜搭低代码平台 AI 开发入口。一句话生成完整应用:创建应用、表单设计、自定义页面、流程配置、数据管理。
5
5
  当用户提到"宜搭"、"yida"、"低代码"、"创建应用"、"创建表单"、"发布页面"、"搭建"、"系统"、"应用"时触发。
6
6
  metadata:
7
- version: 2026-03-30
7
+ version: 2026.04.02-beta.1
8
8
  ---
9
9
 
10
10
  # 宜搭 AI 应用开发指南
@@ -30,11 +30,11 @@ metadata:
30
30
  ## ⚡ 首要步骤(每次必须先执行)
31
31
 
32
32
  ```bash
33
- # 1. 检测 AI 工具环境和登录态
34
- openyida env
33
+ # 1. 确保 openyida 已安装(未安装则自动安装)
34
+ openyida -v 2>/dev/null || npm install -g openyida@latest
35
35
 
36
- # 2. 确认 project/ 目录存在,不存在则初始化
37
- openyida copy
36
+ # 2. 一键诊断并自动修复:版本升级 + 环境检测 + project 目录初始化
37
+ openyida doctor --fix
38
38
  ```
39
39
 
40
40
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yida-login
3
- description: 宜搭登录态管理。支持标准环境扫码登录和悟空环境 CDP 提取 Cookie,Cookie 持久化到 .cache/cookies.json。
3
+ description: 宜搭登录态管理。扫码登录,Cookie 持久化到 .cache/cookies.json。
4
4
  ---
5
5
 
6
6
  # 宜搭登录态管理
@@ -8,13 +8,11 @@ description: 宜搭登录态管理。支持标准环境扫码登录和悟空环
8
8
  ## 严格禁止 (NEVER DO)
9
9
 
10
10
  - 不要在代码中硬编码 Cookie 或凭证,Cookie 必须通过 `openyida login` 命令获取并缓存到 `.cache/cookies.json`
11
- - 不要在悟空环境直接运行 `openyida login`(无 `--wukong` 参数),必须先用悟空内置浏览器打开登录页完成扫码
12
11
  - 不要在 Cookie 失效时手动修改 `.cache/cookies.json`,必须重新执行登录流程
13
12
 
14
13
  ## 严格要求 (MUST DO)
15
14
 
16
15
  - 执行任何宜搭操作前,必须先运行 `openyida env` 确认环境和登录态
17
- - 悟空环境必须按步骤:① 读取 `config.json` 获取 `loginUrl` → ② 用悟空浏览器打开 → ③ 扫码后执行 `openyida login --wukong`
18
16
  - Cookie 失效时,重新登录后必须验证新 Cookie 可用(运行任意查询命令确认)
19
17
 
20
18
  ## 适用场景
@@ -23,7 +21,6 @@ description: 宜搭登录态管理。支持标准环境扫码登录和悟空环
23
21
  |---------|---------|
24
22
  | 首次使用或 Cookie 失效 | 其他命令报 401/未登录错误时自动触发 |
25
23
  | 切换账号/组织 | 先 `openyida logout` 再重新登录 |
26
- | 悟空环境登录 | 必须手动按步骤操作 |
27
24
 
28
25
  ---
29
26
 
@@ -38,18 +35,6 @@ description: 宜搭登录态管理。支持标准环境扫码登录和悟空环
38
35
  openyida login
39
36
  ```
40
37
 
41
- ### 悟空环境
42
-
43
- > ⚠️ 悟空环境必须按以下步骤操作,不能直接运行脚本。
44
-
45
- 1. 读取 `config.json` 获取 `loginUrl`
46
- 2. 用悟空内置浏览器打开登录页面,等待用户完成扫码
47
- 3. 扫码完成后执行:
48
-
49
- ```bash
50
- openyida login --wukong
51
- ```
52
-
53
38
  ## 输出
54
39
 
55
40
  ```json
@@ -62,7 +47,7 @@ openyida login --wukong
62
47
 
63
48
  各命令通过响应体 `errorCode` 自动处理登录态异常:
64
49
 
65
- | errorCode | 含义 | 标准环境 | 悟空环境 |
66
- |-----------|------|---------|----------|
67
- | `TIANSHU_000030` | CSRF Token 过期 | 自动无头刷新 | `openyida login --wukong` |
68
- | `307` | Cookie 失效 | 自动重新登录 | `openyida login --wukong` |
50
+ | errorCode | 含义 | 处理方式 |
51
+ |-----------|------|---------|
52
+ | `TIANSHU_000030` | CSRF Token 过期 | 自动无头刷新 |
53
+ | `307` | Cookie 失效 | 自动重新登录 |