* feat(hosts): connect to saved hosts through a daemon * fix(hosts): validate safe targets and verify encrypted relay routes * test(hosts): include relay coverage in existing CI contracts * fix(cli): preserve validated addresses in daemon command hints * fix(hosts): share daemon links across isolated routed sessions Multiplex logical sessions over the monitored daemon connection and wrap original binary bytes in routing headers. Admit channels under their authenticated parent and current grants; preserve scoped delivery and physical send completion. * fix(hosts): bound encrypted overload and initial acquisition Check encrypted wire capacity before the async channel converts a resource limit into a physical connection error. Bound initial routed acquisition with the existing client timeout, then enable reconnect after admission. * fix(hosts): keep compact row actions clear of host labels Give compact connected-host rows separate text and action widths so long names and producer labels cannot compete with primary controls. * refactor(hosts): remove management settings UI from phase one Keep connected-host management in the CLI and shared SDK while preserving app saved connections and plugin access. * test(hosts): control physical write backpressure across platforms Hold real TCP writes until assertions finish instead of assuming a paused receiver exhausts every platform receive buffer. Preserve physical send settlement, byte identity, capacity and sibling checks. * refactor(hosts): use the ordinary client contract over channel transports Keep queuing, permission codes and reconnection independent of transport selection. Track submitted request outcomes generically while retaining connection error codes and structured causes. * test(e2e): keep transient developer toasts from stalling checks Concurrent locator handlers can wait for a dismiss button another handler removed. Dismiss existing toast DOM at document lifetime, including its open shadow root, without intercepting app actions. * Create, prompt, and monitor agents across connected hosts (#7507) * feat(hosts): delegate agents across connected hosts Resolve MCP host operations through in-process commands for self and the existing routed client transport for other destinations. Keep ordinary parent labels, app sessions and idle finish notifications. * test(app): normalize subagent fixtures through snapshots * docs(protocol): clarify same-host parent labels * fix(hosts): resolve subagents through destination sessions A child address identifies its destination regardless of the connection used. Reuse the existing host candidate selection for discovered routes and direct connections, and keep navigation and row actions independent of the parent transport. * fix(hosts): keep routed destinations distinct during discovery A routed candidate names only the origin daemon. Match it within the named destination profile so two destinations discovered through the same origin retain separate identities and connections, including existing saved routes. * feat(hosts): prompt and query agents on selected hosts Extend the existing MCP host operation boundary with prompt, status, activity and list operations. Local calls retain their handlers and notification owner; selected destinations use ordinary client RPCs and the existing idle finish wait. * test(e2e): preserve toast coverage with CSS hiding * docs(hosts): translate connected host references
25 KiB
title, description, nav
| title | description | nav |
|---|---|---|
| SDK API 参考 | @getpaseo/client 的公开配置、方法、句柄、结果、默认值和生命周期行为。 | API 参考 |
SDK API 参考
所有受支持的运行时值和 TypeScript 类型都从 @getpaseo/client 导入。
createPaseoClient(config)
创建一个客户端,但不打开连接。
必填配置:
| 字段 | 类型 | 含义 |
|---|---|---|
url |
string |
daemon 的 WebSocket 端点,包含 /ws。 |
常用的可选配置:
| 字段 | 类型 | 默认值 | 含义 |
|---|---|---|---|
clientId |
string |
自动生成 | 用于日志和订阅的稳定标识符。 |
password |
string |
未设置 | daemon 密码。 |
authHeader |
string |
未设置 | 用于代理的完整 Authorization 请求头的值。 |
connectTimeoutMs |
number |
客户端默认值 | 连接截止时间。 |
reconnect.enabled |
boolean |
客户端默认值 | 意外断开后重新连接。 |
reconnect.baseDelayMs |
number |
客户端默认值 | 首次重连的延迟。 |
reconnect.maxDelayMs |
number |
客户端默认值 | 重连的最大延迟。 |
logger |
PaseoLogger |
未设置 | 接收 debug、info、warning 和 error 日志。 |
使用中继端到端加密的客户端还可以传入 e2ee.enabled 和 e2ee.daemonPublicKeyB64。appVersion、runtimeGeneration 和运行时指标选项供 Paseo 自己的客户端界面使用;普通集成可以省略它们。
客户端生命周期
| 方法 | 结果 | 行为 |
|---|---|---|
connect() |
Promise<void> |
在 daemon 发送其服务器信息后 resolve。 |
close() |
Promise<void> |
关闭连接并释放此客户端。 |
ensureConnected() |
void |
除非客户端已连接,否则抛出错误。 |
getConnectionState() |
ConnectionState |
返回 idle、connecting、connected、disconnected 或 disposed。 |
调用 close() 后请创建新的客户端。
client.agents
| 方法 | 结果 | 行为 |
|---|---|---|
list(options?) |
PaseoAgentListResult |
列出一页 Agent。scope、filter、sort、page 和 subscribe 与 daemon 目录查询一致。 |
create(options) |
PaseoAgentHandle |
为 cwd 创建一个 Agent 和一个新的工作区。需要 config。 |
ref(agentOrId) |
PaseoAgentHandle |
创建一个本地句柄,不发起请求。 |
subscribe(handler) |
取消订阅函数 | 此 API 实例的本地监听器。需要一个由你持有的 list({ subscribe: {} }) 观察。 |
list({ subscribe: {} }) 还会返回一个 subscriptionId 和一个由你持有的 subscription。它的 subscribe({ snapshot, update, error? }) 回调会先收到快照,再收到限定范围的线上更新;release() 结束这次观察。支持该能力的 daemon 会分配 ID,并让各个观察相互独立。较旧的 daemon 使用本地 ID 及其既有的共享投递行为。普通的列表调用不会创建观察。工作区列表遵循同样的契约。见事件。
创建选项包括 config、cwd、parent、title、prompt、env、outputSchema、images、attachments、git、worktree、autoArchive、background 和 labels。
parent 接受主机本地的 Agent ID、AgentAddress({ serverId, agentId })或 Agent 句柄。句柄的 address 在断开连接后仍保留其主机身份。通过 hosts.client(serverId) 创建时,请传入父 Agent 句柄或完整地址;SDK 会把父级元数据带到目标主机。
background 表示创建工作区的意图。它不能与已有的 workspaceId 一起使用。调用方继承规则和包含后台的发现方式见后台工作区。
config 接受:
| 字段 | 类型 | 含义 |
|---|---|---|
provider |
string |
必填的 provider/model 选择。 |
modeId |
string |
Provider 的运行模式或权限模式。 |
thinkingOptionId |
string |
Provider 的推理级别。 |
featureValues |
Record<string, unknown> |
通过 providers.listFeatures 发现的功能的取值。 |
options |
JSON 对象 | Provider 原生设置,严格校验。见 Provider 选项。 |
systemPrompt |
string |
额外的系统或开发者指令。 |
mcpServers |
MCP 服务器映射 | 作用于会话的 MCP 服务器。 |
toolPolicy |
MCP 工具策略 | MCP 工具的精确预批准规则。 |
Agent 句柄
| 成员 | 结果 | 行为 |
|---|---|---|
id |
string |
稳定的 daemon Agent ID。 |
address |
AgentAddress |
完整的 { serverId, agentId } 身份;需要连接到主机才能确定。 |
workspaceId |
string | null |
当前所在的工作区。 |
cwd |
string | null |
当前工作目录。 |
status |
Agent 状态或 null |
当前的生命周期状态。 |
capabilities |
能力标志或 null |
Provider 会话支持的能力。 |
availableModes |
Agent 模式或 null |
会话可以切换到的模式。 |
pendingPermissions |
权限请求或 null |
等待回应的请求。 |
activeTurn |
当前轮次或 null |
正在进行的轮次,包含 turnId 和 startedAt。 |
lastUsage |
用量或 null |
上一轮的 token 数、费用和上下文窗口用量。 |
lastError |
string | null |
daemon 为该 Agent 记录的最后一个错误。 |
features |
Agent 功能或 null |
Provider 的功能开关和选择项及其当前值。 |
runtimeInfo |
运行时信息或 null |
实时的 Provider、会话 ID、模型、思考选项和模式。 |
archivedAt |
string | null |
归档时间戳;Agent 处于活动状态时为 null。 |
current() |
PaseoAgent | null |
此句柄观察到的当前详细值;从不发起请求。 |
refresh(requestId?) |
PaseoAgentRefetchResult | null |
获取当前的 Agent 及其所在项目。 |
send(text, options?) |
Promise<void> |
在 daemon 接受提示词后 resolve。 |
respondToPermission(options) |
Promise<void> |
按 requestId 以允许或拒绝的 response 回应一个待处理的权限请求。 |
run(text, options?) |
PaseoAgentRunResult |
发送提示词并等待该轮结束。timeoutMs 控制等待时间,默认 10 分钟。 |
waitForFinish(timeoutMs?) |
PaseoAgentRunResult |
等待当前轮次结束,包括初始提示词。默认超时:10 分钟。 |
commands(options?) |
PaseoAgentCommandsResult |
向正在运行的会话查询它的斜杠命令和技能,包括内置的。选项:requestId。 |
subscribe(handler) |
取消订阅函数 | 把 Agent 目录更新过滤到此 ID,并刷新句柄的属性。 |
archive() |
{ archivedAt } |
软删除 Agent 并关闭它的运行时。 |
detach() |
Promise<void> |
解除父子关系,但不停止 Agent。 |
从 workspaceId 到 archivedAt 的属性反映句柄最近观察到的快照。由 ref() 得到的句柄在 refresh()、run()、waitForFinish()、时间线重新获取或 subscribe() 投递快照之前,这些属性都读作 null。已观察到的快照中的可选值也读作 null。当你需要整个快照,或需要区分这些状态时,请调用 current()。
PaseoAgentRunResult 包含 status、final、error 和 lastMessage。存在 final 时会刷新句柄。
PaseoAgentCommandsResult 包含 agentId、commands 和 error。每条命令都有 name、description、argumentHint,以及取值为 "command" 或 "skill" 的可选 kind。无法回答的 Provider 会在 error 中报告,而不是 reject;完全不提供命令列表的 Provider 返回空数组。
时间线句柄
agent.timeline.refetch(options?) 获取一页时间线。选项有 direction、cursor、limit、projection 和 requestId。
agent.timeline.subscribe(handler) 为该 Agent 建立网络订阅需求,并在重连后恢复它。它返回的取消订阅函数会释放这项需求;开始工作之前,请 await unsubscribe.ready 以等待 daemon 的初始确认。投递只包含实时内容。重连时会发出一个本地的 subscription_restored 事件;错过的历史请用 refetch() 显式请求。实时的替换会使之前的 epoch 失效。回调的形状、分页和失败行为见时间线事件。
client.projects
| 方法 | 结果 | 行为 |
|---|---|---|
list(options?) |
PaseoProjectListResult |
列出每个已注册的项目,包括没有活动工作区的项目。 |
subscribe(handler) |
取消订阅函数 | 请求之后的项目更新;取消订阅会释放这项需求。初始状态由 list() 提供。 |
显式的事件观察和清理见事件。
client.workspaces
| 方法 | 结果 | 行为 |
|---|---|---|
list(options?) |
PaseoWorkspaceListResult |
列出、过滤、分页或订阅工作区目录。 |
open(cwd) |
PaseoWorkspaceHandle |
复用某个目录的活动工作区,或创建一个。 |
create(options) |
PaseoWorkspaceHandle |
总是创建一个新的、由目录或 Paseo worktree 支撑的工作区。background: true 会把它从默认的发现结果中隐藏。 |
ref(workspaceOrId) |
PaseoWorkspaceHandle |
创建一个本地句柄。 |
archive(workspaceOrId) |
PaseoWorkspaceArchiveResult |
无需先创建句柄即可归档。 |
subscribe(handler) |
取消订阅函数 | 此 API 实例的本地监听器。需要一个由你持有的 list({ subscribe: {} }) 观察。 |
create({ source, agent, background }) 会同时创建一个工作区及其初始 Agent。agent 接受除 worktree、git、onEvent、idempotencyKey 和 requestId 之外的 Agent 创建选项。请在工作区选项上设置 background;agent.background 会被拒绝。见一次性创建的示例。
工作区句柄提供 id、projectId、directory、name、status、current()、refresh()、setTitle(title)、archive() 和 subscribe()。向 setTitle 传入 null 会恢复推导出的工作区名称。使用 workspace.agents.create(options) 创建 Agent,无需重复提供工作区 ID 或目录。
client.terminals
终端操作需要一个支持工作区终端的主机。较旧的主机不会收到任何终端请求;SDK 会抛出一个要求更新主机的错误。
| 方法 | 结果 | 行为 |
|---|---|---|
create(options) |
Promise<PaseoTerminalHandle> |
创建一个归必填的 workspaceId 所有的终端。 |
list(options?) |
Promise<PaseoTerminalListResult> |
返回 { entries, requestId }。省略过滤条件时列出此主机上的所有终端。 |
ref(terminalOrId) |
PaseoTerminalHandle |
创建一个本地句柄,不发起请求,也不附加终端流。 |
创建选项:
| 字段 | 含义 |
|---|---|
workspaceId |
必填的活动工作区 ID。未知或已归档的 ID 会失败。 |
cwd |
可选的进程绝对工作目录。默认为工作区目录;修改它不会改变所有权。 |
name |
可选的终端名称。 |
command、args |
可选的可执行文件和参数数组。省略时启动默认 shell。 |
size |
可选的初始视口:{ rows, cols }。 |
requestId |
可选的请求关联 ID。 |
列表选项有 workspaceId、cwd 和 requestId。workspaceId 按所有权筛选,包括在工作区目录之外启动的终端。提供它时,cwd 不会限制结果。没有 ID 时,cwd 按工作区根目录过滤。每个条目包含 id、workspaceId、cwd 和 name;cwd 是终端实际的起始目录。
终端句柄提供:
| 方法 | 结果 | 行为 |
|---|---|---|
current() |
PaseoTerminal | null |
来自创建、ref(snapshot) 或刷新的最近快照。由 ID 创建的句柄起初为空。 |
refresh(options?) |
Promise<PaseoTerminal | null> |
获取终端快照;终端已不存在时返回 null。接受 requestId。 |
write(data) |
number |
发送字面文本,不解释按键名称。返回输入的 UTF-16 长度。 |
sendKeys(keys) |
number |
展开按键标记并发送组合后的输入。返回其 UTF-16 长度。 |
capture(options?) |
Promise<PaseoTerminalCaptureResult> |
返回 { terminalId, lines, totalLines, requestId }。 |
kill(requestId?) |
Promise<void> |
等待终端销毁完成。结束一个已被移除的终端也会成功。 |
sendKeys() 识别 Enter、Tab、Escape、Space、BSpace、C-c、C-d、C-z、C-l、C-a 和 C-e。其他字符串按字面传递。输入方法发送后不会等待命令执行,也不会确认终端已消费输入。
capture 接受可选的 start、end、stripAnsi 和 requestId。行范围从零开始、包含两端,跨越回滚缓冲区和视口。负数范围从末尾开始计数;省略范围时捕获所有行。stripAnsi 默认为 true。终端不存在时返回空行。
使用 workspace.terminals.create(options?) 和 workspace.terminals.list(options?) 可以从句柄提供工作区 ID。创建接受除 workspaceId 之外的相同选项;列表只接受 requestId。插件通过 usePaseo() 和处理函数的 paseo context 获得这些方法。
client.providers
| 方法 | 结果 | 行为 |
|---|---|---|
waitForReady(options?) |
PaseoProviderSnapshotResult |
等待直到没有 Provider 处于加载中。默认超时:60 秒。当 daemon 无法关联工作区快照时,以要求更新主机的错误 reject。 |
snapshot(options?) |
PaseoProviderSnapshotResult |
立即返回当前目录。 |
refresh(options?) |
确认 | 强制刷新所有或所选 Provider 的目录。 |
listAvailable() |
可用性结果 | 报告已安装 Provider 的可用性。 |
listModels(provider, options?) |
模型结果 | 为某个 Provider 和目录发现模型。 |
listModes(provider, options?) |
模式结果 | 发现权限模式或运行模式。 |
listFeatures(draftConfig) |
功能结果 | 为当前草稿 Provider 配置发现功能。 |
diagnostic(provider) |
诊断结果 | 返回人类可读的设置诊断信息。 |
listUsage(options?) |
PaseoProviderUsageResult |
返回规范化的订阅窗口、余额和 Provider 详情。不支持时以要求更新主机的错误 reject。选项:requestId。 |
subscribe(handler) |
取消订阅函数 | 请求之后的目录更新;取消订阅会释放这项需求。 |
client.config
config.get(requestId?) 返回 daemon 的可变配置。
config.patch(patch, requestId?) 会校验、持久化并返回更新后的配置。这个管理接口用于主机配置,而不是针对单个 Agent 的选择。一次 patch 会影响使用该 daemon 的每个客户端和之后的每个 Agent。
client.hosts
管理连接到所选 daemon 的主机。管理连接的 daemon 和目标主机都必须支持已连接主机功能。
const directory = await client.hosts.list();
const registration = await client.hosts.add({
connection: "ssh://deploy@build-box",
label: "Build box",
metadata: { team: "infra" },
sourceKey: "build-box",
});
await client.hosts.update(registration.registrationId, { enabled: false });
await client.hosts.remove(registration.registrationId);
list() 返回 { self: { serverId, label }, hosts }。每个主机包括注册 ID 和服务器 ID、标签、经过认证的来源、字符串元数据、启用状态、连接状态、不含凭据的目标描述、上次在线和重试时间戳,以及带恢复说明的错误。它不会返回凭据。
语法有效但无法访问的连接会被保存并重试。无效语法会直接报错,不会保存。
update(registrationId, patch) 接受 label、metadata、enabled、connection 和 replaceIdentity。
元数据会替换整个映射。替换连接会保留预期的服务器 ID,除非通过 replaceIdentity: true 显式接受新目标。
observe() 返回一个由调用方持有的订阅。等待 ready,订阅快照和 hosts.changed 更新,然后调用 release()。
重新连接后,观察会恢复并提供当前快照。
const remote = await client.hosts.client("srv_build_box");
try {
const workspaces = await remote.workspaces.list();
const providers = await remote.providers.listAvailable();
await remote.agents.ref("agent_on_build_box").send("Continue the investigation");
} finally {
await remote.dispose();
}
client(serverId) 返回一个由调用方持有的 PaseoApi,通过所选 daemon 绑定到该目标。
普通 API 的签名不变。路径和 ID 属于目标主机。选择本地服务器 ID 会返回本地作用域。路由支持一跳。
释放一个作用域会释放它的观察,不会关闭同级作用域或删除已保存的主机。
释放源作用域会同时释放派生作用域。观察通过普通客户端生命周期恢复。
连接过程中,新请求使用现有的有界发送队列;断开连接时请求会失败。连接丢失会清除旧的等待项和排队发送项。
普通的不可恢复请求不会重放;现有的已确认或幂等创建恢复会保留其请求身份。
已提交但响应丢失的请求会以 DaemonConnectionError 拒绝(code: "DAEMON_CONNECTION_LOST"),
并附带可选的 outcome: "unknown" 和已知的 serverId。重试修改操作前,请先检查目标状态。
注册和获取主机失败时会提供稳定的 code:host_unknown、host_disabled、host_offline、
permission_denied、unsupported_capability、authentication_failed、server_id_mismatch、
self_host 或 duplicate_host。普通 RPC 权限代码(包括 access_denied)保持不变。
多路复用属于传输层;调用方使用相同的客户端/API 操作和生命周期。发现主机不会授予执行权限。
错误与清理
连接、校验、拒绝和超时失败都会让对应的 promise reject。轮次的结果通过 PaseoAgentRunResult.status 返回,因为权限和 Provider 错误是 Agent 预期内的状态。
请始终在 finally 中关闭客户端。关闭客户端会移除它的本地监听器和网络连接;它不会停止 Agent,也不会归档工作区。