dsh-agentone 0.5.44 → 1.0.0

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.
@@ -259,7 +259,17 @@ export function createDefaultsSync({ config, profiles, credentials, log, interva
259
259
  promise.finally(() => manualOperations.delete(promise)).catch(() => {});
260
260
  return promise;
261
261
  }
262
- return { sync, manualOperation, snapshot: () => structuredClone(state),
262
+ // 快照是 /api/status(5s 轮询)与 defaults/status 的下发边界:description
263
+ // (技能包全文,几百字/条)只在展示层被引用,而新版页面已彻底不渲染——
264
+ // 在出口剥掉,轮询不再背着几十 KB 死重;内部 state 保持完整
265
+ const snapshot = () => {
266
+ const clone = structuredClone(state);
267
+ for (const list of [clone.skills, clone.plugins]) {
268
+ for (const entry of list || []) delete entry.description;
269
+ }
270
+ return clone;
271
+ };
272
+ return { sync, manualOperation, snapshot,
263
273
  reset() { stop(); profiles.setPolicy([]); state = { source: null, revision: null,
264
274
  checked_at: null, user_id: null, error: null, running: false, skills: [], plugins: [] }; },
265
275
  dispose() { disposed = true; stop(); return Promise.allSettled([inFlight, ...manualOperations.keys()]); },
package/lib/index.js CHANGED
@@ -1057,7 +1057,7 @@ export function apply(ctx, config) {
1057
1057
  invalidateStatusCache();
1058
1058
  sendJson(response, 200, { ok: true, installed: result?.installed ?? 0, failed: result?.failed ?? 0 });
1059
1059
  } catch (error) {
1060
- sendJson(response, 502, { error: error?.message || '同步套餐技能失败' });
1060
+ sendJson(response, 502, { error: error?.message || '同步技能失败' });
1061
1061
  }
1062
1062
  });
1063
1063
 
package/lib/page.js CHANGED
@@ -395,52 +395,87 @@ const renderPlan = async () => {
395
395
  ).then(() => renderPlan());
396
396
  });
397
397
  };
