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.
- package/lib/core/doctor.js +119 -72
- package/lib/core/utils.js +1 -1
- package/package.json +2 -11
- package/scripts/postinstall.js +33 -1
- package/yida-skills/SKILL.md +5 -5
- package/yida-skills/skills/yida-login/SKILL.md +5 -20
package/lib/core/doctor.js
CHANGED
|
@@ -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.
|
|
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",
|
package/scripts/postinstall.js
CHANGED
|
@@ -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');
|
package/yida-skills/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
宜搭低代码平台 AI 开发入口。一句话生成完整应用:创建应用、表单设计、自定义页面、流程配置、数据管理。
|
|
5
5
|
当用户提到"宜搭"、"yida"、"低代码"、"创建应用"、"创建表单"、"发布页面"、"搭建"、"系统"、"应用"时触发。
|
|
6
6
|
metadata:
|
|
7
|
-
version: 2026-
|
|
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.
|
|
34
|
-
openyida
|
|
33
|
+
# 1. 确保 openyida 已安装(未安装则自动安装)
|
|
34
|
+
openyida -v 2>/dev/null || npm install -g openyida@latest
|
|
35
35
|
|
|
36
|
-
# 2.
|
|
37
|
-
openyida
|
|
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:
|
|
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 过期 | 自动无头刷新 |
|
|
68
|
-
| `307` | Cookie 失效 | 自动重新登录 |
|
|
50
|
+
| errorCode | 含义 | 处理方式 |
|
|
51
|
+
|-----------|------|---------|
|
|
52
|
+
| `TIANSHU_000030` | CSRF Token 过期 | 自动无头刷新 |
|
|
53
|
+
| `307` | Cookie 失效 | 自动重新登录 |
|