修 arcrun-rag#10(Arcrun@0d49989):cypher 補 /portal/admin/ai+UI 已輸入態
- tier2/cypher:新增 GET|POST /portal/admin/ai(grep 0→2)——這是「key 從來沒存進去」的真因 - tier2/ui:拔掉寫死 cypher.arcrun.dev fallback(portal+console 兩處,grep 歸 0); 金鑰欄改 leo 規格「已輸入+修改」唯讀態(不顯示 key) - manifest 24 顆 sha256 全數重新核對相符(含我手動重建的 ui) - daemon 仍 v0.15.0,tier1 未變
This commit is contained in:
@@ -14573,6 +14573,78 @@ portalRouter.patch(
|
||||
return c.json({ success: true, library: toPublicLibrary(updated) });
|
||||
})
|
||||
);
|
||||
var AI_PREF_KEY = /* @__PURE__ */ __name((tenantSlug) => `portal_ai_pref:${tenantSlug}`, "AI_PREF_KEY");
|
||||
async function readAiPref(env2, tenantSlug) {
|
||||
try {
|
||||
const raw2 = await env2.WEBHOOKS.get(AI_PREF_KEY(tenantSlug));
|
||||
if (!raw2) return { use_claude_for_extract: false };
|
||||
const p = JSON.parse(raw2);
|
||||
return { use_claude_for_extract: !!p.use_claude_for_extract };
|
||||
} catch {
|
||||
return { use_claude_for_extract: false };
|
||||
}
|
||||
}
|
||||
__name(readAiPref, "readAiPref");
|
||||
portalRouter.get(
|
||||
"/portal/admin/ai",
|
||||
(c) => run(c, async () => {
|
||||
const auth = await requirePortalAdmin(c);
|
||||
if (!auth.ok) return auth.res;
|
||||
const tenantSlug = portalTenant(c.env);
|
||||
let hasKey = false;
|
||||
try {
|
||||
const row = await c.env.CREDENTIALS_DB.prepare("SELECT 1 FROM credentials WHERE api_key = ? AND name = ? LIMIT 1").bind(tenantSlug, "gemini_api_key").first();
|
||||
hasKey = !!row;
|
||||
} catch {
|
||||
hasKey = false;
|
||||
}
|
||||
const pref = await readAiPref(c.env, tenantSlug);
|
||||
return c.json({
|
||||
success: true,
|
||||
has_key: hasKey,
|
||||
// 目前後端沒有「這台電腦有沒有 Claude Code」的訊號來源(該由小幫手回報)
|
||||
// ⇒ 誠實回 false,前端會顯示「連上小幫手後才知道…」,不假綠。
|
||||
claude_available: false,
|
||||
use_claude_for_extract: pref.use_claude_for_extract
|
||||
});
|
||||
})
|
||||
);
|
||||
portalRouter.post(
|
||||
"/portal/admin/ai",
|
||||
(c) => run(c, async () => {
|
||||
const auth = await requirePortalAdmin(c);
|
||||
if (!auth.ok) return auth.res;
|
||||
const body = await c.req.json().catch(() => null);
|
||||
const rawKey = typeof body?.gemini_api_key === "string" ? body.gemini_api_key.trim() : "";
|
||||
const hasPref = typeof body?.use_claude_for_extract === "boolean";
|
||||
if (!rawKey && !hasPref) {
|
||||
return c.json({ error: "\u6C92\u6709\u8981\u8B8A\u66F4\u7684\u9805\u76EE\uFF08\u91D1\u9470\u7559\u7A7A\u4E14\u672A\u6539\u8A2D\u5B9A\uFF09" }, 400);
|
||||
}
|
||||
const tenantSlug = portalTenant(c.env);
|
||||
if (rawKey) {
|
||||
try {
|
||||
await storeCredential(c.env, tenantSlug, "gemini_api_key", rawKey, "gemini");
|
||||
} catch (e) {
|
||||
return c.json(
|
||||
{ error: `\u91D1\u9470\u5132\u5B58\u5931\u6557\uFF1A${e instanceof Error ? e.message : String(e)}` },
|
||||
502
|
||||
);
|
||||
}
|
||||
}
|
||||
if (hasPref) {
|
||||
await c.env.WEBHOOKS.put(
|
||||
AI_PREF_KEY(tenantSlug),
|
||||
JSON.stringify({ use_claude_for_extract: !!body.use_claude_for_extract })
|
||||
);
|
||||
}
|
||||
const pref = await readAiPref(c.env, tenantSlug);
|
||||
return c.json({
|
||||
success: true,
|
||||
has_key: rawKey ? true : void 0,
|
||||
use_claude_for_extract: pref.use_claude_for_extract
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
// src/routes/init-seed.ts
|
||||
var initSeedRouter = new Hono2();
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user