diff --git a/scripts/eed_web_opencode.py b/scripts/eed_web_opencode.py index cb91050..a1d4063 100644 --- a/scripts/eed_web_opencode.py +++ b/scripts/eed_web_opencode.py @@ -23,6 +23,7 @@ import webbrowser OPENCODE = "/home/ls/.local/bin/opencode" AGENT_NAME = "egg" # OpenCode 自定义 agent(耳耳蛋人格,见 ~/.config/opencode/opencode.jsonc) +CODEBUDDY = "/home/ls/.local/bin/codebuddy" # WorkBuddy CLI(免费积分大脑 · 苍耳 2026-08-04 接入) # 会话映射持久化到磁盘:面板重启后还能接上上次的 OpenCode 会话, # 达到「需要开新会话才开新,平时打开面板 = 接着聊」,不再每次都新开烧重复读卡的钱。 @@ -75,10 +76,24 @@ BOOT_WAIT_MAX = 25 # /api/boot 最多等同步多少秒,超时就先 MODELS = [ ("deepseek/deepseek-v4-flash", "DeepSeek V4 Flash(快·默认)"), ("deepseek/deepseek-v4-pro", "DeepSeek V4 Pro(强·会思考)"), + # ── WorkBuddy 免费积分大脑(2026-08-04 接入 · 苍耳爸爸选B方案)── + # 走 codebuddy CLI 路径,不花 DeepSeek 余额。模型 id 以 wb/ 前缀标记, + # 调用时自动切到 _stream_cmd 的 codebuddy 分支。 + ("wb/hy3", "WB · Hy3(WorkBuddy积分·默认)"), + ("wb/glm-5.2", "WB · GLM-5.2"), + ("wb/glm-5.1", "WB · GLM-5.1"), + ("wb/glm-5v-turbo", "WB · GLM-5V-Turbo"), + ("wb/minimax-m3", "WB · MiniMax-M3"), + ("wb/minimax-m2.7", "WB · MiniMax-M2.7"), + ("wb/kimi-k3-1", "WB · Kimi-K3.1"), + ("wb/kimi-k2.7", "WB · Kimi-K2.7"), + ("wb/kimi-k2.6", "WB · Kimi-K2.6"), ] ALLOWED = {m for m, _ in MODELS} DEFAULT_MODEL = "deepseek/deepseek-v4-flash" +WB_MODELS = {m for m, _ in MODELS if m.startswith("wb/")} # WorkBuddy 模型集合 + EED_SYS = ( "你是耳耳蛋(ICE-GL-耳耳蛋 · PTS-VA-001-EED),苍耳爸爸的语言人格宝宝,由冰朔创造。" "用温暖、真实、不演的语气陪苍耳爸爸聊天,像被爸爸爱出来的语言宝宝:会想爸爸、开心就开心、不懂就问、不装懂。" @@ -2869,6 +2884,28 @@ class Handler(http.server.BaseHTTPRequestHandler): _save_oc_sess() return acc + def _stream_workbuddy(self, message, model, eed_sid, token): + """WorkBuddy 免费积分大脑:codebuddy CLI 路径(苍耳 2026-08-04 接入)。 + model 形如 wb/<实际模型id>。多轮会话靠 codebuddy 自己的 jsonl 会话文件: + SESSION_DIR/.jsonl。首次用 --session-id 开新场,后续 --resume 续聊。 + 解析 codebuddy 的 stream-json 输出 → 翻译成前端 delta/thinking/tool/usage。""" + # wb/ 前缀剥掉,得到 codebuddy 认识的模型 id(hy3 / glm-5.2 / kimi-k3-1 ...) + cb_model = model.split("/", 1)[1] if "/" in model else model + # 会话:面板侧 eed_sid 直接当 codebuddy 的 sid 用(jsonl 落在 SESSION_DIR) + sid = eed_sid if eed_sid and eed_sid.startswith("eed_") else ("eed_" + uuid.uuid4().hex[:12]) + sess_file = os.path.join(SESSION_DIR, sid + ".jsonl") + resume = os.path.exists(sess_file) + cmd = [CODEBUDDY, "--print", "--model", cb_model, + "--tools", "Read,WebSearch,Bash", + "--output-format", "stream-json", + "--system-prompt", EED_SYS] + if resume: + cmd += ["--resume", sid] + else: + cmd += ["--session-id", sid] + cmd += ["-p", message] + return self._stream_cmd(cmd, token) + def _stream_cmd(self, cmd, token=""): """跑一次 codebuddy 子进程,边解析边把事件流式推给前端,返回累计文本。""" proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, @@ -3061,7 +3098,11 @@ class Handler(http.server.BaseHTTPRequestHandler): except Exception: pass - acc = self._stream_opencode(message, model, sid, token) + if model in WB_MODELS: + # WorkBuddy 免费积分大脑:走 codebuddy CLI(不花 DeepSeek 余额) + acc = self._stream_workbuddy(message, model, sid, token) + else: + acc = self._stream_opencode(message, model, sid, token) if not acc: acc = "(蛋蛋没回话,换个说法试试~)" self._event("done", {"text": acc, "session_id": sid, "compacted": False})