( opts: CreateHelperServerOptions, )
| 87 | * surfaced as `ok:false` responses — never silently swallowed. |
| 88 | */ |
| 89 | export function createHelperServer( |
| 90 | opts: CreateHelperServerOptions, |
| 91 | ): Promise<HelperServer> { |
| 92 | const { socketPath, secret, kernel } = opts |
| 93 | |
| 94 | function buildResponse(req: HelperRequest): Promise<HelperResponse> { |
| 95 | const version = kernel.version() |
| 96 | |
| 97 | // Auth first: a bad secret must not reach any dispatch path. |
| 98 | if (req.secret !== secret) { |
| 99 | return Promise.resolve({ |
| 100 | type: req.type, |
| 101 | ok: false, |
| 102 | version, |
| 103 | error: 'helper: shared secret mismatch', |
| 104 | }) |
| 105 | } |
| 106 | |
| 107 | // Version handshake: reject incompatible wire versions, but still echo the |
| 108 | // helper's own version so the client can detect a stale install (B-3). |
| 109 | if (req.version !== HELPER_PROTOCOL_VERSION) { |
| 110 | return Promise.resolve({ |
| 111 | type: req.type, |
| 112 | ok: false, |
| 113 | version, |
| 114 | error: `helper: protocol version mismatch (helper ${version}, client ${req.version})`, |
| 115 | }) |
| 116 | } |
| 117 | |
| 118 | return dispatch(req, version) |
| 119 | } |
| 120 | |
| 121 | async function dispatch( |
| 122 | req: HelperRequest, |
| 123 | version: string, |
| 124 | ): Promise<HelperResponse> { |
| 125 | try { |
| 126 | switch (req.type) { |
| 127 | case 'ping': |
| 128 | case 'getVersion': |
| 129 | return { type: req.type, ok: true, version } |
| 130 | case 'startKernel': { |
| 131 | const { binaryPath, homeDir, configPath } = req as StartKernelRequest |
| 132 | const result = await kernel.start({ binaryPath, homeDir, configPath }) |
| 133 | return { type: req.type, ok: true, version, running: result.running } |
| 134 | } |
| 135 | case 'stopKernel': |
| 136 | await kernel.stop() |
| 137 | return { type: req.type, ok: true, version } |
| 138 | case 'status': { |
| 139 | const result = kernel.status() |
| 140 | return { type: req.type, ok: true, version, running: result.running } |
| 141 | } |
| 142 | } |
| 143 | } catch (err) { |
| 144 | // Surface (never swallow) any privileged-side failure to the client. |
| 145 | return { |
| 146 | type: req.type, |
no outgoing calls
no test coverage detected