398
+ // 平台清单同步态与插件列表的同名合并:renderDefaults 记录待处理插件并排除
399
+ // 已列名条目,renderPlugins 把同步状态/原因/重试合并进同名行——同一个包只
400
+ // 出现一行(真实用户机 dsh-im:清单同步失败 + 本机未启用曾显示成两条)
401
+ let defaultsPendingPlugins = [];
402
+ let listedPluginNames = new Set();
403
+ let mergedPendingSig = '';
404
+ const DEFAULTS_STATE_LABELS = { current: '已符合', missing: '待安装', pending: '待应用', running: '同步中',
405
+ failed: '失败', conflict: '本机冲突', report_pending: '已安装,待回报', restart_required: '已安装,重启后生效' };
406
+ /** 同步动作按钮的统一绑定(待处理块与合并进插件行的按钮同一契约)。 */
407
+ const bindDefaultsActions = (el) => {
408
+ el.querySelectorAll('[data-default-action]').forEach((btn) => {
409
+ const request = () => fetch('api/defaults/' + btn.dataset.defaultAction, { method: 'POST',
410
+ headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ kind: btn.dataset.kind,
411
+ name: btn.dataset.name, confirm: btn.dataset.defaultAction === 'apply' }) });
412
+ btn.onclick = () => btn.dataset.defaultAction === 'apply'
413
+ ? confirmThen(btn, '替换当前版本?', request, '已开始应用,请查看同步状态')
414
+ : withLoading(btn, request, '已开始重试,请查看同步状态');
415
+ });
416
+ };
417
+ const defaultsPendingSig = () => defaultsPendingPlugins.map((item) => [item.name, item.state,
418
+ item.target_version || '', item.error || ''].join('~')).join('|');
419
+
398
420
  const renderDefaults = (s) => {
399
- const body = $('defaults-body');
400
421
  const config = s.defaults;
401
- const labels = { current: '已符合', missing: '待安装', pending: '待应用', running: '同步中',
402
- failed: '失败', conflict: '本机冲突', report_pending: '已安装,待回报', restart_required: '已安装,重启后生效' };
422
+ const syncBtn = $('defaults-sync-btn');
423
+ const labels = DEFAULTS_STATE_LABELS;
403
424
  const sources = { platform: '平台清单', compatibility: '旧平台兼容默认', cache: '本机缓存' };
404
- if (!config || !s.logged_in) { body.innerHTML = '<div class="muted">登录后检查平台默认能力</div>'; return; }
425
+ const clearBlock = (el) => { el.innerHTML = ''; delete el.dataset.fingerprint; };
426
+ if (!config || !s.logged_in) {
427
+ syncBtn.hidden = true;
428
+ for (const id of ['defaults-meta', 'defaults-plugins', 'defaults-skills']) clearBlock($(id));
429
+ return;
430
+ }
431
+ syncBtn.hidden = false;
432
+ syncBtn.disabled = Boolean(config.running);
405
433
  const entries = [...(config.skills || []), ...(config.plugins || [])];
406
434
  // legacy:0.5.39 之前装的技能只有平台台账、没有本机记录(见 defaults-sync)。
407
435
  // 这类条目单独给一个批量入口,不然升级后每台机器都要点 N 次「确认应用」。
408
436
  const legacyCount = entries.filter((item) => item.legacy).length;
409
- const summary = '<div class="skill-sub">' + esc(sources[config.source] || '尚未检查')
410
- + (config.revision !== null ? ' · 版本 ' + esc(config.revision) : '')
437
+ const pendingCount = entries.filter((item) => item.state !== 'current').length;
438
+ // 待处理插件交给 renderPlugins 合并进同名行(见顶部说明)
439
+ defaultsPendingPlugins = (config.plugins || []).filter((item) => item.state !== 'current');
440
+ // 清单状态收成插件卡头一行 meta(来源/版本/时间/符合统计/错误):健康项不
441
+ // 铺开——技能与插件分别在各自 Tab 的列表里以「平台默认/受管」标签呈现,
442
+ // 这里只按类型冒泡待处理项,长描述彻底退出列表。
443
+ const metaHtml = '<div class="skill-sub">' + esc(sources[config.source] || '尚未检查')
444
+ + (config.revision !== null ? ' · 清单版本 ' + esc(config.revision) : '')
411
445
  + (config.checked_at ? ' · ' + esc(new Date(config.checked_at).toLocaleString()) : '')
446
+ + ' · <span style="color:var(--ok)">' + (entries.length - pendingCount) + ' 项已符合</span>'
447
+ + (pendingCount ? ' · <span style="color:var(--warn)">' + pendingCount + ' 项待处理(见下)</span>' : '')
448
+ + (!entries.length ? ' · 当前清单为空' : '')
412
449
  + (config.running ? ' · 正在检查' : '') + '</div>'
413
- + (config.error || config.profile_error ? '<div class="skill-sub" style="color:var(--err)">' + esc(config.error || config.profile_error) + '</div>' : '')
414
- + (legacyCount ? '<div class="skill-sub"><button id="defaults-repair" class="btn small ghost"'
415
- + (config.running ? ' disabled' : '') + '>重新应用旧版安装的技能(' + legacyCount + ')</button>'
416
- + ' 技能目录会按平台当前版本覆盖</div>' : '');
417
- const html = summary + entries.map((item) => {
450
+ + (config.error || config.profile_error
451
+ ? '<div class="skill-sub" style="color:var(--err)">' + esc(config.error || config.profile_error) + '</div>' : '');
452
+ const meta = $('defaults-meta');
453
+ if (meta.dataset.fingerprint !== metaHtml) { meta.dataset.fingerprint = metaHtml; meta.innerHTML = metaHtml; }
454
+ const statePill = (state) => state === 'failed' || state === 'conflict'
455
+ ? '<span class="pill" style="font-size:11px;background:var(--err-weak);color:var(--err)">'
456
+ + esc(labels[state] || state) + '</span>'
457
+ : '<span class="pill warn" style="font-size:11px">' + esc(labels[state] || state) + '</span>';
458
+ // 单行紧凑条目:名称 · 类型徽标 · 状态徽标 · 版本(→ 目标版本)+ 行内操作
459
+ const rowHtml = (item) => {
418
460
  const action = ['failed', 'report_pending', 'missing'].includes(item.state) ? 'retry'
419
461
  : ['conflict', 'pending'].includes(item.state) ? 'apply' : null;
420
462
  const button = action ? '<button class="btn small ghost" data-default-action="' + action
421
463
  + '" data-kind="' + item.kind + '" data-name="' + esc(item.name) + '"'
422
464
  + (config.running ? ' disabled' : '') + '>' + (action === 'retry' ? '重试' : '确认应用') + '</button>' : '';
423
465
  return '<div class="skill-item"><div class="skill-info"><div class="skill-name">'
424
- + esc(item.description || item.name) + ' <span class="tag">' + (item.kind === 'skill' ? '技能' : '插件')
425
- + '</span></div><div class="skill-sub">' + esc(item.name) + ' · ' + esc(labels[item.state] || item.state)
426
- + (item.legacy ? '(旧版安装)' : '')
427
- + (item.version ? ' · ' + esc(item.version) : '')
466
+ + esc(item.name) + ' <span class="tag">' + (item.kind === 'skill' ? '技能' : '插件') + '</span>'
467
+ + statePill(item.state)
468
+ + (item.legacy ? ' <span class="tag">旧版安装</span>' : '')
469
+ + '</div><div class="skill-sub">'
470
+ + (item.version ? esc(item.version) : '')
428
471
  + (item.target_version && item.target_version !== item.version ? ' → ' + esc(item.target_version) : '')
429
472
  + (item.error ? '<br><span style="color:var(--err)">' + esc(item.error) + '</span>' : '')
430
473
  + '</div></div>' + button + '</div>';
431
- }).join('') + (!entries.length ? '<div class="skill-sub">当前清单为空</div>' : '');
432
- if (body.dataset.fingerprint !== html) {
433
- body.dataset.fingerprint = html; body.innerHTML = html;
434
- body.querySelectorAll('[data-default-action]').forEach((btn) => {
435
- const request = () => fetch('api/defaults/' + btn.dataset.defaultAction, { method: 'POST',
436
- headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ kind: btn.dataset.kind,
437
- name: btn.dataset.name, confirm: btn.dataset.defaultAction === 'apply' }) });
438
- btn.onclick = () => btn.dataset.defaultAction === 'apply'
439
- ? confirmThen(btn, '替换当前版本?', request, '已开始应用,请查看同步状态')
440
- : withLoading(btn, request, '已开始重试,请查看同步状态');
441
- });
442
- const repair = body.querySelector('#defaults-repair');
443
- if (repair) repair.onclick = async () => {
474
+ };
475
+ const bindRepair = (el) => {
476
+ const repair = el.querySelector('#defaults-repair');
477
+ if (!repair) return;
478
+ repair.onclick = async () => {
444
479
  if (repair.dataset.confirming !== '1') {
445
480
  repair.dataset.confirming = '1';
446
481
  repair.dataset.originalLabel = repair.textContent;
@@ -470,8 +505,31 @@ const renderDefaults = (s) => {
470
505
  await refresh();
471
506
  }
472
507
  };
473
- }
474
- $('defaults-sync-btn').disabled = config.running;
508
+ };
509
+ // 按类型各归其位:待处理插件进插件 Tab、待处理技能进技能 Tab,只列非已符合
510
+ // 项;5s 轮询高频调用,块内容没变时靠指纹跳过重绘(不打断进行中的点击)
511
+ const renderBlock = (id, list) => {
512
+ const el = $(id);
513
+ // 插件待处理项:已进插件列表的同名条目不在这里重复出现(合并进那一行)
514
+ const pending = (list || []).filter((item) => item.state !== 'current'
515
+ && !(id === 'defaults-plugins' && listedPluginNames.has(item.name)));
516
+ const legacy = id === 'defaults-skills' && legacyCount
517
+ ? '<div class="skill-sub"><button id="defaults-repair" class="btn small ghost"'
518
+ + (config.running ? ' disabled' : '') + '>重新应用旧版安装的技能(' + legacyCount + ')</button>'
519
+ + ' 技能目录会按平台当前版本覆盖</div>'
520
+ : '';
521
+ const html = (pending.length || legacy)
522
+ ? '<div class="skill-sub" style="margin-top:10px">平台同步待处理</div>'
523
+ + pending.map(rowHtml).join('') + legacy
524
+ : '';
525
+ if (el.dataset.fingerprint !== html) { el.dataset.fingerprint = html; el.innerHTML = html; bindDefaultsActions(el); bindRepair(el); }
526
+ };
527
+ renderBlock('defaults-plugins', config.plugins);
528
+ renderBlock('defaults-skills', config.skills);
529
+ // 待处理集合变化(新失败/恢复)→ 让已加载的插件列表行重新合并;
530
+ // renderPlugins 侧会先对齐 mergedPendingSig,不会互相触发死循环
531
+ const pendingSig = defaultsPendingSig();
532
+ if (renderPlugins._loaded && pendingSig !== mergedPendingSig) void renderPlugins();
475
533
  };
