dsh-agentone 0.5.3 → 0.5.5
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/index.js +40 -15
- package/lib/proc.js +8 -7
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -153,8 +153,25 @@ async function ensureFreshToken(config, log) {
|
|
|
153
153
|
return tokenRefreshInFlight;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
/**
|
|
157
|
-
|
|
156
|
+
/**
|
|
157
|
+
* 插件管理目标 profile:普通 dsh 固定 web(控制台只跑 web profile);
|
|
158
|
+
* DSH Desktop 用 desktopProfiles.current(apply 时探测填充)。
|
|
159
|
+
*/
|
|
160
|
+
let PLUGIN_PROFILE = 'web';
|
|
161
|
+
/** desktop 受管插件操作通道(desktopPnpm.runPlugin),非 desktop 为 null。 */
|
|
162
|
+
let desktopPluginCli = null;
|
|
163
|
+
|
|
164
|
+
function pluginProfileDir(config) {
|
|
165
|
+
return join(resolveDshHome(config), 'profiles', PLUGIN_PROFILE);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** 转发 dsh plugin 子命令:desktop 走受管 pnpm,普通 dsh 走官方 CLI。 */
|
|
169
|
+
async function runPluginCli(args) {
|
|
170
|
+
if (desktopPluginCli) {
|
|
171
|
+
return desktopPluginCli(args);
|
|
172
|
+
}
|
|
173
|
+
return dshPluginCli(args, PLUGIN_PROFILE);
|
|
174
|
+
}
|
|
158
175
|
|
|
159
176
|
/**
|
|
160
177
|
* npm 包名白名单(scoped 与非 scoped)。用户输入会进入 CLI 参数,必须先
|
|
@@ -164,10 +181,6 @@ const NPM_NAME_RE = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
|
|
|
164
181
|
/** 版本白名单:语义化版本、^ ~ 前缀与 latest 标签。 */
|
|
165
182
|
const VERSION_RE = /^(?:\^|~)?\d+(?:\.\d+){0,3}(?:[-+][a-z0-9._-]+)?$|^latest$/;
|
|
166
183
|
|
|
167
|
-
function pluginProfileDir(config) {
|
|
168
|
-
return join(resolveDshHome(config), 'profiles', PLUGIN_PROFILE);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
184
|
/** 校验用户输入的包名/版本;非法值直接拒绝(中文报错)。 */
|
|
172
185
|
function assertValidPackage(name, version) {
|
|
173
186
|
if (!NPM_NAME_RE.test(name)) {
|
|
@@ -319,11 +332,11 @@ const BUILTIN_PLUGIN_ALLOW_BUILD = {
|
|
|
319
332
|
'dsh-im': [],
|
|
320
333
|
};
|
|
321
334
|
|
|
322
|
-
/**
|
|
335
|
+
/** 安装:白名单校验后转发(desktop 受管 pnpm / 官方 CLI;参数数组,无 shell)。 */
|
|
323
336
|
async function installProfilePlugin(config, name, version) {
|
|
324
337
|
assertValidPackage(name, version);
|
|
325
338
|
const target = version ? `${name}@${version}` : name;
|
|
326
|
-
await
|
|
339
|
+
await runPluginCli(['add', target, ...(BUILTIN_PLUGIN_ALLOW_BUILD[name] || [])]);
|
|
327
340
|
return listProfilePlugins(config);
|
|
328
341
|
}
|
|
329
342
|
|
|
@@ -339,7 +352,7 @@ async function removeProfilePlugin(config, name) {
|
|
|
339
352
|
if (name === PLUGIN_PACKAGE_NAME) {
|
|
340
353
|
throw new Error('AgentOne 插件是登录与模型配置的载体,不能卸载自己');
|
|
341
354
|
}
|
|
342
|
-
await
|
|
355
|
+
await runPluginCli(['remove', name]);
|
|
343
356
|
return listProfilePlugins(config);
|
|
344
357
|
}
|
|
345
358
|
|
|
@@ -352,7 +365,7 @@ async function upgradeProfilePlugin(config, name) {
|
|
|
352
365
|
if (name === PLUGIN_PACKAGE_NAME) {
|
|
353
366
|
throw new Error('AgentOne 插件随平台镜像一同升级,无需手动操作');
|
|
354
367
|
}
|
|
355
|
-
await
|
|
368
|
+
await runPluginCli(['update', name]);
|
|
356
369
|
return listProfilePlugins(config);
|
|
357
370
|
}
|
|
358
371
|
|
|
@@ -528,15 +541,27 @@ button{font:inherit;padding:9px 22px;border-radius:10px;border:none;cursor:point
|
|
|
528
541
|
|
|
529
542
|
/**
|
|
530
543
|
* 是否运行在 DSH Desktop 内:宿主进程是 Electron(execPath 指向 DSH Desktop
|
|
531
|
-
*
|
|
532
|
-
*
|
|
544
|
+
* 可执行文件)。与页面侧标记(page.js 传 desktop:true)互为兜底——iframe 内
|
|
545
|
+
* location.search 不含宿主 query,页面自检在设置 iframe 场景会漏。
|
|
533
546
|
*/
|
|
534
547
|
function isDesktopHost() {
|
|
535
|
-
return /DSH Desktop\.app/i.test(process.execPath);
|
|
548
|
+
return /DSH Desktop\.(?:app|exe)/i.test(process.execPath);
|
|
536
549
|
}
|
|
537
550
|
|
|
538
551
|
export function apply(ctx, config) {
|
|
539
552
|
const log = ctx.logger || console;
|
|
553
|
+
// Desktop 环境探测(官方契约,见 harness-one DESKTOP.md):desktopProfiles
|
|
554
|
+
// 只在 DSH Desktop 存在。据此把插件管理切到当前 profile,并用受管
|
|
555
|
+
// desktopPnpm 做装/卸/升级(desktop 里 dsh CLI 拒绝操作 desktop profile)。
|
|
556
|
+
const desktopProfiles = ctx.get?.('desktopProfiles');
|
|
557
|
+
const isDesktopRuntime = Boolean(desktopProfiles?.current?.name) || isDesktopHost();
|
|
558
|
+
if (desktopProfiles?.current?.name) {
|
|
559
|
+
PLUGIN_PROFILE = desktopProfiles.current.name;
|
|
560
|
+
ctx.inject(['desktopPnpm'], (desktopCtx) => {
|
|
561
|
+
desktopPluginCli = (args) => desktopCtx.desktopPnpm.runPlugin(args);
|
|
562
|
+
log.info(`[dsh-agentone] desktop profile: ${PLUGIN_PROFILE}`);
|
|
563
|
+
});
|
|
564
|
+
}
|
|
540
565
|
ctx.effect(() => {
|
|
541
566
|
const register = (path, handler) => ctx.webServer.register({ kind: 'exact', path, handler });
|
|
542
567
|
|
|
@@ -619,7 +644,7 @@ export function apply(ctx, config) {
|
|
|
619
644
|
// DSH Desktop:宿主 webserver 只信 Electron 内部请求,外部浏览器访问
|
|
620
645
|
// /agentone/callback 会 403。desktop 环境(服务端自检 execPath 或页面
|
|
621
646
|
// 传 desktop 标记)改由插件在本进程起一次性本地服务收回调。
|
|
622
|
-
const callbackUrl = body.desktop ||
|
|
647
|
+
const callbackUrl = body.desktop || isDesktopRuntime
|
|
623
648
|
? await openCallbackServer(config, log)
|
|
624
649
|
: String(body.callback_url || '');
|
|
625
650
|
if (!/^https?:\/\/|^\/portal\//.test(callbackUrl)) {
|
|
@@ -802,7 +827,7 @@ export function apply(ctx, config) {
|
|
|
802
827
|
try {
|
|
803
828
|
const [state, outdatedStdout] = await Promise.all([
|
|
804
829
|
listProfilePlugins(config),
|
|
805
|
-
pnpmCli(['outdated', '--format', 'list'], 60000)
|
|
830
|
+
pnpmCli(['outdated', '--format', 'list'], 60000, pluginProfileDir(config))
|
|
806
831
|
.then((r) => r.stdout)
|
|
807
832
|
.catch(() => ''),
|
|
808
833
|
]);
|
package/lib/proc.js
CHANGED
|
@@ -25,12 +25,13 @@ function firstErrorLines(raw) {
|
|
|
25
25
|
* async 函数;execFile 不经过 shell,参数数组中的每个元素都是独立参数,
|
|
26
26
|
* 不存在拼接解释执行。
|
|
27
27
|
*/
|
|
28
|
-
export async function runCliTool(tool, args, { timeoutMs = 300000 } = {}) {
|
|
28
|
+
export async function runCliTool(tool, args, { timeoutMs = 300000, cwd } = {}) {
|
|
29
29
|
try {
|
|
30
30
|
const { stdout, stderr } = await execFileAsync(tool, args, {
|
|
31
31
|
timeout: timeoutMs,
|
|
32
32
|
killSignal: 'SIGKILL',
|
|
33
33
|
env: process.env,
|
|
34
|
+
cwd,
|
|
34
35
|
});
|
|
35
36
|
return { stdout, stderr };
|
|
36
37
|
} catch (error) {
|
|
@@ -45,14 +46,14 @@ export async function runCliTool(tool, args, { timeoutMs = 300000 } = {}) {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
/** dsh plugin 子命令:转发给官方 CLI
|
|
49
|
-
export function dshPluginCli(args) {
|
|
50
|
-
return runCliTool('dsh', ['plugin', '--profile',
|
|
49
|
+
/** dsh plugin 子命令:转发给官方 CLI(profile 由调用方给出)。 */
|
|
50
|
+
export function dshPluginCli(args, profile = 'web') {
|
|
51
|
+
return runCliTool('dsh', ['plugin', '--profile', profile, ...args]);
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
/** pnpm 子命令(当前仅 outdated
|
|
54
|
-
export function pnpmCli(args, timeoutMs) {
|
|
55
|
-
return runCliTool('pnpm', args, { timeoutMs });
|
|
54
|
+
/** pnpm 子命令(当前仅 outdated 查询);cwd 指向目标 profile 目录。 */
|
|
55
|
+
export function pnpmCli(args, timeoutMs, cwd) {
|
|
56
|
+
return runCliTool('pnpm', args, { timeoutMs, cwd });
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
/**
|
package/package.json
CHANGED