dsh-neotui 0.1.22 → 0.1.23
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/package.json +1 -1
- package/src/panels.js +25 -17
package/package.json
CHANGED
package/src/panels.js
CHANGED
|
@@ -112,7 +112,7 @@ export class Picker extends Widget {
|
|
|
112
112
|
export function buildModelPicker(app) {
|
|
113
113
|
const w = Math.min(70, app.screen.w - 4), h = Math.min(24, app.screen.h - 4);
|
|
114
114
|
const manageProviders = {
|
|
115
|
-
label: "⚙
|
|
115
|
+
label: "⚙ 管理供应商…", hint: "M",
|
|
116
116
|
provider: null, model: null,
|
|
117
117
|
action: () => { app.overlay = null; app.setMode("models"); },
|
|
118
118
|
};
|
|
@@ -1640,9 +1640,9 @@ export class SettingsPanel extends Widget {
|
|
|
1640
1640
|
ns: "默认展开/折叠", applies: "live", local: true,
|
|
1641
1641
|
value: { 思考块默认展开: fd.think, 工具块默认展开: fd.bash, 任务清单默认显示: fd.todos },
|
|
1642
1642
|
});
|
|
1643
|
-
// the model provider manager opens its own
|
|
1643
|
+
// the model provider manager opens its own simple form buffer
|
|
1644
1644
|
this.namespaces.splice(2, 0, {
|
|
1645
|
-
ns: "
|
|
1645
|
+
ns: "模型供应商…", applies: "live", local: true, modelsEntry: true,
|
|
1646
1646
|
value: {},
|
|
1647
1647
|
});
|
|
1648
1648
|
this.selectNs(0);
|
|
@@ -1816,9 +1816,7 @@ export class SettingsPanel extends Widget {
|
|
|
1816
1816
|
}
|
|
1817
1817
|
}
|
|
1818
1818
|
|
|
1819
|
-
// ---- Model provider management (
|
|
1820
|
-
|
|
1821
|
-
const MODEL_APIS = ["openai-completions", "anthropic-messages", "google-genai"];
|
|
1819
|
+
// ---- Model provider management (simple form buffer) ----
|
|
1822
1820
|
|
|
1823
1821
|
export class ModelPanel extends Widget {
|
|
1824
1822
|
constructor(app) {
|
|
@@ -1833,6 +1831,7 @@ export class ModelPanel extends Widget {
|
|
|
1833
1831
|
this.formIdx = 0; // form item cursor
|
|
1834
1832
|
this.formItems = []; // {kind:"field"|"model"|"button", ...}
|
|
1835
1833
|
this.modelsSel = -1; // selected model row (shows its subfields)
|
|
1834
|
+
this.draftRoute = null; // the un-saved new provider's route (shows the rename field)
|
|
1836
1835
|
this.editing = null; // { label, commit } while the inline editor is open
|
|
1837
1836
|
this.scanMode = false;
|
|
1838
1837
|
this.scanItems = [];
|
|
@@ -1871,9 +1870,9 @@ export class ModelPanel extends Widget {
|
|
|
1871
1870
|
if (route == null) return [];
|
|
1872
1871
|
const p = this.#profile(route);
|
|
1873
1872
|
const items = [];
|
|
1874
|
-
|
|
1873
|
+
// the route key only appears for a brand-new draft (rename once)
|
|
1874
|
+
if (this.draftRoute === route) items.push({ kind: "field", key: "route", label: "路由名", value: route });
|
|
1875
1875
|
items.push({ kind: "field", key: "displayName", label: "显示名", value: p.displayName ?? "" });
|
|
1876
|
-
items.push({ kind: "field", key: "api", label: "协议 api", value: p.api ?? "openai-completions", cycle: MODEL_APIS });
|
|
1877
1876
|
items.push({ kind: "field", key: "baseURL", label: "baseURL", value: p.baseURL ?? "" });
|
|
1878
1877
|
items.push({ kind: "field", key: "apiKeyEnv", label: "apiKeyEnv", value: p.apiKeyEnv ?? "", note: "环境变量名(密钥不落盘)" });
|
|
1879
1878
|
const models = p.models ?? [];
|
|
@@ -1896,22 +1895,28 @@ export class ModelPanel extends Widget {
|
|
|
1896
1895
|
return items;
|
|
1897
1896
|
}
|
|
1898
1897
|
#rebuild() {
|
|
1899
|
-
// left list
|
|
1898
|
+
// left list: the cursor is ALWAYS visible (● on the selected provider),
|
|
1899
|
+
// and the row being edited shows ✎ — the mode only changes the color.
|
|
1900
1900
|
const listLines = [];
|
|
1901
1901
|
for (let i = 0; i < this.routes.length; i++) {
|
|
1902
1902
|
const r = this.routes[i];
|
|
1903
1903
|
const p = this.providers[r] ?? {};
|
|
1904
|
-
const
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1904
|
+
const cur = i === this.sel;
|
|
1905
|
+
const editing = cur && this.mode === "form";
|
|
1906
|
+
listLines.push([{
|
|
1907
|
+
t: ` ${cur ? "●" : " "} ${truncate(p.displayName || r, 18)}${editing ? " ✎" : ""}`,
|
|
1908
|
+
fg: cur ? T.SELFG : T.TXT, bg: cur ? (editing ? T.MENUSEL : T.SELBG) : T.BG2, bold: cur,
|
|
1909
|
+
}]);
|
|
1910
|
+
}
|
|
1911
|
+
const addCur = this.sel === this.routes.length;
|
|
1912
|
+
listLines.push([{ t: ` ${addCur ? "●" : " "} + 添加供应商`, fg: addCur ? T.SELFG : T.ACCENT, bg: addCur ? T.MENUSEL : T.BG2, bold: true }]);
|
|
1909
1913
|
this.listView.setLines(listLines);
|
|
1910
1914
|
// right form
|
|
1911
1915
|
const route = this.#route();
|
|
1912
1916
|
const formLines = [];
|
|
1913
1917
|
if (route == null) {
|
|
1914
|
-
formLines.push([{ t: "
|
|
1918
|
+
formLines.push([{ t: " 左侧 ↑/↓ 选择供应商,Enter 打开编辑", fg: K.FAINT }]);
|
|
1919
|
+
formLines.push([{ t: " 把光标移到底部的“+ 添加供应商”回车即可新建", fg: K.FAINT }]);
|
|
1915
1920
|
this.formItems = [];
|
|
1916
1921
|
} else if (this.scanMode) {
|
|
1917
1922
|
formLines.push([{ t: ` 扫描 ${truncate(this.#profile(route).baseURL ?? "", 44)} — 空格勾选,Enter 添加,↑/↓ 移动`, fg: K.ACCENT, bold: true }]);
|
|
@@ -1942,7 +1947,7 @@ export class ModelPanel extends Widget {
|
|
|
1942
1947
|
}
|
|
1943
1948
|
formLines.push([{ t: truncate(t, w), fg: cur ? T.SELFG : T.TXT, bg: cur ? T.MENUSEL : T.BG2 }]);
|
|
1944
1949
|
}
|
|
1945
|
-
formLines.push([{ t: " Enter
|
|
1950
|
+
formLines.push([{ t: " ↑/↓ 移动 · Enter 编辑或执行 · ← 回列表 · Esc 退出", fg: K.FAINT }]);
|
|
1946
1951
|
}
|
|
1947
1952
|
this.formView.setLines(formLines);
|
|
1948
1953
|
}
|
|
@@ -1978,6 +1983,7 @@ export class ModelPanel extends Widget {
|
|
|
1978
1983
|
let name = "新供应商", i = 2;
|
|
1979
1984
|
while (this.providers[name] !== undefined) name = `新供应商${i++}`;
|
|
1980
1985
|
this.providers[name] = { displayName: "", api: "openai-completions", baseURL: "", apiKeyEnv: "", models: [] };
|
|
1986
|
+
this.draftRoute = name;
|
|
1981
1987
|
this.routes = Object.keys(this.providers);
|
|
1982
1988
|
this.sel = this.routes.indexOf(name);
|
|
1983
1989
|
this.mode = "form";
|
|
@@ -2083,6 +2089,7 @@ export class ModelPanel extends Widget {
|
|
|
2083
2089
|
expectedRevision: this.revision,
|
|
2084
2090
|
});
|
|
2085
2091
|
this.revision = res?.revision ?? this.revision;
|
|
2092
|
+
this.draftRoute = null;
|
|
2086
2093
|
this.app.toast(`已保存 ${Object.keys(this.providers).length} 个供应商`);
|
|
2087
2094
|
} catch (e) { this.app.toast(`保存失败: ${e.message}`); }
|
|
2088
2095
|
}
|
|
@@ -2215,7 +2222,8 @@ export class ModelPanel extends Widget {
|
|
|
2215
2222
|
if (this.editing && this.input.inside(ev.x, ev.y)) return this.input.onMouse(ev);
|
|
2216
2223
|
if (ev.x < this.x + 26) {
|
|
2217
2224
|
const idx = ev.y - this.listView.y + this.listView.scrollY;
|
|
2218
|
-
|
|
2225
|
+
// one click = select AND open (same as Enter)
|
|
2226
|
+
if (idx >= 0 && idx <= this.routes.length) { this.sel = idx; this.#activateItem(); return true; }
|
|
2219
2227
|
return false;
|
|
2220
2228
|
}
|
|
2221
2229
|
if (this.scanMode) {
|