476
534
  const renderSkills = (s) => {
477
535
  const skillhubEnabled = s.capabilities?.channels?.skillhub?.enabled !== false;
@@ -1044,8 +1102,14 @@ const renderPlugins = async () => {
1044
1102
  }
1045
1103
  // 渲染成功即标记已加载:避免切 tab 重复拉取(outdated 查询有网络开销)
1046
1104
  renderPlugins._loaded = true;
1105
+ // 同名合并登记(见 renderDefaults 顶部说明):已列名的插件,其清单同步
1106
+ // 状态合并进本行;待处理块不再单列一条
1107
+ listedPluginNames = new Set(data.plugins.map((plugin) => plugin.name));
1108
+ const pendingByN = new Map(defaultsPendingPlugins.map((item) => [item.name, item]));
1047
1109
  if (!data.plugins?.length) {
1048
1110
  list.innerHTML = '<div class="skill-sub">暂无已安装插件;内置插件缺失时会在 dsh 启动时自动恢复。</div>';
1111
+ mergedPendingSig = defaultsPendingSig();
1112
+ if (lastStatus) renderDefaults(lastStatus);
1049
1113
  return;
1050
1114
  }
1051
1115
  const rows = data.plugins.map((plugin) => {
@@ -1065,6 +1129,15 @@ const renderPlugins = async () => {
1065
1129
  const builtinTag = plugin.builtin
1066
1130
  ? '<span class="tag">受管</span>'
1067
1131
  : '';
1132
+ // 清单同步态合并:同名待处理插件在本行直接给出状态/原因/动作
1133
+ const pending = pendingByN.get(plugin.name);
1134
+ const syncPill = pending
1135
+ ? (['failed', 'conflict'].includes(pending.state)
1136
+ ? '<span class="pill" style="font-size:11px;background:var(--err-weak);color:var(--err)">同步'
1137
+ + esc(DEFAULTS_STATE_LABELS[pending.state] || pending.state) + '</span>'
1138
+ : '<span class="pill warn" style="font-size:11px">同步'
1139
+ + esc(DEFAULTS_STATE_LABELS[pending.state] || pending.state) + '</span>')
1140
+ : '';
1068
1141
  const version = plugin.latest
1069
1142
  ? esc(plugin.version) + ' → <b>' + esc(plugin.latest) + '</b>'
1070
1143
  : esc(plugin.version || '—');
@@ -1084,17 +1157,25 @@ const renderPlugins = async () => {
1084
1157
  actions.push('<button class="btn small danger" data-remove="' + esc(plugin.name) + '">卸载</button>');
1085
1158
  }
1086
1159
  }
1160
+ if (pending && ['failed', 'report_pending', 'missing'].includes(pending.state)) {
1161
+ actions.push('<button class="btn small ghost" data-default-action="retry" data-kind="plugin" data-name="' + esc(plugin.name) + '">重试</button>');
1162
+ } else if (pending && ['conflict', 'pending'].includes(pending.state)) {
1163
+ actions.push('<button class="btn small ghost" data-default-action="apply" data-kind="plugin" data-name="' + esc(plugin.name) + '">确认应用</button>');
1164
+ }
1087
1165
  const actionHtml = actions.length
1088
1166
  ? '<div style="display:flex;gap:6px">' + actions.join('') + '</div>'
1089
1167
  : '';
1090
1168
  return '<div class="skill-item"><div class="skill-info"><div class="skill-name">'
1091
- + esc(plugin.name) + builtinTag + statePill
1169
+ + esc(plugin.name) + builtinTag + statePill + syncPill
1092
1170
  + '</div><div class="skill-sub">' + desc + esc(plugin.source) + ' · ' + version
1093
1171
  + (plugin.registered ? ' · 已启用,重启后生效' : plugin.bundled ? ' · 已安装,未启用当前 profile(「升级」或重装可启用)' : '')
1172
+ + (pending ? ' · 平台同步 ' + esc(pending.version || '') + (pending.target_version && pending.target_version !== pending.version ? ' → ' + esc(pending.target_version) : '') : '')
1173
+ + (pending?.error ? '<br><span style="color:var(--err)">' + esc(pending.error) + '</span>' : '')
1094
1174
  + '</div></div>' + actionHtml + '</div>';
1095
1175
  });
1096
1176
  // 指纹保护(与 renderSkills 同思路):内容没变不碰 innerHTML——升级后
1097
- // 的定向刷新、切 tab 重入都不会重建按钮节点(打断卸载二次确认)或闪动
1177
+ // 的定向刷新、切 tab 重入都不会重建按钮节点(打断卸载二次确认)或闪动。
1178
+ // 清单同步态参与指纹:失败/恢复会让行内容变化
1098
1179
  const fingerprint = data.plugins.map((plugin) => [
1099
1180
  plugin.name,
1100
1181
  plugin.version || '',
@@ -1102,6 +1183,10 @@ const renderPlugins = async () => {
1102
1183
  plugin.registered ? 1 : 0,
1103
1184
  plugin.bundled ? 1 : 0,
1104
1185
  plugin.self_managed ? 1 : 0,
1186
+ pendingByN.get(plugin.name)
1187
+ ? [pendingByN.get(plugin.name).state, pendingByN.get(plugin.name).target_version || '',
1188
+ pendingByN.get(plugin.name).error || ''].join('~')
1189
+ : '',
1105
1190
  ].join(':')).join('|');
1106
1191
  if (list.dataset.fingerprint !== fingerprint) {
1107
1192
  list.dataset.fingerprint = fingerprint;
@@ -1125,6 +1210,12 @@ const renderPlugins = async () => {
1125
1210
  body: JSON.stringify({ name: btn.dataset.remove }),
1126
1211
  }).then(() => renderPlugins()), '插件已卸载');
1127
1212
  });
