Rename product to Lingma Proxy
This commit is contained in:
30
.github/workflows/release.yml
vendored
30
.github/workflows/release.yml
vendored
@@ -60,14 +60,14 @@ jobs:
|
||||
- name: Build CLI
|
||||
run: |
|
||||
mkdir -p dist
|
||||
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -trimpath -ldflags "-s -w" -o dist/lingma-ipc-proxy ./cmd/lingma-ipc-proxy
|
||||
tar -C dist -czf "lingma-ipc-proxy_${RELEASE_TAG}_darwin_arm64.tar.gz" lingma-ipc-proxy
|
||||
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -trimpath -ldflags "-s -w" -o dist/lingma-proxy ./cmd/lingma-ipc-proxy
|
||||
tar -C dist -czf "lingma-proxy_${RELEASE_TAG}_darwin_arm64.tar.gz" lingma-proxy
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cli-macos
|
||||
path: lingma-ipc-proxy_${{ env.RELEASE_TAG }}_darwin_arm64.tar.gz
|
||||
path: lingma-proxy_${{ env.RELEASE_TAG }}_darwin_arm64.tar.gz
|
||||
|
||||
build-cli-windows:
|
||||
name: Build CLI Windows
|
||||
@@ -86,14 +86,14 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
.\scripts\build.ps1 -Clean
|
||||
$asset = "lingma-ipc-proxy_${env:RELEASE_TAG}_windows_amd64.zip"
|
||||
Compress-Archive -Path .\dist\lingma-ipc-proxy.exe -DestinationPath $asset -Force
|
||||
$asset = "lingma-proxy_${env:RELEASE_TAG}_windows_amd64.zip"
|
||||
Compress-Archive -Path .\dist\lingma-proxy.exe -DestinationPath $asset -Force
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cli-windows
|
||||
path: lingma-ipc-proxy_${{ env.RELEASE_TAG }}_windows_amd64.zip
|
||||
path: lingma-proxy_${{ env.RELEASE_TAG }}_windows_amd64.zip
|
||||
|
||||
build-desktop-macos:
|
||||
name: Build Desktop macOS
|
||||
@@ -130,17 +130,17 @@ jobs:
|
||||
run: |
|
||||
APP_PATH="$(find desktop/build/bin -maxdepth 1 -name '*.app' -print -quit)"
|
||||
test -n "$APP_PATH"
|
||||
test "$(basename "$APP_PATH")" = "Lingma IPC Proxy.app"
|
||||
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "lingma-ipc-proxy-desktop_${RELEASE_TAG}_darwin_arm64.zip"
|
||||
test "$(basename "$APP_PATH")" = "Lingma Proxy.app"
|
||||
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "lingma-proxy-desktop_${RELEASE_TAG}_darwin_arm64.zip"
|
||||
DMG_ROOT="$(mktemp -d)"
|
||||
cp -R "$APP_PATH" "$DMG_ROOT/"
|
||||
ln -s /Applications "$DMG_ROOT/Applications"
|
||||
hdiutil create \
|
||||
-volname "Lingma IPC Proxy" \
|
||||
-volname "Lingma Proxy" \
|
||||
-srcfolder "$DMG_ROOT" \
|
||||
-ov \
|
||||
-format UDZO \
|
||||
"lingma-ipc-proxy-desktop_${RELEASE_TAG}_darwin_arm64.dmg"
|
||||
"lingma-proxy-desktop_${RELEASE_TAG}_darwin_arm64.dmg"
|
||||
rm -rf "$DMG_ROOT"
|
||||
|
||||
- name: Upload artifact
|
||||
@@ -148,8 +148,8 @@ jobs:
|
||||
with:
|
||||
name: desktop-macos
|
||||
path: |
|
||||
lingma-ipc-proxy-desktop_${{ env.RELEASE_TAG }}_darwin_arm64.zip
|
||||
lingma-ipc-proxy-desktop_${{ env.RELEASE_TAG }}_darwin_arm64.dmg
|
||||
lingma-proxy-desktop_${{ env.RELEASE_TAG }}_darwin_arm64.zip
|
||||
lingma-proxy-desktop_${{ env.RELEASE_TAG }}_darwin_arm64.dmg
|
||||
|
||||
build-desktop-windows:
|
||||
name: Build Desktop Windows
|
||||
@@ -191,14 +191,14 @@ jobs:
|
||||
$exe = Get-ChildItem .\desktop\build\bin -Filter *.exe | Select-Object -First 1
|
||||
if (-not $exe) { throw "Desktop exe was not produced" }
|
||||
if ($exe.Name -ne "LingmaProxy.exe") { throw "Unexpected desktop exe name: $($exe.Name)" }
|
||||
$asset = "lingma-ipc-proxy-desktop_${env:RELEASE_TAG}_windows_amd64.zip"
|
||||
$asset = "lingma-proxy-desktop_${env:RELEASE_TAG}_windows_amd64.zip"
|
||||
Compress-Archive -Path $exe.FullName -DestinationPath $asset -Force
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: desktop-windows
|
||||
path: lingma-ipc-proxy-desktop_${{ env.RELEASE_TAG }}_windows_amd64.zip
|
||||
path: lingma-proxy-desktop_${{ env.RELEASE_TAG }}_windows_amd64.zip
|
||||
|
||||
publish:
|
||||
name: Publish Release
|
||||
@@ -218,7 +218,7 @@ jobs:
|
||||
- name: Generate checksums
|
||||
run: |
|
||||
cd artifacts
|
||||
sha256sum * > "lingma-ipc-proxy_${RELEASE_TAG}_sha256.txt"
|
||||
sha256sum * > "lingma-proxy_${RELEASE_TAG}_sha256.txt"
|
||||
|
||||
- name: Create or update release
|
||||
uses: softprops/action-gh-release@v2
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Nothing yet.
|
||||
- Renamed user-facing product, desktop app, release assets, and documentation from Lingma IPC Proxy to Lingma Proxy.
|
||||
- Clarified that Remote API mode is the recommended default and that only IPC plugin mode is based on the `coolxll/lingma-ipc-proxy` protocol discovery.
|
||||
- Added `lingma-proxy.json` and `~/.config/lingma-proxy/config.json` config lookup/write paths while keeping legacy `lingma-ipc-proxy` config fallback.
|
||||
- Added a desktop top-bar force quit button that stops the proxy and exits the app on macOS and Windows.
|
||||
|
||||
## v1.4.6 - 2026-05-06
|
||||
|
||||
|
||||
68
README.md
68
README.md
@@ -2,14 +2,14 @@
|
||||
|
||||
[English](./README.md) | [简体中文](./README.zh-CN.md)
|
||||
|
||||
Lingma Proxy exposes Tongyi Lingma as standard **OpenAI-compatible** and **Anthropic-compatible** HTTP APIs. It can use either the local IDE plugin IPC channel or an experimental remote API backend, and ships as both a CLI proxy service and a cross-platform desktop app for macOS and Windows.
|
||||
Lingma Proxy exposes Tongyi Lingma as standard **OpenAI-compatible** and **Anthropic-compatible** HTTP APIs. It can use either the recommended Remote API backend or the local IDE plugin IPC channel, and ships as both a CLI proxy service and a cross-platform desktop app for macOS and Windows.
|
||||
|
||||
The project is designed for tools such as Claude Code, Cline, Continue, OpenCode, custom agents, and any client that can talk to OpenAI or Anthropic style APIs.
|
||||
|
||||
The proxy now supports two backend modes:
|
||||
|
||||
- **Remote API mode (default, experimental)**: imports the local Lingma login cache or an explicit credential file and calls Lingma remote APIs directly. This feels more like an official API, does not depend on an IDE IPC session, and is currently the recommended mode for Claude Code / Hermes style agents.
|
||||
- **IPC plugin mode**: connects to the local Lingma IDE plugin over WebSocket / Named Pipe. This keeps behavior closest to the IDE plugin and is useful as a compatibility fallback.
|
||||
- **Remote API mode (default, recommended)**: imports the local Lingma login cache or an explicit credential file and calls Lingma remote APIs directly. This behaves closest to a normal hosted API, avoids IDE/plugin session and environment limits, and is currently the best mode for Claude Code / Hermes style agents.
|
||||
- **IPC plugin mode**: connects to the local Lingma IDE plugin over WebSocket / Named Pipe. This keeps behavior closest to the IDE plugin, but it can inherit IDE session lifetime, local plugin state, and environment constraints, so it is mainly a compatibility fallback.
|
||||
|
||||
## Current Version
|
||||
|
||||
@@ -21,22 +21,22 @@ Release builds are produced by GitHub Actions for:
|
||||
|
||||
| Asset | Platform | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `lingma-ipc-proxy_<tag>_darwin_arm64.tar.gz` | macOS | CLI proxy |
|
||||
| `lingma-ipc-proxy_<tag>_windows_amd64.zip` | Windows | CLI proxy |
|
||||
| `lingma-ipc-proxy-desktop_<tag>_darwin_arm64.dmg` | macOS Apple Silicon | Drag-to-install desktop app |
|
||||
| `lingma-ipc-proxy-desktop_<tag>_darwin_arm64.zip` | macOS Apple Silicon | Raw `.app` archive |
|
||||
| `lingma-ipc-proxy-desktop_<tag>_windows_amd64.zip` | Windows | Desktop app |
|
||||
| `lingma-ipc-proxy_<tag>_sha256.txt` | all | Checksums |
|
||||
| `lingma-proxy_<tag>_darwin_arm64.tar.gz` | macOS | CLI proxy |
|
||||
| `lingma-proxy_<tag>_windows_amd64.zip` | Windows | CLI proxy |
|
||||
| `lingma-proxy-desktop_<tag>_darwin_arm64.dmg` | macOS Apple Silicon | Drag-to-install desktop app |
|
||||
| `lingma-proxy-desktop_<tag>_darwin_arm64.zip` | macOS Apple Silicon | Raw `.app` archive |
|
||||
| `lingma-proxy-desktop_<tag>_windows_amd64.zip` | Windows | Desktop app |
|
||||
| `lingma-proxy_<tag>_sha256.txt` | all | Checksums |
|
||||
|
||||
### Which Package Should I Download?
|
||||
|
||||
| Your system | Recommended asset | Notes |
|
||||
| --- | --- | --- |
|
||||
| macOS on Apple Silicon (M1/M2/M3/M4) | `lingma-ipc-proxy-desktop_<tag>_darwin_arm64.dmg` | Open the DMG and drag `Lingma IPC Proxy.app` to `Applications`. |
|
||||
| macOS on Apple Silicon, portable archive | `lingma-ipc-proxy-desktop_<tag>_darwin_arm64.zip` | Same app, but packaged as a zip instead of a drag-to-install DMG. |
|
||||
| Windows x64 / x86_64 / AMD64 | `lingma-ipc-proxy-desktop_<tag>_windows_amd64.zip` | This is the correct package for normal 64-bit Windows PCs, including Intel and AMD CPUs. |
|
||||
| macOS CLI only | `lingma-ipc-proxy_<tag>_darwin_arm64.tar.gz` | Terminal-only proxy binary. |
|
||||
| Windows CLI only | `lingma-ipc-proxy_<tag>_windows_amd64.zip` | Terminal-only proxy binary for 64-bit Windows. |
|
||||
| macOS on Apple Silicon (M1/M2/M3/M4) | `lingma-proxy-desktop_<tag>_darwin_arm64.dmg` | Open the DMG and drag `Lingma Proxy.app` to `Applications`. |
|
||||
| macOS on Apple Silicon, portable archive | `lingma-proxy-desktop_<tag>_darwin_arm64.zip` | Same app, but packaged as a zip instead of a drag-to-install DMG. |
|
||||
| Windows x64 / x86_64 / AMD64 | `lingma-proxy-desktop_<tag>_windows_amd64.zip` | This is the correct package for normal 64-bit Windows PCs, including Intel and AMD CPUs. |
|
||||
| macOS CLI only | `lingma-proxy_<tag>_darwin_arm64.tar.gz` | Terminal-only proxy binary. |
|
||||
| Windows CLI only | `lingma-proxy_<tag>_windows_amd64.zip` | Terminal-only proxy binary for 64-bit Windows. |
|
||||
|
||||
There is currently no separate `windows_arm64` package. On a normal x64 Windows machine, choose `windows_amd64`.
|
||||
|
||||
@@ -165,18 +165,18 @@ flowchart LR
|
||||
If auto detection fails, set the path manually in the desktop Settings page or pass CLI flags:
|
||||
|
||||
```bash
|
||||
lingma-ipc-proxy --transport websocket --ws-url ws://127.0.0.1:36510 --port 8095
|
||||
lingma-ipc-proxy --transport pipe --pipe '\\.\pipe\lingma-ipc'
|
||||
lingma-proxy --transport websocket --ws-url ws://127.0.0.1:36510 --port 8095
|
||||
lingma-proxy --transport pipe --pipe '\\.\pipe\lingma-ipc'
|
||||
```
|
||||
|
||||
## Backend Modes
|
||||
|
||||
### Remote API Mode (Default, Experimental)
|
||||
### Remote API Mode (Default, Recommended)
|
||||
|
||||
Remote mode calls Lingma's remote API directly:
|
||||
|
||||
```bash
|
||||
lingma-ipc-proxy --backend remote --port 8095
|
||||
lingma-proxy --backend remote --port 8095
|
||||
```
|
||||
|
||||
By default it reads the local Lingma login cache in read-only mode:
|
||||
@@ -193,10 +193,10 @@ XDG config/state Lingma cache paths when present
|
||||
You can also pass an explicit credential file:
|
||||
|
||||
```bash
|
||||
lingma-ipc-proxy \
|
||||
lingma-proxy \
|
||||
--backend remote \
|
||||
--remote-base-url https://lingma.alibabacloud.com \
|
||||
--remote-auth-file ~/.config/lingma-ipc-proxy/credentials.json
|
||||
--remote-auth-file ~/.config/lingma-proxy/credentials.json
|
||||
```
|
||||
|
||||
Credential file format:
|
||||
@@ -216,6 +216,7 @@ Credential file format:
|
||||
|
||||
Notes:
|
||||
|
||||
- Remote API mode is the recommended default for day-to-day agent usage. It bypasses the IDE/plugin IPC runtime, so it is less affected by plugin session state, IDE working directory, or local extension environment limitations.
|
||||
- Remote mode does not write or migrate login state. It only reads the local Lingma cache or the credential file you provide.
|
||||
- If your Lingma plugin uses a dedicated domain, remote mode first uses `--remote-base-url`, `LINGMA_REMOTE_BASE_URL`, or the JSON config field. If those are empty, it scans Lingma's local logs on macOS, Windows, and Linux for endpoint hints such as `endpoint config:` and marketplace service URLs.
|
||||
- The desktop Settings page shows the resolved remote domain and detection source without exposing tokens.
|
||||
@@ -228,10 +229,10 @@ Notes:
|
||||
IPC mode talks to the local Lingma IDE plugin:
|
||||
|
||||
```bash
|
||||
lingma-ipc-proxy --backend ipc --transport auto --port 8095
|
||||
lingma-proxy --backend ipc --transport auto --port 8095
|
||||
```
|
||||
|
||||
Use this when VS Code / the Lingma plugin is already running, when you want plugin session behavior, or when you want the model list exposed by the local plugin.
|
||||
Use this when VS Code / the Lingma plugin is already running, when you want plugin session behavior, or when you want the exact model list exposed by the local plugin. Compared with Remote API mode, IPC mode is more coupled to the IDE/plugin process and can be affected by that process's session, current project, and local environment.
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -239,25 +240,25 @@ Use this when VS Code / the Lingma plugin is already running, when you want plug
|
||||
|
||||
1. Install VS Code and the Tongyi Lingma extension.
|
||||
2. Log in to Tongyi Lingma and verify the Lingma panel can chat normally.
|
||||
3. Download the desktop asset from [Releases](https://github.com/Lutiancheng1/lingma-ipc-proxy/releases).
|
||||
4. Start `Lingma IPC Proxy`.
|
||||
3. Download the desktop asset from [Releases](https://github.com/Lutiancheng1/lingma-proxy/releases).
|
||||
4. Start `Lingma Proxy`.
|
||||
5. Click `探测模型` after the proxy is running.
|
||||
6. Configure clients to use `http://127.0.0.1:8095`.
|
||||
|
||||
### CLI
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Lutiancheng1/lingma-ipc-proxy.git
|
||||
cd lingma-ipc-proxy
|
||||
go build -o ./dist/lingma-ipc-proxy ./cmd/lingma-ipc-proxy
|
||||
./dist/lingma-ipc-proxy --host 127.0.0.1 --port 8095 --session-mode auto
|
||||
git clone https://github.com/Lutiancheng1/lingma-proxy.git
|
||||
cd lingma-proxy
|
||||
go build -o ./dist/lingma-proxy ./cmd/lingma-ipc-proxy
|
||||
./dist/lingma-proxy --host 127.0.0.1 --port 8095 --session-mode auto
|
||||
```
|
||||
|
||||
Windows:
|
||||
|
||||
```powershell
|
||||
.\scripts\build.ps1
|
||||
.\dist\lingma-ipc-proxy.exe --host 127.0.0.1 --port 8095 --session-mode auto
|
||||
.\dist\lingma-proxy.exe --host 127.0.0.1 --port 8095 --session-mode auto
|
||||
```
|
||||
|
||||
## Client Configuration
|
||||
@@ -335,7 +336,8 @@ Remote mode enables timeout fallback by default. On timeout, upstream 5xx/429, o
|
||||
Default config file:
|
||||
|
||||
```text
|
||||
./lingma-ipc-proxy.json
|
||||
./lingma-proxy.json
|
||||
./lingma-ipc-proxy.json # legacy fallback
|
||||
```
|
||||
|
||||
Example:
|
||||
@@ -387,7 +389,7 @@ Older builds rejected concurrent chat requests with a `rate_limit_error` saying
|
||||
Example:
|
||||
|
||||
```bash
|
||||
LINGMA_PROXY_MAX_CONCURRENT=8 lingma-ipc-proxy --port 8095
|
||||
LINGMA_PROXY_MAX_CONCURRENT=8 lingma-proxy --port 8095
|
||||
```
|
||||
|
||||
## Function Calling / Tool Calling
|
||||
@@ -460,7 +462,7 @@ cd desktop
|
||||
wails build -platform windows/amd64 -clean
|
||||
```
|
||||
|
||||
The desktop bundle name is always `Lingma IPC Proxy`.
|
||||
The desktop bundle name is always `Lingma Proxy`.
|
||||
|
||||
## Release Plan
|
||||
|
||||
@@ -480,4 +482,4 @@ Planned improvements:
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
This project is based on the protocol insight and initial discovery work from [coolxll/lingma-ipc-proxy](https://github.com/coolxll/lingma-ipc-proxy). The core idea of connecting to Lingma's private local IPC protocol and exposing standard API endpoints came from that project. This fork extends the implementation with broader OpenAI/Anthropic compatibility, tool emulation, image handling, desktop app support, request/log inspection, cross-platform packaging, and release automation.
|
||||
The **IPC plugin mode** is based on the protocol insight and initial discovery work from [coolxll/lingma-ipc-proxy](https://github.com/coolxll/lingma-ipc-proxy). That project first demonstrated that Lingma's private local IPC protocol can be bridged to standard HTTP API endpoints. Lingma Proxy keeps that IPC path as a compatibility backend and extends it with broader OpenAI/Anthropic compatibility, tool emulation, image handling, desktop app support, request/log inspection, cross-platform packaging, and release automation. The default **Remote API mode** is a separate backend that calls Lingma remote APIs directly and is documented independently above.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](./README.md) | [简体中文](./README.zh-CN.md)
|
||||
|
||||
**Lingma Proxy** 是一个通义灵码 API 适配层。它既可以把 Lingma 插件的本地私有 IPC / WebSocket 能力转换成标准 **OpenAI 兼容接口** 和 **Anthropic 兼容接口**,也可以使用实验性的远端 API 模式直接调用 Lingma 远端接口,让 Claude Code、Cline、Continue、OpenCode、自研 Agent 等第三方客户端可以直接调用 Lingma 后端模型。
|
||||
**Lingma Proxy** 是一个通义灵码 API 适配层。它可以通过默认推荐的远端 API 模式直接调用 Lingma 远端接口,也可以把 Lingma 插件的本地私有 IPC / WebSocket 能力转换成标准 **OpenAI 兼容接口** 和 **Anthropic 兼容接口**,让 Claude Code、Cline、Continue、OpenCode、自研 Agent 等第三方客户端可以直接调用 Lingma 后端模型。
|
||||
|
||||
项目同时提供两种使用方式:
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
代理后端支持两种模式:
|
||||
|
||||
- **远端 API 模式(默认,实验)**:读取 Lingma 本地登录缓存或显式凭据,直接调用 Lingma 远端接口。优点是不依赖 IDE 插件窗口和 IPC 会话,体验更像官方 API;目前更推荐给 Claude Code / Hermes 这类本地 Agent。
|
||||
- **IPC 插件模式**:连接本机 Lingma IDE 插件的 WebSocket / Named Pipe。优点是更接近 IDE 插件上下文,适合作为兼容性兜底。
|
||||
- **远端 API 模式(默认,推荐)**:读取 Lingma 本地登录缓存或显式凭据,直接调用 Lingma 远端接口。它更接近普通托管 API,不依赖 IDE 插件窗口、IPC 会话和插件执行环境;目前更推荐给 Claude Code / Hermes 这类本地 Agent。
|
||||
- **IPC 插件模式**:连接本机 Lingma IDE 插件的 WebSocket / Named Pipe。它更接近 IDE 插件上下文,但会继承 IDE 会话生命周期、插件本地状态和环境限制,主要作为兼容性兜底。
|
||||
|
||||
## 当前版本
|
||||
|
||||
@@ -24,22 +24,22 @@ GitHub Actions 会在 Release 中产出:
|
||||
|
||||
| 产物 | 平台 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| `lingma-ipc-proxy_<tag>_darwin_arm64.tar.gz` | macOS | CLI 代理 |
|
||||
| `lingma-ipc-proxy_<tag>_windows_amd64.zip` | Windows | CLI 代理 |
|
||||
| `lingma-ipc-proxy-desktop_<tag>_darwin_arm64.dmg` | Apple Silicon Mac | 拖拽安装桌面 App |
|
||||
| `lingma-ipc-proxy-desktop_<tag>_darwin_arm64.zip` | Apple Silicon Mac | `.app` 压缩包 |
|
||||
| `lingma-ipc-proxy-desktop_<tag>_windows_amd64.zip` | Windows | 桌面 App |
|
||||
| `lingma-ipc-proxy_<tag>_sha256.txt` | 全平台 | 校验文件 |
|
||||
| `lingma-proxy_<tag>_darwin_arm64.tar.gz` | macOS | CLI 代理 |
|
||||
| `lingma-proxy_<tag>_windows_amd64.zip` | Windows | CLI 代理 |
|
||||
| `lingma-proxy-desktop_<tag>_darwin_arm64.dmg` | Apple Silicon Mac | 拖拽安装桌面 App |
|
||||
| `lingma-proxy-desktop_<tag>_darwin_arm64.zip` | Apple Silicon Mac | `.app` 压缩包 |
|
||||
| `lingma-proxy-desktop_<tag>_windows_amd64.zip` | Windows | 桌面 App |
|
||||
| `lingma-proxy_<tag>_sha256.txt` | 全平台 | 校验文件 |
|
||||
|
||||
### 应该下载哪个包?
|
||||
|
||||
| 你的系统 | 推荐下载 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| Apple Silicon Mac(M1/M2/M3/M4) | `lingma-ipc-proxy-desktop_<tag>_darwin_arm64.dmg` | 打开 DMG 后把 `Lingma IPC Proxy.app` 拖到 `Applications`。 |
|
||||
| Apple Silicon Mac,想要压缩包 | `lingma-ipc-proxy-desktop_<tag>_darwin_arm64.zip` | 和 DMG 是同一个 App,只是 zip 形式。 |
|
||||
| Windows x64 / x86_64 / AMD64 | `lingma-ipc-proxy-desktop_<tag>_windows_amd64.zip` | 普通 64 位 Windows 电脑都选这个,包括 Intel 和 AMD CPU。 |
|
||||
| 只想在 macOS 终端跑 CLI | `lingma-ipc-proxy_<tag>_darwin_arm64.tar.gz` | 只有命令行代理,没有桌面界面。 |
|
||||
| 只想在 Windows 终端跑 CLI | `lingma-ipc-proxy_<tag>_windows_amd64.zip` | 只有命令行代理,没有桌面界面。 |
|
||||
| Apple Silicon Mac(M1/M2/M3/M4) | `lingma-proxy-desktop_<tag>_darwin_arm64.dmg` | 打开 DMG 后把 `Lingma Proxy.app` 拖到 `Applications`。 |
|
||||
| Apple Silicon Mac,想要压缩包 | `lingma-proxy-desktop_<tag>_darwin_arm64.zip` | 和 DMG 是同一个 App,只是 zip 形式。 |
|
||||
| Windows x64 / x86_64 / AMD64 | `lingma-proxy-desktop_<tag>_windows_amd64.zip` | 普通 64 位 Windows 电脑都选这个,包括 Intel 和 AMD CPU。 |
|
||||
| 只想在 macOS 终端跑 CLI | `lingma-proxy_<tag>_darwin_arm64.tar.gz` | 只有命令行代理,没有桌面界面。 |
|
||||
| 只想在 Windows 终端跑 CLI | `lingma-proxy_<tag>_windows_amd64.zip` | 只有命令行代理,没有桌面界面。 |
|
||||
|
||||
目前没有单独的 `windows_arm64` 包。常见 x64 Windows 机器请选择 `windows_amd64`。
|
||||
|
||||
@@ -231,18 +231,18 @@ flowchart LR
|
||||
CLI 也可以手动指定:
|
||||
|
||||
```bash
|
||||
lingma-ipc-proxy --transport websocket --ws-url ws://127.0.0.1:36510 --port 8095
|
||||
lingma-ipc-proxy --transport pipe --pipe '\\.\pipe\lingma-ipc'
|
||||
lingma-proxy --transport websocket --ws-url ws://127.0.0.1:36510 --port 8095
|
||||
lingma-proxy --transport pipe --pipe '\\.\pipe\lingma-ipc'
|
||||
```
|
||||
|
||||
## 后端模式
|
||||
|
||||
### 远端 API 模式(默认,实验)
|
||||
### 远端 API 模式(默认,推荐)
|
||||
|
||||
远端模式直接调用 Lingma 远端接口:
|
||||
|
||||
```bash
|
||||
lingma-ipc-proxy --backend remote --port 8095
|
||||
lingma-proxy --backend remote --port 8095
|
||||
```
|
||||
|
||||
默认会只读导入:
|
||||
@@ -259,10 +259,10 @@ lingma-ipc-proxy --backend remote --port 8095
|
||||
也可以指定显式凭据文件:
|
||||
|
||||
```bash
|
||||
lingma-ipc-proxy \
|
||||
lingma-proxy \
|
||||
--backend remote \
|
||||
--remote-base-url https://lingma.alibabacloud.com \
|
||||
--remote-auth-file ~/.config/lingma-ipc-proxy/credentials.json
|
||||
--remote-auth-file ~/.config/lingma-proxy/credentials.json
|
||||
```
|
||||
|
||||
`credentials.json` 格式:
|
||||
@@ -282,6 +282,7 @@ lingma-ipc-proxy \
|
||||
|
||||
说明:
|
||||
|
||||
- 远端 API 模式是日常 Agent 使用的默认推荐模式。它绕过 IDE / 插件 IPC 运行时,因此更少受到插件会话、IDE 当前项目和本地扩展环境限制影响。
|
||||
- 远端模式不会写入或迁移你的登录态,只会读取本机 Lingma 缓存或你指定的凭据文件。
|
||||
- 如果 Lingma 插件配置过专属域名,远端模式会优先使用 `--remote-base-url`、`LINGMA_REMOTE_BASE_URL` 或配置文件;这些为空时,会扫描 macOS、Windows、Linux 上 Lingma 本地日志里的 `endpoint config:`、Marketplace service URL 等线索。
|
||||
- 桌面端设置页会展示当前解析到的远端域名和来源,但不会展示 token / key 明文。
|
||||
@@ -294,10 +295,10 @@ lingma-ipc-proxy \
|
||||
IPC 模式通过本机 Lingma IDE 插件通信:
|
||||
|
||||
```bash
|
||||
lingma-ipc-proxy --backend ipc --transport auto --port 8095
|
||||
lingma-proxy --backend ipc --transport auto --port 8095
|
||||
```
|
||||
|
||||
适合已经打开 VS Code / Lingma 插件、希望使用插件当前会话环境、并优先使用插件探测模型列表的场景。
|
||||
适合已经打开 VS Code / Lingma 插件、希望使用插件当前会话环境、并优先使用插件探测模型列表的场景。相比远端 API 模式,IPC 插件模式更依赖 IDE / 插件进程,也更容易受到插件会话、当前项目和本地环境的影响。
|
||||
|
||||
## 快速开始
|
||||
|
||||
@@ -310,8 +311,8 @@ lingma-ipc-proxy --backend ipc --transport auto --port 8095
|
||||
|
||||
### 使用桌面 App
|
||||
|
||||
1. 前往 [Releases](https://github.com/Lutiancheng1/lingma-ipc-proxy/releases) 下载桌面版。
|
||||
2. macOS 解压后打开 `Lingma IPC Proxy.app`。
|
||||
1. 前往 [Releases](https://github.com/Lutiancheng1/lingma-proxy/releases) 下载桌面版。
|
||||
2. macOS 解压后打开 `Lingma Proxy.app`。
|
||||
3. Windows 解压后运行桌面版 exe。
|
||||
4. 点击启动代理。
|
||||
5. 点击 `探测模型`。
|
||||
@@ -322,19 +323,19 @@ lingma-ipc-proxy --backend ipc --transport auto --port 8095
|
||||
macOS:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Lutiancheng1/lingma-ipc-proxy.git
|
||||
cd lingma-ipc-proxy
|
||||
go build -o ./dist/lingma-ipc-proxy ./cmd/lingma-ipc-proxy
|
||||
./dist/lingma-ipc-proxy --host 127.0.0.1 --port 8095 --session-mode auto
|
||||
git clone https://github.com/Lutiancheng1/lingma-proxy.git
|
||||
cd lingma-proxy
|
||||
go build -o ./dist/lingma-proxy ./cmd/lingma-ipc-proxy
|
||||
./dist/lingma-proxy --host 127.0.0.1 --port 8095 --session-mode auto
|
||||
```
|
||||
|
||||
Windows:
|
||||
|
||||
```powershell
|
||||
git clone https://github.com/Lutiancheng1/lingma-ipc-proxy.git
|
||||
cd lingma-ipc-proxy
|
||||
git clone https://github.com/Lutiancheng1/lingma-proxy.git
|
||||
cd lingma-proxy
|
||||
.\scripts\build.ps1
|
||||
.\dist\lingma-ipc-proxy.exe --host 127.0.0.1 --port 8095 --session-mode auto
|
||||
.\dist\lingma-proxy.exe --host 127.0.0.1 --port 8095 --session-mode auto
|
||||
```
|
||||
|
||||
## 客户端配置
|
||||
@@ -417,6 +418,7 @@ export ANTHROPIC_API_KEY="any"
|
||||
默认读取:
|
||||
|
||||
```text
|
||||
./lingma-proxy.json
|
||||
./lingma-ipc-proxy.json
|
||||
```
|
||||
|
||||
@@ -475,7 +477,7 @@ export ANTHROPIC_API_KEY="any"
|
||||
示例:
|
||||
|
||||
```bash
|
||||
LINGMA_PROXY_MAX_CONCURRENT=8 lingma-ipc-proxy --port 8095
|
||||
LINGMA_PROXY_MAX_CONCURRENT=8 lingma-proxy --port 8095
|
||||
```
|
||||
|
||||
## 工具调用实现
|
||||
@@ -559,10 +561,10 @@ wails build -platform windows/amd64 -clean
|
||||
桌面端最终 App 名称统一为:
|
||||
|
||||
```text
|
||||
Lingma IPC Proxy
|
||||
Lingma Proxy
|
||||
```
|
||||
|
||||
不会再生成 `lingma-proxy-desktop` 旧包名。
|
||||
Release 资产文件名仍使用 `lingma-proxy-desktop_<tag>_...` 区分桌面端和 CLI 端。
|
||||
|
||||
## GitHub Actions Release
|
||||
|
||||
@@ -587,9 +589,9 @@ Release workflow 会执行:
|
||||
|
||||
## 与上游项目的关系
|
||||
|
||||
我对比了上游仓库 [coolxll/lingma-ipc-proxy](https://github.com/coolxll/lingma-ipc-proxy)。上游项目的核心贡献是发现并验证了 Lingma 本地私有 IPC 协议可以被代理成标准 HTTP API,这是本项目的基础思路来源。
|
||||
我对比了上游仓库 [coolxll/lingma-ipc-proxy](https://github.com/coolxll/lingma-ipc-proxy)。上游项目的核心贡献是发现并验证了 Lingma 本地私有 IPC 协议可以被代理成标准 HTTP API,这是本项目 **IPC 插件模式** 的基础思路来源。
|
||||
|
||||
本项目在这个思路上继续扩展了:
|
||||
本项目在 IPC 插件模式上继续扩展了:
|
||||
|
||||
- 更完整的 OpenAI / Anthropic 参数兼容
|
||||
- Tools / Function Calling 模拟
|
||||
@@ -614,4 +616,4 @@ Release workflow 会执行:
|
||||
|
||||
## 致谢
|
||||
|
||||
本项目的协议实现思路参考并继承自 [coolxll/lingma-ipc-proxy](https://github.com/coolxll/lingma-ipc-proxy) 的协议发现工作。Lingma 私有本地 IPC 可以被转换为标准 OpenAI / Anthropic API 这一核心思想是该项目首先验证出来的;本项目在此基础上补充了更完整的协议兼容、工具调用、图片处理、桌面 App、请求 / 日志观测、跨平台打包和 release 自动化。
|
||||
本项目的 **IPC 插件模式** 参考并继承自 [coolxll/lingma-ipc-proxy](https://github.com/coolxll/lingma-ipc-proxy) 的协议发现工作。Lingma 私有本地 IPC 可以被转换为标准 OpenAI / Anthropic API 这一核心思想是该项目首先验证出来的;Lingma Proxy 保留这条 IPC 路径作为兼容后端,并补充了更完整的协议兼容、工具调用、图片处理、桌面 App、请求 / 日志观测、跨平台打包和 release 自动化。默认推荐的 **远端 API 模式** 是独立后端,直接调用 Lingma 远端 API,上文已单独说明。
|
||||
|
||||
@@ -57,7 +57,7 @@ func main() {
|
||||
|
||||
server := httpapi.NewServer(addr, svc)
|
||||
|
||||
log.Printf("lingma-ipc-proxy listening on http://%s", addr)
|
||||
log.Printf("lingma-proxy listening on http://%s", addr)
|
||||
log.Printf("session mode: %s", cfg.SessionMode)
|
||||
log.Printf("transport: %s", cfg.Transport)
|
||||
log.Printf("mode: %s", cfg.Mode)
|
||||
@@ -134,7 +134,7 @@ func loadConfig() (service.Config, string) {
|
||||
remoteFallbackEnabled := flag.Bool("remote-fallback", cfg.RemoteFallbackEnabled, "Enable remote timeout/5xx fallback to the next available model")
|
||||
remoteFallbackModels := flag.String("remote-fallback-models", strings.Join(cfg.RemoteFallbackModels, ","), "Comma-separated remote fallback model IDs")
|
||||
sessionMode := flag.String("session-mode", string(cfg.SessionMode), "Session mode: auto, fresh, reuse")
|
||||
config := flag.String("config", valueOr(configPath, filepath.Join(currentDir(), "lingma-ipc-proxy.json")), "Path to JSON config file")
|
||||
config := flag.String("config", valueOr(configPath, filepath.Join(currentDir(), "lingma-proxy.json")), "Path to JSON config file")
|
||||
flag.Parse()
|
||||
|
||||
parsedSessionMode := parseSessionMode(*sessionMode)
|
||||
@@ -176,9 +176,11 @@ func resolveConfigPath() (string, bool) {
|
||||
if path := strings.TrimSpace(os.Getenv("LINGMA_PROXY_CONFIG")); path != "" {
|
||||
return path, true
|
||||
}
|
||||
defaultPath := filepath.Join(currentDir(), "lingma-ipc-proxy.json")
|
||||
if info, err := os.Stat(defaultPath); err == nil && !info.IsDir() {
|
||||
return defaultPath, true
|
||||
defaultPath := filepath.Join(currentDir(), "lingma-proxy.json")
|
||||
for _, candidate := range []string{defaultPath, filepath.Join(currentDir(), "lingma-ipc-proxy.json")} {
|
||||
if info, err := os.Stat(candidate); err == nil && !info.IsDir() {
|
||||
return candidate, true
|
||||
}
|
||||
}
|
||||
return defaultPath, false
|
||||
}
|
||||
|
||||
@@ -198,6 +198,11 @@ func (a *App) QuitApp() {
|
||||
a.beginQuit()
|
||||
}
|
||||
|
||||
// ForceQuitApp stops the proxy and exits the desktop process immediately.
|
||||
func (a *App) ForceQuitApp() {
|
||||
a.beginQuit()
|
||||
}
|
||||
|
||||
// RequestQuitShortcut requires two shortcut presses to avoid accidental exits.
|
||||
func (a *App) RequestQuitShortcut() {
|
||||
now := time.Now()
|
||||
@@ -358,7 +363,7 @@ func (a *App) saveConfig(cfg service.Config) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dir := filepath.Join(home, ".config", "lingma-ipc-proxy")
|
||||
dir := filepath.Join(home, ".config", "lingma-proxy")
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1041,15 +1046,19 @@ func configSearchPaths() []string {
|
||||
var paths []string
|
||||
// 1. Executable directory (for dev / portable mode)
|
||||
if exe, err := os.Executable(); err == nil {
|
||||
paths = append(paths, filepath.Join(filepath.Dir(exe), "lingma-proxy.json"))
|
||||
paths = append(paths, filepath.Join(filepath.Dir(exe), "lingma-ipc-proxy.json"))
|
||||
}
|
||||
// 2. Current working directory
|
||||
if wd, err := os.Getwd(); err == nil {
|
||||
paths = append(paths, filepath.Join(wd, "lingma-proxy.json"))
|
||||
paths = append(paths, filepath.Join(wd, "lingma-ipc-proxy.json"))
|
||||
}
|
||||
// 3. User home directory
|
||||
if home, err := os.UserHomeDir(); err == nil {
|
||||
paths = append(paths, filepath.Join(home, "lingma-proxy.json"))
|
||||
paths = append(paths, filepath.Join(home, "lingma-ipc-proxy.json"))
|
||||
paths = append(paths, filepath.Join(home, ".config", "lingma-proxy", "config.json"))
|
||||
paths = append(paths, filepath.Join(home, ".config", "lingma-ipc-proxy", "config.json"))
|
||||
}
|
||||
return paths
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<link rel="icon" type="image/png" href="/favicon.png"/>
|
||||
<title>lingma-proxy-desktop</title>
|
||||
<title>Lingma Proxy</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -6,7 +6,7 @@ import Models from './views/Models.vue'
|
||||
import Requests from './views/Requests.vue'
|
||||
import Settings from './views/Settings.vue'
|
||||
import { EventsOff, EventsOn } from '../wailsjs/runtime'
|
||||
import { ClearLogs, GetLogs, GetStatus, HideWindow, MinimizeWindow } from '../wailsjs/go/main/App.js'
|
||||
import { ClearLogs, ForceQuitApp, GetLogs, GetStatus, HideWindow, MinimizeWindow } from '../wailsjs/go/main/App.js'
|
||||
import lingmaIcon from './assets/images/lingma-icon.png'
|
||||
|
||||
const currentTab = ref('dashboard')
|
||||
@@ -105,6 +105,17 @@ async function copyEndpoint() {
|
||||
handleNotice('已复制接口地址:' + value)
|
||||
}
|
||||
|
||||
async function forceQuitApp() {
|
||||
const confirmed = window.confirm('确定要停止代理并退出应用吗?')
|
||||
if (!confirmed) return
|
||||
showToast('正在停止代理并退出应用...')
|
||||
try {
|
||||
await ForceQuitApp()
|
||||
} catch (e) {
|
||||
addLog('error', '退出应用失败:' + (e.message || String(e)))
|
||||
}
|
||||
}
|
||||
|
||||
function safeEventsOn(name, handler) {
|
||||
try {
|
||||
EventsOn(name, handler)
|
||||
@@ -215,7 +226,7 @@ onUnmounted(() => {
|
||||
</span>
|
||||
<span>
|
||||
<strong>灵码代理</strong>
|
||||
<small>IPC Proxy</small>
|
||||
<small>Proxy</small>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -260,6 +271,9 @@ onUnmounted(() => {
|
||||
<button class="icon-button" type="button" :title="themeTitle()" @click="toggleTheme">
|
||||
<i class="bi" :class="themeIcon()" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button class="icon-button danger-icon-button" type="button" title="停止代理并退出应用" @click="forceQuitApp">
|
||||
<i class="bi bi-power" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -1289,6 +1289,17 @@ button {
|
||||
border: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.danger-icon-button {
|
||||
color: #b42318;
|
||||
background: rgba(254, 226, 226, 0.72);
|
||||
border-color: rgba(220, 38, 38, 0.24);
|
||||
}
|
||||
|
||||
.danger-icon-button:hover {
|
||||
color: #991b1b;
|
||||
background: rgba(254, 202, 202, 0.88);
|
||||
}
|
||||
|
||||
.primary-button:hover,
|
||||
.secondary-button:hover,
|
||||
.ghost-button:hover,
|
||||
@@ -1963,6 +1974,17 @@ button:disabled {
|
||||
background: rgba(30, 41, 59, 0.66);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .danger-icon-button {
|
||||
color: #fecaca;
|
||||
border-color: rgba(248, 113, 113, 0.32);
|
||||
background: rgba(127, 29, 29, 0.42);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .danger-icon-button:hover {
|
||||
color: #fff1f2;
|
||||
background: rgba(153, 27, 27, 0.62);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .strip-actions {
|
||||
background: rgba(15, 23, 42, 0.78);
|
||||
}
|
||||
|
||||
2
desktop/frontend/wailsjs/go/main/App.d.ts
vendored
2
desktop/frontend/wailsjs/go/main/App.d.ts
vendored
@@ -7,6 +7,8 @@ export function ClearLogs():Promise<void>;
|
||||
|
||||
export function ClearRequests():Promise<void>;
|
||||
|
||||
export function ForceQuitApp():Promise<void>;
|
||||
|
||||
export function GetConfig():Promise<service.Config>;
|
||||
|
||||
export function GetDetectionInfo():Promise<main.DetectionInfo>;
|
||||
|
||||
@@ -10,6 +10,10 @@ export function ClearRequests() {
|
||||
return window['go']['main']['App']['ClearRequests']();
|
||||
}
|
||||
|
||||
export function ForceQuitApp() {
|
||||
return window['go']['main']['App']['ForceQuitApp']();
|
||||
}
|
||||
|
||||
export function GetConfig() {
|
||||
return window['go']['main']['App']['GetConfig']();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ func main() {
|
||||
enableInspector := os.Getenv("LINGMA_DESKTOP_DEBUG") == "1"
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "Lingma IPC Proxy",
|
||||
Title: "Lingma Proxy",
|
||||
Width: 1100,
|
||||
Height: 750,
|
||||
MinWidth: 900,
|
||||
@@ -40,7 +40,7 @@ func main() {
|
||||
OnBeforeClose: app.beforeClose,
|
||||
OnDomReady: app.onDomReady,
|
||||
SingleInstanceLock: &options.SingleInstanceLock{
|
||||
UniqueId: "lingma-ipc-proxy-desktop",
|
||||
UniqueId: "lingma-proxy-desktop",
|
||||
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
@@ -57,8 +57,8 @@ func main() {
|
||||
HideToolbarSeparator: true,
|
||||
},
|
||||
About: &mac.AboutInfo{
|
||||
Title: "Lingma IPC Proxy",
|
||||
Message: "A desktop GUI for lingma-ipc-proxy",
|
||||
Title: "Lingma Proxy",
|
||||
Message: "A desktop GUI for Lingma Proxy",
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -86,7 +86,7 @@ func appMenu(app *App) *menu.Menu {
|
||||
app.MinimizeWindow()
|
||||
})
|
||||
appMenu.AddSeparator()
|
||||
appMenu.AddText("退出 Lingma IPC Proxy", quitAccelerator, func(_ *menu.CallbackData) {
|
||||
appMenu.AddText("退出 Lingma Proxy", quitAccelerator, func(_ *menu.CallbackData) {
|
||||
app.RequestQuitShortcut()
|
||||
})
|
||||
|
||||
@@ -100,7 +100,7 @@ func appMenu(app *App) *menu.Menu {
|
||||
editMenu.AddText("全选", keys.CmdOrCtrl("a"), func(_ *menu.CallbackData) {})
|
||||
|
||||
return menu.NewMenuFromItems(
|
||||
menu.SubMenu("Lingma IPC Proxy", appMenu),
|
||||
menu.SubMenu("Lingma Proxy", appMenu),
|
||||
menu.SubMenu("编辑", editMenu),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://wails.io/schemas/config.v2.json",
|
||||
"name": "Lingma IPC Proxy",
|
||||
"name": "Lingma Proxy",
|
||||
"outputfilename": "LingmaProxy",
|
||||
"frontend:install": "npm install",
|
||||
"frontend:build": "npm run build",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# lingma-ipc-proxy Architecture
|
||||
# Lingma Proxy Architecture
|
||||
|
||||
This document describes the current architecture of `lingma-ipc-proxy`, including both backend modes:
|
||||
This document describes the current architecture of **Lingma Proxy**, including both backend modes:
|
||||
|
||||
- `ipc`: bridge to the local Lingma IDE plugin transport
|
||||
- `remote`: call Lingma remote HTTP APIs directly with detected credentials
|
||||
- `remote`: the default and recommended mode, calling Lingma remote HTTP APIs directly with detected credentials
|
||||
- `ipc`: a compatibility mode that bridges to the local Lingma IDE plugin transport
|
||||
|
||||
---
|
||||
|
||||
@@ -35,7 +35,20 @@ flowchart LR
|
||||
|
||||
## 2. Runtime Modes
|
||||
|
||||
### 2.1 IPC mode
|
||||
### 2.1 Remote API mode
|
||||
|
||||
`backend=remote`
|
||||
|
||||
- Reads Lingma remote base URL from config, environment, or detected local Lingma logs
|
||||
- Loads credentials from:
|
||||
- explicit `remote_auth_file`
|
||||
- or detected Lingma login cache
|
||||
- Calls remote model list and chat endpoints directly
|
||||
- Supports timeout / 429 / 5xx fallback across available remote models
|
||||
- Does not use local plugin session environment knobs
|
||||
- Avoids IDE/plugin IPC session lifetime, working directory, and extension environment limitations
|
||||
|
||||
### 2.2 IPC plugin mode
|
||||
|
||||
`backend=ipc`
|
||||
|
||||
@@ -45,18 +58,7 @@ flowchart LR
|
||||
- Named Pipe on Windows
|
||||
- Reuses Lingma plugin session semantics
|
||||
- Session/environment options in the desktop UI apply only here
|
||||
|
||||
### 2.2 Remote API mode
|
||||
|
||||
`backend=remote`
|
||||
|
||||
- Reads Lingma remote base URL
|
||||
- Loads credentials from:
|
||||
- explicit `remote_auth_file`
|
||||
- or detected Lingma cache under `~/.lingma`
|
||||
- Calls remote model list and chat endpoints directly
|
||||
- Supports timeout / 429 / 5xx fallback across available remote models
|
||||
- Does not use local plugin session environment knobs
|
||||
- This mode is based on the IPC protocol insight from `coolxll/lingma-ipc-proxy`
|
||||
|
||||
---
|
||||
|
||||
@@ -261,7 +263,8 @@ Responsibilities:
|
||||
|
||||
Persisted local state:
|
||||
|
||||
- config: `~/.config/lingma-ipc-proxy/config.json`
|
||||
- config: `~/.config/lingma-proxy/config.json`
|
||||
- legacy config fallback: `~/.config/lingma-ipc-proxy/config.json`
|
||||
- UI/runtime state: `~/.config/lingma-ipc-proxy/app-state.json`
|
||||
|
||||
Production packaging rules:
|
||||
@@ -277,8 +280,8 @@ Production packaging rules:
|
||||
|
||||
Because the two modes solve different problems:
|
||||
|
||||
- IPC mode preserves plugin session semantics and local tool environment
|
||||
- Remote mode avoids plugin runtime coupling and is usually better for third-party agent clients
|
||||
- Remote mode avoids plugin runtime coupling and is usually better for third-party agent clients.
|
||||
- IPC mode preserves plugin session semantics and remains useful when the caller specifically wants the local plugin's context or model list.
|
||||
|
||||
### 7.2 Why keep tool emulation even with remote mode?
|
||||
|
||||
@@ -313,4 +316,4 @@ If you are extending the system, start here:
|
||||
|
||||
---
|
||||
|
||||
Document version: 2026-04-30
|
||||
Document version: 2026-05-06
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# lingma-ipc-proxy 架构文档
|
||||
# Lingma Proxy 架构文档
|
||||
|
||||
本文档描述 `lingma-ipc-proxy` 的当前架构,覆盖两种后端模式:
|
||||
本文档描述 **Lingma Proxy** 的当前架构,覆盖两种后端模式:
|
||||
|
||||
- `ipc`:桥接本地 Lingma IDE 插件传输层
|
||||
- `remote`:直接调用 Lingma 远端 HTTP API
|
||||
- `remote`:默认推荐模式,使用探测到的登录态直接调用 Lingma 远端 HTTP API
|
||||
- `ipc`:兼容模式,桥接本地 Lingma IDE 插件传输层
|
||||
|
||||
---
|
||||
|
||||
@@ -35,7 +35,20 @@ flowchart LR
|
||||
|
||||
## 2. 运行模式
|
||||
|
||||
### 2.1 IPC 模式
|
||||
### 2.1 Remote API 模式
|
||||
|
||||
`backend=remote`
|
||||
|
||||
- 从配置、环境变量或本地 Lingma 日志中解析远端域名
|
||||
- 加载认证信息:
|
||||
- 显式指定的 `remote_auth_file`
|
||||
- 或自动探测 Lingma 登录缓存
|
||||
- 直接请求远端模型列表和聊天接口
|
||||
- 支持远端超时 / 429 / 5xx 的模型兜底切换
|
||||
- 不依赖本地插件会话环境参数
|
||||
- 避免 IDE / 插件 IPC 会话生命周期、工作目录和扩展环境限制
|
||||
|
||||
### 2.2 IPC 插件模式
|
||||
|
||||
`backend=ipc`
|
||||
|
||||
@@ -45,18 +58,7 @@ flowchart LR
|
||||
- Windows:Named Pipe
|
||||
- 复用 Lingma 插件自身的 session 语义
|
||||
- 桌面端里“会话与环境”相关配置只在这里生效
|
||||
|
||||
### 2.2 Remote API 模式
|
||||
|
||||
`backend=remote`
|
||||
|
||||
- 解析远端域名
|
||||
- 加载认证信息:
|
||||
- 显式指定的 `remote_auth_file`
|
||||
- 或自动探测 `~/.lingma` 下的缓存
|
||||
- 直接请求远端模型列表和聊天接口
|
||||
- 支持远端超时 / 429 / 5xx 的模型兜底切换
|
||||
- 不依赖本地插件会话环境参数
|
||||
- 该模式基于 `coolxll/lingma-ipc-proxy` 的 IPC 协议发现思路
|
||||
|
||||
---
|
||||
|
||||
@@ -260,7 +262,8 @@ Wails 桌面端不是简单预览壳,而是本地代理的运维控制台。
|
||||
|
||||
本地持久化路径:
|
||||
|
||||
- 配置:`~/.config/lingma-ipc-proxy/config.json`
|
||||
- 配置:`~/.config/lingma-proxy/config.json`
|
||||
- 旧配置兼容读取:`~/.config/lingma-ipc-proxy/config.json`
|
||||
- GUI 运行状态:`~/.config/lingma-ipc-proxy/app-state.json`
|
||||
|
||||
打包要求:
|
||||
@@ -276,8 +279,8 @@ Wails 桌面端不是简单预览壳,而是本地代理的运维控制台。
|
||||
|
||||
因为两种模式解决的问题不同:
|
||||
|
||||
- IPC 模式更贴近插件本地上下文和 session 语义
|
||||
- Remote 模式更适合第三方 agent 客户端,减少对插件运行态的依赖
|
||||
- Remote 模式避免插件运行时耦合,通常更适合第三方 Agent 客户端。
|
||||
- IPC 模式保留插件会话语义,适合明确需要本地插件上下文或插件模型列表的场景。
|
||||
|
||||
### 7.2 为什么 Remote 也保留 Tool Emulation?
|
||||
|
||||
@@ -312,4 +315,4 @@ Wails 桌面端不是简单预览壳,而是本地代理的运维控制台。
|
||||
|
||||
---
|
||||
|
||||
文档版本:2026-04-30
|
||||
文档版本:2026-05-06
|
||||
|
||||
@@ -178,7 +178,7 @@ func (s *Server) handleRoot(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"ok": true,
|
||||
"service": "lingma-ipc-proxy",
|
||||
"service": "lingma-proxy",
|
||||
"state": s.svc.State(),
|
||||
})
|
||||
}
|
||||
@@ -214,7 +214,7 @@ func (s *Server) handleDebugRequests(w http.ResponseWriter, r *http.Request) {
|
||||
records := s.debugRecords(limit)
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"ok": true,
|
||||
"service": "lingma-ipc-proxy",
|
||||
"service": "lingma-proxy",
|
||||
"count": len(records),
|
||||
"requests": records,
|
||||
"state": s.svc.State(),
|
||||
@@ -265,7 +265,7 @@ func (s *Server) handleCapabilities(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"service": "lingma-ipc-proxy",
|
||||
"service": "lingma-proxy",
|
||||
"protocols": []string{
|
||||
"openai.chat_completions",
|
||||
"anthropic.messages",
|
||||
@@ -441,8 +441,8 @@ func (s *Server) handleVersion(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"version": "lingma-ipc-proxy",
|
||||
"service": "lingma-ipc-proxy",
|
||||
"version": "lingma-proxy",
|
||||
"service": "lingma-proxy",
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ func (c *Client) headers(cred Credential, path string, body string) (map[string]
|
||||
"Cosy-Machinetype": "",
|
||||
"Cosy-Version": c.cfg.CosyVersion,
|
||||
"Login-Version": "v2",
|
||||
"User-Agent": "lingma-ipc-proxy/remote",
|
||||
"User-Agent": "lingma-proxy/remote",
|
||||
"Accept": "text/event-stream",
|
||||
"Cache-Control": "no-cache",
|
||||
}, nil
|
||||
@@ -396,6 +396,7 @@ func candidateConfigFiles() []string {
|
||||
filepath.Join(home, ".lingma", "extension", "server", "config.json"),
|
||||
filepath.Join(home, ".lingma", "extension", "local", "config.json"),
|
||||
filepath.Join(home, ".lingma", "bin", "config.json"),
|
||||
filepath.Join(home, ".config", "lingma-proxy", "config.json"),
|
||||
filepath.Join(home, ".config", "lingma-ipc-proxy", "config.json"),
|
||||
filepath.Join(home, ".lingma", "logs", "lingma.log"),
|
||||
filepath.Join(home, ".lingma", "logs", "lingma-extension.log"),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
param(
|
||||
[string]$OutputDir = "dist",
|
||||
[string]$BinaryName = "lingma-ipc-proxy.exe",
|
||||
[string]$BinaryName = "lingma-proxy.exe",
|
||||
[switch]$Clean
|
||||
)
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
param(
|
||||
[string]$ServiceName = "LingmaIpcProxy",
|
||||
[string]$ServiceName = "LingmaProxy",
|
||||
[string]$BinaryPath = "",
|
||||
[string]$Arguments = "--host 127.0.0.1 --port 8095 --session-mode auto",
|
||||
[string]$WorkingDirectory = "",
|
||||
[string]$NssmPath = "nssm.exe",
|
||||
[string]$Description = "Lingma IPC proxy service"
|
||||
[string]$Description = "Lingma Proxy service"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -12,7 +12,7 @@ $ErrorActionPreference = "Stop"
|
||||
$repoRoot = Split-Path -Parent $PSScriptRoot
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($BinaryPath)) {
|
||||
$BinaryPath = Join-Path $repoRoot "dist\lingma-ipc-proxy.exe"
|
||||
$BinaryPath = Join-Path $repoRoot "dist\lingma-proxy.exe"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($WorkingDirectory)) {
|
||||
$WorkingDirectory = $repoRoot
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
param(
|
||||
[string]$ServiceName = "LingmaIpcProxy",
|
||||
[string]$ServiceName = "LingmaProxy",
|
||||
[string]$BinaryPath = "",
|
||||
[string]$Arguments = "--host 127.0.0.1 --port 8095 --session-mode auto",
|
||||
[string]$WorkingDirectory = "",
|
||||
@@ -12,7 +12,7 @@ $ErrorActionPreference = "Stop"
|
||||
$repoRoot = Split-Path -Parent $PSScriptRoot
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($BinaryPath)) {
|
||||
$BinaryPath = Join-Path $repoRoot "dist\lingma-ipc-proxy.exe"
|
||||
$BinaryPath = Join-Path $repoRoot "dist\lingma-proxy.exe"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($WorkingDirectory)) {
|
||||
$WorkingDirectory = $repoRoot
|
||||
@@ -21,7 +21,7 @@ if ([string]::IsNullOrWhiteSpace($WinSWExePath)) {
|
||||
$WinSWExePath = Join-Path $repoRoot "dist\WinSW-x64.exe"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($TemplatePath)) {
|
||||
$TemplatePath = Join-Path $PSScriptRoot "lingma-ipc-proxy.xml.template"
|
||||
$TemplatePath = Join-Path $PSScriptRoot "lingma-proxy.xml.template"
|
||||
}
|
||||
|
||||
if (!(Test-Path $BinaryPath)) {
|
||||
@@ -40,7 +40,7 @@ $serviceXmlPath = Join-Path $repoRoot "$ServiceName.xml"
|
||||
$xml = Get-Content -Raw $TemplatePath
|
||||
$xml = $xml.Replace("__SERVICE_ID__", $ServiceName)
|
||||
$xml = $xml.Replace("__SERVICE_NAME__", $ServiceName)
|
||||
$xml = $xml.Replace("__SERVICE_DESCRIPTION__", "Lingma IPC proxy service")
|
||||
$xml = $xml.Replace("__SERVICE_DESCRIPTION__", "Lingma Proxy service")
|
||||
$xml = $xml.Replace("__EXECUTABLE__", $BinaryPath)
|
||||
$xml = $xml.Replace("__ARGUMENTS__", $Arguments)
|
||||
$xml = $xml.Replace("__WORKDIR__", $WorkingDirectory)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
# lingma-ipc-proxy macOS 功能测试脚本
|
||||
# Lingma Proxy macOS 功能测试脚本
|
||||
# 用法: ./scripts/test-macos.sh [host:port]
|
||||
|
||||
ENDPOINT="${1:-127.0.0.1:8095}"
|
||||
@@ -23,7 +23,7 @@ assert_contains() {
|
||||
}
|
||||
|
||||
echo "========================================"
|
||||
echo "lingma-ipc-proxy macOS 功能测试"
|
||||
echo "Lingma Proxy macOS 功能测试"
|
||||
echo "端点: http://$ENDPOINT"
|
||||
echo "========================================"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user