dsh-skill-hub 0.3.0 → 0.3.2
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/README.md +68 -231
- package/README.zh.md +67 -205
- package/lib/client.js +739 -2
- package/lib/client.js.map +1 -1
- package/lib/index.js +2 -3
- package/lib/types/client/SkillHubSettingsCard.d.ts +1 -1
- package/lib/types/client/index.d.ts +6 -1
- package/lib/types/client/settings-form.d.ts +1 -1
- package/lib/types/client/slash-dots.d.ts +2 -9
- package/lib/types/index.d.ts +2 -1
- package/package.json +38 -29
- package/src/client/SkillHubSettingsCard.tsx +1 -1
- package/src/client/index.tsx +10 -1
- package/src/client/settings-form.ts +2 -1
- package/src/client/slash-dots.test.ts +24 -6
- package/src/client/slash-dots.tsx +55 -1
- package/src/index.ts +2 -2
package/lib/client.js
CHANGED
|
@@ -6,7 +6,6 @@ window.__ModuleLoader__.load({
|
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react = require("react");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
-
let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
|
|
10
9
|
//#region src/protocol.ts
|
|
11
10
|
/**
|
|
12
11
|
* Shared API contract for dsh-skill-hub: the route paths and payload shapes
|
|
@@ -1067,16 +1066,54 @@ window.__ModuleLoader__.load({
|
|
|
1067
1066
|
* @param scope - hub settings scope for the dot colors.
|
|
1068
1067
|
* @returns a disposer restoring the original candidates.
|
|
1069
1068
|
*/
|
|
1069
|
+
/**
|
|
1070
|
+
* DOM 兜底:在 alpha.2 新版 MenuView(icon 仅枚举)下通过直接操作
|
|
1071
|
+
* 已渲染的 `[role="option"]` 列表注入彩色点,绕过 `icon` 限制。
|
|
1072
|
+
* 旧版仍走 `icon` 注入,此处仅为新版。
|
|
1073
|
+
*/
|
|
1074
|
+
function injectDotsViaDOM(modelByName, modelColor, userColor) {
|
|
1075
|
+
if (typeof document === "undefined" || typeof requestAnimationFrame === "undefined") return;
|
|
1076
|
+
const run = () => {
|
|
1077
|
+
const options = document.querySelectorAll("[role=\"option\"]");
|
|
1078
|
+
for (const opt of options) {
|
|
1079
|
+
if (opt.querySelector("[data-skill-dot]") !== null) continue;
|
|
1080
|
+
const nameEl = opt.querySelector("[class*=\"itemName\"]");
|
|
1081
|
+
if (nameEl === null) continue;
|
|
1082
|
+
const name = (nameEl.textContent ?? "").trim();
|
|
1083
|
+
if (name.length === 0) continue;
|
|
1084
|
+
if (!modelByName.has(name) && nameEl.textContent !== name) continue;
|
|
1085
|
+
const color = modelByName.get(name) ?? true ? modelColor : userColor;
|
|
1086
|
+
const dot = document.createElement("span");
|
|
1087
|
+
dot.setAttribute("data-skill-dot", "");
|
|
1088
|
+
dot.setAttribute("aria-hidden", "true");
|
|
1089
|
+
dot.style.display = "inline-block";
|
|
1090
|
+
dot.style.width = "6px";
|
|
1091
|
+
dot.style.height = "6px";
|
|
1092
|
+
dot.style.borderRadius = "3px";
|
|
1093
|
+
dot.style.background = color;
|
|
1094
|
+
dot.style.flex = "none";
|
|
1095
|
+
const iconEl = opt.querySelector("[class*=\"itemIcon\"]");
|
|
1096
|
+
if (iconEl !== null && iconEl.nextSibling !== null) iconEl.parentElement?.insertBefore(dot, iconEl.nextSibling);
|
|
1097
|
+
else nameEl.parentElement?.insertBefore(dot, nameEl);
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
requestAnimationFrame(() => setTimeout(run, 0));
|
|
1101
|
+
}
|
|
1070
1102
|
function wrapSkillSource(source, api, scope) {
|
|
1071
1103
|
const original = source.candidates;
|
|
1072
1104
|
source.candidates = async (session, req) => {
|
|
1073
1105
|
const items = await original(session, req);
|
|
1074
1106
|
if (req.signal.aborted) return items;
|
|
1107
|
+
const isNewHost = req !== null && typeof req === "object" && "drilled" in req;
|
|
1075
1108
|
const modelByName = await modelInvocableMap(api);
|
|
1076
1109
|
if (req.signal.aborted) return items;
|
|
1077
1110
|
const snapshot = scope.getSnapshot();
|
|
1078
1111
|
const modelColor = snapshot.value?.dotModelColor ?? "#2f81f7";
|
|
1079
1112
|
const userColor = snapshot.value?.dotUserColor ?? "#3fb950";
|
|
1113
|
+
if (isNewHost) {
|
|
1114
|
+
injectDotsViaDOM(modelByName, modelColor, userColor);
|
|
1115
|
+
return items;
|
|
1116
|
+
}
|
|
1080
1117
|
return items.map((item) => ({
|
|
1081
1118
|
...item,
|
|
1082
1119
|
icon: dotIcon(modelByName.get(item.name) ?? true ? modelColor : userColor)
|
|
@@ -1466,6 +1503,706 @@ window.__ModuleLoader__.load({
|
|
|
1466
1503
|
});
|
|
1467
1504
|
}
|
|
1468
1505
|
//#endregion
|
|
1506
|
+
//#region node_modules/zustand/esm/vanilla.mjs
|
|
1507
|
+
const createStoreImpl = (createState) => {
|
|
1508
|
+
let state;
|
|
1509
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1510
|
+
const setState = (partial, replace) => {
|
|
1511
|
+
const nextState = typeof partial === "function" ? partial(state) : partial;
|
|
1512
|
+
if (!Object.is(nextState, state)) {
|
|
1513
|
+
const previousState = state;
|
|
1514
|
+
state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
|
|
1515
|
+
listeners.forEach((listener) => listener(state, previousState));
|
|
1516
|
+
}
|
|
1517
|
+
};
|
|
1518
|
+
const getState = () => state;
|
|
1519
|
+
const subscribe = (listener) => {
|
|
1520
|
+
listeners.add(listener);
|
|
1521
|
+
return () => listeners.delete(listener);
|
|
1522
|
+
};
|
|
1523
|
+
const destroy = () => {
|
|
1524
|
+
listeners.clear();
|
|
1525
|
+
};
|
|
1526
|
+
const api = {
|
|
1527
|
+
setState,
|
|
1528
|
+
getState,
|
|
1529
|
+
subscribe,
|
|
1530
|
+
destroy
|
|
1531
|
+
};
|
|
1532
|
+
state = createState(setState, getState, api);
|
|
1533
|
+
return api;
|
|
1534
|
+
};
|
|
1535
|
+
const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
|
|
1536
|
+
//#endregion
|
|
1537
|
+
//#region node_modules/zustand/esm/middleware.mjs
|
|
1538
|
+
const subscribeWithSelectorImpl = (fn) => (set, get, api) => {
|
|
1539
|
+
const origSubscribe = api.subscribe;
|
|
1540
|
+
api.subscribe = (selector, optListener, options) => {
|
|
1541
|
+
let listener = selector;
|
|
1542
|
+
if (optListener) {
|
|
1543
|
+
const equalityFn = (options == null ? void 0 : options.equalityFn) || Object.is;
|
|
1544
|
+
let currentSlice = selector(api.getState());
|
|
1545
|
+
listener = (state) => {
|
|
1546
|
+
const nextSlice = selector(state);
|
|
1547
|
+
if (!equalityFn(currentSlice, nextSlice)) {
|
|
1548
|
+
const previousSlice = currentSlice;
|
|
1549
|
+
optListener(currentSlice = nextSlice, previousSlice);
|
|
1550
|
+
}
|
|
1551
|
+
};
|
|
1552
|
+
if (options == null ? void 0 : options.fireImmediately) optListener(currentSlice, currentSlice);
|
|
1553
|
+
}
|
|
1554
|
+
return origSubscribe(listener);
|
|
1555
|
+
};
|
|
1556
|
+
return fn(set, get, api);
|
|
1557
|
+
};
|
|
1558
|
+
const subscribeWithSelector = subscribeWithSelectorImpl;
|
|
1559
|
+
//#endregion
|
|
1560
|
+
//#region node_modules/immer/dist/immer.mjs
|
|
1561
|
+
var NOTHING = Symbol.for("immer-nothing");
|
|
1562
|
+
var DRAFTABLE = Symbol.for("immer-draftable");
|
|
1563
|
+
var DRAFT_STATE = Symbol.for("immer-state");
|
|
1564
|
+
function die(error, ...args) {
|
|
1565
|
+
throw new Error(`[Immer] minified error nr: ${error}. Full error at: https://bit.ly/3cXEKWf`);
|
|
1566
|
+
}
|
|
1567
|
+
var getPrototypeOf = Object.getPrototypeOf;
|
|
1568
|
+
function isDraft(value) {
|
|
1569
|
+
return !!value && !!value[DRAFT_STATE];
|
|
1570
|
+
}
|
|
1571
|
+
function isDraftable(value) {
|
|
1572
|
+
if (!value) return false;
|
|
1573
|
+
return isPlainObject(value) || Array.isArray(value) || !!value[DRAFTABLE] || !!value.constructor?.[DRAFTABLE] || isMap(value) || isSet(value);
|
|
1574
|
+
}
|
|
1575
|
+
var objectCtorString = Object.prototype.constructor.toString();
|
|
1576
|
+
var cachedCtorStrings = /* @__PURE__ */ new WeakMap();
|
|
1577
|
+
function isPlainObject(value) {
|
|
1578
|
+
if (!value || typeof value !== "object") return false;
|
|
1579
|
+
const proto = Object.getPrototypeOf(value);
|
|
1580
|
+
if (proto === null || proto === Object.prototype) return true;
|
|
1581
|
+
const Ctor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor;
|
|
1582
|
+
if (Ctor === Object) return true;
|
|
1583
|
+
if (typeof Ctor !== "function") return false;
|
|
1584
|
+
let ctorString = cachedCtorStrings.get(Ctor);
|
|
1585
|
+
if (ctorString === void 0) {
|
|
1586
|
+
ctorString = Function.toString.call(Ctor);
|
|
1587
|
+
cachedCtorStrings.set(Ctor, ctorString);
|
|
1588
|
+
}
|
|
1589
|
+
return ctorString === objectCtorString;
|
|
1590
|
+
}
|
|
1591
|
+
function each(obj, iter, strict = true) {
|
|
1592
|
+
if (getArchtype(obj) === 0) (strict ? Reflect.ownKeys(obj) : Object.keys(obj)).forEach((key) => {
|
|
1593
|
+
iter(key, obj[key], obj);
|
|
1594
|
+
});
|
|
1595
|
+
else obj.forEach((entry, index) => iter(index, entry, obj));
|
|
1596
|
+
}
|
|
1597
|
+
function getArchtype(thing) {
|
|
1598
|
+
const state = thing[DRAFT_STATE];
|
|
1599
|
+
return state ? state.type_ : Array.isArray(thing) ? 1 : isMap(thing) ? 2 : isSet(thing) ? 3 : 0;
|
|
1600
|
+
}
|
|
1601
|
+
function has(thing, prop) {
|
|
1602
|
+
return getArchtype(thing) === 2 ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop);
|
|
1603
|
+
}
|
|
1604
|
+
function set(thing, propOrOldValue, value) {
|
|
1605
|
+
const t = getArchtype(thing);
|
|
1606
|
+
if (t === 2) thing.set(propOrOldValue, value);
|
|
1607
|
+
else if (t === 3) thing.add(value);
|
|
1608
|
+
else thing[propOrOldValue] = value;
|
|
1609
|
+
}
|
|
1610
|
+
function is(x, y) {
|
|
1611
|
+
if (x === y) return x !== 0 || 1 / x === 1 / y;
|
|
1612
|
+
else return x !== x && y !== y;
|
|
1613
|
+
}
|
|
1614
|
+
function isMap(target) {
|
|
1615
|
+
return target instanceof Map;
|
|
1616
|
+
}
|
|
1617
|
+
function isSet(target) {
|
|
1618
|
+
return target instanceof Set;
|
|
1619
|
+
}
|
|
1620
|
+
function latest(state) {
|
|
1621
|
+
return state.copy_ || state.base_;
|
|
1622
|
+
}
|
|
1623
|
+
function shallowCopy(base, strict) {
|
|
1624
|
+
if (isMap(base)) return new Map(base);
|
|
1625
|
+
if (isSet(base)) return new Set(base);
|
|
1626
|
+
if (Array.isArray(base)) return Array.prototype.slice.call(base);
|
|
1627
|
+
const isPlain = isPlainObject(base);
|
|
1628
|
+
if (strict === true || strict === "class_only" && !isPlain) {
|
|
1629
|
+
const descriptors = Object.getOwnPropertyDescriptors(base);
|
|
1630
|
+
delete descriptors[DRAFT_STATE];
|
|
1631
|
+
let keys = Reflect.ownKeys(descriptors);
|
|
1632
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1633
|
+
const key = keys[i];
|
|
1634
|
+
const desc = descriptors[key];
|
|
1635
|
+
if (desc.writable === false) {
|
|
1636
|
+
desc.writable = true;
|
|
1637
|
+
desc.configurable = true;
|
|
1638
|
+
}
|
|
1639
|
+
if (desc.get || desc.set) descriptors[key] = {
|
|
1640
|
+
configurable: true,
|
|
1641
|
+
writable: true,
|
|
1642
|
+
enumerable: desc.enumerable,
|
|
1643
|
+
value: base[key]
|
|
1644
|
+
};
|
|
1645
|
+
}
|
|
1646
|
+
return Object.create(getPrototypeOf(base), descriptors);
|
|
1647
|
+
} else {
|
|
1648
|
+
const proto = getPrototypeOf(base);
|
|
1649
|
+
if (proto !== null && isPlain) return { ...base };
|
|
1650
|
+
const obj = Object.create(proto);
|
|
1651
|
+
return Object.assign(obj, base);
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
function freeze(obj, deep = false) {
|
|
1655
|
+
if (isFrozen(obj) || isDraft(obj) || !isDraftable(obj)) return obj;
|
|
1656
|
+
if (getArchtype(obj) > 1) Object.defineProperties(obj, {
|
|
1657
|
+
set: dontMutateMethodOverride,
|
|
1658
|
+
add: dontMutateMethodOverride,
|
|
1659
|
+
clear: dontMutateMethodOverride,
|
|
1660
|
+
delete: dontMutateMethodOverride
|
|
1661
|
+
});
|
|
1662
|
+
Object.freeze(obj);
|
|
1663
|
+
if (deep) Object.values(obj).forEach((value) => freeze(value, true));
|
|
1664
|
+
return obj;
|
|
1665
|
+
}
|
|
1666
|
+
function dontMutateFrozenCollections() {
|
|
1667
|
+
die(2);
|
|
1668
|
+
}
|
|
1669
|
+
var dontMutateMethodOverride = { value: dontMutateFrozenCollections };
|
|
1670
|
+
function isFrozen(obj) {
|
|
1671
|
+
if (obj === null || typeof obj !== "object") return true;
|
|
1672
|
+
return Object.isFrozen(obj);
|
|
1673
|
+
}
|
|
1674
|
+
var plugins = {};
|
|
1675
|
+
function getPlugin(pluginKey) {
|
|
1676
|
+
const plugin = plugins[pluginKey];
|
|
1677
|
+
if (!plugin) die(0, pluginKey);
|
|
1678
|
+
return plugin;
|
|
1679
|
+
}
|
|
1680
|
+
var currentScope;
|
|
1681
|
+
function getCurrentScope() {
|
|
1682
|
+
return currentScope;
|
|
1683
|
+
}
|
|
1684
|
+
function createScope(parent_, immer_) {
|
|
1685
|
+
return {
|
|
1686
|
+
drafts_: [],
|
|
1687
|
+
parent_,
|
|
1688
|
+
immer_,
|
|
1689
|
+
canAutoFreeze_: true,
|
|
1690
|
+
unfinalizedDrafts_: 0
|
|
1691
|
+
};
|
|
1692
|
+
}
|
|
1693
|
+
function usePatchesInScope(scope, patchListener) {
|
|
1694
|
+
if (patchListener) {
|
|
1695
|
+
getPlugin("Patches");
|
|
1696
|
+
scope.patches_ = [];
|
|
1697
|
+
scope.inversePatches_ = [];
|
|
1698
|
+
scope.patchListener_ = patchListener;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
function revokeScope(scope) {
|
|
1702
|
+
leaveScope(scope);
|
|
1703
|
+
scope.drafts_.forEach(revokeDraft);
|
|
1704
|
+
scope.drafts_ = null;
|
|
1705
|
+
}
|
|
1706
|
+
function leaveScope(scope) {
|
|
1707
|
+
if (scope === currentScope) currentScope = scope.parent_;
|
|
1708
|
+
}
|
|
1709
|
+
function enterScope(immer2) {
|
|
1710
|
+
return currentScope = createScope(currentScope, immer2);
|
|
1711
|
+
}
|
|
1712
|
+
function revokeDraft(draft) {
|
|
1713
|
+
const state = draft[DRAFT_STATE];
|
|
1714
|
+
if (state.type_ === 0 || state.type_ === 1) state.revoke_();
|
|
1715
|
+
else state.revoked_ = true;
|
|
1716
|
+
}
|
|
1717
|
+
function processResult(result, scope) {
|
|
1718
|
+
scope.unfinalizedDrafts_ = scope.drafts_.length;
|
|
1719
|
+
const baseDraft = scope.drafts_[0];
|
|
1720
|
+
if (result !== void 0 && result !== baseDraft) {
|
|
1721
|
+
if (baseDraft[DRAFT_STATE].modified_) {
|
|
1722
|
+
revokeScope(scope);
|
|
1723
|
+
die(4);
|
|
1724
|
+
}
|
|
1725
|
+
if (isDraftable(result)) {
|
|
1726
|
+
result = finalize(scope, result);
|
|
1727
|
+
if (!scope.parent_) maybeFreeze(scope, result);
|
|
1728
|
+
}
|
|
1729
|
+
if (scope.patches_) getPlugin("Patches").generateReplacementPatches_(baseDraft[DRAFT_STATE].base_, result, scope.patches_, scope.inversePatches_);
|
|
1730
|
+
} else result = finalize(scope, baseDraft, []);
|
|
1731
|
+
revokeScope(scope);
|
|
1732
|
+
if (scope.patches_) scope.patchListener_(scope.patches_, scope.inversePatches_);
|
|
1733
|
+
return result !== NOTHING ? result : void 0;
|
|
1734
|
+
}
|
|
1735
|
+
function finalize(rootScope, value, path) {
|
|
1736
|
+
if (isFrozen(value)) return value;
|
|
1737
|
+
const useStrictIteration = rootScope.immer_.shouldUseStrictIteration();
|
|
1738
|
+
const state = value[DRAFT_STATE];
|
|
1739
|
+
if (!state) {
|
|
1740
|
+
each(value, (key, childValue) => finalizeProperty(rootScope, state, value, key, childValue, path), useStrictIteration);
|
|
1741
|
+
return value;
|
|
1742
|
+
}
|
|
1743
|
+
if (state.scope_ !== rootScope) return value;
|
|
1744
|
+
if (!state.modified_) {
|
|
1745
|
+
maybeFreeze(rootScope, state.base_, true);
|
|
1746
|
+
return state.base_;
|
|
1747
|
+
}
|
|
1748
|
+
if (!state.finalized_) {
|
|
1749
|
+
state.finalized_ = true;
|
|
1750
|
+
state.scope_.unfinalizedDrafts_--;
|
|
1751
|
+
const result = state.copy_;
|
|
1752
|
+
let resultEach = result;
|
|
1753
|
+
let isSet2 = false;
|
|
1754
|
+
if (state.type_ === 3) {
|
|
1755
|
+
resultEach = new Set(result);
|
|
1756
|
+
result.clear();
|
|
1757
|
+
isSet2 = true;
|
|
1758
|
+
}
|
|
1759
|
+
each(resultEach, (key, childValue) => finalizeProperty(rootScope, state, result, key, childValue, path, isSet2), useStrictIteration);
|
|
1760
|
+
maybeFreeze(rootScope, result, false);
|
|
1761
|
+
if (path && rootScope.patches_) getPlugin("Patches").generatePatches_(state, path, rootScope.patches_, rootScope.inversePatches_);
|
|
1762
|
+
}
|
|
1763
|
+
return state.copy_;
|
|
1764
|
+
}
|
|
1765
|
+
function finalizeProperty(rootScope, parentState, targetObject, prop, childValue, rootPath, targetIsSet) {
|
|
1766
|
+
if (childValue == null) return;
|
|
1767
|
+
if (typeof childValue !== "object" && !targetIsSet) return;
|
|
1768
|
+
const childIsFrozen = isFrozen(childValue);
|
|
1769
|
+
if (childIsFrozen && !targetIsSet) return;
|
|
1770
|
+
if (isDraft(childValue)) {
|
|
1771
|
+
const res = finalize(rootScope, childValue, rootPath && parentState && parentState.type_ !== 3 && !has(parentState.assigned_, prop) ? rootPath.concat(prop) : void 0);
|
|
1772
|
+
set(targetObject, prop, res);
|
|
1773
|
+
if (isDraft(res)) rootScope.canAutoFreeze_ = false;
|
|
1774
|
+
else return;
|
|
1775
|
+
} else if (targetIsSet) targetObject.add(childValue);
|
|
1776
|
+
if (isDraftable(childValue) && !childIsFrozen) {
|
|
1777
|
+
if (!rootScope.immer_.autoFreeze_ && rootScope.unfinalizedDrafts_ < 1) return;
|
|
1778
|
+
if (parentState && parentState.base_ && parentState.base_[prop] === childValue && childIsFrozen) return;
|
|
1779
|
+
finalize(rootScope, childValue);
|
|
1780
|
+
if ((!parentState || !parentState.scope_.parent_) && typeof prop !== "symbol" && (isMap(targetObject) ? targetObject.has(prop) : Object.prototype.propertyIsEnumerable.call(targetObject, prop))) maybeFreeze(rootScope, childValue);
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
function maybeFreeze(scope, value, deep = false) {
|
|
1784
|
+
if (!scope.parent_ && scope.immer_.autoFreeze_ && scope.canAutoFreeze_) freeze(value, deep);
|
|
1785
|
+
}
|
|
1786
|
+
function createProxyProxy(base, parent) {
|
|
1787
|
+
const isArray = Array.isArray(base);
|
|
1788
|
+
const state = {
|
|
1789
|
+
type_: isArray ? 1 : 0,
|
|
1790
|
+
scope_: parent ? parent.scope_ : getCurrentScope(),
|
|
1791
|
+
modified_: false,
|
|
1792
|
+
finalized_: false,
|
|
1793
|
+
assigned_: {},
|
|
1794
|
+
parent_: parent,
|
|
1795
|
+
base_: base,
|
|
1796
|
+
draft_: null,
|
|
1797
|
+
copy_: null,
|
|
1798
|
+
revoke_: null,
|
|
1799
|
+
isManual_: false
|
|
1800
|
+
};
|
|
1801
|
+
let target = state;
|
|
1802
|
+
let traps = objectTraps;
|
|
1803
|
+
if (isArray) {
|
|
1804
|
+
target = [state];
|
|
1805
|
+
traps = arrayTraps;
|
|
1806
|
+
}
|
|
1807
|
+
const { revoke, proxy } = Proxy.revocable(target, traps);
|
|
1808
|
+
state.draft_ = proxy;
|
|
1809
|
+
state.revoke_ = revoke;
|
|
1810
|
+
return proxy;
|
|
1811
|
+
}
|
|
1812
|
+
var objectTraps = {
|
|
1813
|
+
get(state, prop) {
|
|
1814
|
+
if (prop === DRAFT_STATE) return state;
|
|
1815
|
+
const source = latest(state);
|
|
1816
|
+
if (!has(source, prop)) return readPropFromProto(state, source, prop);
|
|
1817
|
+
const value = source[prop];
|
|
1818
|
+
if (state.finalized_ || !isDraftable(value)) return value;
|
|
1819
|
+
if (value === peek(state.base_, prop)) {
|
|
1820
|
+
prepareCopy(state);
|
|
1821
|
+
return state.copy_[prop] = createProxy(value, state);
|
|
1822
|
+
}
|
|
1823
|
+
return value;
|
|
1824
|
+
},
|
|
1825
|
+
has(state, prop) {
|
|
1826
|
+
return prop in latest(state);
|
|
1827
|
+
},
|
|
1828
|
+
ownKeys(state) {
|
|
1829
|
+
return Reflect.ownKeys(latest(state));
|
|
1830
|
+
},
|
|
1831
|
+
set(state, prop, value) {
|
|
1832
|
+
const desc = getDescriptorFromProto(latest(state), prop);
|
|
1833
|
+
if (desc?.set) {
|
|
1834
|
+
desc.set.call(state.draft_, value);
|
|
1835
|
+
return true;
|
|
1836
|
+
}
|
|
1837
|
+
if (!state.modified_) {
|
|
1838
|
+
const current2 = peek(latest(state), prop);
|
|
1839
|
+
const currentState = current2?.[DRAFT_STATE];
|
|
1840
|
+
if (currentState && currentState.base_ === value) {
|
|
1841
|
+
state.copy_[prop] = value;
|
|
1842
|
+
state.assigned_[prop] = false;
|
|
1843
|
+
return true;
|
|
1844
|
+
}
|
|
1845
|
+
if (is(value, current2) && (value !== void 0 || has(state.base_, prop))) return true;
|
|
1846
|
+
prepareCopy(state);
|
|
1847
|
+
markChanged(state);
|
|
1848
|
+
}
|
|
1849
|
+
if (state.copy_[prop] === value && (value !== void 0 || prop in state.copy_) || Number.isNaN(value) && Number.isNaN(state.copy_[prop])) return true;
|
|
1850
|
+
state.copy_[prop] = value;
|
|
1851
|
+
state.assigned_[prop] = true;
|
|
1852
|
+
return true;
|
|
1853
|
+
},
|
|
1854
|
+
deleteProperty(state, prop) {
|
|
1855
|
+
if (peek(state.base_, prop) !== void 0 || prop in state.base_) {
|
|
1856
|
+
state.assigned_[prop] = false;
|
|
1857
|
+
prepareCopy(state);
|
|
1858
|
+
markChanged(state);
|
|
1859
|
+
} else delete state.assigned_[prop];
|
|
1860
|
+
if (state.copy_) delete state.copy_[prop];
|
|
1861
|
+
return true;
|
|
1862
|
+
},
|
|
1863
|
+
getOwnPropertyDescriptor(state, prop) {
|
|
1864
|
+
const owner = latest(state);
|
|
1865
|
+
const desc = Reflect.getOwnPropertyDescriptor(owner, prop);
|
|
1866
|
+
if (!desc) return desc;
|
|
1867
|
+
return {
|
|
1868
|
+
writable: true,
|
|
1869
|
+
configurable: state.type_ !== 1 || prop !== "length",
|
|
1870
|
+
enumerable: desc.enumerable,
|
|
1871
|
+
value: owner[prop]
|
|
1872
|
+
};
|
|
1873
|
+
},
|
|
1874
|
+
defineProperty() {
|
|
1875
|
+
die(11);
|
|
1876
|
+
},
|
|
1877
|
+
getPrototypeOf(state) {
|
|
1878
|
+
return getPrototypeOf(state.base_);
|
|
1879
|
+
},
|
|
1880
|
+
setPrototypeOf() {
|
|
1881
|
+
die(12);
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
var arrayTraps = {};
|
|
1885
|
+
each(objectTraps, (key, fn) => {
|
|
1886
|
+
arrayTraps[key] = function() {
|
|
1887
|
+
arguments[0] = arguments[0][0];
|
|
1888
|
+
return fn.apply(this, arguments);
|
|
1889
|
+
};
|
|
1890
|
+
});
|
|
1891
|
+
arrayTraps.deleteProperty = function(state, prop) {
|
|
1892
|
+
return arrayTraps.set.call(this, state, prop, void 0);
|
|
1893
|
+
};
|
|
1894
|
+
arrayTraps.set = function(state, prop, value) {
|
|
1895
|
+
return objectTraps.set.call(this, state[0], prop, value, state[0]);
|
|
1896
|
+
};
|
|
1897
|
+
function peek(draft, prop) {
|
|
1898
|
+
const state = draft[DRAFT_STATE];
|
|
1899
|
+
return (state ? latest(state) : draft)[prop];
|
|
1900
|
+
}
|
|
1901
|
+
function readPropFromProto(state, source, prop) {
|
|
1902
|
+
const desc = getDescriptorFromProto(source, prop);
|
|
1903
|
+
return desc ? `value` in desc ? desc.value : desc.get?.call(state.draft_) : void 0;
|
|
1904
|
+
}
|
|
1905
|
+
function getDescriptorFromProto(source, prop) {
|
|
1906
|
+
if (!(prop in source)) return void 0;
|
|
1907
|
+
let proto = getPrototypeOf(source);
|
|
1908
|
+
while (proto) {
|
|
1909
|
+
const desc = Object.getOwnPropertyDescriptor(proto, prop);
|
|
1910
|
+
if (desc) return desc;
|
|
1911
|
+
proto = getPrototypeOf(proto);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
function markChanged(state) {
|
|
1915
|
+
if (!state.modified_) {
|
|
1916
|
+
state.modified_ = true;
|
|
1917
|
+
if (state.parent_) markChanged(state.parent_);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
function prepareCopy(state) {
|
|
1921
|
+
if (!state.copy_) state.copy_ = shallowCopy(state.base_, state.scope_.immer_.useStrictShallowCopy_);
|
|
1922
|
+
}
|
|
1923
|
+
var Immer2 = class {
|
|
1924
|
+
constructor(config) {
|
|
1925
|
+
this.autoFreeze_ = true;
|
|
1926
|
+
this.useStrictShallowCopy_ = false;
|
|
1927
|
+
this.useStrictIteration_ = true;
|
|
1928
|
+
/**
|
|
1929
|
+
* The `produce` function takes a value and a "recipe function" (whose
|
|
1930
|
+
* return value often depends on the base state). The recipe function is
|
|
1931
|
+
* free to mutate its first argument however it wants. All mutations are
|
|
1932
|
+
* only ever applied to a __copy__ of the base state.
|
|
1933
|
+
*
|
|
1934
|
+
* Pass only a function to create a "curried producer" which relieves you
|
|
1935
|
+
* from passing the recipe function every time.
|
|
1936
|
+
*
|
|
1937
|
+
* Only plain objects and arrays are made mutable. All other objects are
|
|
1938
|
+
* considered uncopyable.
|
|
1939
|
+
*
|
|
1940
|
+
* Note: This function is __bound__ to its `Immer` instance.
|
|
1941
|
+
*
|
|
1942
|
+
* @param {any} base - the initial state
|
|
1943
|
+
* @param {Function} recipe - function that receives a proxy of the base state as first argument and which can be freely modified
|
|
1944
|
+
* @param {Function} patchListener - optional function that will be called with all the patches produced here
|
|
1945
|
+
* @returns {any} a new state, or the initial state if nothing was modified
|
|
1946
|
+
*/
|
|
1947
|
+
this.produce = (base, recipe, patchListener) => {
|
|
1948
|
+
if (typeof base === "function" && typeof recipe !== "function") {
|
|
1949
|
+
const defaultBase = recipe;
|
|
1950
|
+
recipe = base;
|
|
1951
|
+
const self = this;
|
|
1952
|
+
return function curriedProduce(base2 = defaultBase, ...args) {
|
|
1953
|
+
return self.produce(base2, (draft) => recipe.call(this, draft, ...args));
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
if (typeof recipe !== "function") die(6);
|
|
1957
|
+
if (patchListener !== void 0 && typeof patchListener !== "function") die(7);
|
|
1958
|
+
let result;
|
|
1959
|
+
if (isDraftable(base)) {
|
|
1960
|
+
const scope = enterScope(this);
|
|
1961
|
+
const proxy = createProxy(base, void 0);
|
|
1962
|
+
let hasError = true;
|
|
1963
|
+
try {
|
|
1964
|
+
result = recipe(proxy);
|
|
1965
|
+
hasError = false;
|
|
1966
|
+
} finally {
|
|
1967
|
+
if (hasError) revokeScope(scope);
|
|
1968
|
+
else leaveScope(scope);
|
|
1969
|
+
}
|
|
1970
|
+
usePatchesInScope(scope, patchListener);
|
|
1971
|
+
return processResult(result, scope);
|
|
1972
|
+
} else if (!base || typeof base !== "object") {
|
|
1973
|
+
result = recipe(base);
|
|
1974
|
+
if (result === void 0) result = base;
|
|
1975
|
+
if (result === NOTHING) result = void 0;
|
|
1976
|
+
if (this.autoFreeze_) freeze(result, true);
|
|
1977
|
+
if (patchListener) {
|
|
1978
|
+
const p = [];
|
|
1979
|
+
const ip = [];
|
|
1980
|
+
getPlugin("Patches").generateReplacementPatches_(base, result, p, ip);
|
|
1981
|
+
patchListener(p, ip);
|
|
1982
|
+
}
|
|
1983
|
+
return result;
|
|
1984
|
+
} else die(1, base);
|
|
1985
|
+
};
|
|
1986
|
+
this.produceWithPatches = (base, recipe) => {
|
|
1987
|
+
if (typeof base === "function") return (state, ...args) => this.produceWithPatches(state, (draft) => base(draft, ...args));
|
|
1988
|
+
let patches, inversePatches;
|
|
1989
|
+
return [
|
|
1990
|
+
this.produce(base, recipe, (p, ip) => {
|
|
1991
|
+
patches = p;
|
|
1992
|
+
inversePatches = ip;
|
|
1993
|
+
}),
|
|
1994
|
+
patches,
|
|
1995
|
+
inversePatches
|
|
1996
|
+
];
|
|
1997
|
+
};
|
|
1998
|
+
if (typeof config?.autoFreeze === "boolean") this.setAutoFreeze(config.autoFreeze);
|
|
1999
|
+
if (typeof config?.useStrictShallowCopy === "boolean") this.setUseStrictShallowCopy(config.useStrictShallowCopy);
|
|
2000
|
+
if (typeof config?.useStrictIteration === "boolean") this.setUseStrictIteration(config.useStrictIteration);
|
|
2001
|
+
}
|
|
2002
|
+
createDraft(base) {
|
|
2003
|
+
if (!isDraftable(base)) die(8);
|
|
2004
|
+
if (isDraft(base)) base = current(base);
|
|
2005
|
+
const scope = enterScope(this);
|
|
2006
|
+
const proxy = createProxy(base, void 0);
|
|
2007
|
+
proxy[DRAFT_STATE].isManual_ = true;
|
|
2008
|
+
leaveScope(scope);
|
|
2009
|
+
return proxy;
|
|
2010
|
+
}
|
|
2011
|
+
finishDraft(draft, patchListener) {
|
|
2012
|
+
const state = draft && draft[DRAFT_STATE];
|
|
2013
|
+
if (!state || !state.isManual_) die(9);
|
|
2014
|
+
const { scope_: scope } = state;
|
|
2015
|
+
usePatchesInScope(scope, patchListener);
|
|
2016
|
+
return processResult(void 0, scope);
|
|
2017
|
+
}
|
|
2018
|
+
/**
|
|
2019
|
+
* Pass true to automatically freeze all copies created by Immer.
|
|
2020
|
+
*
|
|
2021
|
+
* By default, auto-freezing is enabled.
|
|
2022
|
+
*/
|
|
2023
|
+
setAutoFreeze(value) {
|
|
2024
|
+
this.autoFreeze_ = value;
|
|
2025
|
+
}
|
|
2026
|
+
/**
|
|
2027
|
+
* Pass true to enable strict shallow copy.
|
|
2028
|
+
*
|
|
2029
|
+
* By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties.
|
|
2030
|
+
*/
|
|
2031
|
+
setUseStrictShallowCopy(value) {
|
|
2032
|
+
this.useStrictShallowCopy_ = value;
|
|
2033
|
+
}
|
|
2034
|
+
/**
|
|
2035
|
+
* Pass false to use faster iteration that skips non-enumerable properties
|
|
2036
|
+
* but still handles symbols for compatibility.
|
|
2037
|
+
*
|
|
2038
|
+
* By default, strict iteration is enabled (includes all own properties).
|
|
2039
|
+
*/
|
|
2040
|
+
setUseStrictIteration(value) {
|
|
2041
|
+
this.useStrictIteration_ = value;
|
|
2042
|
+
}
|
|
2043
|
+
shouldUseStrictIteration() {
|
|
2044
|
+
return this.useStrictIteration_;
|
|
2045
|
+
}
|
|
2046
|
+
applyPatches(base, patches) {
|
|
2047
|
+
let i;
|
|
2048
|
+
for (i = patches.length - 1; i >= 0; i--) {
|
|
2049
|
+
const patch = patches[i];
|
|
2050
|
+
if (patch.path.length === 0 && patch.op === "replace") {
|
|
2051
|
+
base = patch.value;
|
|
2052
|
+
break;
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
if (i > -1) patches = patches.slice(i + 1);
|
|
2056
|
+
const applyPatchesImpl = getPlugin("Patches").applyPatches_;
|
|
2057
|
+
if (isDraft(base)) return applyPatchesImpl(base, patches);
|
|
2058
|
+
return this.produce(base, (draft) => applyPatchesImpl(draft, patches));
|
|
2059
|
+
}
|
|
2060
|
+
};
|
|
2061
|
+
function createProxy(value, parent) {
|
|
2062
|
+
const draft = isMap(value) ? getPlugin("MapSet").proxyMap_(value, parent) : isSet(value) ? getPlugin("MapSet").proxySet_(value, parent) : createProxyProxy(value, parent);
|
|
2063
|
+
(parent ? parent.scope_ : getCurrentScope()).drafts_.push(draft);
|
|
2064
|
+
return draft;
|
|
2065
|
+
}
|
|
2066
|
+
function current(value) {
|
|
2067
|
+
if (!isDraft(value)) die(10, value);
|
|
2068
|
+
return currentImpl(value);
|
|
2069
|
+
}
|
|
2070
|
+
function currentImpl(value) {
|
|
2071
|
+
if (!isDraftable(value) || isFrozen(value)) return value;
|
|
2072
|
+
const state = value[DRAFT_STATE];
|
|
2073
|
+
let copy;
|
|
2074
|
+
let strict = true;
|
|
2075
|
+
if (state) {
|
|
2076
|
+
if (!state.modified_) return state.base_;
|
|
2077
|
+
state.finalized_ = true;
|
|
2078
|
+
copy = shallowCopy(value, state.scope_.immer_.useStrictShallowCopy_);
|
|
2079
|
+
strict = state.scope_.immer_.shouldUseStrictIteration();
|
|
2080
|
+
} else copy = shallowCopy(value, true);
|
|
2081
|
+
each(copy, (key, childValue) => {
|
|
2082
|
+
set(copy, key, currentImpl(childValue));
|
|
2083
|
+
}, strict);
|
|
2084
|
+
if (state) state.finalized_ = false;
|
|
2085
|
+
return copy;
|
|
2086
|
+
}
|
|
2087
|
+
var produce = new Immer2().produce;
|
|
2088
|
+
//#endregion
|
|
2089
|
+
//#region node_modules/@deepseek-ai/dsh-client-store/lib/index.js
|
|
2090
|
+
/**
|
|
2091
|
+
* React-free snapshot store engine (zustand vanilla + immer + subscribeWithSelector +
|
|
2092
|
+
* rafFlush middleware + opt-in persist + dev freeze) plus the declarative
|
|
2093
|
+
* shell over it: {@link defineStore} bakes an init/persist/actions literal
|
|
2094
|
+
* into a {@link StoreHandle}, the registration-side store seat of slot
|
|
2095
|
+
* terminals. Engine products are bare observables — subscribe/getSnapshot/
|
|
2096
|
+
* update/set, NO selector hook. Hook synthesis is ui-renderer's (the one
|
|
2097
|
+
* uSES bridge, cached per source at the binding site).
|
|
2098
|
+
*/
|
|
2099
|
+
/**
|
|
2100
|
+
* Notify an observer set without allowing one callback to starve the rest.
|
|
2101
|
+
* @param listeners - current observer callbacks; copied before dispatch.
|
|
2102
|
+
* @param label - diagnostic owner prefix.
|
|
2103
|
+
* @param args - callback arguments.
|
|
2104
|
+
*/
|
|
2105
|
+
function notifySubscribers(listeners, label, ...args) {
|
|
2106
|
+
for (const listener of [...listeners]) try {
|
|
2107
|
+
listener(...args);
|
|
2108
|
+
} catch (error) {
|
|
2109
|
+
console.error(`${label} subscriber failed:`, error);
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
/** Batches subscriber notification into one flush per animation frame. */
|
|
2113
|
+
function rafBatch(notify) {
|
|
2114
|
+
const schedule = typeof requestAnimationFrame === "function" ? (fn) => {
|
|
2115
|
+
requestAnimationFrame(() => {
|
|
2116
|
+
fn();
|
|
2117
|
+
});
|
|
2118
|
+
} : (fn) => {
|
|
2119
|
+
queueMicrotask(fn);
|
|
2120
|
+
};
|
|
2121
|
+
let scheduled = false;
|
|
2122
|
+
return () => {
|
|
2123
|
+
if (scheduled) return;
|
|
2124
|
+
scheduled = true;
|
|
2125
|
+
schedule(() => {
|
|
2126
|
+
scheduled = false;
|
|
2127
|
+
notify();
|
|
2128
|
+
});
|
|
2129
|
+
};
|
|
2130
|
+
}
|
|
2131
|
+
/**
|
|
2132
|
+
* Create a snapshot store.
|
|
2133
|
+
*
|
|
2134
|
+
* Flush default is 'sync' (controlled inputs need same-tick echo); frame-driven
|
|
2135
|
+
* stores opt into 'raf', where a frame's worth of updates coalesces into one
|
|
2136
|
+
* notification. Known raf-mode tradeoff: a component mounting mid-frame reads
|
|
2137
|
+
* fresh state while existing subscribers hear it next flush — transient
|
|
2138
|
+
* frame-level skew, same nature as the object layer's microtask batching.
|
|
2139
|
+
*
|
|
2140
|
+
* @param init - initial state.
|
|
2141
|
+
* @param opts - flush mode and opt-in persistence (localStorage, keyed by name).
|
|
2142
|
+
* @returns the store.
|
|
2143
|
+
*/
|
|
2144
|
+
function createSnapshotStore(init, opts) {
|
|
2145
|
+
const withSelector = subscribeWithSelector(() => init);
|
|
2146
|
+
const api = createStore()(withSelector);
|
|
2147
|
+
if (opts?.persist) attachPersistence(api, opts.persist.name);
|
|
2148
|
+
let subscribe = (fn) => api.subscribe(() => {
|
|
2149
|
+
notifySubscribers([fn], "[client-store]");
|
|
2150
|
+
});
|
|
2151
|
+
if (opts?.flush === "raf") {
|
|
2152
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2153
|
+
const flush = rafBatch(() => {
|
|
2154
|
+
notifySubscribers(listeners, "[client-store]");
|
|
2155
|
+
});
|
|
2156
|
+
api.subscribe(flush);
|
|
2157
|
+
subscribe = (fn) => {
|
|
2158
|
+
listeners.add(fn);
|
|
2159
|
+
return () => {
|
|
2160
|
+
listeners.delete(fn);
|
|
2161
|
+
};
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
2164
|
+
return {
|
|
2165
|
+
getSnapshot: () => api.getState(),
|
|
2166
|
+
subscribe: (fn) => subscribe(fn),
|
|
2167
|
+
update: (mutator) => {
|
|
2168
|
+
api.setState(produce(api.getState(), (draft) => {
|
|
2169
|
+
mutator(draft);
|
|
2170
|
+
}), true);
|
|
2171
|
+
},
|
|
2172
|
+
set: (next) => {
|
|
2173
|
+
api.setState(devFreeze(next), true);
|
|
2174
|
+
}
|
|
2175
|
+
};
|
|
2176
|
+
}
|
|
2177
|
+
/**
|
|
2178
|
+
* Whole-value JSON persistence to localStorage. Hand-rolled instead of the
|
|
2179
|
+
* zustand persist middleware: its write path spreads state into an object
|
|
2180
|
+
* (`partialize({ ...get() })`), exploding primitive state (a persisted string
|
|
2181
|
+
* draft becomes {0:'h',1:'e',...}) — not fixable via merge/deserialize options
|
|
2182
|
+
* because the corruption happens before serialization. Storage failures
|
|
2183
|
+
* (quota, private mode) only disable persistence, never break the store.
|
|
2184
|
+
*/
|
|
2185
|
+
function attachPersistence(api, name) {
|
|
2186
|
+
if (typeof localStorage === "undefined") return;
|
|
2187
|
+
try {
|
|
2188
|
+
const raw = localStorage.getItem(name);
|
|
2189
|
+
if (raw !== null) api.setState(devFreeze(JSON.parse(raw)), true);
|
|
2190
|
+
} catch (error) {
|
|
2191
|
+
console.error(`snapshot store '${name}' rehydration failed:`, error);
|
|
2192
|
+
}
|
|
2193
|
+
api.subscribe((state) => {
|
|
2194
|
+
try {
|
|
2195
|
+
localStorage.setItem(name, JSON.stringify(state));
|
|
2196
|
+
} catch (error) {
|
|
2197
|
+
console.error(`snapshot store '${name}' persistence failed:`, error);
|
|
2198
|
+
}
|
|
2199
|
+
});
|
|
2200
|
+
}
|
|
2201
|
+
/** Deep-freeze draftable wholesale-set state outside production: set() bypasses immer's freeze. */
|
|
2202
|
+
function devFreeze(value) {
|
|
2203
|
+
return freeze(value, true);
|
|
2204
|
+
}
|
|
2205
|
+
//#endregion
|
|
1469
2206
|
//#region src/client/settings-form.ts
|
|
1470
2207
|
/**
|
|
1471
2208
|
* Settings-card form machinery, vendored from the dsh-web-ui family bucket
|
|
@@ -1548,7 +2285,7 @@ window.__ModuleLoader__.load({
|
|
|
1548
2285
|
}
|
|
1549
2286
|
/** Publish a projection of this form, rebuilt whenever the scope or a draft changes. */
|
|
1550
2287
|
bind(project) {
|
|
1551
|
-
const store =
|
|
2288
|
+
const store = createSnapshotStore(project());
|
|
1552
2289
|
this.listeners.add(() => {
|
|
1553
2290
|
store.set(project());
|
|
1554
2291
|
});
|