Skip to content

Latest commit

 

History

History
227 lines (170 loc) · 12 KB

tools.md

File metadata and controls

227 lines (170 loc) · 12 KB

Agent 工具参考

定位:十个 ssh_workspace_* 工具的用途、参数与返回。

这些工具都不复制文件能力:文件内容由 ctx.fs(SFTP)服务,read / write / edit 已经能在远端工作区工作;会话工作区为 ssh:// 时,pwsh / bash 工具的 命令也由本插件路由到远端执行,glob / grep 的 ripgrep 与工作区变更追踪的 git 同样(走 ctx.subprocess 接管)。工具补齐的是主机发现、挂载/卸载、状态, 以及不依赖挂载的远端命令执行。

ssh_workspace_hosts

列出可用主机:存储条目 + ~/.ssh/config 的具体 Host 块。

参数 必填 说明
query 否 大小写不敏感,匹配 alias / host / user / description / tags

返回 hosts[],每项含 alias、host、port、user、auth (key / password / agent)、keyReady、source(store / ssh-config)、 description、tags。

ssh_workspace_mount

把远端目录挂载为工作区。挂载前会先 stat 验证目录真实存在且是目录, 失败返回明确错误(no such directory on <alias>: <path>)。

参数 必填 说明
alias 是 来自 ssh_workspace_hosts
remotePath 是 远端绝对目录路径,如 /home/user/project
title 否 工作区显示名(默认取目录名)
register 否 是否同时登记为持久工作区(默认 true)

