@zswarm/core 0.1.7 → 0.1.8
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/README.md +8 -0
- package/dist/errors.d.ts +2 -1
- package/dist/errors.js +4 -1
- package/dist/exec.d.ts +8 -0
- package/dist/exec.js +12 -12
- package/dist/index.d.ts +6 -2
- package/dist/index.js +5 -1
- package/dist/ops/bus.js +7 -0
- package/dist/ops/dispatch.js +39 -5
- package/dist/ops/doctor.d.ts +80 -0
- package/dist/ops/doctor.js +1377 -0
- package/dist/ops/routing.js +2 -1
- package/dist/ops/serve-bind.d.ts +86 -0
- package/dist/ops/serve-bind.js +354 -0
- package/dist/ops/serve-install.d.ts +88 -0
- package/dist/ops/serve-install.js +1171 -0
- package/dist/ops/serve-tunnel.d.ts +109 -0
- package/dist/ops/serve-tunnel.js +1179 -0
- package/dist/ops/serve.d.ts +89 -21
- package/dist/ops/serve.js +622 -156
- package/dist/ops/types.d.ts +49 -0
- package/dist/ops/util.js +8 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +8 -7
- package/dist/state.js +158 -38
- package/dist/zellij/binary.d.ts +7 -0
- package/dist/zellij/binary.js +20 -7
- package/dist/zellij/client.js +7 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,6 +30,14 @@ const result = await dispatchZswarm({ op: "list" });
|
|
|
30
30
|
`{ ok, data }` or `{ ok: false, error }`, with routing `context` once the
|
|
31
31
|
invocation's destination is known.
|
|
32
32
|
|
|
33
|
+
`ZSWARM_SERVE` / `--serve` may be `host:port`, `tcp://host:port`, or
|
|
34
|
+
`ssh://user@host[:sshPort]?servePort=9419`. The ssh URI opens a process-owned
|
|
35
|
+
SSH LocalForward and calls `probeServe` before ops (including before reuse);
|
|
36
|
+
pass a `serveTunnels` manager if the caller (MCP) should reuse it. Omitting
|
|
37
|
+
the SSH port leaves `Port` to OpenSSH instead of forcing 22. `tcp://` also
|
|
38
|
+
names a private Tailscale Serve frontend over a loopback backend; see
|
|
39
|
+
[Tailscale crew](../../docs/tailscale.md).
|
|
40
|
+
|
|
33
41
|
Spawn lifecycle, body files, guarded keys, status tabs and routing context: [crew operations](../../docs/crew-operations.md).
|
|
34
42
|
|
|
35
43
|
Ops, env, and the event bus: the [zswarm README](../../README.md).
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Every zSwarm failure carries a stable machine-readable code. */
|
|
2
2
|
export declare class ZellijError extends Error {
|
|
3
3
|
readonly code: string;
|
|
4
|
-
|
|
4
|
+
readonly details?: Record<string, unknown>;
|
|
5
|
+
constructor(code: string, message: string, details?: Record<string, unknown>);
|
|
5
6
|
}
|
package/dist/errors.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/** Every zSwarm failure carries a stable machine-readable code. */
|
|
2
2
|
export class ZellijError extends Error {
|
|
3
3
|
code;
|
|
4
|
-
|
|
4
|
+
details;
|
|
5
|
+
constructor(code, message, details) {
|
|
5
6
|
super(message);
|
|
6
7
|
this.name = "ZellijError";
|
|
7
8
|
this.code = code;
|
|
9
|
+
if (details && Object.keys(details).length > 0)
|
|
10
|
+
this.details = details;
|
|
8
11
|
}
|
|
9
12
|
}
|
package/dist/exec.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { type IpcDirs, type RemoteShell } from "./zellij/ipc.js";
|
|
2
|
+
export type ExecSpawnFailure = {
|
|
3
|
+
/** Node could not start this process. Distinct from a remote 127. */
|
|
4
|
+
origin: "local";
|
|
5
|
+
errno: string;
|
|
6
|
+
bin: string;
|
|
7
|
+
};
|
|
2
8
|
export type ExecResult = {
|
|
3
9
|
code: number;
|
|
4
10
|
stdout: string;
|
|
5
11
|
stderr: string;
|
|
12
|
+
/** Present only when this host failed to spawn the binary. */
|
|
13
|
+
spawn?: ExecSpawnFailure;
|
|
6
14
|
};
|
|
7
15
|
export type ExecOptions = {
|
|
8
16
|
timeoutMs: number;
|
package/dist/exec.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { execFile, spawn } from "node:child_process";
|
|
2
2
|
import { cmdQuote, inferRemoteShell, parseZellijServerPaths, pickIpcDirs, unixDiscoverRemote, windowsDiscoverRemote, windowsInteractiveRemote, wrapWithTmpEnv, } from "./zellij/ipc.js";
|
|
3
3
|
export const NOT_FOUND_EXIT = 127;
|
|
4
|
+
function localSpawnResult(err, binPath) {
|
|
5
|
+
const errno = typeof err.code === "string" && err.code ? err.code : "error";
|
|
6
|
+
const missing = errno === "ENOENT" || errno === "ENOTDIR";
|
|
7
|
+
return {
|
|
8
|
+
code: missing ? NOT_FOUND_EXIT : 1,
|
|
9
|
+
stdout: "",
|
|
10
|
+
stderr: `${errno}: ${err.message} (bin=${binPath})`,
|
|
11
|
+
spawn: { origin: "local", errno, bin: binPath },
|
|
12
|
+
};
|
|
13
|
+
}
|
|
4
14
|
/** POSIX single-quoting, for building a command line the remote shell parses. */
|
|
5
15
|
export function shellQuote(arg) {
|
|
6
16
|
if (arg === "")
|
|
@@ -349,12 +359,7 @@ function runUntil(binPath, args, env, options) {
|
|
|
349
359
|
}
|
|
350
360
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
351
361
|
child.on("error", (err) => {
|
|
352
|
-
|
|
353
|
-
finish({
|
|
354
|
-
code: missing ? NOT_FOUND_EXIT : 1,
|
|
355
|
-
stdout: "",
|
|
356
|
-
stderr: `${err.code ?? "error"}: ${err.message} (bin=${binPath})`,
|
|
357
|
-
});
|
|
362
|
+
finish(localSpawnResult(err, binPath));
|
|
358
363
|
});
|
|
359
364
|
child.stdout.on("data", (chunk) => {
|
|
360
365
|
stdout += chunk.toString();
|
|
@@ -383,12 +388,7 @@ function runToExit(binPath, args, env, options) {
|
|
|
383
388
|
}, (error, stdout, stderr) => {
|
|
384
389
|
const failure = error;
|
|
385
390
|
if (failure && typeof failure.code === "string") {
|
|
386
|
-
|
|
387
|
-
resolve({
|
|
388
|
-
code: missing ? NOT_FOUND_EXIT : 1,
|
|
389
|
-
stdout: "",
|
|
390
|
-
stderr: `${failure.code}: ${failure.message} (bin=${binPath})`,
|
|
391
|
-
});
|
|
391
|
+
resolve(localSpawnResult(failure, binPath));
|
|
392
392
|
return;
|
|
393
393
|
}
|
|
394
394
|
if (failure &&
|
package/dist/index.d.ts
CHANGED
|
@@ -15,13 +15,17 @@ export { assertOpAllowed, assertPaneAllowed, isWriteOp, loadPolicy, type Policy,
|
|
|
15
15
|
export { buildSshRemoteCommand, createSshExec, quoteRemoteArg, shellQuote, type IpcDiscoveryState, type SshExecFn, type SshTarget, } from "./exec.js";
|
|
16
16
|
export { resolveSshTarget } from "./zellij/binary.js";
|
|
17
17
|
export { applyIpcTmpEnv, cmdQuote, concreteTmp, encodePowerShellCommand, inferRemoteShell, parseZellijServerPaths, pickIpcDirs, pickIpcTmp, socketDirFromServerPath, tmpFromServerPath, unixDiscoverRemote, windowsDiscoverRemote, windowsInteractiveRemote, wrapWithTmpEnv, } from "./zellij/ipc.js";
|
|
18
|
-
export { callServe, DEFAULT_SERVE_LISTEN,
|
|
18
|
+
export { callServe, DEFAULT_SERVE_LISTEN, isLoopbackHost, parseListenAddress, probeServe, redactServeSecret, SERVE_CALL_TIMEOUT_CAP_MS, SERVE_CAPABILITY_HELLO, SERVE_CONNECT_TIMEOUT_MS, SERVE_CONTROL_FIELD, SERVE_HELLO_CONTROL, SERVE_HELLO_TIMEOUT_MS, SERVE_CORE_VERSION, SERVE_LAUNCH_ID_ENV, SERVE_MAX_HELLO_BYTES, SERVE_MAX_REPLY_BYTES, SERVE_MAX_REQUEST_BYTES, SERVE_CAPTURE_BUDGET_BYTES, SERVE_PROTOCOL, SERVE_REMEDY, SERVE_TASK_NAME, serveCallTimeout, serveChildEnv, serveLogonCommand, serveMaxReplyBytes, startServe, type CallServeOptions, type ProbeServeOptions, type ServeCapability, type ServeDelivery, type ServeErrorDetails, type ServeHelloData, type ServePhase, type StartServeOptions, } from "./ops/serve.js";
|
|
19
|
+
export { authorizeServeListen, canonicalizeListenIp, expandIPv6, sameCanonicalIp, SERVE_BIND_REMEDY, SERVE_BIND_STATUS_MAX_BYTES, SERVE_BIND_VERIFY_TIMEOUT_MS, SERVE_TAILSCALE_BIN_ENV, type ServeBindAuthorization, type ServeBindDeps, } from "./ops/serve-bind.js";
|
|
20
|
+
export { buildServeTaskScript, DEFAULT_SERVE_INSTALL_TIMEOUT_MS, installServeLogon, looksLikeCliEntrypoint, looksLikeMcpEntrypoint, resolveServeCliLaunch, sameWindowsAccount, sameWindowsSid, SERVE_NOT_READY_CODE, SERVE_TASK_OWNED_CODE, serveCommandFingerprint, serveTaskChildEnv, serveTaskLaunchEnv, uninstallServeLogon, type ServeCliLaunch, type ServeInstallInput, type ServeInstallSuccess, type ServeTaskAction, } from "./ops/serve-install.js";
|
|
21
|
+
export { allocateLoopbackPort, assertSafeSshTunnelOpts, buildSshTunnelArgv, createServeTunnelManager, DEFAULT_SSH_PORT, DEFAULT_SSH_SERVE_PORT, describeServeTarget, formatSshServeTarget, forwardServe, isSshServeTarget, parseSshServeTarget, redactSshUserinfo, serveTunnelCacheKey, SSH_SERVE_REMOTE_HOST, SSH_TUNNEL_KEEPALIVE_COUNT, SSH_TUNNEL_KEEPALIVE_INTERVAL_S, stripControllerRouting, type AcquireServeTunnelOptions, type ParsedSshServeTarget, type ServeTunnelHandle, type ServeTunnelManager, type ServeTunnelManagerOptions, } from "./ops/serve-tunnel.js";
|
|
19
22
|
export { parseTabList, resolveTab, type ZellijTab } from "./zellij/tabs.js";
|
|
20
23
|
export { selectTargets } from "./ops/broadcast.js";
|
|
21
24
|
export { diffScreens, cursorKey } from "./ops/tail.js";
|
|
22
25
|
export { classify, lastLine, mapPool, peerStatus, DEFAULT_STATUS_TIMEOUT_MS, STATUS_DUMP_CONCURRENCY, type PeerState, } from "./ops/status.js";
|
|
23
26
|
export { normalizeScreen, truncateDumpText, DEFAULT_DUMP_MAX_CHARS, DEFAULT_WAIT_MAX_CHARS, } from "./ops/util.js";
|
|
24
27
|
export type { RoutingContext } from "./ops/routing.js";
|
|
25
|
-
export type { DispatchDeps, OpsResult } from "./ops/types.js";
|
|
28
|
+
export type { DispatchDeps, OpsResult, ServeInstallDeps } from "./ops/types.js";
|
|
29
|
+
export { DEFAULT_DOCTOR_TIMEOUT_MS, DOCTOR_FAILED_CODE, DOCTOR_SCOPE_FIELD, DOCTOR_SCOPE_HOST, DOCTOR_TAILSCALE_MAX_MS, HOST_REPORT_INCOMPLETE_CODE, HOST_REPORT_INVALID_CODE, doctorOp, inspectDoctorHost, coverHostReport, hostDoctorRequest, isRequiredFailure, mergeHostReply, type DoctorCheck, type DoctorCheckScope, type DoctorCheckState, type DoctorReport, type DoctorRoute, type HostInspectInput, } from "./ops/doctor.js";
|
|
26
30
|
export { normalizeKey, normalizeKeys, tokenizeCommand } from "./keys.js";
|
|
27
31
|
export { cliUsage, mcpInputSchema, parseCliArgv, MCP_TOOL_DESCRIPTION, OP_NAMES, PARAMS, TARGET_OPS, type OpName, type ParamSpec, type ParamType, } from "./schema.js";
|
package/dist/index.js
CHANGED
|
@@ -15,11 +15,15 @@ export { assertOpAllowed, assertPaneAllowed, isWriteOp, loadPolicy, } from "./po
|
|
|
15
15
|
export { buildSshRemoteCommand, createSshExec, quoteRemoteArg, shellQuote, } from "./exec.js";
|
|
16
16
|
export { resolveSshTarget } from "./zellij/binary.js";
|
|
17
17
|
export { applyIpcTmpEnv, cmdQuote, concreteTmp, encodePowerShellCommand, inferRemoteShell, parseZellijServerPaths, pickIpcDirs, pickIpcTmp, socketDirFromServerPath, tmpFromServerPath, unixDiscoverRemote, windowsDiscoverRemote, windowsInteractiveRemote, wrapWithTmpEnv, } from "./zellij/ipc.js";
|
|
18
|
-
export { callServe, DEFAULT_SERVE_LISTEN,
|
|
18
|
+
export { callServe, DEFAULT_SERVE_LISTEN, isLoopbackHost, parseListenAddress, probeServe, redactServeSecret, SERVE_CALL_TIMEOUT_CAP_MS, SERVE_CAPABILITY_HELLO, SERVE_CONNECT_TIMEOUT_MS, SERVE_CONTROL_FIELD, SERVE_HELLO_CONTROL, SERVE_HELLO_TIMEOUT_MS, SERVE_CORE_VERSION, SERVE_LAUNCH_ID_ENV, SERVE_MAX_HELLO_BYTES, SERVE_MAX_REPLY_BYTES, SERVE_MAX_REQUEST_BYTES, SERVE_CAPTURE_BUDGET_BYTES, SERVE_PROTOCOL, SERVE_REMEDY, SERVE_TASK_NAME, serveCallTimeout, serveChildEnv, serveLogonCommand, serveMaxReplyBytes, startServe, } from "./ops/serve.js";
|
|
19
|
+
export { authorizeServeListen, canonicalizeListenIp, expandIPv6, sameCanonicalIp, SERVE_BIND_REMEDY, SERVE_BIND_STATUS_MAX_BYTES, SERVE_BIND_VERIFY_TIMEOUT_MS, SERVE_TAILSCALE_BIN_ENV, } from "./ops/serve-bind.js";
|
|
20
|
+
export { buildServeTaskScript, DEFAULT_SERVE_INSTALL_TIMEOUT_MS, installServeLogon, looksLikeCliEntrypoint, looksLikeMcpEntrypoint, resolveServeCliLaunch, sameWindowsAccount, sameWindowsSid, SERVE_NOT_READY_CODE, SERVE_TASK_OWNED_CODE, serveCommandFingerprint, serveTaskChildEnv, serveTaskLaunchEnv, uninstallServeLogon, } from "./ops/serve-install.js";
|
|
21
|
+
export { allocateLoopbackPort, assertSafeSshTunnelOpts, buildSshTunnelArgv, createServeTunnelManager, DEFAULT_SSH_PORT, DEFAULT_SSH_SERVE_PORT, describeServeTarget, formatSshServeTarget, forwardServe, isSshServeTarget, parseSshServeTarget, redactSshUserinfo, serveTunnelCacheKey, SSH_SERVE_REMOTE_HOST, SSH_TUNNEL_KEEPALIVE_COUNT, SSH_TUNNEL_KEEPALIVE_INTERVAL_S, stripControllerRouting, } from "./ops/serve-tunnel.js";
|
|
19
22
|
export { parseTabList, resolveTab } from "./zellij/tabs.js";
|
|
20
23
|
export { selectTargets } from "./ops/broadcast.js";
|
|
21
24
|
export { diffScreens, cursorKey } from "./ops/tail.js";
|
|
22
25
|
export { classify, lastLine, mapPool, peerStatus, DEFAULT_STATUS_TIMEOUT_MS, STATUS_DUMP_CONCURRENCY, } from "./ops/status.js";
|
|
23
26
|
export { normalizeScreen, truncateDumpText, DEFAULT_DUMP_MAX_CHARS, DEFAULT_WAIT_MAX_CHARS, } from "./ops/util.js";
|
|
27
|
+
export { DEFAULT_DOCTOR_TIMEOUT_MS, DOCTOR_FAILED_CODE, DOCTOR_SCOPE_FIELD, DOCTOR_SCOPE_HOST, DOCTOR_TAILSCALE_MAX_MS, HOST_REPORT_INCOMPLETE_CODE, HOST_REPORT_INVALID_CODE, doctorOp, inspectDoctorHost, coverHostReport, hostDoctorRequest, isRequiredFailure, mergeHostReply, } from "./ops/doctor.js";
|
|
24
28
|
export { normalizeKey, normalizeKeys, tokenizeCommand } from "./keys.js";
|
|
25
29
|
export { cliUsage, mcpInputSchema, parseCliArgv, MCP_TOOL_DESCRIPTION, OP_NAMES, PARAMS, TARGET_OPS, } from "./schema.js";
|
package/dist/ops/bus.js
CHANGED
|
@@ -296,8 +296,15 @@ export async function closeBusPluginPanes(client, session, pluginPath) {
|
|
|
296
296
|
}
|
|
297
297
|
return closed;
|
|
298
298
|
}
|
|
299
|
+
/** Effective SSH transport — not controller OS, not leftover ZSWARM_SSH in env. */
|
|
300
|
+
function isDirectSshClient(client) {
|
|
301
|
+
return client.remote || client.transport.kind === "ssh";
|
|
302
|
+
}
|
|
299
303
|
/** Report on the bus, install it, or forget it. */
|
|
300
304
|
export async function busOp(client, state, args, clock, env = process.env, policy) {
|
|
305
|
+
if ((isTrue(args.install) || isTrue(args.clear)) && isDirectSshClient(client)) {
|
|
306
|
+
throw new ZellijError("bus_remote_unsupported", "run on Zellij host or use --serve through a tunnel; direct SSH cannot install/clear the bus");
|
|
307
|
+
}
|
|
301
308
|
const sessionArg = typeof args.session === "string" ? args.session : undefined;
|
|
302
309
|
if (isTrue(args.clear)) {
|
|
303
310
|
let session = null;
|
package/dist/ops/dispatch.js
CHANGED
|
@@ -22,7 +22,10 @@ import { OP_NAMES } from "../schema.js";
|
|
|
22
22
|
import { dumpMaxChars, fail, isTrue, isVerbose, numberArg, optionalString, paneViewBus, paneViewFull, paneViewSlim, throwIfAborted, truncateDumpText, } from "./util.js";
|
|
23
23
|
import { waitForPane } from "./wait.js";
|
|
24
24
|
import { listPeerWorktrees, removePeerWorktree } from "./worktree.js";
|
|
25
|
-
import {
|
|
25
|
+
import { DEFAULT_SERVE_INSTALL_TIMEOUT_MS, installServeLogon, uninstallServeLogon, } from "./serve-install.js";
|
|
26
|
+
import { serveCallTimeout, } from "./serve.js";
|
|
27
|
+
import { doctorOp } from "./doctor.js";
|
|
28
|
+
import { forwardServe } from "./serve-tunnel.js";
|
|
26
29
|
/**
|
|
27
30
|
* Per-invocation routing from `--local` / `--ssh`. `--local` clears both SSH
|
|
28
31
|
* and serve (and remote IPC). `--ssh` sets the destination for this call and
|
|
@@ -171,18 +174,42 @@ async function dispatchOperation(args, injected, deps, context, env) {
|
|
|
171
174
|
// Policy gates the op before anything touches the session.
|
|
172
175
|
assertOpAllowed(policy, op);
|
|
173
176
|
assertSshGitAllowed(env, op, args);
|
|
177
|
+
if (op === "doctor") {
|
|
178
|
+
// Before serve forwarding and session resolution so a dead tunnel still
|
|
179
|
+
// yields controller findings. Policy already ran.
|
|
180
|
+
return await doctorOp(args, injected, deps, context, env, clock);
|
|
181
|
+
}
|
|
174
182
|
if (op === "serve") {
|
|
183
|
+
const timeoutMs = numberArg(args, "timeoutMs", DEFAULT_SERVE_INSTALL_TIMEOUT_MS, {
|
|
184
|
+
min: 1,
|
|
185
|
+
max: 900_000,
|
|
186
|
+
});
|
|
175
187
|
if (isTrue(args.clear)) {
|
|
176
188
|
const cleared = await uninstallServeLogon({
|
|
177
|
-
platform: process.platform,
|
|
189
|
+
platform: deps.serveInstall?.platform ?? process.platform,
|
|
190
|
+
timeoutMs,
|
|
191
|
+
signal,
|
|
192
|
+
env,
|
|
193
|
+
token: env.ZSWARM_SERVE_TOKEN,
|
|
194
|
+
...deps.serveInstall,
|
|
178
195
|
});
|
|
179
196
|
return { ok: true, data: cleared };
|
|
180
197
|
}
|
|
181
198
|
if (isTrue(args.install)) {
|
|
182
199
|
const installed = await installServeLogon({
|
|
183
200
|
listen: typeof args.listen === "string" ? args.listen : undefined,
|
|
201
|
+
session: optionalString(args.session),
|
|
202
|
+
timeoutMs,
|
|
203
|
+
signal,
|
|
204
|
+
env,
|
|
205
|
+
token: env.ZSWARM_SERVE_TOKEN,
|
|
206
|
+
now: clock.now,
|
|
207
|
+
sleep: clock.sleep,
|
|
208
|
+
tailscaleStatus: deps.tailscaleStatus,
|
|
209
|
+
networkInterfaces: deps.networkInterfaces,
|
|
210
|
+
...deps.serveInstall,
|
|
184
211
|
});
|
|
185
|
-
return { ok: true, data:
|
|
212
|
+
return { ok: true, data: installed };
|
|
186
213
|
}
|
|
187
214
|
throw new ZellijError("usage", "serve --listen is CLI-only; MCP/dispatch would hang the tool call. Run `zswarm serve --listen` in the session that owns Zellij");
|
|
188
215
|
}
|
|
@@ -190,8 +217,15 @@ async function dispatchOperation(args, injected, deps, context, env) {
|
|
|
190
217
|
// just because the host env has ZSWARM_SERVE set.
|
|
191
218
|
if (!injected && env.ZSWARM_SERVE?.trim()) {
|
|
192
219
|
const request = { ...attachKnownSender(args, env) };
|
|
193
|
-
|
|
194
|
-
|
|
220
|
+
return await forwardServe({
|
|
221
|
+
target: env.ZSWARM_SERVE.trim(),
|
|
222
|
+
args: request,
|
|
223
|
+
timeoutMs: serveCallTimeout(args),
|
|
224
|
+
token: env.ZSWARM_SERVE_TOKEN,
|
|
225
|
+
signal,
|
|
226
|
+
env,
|
|
227
|
+
manager: deps.serveTunnels,
|
|
228
|
+
});
|
|
195
229
|
}
|
|
196
230
|
const baseClient = injected ?? createZellijClient({ env, signal, cache: isTrue(args.fresh) ? false : undefined });
|
|
197
231
|
const client = {
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type ZellijClient } from "../zellij/client.js";
|
|
2
|
+
import { type StateStore } from "../state.js";
|
|
3
|
+
import type { RoutingContext } from "./routing.js";
|
|
4
|
+
import { type ServeHelloData } from "./serve.js";
|
|
5
|
+
import type { Clock, DispatchDeps, OpsResult } from "./types.js";
|
|
6
|
+
/** Overall doctor deadline when `timeoutMs` is omitted. */
|
|
7
|
+
export declare const DEFAULT_DOCTOR_TIMEOUT_MS = 10000;
|
|
8
|
+
/** Internal serve-worker flag. Never a public CLI flag or MCP param. */
|
|
9
|
+
export declare const DOCTOR_SCOPE_FIELD = "doctorScope";
|
|
10
|
+
export declare const DOCTOR_SCOPE_HOST = "host";
|
|
11
|
+
export declare const DOCTOR_FAILED_CODE = "doctor_failed";
|
|
12
|
+
/** Host doctor reply after hello was empty, malformed, or not a report. */
|
|
13
|
+
export declare const HOST_REPORT_INVALID_CODE = "host_report_invalid";
|
|
14
|
+
/** Host doctor reply omitted required host/session coverage. */
|
|
15
|
+
export declare const HOST_REPORT_INCOMPLETE_CODE = "host_report_incomplete";
|
|
16
|
+
/** Cap for optional Tailscale so required SSH/hello/session keep budget. */
|
|
17
|
+
export declare const DOCTOR_TAILSCALE_MAX_MS = 1500;
|
|
18
|
+
export type DoctorCheckState = "ok" | "warn" | "fail" | "skipped";
|
|
19
|
+
export type DoctorCheckScope = "controller" | "host";
|
|
20
|
+
export type DoctorCheck = {
|
|
21
|
+
id: string;
|
|
22
|
+
scope: DoctorCheckScope;
|
|
23
|
+
state: DoctorCheckState;
|
|
24
|
+
code: string;
|
|
25
|
+
elapsedMs: number;
|
|
26
|
+
detail: Record<string, unknown>;
|
|
27
|
+
remedy: string | null;
|
|
28
|
+
};
|
|
29
|
+
export type DoctorRoute = {
|
|
30
|
+
transport: "local" | "ssh" | "serve";
|
|
31
|
+
endpoint: string;
|
|
32
|
+
session: string | null;
|
|
33
|
+
sessionOrigin: string;
|
|
34
|
+
};
|
|
35
|
+
export type DoctorReport = {
|
|
36
|
+
route: DoctorRoute;
|
|
37
|
+
server?: ServeHelloData;
|
|
38
|
+
checks: DoctorCheck[];
|
|
39
|
+
};
|
|
40
|
+
export type HostInspectInput = {
|
|
41
|
+
client: ZellijClient;
|
|
42
|
+
state: StateStore;
|
|
43
|
+
env: NodeJS.ProcessEnv;
|
|
44
|
+
sessionArg?: string | null;
|
|
45
|
+
clock: Clock;
|
|
46
|
+
timeoutMs: number;
|
|
47
|
+
signal?: AbortSignal;
|
|
48
|
+
/** Direct SSH cannot treat controller-local bus files as host facts. */
|
|
49
|
+
busUnsupported?: boolean;
|
|
50
|
+
busRemedy?: string;
|
|
51
|
+
};
|
|
52
|
+
export type HostInspectResult = {
|
|
53
|
+
checks: DoctorCheck[];
|
|
54
|
+
session: string | null;
|
|
55
|
+
sessionOrigin: string;
|
|
56
|
+
cancelled?: boolean;
|
|
57
|
+
timedOut?: boolean;
|
|
58
|
+
};
|
|
59
|
+
/** Required-layer failure using accepted doctor semantics. Host install must reuse this. */
|
|
60
|
+
export declare function isRequiredFailure(report: DoctorReport, item: DoctorCheck): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Passive host inspection. Safe reads only: binary/version via the client,
|
|
63
|
+
* session listing, pane listing for an existing plugin pane, and StateStore
|
|
64
|
+
* reads. Never pipes, launches, nudges, or writes markers.
|
|
65
|
+
*/
|
|
66
|
+
export declare function inspectDoctorHost(input: HostInspectInput): Promise<HostInspectResult>;
|
|
67
|
+
export declare function hostDoctorRequest(remainingMs: number, explicitSession: string | null): Record<string, unknown>;
|
|
68
|
+
export declare function coverHostReport(checks: DoctorCheck[], explicit: string | null): DoctorCheck[];
|
|
69
|
+
export declare function mergeHostReply(result: OpsResult): {
|
|
70
|
+
checks: DoctorCheck[];
|
|
71
|
+
session?: string | null;
|
|
72
|
+
sessionOrigin?: string;
|
|
73
|
+
unsupported?: boolean;
|
|
74
|
+
invalid?: boolean;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Inspect-only layered diagnostics. Handle this before ordinary serve
|
|
78
|
+
* forwarding so a dead tunnel still reports controller findings.
|
|
79
|
+
*/
|
|
80
|
+
export declare function doctorOp(args: Record<string, unknown>, injected: ZellijClient | undefined, deps: DispatchDeps, context: RoutingContext, env: NodeJS.ProcessEnv, clock: Clock): Promise<OpsResult>;
|