dsh-nextsteps 1.4.5 → 1.4.7
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/client.js +27 -38
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -10,6 +10,8 @@ window.__ModuleLoader__.load({
|
|
|
10
10
|
const MAX_FOLLOWUPS = 6;
|
|
11
11
|
const PROMPT_TRUNCATE = 60;
|
|
12
12
|
const CLICKED_KEY = 'dsh-nextsteps.clicked';
|
|
13
|
+
const UPDATE_KEY = 'dsh-nextsteps.updated';
|
|
14
|
+
const remembered = () => { try { return localStorage.getItem(UPDATE_KEY); } catch { return null; } };
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
const CSS = `
|
|
@@ -369,6 +371,8 @@ window.__ModuleLoader__.load({
|
|
|
369
371
|
'zh-CN': {"header":"建议的后续操作","srFollowupSent":"后续操作已发送","sendFailed":"发送失败:","intro":"在每个智能体回合完成后的下方推荐下一步提示——单击即可发送。","setLanguage":"语言","setLanguageTip":"后续操作提示将以此语言生成。“自动”会跟随对话语言。","optAuto":"自动(跟随对话)","setModel":"模型","setModelTip":"生成建议的模型。自动会跟随对话所用的模型。","optModelAuto":"自动(与对话相同的模型)","modelUnavailable":"此安装没有可用的模型列表","setMax":"每回合提示数","setMaxTip":"模型应生成的建议提示数量(1-6)。","setHeader":"显示标题","setHeaderTip":"卡片上方的小标题“建议的后续操作”。","updates":"更新","current":"版本","checking":"检查中…","upToDate":"已是最新","available":"{v} 可用","manualCopy":"开发或重命名的副本——请手动更新。","installing":"正在安装 {v}…","restartMsg":"版本 {v} 已安装。请重启 dsh 以使用。","noReleases":"尚未发布任何版本","checkFailed":"检查更新失败({e})","updateNow":"立即更新","check":"检查更新","openRelease":"打开发布页","releaseNotes":"发布说明","repo":"GitHub 仓库","issues":"反馈问题"}
|
|
370
372
|
};
|
|
371
373
|
let pluginSettings = { lang: 'auto', maxFollowups: 3, showHeader: true };
|
|
374
|
+
let updateManager = undefined;
|
|
375
|
+
|
|
372
376
|
let pluginVersion;
|
|
373
377
|
|
|
374
378
|
async function responseJson(response) {
|
|
@@ -555,58 +559,34 @@ window.__ModuleLoader__.load({
|
|
|
555
559
|
const response = await fetch(UPDATE_ROUTE, { cache: 'no-store' });
|
|
556
560
|
const info = await responseJson(response);
|
|
557
561
|
if (!response.ok || info === null || typeof info !== 'object' || info.error !== undefined) throw new Error(info?.error ?? 'HTTP ' + response.status);
|
|
558
|
-
|
|
562
|
+
const status = info.newer !== true ? 'current' : remembered() === info.latest ? 'restart' : info.managed ? 'available' : 'manual';
|
|
563
|
+
setUpdate({ status, info });
|
|
559
564
|
} catch (error) {
|
|
560
565
|
setUpdate((previous) => previous.status === 'restart' ? previous : { status: 'error', info: previous.info, error: String(error?.message ?? error) });
|
|
561
566
|
}
|
|
562
567
|
};
|
|
563
568
|
const install = async () => {
|
|
564
569
|
const { info } = update;
|
|
565
|
-
|
|
566
|
-
try {
|
|
567
|
-
pluginManager = ctx.remote?.pluginManager ?? ctx.get?.('remote')?.pluginManager;
|
|
568
|
-
} catch { pluginManager = undefined; }
|
|
569
|
-
if (info === undefined) return;
|
|
570
|
-
if (pluginManager === undefined || typeof pluginManager.installBundle !== 'function') {
|
|
570
|
+
if (info === undefined || updateManager === undefined) {
|
|
571
571
|
setUpdate({ status: 'error', info, error: 'the plugin manager is not available in this install' });
|
|
572
572
|
return;
|
|
573
573
|
}
|
|
574
574
|
setUpdate({ status: 'installing', info });
|
|
575
575
|
try {
|
|
576
576
|
const requestId = NS + '-update-' + info.latest + '-' + Date.now();
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
const reply = await manager.waitForInstall(id);
|
|
581
|
-
if (reply === null || typeof reply !== 'object' || reply.ok !== true) return undefined;
|
|
582
|
-
return reply.value ?? undefined;
|
|
583
|
-
} catch { return undefined; }
|
|
584
|
-
};
|
|
585
|
-
const attempt = async (spec) => {
|
|
586
|
-
const reply = await pluginManager.installBundle(spec, { enabled: true, requestId });
|
|
587
|
-
if (reply === null || typeof reply !== 'object' || reply.ok !== true) throw new Error(reply?.error?.message ?? 'plugin manager did not answer');
|
|
577
|
+
const installSpec = async (spec) => {
|
|
578
|
+
const reply = await updateManager.installBundle(spec, { requestId });
|
|
579
|
+
if (!reply?.ok) throw new Error(reply?.error?.message ?? 'plugin manager did not answer');
|
|
588
580
|
return reply.value;
|
|
589
581
|
};
|
|
590
|
-
let result;
|
|
591
|
-
if (
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
result = reply.value;
|
|
599
|
-
}
|
|
600
|
-
} else {
|
|
601
|
-
result = await attempt(NPM_NAME + '@' + info.latest);
|
|
602
|
-
if (result !== null && typeof result === 'object' && result.error?.code === 'already-installed') result = await attempt('https://registry.npmjs.org/' + NPM_NAME + '/-/' + NPM_NAME + '-' + info.latest + '.tgz');
|
|
603
|
-
}
|
|
604
|
-
const applied = result !== null && typeof result === 'object' && (result.application === 'applied' || result.application === 'restart-required' || result.version === info.latest);
|
|
605
|
-
if (!applied) {
|
|
606
|
-
const diagnostic = typeof result?.error?.diagnostic === 'string' ? result.error.diagnostic.split('\n').find((entry) => entry.trim() !== '') : undefined;
|
|
607
|
-
throw new Error(diagnostic ?? result?.error?.code ?? 'install failed');
|
|
608
|
-
}
|
|
609
|
-
setUpdate(result.application === 'applied'
|
|
582
|
+
let result = await installSpec(NPM_NAME + '@' + info.latest);
|
|
583
|
+
if (result?.error?.code === 'already-installed') result = await installSpec('https://registry.npmjs.org/' + NPM_NAME + '/-/' + NPM_NAME + '-' + info.latest + '.tgz');
|
|
584
|
+
const firstLine = () => result?.error?.diagnostic?.split(String.fromCharCode(10)).find((line) => line.trim() !== '') ?? result?.error?.code ?? result?.application;
|
|
585
|
+
const live = result?.application === 'applied';
|
|
586
|
+
if (!live && result?.application !== 'restart-required' && result?.version !== info.latest) throw new Error(firstLine());
|
|
587
|
+
if (result?.application === 'failed') console.warn(`dsh-nextsteps: ${info.latest} is installed; dsh could not start it before a restart: ${firstLine()}`);
|
|
588
|
+
try { localStorage.setItem(UPDATE_KEY, info.latest); } catch { }
|
|
589
|
+
setUpdate(live
|
|
610
590
|
? { status: 'current', info: { ...info, current: info.latest, newer: false } }
|
|
611
591
|
: { status: 'restart', info });
|
|
612
592
|
} catch (error) {
|
|
@@ -665,6 +645,15 @@ window.__ModuleLoader__.load({
|
|
|
665
645
|
return {
|
|
666
646
|
inject: ['slots', 'locale', 'remote'],
|
|
667
647
|
apply(ctx) {
|
|
648
|
+
const injectScope = (deps, setup) => {
|
|
649
|
+
if (ctx.inject === undefined) return [];
|
|
650
|
+
const fiber = ctx.inject(deps, setup);
|
|
651
|
+
return [() => fiber.dispose()];
|
|
652
|
+
};
|
|
653
|
+
for (const off of injectScope(['remote.pluginManager'], (scope) => {
|
|
654
|
+
updateManager = scope.remote?.pluginManager;
|
|
655
|
+
scope.effect(() => () => { updateManager = undefined; }, 'dsh-nextsteps: update installer');
|
|
656
|
+
})) if (ctx.effect !== undefined) ctx.effect(() => off, 'dsh-nextsteps: update installer scope');
|
|
668
657
|
installStyles(ctx);
|
|
669
658
|
rehydrateCaptures();
|
|
670
659
|
refreshPluginSettings();
|