Skip to content

Terminal API Reference

AceGuru-mjh edited this page Oct 1, 2026 · 4 revisions

终端 API 契约(P60 冻结)

🖥️ 终端 & Linux · 🏠 首页 › Terminal-API-Reference

Home Version Kotlin Modules Tools License

Terminal-API-Reference typing

📑 本页目录

终端对外暴露一套**冻结于 P60(API Version 1.0)**的公共 API。来源 docs/terminal-api.md。 冻结规则:允许 ADD(可选字段/新能力),谨慎改语义,禁止删除 API / 改参数含义 / 向 Agent 暴露 PID、PTY、Process。

1. 分层与生命周期链

Agent → Terminal(root)→ TerminalSession → JobHandle / Observation / Input

Agent 永不接触 PTY、PID、ProcessHandle、TerminalCore、ObservationEngine、 SessionManager、JobManager、RecoveryCoordinator。

flowchart LR
    A["terminal.createSession(SessionRequest)"] --> B["TerminalSession"]
    B --> C["session.execute(ExecutionRequest) → JobHandle"]
    C --> D["session.observe(ObservationRequest) → ObservationResult"]
    D --> E["session.sendInput(TerminalInput)"]
    E --> F["job.await() → JobResult"]
    F --> G["session.close()(幂等)"]
Loading

2. Terminal(root)API

方法 返回 说明
createSession(SessionRequest) Result<TerminalSession> 创建 workspace 与会话
getSession(SessionId) TerminalSession? 取回会话
listSessions() List<SessionSummary> 全部活跃会话
shutdown() Result<Unit> 关闭全部
capabilities() TerminalCapabilities 后端能力
apiVersion() String 恒为 "1.0"

3. TerminalSession API

方法 返回 说明
execute(ExecutionRequest) Result<JobHandle> 非阻塞
sendInput(TerminalInput) Result<Unit> 写入 PTY
observe(ObservationRequest) Result<ObservationResult> 增量观察
snapshot() SessionSnapshot 全量状态
resize(TerminalSize) Result<Unit> PTY + VT + Screen 同步
stop() Result<Unit> 停 job,会话仍存活
close() Result<Unit> 幂等,完整清理

4. JobHandle API

方法 说明
cancel() 请求停止(CANCELLING → CANCELLED)
snapshot() 不可变 JobSnapshot
await() 阻塞至终止。取消 await ≠ 取消 Job

5. 错误模型(9 个码)

统一 TerminalError(code, message, retryable) —— Agent 按 code 匹配,不要匹配 message。

code 可重试 含义
SESSION_NOT_FOUND ❌ 会话不存在
SESSION_NOT_RUNNING ❌ 会话非运行态
SESSION_ALREADY_CLOSED ❌ 已关闭(幂等 close 返回成功)
JOB_NOT_FOUND ❌ job 不存在
TIMEOUT ✅ 超时
CANCELLED ❌ 已取消
BACKEND_UNAVAILABLE ✅ 后端不可用
CURSOR_EXPIRED ✅ 观察游标过旧 → 调 snapshot() 重新同步
INVALID_CURSOR ❌ 游标来自别的 session
UNSUPPORTED ❌ 后端无此能力

6. 观察协议与游标

调用 返回
observe(cursor = null) ObservationResult.Snapshot(全量)
observe(cursor = "abc") ObservationResult.Delta(增量)
observe(cursor = "expired") ObservationResult.CursorExpired(需重新同步)

Caution

游标是不透明字符串:Agent 禁止解析、禁止跨 session 使用。

7. 线程与重入契约

  • Terminal / TerminalSession / JobHandle 线程安全(任意线程/协程);
  • TerminalSnapshot 及所有公开模型不可变,可安全共享;
  • 回调在独立 dispatcher 派发,绝不在持锁时执行;
  • 顺序固定:状态变更 → 事件入队 → 释放锁 → 派发回调。

8. 后端契约

后端 id 实现
LocalShellBackend "local" forkpty + execv("/system/bin/sh", "-i")
LinuxPRootBackend "linux-ubuntu" forkpty + execv(libproot.so … /bin/bash -i)
  • 默认 backendId = "local";
  • Agent 通过 terminal.backends() 发现后端(可用性 READY / NEEDS_ROOTFS / FAILED), 通过 terminal.ubuntu.install(幂等、可续传)供应 rootfs;
  • Agent 不需要知道当前是哪个后端 —— 换后端 = Agent 代码零改动;
  • 会话元数据(backendId / rootfsId / workspaceId / guestCwd / binds)随会话持久化 (SessionRecord schema v3),崩溃恢复才能区分 local 与 Ubuntu 会话。

9. Workspace 与 User Home(T75)

挂载 宿主路径 guest 路径
workspace <filesDir>/linux/workspaces/<id>/ /workspace
user home <filesDir>/linux/home/ /root

规则:

  • workspace id 正则 ^[a-z0-9][a-z0-9_-]{0,63}$;未知但合法者自动创建(workspace-per-task 零摩擦);
  • delete 在有会话挂载时拒绝(需先 close);
  • guest /root 是宿主 bind,不在 rootfs 内 → 用户文件在 rootfs 换版后仍存活;首次使用从 /etc/skel 播种(或最小 .bashrc 兜底);
  • guest 环境携带 HOME=/root USER=root LOGNAME=root;
  • LOCAL 会话拒绝 workspaceId(InvalidInput,显式优于静默)。

10. 最小示例

s = terminal.createSession(SessionRequest(workingDirectory = "/sdcard"))
job = s.execute(ExecutionRequest(command = "echo hello"))
result = job.await()
assert result.exitInfo?.exitCode == 0
s.close()          # 幂等

11. 相关页面

footer

🏠 返回首页 · 📚 文档索引 · ❓ FAQ · 🔧 故障排查 · 🗺️ 路线图 · 🐛 提 Issue

Android Guru Agent · v1.4.4 · Kotlin 2.0.21 · Compose · PRoot · Room

Clone this wiki locally