@wendongfly/myhi 1.3.54 → 1.3.56
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/dist/builtin-skills/e2e.md +14 -0
- package/dist/builtin-skills/pw-install.md +14 -0
- package/dist/builtin-skills/seed.md +21 -0
- package/dist/chat.html +41 -13
- package/dist/index.js +14 -14
- package/dist/index.min.js +96 -96
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# E2E 端到端测试(Playwright)
|
|
2
|
+
|
|
3
|
+
使用 Playwright 对指定功能或页面进行自动化端到端测试。
|
|
4
|
+
|
|
5
|
+
执行步骤:
|
|
6
|
+
1. 确认 Playwright 已安装,若未安装先完成安装(检查 @playwright/test + 浏览器)
|
|
7
|
+
2. 了解测试目标:应用 URL、模块名称、核心用户流程
|
|
8
|
+
3. 分析页面结构(优先用 getByRole / getByLabel / getByText 定位,避免脆弱 CSS 选择器)
|
|
9
|
+
4. 编写测试用例,覆盖:主流程(happy path)+ 关键边界(表单校验、权限拦截、空状态)
|
|
10
|
+
5. 运行测试:npx playwright test --reporter=list
|
|
11
|
+
6. 失败时:查看截图和 trace,分析根因,修复后重跑
|
|
12
|
+
7. 输出测试报告:通过/失败数量 + 覆盖的功能点列表
|
|
13
|
+
|
|
14
|
+
目标模块或说明:$ARGUMENTS
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# 检查并安装 Playwright
|
|
2
|
+
|
|
3
|
+
检测当前项目的 Playwright 安装状态,按需完成安装和配置。
|
|
4
|
+
|
|
5
|
+
执行步骤:
|
|
6
|
+
1. 识别包管理器(检查 pnpm-lock.yaml / yarn.lock / package-lock.json)
|
|
7
|
+
2. 检查 `@playwright/test` 是否已在 devDependencies 中
|
|
8
|
+
3. 若未安装:用检测到的包管理器安装 `@playwright/test`
|
|
9
|
+
4. 检查浏览器:运行 `npx playwright install --dry-run`,若缺少则安装 chromium
|
|
10
|
+
5. 检查是否有 `playwright.config.{ts,js}`,若无则根据项目框架(Vite/Next/Nuxt 等)生成合适的配置
|
|
11
|
+
6. 验证安装:运行一个最简示例测试确认环境正常
|
|
12
|
+
7. 输出可用的测试命令清单
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 插入拟真测试数据
|
|
2
|
+
|
|
3
|
+
通过 Playwright UI 操作或直接 API 调用,为指定模块批量写入符合真实场景的测试数据。
|
|
4
|
+
|
|
5
|
+
数据生成规范(中国用户习惯):
|
|
6
|
+
- 姓名:常用汉字姓氏 + 名(2-3字,自然感强)
|
|
7
|
+
- 手机:1xx 开头,用 130-139 / 150-159 / 180-189 等真实号段
|
|
8
|
+
- 邮箱:拼音+数字 @ qq.com / 163.com / gmail.com
|
|
9
|
+
- 地址:省市区+街道+门牌,层级完整真实
|
|
10
|
+
- 身份证:区域码正确+真实生日+合法顺序码(仅测试用途)
|
|
11
|
+
- 金额:符合业务量级(几十到几千元,非整数)
|
|
12
|
+
- 日期:最近 1 年内随机,格式与系统保持一致
|
|
13
|
+
|
|
14
|
+
执行步骤:
|
|
15
|
+
1. 分析目标模块的字段要求(查看表单 / API 接口 / 数据库 schema)
|
|
16
|
+
2. 生成 15-20 条完整拟真记录(多样性:不同年龄段、城市、金额区间)
|
|
17
|
+
3. 选择最高效写入方式:API 直调(首选)→ Playwright UI 填表 → 直接 SQL
|
|
18
|
+
4. 批量执行写入,遇错记录并继续(不中断整批)
|
|
19
|
+
5. 验证:查询条数与关键字段,确认数据已成功入库
|
|
20
|
+
|
|
21
|
+
目标模块:$ARGUMENTS
|
package/dist/chat.html
CHANGED
|
@@ -350,6 +350,7 @@
|
|
|
350
350
|
<button class="sk sk-claude" onclick="openGitSheet()" style="color:#3fb950">提交</button>
|
|
351
351
|
<button class="sk sk-claude" onclick="showMemory()">记忆</button>
|
|
352
352
|
<button class="sk sk-claude" onclick="openSkillSheet()" style="color:#9d5cf5">技能</button>
|
|
353
|
+
<span id="sk-builtin-skills"></span>
|
|
353
354
|
<span id="sk-custom-skills"></span>
|
|
354
355
|
</div>
|
|
355
356
|
</div>
|
|
@@ -2403,16 +2404,23 @@
|
|
|
2403
2404
|
try {
|
|
2404
2405
|
const resp = await fetch(`/api/skills?sessionId=${SESSION_ID}`);
|
|
2405
2406
|
const data = await resp.json();
|
|
2406
|
-
const container = document.getElementById('sk-custom-skills');
|
|
2407
2407
|
_customSkills = data.skills || [];
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2408
|
+
const builtins = _customSkills.filter(s => s.source === 'builtin');
|
|
2409
|
+
const customs = _customSkills.filter(s => s.source !== 'builtin');
|
|
2410
|
+
// 内置技能:始终逐个显示(青绿色)
|
|
2411
|
+
const builtinEl = document.getElementById('sk-builtin-skills');
|
|
2412
|
+
builtinEl.innerHTML = builtins.map(s =>
|
|
2413
|
+
`<button class="sk sk-claude" onclick="runSkill('${escHtml(s.name)}')" title="${escHtml(s.desc)}" style="color:#26a69a">/${escHtml(s.name)}</button>`
|
|
2414
|
+
).join('');
|
|
2415
|
+
// 用户/项目技能:≤3 显示按钮;>3 折叠
|
|
2416
|
+
const customEl = document.getElementById('sk-custom-skills');
|
|
2417
|
+
if (!customs.length) { customEl.innerHTML = ''; return; }
|
|
2418
|
+
if (customs.length <= 3) {
|
|
2419
|
+
customEl.innerHTML = customs.map(s =>
|
|
2412
2420
|
`<button class="sk sk-claude" onclick="runSkill('${escHtml(s.name)}')" title="${escHtml(s.desc)}" style="color:#9d5cf5">/${escHtml(s.name)}</button>`
|
|
2413
2421
|
).join('');
|
|
2414
2422
|
} else {
|
|
2415
|
-
|
|
2423
|
+
customEl.innerHTML = `<button class="sk sk-claude" onclick="openCmdSheet()" style="color:#9d5cf5">/命令 (${customs.length})</button>`;
|
|
2416
2424
|
}
|
|
2417
2425
|
} catch {}
|
|
2418
2426
|
}
|
|
@@ -2444,15 +2452,33 @@
|
|
|
2444
2452
|
document.getElementById('skill-run-sheet').classList.remove('open');
|
|
2445
2453
|
_pendingSkillName = null;
|
|
2446
2454
|
};
|
|
2447
|
-
window.submitSkillRun = function() {
|
|
2455
|
+
window.submitSkillRun = async function() {
|
|
2448
2456
|
if (!_pendingSkillName) return;
|
|
2449
2457
|
const args = document.getElementById('skill-run-input').value.trim();
|
|
2450
2458
|
const name = _pendingSkillName;
|
|
2459
|
+
const skill = _customSkills.find(s => s.name === name);
|
|
2451
2460
|
closeSkillRunSheet();
|
|
2452
2461
|
if (!isController && canTakeControl()) socket.emit('take-control', { sessionId: SESSION_ID });
|
|
2453
|
-
const
|
|
2454
|
-
|
|
2455
|
-
|
|
2462
|
+
const displayCmd = args ? `/${name} ${args}` : `/${name}`;
|
|
2463
|
+
if (skill?.source === 'builtin') {
|
|
2464
|
+
// 内置技能不在 .claude/commands/ 里,需拉取内容后直接发送为 prompt
|
|
2465
|
+
try {
|
|
2466
|
+
const resp = await fetch(`/api/skills/content?name=${encodeURIComponent(name)}&sessionId=${SESSION_ID}`);
|
|
2467
|
+
const data = await resp.json();
|
|
2468
|
+
let prompt = data.content || displayCmd;
|
|
2469
|
+
if (args) {
|
|
2470
|
+
prompt = prompt.replace(/\$ARGUMENTS/g, args);
|
|
2471
|
+
} else {
|
|
2472
|
+
prompt = prompt.replace(/[^\n]*\$ARGUMENTS[^\n]*/g, '').replace(/\n{3,}/g, '\n\n').trim();
|
|
2473
|
+
}
|
|
2474
|
+
socket.emit('agent:query', { prompt });
|
|
2475
|
+
} catch {
|
|
2476
|
+
socket.emit('agent:query', { prompt: displayCmd });
|
|
2477
|
+
}
|
|
2478
|
+
} else {
|
|
2479
|
+
socket.emit('agent:query', { prompt: displayCmd });
|
|
2480
|
+
}
|
|
2481
|
+
addInputMessage(displayCmd);
|
|
2456
2482
|
showThinking();
|
|
2457
2483
|
};
|
|
2458
2484
|
window.openCmdSheet = function() {
|
|
@@ -2462,8 +2488,9 @@
|
|
|
2462
2488
|
filterInp.value = '';
|
|
2463
2489
|
const render = (keyword = '') => {
|
|
2464
2490
|
const kw = keyword.toLowerCase();
|
|
2491
|
+
// 命令面板只列用户/项目技能(内置技能始终在快捷栏直接显示)
|
|
2465
2492
|
const filtered = _customSkills.filter(s =>
|
|
2466
|
-
!kw || s.name.toLowerCase().includes(kw) || (s.desc || '').toLowerCase().includes(kw));
|
|
2493
|
+
s.source !== 'builtin' && (!kw || s.name.toLowerCase().includes(kw) || (s.desc || '').toLowerCase().includes(kw)));
|
|
2467
2494
|
listEl.innerHTML = filtered.length
|
|
2468
2495
|
? filtered.map(s => `<div class="action-sheet-item" onclick="runSkillAndClose('${escHtml(s.name)}')">
|
|
2469
2496
|
<div><div style="color:#d2a8ff">/${escHtml(s.name)}</div>${s.desc ? `<div class="desc">${escHtml(s.desc)}</div>` : ''}</div>
|
|
@@ -2505,11 +2532,12 @@
|
|
|
2505
2532
|
try {
|
|
2506
2533
|
const resp = await fetch(`/api/skills?sessionId=${SESSION_ID}&detail=1`);
|
|
2507
2534
|
const data = await resp.json();
|
|
2508
|
-
|
|
2535
|
+
const editable = (data.skills || []).filter(s => s.source !== 'builtin');
|
|
2536
|
+
if (!editable.length) {
|
|
2509
2537
|
listEl.innerHTML = '<div style="text-align:center;color:#8b949e;padding:2rem 0">暂无技能,点击右上角 + 新建</div>';
|
|
2510
2538
|
return;
|
|
2511
2539
|
}
|
|
2512
|
-
listEl.innerHTML =
|
|
2540
|
+
listEl.innerHTML = editable.map(s => `
|
|
2513
2541
|
<div class="action-sheet-item" style="gap:0.5rem">
|
|
2514
2542
|
<div style="min-width:0;flex:1;cursor:pointer" onclick="editSkill('${escHtml(s.name)}','${escHtml(s.source)}')">
|
|
2515
2543
|
<div style="color:#9d5cf5;font-weight:500">/${escHtml(s.name)}</div>
|