Skip to content
0WD0Public

About

No description, website, or topics provided.

Resources

Stars

6 stars

Watchers

0 watching

Forks

Repository files navigation

amp-local

在本地跑一个 amp(ampcode.com)服务端 —— 让官方 amp CLI 完全在本机工作:LLM 调用走你自己的 端点(CLIProxyAPI / ollama / vllm / one-api / opencode Zen Go / OpenAI / Anthropic …),线程、 项目、附件全部落在本地磁盘,不依赖云端。

定位:CLI 是 executor(在本地执行工具),服务端是 agent 大脑(跑 LLM、编排回合)。amp-local 替代后者。协议细节来自对 amp bundle 与真实 ampcode.com 流量的逆向,见 notes/protocol.md。

快速开始

# 1. 准备配置(默认读取 ~/.config/amp-local/config.json,可用 AMP_LOCAL_CONFIG 指定)
mkdir -p ~/.config/amp-local
cp config.example.json ~/.config/amp-local/config.json
$EDITOR ~/.config/amp-local/config.json

# 2. 启动
bun src/main.ts

# 3. 让 amp CLI 连到本地。未配置 users 时 key 任意;配置 users 后使用对应 apiKey
AMP_URL=http://127.0.0.1:9876 AMP_API_KEY=local amp -x "你好"