返回 ok、workspacePath(ssh:// 拼写,可直接用作会话工作区)、title、 registered、workspaceId、entryCount、error。 登记失败时仍挂载在进程内,error 给出登记失败的原因。

ssh_workspace_unmount

停用一个已挂载的远端目录。默认不删除任何东西:工作区记录保留(侧边栏那一行 仍在,置灰且按钮不可点),会话也保留不归档——记录还在,那个分组就还在,把会话藏起来 等于把用户特意保留的分组清空。

停用后该工作区内的所有操作都被拒绝——读文件、列目录、写、变更监视、执行命令、 开终端、跑 glob / grep / git、传输文件;SSH 连接本身保留(主机面板、 不带 cwd 的 ssh_workspace_exec、端口转发都照常可用)。

参数 必填 说明
workspacePath 是 ssh_workspace_mount 返回的 ssh:// 路径
mode 否 detach(默认,保留工作区记录)或 deregister(同时删除记录)
archiveSessions 否 是否归档会话。默认跟随模式:detach 为 false,deregister 为 true。显式传值优先

返回 ok、mode、wasMounted、deregistered、archived[](成功归档的会话 id)、 archiveFailed[{ sessionId, error }]、error。

两个模式的作用范围(这是最容易搞错的一点):

模式 工作区记录 侧栏那一行 面板「已停用」那一行 会话
detach(默认) 保留 保留,置灰且按钮不可点 保留,可「启用」 保留,不归档
deregister 删除 消失 消失 归档

「保留记录却不保留会话」是自相矛盾的:detach 留住侧栏那个分组,就是为了让用户还能 点开它;归档等于把分组内容清空——行还在,点开却是空的,比删掉更让人困惑。所以归档 跟随「删除记录」,而不是一个独立开关。

deregister 会同时清掉持久停用清单与运行时围栏两处标记。只删记录而不清 标记,会留下一个「面板里还挂着启用按钮、实际任何地方都不存在」的工作区,而这个 路径的运行时围栏又拒绝一切操作——用户无从恢复。forget 作为旧拼写被接受并归一化 为 deregister,两者不会各自漂移。

归档是逐个进行的,失败不中断:有正在跑回合 / 子智能体 / 后台任务的会话会被 registry 拒绝(这是它的文档化行为,本工具不传 stopActivity,因为卸载工作区不等于 要求中止正在进行的对话)。被拒的会话留在列表里,并逐条出现在 archiveFailed。

本工具没有「删除会话」选项。DSH 没有公开的会话删除 API,绕过服务层直接 unlink 会话日志会留下孤儿数据,所以归档是这里能给出的最强且可恢复的语义。

ssh_workspace_enable

把一个被停用的工作区重新挂载,并取消归档它的会话。这是 detach 的逆操作。

参数 必填 说明
workspacePath 是 之前停用的 ssh:// 路径
unarchiveSessions 否 是否取消归档会话(默认 true)

返回 ok、workspacePath、registered、unarchived[]、 unarchiveFailed[{ sessionId, error }]、error。

启用前会先 stat 验证远端目录仍然存在——否则会得到一个「看起来在服务、实际 ENOENT」的工作区。工作区记录若已被 deregister 模式删掉,会重新 createCanonical 建一条。

ssh_workspace_status

无参数。返回当前挂载点 mounted[]、已停用的工作区 disabled[]、活动连接 connections[{ alias, state, inFlight }](state 为 connected / broken)、 打开中的端口转发 forwards[]、持久会话 shells[{ alias, session, alive }], 以及 fsPatched(远端服务是否在役)。

mounted 与 disabled 是互斥的两个集合:停用会把路径从前者移到后者。

ssh_workspace_exec

在远端执行 shell 命令,不依赖工作区挂载:主机巡检、挂载前查看目录、 会话工作区之外的路径都走它(工作区内的日常命令直接用 pwsh / bash 工具, ssh:// workdir 已被路由到远端)。

每次调用是一个全新进程:cd、导出的变量、后台任务都不会保留。需要保留 状态时用 ssh_workspace_shell。

参数 必填 说明
alias 是 主机别名
command 是 远端 shell 命令
cwd 否 远端工作目录
timeoutMs 否 超时毫秒(默认 60000);run_in_background 时忽略
run_in_background 否 作为后台任务启动,立即返回 job id

返回 success、exitCode(整数或 null)、timedOut、stdout、stderr、 truncated、durationMs、error;后台模式下额外返回 jobId,用 job_output / job_kill 收集与终止。部署没有 ctx.jobs(或该 owner 无控制器) 时自动内联执行,不会返回无人能读的 id。

cwd 落在已停用的工作区内时调用被拒绝;不带 cwd(登录目录)或 cwd 在工作区 之外照常执行——这正是「停用工作区但保留 SSH 连接」的含义。

ssh_workspace_shell

在持久的远端 shell 里执行命令:同一 (主机, 会话名) 上维持一个 POSIX sh, cd、导出的变量与后台任务跨调用保留,等同于一直使用同一个终端。

远端 shell 固定是 POSIX sh,即使本机是 Windows 也请写 POSIX 语法。 部署自带的 persistent bash / pwsh 工具按本机方言构造命令行(Windows 上是 PowerShell),无法驱动远端主机,因此本插件单独提供这个工具而不是接管它们。

参数 必填 说明
alias 是 主机别名
command 否 POSIX shell 命令;close: true 时可省
session 否 会话名(默认 default),不同名字互不干扰
close 否 关闭该会话并释放,而不是执行命令
timeoutMs 否 等待命令结束的毫秒(默认 60000)

返回 ok、output、exitCode、session、reused(本次调用是否复用了已有 会话);关闭时返回 closed(关闭的会话数)。

退出码通过命令行末尾追加的标记行取回:PTY 没有独立退出通道,$? 被立即 捕获并随标记一起打印,因此输出里的标记行不会混进 output。

ssh_workspace_transfer

在本机与远端之间经 SFTP 双向拷贝文件,字节不经过对话内容。适合推送构建 产物、拉取日志;不用于编辑文件(挂载工作区里的 read / write / edit 已经 直接读写远端)。

参数 必填 说明
alias 是 主机别名
direction 是 upload(本机 → 远端)或 download(远端 → 本机)
localPath 是 本机绝对路径(上传的源 / 下载的目标)
remotePath 是 远端绝对路径(上传的目标 / 下载的源)
recursive 否 上传整个本地目录树(仅 upload)

返回 ok、bytes、files(递归时)、error。

上传先写同级暂存名再 rename 发布:目标文件在被替换之前,读到的始终是旧 内容或完整新内容,不会是半截文件。上传失败会清掉暂存文件并保留目标原内容。 下载读至 EOF 而非依赖 stat 时的长度,因此传输期间变长的文件会被完整取回。 单文件上限 1 GiB。

浏览器端另有 GET /download?alias=&path= 流式路由:文件选择对话框里每个文件行 有下载按钮,走这条路由把字节直接写进响应(不是 JSON),交给浏览器保存。它自行 施加回环来源与 Host 头双重校验,只接受 GET。

ssh_workspace_forward

把远端端口映射到本机(等价 ssh -L):远端 dev server 变成可打开的 http://localhost:<port>。映射骑在连接池里的 SSH 连接上,连接断开即自动关闭; 重复映射同一目标返回已有条目。注意远端应用可能有自己的 host / 回调白名单 (Vite 的 server.allowedHosts、Next 的 allowedDevOrigins、OAuth 的 redirect URI),需要一并放行 localhost。

参数 必填 说明
alias 是 主机别名
remotePort 是 远端端口
localPort 否 本地端口,默认同远端;被占用时自动另选,传 0 由系统分配
remoteHost 否 SSH 服务端拨号的目标(默认 127.0.0.1)
localHost 否 本地监听地址(默认 127.0.0.1,仅本机;0.0.0.0 暴露到局域网)

ssh_workspace_unforward

关闭一条端口转发并释放本地端口。

参数 必填 说明
id 是 来自 ssh_workspace_forward 或 ssh_workspace_status

通用约定

  • 路径一律使用 ssh:// 实际拼写(不含显示用的 @);
  • 错误语义与 ctx.fs 同一套(FS_* 码,另加远端专用的 FS_OUTSIDE_WORKSPACE), 写入围栏对工具触发的写同样生效;read-only 会话会拒绝远端 write / edit (FS_SANDBOX_DENIED),ssh_workspace_transfer 的上传同样是写入,也受该模式约束 (工具自己从会话解析 sandboxPolicy,因为它不经 ctx.fs);下载只读远端、写本机, 因此在 read-only 下照常可用;
  • 命令执行同样受模式约束:ssh_workspace_exec、ssh_workspace_shell 在 read-only 下直接拒绝(返回 success: false / ok: false,文案自述原因与出路),因为本机沙箱跨不过 SSH,没有可用的围栏手段。ssh_workspace_shell 的 close: true 不受限——关闭不改变远端任何东西。 这三处与 write / edit / 上传共用 lib/mode-gate.js 的判定,不会各自漂移;
  • glob / grep 在远端工作区调用远端主机的 ripgrep(需远端已安装 rg, 缺失时命令以退出码 127 失败并附安装提示);工作区变更追踪用远端 git (未安装时该功能自动降级,不阻断会话)。本地工作区不受影响。
  • 挂载时探测 rg / git / inotifywait,缺失项在挂载结果与面板里直接提示; 远端有 inotifywait 时变更监视走事件推送,否则回落到轮询。
  • 已停用的工作区对所有读写 / 命令 / 传输一律拒绝,错误信息会点名 "the remote workspace is detached";详见 unmount-modes.md。

相关