dsh-agentone 0.5.19 → 0.5.21
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/README.md +3 -1
- package/lib/index.js +24 -1
- package/lib/page.js +34 -1
- package/lib/proc.js +64 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -31,7 +31,9 @@ lark-cli / ccpg-cli 状态探测。
|
|
|
31
31
|
失效);desktop 受管 pnpm 通道操作串行排队,宿主并发锁占用时自动退避
|
|
32
32
|
重试(不把「another desktop pnpm operation is already running」抛给用户);
|
|
33
33
|
自身随平台镜像升级(列表中不提供按钮)。
|
|
34
|
-
- **CLI
|
|
34
|
+
- **CLI 探测、安装与授权(M4)**:`lark-cli` / `ccpg-cli` 安装与授权态三态探测;
|
|
35
|
+
未安装时「安装」一键自助安装(lark 走 `npm install -g @larksuite/cli@latest`,
|
|
36
|
+
ccpg 走公司 `auto-install.sh`,口径与平台 cli-deployd 一致);
|
|
35
37
|
已装未授权时「去授权」发起官方 Device Flow(授权链接 + ASCII 二维码 +
|
|
36
38
|
验证码 + 自动轮询确认,设备码仅存插件进程内存)。
|
|
37
39
|
- **首启引导**:dsh 首次启动弹出飞书登录引导(order -50,早于官方
|
package/lib/index.js
CHANGED
|
@@ -34,7 +34,7 @@ import { applyPlatformSkillhub, removePlatformSkillhub } from './skillhub.js';
|
|
|
34
34
|
import { beginCliAuth, cliAuthQrcode, completeCliAuth, parseCliAuthBeginOutput } from './cliauth.mjs';
|
|
35
35
|
import { platformFetch } from './http.js';
|
|
36
36
|
import { donePageHtml, statusPageHtml } from './page.js';
|
|
37
|
-
import { compareSemver, dshPluginCli, firstErrorLines, probeCliDetail, pnpmViewLatest, upgradeCliTool } from './proc.js';
|
|
37
|
+
import { compareSemver, dshPluginCli, firstErrorLines, installCliTool, probeCliDetail, pnpmViewLatest, upgradeCliTool } from './proc.js';
|
|
38
38
|
|
|
39
39
|
import { clearCredentials, loadCredentials, resolveDshHome, saveCredentials, updateCredentials } from './store.js';
|
|
40
40
|
|
|
@@ -1199,6 +1199,29 @@ export function apply(ctx, config) {
|
|
|
1199
1199
|
sendJson(response, 200, { tools: { 'lark-cli': lark, 'ccpg-cli': ccpg } });
|
|
1200
1200
|
});
|
|
1201
1201
|
|
|
1202
|
+
register('/agentone/api/cli/install', async (request, response) => {
|
|
1203
|
+
if (request.method !== 'POST') {
|
|
1204
|
+
response.writeHead(405, { allow: 'POST' });
|
|
1205
|
+
response.end();
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
try {
|
|
1209
|
+
const body = await readJsonBody(request);
|
|
1210
|
+
const tool = String(body.tool || '');
|
|
1211
|
+
if (!CLI_TOOLS.has(tool)) {
|
|
1212
|
+
sendJson(response, 400, { error: '不支持的 CLI 工具' });
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
// 自助安装(lark 走 npm、ccpg 走官方 auto-install.sh),与升级一样
|
|
1216
|
+
// 分钟级耗时:输出尾部透传给前端展示失败原因
|
|
1217
|
+
const output = await installCliTool(tool);
|
|
1218
|
+
const detail = await probeCliDetail(tool).catch(() => null);
|
|
1219
|
+
sendJson(response, 200, { ok: true, output, tool: detail });
|
|
1220
|
+
} catch (error) {
|
|
1221
|
+
sendJson(response, 502, { error: error?.message || 'CLI 安装失败,请稍后重试' });
|
|
1222
|
+
}
|
|
1223
|
+
});
|
|
1224
|
+
|
|
1202
1225
|
register('/agentone/api/cli/upgrade', async (request, response) => {
|
|
1203
1226
|
if (request.method !== 'POST') {
|
|
1204
1227
|
response.writeHead(405, { allow: 'POST' });
|
package/lib/page.js
CHANGED
|
@@ -512,6 +512,9 @@ const renderCliData = (s, tools) => {
|
|
|
512
512
|
state === 'unauthorized'
|
|
513
513
|
? '<button class="btn small primary" data-cli-auth="' + esc(name) + '">去授权</button>'
|
|
514
514
|
: '',
|
|
515
|
+
state === 'missing'
|
|
516
|
+
? '<button class="btn small primary" data-cli-install="' + esc(name) + '">安装</button>'
|
|
517
|
+
: '',
|
|
515
518
|
upgradable
|
|
516
519
|
? '<button class="btn small ghost" data-cli-upgrade="' + esc(name) + '">升级</button>'
|
|
517
520
|
: '',
|
|
@@ -522,10 +525,13 @@ const renderCliData = (s, tools) => {
|
|
|
522
525
|
});
|
|
523
526
|
body.innerHTML = rows.join('')
|
|
524
527
|
+ '<div class="hint">在对话中直接使用(如 /lark 帮助),由 dsh 自动调用。</div>'
|
|
525
|
-
+ '<div class="hint"
|
|
528
|
+
+ '<div class="hint">未安装时点「安装」自助安装;已安装未授权时点「去授权」用飞书扫码完成即可。</div>';
|
|
526
529
|
body.querySelectorAll('[data-cli-upgrade]').forEach((btn) => {
|
|
527
530
|
btn.onclick = () => cliUpgrade(btn.dataset.cliUpgrade, btn);
|
|
528
531
|
});
|
|
532
|
+
body.querySelectorAll('[data-cli-install]').forEach((btn) => {
|
|
533
|
+
btn.onclick = () => cliInstall(btn.dataset.cliInstall, btn);
|
|
534
|
+
});
|
|
529
535
|
body.querySelectorAll('[data-cli-auth]').forEach((btn) => {
|
|
530
536
|
btn.onclick = () => cliAuthDialog(btn.dataset.cliAuth);
|
|
531
537
|
});
|
|
@@ -642,6 +648,33 @@ const cliAuthDialog = async (tool) => {
|
|
|
642
648
|
}
|
|
643
649
|
};
|
|
644
650
|
|
|
651
|
+
/** CLI 一键安装:lark 走 npm 全局安装、ccpg 走官方安装脚本,耗时可达
|
|
652
|
+
* 分钟级。响应自带安装后立即探测的单工具详情,直接合进缓存刷新界面。 */
|
|
653
|
+
const cliInstall = async (tool, btn) => {
|
|
654
|
+
btn.disabled = true;
|
|
655
|
+
btn.textContent = '安装中,可能需要 1–3 分钟…';
|
|
656
|
+
try {
|
|
657
|
+
const resp = await fetch('api/cli/install', {
|
|
658
|
+
method: 'POST',
|
|
659
|
+
headers: { 'Content-Type': 'application/json' },
|
|
660
|
+
body: JSON.stringify({ tool }),
|
|
661
|
+
});
|
|
662
|
+
const data = await resp.json().catch(() => ({}));
|
|
663
|
+
if (!resp.ok) throw new Error(data.error || 'CLI 安装失败');
|
|
664
|
+
renderCli._probedAt = 0;
|
|
665
|
+
if (data.tool) {
|
|
666
|
+
renderCliData(lastStatus, { [tool]: data.tool });
|
|
667
|
+
} else {
|
|
668
|
+
renderCli(lastStatus);
|
|
669
|
+
}
|
|
670
|
+
if (data.output) alert(data.output);
|
|
671
|
+
} catch (error) {
|
|
672
|
+
alert(error.message || 'CLI 安装失败,请稍后重试');
|
|
673
|
+
btn.disabled = false;
|
|
674
|
+
btn.textContent = '安装';
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
|
|
645
678
|
/** CLI 一键升级:官方 tool update(ccpg 下载二进制可达分钟级)。 */
|
|
646
679
|
const cliUpgrade = async (tool, btn) => {
|
|
647
680
|
btn.disabled = true;
|
package/lib/proc.js
CHANGED
|
@@ -239,6 +239,70 @@ async function cliLatestVersion(tool, timeoutMs) {
|
|
|
239
239
|
return null;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
/** ccpg-cli 官方安装脚本地址(与平台侧 cli-deployd-go InstallCCPGCLI 同源,
|
|
243
|
+
* 保持两端口径一致;auto-install.sh 自带二进制下载与 PATH 写入)。 */
|
|
244
|
+
const CCPG_CLI_INSTALL_URL_PREFIX = 'http://bms.einwin.com/media/ccpg-cli/202605091513';
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* lark-cli 装成功后静默安装其全局技能(软失败,不阻断安装结果)。
|
|
248
|
+
* 与平台侧 cli-deployd 口径一致:`npx -y skills add larksuite/cli -g --all`
|
|
249
|
+
* (技能内容由 skills CLI 内部 git clone GitHub);已装(~/.agents/skills
|
|
250
|
+
* 非空)则跳过。返回描述性输出供日志/前端提示。
|
|
251
|
+
*/
|
|
252
|
+
async function installLarkSkills({ timeoutMs = 180_000 } = {}) {
|
|
253
|
+
const skillsDir = join(homedir(), '.agents/skills');
|
|
254
|
+
try {
|
|
255
|
+
if (readdirSync(skillsDir).length > 0) return 'lark-cli skills already installed';
|
|
256
|
+
} catch {
|
|
257
|
+
// 目录不存在 → 未安装,继续
|
|
258
|
+
}
|
|
259
|
+
const { stdout } = await runCliTool('npx', [
|
|
260
|
+
'-y', 'skills', 'add', 'larksuite/cli',
|
|
261
|
+
'-g', '--all', '--dangerously-accept-openclaw-risks',
|
|
262
|
+
], { timeoutMs });
|
|
263
|
+
const lines = String(stdout).split('\n').map((l) => l.trim()).filter(Boolean);
|
|
264
|
+
return lines.slice(-3).join('\n');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 触发 CLI 官方安装(工具缺失时用户自助安装):
|
|
269
|
+
* lark-cli npm 全局装最新版(包名 @larksuite/cli,npm/pnpm 环境均可;
|
|
270
|
+
* lark-cli 自动探测安装方式,后续 update 升级能复用),
|
|
271
|
+
* 装成功后静默安装配套全局技能(软失败,不阻断安装结果)
|
|
272
|
+
* ccpg-cli curl 公司 auto-install.sh(失败退化 wget),与平台
|
|
273
|
+
* cli-deployd-go 的 install 口径一致。
|
|
274
|
+
* 返回输出尾部给前端展示。只接受 CLI_TOOLS 白名单内的 tool。
|
|
275
|
+
*/
|
|
276
|
+
export async function installCliTool(tool, { timeoutMs = 300_000 } = {}) {
|
|
277
|
+
let stdout;
|
|
278
|
+
if (tool === 'lark-cli') {
|
|
279
|
+
({ stdout } = await runCliTool('npm', ['install', '-g', '@larksuite/cli@latest'], { timeoutMs }));
|
|
280
|
+
const skillsNote = await installLarkSkills().catch((error) => {
|
|
281
|
+
// 软失败:技能装不上不影响 CLI 本体已装成功(如 GitHub 不可达)
|
|
282
|
+
return `lark-cli skills install soft-failed: ${error?.message || error}`;
|
|
283
|
+
});
|
|
284
|
+
stdout = `${stdout}\n${skillsNote}`;
|
|
285
|
+
} else if (tool === 'ccpg-cli') {
|
|
286
|
+
// 下载 auto-install.sh(curl 失败退化 wget)后交 bash 执行;execFile 不经
|
|
287
|
+
// 外层 shell,脚本文本作为 bash -c 的单一参数,与平台侧 `| bash` 等价。
|
|
288
|
+
const fetchScript = () => runCliTool('curl', [
|
|
289
|
+
'-fsSL', '--retry', '3', '--retry-delay', '5', '--max-time', '120',
|
|
290
|
+
`${CCPG_CLI_INSTALL_URL_PREFIX}/auto-install.sh`,
|
|
291
|
+
], { timeoutMs: 120_000 })
|
|
292
|
+
.catch(() => runCliTool('wget', ['-qO-', `${CCPG_CLI_INSTALL_URL_PREFIX}/auto-install.sh`], { timeoutMs: 120_000 }));
|
|
293
|
+
const fetched = (await fetchScript()).stdout.trim();
|
|
294
|
+
if (!fetched) throw new Error('安装脚本下载失败,请检查网络后重试');
|
|
295
|
+
({ stdout } = await runCliTool('bash', ['-c', fetched], {
|
|
296
|
+
timeoutMs,
|
|
297
|
+
env: { CCPG_CLI_URL_PREFIX: CCPG_CLI_INSTALL_URL_PREFIX },
|
|
298
|
+
}));
|
|
299
|
+
} else {
|
|
300
|
+
throw new Error('不支持的 CLI 工具');
|
|
301
|
+
}
|
|
302
|
+
const lines = String(stdout).split('\n').map((l) => l.trim()).filter(Boolean);
|
|
303
|
+
return lines.slice(-6).join('\n');
|
|
304
|
+
}
|
|
305
|
+
|
|
242
306
|
/**
|
|
243
307
|
* 触发 CLI 官方自升级(`tool update`):ccpg-cli 从更新服务器下载二进制
|
|
244
308
|
* (~17MB),lark-cli 自动探测 npm/pnpm/手动安装方式(手动时只打印
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-agentone",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "AgentOne 平台集成插件:飞书登录、平台模型(同步失败自愈重试)、SkillHub 技能(升级检测一键升级、装后即时刷新、套餐技能自动同步)、套餐申请、插件管理与自助升级、lark-cli / ccpg-cli
|
|
3
|
+
"version": "0.5.21",
|
|
4
|
+
"description": "AgentOne 平台集成插件:飞书登录、平台模型(同步失败自愈重试)、SkillHub 技能(升级检测一键升级、装后即时刷新、套餐技能自动同步)、套餐申请、插件管理与自助升级、lark-cli / ccpg-cli 探测与一键安装(请求超时与错误码透传、令牌轮换 single-flight、凭据损坏容错与并发安全写入、状态页 UX 增强)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|