@zswarm/core 0.6.0 → 0.7.0
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/dist/host/cli.js +5 -1
- package/dist/host/relay.d.ts +7 -0
- package/dist/host/relay.js +32 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/host/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { ZellijError } from "../errors.js";
|
|
3
|
-
import { createStateStore } from "../state.js";
|
|
3
|
+
import { createStateStore, defaultStateDir } from "../state.js";
|
|
4
4
|
import { crewCheck, crewClient, crewDown, crewStart, crewStatus, crewUp } from "./crew.js";
|
|
5
5
|
import { hostDoctor, hostInstall, hostInstallArgs, hostScriptPath } from "./host.js";
|
|
6
6
|
import { listLeases } from "./lease.js";
|
|
@@ -151,6 +151,10 @@ async function relay(argv) {
|
|
|
151
151
|
if (flags["--json"] === true)
|
|
152
152
|
return json(() => ({ leases }));
|
|
153
153
|
process.stdout.write(`${leaseTable(leases)}\n`);
|
|
154
|
+
if (leases.length === 0) {
|
|
155
|
+
// A tool that runs zswarm with its own ZSWARM_STATE_DIR keeps its leases there.
|
|
156
|
+
process.stderr.write(`no live leases in ${defaultStateDir()}; set ZSWARM_STATE_DIR to read another state directory\n`);
|
|
157
|
+
}
|
|
154
158
|
return 0;
|
|
155
159
|
}
|
|
156
160
|
const cancelId = str(flags["--cancel"]);
|
package/dist/host/relay.d.ts
CHANGED
|
@@ -46,6 +46,9 @@ export type RelayConfig = {
|
|
|
46
46
|
to: string;
|
|
47
47
|
done: string;
|
|
48
48
|
replyTo: string;
|
|
49
|
+
/** The reply pane's unique title when `replyTo` was a pane id: delivery tries
|
|
50
|
+
* the name first, because ids shift when panes are restarted or renumbered. */
|
|
51
|
+
replyToName?: string;
|
|
49
52
|
replySession?: string;
|
|
50
53
|
from: string;
|
|
51
54
|
/** The target harness (`--harness`); sent with the body and the reply. */
|
|
@@ -112,6 +115,10 @@ export declare function fillMessage(template: string, fields: Record<string, str
|
|
|
112
115
|
* the verdict and keeps waiting — the done line is the real proof of delivery.
|
|
113
116
|
*/
|
|
114
117
|
export declare function softSendVerdict(res: OpsResult): boolean;
|
|
118
|
+
/** The unique title of the reply pane when `replyTo` is a pane id (`terminal_14`, `14`),
|
|
119
|
+
* else undefined: an untitled pane (default shell title) or a title shared by two panes
|
|
120
|
+
* keeps delivery by id. */
|
|
121
|
+
export declare function replyPaneName(cfg: Pick<RelayConfig, "replyTo" | "replySession">, env: NodeJS.ProcessEnv, call: NonNullable<RelayDeps["call"]>): Promise<string | undefined>;
|
|
115
122
|
/** Paste `body` into the reply pane, retrying with backoff; false leaves it in undelivered/. */
|
|
116
123
|
export declare function deliverMessage(cfg: RelayConfig, body: string, dir: string, deps?: RelayDeps): Promise<boolean>;
|
|
117
124
|
/** The waiting loop; returns the final status and the message it delivered or left behind. */
|
package/dist/host/relay.js
CHANGED
|
@@ -111,6 +111,28 @@ export function softSendVerdict(res) {
|
|
|
111
111
|
const submitted = res.data?.submitted;
|
|
112
112
|
return submitted !== true;
|
|
113
113
|
}
|
|
114
|
+
/** The unique title of the reply pane when `replyTo` is a pane id (`terminal_14`, `14`),
|
|
115
|
+
* else undefined: an untitled pane (default shell title) or a title shared by two panes
|
|
116
|
+
* keeps delivery by id. */
|
|
117
|
+
export async function replyPaneName(cfg, env, call) {
|
|
118
|
+
const ref = cfg.replyTo.trim();
|
|
119
|
+
if (!/^(terminal_)?\d+$/i.test(ref))
|
|
120
|
+
return undefined;
|
|
121
|
+
const args = { op: "list" };
|
|
122
|
+
if (cfg.replySession)
|
|
123
|
+
args.session = cfg.replySession;
|
|
124
|
+
const res = await call(args, localEnv(env)).catch(() => null);
|
|
125
|
+
if (!res?.ok)
|
|
126
|
+
return undefined;
|
|
127
|
+
const panes = (res.data.panes ?? [])
|
|
128
|
+
.filter((p) => !p.isPlugin);
|
|
129
|
+
const id = `terminal_${ref.replace(/^terminal_/i, "")}`;
|
|
130
|
+
const title = panes.find((p) => p.id === id)?.title?.trim();
|
|
131
|
+
if (!title || /^(Pane #\d+|-?(zsh|bash|fish|sh|pwsh|powershell))$/i.test(title))
|
|
132
|
+
return undefined;
|
|
133
|
+
const same = panes.filter((p) => (p.title ?? "").trim().toLowerCase() === title.toLowerCase());
|
|
134
|
+
return same.length === 1 ? title : undefined;
|
|
135
|
+
}
|
|
114
136
|
/** Paste `body` into the reply pane, retrying with backoff; false leaves it in undelivered/. */
|
|
115
137
|
export async function deliverMessage(cfg, body, dir, deps = {}) {
|
|
116
138
|
const env = deps.env ?? process.env;
|
|
@@ -125,13 +147,20 @@ export async function deliverMessage(cfg, body, dir, deps = {}) {
|
|
|
125
147
|
await sleep(delay * 1000);
|
|
126
148
|
// Generous Zellij budgets: this runs exactly when the machine is busiest.
|
|
127
149
|
const args = {
|
|
128
|
-
op: "send", to: cfg.replyTo, body, from: cfg.from, fresh: true, settleMs: 800, observeMs: 30_000,
|
|
150
|
+
op: "send", to: cfg.replyToName ?? cfg.replyTo, body, from: cfg.from, fresh: true, settleMs: 800, observeMs: 30_000,
|
|
151
|
+
timeoutMs: 60_000,
|
|
129
152
|
};
|
|
130
153
|
if (cfg.replySession)
|
|
131
154
|
args.session = cfg.replySession;
|
|
132
155
|
if (cfg.harness)
|
|
133
156
|
args.harness = cfg.harness;
|
|
134
|
-
const
|
|
157
|
+
const send = (a) => call(a, localEnv(env)).catch((err) => ({ ok: false, error: { code: "failed", message: String(err) } }));
|
|
158
|
+
let res = await send(args);
|
|
159
|
+
if (!res.ok && cfg.replyToName && (res.error.code === "peer_not_found" || res.error.code === "peer_ambiguous")) {
|
|
160
|
+
// The named pane is gone or now ambiguous: the id it had at start is the last resort.
|
|
161
|
+
log(`message attempt ${i + 1}: pane "${cfg.replyToName}" ${res.error.code}; trying ${cfg.replyTo}`);
|
|
162
|
+
res = await send({ ...args, to: cfg.replyTo });
|
|
163
|
+
}
|
|
135
164
|
if (res.ok) {
|
|
136
165
|
const submitted = String(res.data?.submitted ?? "unknown");
|
|
137
166
|
recordDelivery(dir, submitted, now());
|
|
@@ -430,6 +459,7 @@ export async function startRelay(input) {
|
|
|
430
459
|
};
|
|
431
460
|
// Read the body before the relay directory (and its token copy) exists.
|
|
432
461
|
const body = input.bodyFile ? readFileSync(input.bodyFile, "utf8") : undefined;
|
|
462
|
+
cfg.replyToName = await replyPaneName(cfg, env, input.deps?.call ?? ((args, e) => dispatchZswarm(args, undefined, { env: e })));
|
|
433
463
|
const dir = prepareRelay(cfg, { check: input.check, message: input.message }, env);
|
|
434
464
|
const store = input.store ?? createStateStore({ env });
|
|
435
465
|
const leaseTarget = { serve, session: cfg.session, pane: cfg.to };
|
package/dist/index.d.ts
CHANGED
|
@@ -39,6 +39,6 @@ export { findPython, runSlot, slotScriptPath } from "./host/slot.js";
|
|
|
39
39
|
export { installServeService, serveServiceName, serveServiceSpec, serveTokenFromEnv, serveTokenPath, uninstallServeService, SERVE_AWAIT_SESSION_ENV, SERVE_TOKEN_FILE_ENV, type ServeServiceInput, } from "./host/serve-service.js";
|
|
40
40
|
export { accountArgv, installServices, launchdLabel, launchdPlist, removeServices, serviceAccount, serviceStates, systemdUnitName, systemdUnits, writeAccountFile, type Runner, type ServiceAccount, type ServiceHost, type ServiceKind, type ServiceSpec, type ServiceState, } from "./host/services.js";
|
|
41
41
|
export { crewCheck, crewClient, crewDir, crewDown, crewServiceSpecs, crewStart, crewStatus, crewUp, firstLayoutPane, layoutPaneNames, parseEnvFile, type CrewDeps, type CrewUpInput, } from "./host/crew.js";
|
|
42
|
-
export { cancelAllTo, cancelRelay, deliverMessage, doneLines, fillMessage, freshDoneLine, launchRelay, listRelays, prepareRelay, pruneRelays, relayLoop, relaysDir, runRelayDir, scrubRelayToken, startRelay, waitForRelay, type RelayAdminDeps, type RelayCancelResult, type RelayConfig, type RelayDeps, type RelayJob, type RelayJobRunner, type RelayRow, type RelayStartInput, type RelayStatus, } from "./host/relay.js";
|
|
42
|
+
export { cancelAllTo, cancelRelay, deliverMessage, doneLines, fillMessage, freshDoneLine, launchRelay, listRelays, prepareRelay, pruneRelays, relayLoop, relaysDir, replyPaneName, runRelayDir, scrubRelayToken, startRelay, waitForRelay, type RelayAdminDeps, type RelayCancelResult, type RelayConfig, type RelayDeps, type RelayJob, type RelayJobRunner, type RelayRow, type RelayStartInput, type RelayStatus, } from "./host/relay.js";
|
|
43
43
|
export { hostChecks, hostDoctor, hostInstall, hostInstallArgs, hostScriptPath, parseHostReport, type HostCheck, type HostDoctorInput, type HostInstallInput, type SshRunner, } from "./host/host.js";
|
|
44
44
|
export { isSelfPane } from "./ops/guards.js";
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,6 @@ export { findPython, runSlot, slotScriptPath } from "./host/slot.js";
|
|
|
37
37
|
export { installServeService, serveServiceName, serveServiceSpec, serveTokenFromEnv, serveTokenPath, uninstallServeService, SERVE_AWAIT_SESSION_ENV, SERVE_TOKEN_FILE_ENV, } from "./host/serve-service.js";
|
|
38
38
|
export { accountArgv, installServices, launchdLabel, launchdPlist, removeServices, serviceAccount, serviceStates, systemdUnitName, systemdUnits, writeAccountFile, } from "./host/services.js";
|
|
39
39
|
export { crewCheck, crewClient, crewDir, crewDown, crewServiceSpecs, crewStart, crewStatus, crewUp, firstLayoutPane, layoutPaneNames, parseEnvFile, } from "./host/crew.js";
|
|
40
|
-
export { cancelAllTo, cancelRelay, deliverMessage, doneLines, fillMessage, freshDoneLine, launchRelay, listRelays, prepareRelay, pruneRelays, relayLoop, relaysDir, runRelayDir, scrubRelayToken, startRelay, waitForRelay, } from "./host/relay.js";
|
|
40
|
+
export { cancelAllTo, cancelRelay, deliverMessage, doneLines, fillMessage, freshDoneLine, launchRelay, listRelays, prepareRelay, pruneRelays, relayLoop, relaysDir, replyPaneName, runRelayDir, scrubRelayToken, startRelay, waitForRelay, } from "./host/relay.js";
|
|
41
41
|
export { hostChecks, hostDoctor, hostInstall, hostInstallArgs, hostScriptPath, parseHostReport, } from "./host/host.js";
|
|
42
42
|
export { isSelfPane } from "./ops/guards.js";
|