Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/architecture/local-api-and-bridge.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Each family exposes the standard sub-paths clients expect: `/v1/chat/completions

**Agent-as-API (`local-agent`).** Turns a hosted coding agent itself into an OpenAI/Anthropic-compatible endpoint: requests become prompts to a real agent (with its tools and workspace), responses stream back in the requested dialect. This lets any OpenAI-compatible tool drive a full coding agent.

The primary profile bridge and agent-as-API families use separate daemon-lifetime credentials. A client configured with `local-api-auth.json` can call `/local-api` but cannot start an agent; agent-as-API clients use `local-agent-api-auth.json`.

## What happens to a request

1. **Decode** from the client dialect into the universal request.
Expand All @@ -54,7 +56,7 @@ Authentication to upstream providers is static API key per profile. OAuth/subscr

## Trust boundary

The bridge binds to the loopback interface and requires the local bridge auth gate; it is not reachable through tunnels. Request bodies up to 64 MB are accepted to accommodate large context payloads. Credentials never appear in rendered client configs — only local URLs do; the daemon injects real keys upstream.
The bridge binds to the loopback interface and requires the local bridge gate; the primary `/local-api` and `/local-agent` paths additionally require their scoped credentials. It is not reachable through tunnels. Request bodies up to 64 MB are accepted to accommodate large context payloads. Provider credentials never appear in rendered client configs; the daemon injects real keys upstream.

---

Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/security-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Share links are the only intentionally unauthenticated surface, scoped to one pr
## Credential handling

- Provider API keys are stored in the profile store under `~/.vibearound/` and injected into upstream requests **by the daemon**. Rendered agent configs contain only local bridge URLs — a leaked agent config exposes no provider key.
- The bridge and agent-as-API endpoints are loopback-only and sit behind a local-bridge gate; they are not reachable through tunnels.
- The bridge and agent-as-API endpoints are loopback-only and sit behind a local-bridge gate; they are not reachable through tunnels. The primary `/local-api` and `/local-agent` families have separate rotating scoped tokens, so a model bridge client cannot launch an agent.
- The daemon's own auth token file is plaintext in your home directory (same trust level as `~/.ssh`); treat backups accordingly.
- Bridge request/response recording for the launch popup is held in memory only and never written to disk.

Expand Down
3 changes: 2 additions & 1 deletion docs/guides/channels/slack.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Slack runs over Socket Mode — no public callback URL needed. The whole app def
"oauth_config": {
"scopes": {
"bot": [
"files:read", "app_mentions:read", "chat:write", "commands",
"files:read", "files:write", "app_mentions:read", "chat:write", "commands",
"im:history", "im:read", "im:write"
]
},
Expand Down Expand Up @@ -69,6 +69,7 @@ Required fields: `bot_token` (xoxb) and `app_token` (xapp).

- Slack reserves bare slash commands, so VibeAround commands use the `/va` prefix: `/va new`, `/va switch claude`, `/va status` ([command reference](../im-usage.md#command-reference) — every command works behind the prefix).
- Connection dies immediately? Check that Socket Mode is enabled and `app_token` is the `xapp-` token, not the bot token.
- Sending workspace files requires the bot scope `files:write`. After adding the scope, reinstall the Slack app so the existing bot token receives it.

---

Expand Down
4 changes: 3 additions & 1 deletion docs/internals/modules/auth.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Module: auth

`src/core/src/auth/` (current location) — credentials that gate server surfaces: the daemon token and short-lived pairing codes. Policy discussion: [security model](../../architecture/security-model.md).
`src/core/src/auth/` (current location) — credentials that gate server surfaces: the owner token, local API scoped tokens, and short-lived pairing codes. Policy discussion: [security model](../../architecture/security-model.md).

## Responsibility

Expand All @@ -12,6 +12,8 @@ Generate and persist the daemon auth token, and manage the pairing-code table th
|---|---|---|
| `AuthToken` | `token.rs` | Random per-daemon-start bearer token |
| `write_token_file` | `mod.rs` | Persists `{port, token}` to `~/.vibearound/auth.json` for out-of-process consumers (tray, CLI, desktop-ui) |
| `write_local_api_token_file` | `mod.rs` | Persists the credential accepted only by the profile-backed model bridge |
| `write_local_agent_api_token_file` | `mod.rs` | Persists the credential accepted only by the agent-as-API surface |
| `pair` | `pair.rs` | 6-digit codes, 60 s TTL, verified via a trusted surface; `validate(code)` returns the token on success |

## Interactions
Expand Down
9 changes: 6 additions & 3 deletions docs/reference/api-surfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Companion skills installed per agent (`skill_auto_install`): `vibearound` (hando

## Local API route families

Loopback-only, gated by the local-bridge check; bodies up to 64 MB. Mechanism: [Local API and bridge](../architecture/local-api-and-bridge.md).
Loopback-only and gated by the local-bridge check; the primary `/local-api` and `/local-agent` families also require their own credentials. Bodies up to 64 MB. Mechanism: [Local API and bridge](../architecture/local-api-and-bridge.md).

```text
/va/local-api/{profile}/{scope}/{api_type}/v1/{responses | chat/completions | messages | models}
Expand All @@ -32,18 +32,20 @@ Loopback-only, gated by the local-bridge check; bodies up to 64 MB. Mechanism: [

### Copy-paste examples

Local-bridge routes need **no Authorization header** — the gate is loopback peer + loopback Host (they are unreachable through tunnels). Substitute your profile id and a model id the profile exposes.
Set `LOCAL_API_KEY` to the `token` in `~/.vibearound/local-api-auth.json`, and `LOCAL_AGENT_API_KEY` to the `token` in `~/.vibearound/local-agent-api-auth.json`. Both rotate on daemon restart. The desktop Local API panel exposes the agent-as-API key for copying.

List the models a profile serves:

```bash
curl http://127.0.0.1:12358/va/local-api/moonshot/curl-test/openai-chat/v1/models
curl http://127.0.0.1:12358/va/local-api/moonshot/curl-test/openai-chat/v1/models \
-H "Authorization: Bearer $LOCAL_API_KEY"
```

Chat completion through the bridge (client speaks OpenAI Chat; the daemon translates to whatever the profile's provider speaks):

```bash
curl http://127.0.0.1:12358/va/local-api/moonshot/curl-test/openai-chat/v1/chat/completions \
-H "Authorization: Bearer $LOCAL_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"model": "kimi-k2.7-code", "messages": [{"role": "user", "content": "hello"}]}'
```
Expand All @@ -52,6 +54,7 @@ Agent-as-API — the same request shape, but executed by a hosted coding agent (

```bash
curl http://127.0.0.1:12358/va/local-agent/claude/direct/v1/chat/completions \
-H "Authorization: Bearer $LOCAL_AGENT_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"model": "claude", "messages": [{"role": "user", "content": "what does this repo do?"}]}'
```
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Everything lives under `~/.vibearound/` (override with `VIBEAROUND_DATA_DIR`):
| `agents.json` | desktop Launch UI, `va-launch` (executable discovery) | Per-agent launch preferences — [schema below](#agentsjson) | Yes, carefully |
| `launch/profiles/<name>.json` | you, desktop (temp materialized copies) | Saved native-launch profiles — [schema below](#launch-profile-json-schema-v1) | **Yes** (that is the point) |
| `auth.json` | daemon, every start | `{port, token}` for out-of-process clients | No — rewritten each start |
| `local-api-auth.json` | daemon, every start | Scoped `{port, token}` for profile-backed model bridge clients | No — rewritten each start |
| `local-agent-api-auth.json` | daemon, every start | Scoped `{port, token}` for agent-as-API clients | No — rewritten each start |
| `profiles/<profile-id>.json` | desktop/dashboard profile UI | Saved model profiles (provider, endpoint, key, model routes) | Prefer the UI; hand-edits are read on reload |
| `profile-state/<profile-id>/` | profile rendering | Rendered per-profile agent config files (settings overlays); env pointers reference these ([launch internals](../internals/launch.md#environment-assembly-layer-by-layer)) | No — regenerated per render |
| `plugins/<kind>/` | desktop plugin manager | Installed channel plugins + manifests | Only during plugin development |
Expand Down Expand Up @@ -160,6 +162,8 @@ Two "profile" concepts meet here and must not be confused: a **provider profile*
~/.vibearound/
├── settings.json # configuration (this page)
├── auth.json # dashboard token, rewritten each daemon start
├── local-api-auth.json # profile bridge token, rewritten each daemon start
├── local-agent-api-auth.json # agent-as-API token, rewritten each daemon start
├── agents.json # resolved agent executables (va-launch cache)
├── plugins/<kind>/ # installed channel plugins
├── launch/profiles/ # saved launch profile JSON (schema v1)
Expand Down
4 changes: 3 additions & 1 deletion docs/zh/architecture/local-api-and-bridge.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Bridge 把两者解耦。它在本地端点上接受**客户端**方言的请求

**Agent-as-API(`local-agent`)。** 把一个托管的编程 Agent 本身变成 OpenAI/Anthropic 兼容端点:请求变成发给真实 Agent(带工具和 Workspace)的提示,响应以所请求的方言流回。任何 OpenAI 兼容工具都能借此驱动一个完整的编程 Agent。

主路径 Profile Bridge 与 Agent-as-API 使用彼此独立、随守护进程轮换的凭证。拿到 `local-api-auth.json` 的客户端只能调用 `/local-api`,不能启动 Agent;Agent-as-API 客户端使用 `local-agent-api-auth.json`。

## 一个请求经历了什么

1. **解码**:从客户端方言解码为统一请求。
Expand All @@ -54,7 +56,7 @@ Bridge 把两者解耦。它在本地端点上接受**客户端**方言的请求

## 信任边界

Bridge 绑定回环接口,且要求本地 bridge 认证门;隧道无法触达它。请求体最大接受 64 MB,以容纳大上下文负载。凭据永远不出现在渲染给客户端的配置里 —— 里面只有本地 URL;真正的 key 由守护进程注入上游请求。
Bridge 绑定回环接口并要求本地 bridge 门禁;主路径 `/local-api` 和 `/local-agent` 还分别要求自己的 scoped credential。隧道无法触达它。请求体最大接受 64 MB,以容纳大上下文负载。供应商凭据不会出现在渲染给客户端的配置里;真正的 key 由守护进程注入上游请求。

---

Expand Down
2 changes: 1 addition & 1 deletion docs/zh/architecture/security-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ dev server 实时预览和 Markdown 渲染有两种 URL 形式:
## 凭据处理

- 供应商 API key 存在 `~/.vibearound/` 下的 Profile 存储里,**由守护进程**注入上游请求。渲染给 Agent 的配置只含本地 Bridge URL —— Agent 配置泄露不会暴露任何供应商 key。
- Bridge 和 agent-as-API 端点仅监听回环地址,且有本地 bridge 门;隧道无法触达。
- Bridge 和 agent-as-API 端点仅监听回环地址,且有本地 bridge 门;隧道无法触达。主路径 `/local-api` 和 `/local-agent` 各有独立、随守护进程轮换的 scoped token,因此模型 Bridge 客户端不能启动 Agent。
- 守护进程自己的 token 文件是家目录里的明文(信任级别等同 `~/.ssh`);备份时相应对待。
- 启动弹窗的 Bridge 请求/响应记录只在内存里,从不落盘。

Expand Down
3 changes: 2 additions & 1 deletion docs/zh/guides/channels/slack.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Slack 走 Socket Mode —— 不需要公网回调 URL。整个应用定义一
"oauth_config": {
"scopes": {
"bot": [
"files:read", "app_mentions:read", "chat:write", "commands",
"files:read", "files:write", "app_mentions:read", "chat:write", "commands",
"im:history", "im:read", "im:write"
]
},
Expand Down Expand Up @@ -69,6 +69,7 @@ Slack 走 Socket Mode —— 不需要公网回调 URL。整个应用定义一

- Slack 保留了裸的斜杠命令,所以 VibeAround 命令用 `/va` 前缀:`/va new`、`/va switch claude`、`/va status`([命令参考](../im-usage.md#命令参考) —— 每条命令都能加前缀使用)。
- 连接一建立就断?确认 Socket Mode 已启用,且 `app_token` 是 `xapp-` 开头的 token,不是 bot token。
- 发送 workspace 文件需要 bot scope `files:write`。添加 scope 后需重新安装 Slack App,现有 bot token 才会获得该权限。

---

Expand Down
4 changes: 3 additions & 1 deletion docs/zh/internals/modules/auth.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Module: auth

`src/core/src/auth/`(当前位置):server surfaces 使用的 daemon token 与短寿命 pairing codes。策略讨论见[安全模型](../../architecture/security-model.md)。
`src/core/src/auth/`(当前位置):server surfaces 使用的 owner token、本地 API scoped token 与短寿命 pairing codes。策略讨论见[安全模型](../../architecture/security-model.md)。

## 职责

Expand All @@ -12,6 +12,8 @@
|---|---|---|
| `AuthToken` | `token.rs` | 每次 daemon start 都随机生成的 bearer token |
| `write_token_file` | `mod.rs` | 把 `{port, token}` 持久化到 `~/.vibearound/auth.json`,供进程外消费者使用(tray、CLI、desktop-ui) |
| `write_local_api_token_file` | `mod.rs` | 持久化仅由 Profile 模型 Bridge 接受的凭据 |
| `write_local_agent_api_token_file` | `mod.rs` | 持久化仅由 Agent-as-API 接受的凭据 |
| `pair` | `pair.rs` | 6 位 codes,60 秒 TTL,通过 trusted surface 验证;`validate(code)` 成功时返回 token |

## 交互
Expand Down
9 changes: 6 additions & 3 deletions docs/zh/reference/api-surfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

## 本地 API 路由族

仅回环地址,由本地 bridge 检查把守;请求体最大 64 MB。机制见[本地 API 与 Bridge](../architecture/local-api-and-bridge.md)。
仅回环地址,并由本地 bridge 检查把守;主路径 `/local-api` 和 `/local-agent` 还分别要求自己的凭证。请求体最大 64 MB。机制见[本地 API 与 Bridge](../architecture/local-api-and-bridge.md)。

```text
/va/local-api/{profile}/{scope}/{api_type}/v1/{responses | chat/completions | messages | models}
Expand All @@ -32,18 +32,20 @@

### 可直接复制的示例

本地 bridge 路由**不需要 Authorization 头** —— 门禁是回环对端 + 回环 Host(隧道无法触达它们)。把 profile id 和模型 id 换成你的 Profile 暴露的值
把 `LOCAL_API_KEY` 设为 `~/.vibearound/local-api-auth.json` 中的 `token`,把 `LOCAL_AGENT_API_KEY` 设为 `~/.vibearound/local-agent-api-auth.json` 中的 `token`。两者都会在守护进程重启时轮换。桌面端的本地 API 面板也可直接复制 Agent-as-API key

列出某个 Profile 提供的模型:

```bash
curl http://127.0.0.1:12358/va/local-api/moonshot/curl-test/openai-chat/v1/models
curl http://127.0.0.1:12358/va/local-api/moonshot/curl-test/openai-chat/v1/models \
-H "Authorization: Bearer $LOCAL_API_KEY"
```

经 Bridge 的 chat completion(客户端说 OpenAI Chat;守护进程翻译成该 Profile 供应商说的方言):

```bash
curl http://127.0.0.1:12358/va/local-api/moonshot/curl-test/openai-chat/v1/chat/completions \
-H "Authorization: Bearer $LOCAL_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"model": "kimi-k2.7-code", "messages": [{"role": "user", "content": "hello"}]}'
```
Expand All @@ -52,6 +54,7 @@ Agent-as-API —— 同样的请求形状,但由托管的编程 Agent(带工

```bash
curl http://127.0.0.1:12358/va/local-agent/claude/direct/v1/chat/completions \
-H "Authorization: Bearer $LOCAL_AGENT_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"model": "claude", "messages": [{"role": "user", "content": "what does this repo do?"}]}'
```
Expand Down
4 changes: 4 additions & 0 deletions docs/zh/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ VibeAround 读写的每一个文件,可手动编辑的都附完整 schema。
| `agents.json` | 桌面 Launch UI、`va-launch`(可执行文件发现) | 按 Agent 的启动偏好 —— [schema 见下](#agentsjson) | 可以,小心改 |
| `launch/profiles/<name>.json` | 你、桌面(临时物化副本) | 保存的原生启动配置 —— [schema 见下](#launch-profile-json-schema-v1) | **可以**(本来就是给你编辑的) |
| `auth.json` | 守护进程,每次启动 | 供进程外客户端使用的 `{port, token}` | 不行 —— 每次启动重写 |
| `local-api-auth.json` | 守护进程,每次启动 | Profile 模型 Bridge 客户端专用的 `{port, token}` | 不行 —— 每次启动重写 |
| `local-agent-api-auth.json` | 守护进程,每次启动 | Agent-as-API 客户端专用的 `{port, token}` | 不行 —— 每次启动重写 |
| `profiles/<profile-id>.json` | 桌面/控制台 Profile UI | 保存的模型 Profile(供应商、端点、key、模型路由) | 优先用 UI;手动改动会在重载时读取 |
| `profile-state/<profile-id>/` | Profile 渲染 | 渲染出的按 Profile 的 Agent 配置文件(设置覆盖层);环境指针引用这些([启动内幕](../internals/launch.md#environment-assembly-layer-by-layer)) | 不行 —— 每次渲染重新生成 |
| `plugins/<kind>/` | 桌面插件管理器 | 已安装的渠道插件 + 清单 | 仅插件开发期间 |
Expand Down Expand Up @@ -160,6 +162,8 @@ VibeAround 还会写**每个已启用 Agent 自己的全局配置**(MCP server
~/.vibearound/
├── settings.json # 配置(本页)
├── auth.json # 控制台 token,每次守护进程启动重写
├── local-api-auth.json # Profile Bridge token,每次守护进程启动重写
├── local-agent-api-auth.json # Agent-as-API token,每次守护进程启动重写
├── agents.json # 解析出的 Agent 可执行文件(va-launch 缓存)
├── plugins/<kind>/ # 已安装的渠道插件
├── launch/profiles/ # 保存的启动配置 JSON(schema v1)
Expand Down
Loading