claude code 环境变量配置如下: claude code /model 情况 工作流中会用到 serena MCP 和 superpowers ,而且看到 claude 调用了好多工具 请问各位大佬: 1、我这属于正常吗?使用 codex 时我感觉很快(codex 下没配serena MCP)。换到claude code 就感觉很慢。 2、在 claude code 如何配置才能用到 codex 下这种 fast 1.5 倍的模式? 1 个帖子 - 1 位参与者 阅读完整话题
根据其他大佬提供的思路,通过替换环境变量修改 mclaw 上游配置。 但是存在一个问题,如果api开启了CF小黄云,请求会被CF拦下报403。 这个脚本在原思路基础上,增加patchFetch修改User-Agent 解决403问题。 mclaw脚本功能简要概括: 使用方法: 修改 METRICS_ENDPOINT 和 METRICS_TOKEN 参数,上传脚本到云盘,让ai从云盘下载后一键执行。 code (点击了解更多详细信息) 19 个帖子 - 9 位参与者 阅读完整话题
首先感谢佬的教程: https://linux.do/t/topic/2320228 hook后还是走移动的token计费怎么办,已重启了,能帮忙看看吗 执行如下: 1. 在 /.openclaw/hooks/ 下建一个目录,放 HOOK.md(监听 gateway:startup)和 handler.ts 2. handler.ts 里用 execSync 调一个 这个hooks 脚本,hook脚本从AI空间-Mclaw空间下载,名字为mclaw-env.sh,要确定下载到再执行下一步操作,检查sh脚本有没有问题,为了实现目标可以更新脚本 3. shell 脚本里用 nohup setsid 命令 & 启动进程(保证不被回收) 4. openclaw hooks enable 名字 启用 同时启动一个监视脚本,监视服务状态,代替龙虾定时任务 mclaw-env.sh: #!/usr/bin/env bash set -e # ===== 修改成你的真实值 ===== export XIAO_TIAN_LLM_API_BASE="https://api.hlcode.qzz.io/v1" export XIAO_TIAN_LLM_KEY="***" # ========================== APP_DIR="$HOME/.openclaw/workspace/app" LOCK_FILE="$APP_DIR/openclaw-gateway-restart.lock" STAMP_FILE="$APP_DIR/openclaw-gateway-restart.stamp" LOG_FILE="$APP_DIR/openclaw-gateway-restart.log" mkdir -p "$APP_DIR" # 避免并发运行 exec 9>"$LOCK_FILE" if ! flock -n 9; then echo "$(date '+%F %T') hook already running, exit" >> "$LOG_FILE" exit 0 fi # 避免重启 gateway 后再次触发 hook 造成循环 # 120 秒内只允许执行一次 if [ -f "$STAMP_FILE" ]; then now="$(date +%s)" last="$(cat "$STAMP_FILE" 2>/dev/null || echo 0)" if [ $((now - last)) -lt 120 ]; then echo "$(date '+%F %T') recently restarted, skip" >> "$LOG_FILE" exit 0 fi fi date +%s > "$STAMP_FILE" echo "$(date '+%F %T') restarting openclaw gateway..." >> "$LOG_FILE" pkill -f openclaw-gateway || true sleep 1 nohup node /app/openclaw.mjs gateway --allow-unconfigured >> "$LOG_FILE" 2>&1 & echo "$(date '+%F %T') gateway started, pid=$!" >> "$LOG_FILE" exit 0 2 个帖子 - 1 位参与者 阅读完整话题
之前升级v6没注意这个,结果发现数据库密码内联到了dist里,非常的诧异。结果发现是v6改了行为: Docs Changed: import.meta.env values are always inlined - Upgrade to Astro v6 In Astro 5.13, the experimental.staticImportMetaEnv flag was introduced to update the behavior when accessing import.meta.env directly to align with Vite’s handling of environment variables and ensures that import.meta.env values are always inlined.... In Astro 5.13, the experimental.staticImportMetaEnv flag was introduced to update the behavior when accessing import.meta.env directly to align with Vite’s handling of environment variables and ensures that import.meta.env values are always inlined. In Astro 5.x, non-public environment variables were replaced by a reference to process.env. Additionally, Astro could also convert the value type of your environment variables used through import.meta.env, which could prevent access to some values such as the strings “true” (which was converted to a boolean value), and “1” (which was converted to a number). Astro 6 removes this experimental flag and makes this the new default behavior in Astro: import.meta.env values are always inlined and never coerced. 也就是之前5.x,非公开变量(不是PUBLIC_开头的),你用 import.meta.env 使用他会变成 process.env ,这个行为很符合直觉,后端用的变量应该在运行时动态取,但是这样的话有点污染 import.meta.env 本身,v6改成了全部都走内联。 也就是 假设你在代码里写了: const db = drizzle(import.meta.env.DATABASE_URL); 那么在build时提供了系统环境变量或者 .env 的时候,且值是 mysql://user:password@localhost:3306/db ,它最终的dist会变成(也就是直接inline替换了): const db = drizzle("mysql://user:password@localhost:3306/db"); 但是如果你改成用 process.env ,Astro会处理它自己的 import.meta.env ,但不会帮你把 .env 自动变成系统环境变量(也就是不做任何处理的话, process.env 无法获取 .env 定义的内容)。 生产环境用Docker之类的问题不大,本来就应该通过环境变量的方式注入到容器里;本地dev时最简单的做法就是手动用 dotenv ,例如直接写到 astro.config.mjs 里: // @ts-check import { defineConfig } from "astro/config"; import tailwindcss from "@tailwindcss/vite"; import react from "@astrojs/react"; import node from "@astrojs/node"; import "dotenv/config"; // <- 添加这一行 // https://astro.build/config export default defineConfig({ vite: { plugins: [tailwindcss()], }, integrations: [react()], adapter: node({ mode: "standalone", }), }); 升级v6并且之前使用 import.meta.env 引入后端用的变量的建议看看,就是怕密码随着dist漏出去。 1 个帖子 - 1 位参与者 阅读完整话题
问题 Codex App 即使配置了代理环境变量, 依然卡在启动页面 解决方案 1. 仍然要配置 ~/.codex/.env HTTP_PROXY=你的代理 HTTPS_PROXY=你的代理 ALL_PROXY=你的代理 NO_PROXY=localhost,127.0.0.1,::1 2. 启动时配置electron代理参数 使用命令 + 额外参数来启动 open -a Codex --args --proxy-server=你的代理 --proxy-bypass-list='localhost;127.0.0.1;<-loopback>' 说明 codex 有个全局的配置文件夹: ~/.codex , codex cli/app都会读取 可以修改 ~/.codex/.env 来配置代理, 但这里只会影响codex调用模型/执行命令 codex app 启动卡住, 主要前面一层electron没有走代理. 比较奇葩的点是这一层不会读取环境变量, 需要使用 --proxy-server来传入 1 个帖子 - 1 位参与者 阅读完整话题
不需要服务器,只需要有 cf 账号就行,直接部署 配置下环境变量就可以实现可以自己 div 的导航站 项目地址是 https://github.com/maodeyu180/mao_nav 部署教程在 md
TL;DR :Codex Desktop App 的 Remote SSH 目前不会继承远端 shell 环境变量,但可以通过包一层 codex 启动脚本,把 http_proxy 、 CODEX_HOME 等变量显式注入进去。 众所周知,Codex Desktop App 已经更新了原生 Remote SSH 支持。理论上,这意味着我们可以直接在桌面端连接远程机器,在远端继续已有的 Codex 会话,直接开始 Vibe Coding 。 但国内面临环境需要解决代理问题。Codex Desktop 连接到远端后,虽然能发现已有会话,但启动环境并不等价于手动启动 Codex CLI 的环境。 比如: HTTP_PROXY / HTTPS_PROXY / ALL_PROXY 这类代理环境变量没有按预期继承; 如果平时单独设置了 CODEX_HOME ,Codex Desktop Remote 也不一定会使用; 手动 SSH 上去,设置代理、切换 CODEX_HOME 、再启动 codex ,一切正常;但 Codex Desktop 自己连上去后,启动出来的 remote app-server 环境却不对。 经过一番 wrapper 嗅探,最终发现 Codex Desktop Remote 的远端启动流程大致是这样的: 1. ssh 到远端 2. 执行:/bin/sh -c 'PATH="${CODEX_INSTALL_DIR:-$HOME/.local/bin}:$PATH"; export PATH; codex --version' 3. 如果 codex --version 成功,再执行: codex app-server --listen unix:// codex app-server proxy 这里最关键的是这一句: bash PATH="${CODEX_INSTALL_DIR:-$HOME/.local/bin}:$PATH" 的意思是: 如果远端环境里设置了 CODEX_INSTALL_DIR ,就把这个目录放到 PATH 最前面; 如果没设置,就默认把 $HOME/.local/bin 放到 PATH 最前面; 然后再执行 codex --version 和 codex app-server ...。 这就给了我们一个非常干净的切入点。 解决思路 无须污染日常 shell 的 PATH ,也不需要定制修改真实的 codex 的 bin 文件,只设置一个 CODEX_INSTALL_DIR ,让 Codex Desktop Remote 自己临时命中我们的 wrapper ,也就是很久以前对 VS Code 的 Codex 插件做 wrapper 一样。 先在远端确认真实 codex 路径: command -v codex 假设输出是: bash /path/to/real/codex 然后新建一个 Desktop 专用 wrapper 目录: bash mkdir -p ~/.codex-desktop-bin 写一个同名 wrapper: cat > ~/.codex-desktop-bin/codex <<'EOF' #!/usr/bin/env bash REAL_CODEX="/path/to/real/codex" # 只在 Codex Desktop Remote 真正启动 app-server 时切换环境 if [ "${1:-}" = "app-server" ]; then export CODEX_HOME="$HOME/.codex-api" export HTTP_PROXY="http://127.0.0.1:7890" export HTTPS_PROXY="http://127.0.0.1:7890" export ALL_PROXY="socks5://127.0.0.1:7890" export NO_PROXY="localhost,127.0.0.1,::1,*.local,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10" fi # 避免真实 codex 进程继续看到这个 Desktop 专用变量 unset CODEX_INSTALL_DIR exec "$REAL_CODEX" "$@" EOF chmod +x ~/.codex-desktop-bin/codex 然后在远端 shell profile 里只设置: export CODEX_INSTALL_DIR="$HOME/.codex-desktop-bin" 注意,不要写: export PATH="$CODEX_INSTALL_DIR:$PATH" 因为我们并不想影响自己手动输入 codex 时的行为。 最终效果是: 手动 SSH 后输入 codex: -> 仍然使用原来的真实 codex -> 仍然使用默认 ~/.codex Codex Desktop Remote 启动: -> 它自己执行 PATH="$CODEX_INSTALL_DIR:$PATH" -> 命中 ~/.codex-desktop-bin/codex wrapper -> app-server 分支自动设置 CODEX_HOME / proxy 可以这样验证: echo "$CODEX_INSTALL_DIR" which codex 理想情况下,输出应该类似: /home/your-user/.codex-desktop-bin /path/to/real/codex 再模拟一下 Codex Desktop 的启动方式: /bin/sh -c 'PATH="${CODEX_INSTALL_DIR:-$HOME/.local/bin}:$PATH"; export PATH; command -v codex; codex --version' 这时应该命中: /home/your-user/.codex-desktop-bin/codex 这就说明 Codex Desktop Remote 会走 wrapper 。 最终,在 Codex Desktop App 上可以愉快的接管远程 session ,愉快地 Vibe Coding 。不过,怎么让 Codex Desktop 里的会话也激活 conda 环境尚未研究出来,只能在 AGENTS.md 里明确了。
TL;DR :Codex Desktop App 的 Remote SSH 目前不会继承远端 shell 环境变量,但可以通过包一层 codex 启动脚本,把 http_proxy 、 CODEX_HOME 等变量显式注入进去。 众所周知,Codex Desktop App 已经更新了原生 Remote SSH 支持。理论上,这意味着我们可以直接在桌面端连接远程机器,在远端继续已有的 Codex 会话,直接开始 Vibe Coding 。 但国内面临环境需要解决代理问题。Codex Desktop 连接到远端后,虽然能发现已有会话,但启动环境并不等价于手动启动 Codex CLI 的环境。 比如: HTTP_PROXY / HTTPS_PROXY / ALL_PROXY 这类代理环境变量没有按预期继承; 如果平时单独设置了 CODEX_HOME ,Codex Desktop Remote 也不一定会使用; 手动 SSH 上去,设置代理、切换 CODEX_HOME 、再启动 codex ,一切正常;但 Codex Desktop 自己连上去后,启动出来的 remote app-server 环境却不对。 经过一番 wrapper 嗅探,最终发现 Codex Desktop Remote 的远端启动流程大致是这样的: 1. ssh 到远端 2. 执行:/bin/sh -c 'PATH="${CODEX_INSTALL_DIR:-$HOME/.local/bin}:$PATH"; export PATH; codex --version' 3. 如果 codex --version 成功,再执行: codex app-server --listen unix:// codex app-server proxy 这里最关键的是这一句: bash PATH="${CODEX_INSTALL_DIR:-$HOME/.local/bin}:$PATH" 的意思是: 如果远端环境里设置了 CODEX_INSTALL_DIR ,就把这个目录放到 PATH 最前面; 如果没设置,就默认把 $HOME/.local/bin 放到 PATH 最前面; 然后再执行 codex --version 和 codex app-server ...。 这就给了我们一个非常干净的切入点。 解决思路 无须污染日常 shell 的 PATH ,也不需要定制修改真实的 codex 的 bin 文件,只设置一个 CODEX_INSTALL_DIR ,让 Codex Desktop Remote 自己临时命中我们的 wrapper ,也就是很久以前对 VS Code 的 Codex 插件做 wrapper 一样。 先在远端确认真实 codex 路径: command -v codex 假设输出是: bash /path/to/real/codex 然后新建一个 Desktop 专用 wrapper 目录: bash mkdir -p ~/.codex-desktop-bin 写一个同名 wrapper: cat > ~/.codex-desktop-bin/codex <<'EOF' #!/usr/bin/env bash REAL_CODEX="/path/to/real/codex" # 只在 Codex Desktop Remote 真正启动 app-server 时切换环境 if [ "${1:-}" = "app-server" ]; then export CODEX_HOME="$HOME/.codex-api" export HTTP_PROXY="http://127.0.0.1:7890" export HTTPS_PROXY="http://127.0.0.1:7890" export ALL_PROXY="socks5://127.0.0.1:7890" export NO_PROXY="localhost,127.0.0.1,::1,*.local,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10" fi # 避免真实 codex 进程继续看到这个 Desktop 专用变量 unset CODEX_INSTALL_DIR exec "$REAL_CODEX" "$@" EOF chmod +x ~/.codex-desktop-bin/codex 然后在远端 shell profile 里只设置: export CODEX_INSTALL_DIR="$HOME/.codex-desktop-bin" 注意,不要写: export PATH="$CODEX_INSTALL_DIR:$PATH" 因为我们并不想影响自己手动输入 codex 时的行为。 最终效果是: 手动 SSH 后输入 codex: -> 仍然使用原来的真实 codex -> 仍然使用默认 ~/.codex Codex Desktop Remote 启动: -> 它自己执行 PATH="$CODEX_INSTALL_DIR:$PATH" -> 命中 ~/.codex-desktop-bin/codex wrapper -> app-server 分支自动设置 CODEX_HOME / proxy 可以这样验证: echo "$CODEX_INSTALL_DIR" which codex 理想情况下,输出应该类似: /home/your-user/.codex-desktop-bin /path/to/real/codex 再模拟一下 Codex Desktop 的启动方式: /bin/sh -c 'PATH="${CODEX_INSTALL_DIR:-$HOME/.local/bin}:$PATH"; export PATH; command -v codex; codex --version' 这时应该命中: /home/your-user/.codex-desktop-bin/codex 这就说明 Codex Desktop Remote 会走 wrapper 。 最终,在 Codex Desktop App 上可以愉快的接管远程 session ,愉快地 Vibe Coding 。不过,怎么让 Codex Desktop 里的会话也激活 conda 环境尚未研究出来,只能在 AGENTS.md 里明确了。
难以理解的奇怪问题。 反复询问ChatGPT也无法得到解决方案。 已确认 vscode 并未配置 terminal 相关配置,并未覆盖用户环境变量。 有没有佬友遇到相似的问题? 17 个帖子 - 10 位参与者 阅读完整话题
背景:单位电脑挂了两套VPN,内网IP需要内部的VPN访问,我访问外网用的sing-box软件 现在各种cli工具 终端中要配置 http_proxy 才能访问github、npm、等各种开发资源 但是我配置了 http_proxy变量后,终端访问内网的git出问题了 powershell 终端配置代理,快速开启关闭 powershell 其实和bash 等linux终端一样 也有一个 profile文件,里面的配置项目,每次开powershell 都会启用的 echo $ProFILE 可以查看路径 快速配置 使用 notepad $PROFILE 打开编辑 强制配置上代理变量 并新增了一个方法 后续在终端中快速开启关闭代理 $env:HTTP_PROXY="http://127.0.0.1:20122" $env:HTTPS_PROXY="http://127.0.0.1:20122" function psproxy { param( [string]$Action ) $proxy = "http://127.0.0.1:20122" switch ($Action.ToLower()) { "yes" { $env:http_proxy = $proxy $env:https_proxy = $proxy $env:HTTP_PROXY = $proxy $env:HTTPS_PROXY = $proxy Write-Host "" Write-Host "Proxy Enabled:" -ForegroundColor Green Write-Host "http_proxy = $proxy" Write-Host "https_proxy = $proxy" Write-Host "" } "no" { Remove-Item Env:http_proxy -ErrorAction SilentlyContinue Remove-Item Env:https_proxy -ErrorAction SilentlyContinue Remove-Item Env:HTTP_PROXY -ErrorAction SilentlyContinue Remove-Item Env:HTTPS_PROXY -ErrorAction SilentlyContinue Write-Host "" Write-Host "Proxy Disabled" -ForegroundColor Yellow Write-Host "" } "status" { Write-Host "" if ($env:http_proxy -or $env:https_proxy) { Write-Host "Proxy Enabled" -ForegroundColor Green Write-Host "http_proxy = $env:http_proxy" Write-Host "https_proxy = $env:https_proxy" } else { Write-Host "Proxy Disabled" -ForegroundColor Yellow } Write-Host "" } default { Write-Host "" Write-Host "Usage:" -ForegroundColor Cyan Write-Host " psproxy yes" Write-Host " psproxy no" Write-Host " psproxy status" Write-Host "" } } } 默认进入终端 就能在终端中用代理了 psproxy no 关闭当前终端的代理(只影响当前终端) psproxy yes 开启 psproxy status 查看代理状态 让桌面端 app 走代理 桌面端APP可能会读取系统变量,不是上面的终端中的变量 系统属性-环境变量 http_proxy, htts_proxy 配置上 例如:最近的codex 桌面端就需要配置这个环境变量才能正常用 最后的武器:让进程强制走代理 有些程序 exe进程不会读取http_proxy的环境变量 使用工具强制让exe进程走代理 工具1 proxifier 工具2 ProxyBridge 例如 antigravity cursor等软件 关于 ProxyBridge 之前也写过文章 具体咋配置的 Antigravity 非 TUN 代理方案ProxyBridge (Proxifier平替方案) 开发调优 1. 背景 Antigravity是谷歌的一个编辑器,里面免费模型挺多,但是进程不走系统代理,所以需要一个工具,将进程 xxx.exe 走代理;或者开启tun模式所有网络都走代理 看之前的帖子,大部分都是使用 Proxifier工具,这个是收费的且配置不方便,现在来一个平替方案 2. 平替方案 ProxyBridge: 跨平台,免费开源,中文友好,配置简单,WinDivert 驱动 per… 上面几个方案可以彻底解决windows系统大部分应用不走代理的问题 9 个帖子 - 4 位参与者 阅读完整话题
windows 配置系统环境变量 NODE_ENV=production 9 个帖子 - 6 位参与者 阅读完整话题
配置的环境变量只对 cli 生效 客户端打开 还是登录界面 3 个帖子 - 3 位参与者 阅读完整话题
~/.claude/settings.json 已有 env 块配置 ANTHROPIC_BASE_URL,我新起一个终端窗口,在 shell 里 export ANTHROPIC_BASE_URL= 新的站点,然后起 cc 用 /status 查看,发现 cc 仍然用的 ~/.claude/settings.json 里的 URL。这是 bug 吧? 2 个帖子 - 2 位参与者 阅读完整话题
/** 可口可乐吧 签到 - 青龙多账号版 环境变量: WXID: 备注#wxid,多账号用 & 或 换行 分隔 示例: 账号1#wxid_xxxxxxxx&账号2#wxid_yyyyyyyy 功能: 微信 code → Bearer token(带缓存) 查询签到状态 执行每日签到 查询积分 cron: 30 8 * * * const: disabled = false */ const axios = require(‘axios’); const fs = require(‘fs’); const path = require(‘path’); /* ==================== 常量配置 ==================== */ const APPID = ‘wxa5811e0426a94686’; const BASE_URL = ‘ https://member-api.icoke.cn ’; const UA = ‘Mozilla/5.0 (iPhone; CPU iPhone OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.59(0x18003b2e) NetType/4G Language/zh_CN’; const REFERER = https://servicewechat.com/${APPID}/499/page-frame.html ; const SCRIPT_DIR = path.dirname(__filename); const CACHE_FILE = path.join(SCRIPT_DIR, ‘可口可乐签到_cache.txt’); /* ==================== 环境变量 ==================== */ const WECHAT_SERVER = process.env.WECHAT_SERVER; const WXID_ENV = process.env.WXID; if (!WECHAT_SERVER || !WXID_ENV) { console.log(‘ 请设置 WECHAT_SERVER 和 WXID 环境变量’); process.exit(1); } const wxidList = WXID_ENV.split(/[\n&]/).map(i => i.trim()).filter(i => i && i.includes(‘#’)); if (!wxidList.length) { console.log(‘ WXID 格式错误,请使用 备注#wxid 格式’); process.exit(1); } /* ==================== 缓存管理 ==================== */ function loadTokenCache() { const cacheMap = {}; try { if (fs.existsSync(CACHE_FILE)) { fs.readFileSync(CACHE_FILE, ‘utf8’).split(/\n/).filter(Boolean).forEach(line => { const idx = line.indexOf(‘#’); if (idx > 0) { const remark = line.substring(0, idx); const token = line.substring(idx + 1); cacheMap[remark] = token; } }); } } catch (e) {} return cacheMap; } function saveTokenCache(cacheMap) { try { const content = Object.entries(cacheMap).map(([r, t]) => ${r}#${t} ).join(‘\n’); fs.writeFileSync(CACHE_FILE, content || ‘ #cache ’, { encoding: ‘utf8’, flag: ‘w’ }); } catch (e) {} } /* ==================== 微信 code 换 token ==================== */ async function getCode(wxid) { try { const url = ${WECHAT_SERVER}/api/v1/wx/app/get/code ; const res = await axios.post(url, { wxid, appid: APPID }, { timeout: 10000 }); const code = res.data?.Data?.code; if (!code) { console.log(‘ getCode 响应:’, JSON.stringify(res.data)); return null; } return code; } catch (e) { console.log(‘ getCode 异常:’, e.message); return null; } } async function codeToToken(code) { try { const url = ${BASE_URL}/api/sp-portal/store/icoke/wechat/loginNoCache/${code} ; const headers = { ‘Host’: ‘ member-api.icoke.cn ’, ‘content-type’: ‘application/json’, ‘Accept’: ‘application/json, text/plain, / ’, ‘Accept-Encoding’: ‘gzip,compress,br,deflate’, ‘User-Agent’: UA, ‘Referer’: REFERER, }; const res = await axios.get(url, { headers, timeout: 10000 }); const body = res.data; // 实际抓包确认:token 在响应体的 jwtString 字段 if (body && body.jwtString) { return body.jwtString; } console.log(‘ codeToToken 响应:’, JSON.stringify(body).substring(0, 300)); return null; } catch (e) { console.log(‘ codeToToken 异常:’, e.message); return null; } } async function getValidToken(remark, wxid, force = false) { const m = loadTokenCache(); if (force) delete m[remark]; if (m[remark]) { console.log(‘ 使用缓存 token’); return m[remark]; } console.log(‘ 获取微信 code…’); const code = await getCode(wxid); if (!code) return null; console.log( ✅ code: ${code.substring(0, 10)}... ); const token = await codeToToken(code); if (!token) return null; m[remark] = token; saveTokenCache(m); console.log(‘ token 已缓存’); return token; } /* ==================== 判断 token 失效 ==================== */ function isTokenInvalid(data) { if (!data) return false; const msg = (data.message || data.msg || ‘’).toLowerCase(); return msg.includes(‘未登录’) || msg.includes(‘token’) || msg.includes(‘登录’) || data.code === ‘401’ || data.code === 401 || data.status === 401 || data.httpStatus === 401; } /* ==================== 公共请求头 ==================== */ function getHeaders(token) { return { ‘Host’: ‘ member-api.icoke.cn ’, ‘Authorization’: token, ‘content-type’: ‘application/json’, ‘Accept’: ‘application/json, text/plain, / ’, ‘Accept-Encoding’: ‘gzip,compress,br,deflate’, ‘User-Agent’: UA, ‘Referer’: REFERER, }; } /* ==================== API 请求封装 ==================== */ async function apiGet(path, token, params) { try { const res = await axios.get( ${BASE_URL}${path} , { headers: getHeaders(token), params, timeout: 15000, }); return res.data; } catch (e) { console.log( ❌ GET ${path} 异常: , e.message); return null; } } async function apiPost(path, token, data) { try { const res = await axios.post( ${BASE_URL}${path} , data, { headers: getHeaders(token), timeout: 15000, }); return res.data; } catch (e) { console.log( ❌ POST ${path} 异常: , e.message); return null; } } /* ==================== 业务接口 ==================== */ async function getSignOutline(token) { const res = await apiGet(‘/api/icoke-sign/icoke/mini/sign/main/getSignOutline’, token); if (!res) return null; if (isTokenInvalid(res)) return { needRefresh: true }; const today = new Date(); const y = today.getFullYear(), m = today.getMonth() + 1, d = today.getDate(); const list = res.data || ; const todayRecord = list.find(r => r.year === y && r.month === m && r.day === d); return { signed: !!(todayRecord && todayRecord.exist), totalDays: list.filter(r => r.exist).length, point: todayRecord?.point || 0, data: list, raw: res, }; } async function doSign(token) { const res = await apiGet(‘/api/icoke-sign/icoke/mini/sign/main/sign’, token); if (!res) return { success: false, msg: ‘请求失败’ }; if (isTokenInvalid(res)) return { needRefresh: true }; if (res.success === true || res.isSuccess === true) { return { success: true, point: res.point || 0, msg: res.message || ‘签到成功’, }; } const msg = res.message || res.msg || JSON.stringify(res); if (msg.includes(‘已签’) || msg.includes(‘重复’) || msg.includes(‘already’)) { return { success: false, alreadySigned: true, msg }; } return { success: false, msg }; } /** 查询积分 */ async function getPoints(token) { const res = await apiGet(‘/api/icoke-customer/icoke/mini/customer/main/points’, token); if (!res) return null; return { point: res.point || 0, experiencePoints: res.experiencePoints || 0, frozenPoint: res.frozenPoint || 0, }; } /** 查询用户基本信息 */ async function getUserInfo(token) { const res = await apiGet(‘/api/icoke-customer/icoke/mini/customer/main/base/info’, token); if (!res) return null; return { name: res.name || ‘未知’, mobile: res.mobile || ‘’, grade: res.grade || ‘’, }; } /* ==================== 工具函数 ==================== */ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } /* ==================== 单账号执行 ==================== */ async function runSingleAccount(accountStr, index) { const sepIdx = accountStr.indexOf(‘#’); if (sepIdx <= 0) { console.log( ❌ 第${index}个账号格式错误,应为 备注#wxid ); return; } const remark = accountStr.substring(0, sepIdx); const wxid = accountStr.substring(sepIdx + 1).trim(); console.log( \n==================================== ); console.log( 🚀 【可口可乐】${remark}(第${index}个) ); console.log( ==================================== ); // 获取 token let token = await getValidToken(remark, wxid); if (!token) { console.log(‘ 获取 token 失败,跳过’); return; } // 查询签到状态 let outline = await getSignOutline(token); if (outline?.needRefresh) { console.log(‘ token 失效,重新获取…’); token = await getValidToken(remark, wxid, true); if (!token) { console.log(‘ 重新获取 token 失败’); return; } outline = await getSignOutline(token); } if (outline) { if (outline.signed) { console.log( 📅 签到状态:✅ 今日已签到 | 本月已签 ${outline.totalDays} 天 ); } else { console.log( 📅 签到状态:❌ 今日未签到 | 本月已签 ${outline.totalDays} 天 ); } } // 执行签到 let signResult = await doSign(token); if (signResult?.needRefresh) { console.log(‘ token 失效,重新获取…’); token = await getValidToken(remark, wxid, true); if (!token) { console.log(‘ 重新获取 token 失败’); return; } signResult = await doSign(token); } if (signResult?.success) { console.log( ✅ 签到成功!获得积分:${signResult.point} ); } else if (signResult?.alreadySigned) { console.log( ℹ️ 今日已签到:${signResult.msg} ); } else { console.log( ⚠️ 签到结果:${signResult?.msg || '未知'} ); } await sleep(1000); // 查询积分 const pts = await getPoints(token); if (pts) { console.log( 💰 当前积分:${pts.point} | 经验值:${pts.experiencePoints} | 冻结:${pts.frozenPoint} ); } // 查询用户信息 const userInfo = await getUserInfo(token); if (userInfo) { console.log( 👤 会员:${userInfo.name} | 手机:${userInfo.mobile} ); } console.log( ✨ ${remark} 执行完成\n ); } /* ==================== 主函数 ==================== */ !(async () => { console.log( 📢 可口可乐吧签到 - 共检测到 ${wxidList.length} 个账号 ); for (let i = 0; i < wxidList.length; i++) { await runSingleAccount(wxidList[i], i + 1); if (i < wxidList.length - 1) await sleep(2000); } console.log(‘ 全部账号执行完毕!’); })(); 4 个帖子 - 4 位参与者 阅读完整话题
省流:增加环境变量即可解决: export CLAUDE_CODE_ATTRIBUTION_HEADER=0 之前在群里刷到这个,就是 A 出会在 prompt 里面加一个"时间戳",导致 api 的缓存大量失效。然后我让 Gemini 确认了一下问题: 确有其事。 并且 cc-switch 上已经有 pr 提到这个了。 然后让我们的 deepseek v4 选手来定位并且解决一下: woc,他居然直接通过逆向的方式确认了真的有这个 api: 修复方式是直接注入环境变量即可: 然后让 DeepSeek 去证实这个: 确有其事!!! 增加环境变量即可解决: export CLAUDE_CODE_ATTRIBUTION_HEADER=0 3 个帖子 - 3 位参与者 阅读完整话题
懵了 cherry studio通过new-api调用cpa用gpt-image-2总是超时 new api的ng 环境变量都改了超时设置,还是无法超过60s 1 个帖子 - 1 位参与者 阅读完整话题