helixlife-v5-cli 1.2.4 → 1.2.6
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.
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 综述工作台(jova)· 统一入口(WorkBuddy 默认只用本脚本)
|
|
3
|
-
*
|
|
4
|
-
* 改 userIntent 一行;自动按 pathname 路由。
|
|
5
|
-
* outline 页「扩写前言」等:本脚本内直接执行(hover → 编辑,禁止添加子级)。
|
|
6
|
-
*
|
|
7
|
-
* 用法:
|
|
8
|
-
* helixlife-v5-cli run-code --filename=scripts/workbench-jova-dispatch.js
|
|
9
|
-
*/
|
|
10
|
-
async page => {
|
|
11
|
-
// ── Agent 只改这一行(原样粘贴用户说法,如「扩写前言」)──
|
|
12
|
-
const userIntent = '扩写前言';
|
|
13
|
-
const action = null; // proofread/writing 子流程用;outline 忽略
|
|
14
|
-
|
|
15
|
-
const pathname = new URL(page.url()).pathname;
|
|
16
|
-
const FORBIDDEN_BUTTONS = ['添加子级', '添加同级'];
|
|
17
|
-
|
|
18
|
-
const outlineVerbs = ['扩写', '精简', '改写', '润色', '重写', '优化'];
|
|
19
|
-
const isOutlineVerbIntent = outlineVerbs.some(v => userIntent.trim().startsWith(v));
|
|
20
|
-
const isProofreadIntent = /^校对/.test(userIntent.trim());
|
|
21
|
-
|
|
22
|
-
function parseOutlineIntent(raw) {
|
|
23
|
-
const text = raw.trim();
|
|
24
|
-
for (const verb of outlineVerbs) {
|
|
25
|
-
if (text.startsWith(verb)) {
|
|
26
|
-
const title = text.slice(verb.length).trim();
|
|
27
|
-
if (title) return { nodeTitle: title, userRequirement: verb };
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return { nodeTitle: '前言', userRequirement: text };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function normalizeWritingIntent(raw) {
|
|
34
|
-
const text = raw.trim();
|
|
35
|
-
const tools = ['校对', '文风', '润色', '降重', '翻译', '改写', '扩写', '缩写', '文献列表'];
|
|
36
|
-
for (const tool of tools) {
|
|
37
|
-
if (text === tool || text.startsWith(`${tool} `) || text.startsWith(tool)) {
|
|
38
|
-
const sectionTitle = text.slice(tool.length).trim();
|
|
39
|
-
return sectionTitle ? `${tool} ${sectionTitle}` : tool;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return text;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (!pathname.includes('/workbench/jova/')) {
|
|
46
|
-
return {
|
|
47
|
-
ok: false,
|
|
48
|
-
userIntent,
|
|
49
|
-
pathname,
|
|
50
|
-
forbiddenNeverClick: FORBIDDEN_BUTTONS,
|
|
51
|
-
reason: '当前不在综述工作台 jova 流程页',
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// ── outline:扩写/润色/精简 + 章节(禁止添加子级)──
|
|
56
|
-
if (pathname.includes('/jova/outline') && isOutlineVerbIntent) {
|
|
57
|
-
const { nodeTitle, userRequirement } = parseOutlineIntent(userIntent);
|
|
58
|
-
const main = page.locator('main');
|
|
59
|
-
|
|
60
|
-
async function resetEditingState() {
|
|
61
|
-
const closeIcons = main.getByRole('img', { name: 'close' });
|
|
62
|
-
for (let i = 0; i < (await closeIcons.count()); i++) {
|
|
63
|
-
const icon = closeIcons.nth(i);
|
|
64
|
-
if (await icon.isVisible()) {
|
|
65
|
-
await icon.click();
|
|
66
|
-
await page.waitForTimeout(400);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
const cancelReplace = main.getByRole('button', { name: '取 消' });
|
|
70
|
-
if ((await cancelReplace.count()) > 0 && (await cancelReplace.first().isVisible())) {
|
|
71
|
-
await cancelReplace.first().click();
|
|
72
|
-
await page.waitForTimeout(400);
|
|
73
|
-
}
|
|
74
|
-
const saveBtn = main.getByRole('button', { name: '保 存' });
|
|
75
|
-
if ((await saveBtn.count()) > 0 && (await saveBtn.first().isVisible())) {
|
|
76
|
-
await saveBtn.first().click();
|
|
77
|
-
await page.waitForTimeout(400);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function outlineNode(title) {
|
|
82
|
-
const base = title.replace(/[::]\s*$/, '');
|
|
83
|
-
const titleRe = new RegExp(`^${base.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[::]?$`);
|
|
84
|
-
return main
|
|
85
|
-
.locator('[aria-label*="操作区"]')
|
|
86
|
-
.filter({
|
|
87
|
-
has: page.locator(':scope > *').first().filter({ hasText: titleRe }),
|
|
88
|
-
})
|
|
89
|
-
.first();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
await resetEditingState();
|
|
93
|
-
|
|
94
|
-
const opArea = outlineNode(nodeTitle);
|
|
95
|
-
if ((await opArea.count()) === 0) {
|
|
96
|
-
return {
|
|
97
|
-
ok: false,
|
|
98
|
-
route: 'outline',
|
|
99
|
-
userIntent,
|
|
100
|
-
nodeTitle,
|
|
101
|
-
userRequirement,
|
|
102
|
-
forbiddenNeverClick: FORBIDDEN_BUTTONS,
|
|
103
|
-
reason: `未找到提纲节点「${nodeTitle}」`,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
await opArea.hover();
|
|
108
|
-
await page.waitForTimeout(400);
|
|
109
|
-
await opArea.getByRole('button', { name: '编辑' }).click();
|
|
110
|
-
|
|
111
|
-
const regenTitle = main.getByText('重新生成', { exact: true });
|
|
112
|
-
await regenTitle.waitFor({ state: 'visible', timeout: 10000 });
|
|
113
|
-
|
|
114
|
-
const userReqBox = main.getByRole('textbox', { name: '用户需求' });
|
|
115
|
-
await userReqBox.waitFor({ state: 'visible', timeout: 5000 });
|
|
116
|
-
await userReqBox.fill(userRequirement);
|
|
117
|
-
|
|
118
|
-
await main.getByRole('button', { name: '一键生成' }).click();
|
|
119
|
-
const replaceBtn = main.getByRole('button', { name: '替换原文' });
|
|
120
|
-
await replaceBtn.waitFor({ state: 'visible', timeout: 120000 });
|
|
121
|
-
await page.waitForTimeout(800);
|
|
122
|
-
|
|
123
|
-
await replaceBtn.click();
|
|
124
|
-
await main.getByText('是否将本次生成结果替换原文?', { exact: true }).waitFor({ state: 'visible', timeout: 10000 });
|
|
125
|
-
await main.getByRole('button', { name: '确 定' }).click();
|
|
126
|
-
await page.waitForTimeout(800);
|
|
127
|
-
|
|
128
|
-
const saveBtn = main.getByRole('button', { name: '保 存' });
|
|
129
|
-
await saveBtn.waitFor({ state: 'visible', timeout: 10000 });
|
|
130
|
-
await saveBtn.click();
|
|
131
|
-
await page.waitForTimeout(1000);
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
ok: true,
|
|
135
|
-
route: 'outline',
|
|
136
|
-
userIntent,
|
|
137
|
-
nodeTitle,
|
|
138
|
-
userRequirement,
|
|
139
|
-
clickedButton: '编辑',
|
|
140
|
-
forbiddenNeverClick: FORBIDDEN_BUTTONS,
|
|
141
|
-
message: `已通过「编辑→重新生成」完成「${userRequirement}」节点「${nodeTitle}」(未使用添加子级)。`,
|
|
142
|
-
url: page.url(),
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// ── proofread / writing:返回子脚本,仍禁止添加子级 ──
|
|
147
|
-
if (pathname.includes('/jova/proofread') || isProofreadIntent) {
|
|
148
|
-
return {
|
|
149
|
-
ok: false,
|
|
150
|
-
route: 'proofread',
|
|
151
|
-
userIntent,
|
|
152
|
-
pathname,
|
|
153
|
-
forbiddenNeverClick: FORBIDDEN_BUTTONS,
|
|
154
|
-
nextScript: 'scripts/workbench-jova-proofread-section.js',
|
|
155
|
-
setIntent: userIntent,
|
|
156
|
-
setAction: action,
|
|
157
|
-
message: '请改 proofread-section.js 的 intent/action 后 run-code;禁止点添加子级。',
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (pathname.includes('/jova/writing')) {
|
|
162
|
-
return {
|
|
163
|
-
ok: false,
|
|
164
|
-
route: 'writing',
|
|
165
|
-
userIntent,
|
|
166
|
-
pathname,
|
|
167
|
-
forbiddenNeverClick: FORBIDDEN_BUTTONS,
|
|
168
|
-
nextScript: 'scripts/workbench-jova-writing-tool.js',
|
|
169
|
-
setIntent: normalizeWritingIntent(userIntent),
|
|
170
|
-
setAction: action,
|
|
171
|
-
message: '请改 writing-tool.js 的 intent 后 run-code;writing 页无添加子级按钮。',
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (pathname.includes('/jova/outline')) {
|
|
176
|
-
return {
|
|
177
|
-
ok: false,
|
|
178
|
-
route: 'outline',
|
|
179
|
-
userIntent,
|
|
180
|
-
pathname,
|
|
181
|
-
forbiddenNeverClick: FORBIDDEN_BUTTONS,
|
|
182
|
-
nextScript: 'scripts/workbench-jova-outline-regenerate-node.js',
|
|
183
|
-
setIntent: userIntent,
|
|
184
|
-
reason: 'userIntent 未匹配扩写/精简/润色/改写/重写/优化 前缀',
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return {
|
|
189
|
-
ok: false,
|
|
190
|
-
userIntent,
|
|
191
|
-
pathname,
|
|
192
|
-
forbiddenNeverClick: FORBIDDEN_BUTTONS,
|
|
193
|
-
reason: '当前 jova 步骤页不支持本章 AI 操作(topic/proofread 以外)',
|
|
194
|
-
};
|
|
195
|
-
};
|