Web 前端(webapp)构建:cd web && bun install && bun run build(产物 web/build/, 服务器启动后直接访问 http://127.0.0.1:9876/)

依赖:Bun。bun install 安装依赖后即可运行。

兼容性基线:0.0.1787286307-ga0cd7a(0821)。普通 execute、Docker Orb、 MCP/Plugin/Skill repository 列表、Sites 明确拒绝路径及附件 resumable upload 已实测; 0821 的 actor/bridge 调用集合与 0820 相同,核心 WS/bare 无需改版。

架构

amp CLI (executor)  ──REST + WebSocket──▶  amp-local (agent 大脑)
   本地执行工具                            · LLM 适配器(多 provider / 多协议方言)
   文件/Shell/工具注册                      · 回合编排、工具调度(tool_lease)
                                           · 线程/项目/附件/标签/技能存储

两条通道:

  • REST(/api/internal、/api/thread-actors、/actors/*、附件、线程搜索、远程线程等)
  • WebSocket
    • threadActor:文本帧 JSON-RPC 2.0(心跳 ping→pong);CLI 的 executor 连接、工具结果回传、 回合消息流(delta / message_added / agent_state / tool_lease…)都走这里
    • userActor / runner:二进制 rivet bare 帧(client-protocol v4);侧边栏摘要、pin、runner 注册、 远程线程意图等

支持 runner(Agents Anywhere) 闭环:CLI 注册为 runner 后,/api/remote-thread 创建的远程线程 通过 runnerIntentsUpdated 事件推给对应 runner 自动执行。

配置(声明式)

所有配置在 ~/.config/amp-local/config.json(可用 AMP_LOCAL_CONFIG 指定),无需环境变量。结构:

{
  "port": 9876,                                // 监听端口(默认 9876;AMP_LOCAL_PORT 覆盖)
  "dataDir": "/home/you/.local/share/amp-local", // 数据目录(默认 ~/.local/share/amp-local;AMP_LOCAL_DATA_DIR 覆盖)
  "user": { "userId": "user_local", "username": "local" },
  "llm": {
    // 命名 provider,可多个;可互相引用(provider: "cliproxy" 之类)
    "providers": {
      "cliproxy": {
        "baseUrl": "http://127.0.0.1:8317/v1",
        "apiKey": "amp-local-dev"              // 明文密钥
      },
      "xai": {
        "baseUrl": "http://127.0.0.1:8000/v1",
        "apiKeyEnv": "XAI_API_KEY"             // 从环境变量读(推荐,密钥不落盘)
      },
      "opencode-go": {
        "baseUrl": "https://api.example-llm.com/v1",
        "apiKeyFile": "/home/you/.secrets/opencode.key",  // 从文件读
        "protocol": "completions"               // 协议方言覆盖(见下)
      }
    },
    // 全局默认 provider(model 为默认模型)
    "default": { "provider": "cliproxy", "model": "gpt-4o-mini" },
    // mode → provider + model 绑定(low/medium/high/ultra,任意 key 均可)
    "modes": {
      "low":    { "provider": "cliproxy", "model": "gpt-4o-mini" },
      "medium": {
        "provider": "cliproxy",
        "model": "gpt-4o",
        "models": ["gpt-4o", "gpt-4o-mini"]    // fallback 链(见下)
      },
      "high":   { "provider": "cliproxy", "model": "claude-3-5-sonnet" },
      "ultra":  { "provider": "cliproxy", "model": "claude-3-5-sonnet" }
    },
    // 全局协议方言(可被 provider/mode 级覆盖)
    "protocol": "responses"
  }
}

字段说明

字段 说明
port / dataDir / user 监听端口、数据目录、本机用户标识(userId 同时用作项目 namespace 前缀)
provider baseUrl LLM 端点,不带尾斜杠(如 http://127.0.0.1:8317/v1)
provider apiKey / apiKeyEnv / apiKeyFile 明文 / 环境变量名 / 文件路径(文件内容 trim 后使用);三选一,优先级 apiKey > apiKeyEnv > apiKeyFile。路径不做 ~ 展开,请写绝对路径
provider provider 引用另一个 provider,继承其 baseUrl/apiKey/protocol 后再覆盖
llm.default 全局默认 provider;model 为默认模型
llm.modes.<mode> 每个 mode 独立绑定;缺 provider/baseUrl 时走全局默认;model 支持 models 数组
mode models fallback 模型链:数组按序尝试,上游模型间歇不可用时自动降级(如 ["gpt-4o", "gpt-4o-mini"])
protocol 协议方言,见下

协议方言(responses / completions / anthropic)

值 端点 适用
responses(默认) /responses(OpenAI Responses API) CLIProxyAPI 默认;直连 OpenAI 原生
completions /chat/completions ollama / vllm / one-api / opencode Zen Go 等 OpenAI 兼容网关
anthropic /messages 直连 Anthropic(适配器可用,部分特性尚待完善)

环境变量覆盖(优先级高于配置文件)

变量 作用
AMP_LOCAL_CONFIG 配置文件路径(默认 ~/.config/amp-local/config.json)
AMP_LOCAL_PORT 端口
AMP_LOCAL_DATA_DIR 数据目录
AMP_LOCAL_LLM_BASE_URL / AMP_LOCAL_LLM_API_KEY / AMP_LOCAL_LLM_MODEL 全局默认 provider 的旧式覆盖
AMP_LOCAL_MODELS JSON 对象 {mode: model} 兼容旧写法(配置文件 modes 优先)

功能

  • 多 provider + 多模式绑定:low / medium / high / ultra 各自映射到 provider + 模型; CLI 切换 mode 即换模型
  • 协议方言适配:同一套 amp 消息块(text/thinking/tool_use/tool_result)自动转换为 responses / completions / anthropic 格式,各上游怪癖(completions 要求 tool 消息紧跟 assistant、 responses 的 item_id 关联、reasoning 回传等)隔离在适配器内部
  • 模型 fallback 链:models 数组按序降级
  • 线程全生命周期:创建/恢复/导入(/request/import)、归档、pin、重命名、标签、全文搜索、 编辑消息、重试、truncate、turn 串行队列、草稿
  • 项目注册表:projects.json 持久化;listAccessibleProjects / getProject / createProject / updateProject / deleteProject / resolveProjectByRepositoryURLs 等,支持 git remote 匹配
  • 服务器实现工具(直接进 LLM 工具集,不走本地 executor): read_thread create_thread thread_interact wait_for_threads get_schedule set_schedule update_schedule clear_schedule Task finder view_media librarian list_agent_modes list_runners get_current_user_identity
  • Skills:loadSkills 从 ~/.agents/skills、~/.config/agents/skills、~/.claude/skills 及 工作区 .agents/skills、.claude/skills 读取 SKILL.md,CLI 落盘后 skill 工具直接可用
  • 附件:普通 base64 上传(/api/attachments)和 0820+ 可恢复流式上传 (/api/attachments/resumable,最大 512 MiB)→ SHA-256 存盘 → 多级重定向下载; 0821 TUI 超出 4 张的图片会在后台复用此 resumable 通道 (/attachments → /user-content/attachments → /raw-attachments)
  • Runner / 远程线程(Agents Anywhere):registerRunner / runnerHeartbeat / /api/remote-thread / createRemoteExecutorThread 完整闭环
  • 插件生命周期:回合发 session.start / agent.start / agent.end 插件消息
  • 标题自动生成:无标题线程取首条用户消息截取 48 字
  • Web 前端(web/,SvelteKit 5):对齐 ampcode.com 的 webapp ——
    • 侧边栏线程列表 + 线程视图(WS 实时消息:thinking 折叠/富文本/工具调用)
    • Command Palette(Ctrl+K):命令面板(Global/Thread/Navigation 三组 40+ 命令, 输入过滤、Prompt 区可直接用文本建线程/搜索)+ 新建线程模式(Executor 选 New Orb 或本地 Runner、Project、Mode)+ 无匹配场景对齐真实
    • 快捷键:Ctrl+K 面板 / Ctrl+Shift+K 搜索 / Ctrl+/ Puck / Alt+Enter 新建 / Ctrl+M/J/S 新建表单(Executor/Project/Mode)
    • Projects 页(项目卡片 + New Project 对话框对齐真实)
    • 模块化架构(lib/ui + lib/thread 组件分层);服务器 serve 静态产物(SPA fallback)

数据存储(默认 ~/.local/share/amp-local/,遵循 XDG_DATA_HOME)

路径 内容
threads/<TID>.json 线程 + 全部消息(消息粒度持久化,中断/被杀不丢)
projects.json 项目注册表
attachments/ 附件(sha256 文件名 + .meta.json 元数据)

协议与端点速览

REST 端点(详见 notes/protocol.md):

端点 说明
POST /api/internal?<method> 核心方法网关:getUserInfo loadPlugins listAgentModes loadSkills archiveThread、项目/线程/标签/账单等(方法在 query 或 body.method)
POST /api/thread-actors 创建/复用线程,返回 {threadId, wsToken, ...}
POST /api/thread-actors/<id> 标记线程已导入
POST /api/user-actor-credentials userActor 凭据
POST /api/remote-thread 模拟 web 端远程创建线程(Agents Anywhere)
POST /api/attachments 附件上传
POST /api/attachments/resumable 0820+ 大媒体 prepare / signed PUT / complete,可恢复且不把文件整体读入内存
GET /api/threads/find?q= 线程全文搜索
GET /actors/metadata、GET /actors/actors rivet actor 解析/元数据
POST /gateway/…/request/import 线程数据导入
POST /gateway/…/action/<name> userActor HTTP action(rivet HTTP 通道)

WebSocket:

  • threadActor:JSON-RPC 2.0 文本帧;CLI→服务器 executor_connect executor_tools_register client_append_user_msg executor_tool_result 等;服务器→CLI 初始化序列 + delta / message_added / agent_state / tool_lease 等回合事件流
  • userActor:bare/cbor 二进制帧(Init / ActionRequest / Event);getRecentThreads、 setThreadPinned、registerRunner、runnerHeartbeat、订阅事件

认证:未配置 users 时接受任意 API key;配置 users 后仅接受对应 apiKey, WS 使用 /api/thread-actors 发放的 wsToken。本机默认可用 AMP_API_KEY=local。

开发

bun install       # 安装依赖(@rivetkit/bare-ts、cbor-x、vbare)
bun run typecheck # tsc --noEmit
bun src/main.ts   # 启动服务器

目录结构:

src/
  main.ts          # 入口:Bun HTTP + WebSocket
  config.ts        # 声明式配置 + 环境变量覆盖
  rest-api.ts      # HTTP 端点(fetch handler)
  ws-handler.ts    # threadActor 的 JSON-RPC 消息分发
  agent-loop.ts    # agent 回合循环 + turn 队列 + 标题生成
  llm.ts           # LLM 适配器层(blocks ↔ 各协议方言 + SSE 解析)
  server-tools.ts  # 服务器实现工具
  server-state.ts  # 共享状态 + rivet bare 帧编解码
  store.ts         # 线程本地存储
  projects.ts      # 项目注册表
  thread-format.ts # CLI 线程格式转换
  types.ts         # 协议类型定义
notes/
  protocol.md      # 协议规格(逆向自真实流量)
  server-tools.md  # 服务器工具实测格式
web/
  src/routes/          # SvelteKit 页面(layout/threads/[id]/projects)
  src/lib/             # 前端逻辑分层
    config.ts/types.ts # 配置 + 共享类型
    api.ts/ws.ts       # API 客户端 + threadActor WS 客户端
    commands.ts        # Command Palette 命令定义(对齐真实枚举)
    markdown.ts        # 富文本渲染 + 消息块提取
    ui/                # Sidebar / CommandPalette / NewThreadForm / ExecutorPicker
    thread/            # MessageList / MessageItem(WS 消息渲染)

已知局限

  • 未配置 users 时不校验 API key,仅适合本机或可信网络;团队部署应配置 users
  • anthropic 适配器可用但部分特性未完善;模型注册表(src/models.ts)为逆向数据,部分条目不完整
  • domains/sites/secrets/global repositories/account MCP 当前只提供真实空列表;云端管理写操作和 0821 新增的 createSite / updateSite 返回明确 not_supported
  • 未知 internal API 默认返回 not_supported,不会再用成功 {} 掩盖缺失实现并触发 CLI schema 崩溃
  • Gmail 服务、云 model-router 管理及 0821 list_schedules 尚未在 amp-local 实现
  • 单进程内存态会话(session),重启后线程从磁盘恢复

orb 沙箱(服务器端执行)

对齐 Amp 的 orb 架构:每线程一个沙箱执行器,amp --orb-execute -x "msg" 创建 orb 线程后, 服务器在沙箱工作区启动 amp --headless=<threadId>(agent-headless)作为该线程的 executor, CLI 以 observer 连接查看结果。工具在沙箱执行器上运行(不是用户本地 CLI)。

配置(~/.config/amp-local/config.json):

{
  "orb": {
    "enabled": true,
    "executor": "docker",
    "dockerImage": "amp-agent:latest",
    "ampDir": "",
    "workspaceDir": "~/.local/share/amp-local/sandboxes"
  }
}

执行器后端(orb.executor):

  • local(P0):服务器本地子进程沙箱,无隔离(单机验证)
  • docker(P1):每线程一个容器(进程/文件隔离,团队化基础)

Docker 模式要点:

  • 镜像:docker build -f docker/agent.Dockerfile -t amp-agent:latest .(全部组件从官方渠道安装, 零本机文件 COPY,可分享;固定版本 --build-arg AMP_VERSION=<version>; amp=static.ampcode.com / websocat=github.com/vi/websocat / base=debian:bookworm-slim)
  • docker 模式:镜像内装官方 amp CLI(amp --headless=<tid> 运行),无需宿主的 amp bundle; 升级 amp 版本 = 重建镜像(--build-arg AMP_VERSION)
  • local 模式(宿主子进程):orb.spawnCommand 可配 ["amp"](官方 CLI)或 bun 方式
  • 工作区 sandboxes/<threadId> bind mount 到容器 /workspace(双向可见,容器删除文件保留)
  • bridge 网络 + 动态端口映射(多容器并发):容器内 sshd 固定 2222,宿主端口按容器分配(2200-2299)
  • headless 通过 host.docker.internal 连服务器(--add-host)
  • 容器 root + 定向 drop 危险能力(NET_RAW/NET_ADMIN/SYS_ADMIN/SYS_PTRACE/SYS_MODULE/MKNOD/SETPCAP/SYS_BOOT/SYS_TIME)+ no-new-privileges(保留 sshd 所需 DAC/SETGID/SETUID/SYS_CHROOT)
  • 资源限制:--memory 2g --cpus 2 --pids-limit 256;--restart unless-stopped(服务器重启自恢复)
  • 自动暂停/恢复(对齐 amp 官方:15 分钟无活动自动暂停,活动到达立即恢复,归档立即暂停):
    • 暂停 = docker stop(保留容器与文件系统状态,快速唤醒,不占资源)
    • 恢复 = docker start + 跑工作区 .agents/resume hook(最多等 10s,官方语义)
    • 空闲超时可用 AMP_LOCAL_ORB_IDLE_MINUTES 调整(默认 15)
  • 创建时 .agents/setup hook(对齐官方:从 repo root 跑一次准备依赖;共享工作区用标记文件只跑一次)
  • gh 认证注入(对齐官方 "Authenticated gh"):从宿主 GH_TOKEN 环境变量或 ~/.config/gh/hosts.yml 读 token → docker run -e GH_TOKEN + 容器内 gh auth setup-git(私有仓库可 clone)
  • 工具层对齐官方 orb 预装清单:git/ssh/tmux/vim/less/procps/iproute2/net-tools/busybox/python3 + ffmpeg/ImageMagick/jq/fzf/unzip/zstd/lsof/ripgrep + gh(认证注入见上)+ node 24/npm + pnpm/yarn
    • 暂未预装(此网络环境 GitHub 下载过慢):Bun、agent-browser(91MB)——需要时容器内 npm i -g bun / npm i -g agent-browser;--network 注意:构建镜像时容器 IPv6 不通, 相关 curl 已加 -4、npm 用 NODE_OPTIONS=--dns-result-order=ipv4first
  • 服务器启动时自动清理孤儿容器(线程已归档的残留)

项目工作区隔离

  • 线程关联项目(--orb-execute --project <namespace/name | id | repositoryURL>)→ 工作区 = sandboxes/<projectKey>/(同项目线程共享工作区,像多个 agent 在同一 git checkout 上工作)
  • 无项目线程 → sandboxes/<threadId>/(按线程隔离,默认)
  • 项目创建:amp projects create --repository <git-url>(或 /api/internal?createProject)

SSH 终端(沙箱调试)

  • 容器内 sshd 固定 2222(bridge 网络),宿主端口动态分配(2200-2299,每容器独立)
  • 使用:ssh -p <动态端口> user@<服务器-IP>(端口见服务器日志或 listOrbSandboxes API;Tailscale 下为 tailnet IP)
  • user 免密 sudo;容器内 /workspace 即项目工作区(bind mount)
  • 待办:websocat(WebSocket→SSH 隧道,供 web/TUI 终端,orb-repro 模式)

portal(dev server 暴露)

  • devPortalTunnelEnsure{threadID, childPort} → {"url":"http://<容器IP>:<childPort>"}(bridge 网络)
  • 宿主可直连容器 IP(单机场景);团队成员(远程)访问需后续 TCP 代理(服务器端口转发)
  • 待办:服务器 TCP 代理(宿主端口 → 容器 IP:devPort)

Fast Mode(对齐 0805a:Alt+R speed.toggleFast,与 effort 无关)

  • 真实语义(逆向 amp.js hW() + pi-openai-fast-mode 同源):fast = GPT 模型的 service_tier: "priority"(OpenAI 优先级服务层);仅 openai provider + gpt- 前缀模型支持
  • 链路:CLI Alt+R → client_update_thread_feature {feature:"fast", enabled} → 线程 features 持久化 → agent 回合 LLM 调用注入 service_tier: "priority"(模型名 gpt- 前缀才生效)
  • 线程 features 随 getSession 加载、thread_features 推送、重启保留

专用角色模型(oracle/librarian)

  • 真实 amp:oracle 用独立的 second-opinion 前沿模型(manual:"the second opinion always comes from a different frontier model")
  • 本地配置 llm.oracle / llm.librarian(provider/model,与 modes 同格式);未配置回退: oracle → high mode、librarian → medium mode
  • reasoningEffort 可配置(所有 mode + oracle/librarian):"reasoningEffort": "low|medium|high" (OpenAI responses 透传 reasoning.effort,chat 透传 reasoning_effort)
  • 例:
    "llm": {
      "oracle": { "provider": "xai", "model": "gpt-5.6-sol", "reasoningEffort": "high" },
      "librarian": { "provider": "cliproxy", "model": "gpt-4o-mini" }
    }

Schedules(定时唤醒,对齐官方 "agents can set their own schedules")

  • 工具:set_schedule(RRULE + prompt)/get_schedule/update_schedule/clear_schedule(agent 侧)
  • 触发:服务器每分钟检查,到点把 prompt 作为用户消息 append 到线程 + 唤醒 orb(agent 接管执行)
  • RRULE 解析用 rrule npm 包;DTSTART;TZID=... 时区正确换算(北京 9:00 → UTC 01:00)

多用户 API key(团队化)

配置 users 即开启鉴权(不配则保持不校验,单机模式):

{
  "serverApiKey": "key-server-000",
  "users": [
    { "userId": "alice", "username": "alice", "apiKey": "key-alice-xxx" },
    { "userId": "bob", "username": "bob", "apiKey": "key-bob-yyy" }
  ]
}
  • serverApiKey:服务器自身身份(orb 沙箱 headless 执行器用;必须配,否则沙箱 401)
  • 团队成员:AMP_URL=http://<服务器>:9876 AMP_API_KEY=<自己的key> amp -x "..."
  • 错误/缺失 key → 401(CLI 报 "Invalid or missing API key")

凭证通道(对齐真实 CLI):

通道 用途
Authorization: Bearer <key> 用户 REST 请求(getUserInfo/thread-actors 等)
x-rivet-token: <wsToken> actor 请求(CLI 用 thread-actors 发放的 wsToken)
WS subprotocol rivet_conn_params WS 握手(wsToken;headless 执行器用 apiKey 字段)
/actors/metadata 豁免鉴权(actor 发现,CLI 无凭证调用)

协议层(rivet 官方编解码)

src/rivet/ = 复制自 npm rivetkit@2.3.10 的官方生成文件(勿手改):

  • client-protocol/v1-v4.ts + client-protocol-versioned.ts(vbare 版本化封装)
  • 帧 = u16 LE 版本(4) + bare body,与上游 engine 逐字节同源
  • 升级协议版本:替换生成文件 + 补转换链即可

About

No description, website, or topics provided.

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages