diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9e66ece --- /dev/null +++ b/Makefile @@ -0,0 +1,92 @@ +# ────────────────────────────────────────────── +# cursor-api-proxy — 設定與建置 +# 編輯下方變數,然後執行 make env 產生 .env 檔 +# ────────────────────────────────────────────── + +# ── 伺服器設定 ───────────────────────────────── +HOST ?= 127.0.0.1 +PORT ?= 8765 +API_KEY ?= +TIMEOUT_MS ?= 300000 +MULTI_PORT ?= false +VERBOSE ?= false + +# ── Agent / 模型設定 ────────────────────────── +AGENT_BIN ?= agent +AGENT_NODE ?= +AGENT_SCRIPT ?= +DEFAULT_MODEL ?= auto +STRICT_MODEL ?= true +MAX_MODE ?= false +FORCE ?= false +APPROVE_MCPS ?= false + +# ── 工作區與帳號 ────────────────────────────── +WORKSPACE ?= +CHAT_ONLY_WORKSPACE ?= true +CONFIG_DIRS ?= + +# ── TLS / HTTPS ─────────────────────────────── +TLS_CERT ?= +TLS_KEY ?= + +# ── 記錄 ────────────────────────────────────── +SESSIONS_LOG ?= + +# ────────────────────────────────────────────── + +ENV_FILE ?= .env + +.PHONY: env run build clean help + +## 產生 .env 檔(預設輸出至 .env,可用 ENV_FILE=xxx 覆寫) +env: + @printf '# 由 make env 自動產生,請勿手動編輯\n' > $(ENV_FILE) + @printf 'CURSOR_BRIDGE_HOST=%s\n' "$(HOST)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_PORT=%s\n' "$(PORT)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_API_KEY=%s\n' "$(API_KEY)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_TIMEOUT_MS=%s\n' "$(TIMEOUT_MS)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_MULTI_PORT=%s\n' "$(MULTI_PORT)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_VERBOSE=%s\n' "$(VERBOSE)" >> $(ENV_FILE) + @printf 'CURSOR_AGENT_BIN=%s\n' "$(AGENT_BIN)" >> $(ENV_FILE) + @printf 'CURSOR_AGENT_NODE=%s\n' "$(AGENT_NODE)" >> $(ENV_FILE) + @printf 'CURSOR_AGENT_SCRIPT=%s\n' "$(AGENT_SCRIPT)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_DEFAULT_MODEL=%s\n' "$(DEFAULT_MODEL)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_STRICT_MODEL=%s\n' "$(STRICT_MODEL)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_MAX_MODE=%s\n' "$(MAX_MODE)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_FORCE=%s\n' "$(FORCE)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_APPROVE_MCPS=%s\n' "$(APPROVE_MCPS)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_WORKSPACE=%s\n' "$(WORKSPACE)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_CHAT_ONLY_WORKSPACE=%s\n' "$(CHAT_ONLY_WORKSPACE)" >> $(ENV_FILE) + @printf 'CURSOR_CONFIG_DIRS=%s\n' "$(CONFIG_DIRS)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_TLS_CERT=%s\n' "$(TLS_CERT)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_TLS_KEY=%s\n' "$(TLS_KEY)" >> $(ENV_FILE) + @printf 'CURSOR_BRIDGE_SESSIONS_LOG=%s\n' "$(SESSIONS_LOG)" >> $(ENV_FILE) + @echo "已產生 $(ENV_FILE)" + +## 編譯二進位檔 +build: + go build -o cursor-api-proxy . + +## 載入 .env 後直接執行(需先執行 make env 或已有 .env) +run: build + @if [ -f $(ENV_FILE) ]; then \ + set -a && . ./$(ENV_FILE) && set +a && ./cursor-api-proxy; \ + else \ + echo "找不到 $(ENV_FILE),請先執行 make env"; exit 1; \ + fi + +## 清除產出物 +clean: + rm -f cursor-api-proxy $(ENV_FILE) + +## 顯示說明 +help: + @echo "可用目標:" + @echo " make env 產生 .env(先在 Makefile 頂端填好變數)" + @echo " make build 編譯 cursor-api-proxy 二進位檔" + @echo " make run 編譯並載入 .env 執行" + @echo " make clean 刪除二進位檔與 .env" + @echo "" + @echo "覆寫範例:" + @echo " make env PORT=9000 API_KEY=mysecret TIMEOUT_MS=60000" diff --git a/README.md b/README.md index 426eb26..a4f8554 100644 --- a/README.md +++ b/README.md @@ -80,11 +80,52 @@ go build -o cursor-api-proxy . ## 環境變數 +### 伺服器設定 + | 變數 | 預設值 | 說明 | |------|--------|------| -| `CURSOR_BRIDGE_HOST` | `127.0.0.1` | 監聽位址 | -| `CURSOR_BRIDGE_PORT` | `8080` | 監聽連接埠 | -| `HTTPS_PROXY` | - | HTTP 代理伺服器 | +| `CURSOR_BRIDGE_HOST` | `127.0.0.1` | 監聽位址(設為 `0.0.0.0` 可供區域網路存取) | +| `CURSOR_BRIDGE_PORT` | `8765` | 監聽連接埠 | +| `CURSOR_BRIDGE_API_KEY` | _(無)_ | API 鑑別金鑰,設定後所有請求需帶此金鑰 | +| `CURSOR_BRIDGE_TIMEOUT_MS` | `300000` | 請求逾時毫秒數(預設 5 分鐘) | +| `CURSOR_BRIDGE_MULTI_PORT` | `false` | 啟用多連接埠模式 | +| `CURSOR_BRIDGE_VERBOSE` | `false` | 啟用詳細日誌輸出 | + +### Agent / 模型設定 + +| 變數 | 預設值 | 說明 | +|------|--------|------| +| `CURSOR_AGENT_BIN` / `CURSOR_CLI_BIN` / `CURSOR_CLI_PATH` | `agent` | Cursor CLI 二進位檔路徑 | +| `CURSOR_AGENT_NODE` | _(無)_ | Node.js 執行檔路徑(Windows 使用) | +| `CURSOR_AGENT_SCRIPT` | _(無)_ | Agent 腳本路徑(Windows 使用) | +| `CURSOR_BRIDGE_DEFAULT_MODEL` | `auto` | 預設使用的模型 ID | +| `CURSOR_BRIDGE_STRICT_MODEL` | `true` | 嚴格模式:禁止使用不在清單中的模型 | +| `CURSOR_BRIDGE_MAX_MODE` | `false` | 啟用 Max Mode(消耗更多額度) | +| `CURSOR_BRIDGE_FORCE` | `false` | 強制執行,不詢問確認 | +| `CURSOR_BRIDGE_APPROVE_MCPS` | `false` | 自動核准 MCP 工具呼叫 | + +### 工作區與帳號 + +| 變數 | 預設值 | 說明 | +|------|--------|------| +| `CURSOR_BRIDGE_WORKSPACE` | _(目前目錄)_ | 工作目錄路徑 | +| `CURSOR_BRIDGE_CHAT_ONLY_WORKSPACE` | `true` | 限制 agent 只能存取工作目錄 | +| `CURSOR_CONFIG_DIRS` / `CURSOR_ACCOUNT_DIRS` | _(自動探索)_ | 帳號設定目錄,多個用逗號分隔 | + +### TLS / HTTPS + +| 變數 | 預設值 | 說明 | +|------|--------|------| +| `CURSOR_BRIDGE_TLS_CERT` | _(無)_ | TLS 憑證檔路徑(啟用 HTTPS) | +| `CURSOR_BRIDGE_TLS_KEY` | _(無)_ | TLS 私鑰檔路徑(啟用 HTTPS) | + +### 記錄與 Windows 特定 + +| 變數 | 預設值 | 說明 | +|------|--------|------| +| `CURSOR_BRIDGE_SESSIONS_LOG` | `~/.cursor-api-proxy/sessions.log` | Session 記錄檔路徑 | +| `CURSOR_BRIDGE_WIN_CMDLINE_MAX` | `30000` | Windows 命令列最大長度(4096–32700) | +| `COMSPEC` | `cmd.exe` | Windows 命令直譯器路徑 | ## 常見問題 diff --git a/go.mod b/go.mod index 27de6b7..c231a41 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,13 @@ module cursor-api-proxy go 1.25.0 +require ( + github.com/google/uuid v1.6.0 + modernc.org/sqlite v1.48.0 +) + require ( github.com/dustin/go-humanize v1.0.1 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect @@ -12,5 +16,4 @@ require ( modernc.org/libc v1.70.0 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect - modernc.org/sqlite v1.48.0 // indirect ) diff --git a/go.sum b/go.sum index d96a814..8411195 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,51 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= +modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= +modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.32.0 h1:hjG66bI/kqIPX1b2yT6fr/jt+QedtP2fqojG2VrFuVw= +modernc.org/ccgo/v4 v4.32.0/go.mod h1:6F08EBCx5uQc38kMGl+0Nm0oWczoo1c7cgpzEry7Uc0= +modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= +modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= +modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= +modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo= +modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= +modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= +modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= modernc.org/libc v1.70.0 h1:U58NawXqXbgpZ/dcdS9kMshu08aiA6b7gusEusqzNkw= modernc.org/libc v1.70.0/go.mod h1:OVmxFGP1CI/Z4L3E0Q3Mf1PDE0BucwMkcXjjLntvHJo= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= +modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= modernc.org/sqlite v1.48.0 h1:ElZyLop3Q2mHYk5IFPPXADejZrlHu7APbpB0sF78bq4= modernc.org/sqlite v1.48.0/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig= +modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=