centralu 0.1.0-beta.43 → 0.1.0-beta.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/serve-detach.mjs +3 -2
- package/bin/serve-handover.mjs +6 -4
- package/bin/serve-host.mjs +3 -3
- package/package.json +5 -5
package/bin/serve-detach.mjs
CHANGED
|
@@ -270,7 +270,8 @@ export async function runDetachedChild({ spec, ...opts }) {
|
|
|
270
270
|
*
|
|
271
271
|
* A stop that went through is remembered in the data folder (`markStopped`, #1143), so a linked hub does not start the
|
|
272
272
|
* host again by itself; the next host that starts here removes the mark. Not for a hub's own stop, which starts the
|
|
273
|
-
* host again itself (an update, a rollback): the hub runs it with `CENTRALU_STOP_BY=hub` (links/tunnel.ts `stopCommand`)
|
|
273
|
+
* host again itself (an update, a rollback): the hub runs it with `CENTRALU_STOP_BY=hub` (links/tunnel.ts `stopCommand`).
|
|
274
|
+
* With `CENTRALU_STOP_FOR=update` too (#1618), the host is asked to list the turns it ends, which the next host continues
|
|
274
275
|
*/
|
|
275
276
|
export async function runStop({
|
|
276
277
|
env,
|
|
@@ -283,7 +284,7 @@ export async function runStop({
|
|
|
283
284
|
write = (line) => process.stdout.write(line),
|
|
284
285
|
}) {
|
|
285
286
|
const dataDir = serveDataDir(env, home)
|
|
286
|
-
const stopped = await stopServedHost({ dataDir, entry, platform, timeoutMs, graceMs, kill })
|
|
287
|
+
const stopped = await stopServedHost({ dataDir, entry, platform, forUpdate: env.CENTRALU_STOP_FOR === 'update', timeoutMs, graceMs, kill })
|
|
287
288
|
if (stopped.ok && env.CENTRALU_STOP_BY !== 'hub') markStopped(dataDir, 'stop')
|
|
288
289
|
return answerLine(write, 'stop', stopped)
|
|
289
290
|
}
|
package/bin/serve-handover.mjs
CHANGED
|
@@ -23,9 +23,11 @@ import { isAlive, say, sleep, waitUntil } from './serve-util.mjs'
|
|
|
23
23
|
* with this folder's token: a stale pid is never signalled.
|
|
24
24
|
*
|
|
25
25
|
* `{ ok, wasRunning, how?, message? }`, the `--stop` line's `stop`. With `ifIdle` (#1224, the hand-over) the host stops only
|
|
26
|
-
* when nothing runs there, and `{ ok: false, busy: true }` says it did not.
|
|
26
|
+
* when nothing runs there, and `{ ok: false, busy: true }` says it did not. `forUpdate` (#1618): a hub's update stops it, and
|
|
27
|
+
* the host writes the turns it ends for the next one (`host.stop { forUpdate }`); a host that does not take the request is
|
|
28
|
+
* ended as any is, and lists nothing.
|
|
27
29
|
*/
|
|
28
|
-
export async function stopServedHost({ dataDir, entry, platform = process.platform, ifIdle = false, timeoutMs = 30_000, graceMs = 15_000, kill = (pid, sig) => process.kill(pid, sig) }) {
|
|
30
|
+
export async function stopServedHost({ dataDir, entry, platform = process.platform, ifIdle = false, forUpdate = false, timeoutMs = 30_000, graceMs = 15_000, kill = (pid, sig) => process.kill(pid, sig) }) {
|
|
29
31
|
const state = readServeState(dataDir)
|
|
30
32
|
if (!state) return { ok: true, wasRunning: false, message: `no centralu serve has run for ${dataDir}` }
|
|
31
33
|
const port = state.port ?? DEFAULT_SERVE_PORT
|
|
@@ -41,8 +43,8 @@ export async function stopServedHost({ dataDir, entry, platform = process.platfo
|
|
|
41
43
|
const launcherPid = launcher && hostPid && launcher.hostPid === hostPid ? launcher.pid : null
|
|
42
44
|
const down = async () => !(await probe()).running && !(hostPid && isAlive(hostPid))
|
|
43
45
|
|
|
44
|
-
let asked = await askHostToStop({ port, token: state.token, protocolVersion: first.protocolVersion ?? installed, prove, ifIdle })
|
|
45
|
-
if (!asked.ok && asked.protocolVersion !== undefined) asked = await askHostToStop({ port, token: state.token, protocolVersion: asked.protocolVersion, prove, ifIdle })
|
|
46
|
+
let asked = await askHostToStop({ port, token: state.token, protocolVersion: first.protocolVersion ?? installed, prove, ifIdle, forUpdate })
|
|
47
|
+
if (!asked.ok && asked.protocolVersion !== undefined) asked = await askHostToStop({ port, token: state.token, protocolVersion: asked.protocolVersion, prove, ifIdle, forUpdate })
|
|
46
48
|
// `ifIdle` and it has work running (#1224): it was left as it is
|
|
47
49
|
if (asked.busy) return { ok: false, wasRunning: true, busy: true, message: asked.message }
|
|
48
50
|
let how = 'asked'
|
package/bin/serve-host.mjs
CHANGED
|
@@ -367,9 +367,9 @@ export function askHostRpc({ port, token, protocolVersion, prove = false, method
|
|
|
367
367
|
* `{ ok: true }` once the host took it, `{ ok: false, message, protocolVersion? }` otherwise; the
|
|
368
368
|
* last names the host's protocol when the hello was refused for it, so the caller can ask again.
|
|
369
369
|
* `ifIdle` (#1224): only if nothing runs there, checked and acted on by the host in one step; `{ ok: false, busy: true }`
|
|
370
|
-
* when something does.
|
|
370
|
+
* when something does. `forUpdate` (#1618): a hub's update stops it, and the host lists the turns it ends for the next one.
|
|
371
371
|
*/
|
|
372
|
-
export function askHostToStop({ port, token, protocolVersion, prove = false, ifIdle = false, timeoutMs = 5000, WebSocketImpl = globalThis.WebSocket }) {
|
|
372
|
+
export function askHostToStop({ port, token, protocolVersion, prove = false, ifIdle = false, forUpdate = false, timeoutMs = 5000, WebSocketImpl = globalThis.WebSocket }) {
|
|
373
373
|
if (typeof WebSocketImpl !== 'function') return Promise.resolve({ ok: false, message: `Node ${process.version} has no WebSocket to ask with` })
|
|
374
374
|
// With `prove`, the token goes out only to a host that proved it holds it (#838)
|
|
375
375
|
return helloExchange({
|
|
@@ -380,7 +380,7 @@ export function askHostToStop({ port, token, protocolVersion, prove = false, ifI
|
|
|
380
380
|
unproven: () => done({ ok: false, message: 'what answers on the port did not prove it holds the token' }),
|
|
381
381
|
gone: () => done({ ok: false, message: 'the connection closed' }),
|
|
382
382
|
message: (m, ws) => {
|
|
383
|
-
if (m.kind === 'hello_ok') ws.send(JSON.stringify({ kind: 'rpc', id: 'stop', method: 'host.stop', params: ifIdle ? { ifIdle: true } : {} }))
|
|
383
|
+
if (m.kind === 'hello_ok') ws.send(JSON.stringify({ kind: 'rpc', id: 'stop', method: 'host.stop', params: { ...(ifIdle ? { ifIdle: true } : {}), ...(forUpdate ? { forUpdate: true } : {}) } }))
|
|
384
384
|
else if (m.kind === 'res' && m.id === 'stop' && m.ok && m.result?.ok === false) {
|
|
385
385
|
// `ifIdle` and something runs there (#1224): nothing was changed
|
|
386
386
|
done({ ok: false, busy: true, message: 'it has work running', activity: m.result.busy ?? null, calls: m.result.calls ?? 0 })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "centralu",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.44",
|
|
4
4
|
"description": "Run, watch and steer several Claude Code and Codex CLI sessions from one window",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ijun17",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"win32"
|
|
39
39
|
],
|
|
40
40
|
"optionalDependencies": {
|
|
41
|
-
"@centralu/darwin-arm64": "0.1.0-beta.
|
|
42
|
-
"@centralu/linux-arm64": "0.1.0-beta.
|
|
43
|
-
"@centralu/linux-x64": "0.1.0-beta.
|
|
44
|
-
"@centralu/win32-x64": "0.1.0-beta.
|
|
41
|
+
"@centralu/darwin-arm64": "0.1.0-beta.44",
|
|
42
|
+
"@centralu/linux-arm64": "0.1.0-beta.44",
|
|
43
|
+
"@centralu/linux-x64": "0.1.0-beta.44",
|
|
44
|
+
"@centralu/win32-x64": "0.1.0-beta.44"
|
|
45
45
|
}
|
|
46
46
|
}
|