dsh-theone 0.3.12 → 0.3.13
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 +1 -1
- package/README.zh.md +1 -1
- package/dist/client-locales.d.ts +9 -0
- package/dist/client-locales.js +18 -0
- package/dist/client.js +245 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +14 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ Each project gets its own background session that reasons, runs tools and compac
|
|
|
47
47
|
- **Related work connects; unrelated work stays out.** Related topics share progress automatically and TheOne learns which ones belong together from how you use them. A topic's constraints (say, "budget figures stay out of the paper") are attached verbatim every time, so compaction never drops them.
|
|
48
48
|
- **Gets better with use.** Say "wrong topic" or click **Move to…** in the directory, and similar messages go to the right place from then on.
|
|
49
49
|
- **Your old sessions become a topic directory.** After install it reads your existing sessions in the background, turns them into topics grouped into workspaces, and you pick up where you left off.
|
|
50
|
-
- **Nothing extra to configure.** No separate API key: routing and the background sessions use the model you chose in DSH.
|
|
50
|
+
- **Nothing extra to configure.** No separate API key: routing and the background sessions use the model you chose in DSH. When TheOne is the selected model, a **Background** button beside the model menu shows which model does the routing and the work, and switches it.
|
|
51
51
|
|
|
52
52
|

|
|
53
53
|
|
package/README.zh.md
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
- **相关的事会互通,无关的事互不打扰**:相关话题自动共享进展,并从你的使用中学习哪些话题有关联;话题的约束(比如「预算数字不能写进论文」)每次都原样带上,压缩不会把它丢掉。
|
|
48
48
|
- **越用越准**:说「分错了」或在目录里点「改到…」,TheOne 会记住,类似的消息以后直接分对。
|
|
49
49
|
- **旧会话自动变成话题目录**:装上后它会在后台读取你已有的会话,整理成话题并按工作区分组,直接接着聊。
|
|
50
|
-
- **零额外配置**:不用另填 API Key,路由和后台都用你在 DSH
|
|
50
|
+
- **零额外配置**:不用另填 API Key,路由和后台都用你在 DSH 里选好的模型。选中 TheOne 时,模型按钮旁边会出现 **后台** 按钮,显示并切换分配话题和干活用的模型。
|
|
51
51
|
|
|
52
52
|

