ework-web 0.10.15 → 0.10.16

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ework-web",
3
- "version": "0.10.15",
3
+ "version": "0.10.16",
4
4
  "type": "module",
5
5
  "description": "ework-web — standalone multi-project issue tracker. Local SQLite-backed, no external API dependency. Bun + TypeScript + SSR HTML.",
6
6
  "license": "MIT",
package/src/config.ts CHANGED
@@ -107,7 +107,7 @@ export const SETTINGS_GROUPS: SettingGroup[] = [
107
107
  {
108
108
  title: "AI 模型",
109
109
  fields: [
110
- { key: "defaultModel", label: "默认模型(空 = 用 opencode.json;注意环境变量可能污染,建议点下方刷新自动选一个)", type: "model" },
110
+ { key: "defaultModel", label: "默认模型(点下方「刷新 opencode 模型列表」更新)", type: "model" },
111
111
  ],
112
112
  },
113
113
  {
@@ -20,14 +20,15 @@ function fieldInput(group: SettingGroup, cfg: Config, models: CachedModel[]): st
20
20
  // If the cache is empty (opencode not yet polled), fall back to a free
21
21
  // text input so the user can still type a known provider/model id.
22
22
  if (models.length === 0) {
23
- return `<label class="sf"><span>${escapeHtml(f.label)}</span><input type="text" name="${escapeAttr(String(f.key))}" value="${escapeAttr(cur)}" placeholder="provider/model(点下面的刷新拉列表)"></label>`;
23
+ return `<label class="sf"><span>${escapeHtml(f.label)}</span><input type="text" name="${escapeAttr(String(f.key))}" value="${escapeAttr(cur)}" placeholder="provider/model(点下方刷新拉列表)"></label>`;
24
24
  }
25
- const opts = [`<option value=""${cur === "" ? " selected" : ""}>(用 opencode 默认)</option>`]
26
- .concat(
27
- models.map(
28
- (m) =>
29
- `<option value="${escapeAttr(m.id)}"${m.id === cur ? " selected" : ""}>${escapeHtml(m.label)}</option>`
30
- )
25
+ // No empty "use opencode default" option: empty default lets env
26
+ // vars pollute the model slot (see M-1 in index.ts refresh handler).
27
+ // If cur is empty, the browser auto-selects the first option.
28
+ const opts = models
29
+ .map(
30
+ (m) =>
31
+ `<option value="${escapeAttr(m.id)}"${m.id === cur ? " selected" : ""}>${escapeHtml(m.label)}</option>`
31
32
  )
32
33
  .join("");
33
34
  return `<label class="sf"><span>${escapeHtml(f.label)}</span><select name="${escapeAttr(String(f.key))}">${opts}</select></label>`;
@@ -104,7 +105,7 @@ export function buildSettingsPage(cfg: Config, saved: boolean, viewer: UserRow,
104
105
  const ttsLink = viewer.is_admin === 1
105
106
  ? `<p class="hint">要增删朗读后端(kokoro / cosyvoice3 等),去 <a href="/admin/tts-backends">朗读后端管理</a>。</p>`
106
107
  : "";
107
- const modelRefreshForm = `<form method="POST" action="/settings/models/refresh" style="margin-top:.4rem"><button type="submit" class="secondary">🔄 刷新 opencode 模型列表</button></form>`;
108
+ const modelRefreshForm = `<section class="sg"><h2>opencode 模型列表</h2><p class="hint" style="margin:0 0 .6rem">从 <code>opencode models</code> 拉取可用模型并刷新上方下拉列表。刷新后自动选定一个具体模型作为默认(不会留空)。</p><form method="POST" action="/settings/models/refresh"><button type="submit" class="secondary">🔄 刷新 opencode 模型列表</button></form></section>`;
108
109
  const html = `<!doctype html>
109
110
  <html lang="zh"><head><meta charset="utf-8">
110
111
  <meta name="viewport" content="width=device-width,initial-scale=1">
@@ -164,9 +165,9 @@ button.secondary{background:transparent;color:var(--text-muted);border:1px solid
164
165
  <p class="hint">改完保存立即生效,无需重启。密钥/启动项(token、端口等)仍在 <code>.env</code>,不在此处。</p>
165
166
  ${banner}
166
167
  <form method="POST" action="/settings">${groups}
167
- ${modelRefreshForm}
168
168
  <div class="bar"><button type="submit">保存</button><a class="a-back" href="/">返回</a></div>
169
169
  </form>
170
+ ${modelRefreshForm}
170
171
  ${ttsLink}
171
172
  ${buildDbSection(viewer)}
172
173
  ${buildDaemonSection(viewer)}