better-dsh 0.0.0 → 0.2.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/LICENSE +24 -0
- package/README.md +294 -4
- package/control-prompt.md +37 -0
- package/cordis.patch.yml +53 -0
- package/docs/00_adr/0001-bridge-tool-layer-not-service-layer.md +14 -0
- package/docs/00_adr/0002-masking-is-presentation-only.md +15 -0
- package/docs/10_plans/A2A-messaging-channel-test-archive.md +256 -0
- package/docs/10_plans/code-mode-vs-rlm-ipython-comparison.md +137 -0
- package/docs/10_plans/dashr-blueprint-review.md +201 -0
- package/docs/10_plans/dashr-blueprint.md +561 -0
- package/docs/10_plans/dashr-compaction-window-and-archive.md +307 -0
- package/docs/10_plans/dashr-profile-layer-feasibility.md +367 -0
- package/docs/10_plans/dashr-sandbox-escalation-semantics-gap.md +171 -0
- package/docs/10_plans/dashr-security-sandbox-analysis.md +187 -0
- package/docs/10_plans/dashr-surface-invariant-and-omp-imports.md +97 -0
- package/docs/10_plans/ipython-kernel-interactive-interface-test-report.md +152 -0
- package/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +146 -0
- package/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +50 -0
- package/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +79 -0
- package/docs/10_plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +138 -0
- package/docs/10_plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +161 -0
- package/docs/10_plans/kernel-refactoring/V0.1.5-development-plan.md +109 -0
- package/docs/10_plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +50 -0
- package/docs/10_plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +113 -0
- package/docs/10_plans/recallable-compaction.md +147 -0
- package/docs/10_plans/spike-tag-repro.mjs +102 -0
- package/docs/10_plans/upstream-analysis.md +128 -0
- package/docs/50_test-reports/REPL-/345/267/245/345/205/267/350/260/203/347/224/250-/346/210/252/346/226/255/350/257/212/346/226/255.md +110 -0
- package/docs/50_test-reports/kernel-provisioning.md +44 -0
- package/docs/50_test-reports/repl-kernel-provisioning-test-report.md +87 -0
- package/docs/50_test-reports/upstream-dsh-0.1.2-alpha.5-local-test-report.md +81 -0
- package/docs/50_test-reports/upstream-dsh-0.1.2-alpha.5-report.md +93 -0
- package/docs/50_test-reports/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +142 -0
- package/docs/50_test-reports/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +193 -0
- package/docs/50_test-reports/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +96 -0
- package/docs/50_test-reports/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +127 -0
- package/docs/50_test-reports/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +150 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/README.md +138 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/code-mode-repl-only.observation.md +74 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +3890 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +544 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/functions.json +592 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/skills-catalog.snapshot.md +30 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.output-schemas.json +1236 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.python.txt +592 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.typescript.txt +516 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/wire-vs-transcription.diff.md +54 -0
- package/docs/50_test-reports/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +224 -0
- package/docs/50_test-reports/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +168 -0
- package/docs/50_test-reports/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +123 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.lock +7 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.toml +6 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +8 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/main.rs +4 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/hashline-probe.md +5 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.lock +7 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.toml +7 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/build.rs +4 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/src/main.rs +13 -0
- package/docs/50_test-reports/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +110 -0
- package/docs/50_test-reports/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +86 -0
- package/docs/50_test-reports/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +66 -0
- package/docs/50_test-reports/v0.2.1d-/345/256/236/346/265/213/346/212/245/345/221/212.md +67 -0
- package/docs/50_test-reports/v0.2.1e-P1-/345/256/236/346/265/213/346/212/245/345/221/212.md +136 -0
- package/docs/50_test-reports/v0.2.1ef-dev-audit-report.md +73 -0
- package/docs/50_test-reports/v0.2.1f-plugin-shipped-ui-patches/345/256/236/346/265/213/346/212/245/345/221/212.md +102 -0
- package/docs/60_exploration-and-research/cordis-research.md +350 -0
- package/docs/60_exploration-and-research/dsh-web-profile-package-map.md +186 -0
- package/docs/60_exploration-and-research/dsh-web-ui-slot-system-research.md +310 -0
- package/docs/60_exploration-and-research/dsh-webui-strip-boundary-research.md +300 -0
- package/docs/60_exploration-and-research/ios-chat-app-bridge-research.md +324 -0
- package/docs/60_exploration-and-research/web-frontend-composability-research.md +191 -0
- package/docs/REPL-/345/267/245/345/205/267/350/260/203/347/224/250-/346/210/252/346/226/255/350/257/212/346/226/255.md +110 -0
- package/docs/adr/0001-bridge-tool-layer-not-service-layer.md +14 -0
- package/docs/adr/0002-masking-is-presentation-only.md +15 -0
- package/docs/distro-blueprint.md +81 -0
- package/docs/dsh-webUI-with-rlm-mode.png +0 -0
- package/docs/plans/A2A-messaging-channel-test-archive.md +256 -0
- package/docs/plans/code-mode-vs-rlm-ipython-comparison.md +137 -0
- package/docs/plans/dashr-blueprint-review.md +201 -0
- package/docs/plans/dashr-blueprint.md +561 -0
- package/docs/plans/dashr-compaction-window-and-archive.md +307 -0
- package/docs/plans/dashr-profile-layer-feasibility.md +367 -0
- package/docs/plans/dashr-sandbox-escalation-semantics-gap.md +171 -0
- package/docs/plans/dashr-security-sandbox-analysis.md +187 -0
- package/docs/plans/dashr-surface-invariant-and-omp-imports.md +97 -0
- package/docs/plans/ipython-kernel-interactive-interface-test-report.md +152 -0
- package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +146 -0
- package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +50 -0
- package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +79 -0
- package/docs/plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +138 -0
- package/docs/plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +161 -0
- package/docs/plans/kernel-refactoring/V0.1.5-development-plan.md +109 -0
- package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +50 -0
- package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +113 -0
- package/docs/plans/recallable-compaction.md +147 -0
- package/docs/plans/spike-tag-repro.mjs +102 -0
- package/docs/plans/upstream-analysis.md +128 -0
- package/docs/repositioning-and-rebranding.md +102 -0
- package/docs/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +142 -0
- package/docs/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +193 -0
- package/docs/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +96 -0
- package/docs/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +127 -0
- package/docs/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +150 -0
- package/docs/v0.1.8d_artifacts/README.md +138 -0
- package/docs/v0.1.8d_artifacts/code-mode-repl-only.observation.md +74 -0
- package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +3890 -0
- package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +544 -0
- package/docs/v0.1.8d_artifacts/functions.json +592 -0
- package/docs/v0.1.8d_artifacts/skills-catalog.snapshot.md +30 -0
- package/docs/v0.1.8d_artifacts/tools-sdk.output-schemas.json +1236 -0
- package/docs/v0.1.8d_artifacts/tools-sdk.python.txt +592 -0
- package/docs/v0.1.8d_artifacts/tools-sdk.typescript.txt +516 -0
- package/docs/v0.1.8d_artifacts/wire-vs-transcription.diff.md +54 -0
- package/docs/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +224 -0
- package/docs/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +168 -0
- package/docs/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +123 -0
- package/docs/v0.2.0b_artifacts/f2probe/Cargo.lock +7 -0
- package/docs/v0.2.0b_artifacts/f2probe/Cargo.toml +6 -0
- package/docs/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +8 -0
- package/docs/v0.2.0b_artifacts/f2probe/src/main.rs +4 -0
- package/docs/v0.2.0b_artifacts/hashline-probe.md +5 -0
- package/docs/v0.2.0b_artifacts/slowprobe/Cargo.lock +7 -0
- package/docs/v0.2.0b_artifacts/slowprobe/Cargo.toml +7 -0
- package/docs/v0.2.0b_artifacts/slowprobe/build.rs +4 -0
- package/docs/v0.2.0b_artifacts/slowprobe/src/main.rs +13 -0
- package/docs/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +110 -0
- package/docs/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +86 -0
- package/docs/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +66 -0
- package/lib/client/index.js +473 -0
- package/lib/index.d.ts +736 -0
- package/lib/index.js +11518 -0
- package/lib/kernel-env-hxaihi9C.js +195 -0
- package/lib/kernel-env.d.ts +80 -0
- package/lib/kernel-env.js +3 -0
- package/lib/py-sdk-BCaOGYz7.d.ts +125 -0
- package/lib/py-sdk-CbgYiX8O.js +691 -0
- package/lib/py-sdk.d.ts +2 -0
- package/lib/py-sdk.js +3 -0
- package/package.json +325 -4
- package/scripts/kernel-provision.mjs +35 -0
- package/index.js +0 -3
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({ id: "better-dsh", factory: (require) => {
|
|
2
|
+
var module = { exports: {} }; var exports = module.exports;
|
|
3
|
+
//#region rolldown:runtime
|
|
4
|
+
var __create = Object.create;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
12
|
+
key = keys[i];
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
21
|
+
value: mod,
|
|
22
|
+
enumerable: true
|
|
23
|
+
}) : target, mod));
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
let react = require("react");
|
|
27
|
+
react = __toESM(react);
|
|
28
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
29
|
+
react_jsx_runtime = __toESM(react_jsx_runtime);
|
|
30
|
+
|
|
31
|
+
//#region src/failover/config.ts
|
|
32
|
+
/**
|
|
33
|
+
* The `failover` general-fallback config (host-plane, per-turn latch).
|
|
34
|
+
*
|
|
35
|
+
* Pure module — no `@deepseek-ai/*` value imports, so both the host module and
|
|
36
|
+
* the client half may import it (the client type-only) without dragging a host
|
|
37
|
+
* runtime dependency into the browser bundle.
|
|
38
|
+
*
|
|
39
|
+
* A route is a `provider/model` string (e.g. `deepseek/deepseek-v4-flash`).
|
|
40
|
+
* The empty string `''` means "not set" — the slot is skipped.
|
|
41
|
+
*
|
|
42
|
+
* @module dashr/failover/config
|
|
43
|
+
*/
|
|
44
|
+
/** The settings namespace the General row reads and writes. */
|
|
45
|
+
const FAILOVER_SETTINGS_NS = "failover";
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/failover/client/locales.ts
|
|
49
|
+
/**
|
|
50
|
+
* Client locale dictionary for the failover General row.
|
|
51
|
+
* @module dashr/failover/client/locales
|
|
52
|
+
*/
|
|
53
|
+
const NS = "failover";
|
|
54
|
+
const en = {
|
|
55
|
+
"title": "Model failover",
|
|
56
|
+
"fallback1": "Fallback 1",
|
|
57
|
+
"fallback2": "Fallback 2",
|
|
58
|
+
"not-set": "— not set —",
|
|
59
|
+
"loading": "Loading…",
|
|
60
|
+
"error": "Save failed: {{message}}"
|
|
61
|
+
};
|
|
62
|
+
const zh = {
|
|
63
|
+
"title": "模型故障转移",
|
|
64
|
+
"fallback1": "备用模型 1",
|
|
65
|
+
"fallback2": "备用模型 2",
|
|
66
|
+
"not-set": "— 不设置 —",
|
|
67
|
+
"loading": "加载中…",
|
|
68
|
+
"error": "保存失败:{{message}}"
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region \0dsh-css:/home/u1/workspaces/dashr/dashr/src/failover/client/FailoverRow.module.css.mjs
|
|
73
|
+
const css = "._440e1d7b_row {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px 0;\n}\n\n._9865b509_title {\n font-weight: 600;\n font-size: 14px;\n}\n\n._3cfec826_slots {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n._70954771_slot {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n._ba1fd839_slotLabel {\n min-width: 88px;\n flex-shrink: 0;\n font-size: 13px;\n color: var(--dsw-alias-text-secondary, #666);\n}\n\n._11c2662d_select {\n flex: 1;\n max-width: 280px;\n min-width: 0;\n}\n\n._b7c358f9_alert {\n color: var(--dsw-alias-danger, #c0392b);\n font-size: 12px;\n}\n";
|
|
74
|
+
const tagId = "better-dsh/FailoverRow.module.css";
|
|
75
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
76
|
+
const tag = document.createElement("style");
|
|
77
|
+
tag.dataset.plugin = "better-dsh";
|
|
78
|
+
tag.dataset.pluginCss = tagId;
|
|
79
|
+
tag.textContent = css;
|
|
80
|
+
document.head.appendChild(tag);
|
|
81
|
+
}
|
|
82
|
+
var FailoverRow_module_css_default = {
|
|
83
|
+
"row": "_440e1d7b_row",
|
|
84
|
+
"title": "_9865b509_title",
|
|
85
|
+
"slots": "_3cfec826_slots",
|
|
86
|
+
"slot": "_70954771_slot",
|
|
87
|
+
"slotLabel": "_ba1fd839_slotLabel",
|
|
88
|
+
"select": "_11c2662d_select",
|
|
89
|
+
"alert": "_b7c358f9_alert"
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/failover/client/FailoverRow.tsx
|
|
94
|
+
/** Render the failover row: title + two model selectors. */
|
|
95
|
+
function FailoverRow({ catalog, loadConfig, save, t }) {
|
|
96
|
+
const [loaded, setLoaded] = (0, react.useState)(null);
|
|
97
|
+
const [error, setError] = (0, react.useState)(null);
|
|
98
|
+
const [saving, setSaving] = (0, react.useState)(false);
|
|
99
|
+
(0, react.useEffect)(() => {
|
|
100
|
+
let alive = true;
|
|
101
|
+
(async () => {
|
|
102
|
+
try {
|
|
103
|
+
const [routes$1, cfg] = await Promise.all([catalog(), loadConfig()]);
|
|
104
|
+
if (!alive) return;
|
|
105
|
+
setLoaded({
|
|
106
|
+
routes: routes$1,
|
|
107
|
+
config: cfg ?? {
|
|
108
|
+
fallback1: "",
|
|
109
|
+
fallback2: ""
|
|
110
|
+
},
|
|
111
|
+
revision: cfg?.revision
|
|
112
|
+
});
|
|
113
|
+
} catch (err) {
|
|
114
|
+
if (alive) setError(err instanceof Error ? err.message : String(err));
|
|
115
|
+
}
|
|
116
|
+
})();
|
|
117
|
+
return () => {
|
|
118
|
+
alive = false;
|
|
119
|
+
};
|
|
120
|
+
}, [catalog, loadConfig]);
|
|
121
|
+
const select = async (slot, value) => {
|
|
122
|
+
if (loaded === null || saving) return;
|
|
123
|
+
setSaving(true);
|
|
124
|
+
setError(null);
|
|
125
|
+
try {
|
|
126
|
+
const nextRevision = await save({ [slot]: value }, loaded.revision);
|
|
127
|
+
setLoaded({
|
|
128
|
+
...loaded,
|
|
129
|
+
config: {
|
|
130
|
+
...loaded.config,
|
|
131
|
+
[slot]: value
|
|
132
|
+
},
|
|
133
|
+
revision: nextRevision
|
|
134
|
+
});
|
|
135
|
+
} catch (err) {
|
|
136
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
137
|
+
} finally {
|
|
138
|
+
setSaving(false);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const routes = loaded?.routes ?? [];
|
|
142
|
+
const renderSelect = (slot, label) => {
|
|
143
|
+
const value = loaded?.config[slot] ?? "";
|
|
144
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
145
|
+
className: FailoverRow_module_css_default.slot,
|
|
146
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
147
|
+
className: FailoverRow_module_css_default.slotLabel,
|
|
148
|
+
children: label
|
|
149
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
150
|
+
className: FailoverRow_module_css_default.select,
|
|
151
|
+
value,
|
|
152
|
+
disabled: saving || loaded === null,
|
|
153
|
+
onChange: (event) => {
|
|
154
|
+
select(slot, event.target.value);
|
|
155
|
+
},
|
|
156
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
157
|
+
value: "",
|
|
158
|
+
children: t("not-set")
|
|
159
|
+
}), routes.map((route) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
160
|
+
value: route,
|
|
161
|
+
children: route
|
|
162
|
+
}, route))]
|
|
163
|
+
})]
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
167
|
+
className: FailoverRow_module_css_default.row,
|
|
168
|
+
children: [
|
|
169
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
170
|
+
className: FailoverRow_module_css_default.title,
|
|
171
|
+
children: t("title")
|
|
172
|
+
}),
|
|
173
|
+
error !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
174
|
+
className: FailoverRow_module_css_default.alert,
|
|
175
|
+
role: "alert",
|
|
176
|
+
children: t("error", { message: error })
|
|
177
|
+
}) : null,
|
|
178
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
179
|
+
className: FailoverRow_module_css_default.slots,
|
|
180
|
+
children: [renderSelect("fallback1", t("fallback1")), renderSelect("fallback2", t("fallback2"))]
|
|
181
|
+
})
|
|
182
|
+
]
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region src/mobile/gesture.ts
|
|
188
|
+
/**
|
|
189
|
+
* Resolved defaults — the `1706b81` constants (120 / viewport÷4 / 40 / 1.3 /
|
|
190
|
+
* 768) plus the one addition, the velocity gate. A slow text-selection drag
|
|
191
|
+
* runs ~0.13 px/ms; 0.15 px/ms filters those while any comfortable sweep
|
|
192
|
+
* (0.4 px/ms and up) passes.
|
|
193
|
+
*/
|
|
194
|
+
const DEFAULT_SWIPE_THRESHOLDS = {
|
|
195
|
+
breakpoint: 768,
|
|
196
|
+
swipeDistancePx: 40,
|
|
197
|
+
dominanceRatio: 1.3,
|
|
198
|
+
leftEdgeBandPx: 120,
|
|
199
|
+
rightZoneRatio: .25,
|
|
200
|
+
swipeVelocityPxPerMs: .15
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Whether one completed gesture's viewport is in the gesture band.
|
|
204
|
+
*
|
|
205
|
+
* @param viewportWidth - viewport width at gesture time (px).
|
|
206
|
+
* @param thresholds - resolved recognition thresholds (`.breakpoint`).
|
|
207
|
+
* @returns `true` when `viewportWidth` is strictly below the breakpoint.
|
|
208
|
+
*/
|
|
209
|
+
function isNarrowViewport(viewportWidth, thresholds) {
|
|
210
|
+
return viewportWidth < thresholds.breakpoint;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Whether a pointerdown may START a gesture — the source's pointerdown
|
|
214
|
+
* gate, verbatim: with both panels closed, only the left band (X120) or
|
|
215
|
+
* the right three quarters of the screen admit; with a panel open, any
|
|
216
|
+
* position admits (that swipe is a dismiss).
|
|
217
|
+
*
|
|
218
|
+
* @param x - pointerdown client X.
|
|
219
|
+
* @param viewportWidth - viewport width at gesture time (px).
|
|
220
|
+
* @param panels - panel state at pointerdown.
|
|
221
|
+
* @param thresholds - resolved recognition thresholds.
|
|
222
|
+
* @returns `true` when the origin is admitted into tracking.
|
|
223
|
+
*/
|
|
224
|
+
function admitsSwipeStart(x, viewportWidth, panels, thresholds) {
|
|
225
|
+
if (!(panels.leftCollapsed && !panels.rightOpen)) return true;
|
|
226
|
+
return x <= thresholds.leftEdgeBandPx || x >= viewportWidth * thresholds.rightZoneRatio;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Classify one in-flight drag into a panel action — the source's
|
|
230
|
+
* pointermove decision, verbatim, plus the velocity gate. Callers fire
|
|
231
|
+
* ONCE (then drop the drag): a `null` here means "not yet / not this
|
|
232
|
+
* gesture", and the same drag may classify on a LATER move event as its
|
|
233
|
+
* displacement or velocity grows.
|
|
234
|
+
*
|
|
235
|
+
* @param progress - the drag's displacement and elapsed time so far.
|
|
236
|
+
* @param panels - panel state read live at this event.
|
|
237
|
+
* @param sessionLive - whether a session is current (gates opening the
|
|
238
|
+
* right panel, mirroring the source's `detailsSession !== undefined`).
|
|
239
|
+
* @param thresholds - resolved recognition thresholds.
|
|
240
|
+
* @returns the action the drag maps to, or `null` when no panel admits
|
|
241
|
+
* it yet.
|
|
242
|
+
*/
|
|
243
|
+
function classifySwipeProgress(progress, panels, sessionLive, thresholds) {
|
|
244
|
+
const adx = Math.abs(progress.dx);
|
|
245
|
+
const ady = Math.abs(progress.dy);
|
|
246
|
+
if (adx < thresholds.swipeDistancePx) return null;
|
|
247
|
+
if (adx <= ady * thresholds.dominanceRatio) return null;
|
|
248
|
+
if (thresholds.swipeVelocityPxPerMs > 0) {
|
|
249
|
+
if (progress.dtMs <= 0) return null;
|
|
250
|
+
if (adx / progress.dtMs < thresholds.swipeVelocityPxPerMs) return null;
|
|
251
|
+
}
|
|
252
|
+
if (progress.dx < 0) {
|
|
253
|
+
if (!panels.leftCollapsed) return "close-left";
|
|
254
|
+
if (sessionLive && !panels.rightOpen) return "open-right";
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
if (panels.rightOpen) return "close-right";
|
|
258
|
+
if (panels.leftCollapsed) return "open-left";
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Merge the host-injected page config over the defaults. An absent config
|
|
263
|
+
* (host feature off, or an old cached page) resolves to enabled=false — the
|
|
264
|
+
* client half is inert unless the host opted the page in.
|
|
265
|
+
*
|
|
266
|
+
* @param pageConfig - `window.__DASHR_MOBILE__` as left by the boot script.
|
|
267
|
+
* @returns resolved thresholds plus the enable flag.
|
|
268
|
+
*/
|
|
269
|
+
function resolveMobileConfig(pageConfig) {
|
|
270
|
+
if (pageConfig === void 0 || pageConfig.enabled !== true) return {
|
|
271
|
+
enabled: false,
|
|
272
|
+
...DEFAULT_SWIPE_THRESHOLDS
|
|
273
|
+
};
|
|
274
|
+
const n = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
275
|
+
const v = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : fallback;
|
|
276
|
+
return {
|
|
277
|
+
enabled: true,
|
|
278
|
+
breakpoint: n(pageConfig.breakpoint, DEFAULT_SWIPE_THRESHOLDS.breakpoint),
|
|
279
|
+
swipeDistancePx: n(pageConfig.swipeDistancePx, DEFAULT_SWIPE_THRESHOLDS.swipeDistancePx),
|
|
280
|
+
dominanceRatio: n(pageConfig.dominanceRatio, DEFAULT_SWIPE_THRESHOLDS.dominanceRatio),
|
|
281
|
+
leftEdgeBandPx: n(pageConfig.leftEdgeBandPx, DEFAULT_SWIPE_THRESHOLDS.leftEdgeBandPx),
|
|
282
|
+
rightZoneRatio: n(pageConfig.rightZoneRatio, DEFAULT_SWIPE_THRESHOLDS.rightZoneRatio),
|
|
283
|
+
swipeVelocityPxPerMs: v(pageConfig.swipeVelocityPxPerMs, DEFAULT_SWIPE_THRESHOLDS.swipeVelocityPxPerMs)
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
//#endregion
|
|
288
|
+
//#region src/mobile/client/index.ts
|
|
289
|
+
/** Left sidebar state, live off AppFrame's semantic attribute. */
|
|
290
|
+
function readLeftCollapsed() {
|
|
291
|
+
return document.querySelector("[data-sidebar-collapsed]") !== null;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Better Sidebar's right-panel state, live off the body attribute the
|
|
295
|
+
* plugin itself publishes (collapsed = closed). Read SYNCHRONOUSLY in the
|
|
296
|
+
* handlers — a cached mirror lags the panel's own DOM write by a render,
|
|
297
|
+
* and a close-swipe issued right after an open-swipe would misroute.
|
|
298
|
+
*/
|
|
299
|
+
function readRightOpen() {
|
|
300
|
+
return !document.body.hasAttribute("data-dsh-sidebar-collapsed");
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Whether a session is current — the plugin-side stand-in for the source's
|
|
304
|
+
* `detailsSession !== undefined` guard (the right panel opens in a session
|
|
305
|
+
* only). Better Sidebar's own shipped CSS keys off the same slot selector,
|
|
306
|
+
* so it is load-bearing beyond this feature.
|
|
307
|
+
*/
|
|
308
|
+
function readSessionLive() {
|
|
309
|
+
return document.querySelector("[data-slot=\"conversation.session.header\"]") !== null;
|
|
310
|
+
}
|
|
311
|
+
/** Panel state snapshot, both sources live. */
|
|
312
|
+
function readPanelState() {
|
|
313
|
+
return {
|
|
314
|
+
leftCollapsed: readLeftCollapsed(),
|
|
315
|
+
rightOpen: readRightOpen()
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Toggle Better Sidebar's right panel through its persistent DOM: the
|
|
320
|
+
* plugin exposes no JS toggle on its client service (its open/close
|
|
321
|
+
* reducer is store-internal), so the swipe reaches it the same way the
|
|
322
|
+
* source did — clicking the LAST button of its always-rendered
|
|
323
|
+
* `[data-dsh-toggle-cluster]` (the bottom-panel button precedes it and is
|
|
324
|
+
* absent below the plugin's 768px narrow breakpoint). Absent cluster or
|
|
325
|
+
* buttons: a no-op, never a crash.
|
|
326
|
+
*/
|
|
327
|
+
function toggleBetterSidebar() {
|
|
328
|
+
const buttons = document.querySelector("[data-dsh-toggle-cluster]")?.querySelectorAll("button");
|
|
329
|
+
(buttons?.[buttons.length - 1])?.click();
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The narrow-viewport CSS: zero-width sidebar track under the breakpoint,
|
|
333
|
+
* keyed to AppFrame's semantic attribute (survives class-hash churn).
|
|
334
|
+
* Rendered with the breakpoint baked in (media queries cannot read JS
|
|
335
|
+
* config); the tag carries the plugin-owned dataset so the loader's
|
|
336
|
+
* style-claim machinery removes it on unload, like module CSS.
|
|
337
|
+
*/
|
|
338
|
+
function mobileCss(breakpointPx) {
|
|
339
|
+
const wide = Math.max(1, Math.floor(breakpointPx) - .02);
|
|
340
|
+
return [
|
|
341
|
+
`@media (max-width: ${String(wide)}px) {`,
|
|
342
|
+
` [data-sidebar-collapsed] {`,
|
|
343
|
+
` grid-template-columns: 0px minmax(0, 1fr) 0px !important;`,
|
|
344
|
+
` }`,
|
|
345
|
+
`}`
|
|
346
|
+
].join("\n");
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Mount the mobile feature: style injection plus the swipe listeners.
|
|
350
|
+
* Inert unless the host's boot script opted the page in.
|
|
351
|
+
*
|
|
352
|
+
* @param ctx - client root context.
|
|
353
|
+
* @returns the effect disposer (style tag + listeners removed on unload).
|
|
354
|
+
*/
|
|
355
|
+
function setupMobileLayout(ctx) {
|
|
356
|
+
const pageConfig = globalThis.__DASHR_MOBILE__;
|
|
357
|
+
const config = resolveMobileConfig(pageConfig);
|
|
358
|
+
if (!config.enabled) return;
|
|
359
|
+
const styleTagId = "better-dsh/mobile";
|
|
360
|
+
ctx.effect(() => {
|
|
361
|
+
const tag = document.createElement("style");
|
|
362
|
+
tag.dataset.plugin = "better-dsh";
|
|
363
|
+
tag.dataset.pluginCss = styleTagId;
|
|
364
|
+
tag.textContent = mobileCss(config.breakpoint);
|
|
365
|
+
document.head.append(tag);
|
|
366
|
+
const offLayout = ctx.inject(["layout"], (layoutCtx) => {
|
|
367
|
+
const layout = layoutCtx.get("layout");
|
|
368
|
+
if (layout === void 0) return;
|
|
369
|
+
let start;
|
|
370
|
+
const onPointerDown = (event) => {
|
|
371
|
+
start = void 0;
|
|
372
|
+
const viewport = window.innerWidth;
|
|
373
|
+
if (!isNarrowViewport(viewport, config)) return;
|
|
374
|
+
if (!admitsSwipeStart(event.clientX, viewport, readPanelState(), config)) return;
|
|
375
|
+
start = {
|
|
376
|
+
x: event.clientX,
|
|
377
|
+
y: event.clientY,
|
|
378
|
+
t: event.timeStamp
|
|
379
|
+
};
|
|
380
|
+
};
|
|
381
|
+
const onPointerMove = (event) => {
|
|
382
|
+
const origin = start;
|
|
383
|
+
if (origin === void 0) return;
|
|
384
|
+
const action = classifySwipeProgress({
|
|
385
|
+
dx: event.clientX - origin.x,
|
|
386
|
+
dy: event.clientY - origin.y,
|
|
387
|
+
dtMs: event.timeStamp - origin.t
|
|
388
|
+
}, readPanelState(), readSessionLive(), config);
|
|
389
|
+
if (action === null) return;
|
|
390
|
+
start = void 0;
|
|
391
|
+
if (action === "open-left" || action === "close-left") layout.toggleSidebar();
|
|
392
|
+
else toggleBetterSidebar();
|
|
393
|
+
};
|
|
394
|
+
const onPointerEnd = () => {
|
|
395
|
+
start = void 0;
|
|
396
|
+
};
|
|
397
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
398
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
399
|
+
document.addEventListener("pointerup", onPointerEnd, true);
|
|
400
|
+
document.addEventListener("pointercancel", onPointerEnd, true);
|
|
401
|
+
return () => {
|
|
402
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
403
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
404
|
+
document.removeEventListener("pointerup", onPointerEnd, true);
|
|
405
|
+
document.removeEventListener("pointercancel", onPointerEnd, true);
|
|
406
|
+
};
|
|
407
|
+
});
|
|
408
|
+
return () => {
|
|
409
|
+
tag.remove();
|
|
410
|
+
Promise.resolve(offLayout.dispose());
|
|
411
|
+
};
|
|
412
|
+
}, "dashr: mobile layout");
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
//#endregion
|
|
416
|
+
//#region src/failover/client/index.ts
|
|
417
|
+
/** Required services (cordis fiber inject). */
|
|
418
|
+
const inject = [
|
|
419
|
+
"slots",
|
|
420
|
+
"locale",
|
|
421
|
+
"remote",
|
|
422
|
+
"remote.settings",
|
|
423
|
+
"remote.session"
|
|
424
|
+
];
|
|
425
|
+
/**
|
|
426
|
+
* Register the `failover` dictionaries and the General settings row.
|
|
427
|
+
* @param ctx - client root context.
|
|
428
|
+
*/
|
|
429
|
+
function apply(ctx) {
|
|
430
|
+
ctx.effect(() => ctx.locale.register(NS, {
|
|
431
|
+
zh,
|
|
432
|
+
en
|
|
433
|
+
}), "llm-failover: dictionaries");
|
|
434
|
+
setupMobileLayout(ctx);
|
|
435
|
+
ctx.slots.inject("settings.general.item", function* () {
|
|
436
|
+
yield ctx.slots.register({
|
|
437
|
+
name: "settings.general.item",
|
|
438
|
+
id: "failover",
|
|
439
|
+
order: 100,
|
|
440
|
+
locale: NS,
|
|
441
|
+
inject: () => ({
|
|
442
|
+
catalog: async () => {
|
|
443
|
+
const response = await ctx.remote.session.modelCatalog();
|
|
444
|
+
if (!response.ok) throw new Error(`${response.error.code}: ${response.error.message}`);
|
|
445
|
+
return response.value.groups.flatMap((group) => group.models.map((model) => `${group.id}/${model.id}`));
|
|
446
|
+
},
|
|
447
|
+
loadConfig: async () => {
|
|
448
|
+
const response = await ctx.remote.settings.describe();
|
|
449
|
+
if (!response.ok) throw new Error(`${response.error.code}: ${response.error.message}`);
|
|
450
|
+
const view = response.value.namespaces.find((entry) => entry.ns === FAILOVER_SETTINGS_NS);
|
|
451
|
+
if (view === void 0) return null;
|
|
452
|
+
const value = view.value;
|
|
453
|
+
return {
|
|
454
|
+
fallback1: typeof value.fallback1 === "string" ? value.fallback1 : "",
|
|
455
|
+
fallback2: typeof value.fallback2 === "string" ? value.fallback2 : "",
|
|
456
|
+
revision: view.revision
|
|
457
|
+
};
|
|
458
|
+
},
|
|
459
|
+
save: async (patch, revision) => {
|
|
460
|
+
const response = await ctx.remote.settings.update(FAILOVER_SETTINGS_NS, patch, revision);
|
|
461
|
+
if (!response.ok) throw new Error(`${response.error.code}: ${response.error.message}`);
|
|
462
|
+
return response.value.revision;
|
|
463
|
+
}
|
|
464
|
+
})
|
|
465
|
+
}, FailoverRow);
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
//#endregion
|
|
470
|
+
exports.FailoverRow = FailoverRow;
|
|
471
|
+
exports.apply = apply;
|
|
472
|
+
exports.inject = inject;
|
|
473
|
+
return module.exports; } });
|