dsh-plugin-effort-declare 0.1.2 → 0.1.3
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/CONTRIBUTING.en.md +2 -0
- package/CONTRIBUTING.md +2 -0
- package/INSTALL.en.md +1 -1
- package/INSTALL.md +1 -1
- package/README.en.md +2 -1
- package/README.md +2 -1
- package/lib/client.js +242 -53
- package/lib/client.js.map +1 -1
- package/lib/types/client/EffortDeclareSection.d.ts +12 -2
- package/lib/types/client/EffortDeclareSection.d.ts.map +1 -1
- package/lib/types/client/build-info.d.ts +2 -0
- package/lib/types/client/build-info.d.ts.map +1 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/load-drafts.d.ts +36 -6
- package/lib/types/client/load-drafts.d.ts.map +1 -1
- package/lib/types/core/attribution.d.ts +13 -0
- package/lib/types/core/attribution.d.ts.map +1 -0
- package/lib/types/core/efforts.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/README.en.md +1 -1
- package/src/README.md +1 -1
- package/src/client/EffortDeclareSection.tsx +143 -41
- package/src/client/README.en.md +5 -3
- package/src/client/README.md +5 -3
- package/src/client/build-info.ts +12 -0
- package/src/client/effort-declare.module.css +8 -0
- package/src/client/globals.d.ts +5 -0
- package/src/client/index.ts +13 -11
- package/src/client/load-drafts.ts +124 -8
- package/src/core/README.en.md +2 -1
- package/src/core/README.md +2 -1
- package/src/core/attribution.ts +24 -0
- package/src/core/efforts.ts +4 -1
package/CONTRIBUTING.en.md
CHANGED
|
@@ -52,6 +52,8 @@ pnpm pack # confirm the tarball contains lib/ and cordis.patch.yml
|
|
|
52
52
|
pnpm publish
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
The settings footer version and copyright end year are frozen into the client bundle at `pnpm build` (`package.json` version plus the UTC year at that moment). Bump the version, then build / publish. Do not read the wall clock at DSH startup.
|
|
56
|
+
|
|
55
57
|
`pnpm publish` fails on an unclean Git tree. Commit first (and preferably push). Do not pass `--no-git-checks`.
|
|
56
58
|
|
|
57
59
|
After publish, users update with `dsh plugin --profile web update dsh-plugin-effort-declare` or `add dsh-plugin-effort-declare@latest`. Authors do not implement an update command; official `dsh plugin` forwards the rest of the line to pnpm.
|
package/CONTRIBUTING.md
CHANGED
|
@@ -52,6 +52,8 @@ pnpm pack # 确认 tarball 含 lib/ 与 cordis.patch.yml
|
|
|
52
52
|
pnpm publish
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
页脚版本与版权结束年在 `pnpm build` 时写入 client bundle(`package.json` 的 version + 当时的 UTC 年)。先改 version 再 build / publish。不要在运行时读系统时钟。
|
|
56
|
+
|
|
55
57
|
`pnpm publish` 在 Git 有未提交改动时会失败。应先 commit(建议再 push),不要用 `--no-git-checks` 绕过。
|
|
56
58
|
|
|
57
59
|
发布后用户用 `dsh plugin --profile web update dsh-plugin-effort-declare` 或 `add dsh-plugin-effort-declare@latest` 更新。作者无需在插件里实现更新命令;官方 `dsh plugin` 会把参数转给 pnpm。
|
package/INSTALL.en.md
CHANGED
|
@@ -83,7 +83,7 @@ dsh plugin --profile web add file:/absolute/path/to/dsh-plugin-effort-declare
|
|
|
83
83
|
|
|
84
84
|
## After install
|
|
85
85
|
|
|
86
|
-
Restart DSH. Open **Settings → Reasoning efforts**. Add a custom provider on the Models page first; otherwise this page has nothing to edit.
|
|
86
|
+
Restart DSH. Open **Settings → Reasoning efforts**. The footer is the installed version (for example `0.1.3 © 2026 Stardust`); bumping `package.json` only shows up after you rebuild and reinstall. Add a custom provider on the Models page first; otherwise this page has nothing to edit.
|
|
87
87
|
|
|
88
88
|
## Uninstall
|
|
89
89
|
|
package/INSTALL.md
CHANGED
|
@@ -83,7 +83,7 @@ dsh plugin --profile web add file:/绝对路径/dsh-plugin-effort-declare
|
|
|
83
83
|
|
|
84
84
|
## 装完之后
|
|
85
85
|
|
|
86
|
-
重启 DSH。打开 **设置 →
|
|
86
|
+
重启 DSH。打开 **设置 → 推理档位**。页脚是当前装上的版本(例如 `0.1.3 © 2026 Stardust`),改 `package.json` 后必须重新打包再安装才会变。先在「模型」页添加第三方提供方,本页才会出现可编辑的条目。
|
|
87
87
|
|
|
88
88
|
## 卸载
|
|
89
89
|
|
package/README.en.md
CHANGED
|
@@ -34,6 +34,7 @@ Hand-added third-party providers on the Models page need a reasoning-level decla
|
|
|
34
34
|
| Reasoning efforts page | Choose levels per model; change the gateway spelling if it differs |
|
|
35
35
|
| Presets | DeepSeek compatible, OpenAI compatible, or on/off only. A preset **replaces** that dialect; it does not stack |
|
|
36
36
|
| vs Models | Models owns the endpoint, keys, and model list; this page only declares which reasoning levels are offered |
|
|
37
|
+
| Version footer | Bottom of the page shows the plugin version and copyright years (frozen at pack time; opening DSH does not advance the year) |
|
|
37
38
|
|
|
38
39
|
## Install
|
|
39
40
|
|
|
@@ -51,7 +52,7 @@ dsh plugin --profile web update dsh-plugin-effort-declare
|
|
|
51
52
|
|
|
52
53
|
Or `add dsh-plugin-effort-declare@latest`. Details: [install guide](./INSTALL.en.md) **Update**.
|
|
53
54
|
|
|
54
|
-
Restart DSH, then open **Settings → Reasoning efforts**. Add a custom provider on the Models page first. GitHub, local folder, and uninstall: [install guide](./INSTALL.en.md).
|
|
55
|
+
Restart DSH, then open **Settings → Reasoning efforts**. The footer shows which version is installed. Add a custom provider on the Models page first. GitHub, local folder, and uninstall: [install guide](./INSTALL.en.md).
|
|
55
56
|
|
|
56
57
|
## Usage
|
|
57
58
|
|
package/README.md
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
| 推理档位页 | 按模型勾选可选档位;网关用的名字如果不同,可以改拼写 |
|
|
35
35
|
| 预设 | DeepSeek 兼容、OpenAI 兼容、只开/关思考。点预设会换成那一套,不是叠加上去 |
|
|
36
36
|
| 和「模型」页 | 「模型」管地址、密钥和模型名单;本页只管「能选哪些推理档」 |
|
|
37
|
+
| 版本页脚 | 页面底部显示当前插件版本与版权年(打包时写入;打开 DSH 不会跟着日历变) |
|
|
37
38
|
|
|
38
39
|
## 安装
|
|
39
40
|
|
|
@@ -51,7 +52,7 @@ dsh plugin --profile web update dsh-plugin-effort-declare
|
|
|
51
52
|
|
|
52
53
|
或 `add dsh-plugin-effort-declare@latest`。详见 [安装说明](./INSTALL.md) 的「更新」。
|
|
53
54
|
|
|
54
|
-
装完后重启 DSH,打开 **设置 →
|
|
55
|
+
装完后重启 DSH,打开 **设置 → 推理档位**。页脚可核对装上的版本。请先在「模型」页添加过第三方提供方。GitHub、本地文件夹和卸载也在 [安装说明](./INSTALL.md)。
|
|
55
56
|
|
|
56
57
|
## 使用
|
|
57
58
|
|
package/lib/client.js
CHANGED
|
@@ -389,7 +389,10 @@ window.__ModuleLoader__.load({
|
|
|
389
389
|
const next = { ...efforts };
|
|
390
390
|
delete next.off;
|
|
391
391
|
if (mode === "empty") next.off = null;
|
|
392
|
-
else if (mode === "value")
|
|
392
|
+
else if (mode === "value") {
|
|
393
|
+
const trimmed = value.trim();
|
|
394
|
+
next.off = trimmed.length > 0 ? trimmed : "none";
|
|
395
|
+
}
|
|
393
396
|
return next;
|
|
394
397
|
}
|
|
395
398
|
/** Whether a thinking level (other than Off) is currently declared. */
|
|
@@ -528,20 +531,104 @@ window.__ModuleLoader__.load({
|
|
|
528
531
|
return validateReasoningEfforts(row.reasoningEfforts);
|
|
529
532
|
}
|
|
530
533
|
//#endregion
|
|
534
|
+
//#region src/core/attribution.ts
|
|
535
|
+
/**
|
|
536
|
+
* Plugin footer attribution. Version and end-year are frozen into the client
|
|
537
|
+
* bundle at pack time; this module only formats the line.
|
|
538
|
+
*/
|
|
539
|
+
/** First publication year (LICENSE). Not the user's wall clock. */
|
|
540
|
+
const COPYRIGHT_FROM = 2026;
|
|
541
|
+
const COPYRIGHT_HOLDER = "Stardust";
|
|
542
|
+
/**
|
|
543
|
+
* `0.1.2 © 2026 Stardust` or `0.1.2 © 2026–2027 Stardust`.
|
|
544
|
+
* Throws if version is empty or `to < from` — a bad stamp must not render.
|
|
545
|
+
*/
|
|
546
|
+
function formatAttribution(version, from, to) {
|
|
547
|
+
if (version.trim() === "") throw new Error("plugin version must be a non-empty string");
|
|
548
|
+
if (!Number.isInteger(from) || !Number.isInteger(to) || to < from) throw new Error(`invalid copyright range: ${String(from)}\u2013${String(to)}`);
|
|
549
|
+
return `${version} \u00a9 ${to === from ? String(from) : `${String(from)}\u2013${String(to)}`} ${COPYRIGHT_HOLDER}`;
|
|
550
|
+
}
|
|
551
|
+
//#endregion
|
|
552
|
+
//#region src/client/build-info.ts
|
|
553
|
+
/**
|
|
554
|
+
* Footer line frozen into the client bundle. Do not read the clock or
|
|
555
|
+
* package.json at DSH startup — host apply is empty and the settings page
|
|
556
|
+
* runs in the browser.
|
|
557
|
+
*/
|
|
558
|
+
const PLUGIN_FOOTER_TEXT = formatAttribution("0.1.3", COPYRIGHT_FROM, 2026);
|
|
559
|
+
//#endregion
|
|
531
560
|
//#region src/client/load-drafts.ts
|
|
532
561
|
function schemaDefaultString(node) {
|
|
533
562
|
if (!isPlainObject(node) || !isPlainObject(node.meta)) return void 0;
|
|
534
563
|
return typeof node.meta.default === "string" ? node.meta.default : void 0;
|
|
535
564
|
}
|
|
565
|
+
/** Namespace revision on a describe snapshot, if that row exists. */
|
|
566
|
+
function namespaceRevision(snapshot, ns) {
|
|
567
|
+
return snapshot.view?.namespaces.find((view) => view.ns === ns)?.revision;
|
|
568
|
+
}
|
|
536
569
|
/**
|
|
537
|
-
*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
|
|
541
|
-
|
|
570
|
+
* True when `incoming` is the Host echo of a mutate this page already folded,
|
|
571
|
+
* or an older revision the snapshot has already passed. `echoed` is undefined
|
|
572
|
+
* until the first successful write.
|
|
573
|
+
*/
|
|
574
|
+
function isOwnDocumentEcho(echoed, incoming) {
|
|
575
|
+
return echoed !== void 0 && incoming <= echoed;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* After a preserve-dirty reload: conflicted cards get a conflict notice;
|
|
579
|
+
* live cards drop leftover conflict/error; saved notices stay; gone cards drop.
|
|
542
580
|
*/
|
|
543
|
-
|
|
544
|
-
|
|
581
|
+
function foldReloadNotices(current, args) {
|
|
582
|
+
const live = new Set(args.liveProviders);
|
|
583
|
+
const conflicted = new Set(args.conflicted);
|
|
584
|
+
const next = {};
|
|
585
|
+
for (const [provider, notice] of Object.entries(current)) {
|
|
586
|
+
if (!live.has(provider)) continue;
|
|
587
|
+
if (conflicted.has(provider)) continue;
|
|
588
|
+
if (notice.kind === "conflict" || notice.kind === "error") continue;
|
|
589
|
+
next[provider] = notice;
|
|
590
|
+
}
|
|
591
|
+
for (const provider of args.conflicted) next[provider] = args.conflictNotice;
|
|
592
|
+
return next;
|
|
593
|
+
}
|
|
594
|
+
function waitUntil(describe, predicate, signal) {
|
|
595
|
+
if (signal?.aborted) return Promise.resolve(false);
|
|
596
|
+
if (predicate()) return Promise.resolve(true);
|
|
597
|
+
return new Promise((resolve) => {
|
|
598
|
+
let settled = false;
|
|
599
|
+
const finish = (ok) => {
|
|
600
|
+
if (settled) return;
|
|
601
|
+
settled = true;
|
|
602
|
+
stop();
|
|
603
|
+
signal?.removeEventListener("abort", onAbort);
|
|
604
|
+
resolve(ok);
|
|
605
|
+
};
|
|
606
|
+
const onAbort = () => {
|
|
607
|
+
finish(false);
|
|
608
|
+
};
|
|
609
|
+
const stop = describe.subscribe(() => {
|
|
610
|
+
if (predicate()) finish(true);
|
|
611
|
+
});
|
|
612
|
+
signal?.addEventListener("abort", onAbort);
|
|
613
|
+
if (predicate()) finish(true);
|
|
614
|
+
else if (signal?.aborted) finish(false);
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
/** Resolve when the mirror's namespace revision is at least `revision`, or abort. */
|
|
618
|
+
async function waitForNamespaceRevision(describe, ns, revision, signal) {
|
|
619
|
+
return await waitUntil(describe, () => {
|
|
620
|
+
const current = namespaceRevision(describe.getSnapshot(), ns);
|
|
621
|
+
return current !== void 0 && current >= revision;
|
|
622
|
+
}, signal) ? "matched" : "aborted";
|
|
623
|
+
}
|
|
624
|
+
/** Resolve when the namespace revision differs from `previous`, or abort. */
|
|
625
|
+
async function waitForNamespaceRevisionChange(describe, ns, previous, signal) {
|
|
626
|
+
return await waitUntil(describe, () => {
|
|
627
|
+
const current = namespaceRevision(describe.getSnapshot(), ns);
|
|
628
|
+
return current !== void 0 && current !== previous;
|
|
629
|
+
}, signal) ? "changed" : "aborted";
|
|
630
|
+
}
|
|
631
|
+
async function assembleDrafts(api, describe, schema) {
|
|
545
632
|
const mirrored = describe.getSnapshot();
|
|
546
633
|
if (mirrored.view === void 0) return {
|
|
547
634
|
writable: false,
|
|
@@ -592,6 +679,14 @@ window.__ModuleLoader__.load({
|
|
|
592
679
|
drafts
|
|
593
680
|
};
|
|
594
681
|
}
|
|
682
|
+
/**
|
|
683
|
+
* `ensure`: first paint / idle recovery (official ensure only reads from idle).
|
|
684
|
+
* `snapshot`: refresh after the mirror revision already moved — do not ensure.
|
|
685
|
+
*/
|
|
686
|
+
async function loadDrafts(api, describe, schema, mode = "ensure") {
|
|
687
|
+
if (mode === "ensure") await describe.ensure();
|
|
688
|
+
return assembleDrafts(api, describe, schema);
|
|
689
|
+
}
|
|
595
690
|
//#endregion
|
|
596
691
|
//#region src/client/schema-ops.ts
|
|
597
692
|
/** Wrap a live settingsSchema service as plain callbacks. */
|
|
@@ -624,7 +719,7 @@ window.__ModuleLoader__.load({
|
|
|
624
719
|
}
|
|
625
720
|
//#endregion
|
|
626
721
|
//#region \0dsh-css:C:\Users\zimo\AppData\Roaming\io.github.hairyf.deepseek-harness-desktop\data\dsh\临时目录\dsh-plugin-effort-declare\src\client\effort-declare.module.css.mjs
|
|
627
|
-
const cssText = ".hYEBUa_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.hYEBUa_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.hYEBUa_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.hYEBUa_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.hYEBUa_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.hYEBUa_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.hYEBUa_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.hYEBUa_rowCard{border:1px solid var(--dsw-alias-border-l2);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.hYEBUa_rowHead{align-items:baseline;gap:8px;display:flex}.hYEBUa_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.hYEBUa_rowTag{border:1px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.hYEBUa_compatSummary{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.hYEBUa_presetRow,.hYEBUa_actions{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.hYEBUa_fieldLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.hYEBUa_primaryButton,.hYEBUa_secondaryButton{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border-radius:18px;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.hYEBUa_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);border:none}.hYEBUa_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.hYEBUa_secondaryButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.hYEBUa_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.hYEBUa_primaryButton:disabled,.hYEBUa_secondaryButton:disabled,.hYEBUa_linkButton:disabled,.hYEBUa_input:disabled{opacity:.4;cursor:default}.hYEBUa_primaryButton:focus-visible,.hYEBUa_secondaryButton:focus-visible,.hYEBUa_linkButton:focus-visible,.hYEBUa_input:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.hYEBUa_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.hYEBUa_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.hYEBUa_modelEntry{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;padding:10px 0;display:flex}.hYEBUa_modelHead{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.hYEBUa_modelId{font-size:13px;font-weight:500;line-height:20px}.hYEBUa_modelName{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.hYEBUa_levels{flex-wrap:wrap;gap:10px 14px;display:flex}.hYEBUa_level{align-items:center;gap:6px;font-size:12px;line-height:18px;display:inline-flex}.hYEBUa_wireRow{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.hYEBUa_input,.hYEBUa_selectInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);height:32px;color:var(--dsw-alias-label-primary);font:inherit;border-radius:8px;padding:0 10px;font-size:13px}.hYEBUa_wireInput{width:7em}.hYEBUa_offGroup{flex-direction:column;gap:6px;display:flex}.hYEBUa_advanced{border-top:1px solid var(--dsw-alias-border-l2);padding-top:8px}.hYEBUa_advanced summary{cursor:pointer;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.hYEBUa_advancedBody{flex-direction:column;gap:10px;padding-top:10px;display:flex}.hYEBUa_check{align-items:flex-start;gap:8px;font-size:12px;line-height:18px;display:flex}";
|
|
722
|
+
const cssText = ".hYEBUa_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.hYEBUa_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.hYEBUa_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.hYEBUa_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.hYEBUa_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.hYEBUa_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.hYEBUa_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.hYEBUa_rowCard{border:1px solid var(--dsw-alias-border-l2);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.hYEBUa_rowHead{align-items:baseline;gap:8px;display:flex}.hYEBUa_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.hYEBUa_rowTag{border:1px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.hYEBUa_compatSummary{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.hYEBUa_presetRow,.hYEBUa_actions{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.hYEBUa_fieldLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.hYEBUa_primaryButton,.hYEBUa_secondaryButton{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border-radius:18px;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.hYEBUa_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);border:none}.hYEBUa_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.hYEBUa_secondaryButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.hYEBUa_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.hYEBUa_primaryButton:disabled,.hYEBUa_secondaryButton:disabled,.hYEBUa_linkButton:disabled,.hYEBUa_input:disabled{opacity:.4;cursor:default}.hYEBUa_primaryButton:focus-visible,.hYEBUa_secondaryButton:focus-visible,.hYEBUa_linkButton:focus-visible,.hYEBUa_input:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.hYEBUa_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.hYEBUa_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.hYEBUa_modelEntry{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;padding:10px 0;display:flex}.hYEBUa_modelHead{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.hYEBUa_modelId{font-size:13px;font-weight:500;line-height:20px}.hYEBUa_modelName{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.hYEBUa_levels{flex-wrap:wrap;gap:10px 14px;display:flex}.hYEBUa_level{align-items:center;gap:6px;font-size:12px;line-height:18px;display:inline-flex}.hYEBUa_wireRow{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.hYEBUa_input,.hYEBUa_selectInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);height:32px;color:var(--dsw-alias-label-primary);font:inherit;border-radius:8px;padding:0 10px;font-size:13px}.hYEBUa_wireInput{width:7em}.hYEBUa_offGroup{flex-direction:column;gap:6px;display:flex}.hYEBUa_advanced{border-top:1px solid var(--dsw-alias-border-l2);padding-top:8px}.hYEBUa_advanced summary{cursor:pointer;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.hYEBUa_advancedBody{flex-direction:column;gap:10px;padding-top:10px;display:flex}.hYEBUa_check{align-items:flex-start;gap:8px;font-size:12px;line-height:18px;display:flex}.hYEBUa_footer{color:var(--dsw-alias-label-tertiary);opacity:.7;margin:16px 0 0;font-size:11px;line-height:16px}";
|
|
628
723
|
const cssTagId = "dsh-plugin-effort-declare/effort-declare.module.css";
|
|
629
724
|
var effort_declare_module_css_default = {
|
|
630
725
|
"actions": "hYEBUa_actions",
|
|
@@ -634,6 +729,7 @@ window.__ModuleLoader__.load({
|
|
|
634
729
|
"compatSummary": "hYEBUa_compatSummary",
|
|
635
730
|
"error": "hYEBUa_error",
|
|
636
731
|
"fieldLabel": "hYEBUa_fieldLabel",
|
|
732
|
+
"footer": "hYEBUa_footer",
|
|
637
733
|
"input": "hYEBUa_input",
|
|
638
734
|
"intro": "hYEBUa_intro",
|
|
639
735
|
"level": "hYEBUa_level",
|
|
@@ -999,40 +1095,75 @@ window.__ModuleLoader__.load({
|
|
|
999
1095
|
const [notices, setNotices] = (0, react.useState)({});
|
|
1000
1096
|
const generationRef = (0, react.useRef)(0);
|
|
1001
1097
|
const draftsRef = (0, react.useRef)(drafts);
|
|
1098
|
+
const echoedRevisionRef = (0, react.useRef)(void 0);
|
|
1099
|
+
const pendingRevisionRef = (0, react.useRef)(void 0);
|
|
1100
|
+
const busyRouteRef = (0, react.useRef)(null);
|
|
1101
|
+
const abortRef = (0, react.useRef)(null);
|
|
1002
1102
|
draftsRef.current = drafts;
|
|
1003
|
-
const
|
|
1103
|
+
const applyDrafts = (next) => {
|
|
1104
|
+
const resolved = typeof next === "function" ? next(draftsRef.current) : next;
|
|
1105
|
+
draftsRef.current = resolved;
|
|
1106
|
+
setDrafts(resolved);
|
|
1107
|
+
};
|
|
1108
|
+
const snapshotMode = () => describe === void 0 || describe.getSnapshot().status === "idle" ? "ensure" : "snapshot";
|
|
1109
|
+
const beginGeneration = () => {
|
|
1110
|
+
abortRef.current?.abort();
|
|
1111
|
+
const abort = new AbortController();
|
|
1112
|
+
abortRef.current = abort;
|
|
1113
|
+
return {
|
|
1114
|
+
generation: nextGeneration(generationRef),
|
|
1115
|
+
signal: abort.signal
|
|
1116
|
+
};
|
|
1117
|
+
};
|
|
1118
|
+
const failGeneration = (generation, failure) => {
|
|
1119
|
+
if (!generationIsCurrent(generationRef, generation)) return;
|
|
1120
|
+
setStatus("error");
|
|
1121
|
+
setError(failure instanceof Error ? failure.message : t("loadError"));
|
|
1122
|
+
};
|
|
1123
|
+
const settleReload = (generation, preserveDirty, result) => {
|
|
1124
|
+
if (!generationIsCurrent(generationRef, generation)) return;
|
|
1125
|
+
setWritable(result.writable);
|
|
1126
|
+
setFormats(result.formats);
|
|
1127
|
+
if (result.error !== void 0) {
|
|
1128
|
+
setStatus("error");
|
|
1129
|
+
setError(result.error);
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
const merged = mergeLoadedDrafts(draftsRef.current, result.drafts, { preserveDirty });
|
|
1133
|
+
applyDrafts(merged.drafts);
|
|
1134
|
+
setNotices((current) => foldReloadNotices(current, {
|
|
1135
|
+
conflicted: merged.conflicted,
|
|
1136
|
+
conflictNotice: {
|
|
1137
|
+
kind: "conflict",
|
|
1138
|
+
text: t("dirtyConflict")
|
|
1139
|
+
},
|
|
1140
|
+
liveProviders: merged.drafts.map((draft) => draft.provider)
|
|
1141
|
+
}));
|
|
1142
|
+
setStatus("ready");
|
|
1143
|
+
};
|
|
1144
|
+
const loadSnapshotThenSettle = async (generation, preserveDirty) => {
|
|
1145
|
+
if (api === void 0 || describe === void 0 || schema === void 0) return;
|
|
1146
|
+
if (!generationIsCurrent(generationRef, generation)) return;
|
|
1147
|
+
try {
|
|
1148
|
+
const result = await loadDrafts(api, describe, schema, "snapshot");
|
|
1149
|
+
settleReload(generation, preserveDirty, result);
|
|
1150
|
+
} catch (failure) {
|
|
1151
|
+
failGeneration(generation, failure);
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
const reload = (0, react.useCallback)((preserveDirty, mode = "ensure") => {
|
|
1004
1155
|
if (api === void 0 || describe === void 0 || schema === void 0) {
|
|
1005
1156
|
setStatus("error");
|
|
1006
1157
|
setError(t("loadError"));
|
|
1007
1158
|
return;
|
|
1008
1159
|
}
|
|
1009
|
-
const generation =
|
|
1160
|
+
const { generation } = beginGeneration();
|
|
1010
1161
|
if (draftsRef.current.length === 0) setStatus("loading");
|
|
1011
1162
|
setError("");
|
|
1012
|
-
loadDrafts(api, describe, schema).then((result) => {
|
|
1013
|
-
|
|
1014
|
-
setWritable(result.writable);
|
|
1015
|
-
setFormats(result.formats);
|
|
1016
|
-
if (result.error !== void 0) {
|
|
1017
|
-
setStatus("error");
|
|
1018
|
-
setError(result.error);
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
const merged = mergeLoadedDrafts(draftsRef.current, result.drafts, { preserveDirty });
|
|
1022
|
-
setDrafts(merged.drafts);
|
|
1023
|
-
if (merged.conflicted.length > 0) setNotices((current) => {
|
|
1024
|
-
const next = { ...current };
|
|
1025
|
-
for (const provider of merged.conflicted) next[provider] = {
|
|
1026
|
-
kind: "conflict",
|
|
1027
|
-
text: t("dirtyConflict")
|
|
1028
|
-
};
|
|
1029
|
-
return next;
|
|
1030
|
-
});
|
|
1031
|
-
setStatus("ready");
|
|
1163
|
+
loadDrafts(api, describe, schema, mode).then((result) => {
|
|
1164
|
+
settleReload(generation, preserveDirty, result);
|
|
1032
1165
|
}, (failure) => {
|
|
1033
|
-
|
|
1034
|
-
setStatus("error");
|
|
1035
|
-
setError(failure instanceof Error ? failure.message : t("loadError"));
|
|
1166
|
+
failGeneration(generation, failure);
|
|
1036
1167
|
});
|
|
1037
1168
|
}, [
|
|
1038
1169
|
api,
|
|
@@ -1040,22 +1171,61 @@ window.__ModuleLoader__.load({
|
|
|
1040
1171
|
schema,
|
|
1041
1172
|
t
|
|
1042
1173
|
]);
|
|
1174
|
+
const refreshAtRevision = (0, react.useCallback)((revision, preserveDirty) => {
|
|
1175
|
+
if (api === void 0 || describe === void 0 || schema === void 0) return;
|
|
1176
|
+
const { generation, signal } = beginGeneration();
|
|
1177
|
+
if (draftsRef.current.length === 0) setStatus("loading");
|
|
1178
|
+
setError("");
|
|
1179
|
+
waitForNamespaceRevision(describe, LLM_PI_AI_NS, revision, signal).then((outcome) => {
|
|
1180
|
+
if (outcome === "aborted" || !generationIsCurrent(generationRef, generation)) return;
|
|
1181
|
+
return loadSnapshotThenSettle(generation, preserveDirty);
|
|
1182
|
+
}, (failure) => {
|
|
1183
|
+
failGeneration(generation, failure);
|
|
1184
|
+
});
|
|
1185
|
+
}, [
|
|
1186
|
+
api,
|
|
1187
|
+
describe,
|
|
1188
|
+
schema,
|
|
1189
|
+
t
|
|
1190
|
+
]);
|
|
1191
|
+
const flushPendingSettings = (refresh) => {
|
|
1192
|
+
const pending = pendingRevisionRef.current;
|
|
1193
|
+
pendingRevisionRef.current = void 0;
|
|
1194
|
+
if (pending === void 0) return;
|
|
1195
|
+
if (isOwnDocumentEcho(echoedRevisionRef.current, pending)) return;
|
|
1196
|
+
refresh(pending, true);
|
|
1197
|
+
};
|
|
1043
1198
|
(0, react.useEffect)(() => {
|
|
1044
|
-
reload(false);
|
|
1199
|
+
reload(false, "ensure");
|
|
1045
1200
|
}, [reload]);
|
|
1201
|
+
(0, react.useEffect)(() => () => {
|
|
1202
|
+
abortRef.current?.abort();
|
|
1203
|
+
nextGeneration(generationRef);
|
|
1204
|
+
}, []);
|
|
1046
1205
|
(0, react.useEffect)(() => {
|
|
1047
1206
|
if (props.subscribeInvalidate === void 0) return void 0;
|
|
1048
|
-
return props.subscribeInvalidate((
|
|
1049
|
-
if (source === "writable") {
|
|
1207
|
+
return props.subscribeInvalidate((event) => {
|
|
1208
|
+
if (event.source === "writable") {
|
|
1050
1209
|
const view = describe?.getSnapshot().view;
|
|
1051
1210
|
if (view !== void 0) setWritable(view.writable);
|
|
1052
1211
|
return;
|
|
1053
1212
|
}
|
|
1054
|
-
if (source === "settings"
|
|
1213
|
+
if (event.source === "settings") {
|
|
1214
|
+
if (busyRouteRef.current !== null) {
|
|
1215
|
+
pendingRevisionRef.current = event.revision;
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1218
|
+
if (isOwnDocumentEcho(echoedRevisionRef.current, event.revision)) return;
|
|
1219
|
+
refreshAtRevision(event.revision, true);
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
if (event.source === "directory") reload(true, snapshotMode());
|
|
1223
|
+
if (event.source === "reset") reload(true, "ensure");
|
|
1055
1224
|
});
|
|
1056
1225
|
}, [
|
|
1057
1226
|
describe,
|
|
1058
1227
|
props.subscribeInvalidate,
|
|
1228
|
+
refreshAtRevision,
|
|
1059
1229
|
reload
|
|
1060
1230
|
]);
|
|
1061
1231
|
const patchNotice = (provider, notice) => {
|
|
@@ -1068,7 +1238,7 @@ window.__ModuleLoader__.load({
|
|
|
1068
1238
|
};
|
|
1069
1239
|
const save = async (draft) => {
|
|
1070
1240
|
if (api === void 0 || describe === void 0 || schema === void 0) return;
|
|
1071
|
-
if (status === "loading" ||
|
|
1241
|
+
if (status === "loading" || busyRouteRef.current !== null) {
|
|
1072
1242
|
patchNotice(draft.provider, {
|
|
1073
1243
|
kind: "error",
|
|
1074
1244
|
text: t("saveBusy")
|
|
@@ -1083,6 +1253,7 @@ window.__ModuleLoader__.load({
|
|
|
1083
1253
|
});
|
|
1084
1254
|
return;
|
|
1085
1255
|
}
|
|
1256
|
+
busyRouteRef.current = draft.provider;
|
|
1086
1257
|
setBusyRoute(draft.provider);
|
|
1087
1258
|
patchNotice(draft.provider, void 0);
|
|
1088
1259
|
try {
|
|
@@ -1094,7 +1265,7 @@ window.__ModuleLoader__.load({
|
|
|
1094
1265
|
afterCompat: draft.compat
|
|
1095
1266
|
});
|
|
1096
1267
|
if (ops.length === 0) {
|
|
1097
|
-
|
|
1268
|
+
applyDrafts((current) => current.map((row) => row.provider === draft.provider ? alignDraft(row) : row));
|
|
1098
1269
|
return;
|
|
1099
1270
|
}
|
|
1100
1271
|
const willWriteCompat = ops.some((op) => op.path.length > draft.settingsPath.length && op.path[draft.settingsPath.length] === "compat");
|
|
@@ -1128,12 +1299,21 @@ window.__ModuleLoader__.load({
|
|
|
1128
1299
|
kind: conflict ? "conflict" : "error",
|
|
1129
1300
|
text: conflict ? t("conflict") : response.result.error.message
|
|
1130
1301
|
});
|
|
1131
|
-
if (conflict)
|
|
1302
|
+
if (conflict) {
|
|
1303
|
+
const { generation, signal } = beginGeneration();
|
|
1304
|
+
waitForNamespaceRevisionChange(describe, LLM_PI_AI_NS, draft.revision, signal).then((outcome) => {
|
|
1305
|
+
if (outcome === "aborted" || !generationIsCurrent(generationRef, generation)) return;
|
|
1306
|
+
return loadSnapshotThenSettle(generation, true);
|
|
1307
|
+
}, (failure) => {
|
|
1308
|
+
failGeneration(generation, failure);
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1132
1311
|
return;
|
|
1133
1312
|
}
|
|
1134
1313
|
const view = response.result.value;
|
|
1314
|
+
echoedRevisionRef.current = view.revision;
|
|
1135
1315
|
describe.acceptView(view);
|
|
1136
|
-
|
|
1316
|
+
applyDrafts(applySaveSuccess(draftsRef.current, draft.provider, {
|
|
1137
1317
|
user: view.user ?? {},
|
|
1138
1318
|
revision: view.revision
|
|
1139
1319
|
}));
|
|
@@ -1147,7 +1327,9 @@ window.__ModuleLoader__.load({
|
|
|
1147
1327
|
text: failure instanceof Error ? failure.message : t("loadError")
|
|
1148
1328
|
});
|
|
1149
1329
|
} finally {
|
|
1330
|
+
busyRouteRef.current = null;
|
|
1150
1331
|
setBusyRoute(null);
|
|
1332
|
+
flushPendingSettings(refreshAtRevision);
|
|
1151
1333
|
}
|
|
1152
1334
|
};
|
|
1153
1335
|
const showLoading = status === "loading" && drafts.length === 0;
|
|
@@ -1182,7 +1364,7 @@ window.__ModuleLoader__.load({
|
|
|
1182
1364
|
type: "button",
|
|
1183
1365
|
className: effort_declare_module_css_default.secondaryButton,
|
|
1184
1366
|
onClick: () => {
|
|
1185
|
-
reload(true);
|
|
1367
|
+
reload(true, snapshotMode());
|
|
1186
1368
|
},
|
|
1187
1369
|
children: t("reload")
|
|
1188
1370
|
}) : null,
|
|
@@ -1205,21 +1387,25 @@ window.__ModuleLoader__.load({
|
|
|
1205
1387
|
t,
|
|
1206
1388
|
onChange: (next) => {
|
|
1207
1389
|
patchNotice(next.provider, void 0);
|
|
1208
|
-
|
|
1390
|
+
applyDrafts((current) => current.map((row) => row.provider === next.provider ? next : row));
|
|
1209
1391
|
},
|
|
1210
1392
|
onSave: (next) => {
|
|
1211
1393
|
save(next);
|
|
1212
1394
|
},
|
|
1213
1395
|
onCancel: (next) => {
|
|
1214
1396
|
patchNotice(next.provider, void 0);
|
|
1215
|
-
|
|
1397
|
+
applyDrafts((current) => current.map((row) => row.provider === next.provider ? {
|
|
1216
1398
|
...row,
|
|
1217
1399
|
models: cloneModels(row.originalModels),
|
|
1218
1400
|
compat: cloneObject(row.originalCompat)
|
|
1219
1401
|
} : row));
|
|
1220
1402
|
}
|
|
1221
1403
|
}, draft.provider))
|
|
1222
|
-
}) : null
|
|
1404
|
+
}) : null,
|
|
1405
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1406
|
+
className: effort_declare_module_css_default.footer,
|
|
1407
|
+
children: PLUGIN_FOOTER_TEXT
|
|
1408
|
+
})
|
|
1223
1409
|
]
|
|
1224
1410
|
});
|
|
1225
1411
|
}
|
|
@@ -1357,22 +1543,25 @@ window.__ModuleLoader__.load({
|
|
|
1357
1543
|
const describe = ctx.settingsScope.describe();
|
|
1358
1544
|
const invalidation = /* @__PURE__ */ new Set();
|
|
1359
1545
|
ctx.effect(() => {
|
|
1360
|
-
const emit = (
|
|
1361
|
-
for (const listener of invalidation) listener(
|
|
1546
|
+
const emit = (event) => {
|
|
1547
|
+
for (const listener of invalidation) listener(event);
|
|
1362
1548
|
};
|
|
1363
1549
|
const disposers = [
|
|
1364
1550
|
describe.subscribe(() => {
|
|
1365
|
-
emit("writable");
|
|
1551
|
+
emit({ source: "writable" });
|
|
1366
1552
|
}),
|
|
1367
|
-
ctx.remote.$on("settings/document-updated", (ns) => {
|
|
1553
|
+
ctx.remote.$on("settings/document-updated", (ns, revision) => {
|
|
1368
1554
|
if (ns !== "llm-pi-ai") return;
|
|
1369
|
-
emit(
|
|
1555
|
+
emit({
|
|
1556
|
+
source: "settings",
|
|
1557
|
+
revision
|
|
1558
|
+
});
|
|
1370
1559
|
}),
|
|
1371
1560
|
ctx.remote.$on("llm/adapters-updated", () => {
|
|
1372
|
-
emit("directory");
|
|
1561
|
+
emit({ source: "directory" });
|
|
1373
1562
|
}),
|
|
1374
1563
|
ctx.on("connection/reset", () => {
|
|
1375
|
-
emit("
|
|
1564
|
+
emit({ source: "reset" });
|
|
1376
1565
|
})
|
|
1377
1566
|
];
|
|
1378
1567
|
return () => {
|