(server: RuntimeServer, adapter: RuntimeNodePtyAdapter)
| 102 | } |
| 103 | |
| 104 | export function registerRuntimeNodePtyModule(server: RuntimeServer, adapter: RuntimeNodePtyAdapter): () => void { |
| 105 | server.registerNotification("pty/started") |
| 106 | server.registerNotification("pty/output") |
| 107 | server.registerNotification("pty/exit") |
| 108 | server.registerNotification("pty/killed") |
| 109 | |
| 110 | const removeLifecycleListener = adapter.addLifecycleListener((event) => { |
| 111 | if (event.type === "started") { |
| 112 | const runtime = server.supervisor.create({ |
| 113 | runtimeId: ptyRuntimeId(event.ptyId), |
| 114 | kind: "pty", |
| 115 | status: "running", |
| 116 | scope: { |
| 117 | ownerType: "pty", |
| 118 | ownerId: event.ptyId, |
| 119 | rootPath: event.cwd, |
| 120 | }, |
| 121 | nativeId: event.ptyId, |
| 122 | pid: event.pid, |
| 123 | pgid: event.pgid, |
| 124 | processLabel: event.shell, |
| 125 | processStartedAt: event.processStartedAt ?? now(), |
| 126 | }) |
| 127 | server.notify("runtime/created", runtime) |
| 128 | server.notify("pty/started", { ...event, runtimeId: runtime.runtimeId }) |
| 129 | return |
| 130 | } |
| 131 | |
| 132 | if (event.type === "output") { |
| 133 | server.supervisor.touchByOwner("pty", event.ptyId) |
| 134 | server.notify("pty/output", event) |
| 135 | return |
| 136 | } |
| 137 | |
| 138 | const status = event.type === "killed" ? "stopped" : event.exitCode === 0 ? "completed" : "failed" |
| 139 | const runtime = server.supervisor.update(ptyRuntimeId(event.ptyId), { |
| 140 | status, |
| 141 | exitedAt: now(), |
| 142 | exitCode: event.type === "killed" ? null : event.exitCode, |
| 143 | signal: event.type === "killed" ? "killed" : null, |
| 144 | }) |
| 145 | server.notify(status === "completed" ? "runtime/completed" : status === "stopped" ? "runtime/stopped" : "runtime/failed", runtime) |
| 146 | server.notify(event.type === "killed" ? "pty/killed" : "pty/exit", event) |
| 147 | }) |
| 148 | |
| 149 | server.register( |
| 150 | "pty/spawn", |
| 151 | async (params) => { |
| 152 | const parsed = ptySpawnParams(params) |
| 153 | const result = await adapter.spawn(parsed) |
| 154 | return { ...result, ptyId: parsed.ptyId, runtimeId: ptyRuntimeId(parsed.ptyId) } |
| 155 | }, |
| 156 | { |
| 157 | validateParams: validateParams( |
| 158 | requiredStringParam("cwd"), |
| 159 | optionalString("ptyId"), |
| 160 | optionalStringRecordParam("env"), |
| 161 | optionalPositiveInteger("cols"), |
no test coverage detected