终端 / 主机 / 文件传输
终端 / 主机 / 文件传输
Section titled “终端 / 主机 / 文件传输”这一组 API 让插件与用户的工作区交互:读写终端、开终端 tab、在主机上执行 命令、传输文件、存取凭证。
终端(ctx.terminal)
Section titled “终端(ctx.terminal)”读取活跃 pane
Section titled “读取活跃 pane”ctx.terminal.getActivePane(): ActivePaneInfo | null;// ActivePaneInfo { paneId: string; kind: "local" | "ssh" | "serial"; backendId: string }返回当前活跃终端 pane 的只读投影;预览等非终端 pane 返回 null。
ctx.terminal.writeActive(text: string): Promise<boolean>;ctx.terminal.writePane(paneId: string, text: string): Promise<boolean>;writeActive:向活跃 pane 写入并聚焦。writePane:向指定 pane 写入(pane 不在当前活跃 tab 也能写,宿主 会自动切换 tab 并聚焦,用户能看到注入的命令);pane 不存在或写入失败 返回false。后端会话未就绪时会主动确保建立(与 attach 路径去重)。
ctx.terminal.onOutput(cb: (chunk: OutputChunk, pane: ActivePaneInfo) => void): Disposer;// OutputChunk { seq: number; data: string }订阅活跃 pane 的输出流,切换 pane 自动跟随;返回退订函数。
ctx.terminal.focusActive(): void;会话创建(ctx.sessions)
Section titled “会话创建(ctx.sessions)”一键连数据库、开运维会话、Docker exec 借道都从这里开终端 tab:
ctx.sessions.openLocalTab(): Promise<string | null>; // 新开本地终端 tab,返回 paneIdctx.sessions.openHostTab(hostId: string): Promise<string | null>; // 新开指定主机的 SSH tab(自动确保连接在线)ctx.sessions.focus(paneId: string): void; // 聚焦某个 pane实例:Docker exec 借道
Section titled “实例:Docker exec 借道”官方 Docker 插件「在终端中持续跟随」模式:开 tab 后向 pane 注入命令:
const paneId = await ctx.sessions.openLocalTab();if (paneId) await ctx.terminal.writePane(paneId, `docker exec -it ${id} bash\n`);主机(ctx.hosts)
Section titled “主机(ctx.hosts)”ctx.hosts.list(): readonly HostSummary[];// HostSummary { id, name, host, port, username, group?, tags: string[], favorite }
ctx.hosts.connect(hostId: string): Promise<string>; // 建立(或复用)SSH 连接,返回 sessionIdctx.hosts.exec(hostId, command, opts?: { timeoutSecs? }): Promise<{ stdout; stderr; exitCode }>;ctx.hosts.disconnect(hostId: string): Promise<void>;ctx.hosts.reconnect(hostId: string): Promise<string>; // 重建 transport(复用现有配置),返回新 sessionIdctx.hosts.execLocal(command: string, opts?: { timeoutSecs? }): Promise<{ stdout; stderr; exitCode }>;ctx.hosts.execStream(hostId: string, command: string): Promise<ProcessHandle>; // L1 process要点:
list()返回的是只读投影,不含任何凭证字段。exec/execLocal是一次性的(等进程退出拿全部输出),撑不起日志 follow / 进度流——流式场景用process.spawn/hosts.execStream(见 流式进程与 sidecar)。execLocal在宿主本机执行 shell 命令(临时 PTY 只收集 stdout,stderr恒为空串);默认超时 60s。execStream需要 L1process能力(与ctx.process.spawn同一把信任锁)。
// 在指定主机上执行命令并展示结果const res = await ctx.hosts.exec(hostId, "df -h /", { timeoutSecs: 15 });if (res.exitCode === 0) { ctx.ui.toast.success({ title: res.stdout.trim().split("\n").pop() });} else { ctx.ui.toast.error({ title: "执行失败", description: res.stderr });}
// 在宿主本机执行const local = await ctx.hosts.execLocal("uname -a", { timeoutSecs: 15 });ctx.ui.toast.info({ title: local.stdout.trim() });文件传输(ctx.sftp)
Section titled “文件传输(ctx.sftp)”同步形态的文件传输投影:Promise 在传输真正完成 / 失败后才 settle,
内部使用主机的文件 SSH 会话(与 hosts.exec 的 terminal 会话分离,
互不干扰)。错误消息透传 sftp 命令的原始错误:
ctx.sftp.upload(hostId, localPath, remotePath, onProgress?): Promise<void>;ctx.sftp.download(hostId, remotePath, localPath, onProgress?): Promise<void>;
// onProgress?: (p: { transferred: number; total: number }) => void// total 在传输开始后可能为 0,表示总大小未知await ctx.sftp.upload(hostId, localPath, remotePath, (p) => { if (p.total > 0) console.log(`${Math.round((p.transferred / p.total) * 100)}%`);});凭证保险库(ctx.vault)
Section titled “凭证保险库(ctx.vault)”keyring 投影(官方 Docker 插件的 registry 登录凭据用)。无能力门禁:
vault 与 hosts / tunnels / sessions 同属核心服务投影,不参与
capabilities 声明(process / sidecar 才需要 L1):
ctx.vault.get(id: string): Promise<string | null>; // 不存在返回 nullctx.vault.set(id: string, secret: string): Promise<void>; // 覆盖写入ctx.vault.delete(id: string): Promise<void>; // 不存在时静默成功