|
|
53
53
|
|
package/dist/client-locales.d.ts
CHANGED
|
@@ -5,6 +5,15 @@ export declare const zh: {
|
|
|
5
5
|
readonly 'gateway.opening': "正在打开 TheOne 主聊天…";
|
|
6
6
|
readonly 'gateway.error': "主聊天暂时无法打开,请检查 DSH 连接和 TheOne 插件状态。";
|
|
7
7
|
readonly retry: "重试";
|
|
8
|
+
readonly 'bg.label': "后台";
|
|
9
|
+
readonly 'bg.follow': "默认";
|
|
10
|
+
readonly 'bg.title': "后台模型:分配话题和干活都用它";
|
|
11
|
+
readonly 'bg.followItem': "跟随 DSH 默认模型";
|
|
12
|
+
readonly 'bg.hint': "后台模型:{model}。TheOne 分配话题和后台干活都用这个模型。";
|
|
13
|
+
readonly 'bg.hintFollow': "后台模型:{model}(跟随 DSH 默认模型)。点击可以固定为其他模型。";
|
|
14
|
+
readonly 'bg.search': "搜索模型";
|
|
15
|
+
readonly 'bg.none': "没有匹配的模型";
|
|
16
|
+
readonly 'bg.error': "后台模型没有切换成功,请重试。";
|
|
8
17
|
readonly 'update.available': "更新";
|
|
9
18
|
readonly 'update.installing': "更新中…";
|
|
10
19
|
readonly 'update.restart': "重启生效";
|
package/dist/client-locales.js
CHANGED
|
@@ -5,6 +5,15 @@ export const zh = {
|
|
|
5
5
|
'gateway.opening': '正在打开 TheOne 主聊天…',
|
|
6
6
|
'gateway.error': '主聊天暂时无法打开,请检查 DSH 连接和 TheOne 插件状态。',
|
|
7
7
|
'retry': '重试',
|
|
8
|
+
'bg.label': '后台',
|
|
9
|
+
'bg.follow': '默认',
|
|
10
|
+
'bg.title': '后台模型:分配话题和干活都用它',
|
|
11
|
+
'bg.followItem': '跟随 DSH 默认模型',
|
|
12
|
+
'bg.hint': '后台模型:{model}。TheOne 分配话题和后台干活都用这个模型。',
|
|
13
|
+
'bg.hintFollow': '后台模型:{model}(跟随 DSH 默认模型)。点击可以固定为其他模型。',
|
|
14
|
+
'bg.search': '搜索模型',
|
|
15
|
+
'bg.none': '没有匹配的模型',
|
|
16
|
+
'bg.error': '后台模型没有切换成功,请重试。',
|
|
8
17
|
'update.available': '更新',
|
|
9
18
|
'update.installing': '更新中…',
|
|
10
19
|
'update.restart': '重启生效',
|
|
@@ -185,6 +194,15 @@ export const en = {
|
|
|
185
194
|
'gateway.opening': 'Opening TheOne main chat…',
|
|
186
195
|
'gateway.error': 'Main chat could not open. Check your DSH connection and TheOne plugin status.',
|
|
187
196
|
'retry': 'Retry',
|
|
197
|
+
'bg.label': 'Background',
|
|
198
|
+
'bg.follow': 'Default',
|
|
199
|
+
'bg.title': 'Background model: routes and does the work',
|
|
200
|
+
'bg.followItem': 'Follow DSH\'s default model',
|
|
201
|
+
'bg.hint': 'Background model: {model}. TheOne routes and does the background work with it.',
|
|
202
|
+
'bg.hintFollow': "Background model: {model} (following DSH's default). Click to pin another model.",
|
|
203
|
+
'bg.search': 'Search models',
|
|
204
|
+
'bg.none': 'No matching models',
|
|
205
|
+
'bg.error': 'The background model was not switched. Try again.',
|
|
188
206
|
'update.available': 'Update',
|
|
189
207
|
'update.installing': 'Updating…',
|
|
190
208
|
'update.restart': 'Restart to apply',
|
package/dist/client.js
CHANGED
|
@@ -88,6 +88,15 @@ var zh = {
|
|
|
88
88
|
"gateway.opening": "\u6B63\u5728\u6253\u5F00 TheOne \u4E3B\u804A\u5929\u2026",
|
|
89
89
|
"gateway.error": "\u4E3B\u804A\u5929\u6682\u65F6\u65E0\u6CD5\u6253\u5F00\uFF0C\u8BF7\u68C0\u67E5 DSH \u8FDE\u63A5\u548C TheOne \u63D2\u4EF6\u72B6\u6001\u3002",
|
|
90
90
|
"retry": "\u91CD\u8BD5",
|
|
91
|
+
"bg.label": "\u540E\u53F0",
|
|
92
|
+
"bg.follow": "\u9ED8\u8BA4",
|
|
93
|
+
"bg.title": "\u540E\u53F0\u6A21\u578B\uFF1A\u5206\u914D\u8BDD\u9898\u548C\u5E72\u6D3B\u90FD\u7528\u5B83",
|
|
94
|
+
"bg.followItem": "\u8DDF\u968F DSH \u9ED8\u8BA4\u6A21\u578B",
|
|
95
|
+
"bg.hint": "\u540E\u53F0\u6A21\u578B\uFF1A{model}\u3002TheOne \u5206\u914D\u8BDD\u9898\u548C\u540E\u53F0\u5E72\u6D3B\u90FD\u7528\u8FD9\u4E2A\u6A21\u578B\u3002",
|
|
96
|
+
"bg.hintFollow": "\u540E\u53F0\u6A21\u578B\uFF1A{model}\uFF08\u8DDF\u968F DSH \u9ED8\u8BA4\u6A21\u578B\uFF09\u3002\u70B9\u51FB\u53EF\u4EE5\u56FA\u5B9A\u4E3A\u5176\u4ED6\u6A21\u578B\u3002",
|
|
97
|
+
"bg.search": "\u641C\u7D22\u6A21\u578B",
|
|
98
|
+
"bg.none": "\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B",
|
|
99
|
+
"bg.error": "\u540E\u53F0\u6A21\u578B\u6CA1\u6709\u5207\u6362\u6210\u529F\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
91
100
|
"update.available": "\u66F4\u65B0",
|
|
92
101
|
"update.installing": "\u66F4\u65B0\u4E2D\u2026",
|
|
93
102
|
"update.restart": "\u91CD\u542F\u751F\u6548",
|
|
@@ -268,6 +277,15 @@ var en = {
|
|
|
268
277
|
"gateway.opening": "Opening TheOne main chat\u2026",
|
|
269
278
|
"gateway.error": "Main chat could not open. Check your DSH connection and TheOne plugin status.",
|
|
270
279
|
"retry": "Retry",
|
|
280
|
+
"bg.label": "Background",
|
|
281
|
+
"bg.follow": "Default",
|
|
282
|
+
"bg.title": "Background model: routes and does the work",
|
|
283
|
+
"bg.followItem": "Follow DSH's default model",
|
|
284
|
+
"bg.hint": "Background model: {model}. TheOne routes and does the background work with it.",
|
|
285
|
+
"bg.hintFollow": "Background model: {model} (following DSH's default). Click to pin another model.",
|
|
286
|
+
"bg.search": "Search models",
|
|
287
|
+
"bg.none": "No matching models",
|
|
288
|
+
"bg.error": "The background model was not switched. Try again.",
|
|
271
289
|
"update.available": "Update",
|
|
272
290
|
"update.installing": "Updating\u2026",
|
|
273
291
|
"update.restart": "Restart to apply",
|
|
@@ -733,6 +751,210 @@ function apply(ctx) {
|
|
|
733
751
|
size === 16 && (0, import_react.createElement)(UpdateButton)
|
|
734
752
|
);
|
|
735
753
|
}
|
|
754
|
+
const readSettings = async () => {
|
|
755
|
+
const response = await fetch("/api/theone/settings", { signal: lifetime.signal, cache: "no-store" });
|
|
756
|
+
if (!response.ok) throw new Error("Settings unavailable");
|
|
757
|
+
return await response.json();
|
|
758
|
+
};
|
|
759
|
+
const saveBackgroundModel = async (choice) => {
|
|
760
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
761
|
+
const current = await readSettings();
|
|
762
|
+
const response = await fetch("/api/theone/settings", {
|
|
763
|
+
method: "PUT",
|
|
764
|
+
signal: lifetime.signal,
|
|
765
|
+
cache: "no-store",
|
|
766
|
+
headers: { "content-type": "application/json" },
|
|
767
|
+
body: JSON.stringify({ revision: current.revision, values: { ...current.savedValues, workerProvider: choice?.provider ?? null, workerModel: choice?.model ?? null } })
|
|
768
|
+
});
|
|
769
|
+
if (response.ok) return await response.json();
|
|
770
|
+
if (response.status !== 409) break;
|
|
771
|
+
}
|
|
772
|
+
throw new Error("Background model not saved");
|
|
773
|
+
};
|
|
774
|
+
function BackgroundModel({ directory }) {
|
|
775
|
+
const t2 = useText();
|
|
776
|
+
const state = (0, import_react.useSyncExternalStore)((listener) => directory.subscribe(listener), () => directory.getSnapshot());
|
|
777
|
+
const selection = state.pending ?? state.current;
|
|
778
|
+
const theone = selection?.provider === "theone";
|
|
779
|
+
const [settings, setSettings] = (0, import_react.useState)();
|
|
780
|
+
const [failed, setFailed] = (0, import_react.useState)(false);
|
|
781
|
+
const [saving, setSaving] = (0, import_react.useState)(false);
|
|
782
|
+
const button = (0, import_react.useRef)(null);
|
|
783
|
+
const closeMenu = (0, import_react.useRef)();
|
|
784
|
+
(0, import_react.useEffect)(() => {
|
|
785
|
+
if (!theone) return;
|
|
786
|
+
let alive = true;
|
|
787
|
+
readSettings().then((value) => {
|
|
788
|
+
if (alive) setSettings(value);
|
|
789
|
+
}, () => {
|
|
790
|
+
});
|
|
791
|
+
return () => {
|
|
792
|
+
alive = false;
|
|
793
|
+
closeMenu.current?.();
|
|
794
|
+
};
|
|
795
|
+
}, [theone]);
|
|
796
|
+
if (!theone) return null;
|
|
797
|
+
const pinned = settings?.values.workerProvider && settings.values.workerModel ? { provider: settings.values.workerProvider, model: settings.values.workerModel } : null;
|
|
798
|
+
const nameOf = (provider, model) => settings?.models.find((item) => item.provider === provider && item.id === model)?.name ?? model;
|
|
799
|
+
const effective = settings?.model ? nameOf(settings.model.provider, settings.model.model) : void 0;
|
|
800
|
+
const label = pinned ? nameOf(pinned.provider, pinned.model) : effective ?? t2("bg.follow");
|
|
801
|
+
const choose = async (choice) => {
|
|
802
|
+
closeMenu.current?.();
|
|
803
|
+
setSaving(true);
|
|
804
|
+
setFailed(false);
|
|
805
|
+
try {
|
|
806
|
+
setSettings(await saveBackgroundModel(choice));
|
|
807
|
+
} catch {
|
|
808
|
+
setFailed(true);
|
|
809
|
+
} finally {
|
|
810
|
+
setSaving(false);
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
const open = () => {
|
|
814
|
+
const anchor = button.current;
|
|
815
|
+
if (!anchor || closeMenu.current) {
|
|
816
|
+
closeMenu.current?.();
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
const menu = document.createElement("div");
|
|
820
|
+
menu.className = "theone-bg-menu";
|
|
821
|
+
menu.setAttribute("role", "menu");
|
|
822
|
+
menu.setAttribute("translate", "no");
|
|
823
|
+
menu.setAttribute("aria-label", t2("bg.title"));
|
|
824
|
+
const heading = document.createElement("div");
|
|
825
|
+
heading.className = "theone-bg-heading";
|
|
826
|
+
heading.textContent = t2("bg.title");
|
|
827
|
+
const list = document.createElement("div");
|
|
828
|
+
list.className = "theone-bg-list";
|
|
829
|
+
const models = (settings?.models ?? []).filter((item2) => item2.provider !== "theone");
|
|
830
|
+
const item = (text, sub, checked, pick) => {
|
|
831
|
+
const row = document.createElement("button");
|
|
832
|
+
row.type = "button";
|
|
833
|
+
row.setAttribute("role", "menuitemradio");
|
|
834
|
+
row.setAttribute("aria-checked", String(checked));
|
|
835
|
+
row.className = "theone-bg-item";
|
|
836
|
+
const name = document.createElement("span");
|
|
837
|
+
name.textContent = text;
|
|
838
|
+
row.append(name);
|
|
839
|
+
if (sub) {
|
|
840
|
+
const small = document.createElement("small");
|
|
841
|
+
small.textContent = sub;
|
|
842
|
+
row.append(small);
|
|
843
|
+
}
|
|
844
|
+
const mark = document.createElement("span");
|
|
845
|
+
mark.className = "theone-bg-check";
|
|
846
|
+
mark.textContent = checked ? "\u2713" : "";
|
|
847
|
+
row.append(mark);
|
|
848
|
+
row.addEventListener("click", pick);
|
|
849
|
+
return row;
|
|
850
|
+
};
|
|
851
|
+
const render = (query) => {
|
|
852
|
+
list.replaceChildren(item(t2("bg.followItem"), !pinned && effective ? effective : void 0, !pinned, () => {
|
|
853
|
+
void choose(null);
|
|
854
|
+
}));
|
|
855
|
+
const needle = query.trim().toLowerCase();
|
|
856
|
+
const matched = models.filter((model) => !needle || `${model.name} ${model.id} ${model.provider}`.toLowerCase().includes(needle));
|
|
857
|
+
for (const provider of [...new Set(matched.map((model) => model.provider))]) {
|
|
858
|
+
const group = document.createElement("div");
|
|
859
|
+
group.className = "theone-bg-group";
|
|
860
|
+
group.textContent = provider;
|
|
861
|
+
list.append(group);
|
|
862
|
+
for (const model of matched.filter((entry) => entry.provider === provider))
|
|
863
|
+
list.append(item(model.name, model.name !== model.id ? model.id : void 0, pinned?.provider === model.provider && pinned.model === model.id, () => {
|
|
864
|
+
void choose({ provider: model.provider, model: model.id });
|
|
865
|
+
}));
|
|
866
|
+
}
|
|
867
|
+
if (!matched.length && needle) {
|
|
868
|
+
const empty = document.createElement("p");
|
|
869
|
+
empty.className = "theone-bg-empty";
|
|
870
|
+
empty.textContent = t2("bg.none");
|
|
871
|
+
list.append(empty);
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
menu.append(heading);
|
|
875
|
+
let search;
|
|
876
|
+
if (models.length > 8) {
|
|
877
|
+
search = document.createElement("input");
|
|
878
|
+
search.type = "search";
|
|
879
|
+
search.className = "theone-bg-search";
|
|
880
|
+
search.placeholder = t2("bg.search");
|
|
881
|
+
search.addEventListener("input", () => render(search.value));
|
|
882
|
+
menu.append(search);
|
|
883
|
+
}
|
|
884
|
+
menu.append(list);
|
|
885
|
+
render("");
|
|
886
|
+
document.body.append(menu);
|
|
887
|
+
anchor.setAttribute("aria-expanded", "true");
|
|
888
|
+
const place = () => {
|
|
889
|
+
const bounds = anchor.getBoundingClientRect(), size = menu.getBoundingClientRect();
|
|
890
|
+
menu.style.left = `${Math.max(8, Math.min(bounds.right - size.width, window.innerWidth - size.width - 8))}px`;
|
|
891
|
+
menu.style.top = `${Math.max(8, bounds.top - size.height - 8)}px`;
|
|
892
|
+
};
|
|
893
|
+
place();
|
|
894
|
+
const rows = () => [...menu.querySelectorAll(".theone-bg-item")];
|
|
895
|
+
const outside = (event) => {
|
|
896
|
+
if (!menu.contains(event.target) && !anchor.contains(event.target)) close();
|
|
897
|
+
};
|
|
898
|
+
const keydown = (event) => {
|
|
899
|
+
if (event.key === "Escape") {
|
|
900
|
+
event.preventDefault();
|
|
901
|
+
close();
|
|
902
|
+
anchor.focus();
|
|
903
|
+
} else if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
904
|
+
event.preventDefault();
|
|
905
|
+
const all = rows(), index = all.indexOf(document.activeElement);
|
|
906
|
+
all[(index + (event.key === "ArrowDown" ? 1 : all.length - 1) + (index < 0 && event.key === "ArrowUp" ? 1 : 0)) % all.length]?.focus();
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
const close = () => {
|
|
910
|
+
menu.remove();
|
|
911
|
+
closeMenu.current = void 0;
|
|
912
|
+
anchor.setAttribute("aria-expanded", "false");
|
|
913
|
+
document.removeEventListener("pointerdown", outside, true);
|
|
914
|
+
document.removeEventListener("keydown", keydown, true);
|
|
915
|
+
window.removeEventListener("resize", close);
|
|
916
|
+
window.removeEventListener("blur", close);
|
|
917
|
+
};
|
|
918
|
+
closeMenu.current = close;
|
|
919
|
+
document.addEventListener("pointerdown", outside, true);
|
|
920
|
+
document.addEventListener("keydown", keydown, true);
|
|
921
|
+
window.addEventListener("resize", close);
|
|
922
|
+
window.addEventListener("blur", close);
|
|
923
|
+
(search ?? rows().find((row) => row.getAttribute("aria-checked") === "true") ?? rows()[0])?.focus();
|
|
924
|
+
};
|
|
925
|
+
const title = failed ? t2("bg.error") : t2(pinned ? "bg.hint" : "bg.hintFollow", { model: label });
|
|
926
|
+
return (0, import_react.createElement)(
|
|
927
|
+
"button",
|
|
928
|
+
{
|
|
929
|
+
ref: button,
|
|
930
|
+
type: "button",
|
|
931
|
+
className: "theone-bg",
|
|
932
|
+
title,
|
|
933
|
+
"aria-label": title,
|
|
934
|
+
"aria-haspopup": "menu",
|
|
935
|
+
"data-failed": failed,
|
|
936
|
+
disabled: saving,
|
|
937
|
+
onClick: () => {
|
|
938
|
+
if (settings) open();
|
|
939
|
+
else readSettings().then((value) => {
|
|
940
|
+
setSettings(value);
|
|
941
|
+
}, () => setFailed(true));
|
|
942
|
+
}
|
|
943
|
+
},
|
|
944
|
+
(0, import_react.createElement)("span", { className: "theone-bg-caption" }, t2("bg.label")),
|
|
945
|
+
(0, import_react.createElement)("span", { className: "theone-bg-text" }, label),
|
|
946
|
+
(0, import_react.createElement)("span", { className: "theone-bg-chevron", "aria-hidden": true }, saving ? "\u2026" : "\u2303")
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
ctx.inject(["slots", "modelDirectories"], (scope) => {
|
|
950
|
+
const slots = scope.slots;
|
|
951
|
+
slots.inject("conversation.input.right", () => slots.register({
|
|
952
|
+
name: "conversation.input.right",
|
|
953
|
+
id: "theone.background-model",
|
|
954
|
+
order: 100,
|
|
955
|
+
inject: (sessionId) => ({ directory: scope.modelDirectories.directoryFor(sessionId).store })
|
|
956
|
+
}, BackgroundModel));
|
|
957
|
+
});
|
|
736
958
|
function GatewayPanel() {
|
|
737
959
|
const t2 = useText();
|
|
738
960
|
const [error, setError] = (0, import_react.useState)();
|
|
@@ -1415,7 +1637,7 @@ function apply(ctx) {
|
|
|
1415
1637
|
ctx.effect(() => {
|
|
1416
1638
|
const style = document.createElement("style");
|
|
1417
1639
|
style.dataset.plugin = "dsh-theone";
|
|
1418
|
-
style.textContent = sidebarCss + catalogCss + settingsCss;
|
|
1640
|
+
style.textContent = sidebarCss + catalogCss + settingsCss + composerCss;
|
|
1419
1641
|
document.head.append(style);
|
|
1420
1642
|
return () => {
|
|
1421
1643
|
lifetime.abort();
|
|
@@ -1494,6 +1716,28 @@ button:has(.theone-catalog-entry)>span:not(:has(.theone-catalog-entry)){display:
|
|
|
1494
1716
|
.theone-catalog{padding:32px;max-width:1180px;margin:auto;box-sizing:border-box;height:100%;overflow:auto;color:var(--dsw-alias-label-primary)}
|
|
1495
1717
|
.theone-catalog-header{display:flex;justify-content:space-between;align-items:center;gap:16px}.theone-catalog h1{font-size:24px;margin:0 0 8px}.theone-catalog-header p,.theone-catalog-status,.theone-group-summary{opacity:.65;margin:0 0 18px;line-height:1.6}.theone-catalog button{border:1px solid #8883;border-radius:9px;padding:8px 13px;background:transparent;color:inherit;cursor:pointer;font:inherit;white-space:nowrap}.theone-catalog button:disabled{opacity:.5;cursor:default}.theone-catalog-groups{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,310px),1fr));gap:20px}.theone-topic-group{border:1px solid #8882;border-radius:16px;padding:20px;background:#88805}.theone-topic-group h2{font-size:18px;margin:0 0 8px}.theone-topic-group h2 span{font-size:13px;opacity:.5}.theone-topic-card{border-top:1px solid #8882;padding:16px 0}.theone-topic-card:last-child{padding-bottom:0}.theone-topic-card h3{font-size:15px;line-height:1.5;margin:0 0 7px}.theone-topic-card p{font-size:13px;line-height:1.7;opacity:.75;margin:0 0 12px;display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}.theone-topic-actions{display:flex;gap:8px;flex-wrap:wrap}.theone-topic-actions button{font-size:12px}.theone-topic-actions .theone-source-link{border-color:transparent;opacity:.6}.theone-catalog-warning{background:#ff900011;padding:12px;border-radius:10px;font-size:13px}.theone-catalog-entry{display:flex;align-items:center;gap:10px;font-size:14px}.theone-catalog-empty{padding:40px 0;opacity:.65;line-height:1.8}.theone-catalog-tools{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}.theone-topic-links{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0 0 12px;font-size:12px}.theone-links-label,.theone-links-empty{opacity:.6}.theone-link-chip{display:inline-flex;align-items:center;gap:2px;border:1px solid #8883;border-radius:999px;padding:2px 4px 2px 9px}.theone-catalog .theone-link-chip button{border:0;padding:0 5px;opacity:.6;font-size:13px;line-height:1}.theone-topic-links select{font:inherit;font-size:12px;color:inherit;background:transparent;border:1px solid #8883;border-radius:8px;padding:2px 6px}.theone-link-private{display:inline-flex;align-items:center;gap:4px;opacity:.75;cursor:pointer}.theone-topic-card .theone-topic-state{font-size:12px;opacity:.8;-webkit-line-clamp:3}.theone-topic-state span{opacity:.6;margin-right:4px}.theone-manage{display:flex;flex-direction:column;gap:10px;margin-top:12px;padding:14px;border:1px solid #8883;border-radius:12px;font-size:12px}.theone-create{flex-direction:row;flex-wrap:wrap;align-items:center;margin:0 0 18px}.theone-create input{flex:1;min-width:180px}.theone-manage-field{display:flex;flex-direction:column;gap:5px}.theone-manage-field>span{opacity:.65}.theone-manage input,.theone-manage textarea,.theone-manage select,.theone-routes select{font:inherit;font-size:12px;color:inherit;background:transparent;border:1px solid #8883;border-radius:8px;padding:6px 8px;box-sizing:border-box;min-width:0}.theone-manage textarea{resize:vertical;width:100%}.theone-manage-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.theone-manage-row select,.theone-manage-row input{flex:1;min-width:140px}.theone-manage-hint{opacity:.6;font-size:12px;line-height:1.6;margin:0}.theone-catalog .theone-danger{color:#c4402f;border-color:#c4402f55}.theone-routes{border:1px solid #8882;border-radius:16px;padding:14px 20px;margin:0 0 20px}.theone-routes summary{cursor:pointer;font-weight:500}.theone-routes summary span{opacity:.5;font-size:13px}.theone-routes ol{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:10px}.theone-routes li{border-top:1px solid #8882;padding-top:10px;font-size:12px;display:flex;flex-direction:column;gap:5px}.theone-route-head{display:flex;gap:10px;min-width:0}.theone-route-head time{opacity:.55;flex:none}.theone-route-head q{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.theone-route-body{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.theone-route-body small{opacity:.6}.theone-route-fixed{opacity:.75}@media(max-width:640px){.theone-catalog{padding:20px}.theone-catalog-header{align-items:flex-start}.theone-catalog-header h1{font-size:21px}}
|
|
1496
1718
|
`;
|
|
1719
|
+
var composerCss = `
|
|
1720
|
+
.theone-bg{display:inline-flex;align-items:center;gap:5px;height:32px;padding:0 10px;border:0;border-radius:10px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;white-space:nowrap;cursor:pointer;max-width:220px}
|
|
1721
|
+
.theone-bg:hover,.theone-bg[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}
|
|
1722
|
+
.theone-bg:focus-visible{outline:2px solid var(--dsw-focus-ring-color,#4a7fb5);outline-offset:1px}
|
|
1723
|
+
.theone-bg:disabled{opacity:.6;cursor:default}
|
|
1724
|
+
.theone-bg-caption,.theone-bg-chevron{color:var(--dsw-alias-label-secondary)}
|
|
1725
|
+
.theone-bg-text{overflow:hidden;text-overflow:ellipsis;display:var(--dsh-composer-model-text-display,inline)}
|
|
1726
|
+
.theone-bg-chevron{font-size:11px}
|
|
1727
|
+
.theone-bg[data-failed=true] .theone-bg-caption{color:#d9480f}
|
|
1728
|
+
.theone-bg-menu{position:fixed;z-index:10000;width:280px;max-height:min(420px,70vh);display:flex;flex-direction:column;padding:6px;border:1px solid var(--dsw-alias-border-l2);border-radius:14px;background:var(--dsw-specific-sidebar-fill);color:var(--dsw-alias-label-primary);box-shadow:0 10px 32px #0003;font:inherit;font-size:14px;box-sizing:border-box}
|
|
1729
|
+
.theone-bg-heading{padding:8px 10px 6px;font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
1730
|
+
.theone-bg-search{margin:0 4px 6px;padding:7px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:transparent;color:inherit;font:inherit;font-size:13px;outline:none}
|
|
1731
|
+
.theone-bg-search:focus{border-color:var(--dsw-focus-ring-color,#4a7fb5)}
|
|
1732
|
+
.theone-bg-list{overflow:auto;min-height:0}
|
|
1733
|
+
.theone-bg-group{padding:8px 10px 4px;font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
1734
|
+
.theone-bg-item{display:flex;align-items:center;gap:8px;width:100%;padding:9px 10px;border:0;border-radius:8px;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}
|
|
1735
|
+
.theone-bg-item:hover,.theone-bg-item:focus-visible{outline:none;background:var(--dsw-alias-interactive-bg-hover)}
|
|
1736
|
+
.theone-bg-item span:first-child{flex:0 1 auto;min-width:40px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
1737
|
+
.theone-bg-item small{flex:0 100 auto;color:var(--dsw-alias-label-secondary);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
|
|
1738
|
+
.theone-bg-check{margin-left:auto;flex:none;width:14px;text-align:center;color:var(--dsw-alias-label-primary)}
|
|
1739
|
+
.theone-bg-empty{margin:8px 10px;font-size:13px;color:var(--dsw-alias-label-secondary)}
|
|
1740
|
+
`;
|
|
1497
1741
|
var settingsCss = `
|
|
1498
1742
|
.theone-settings{--one-settings-accent:#a75b1e}[data-ds-dark-theme] .theone-settings{--one-settings-accent:#93c8f3}
|
|
1499
1743
|
.theone-settings input,.theone-settings select{width:100%;box-sizing:border-box;min-height:38px;padding:8px 11px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;font:inherit;color:inherit;background:var(--dsw-specific-sidebar-fill)}.theone-settings input:focus-visible,.theone-settings select:focus-visible{outline:2px solid var(--one-settings-accent);outline-offset:2px}.theone-settings input:disabled,.theone-settings select:disabled,.theone-settings button:disabled{opacity:.5;cursor:default}.theone-settings small{display:block;margin-top:5px;color:var(--dsw-alias-label-secondary);font-size:12px}
|
package/dist/index.d.ts
CHANGED
|
@@ -76,6 +76,7 @@ export default class TheOne extends Service {
|
|
|
76
76
|
private readonly closing;
|
|
77
77
|
/** A model the user picked in main chat's own model selector; it answers through the Workers. */
|
|
78
78
|
private pickedModel?;
|
|
79
|
+
private adapter?;
|
|
79
80
|
/** Update checks and one-click install through DSH's plugin manager. */
|
|
80
81
|
readonly updater: Updater;
|
|
81
82
|
/** Sessions whose current step answers through TheOne; only these refuse to run tools themselves. */
|
|
@@ -97,7 +98,10 @@ export default class TheOne extends Service {
|
|
|
97
98
|
private backingModel;
|
|
98
99
|
/** Every model DSH offers besides TheOne; a provider that cannot list its models in time offers none. */
|
|
99
100
|
private offeredModels;
|
|
100
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* Main chat's model menu has one TheOne entry; the background model is chosen with the button
|
|
103
|
+
* beside it. Selections of the older "TheOne · <model>" entries still resolve.
|
|
104
|
+
*/
|
|
101
105
|
gatewayModels(provider: string): Promise<LlmModelInfo[]>;
|
|
102
106
|
/** The entry has exactly the backing model's capacity, including DSH overrides. */
|
|
103
107
|
gatewayModelInfo(provider?: string, signal?: AbortSignal, model?: string): Promise<LlmResolvedModelInfo>;
|
package/dist/index.js
CHANGED
|
@@ -166,6 +166,7 @@ export default class TheOne extends Service {
|
|
|
166
166
|
closing = new Map();
|
|
167
167
|
/** A model the user picked in main chat's own model selector; it answers through the Workers. */
|
|
168
168
|
pickedModel;
|
|
169
|
+
adapter;
|
|
169
170
|
/** Update checks and one-click install through DSH's plugin manager. */
|
|
170
171
|
updater;
|
|
171
172
|
/** Sessions whose current step answers through TheOne; only these refuse to run tools themselves. */
|
|
@@ -231,7 +232,7 @@ export default class TheOne extends Service {
|
|
|
231
232
|
this.catalog.start();
|
|
232
233
|
}
|
|
233
234
|
this.registerCatalogChannel();
|
|
234
|
-
ctx.llm.registerAdapter(['theone'], new GatewayAdapter(this));
|
|
235
|
+
this.adapter = ctx.llm.registerAdapter(['theone'], new GatewayAdapter(this));
|
|
235
236
|
ctx.on('session/event', (session, event) => {
|
|
236
237
|
if (event.type === 'turn/end') {
|
|
237
238
|
if (session.id === this.reservedGateway)
|
|
@@ -801,7 +802,14 @@ export default class TheOne extends Service {
|
|
|
801
802
|
const { historyCatalog: _catalog, catalogIntervalMs: _interval, ...live } = settingsConfig(values);
|
|
802
803
|
if (live.routerMode !== this.config.routerMode)
|
|
803
804
|
this.router = this.routerFor(live.routerMode);
|
|
805
|
+
const modelChanged = live.workerProvider !== this.config.workerProvider || live.workerModel !== this.config.workerModel;
|
|
804
806
|
this.config = { ...this.config, ...live };
|
|
807
|
+
// Main chat's reasoning levels and image input are the background model's; DSH re-reads them on this signal.
|
|
808
|
+
if (modelChanged)
|
|
809
|
+
try {
|
|
810
|
+
this.adapter?.replace(['theone']);
|
|
811
|
+
}
|
|
812
|
+
catch { /* Released during shutdown. */ }
|
|
805
813
|
this.store.seed(descriptors);
|
|
806
814
|
}
|
|
807
815
|
/** Capture before Web saves the gateway itself as DSH's new default. */
|
|
@@ -828,18 +836,14 @@ export default class TheOne extends Service {
|
|
|
828
836
|
.catch(() => [])));
|
|
829
837
|
return listed.flat();
|
|
830
838
|
}
|
|
831
|
-
/**
|
|
839
|
+
/**
|
|
840
|
+
* Main chat's model menu has one TheOne entry; the background model is chosen with the button
|
|
841
|
+
* beside it. Selections of the older "TheOne · <model>" entries still resolve.
|
|
842
|
+
*/
|
|
832
843
|
async gatewayModels(provider) {
|
|
833
844
|
// The entry accepts whatever the backing model accepts (e.g. images).
|
|
834
845
|
const info = await this.gatewayModelInfo(provider).catch(() => undefined);
|
|
835
|
-
|
|
836
|
-
// A model pinned in TheOne's settings decides for the Workers, so choices here would do nothing.
|
|
837
|
-
if (this.config.workerProvider && this.config.workerModel)
|
|
838
|
-
return models;
|
|
839
|
-
for (const model of await this.offeredModels())
|
|
840
|
-
models.push({ provider, id: viaModel({ provider: model.provider, model: model.id }), name: `TheOne · ${model.name}`,
|
|
841
|
-
...(model.description ? { description: model.description } : {}), ...(model.inputModalities ? { inputModalities: [...model.inputModalities] } : {}) });
|
|
842
|
-
return models;
|
|
846
|
+
return [{ provider, id: 'gateway', name: 'TheOne', inputModalities: [...(info?.inputModalities ?? ['text'])] }];
|
|
843
847
|
}
|
|
844
848
|
/** The entry has exactly the backing model's capacity, including DSH overrides. */
|
|
845
849
|
async gatewayModelInfo(provider = 'theone', signal, model = 'gateway') {
|