1213
+ // 合并进插件行的同步动作按钮(与待处理块同一契约)
1214
+ bindDefaultsActions(list);
1215
+ // 对齐「已合并的待处理集合」:renderDefaults 的变化触发到此为止(不会回环);
1216
+ // 列名登记可能让待处理块的排除集变化,定向重绘一次
1217
+ mergedPendingSig = defaultsPendingSig();
1218
+ if (lastStatus) renderDefaults(lastStatus);
1128
1219
  };
1129
1220
  // ==about-upgrade-begin==
1130
1221
  // 关于页版本行:aboutSelf(GET api/plugin/self)有值时展示升级入口或
@@ -1403,7 +1494,7 @@ $('skillhub-sync-btn').onclick = () => withLoading(
1403
1494
  () => fetch('api/skillhub/sync', { method: 'POST' }),
1404
1495
  'SkillHub 配置已同步',
1405
1496
  );
1406
- // 手动同步套餐技能:文案按结果给(装了几个),失败由 withLoading 展示
1497
+ // 手动同步技能:文案按结果给(装了几个),失败由 withLoading 展示
1407
1498
  $('skill-sync-btn').onclick = () => withLoading(
1408
1499
  $('skill-sync-btn'),
1409
1500
  async () => {
@@ -1514,9 +1605,10 @@ export function statusPageHtml() {
1514
1605
  <div class="card" id="skills-card">
1515
1606
  <h3>平台技能 <span class="muted">套餐自动同步</span></h3>
1516
1607
  <div id="skills-list"></div>
1608
+ <div id="defaults-skills"></div>
1517
1609
  <div class="hint" id="skills-meta"></div>
1518
1610
  <div class="row" style="margin-top:8px">
1519
- <button id="skill-sync-btn" class="btn ghost small" data-loading="同步中…">同步套餐技能</button>
1611
+ <button id="skill-sync-btn" class="btn ghost small" data-loading="同步中…">同步技能</button>
1520
1612
  </div>
1521
1613
  <div class="search" style="margin-top:12px">
1522
1614
  <input id="search-input" placeholder="搜索技能市场,如:数据 / 报告 / lark" />
@@ -1532,11 +1624,11 @@ export function statusPageHtml() {
1532
1624
 
1533
1625
  <div class="tabpane" id="pane-plugins" hidden>
1534
1626
  <div class="card">
1535
- <h3>平台默认能力 <button id="defaults-sync-btn" class="btn ghost small" style="margin-left:auto">检查并更新</button></h3>
1536
- <div id="defaults-body" aria-live="polite"><div class="skill-sub">检查中…</div></div>
1537
- </div>
1538
- <div class="card">
1539
- <h3>dsh 插件 <span class="muted">当前 profile 已安装的插件</span></h3>
1627
+ <h3>dsh 插件 <span class="muted">当前 profile 已安装的插件</span>
1628
+ <button id="defaults-sync-btn" class="btn ghost small" style="margin-left:auto" hidden>检查并更新</button>
1629
+ </h3>
1630
+ <div id="defaults-meta" aria-live="polite"></div>
1631
+ <div id="defaults-plugins"></div>
1540
1632
  <div id="plugins-list"></div>
1541
1633
  <div class="hint" id="plugins-hint">受管技能和插件始终更新到最新发布版本;仅管理员停用后可卸载受管插件。</div>
1542
1634
  </div>
package/lib/proc.js CHANGED
@@ -288,7 +288,13 @@ export function scriptInvocation(resolved, args, {
288
288
  execPath = process.execPath,
289
289
  } = {}) {
290
290
  if (!/\.(?:mjs|cjs)$/i.test(String(resolved || ''))) return null;
291
- if (runtime?.node) return { file: runtime.node, args: [resolved, ...args], env: {} };
291
+ if (runtime?.node) {
292
+ // Windows 的 node 启动器可能是 .cmd shim(runtime/bin/node.cmd 要求
293
+ // DSH_DESKTOP_NODE_EXECUTABLE 指向真实可执行文件,与
294
+ // desktopShimEnvDefaults 同一约定);真实 node.exe 则无需任何变量
295
+ const env = /\.cmd$/i.test(runtime.node) ? { DSH_DESKTOP_NODE_EXECUTABLE: execPath } : {};
296
+ return { file: runtime.node, args: [resolved, ...args], env };
297
+ }
292
298
  if (electron) {
293
299
  return { file: execPath, args: [resolved, ...args], env: { ELECTRON_RUN_AS_NODE: '1' } };
294
300
  }
@@ -590,10 +596,14 @@ export async function runCliTool(tool, args, { timeoutMs = 300000, cwd, env, sig
590
596
  function missingCommandGuidance(tool) {
591
597
  if (tool === 'npm' || tool === 'npx') {
592
598
  // 触达这里的机器连桌面壳自带工具链都没有(scriptInvocation/兜底映射
593
- // 均未命中)——重启通常能恢复探测,再给手动安装出路
599
+ // 均未命中)——重启通常能恢复探测,再给手动安装出路。社区桌面端
600
+ // (DSH Desktop/NEXT)与官方壳分开点名,避免指错重启对象
601
+ const brand = /DSH (?:Desktop|NEXT)\.(?:app|exe)/i.test(process.execPath)
602
+ ? 'DSH Desktop'
603
+ : 'DeepSeek Harness';
594
604
  return process.platform === 'win32'
595
- ? '未找到 npm/npx 命令:lark-cli 依赖 Node.js 环境,请先从 https://nodejs.org 下载安装 Node.js(LTS 版,安装时保持默认选项),安装完成后重启 DeepSeek Harness 再点「安装」'
596
- : '未找到 npm/npx 命令:lark-cli 依赖 Node.js 环境,且未探测到 DeepSeek Harness 自带的 Node 运行时。请重启 DeepSeek Harness 后重试;仍失败时安装 Node.js(推荐 nvm:nvm install --lts)后再点「安装」';
605
+ ? `未找到 npm/npx 命令:lark-cli 依赖 Node.js 环境,请先从 https://nodejs.org 下载安装 Node.js(LTS 版,安装时保持默认选项),安装完成后重启 ${brand} 再点「安装」`
606
+ : `未找到 npm/npx 命令:lark-cli 依赖 Node.js 环境,且未探测到 ${brand} 自带的 Node 运行时。请重启 ${brand} 后重试;仍失败时安装 Node.js(推荐 nvm:nvm install --lts)后再点「安装」`;
597
607
  }
598
608
  if (tool === 'pnpm') {
599
609
  return '未找到 pnpm 命令,无法查询插件最新版本。可安装 pnpm(npm install -g pnpm)后重启 DSH Desktop;不影响插件正常使用,仅影响升级提示。';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-agentone",
3
- "version": "0.5.44",
4
- "description": "AgentOne 平台集成:平台模型、SkillHub 技能、套餐与 CLI;无 Node 的 macOS 用桌面壳自带工具链装 lark-cli",
3
+ "version": "1.0.0",
4
+ "description": "AgentOne 平台集成:平台模型、SkillHub 技能、套餐与 CLI;平台清单融入技能/插件双 Tab,无 Node 机器用桌面壳自带工具链装 lark-cli",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "smoke": "node scripts/env-matrix-smoke.mjs"