@zswarm/core 0.1.0 → 0.1.1
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/ops/bus.d.ts +1 -0
- package/dist/ops/bus.js +29 -2
- package/dist/schema.d.ts +0 -1
- package/dist/schema.js +20 -1
- package/package.json +2 -2
package/dist/ops/bus.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare function planBus(client: ZellijClient, state: StateStore, env?: N
|
|
|
23
23
|
* message and replies with nothing, so each attempt rotates to a new key. And a
|
|
24
24
|
* freshly launched instance replies before Zellij has pushed it a manifest, so
|
|
25
25
|
* a not-ready answer is retried once rather than reported as an empty session.
|
|
26
|
+
* If it is still cold after that, one same-title rename nudges Zellij to push.
|
|
26
27
|
*/
|
|
27
28
|
export declare function busSnapshot(client: ZellijClient, state: StateStore, session: string, clock: Clock, env?: NodeJS.ProcessEnv, payload?: string): Promise<{
|
|
28
29
|
snapshot: BusSnapshot;
|
package/dist/ops/bus.js
CHANGED
|
@@ -53,7 +53,7 @@ export function planBus(client, state, env = process.env) {
|
|
|
53
53
|
if (!plugin) {
|
|
54
54
|
return {
|
|
55
55
|
...base,
|
|
56
|
-
reason: "no plugin wasm found; build
|
|
56
|
+
reason: "no plugin wasm found; run pnpm build:plugin or set ZSWARM_BUS_PLUGIN",
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
if (processDisabled)
|
|
@@ -69,6 +69,19 @@ async function askOnce(client, session, url, configKey, payload) {
|
|
|
69
69
|
const result = await client.pipePlugin({ session, url, configKey, payload });
|
|
70
70
|
return parseBusReply(result.stdout);
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Zellij pushes a pane manifest on change, never on subscribe — there is no
|
|
74
|
+
* get_pane_manifest(). A quiet session leaves a freshly launched instance
|
|
75
|
+
* blind (ready:false, paneUpdates:0) until something moves. Renaming a pane
|
|
76
|
+
* to the title it already has is an invisible change that forces the push.
|
|
77
|
+
*/
|
|
78
|
+
async function nudgeManifest(client, session) {
|
|
79
|
+
const panes = await client.listPanes(session);
|
|
80
|
+
const pane = panes.find((p) => !p.isPlugin && !p.exited && p.title.trim());
|
|
81
|
+
if (!pane)
|
|
82
|
+
return;
|
|
83
|
+
await client.renamePane({ session, paneId: pane.id, name: pane.title });
|
|
84
|
+
}
|
|
72
85
|
/**
|
|
73
86
|
* One pipe, one answer — or null, and the caller polls instead.
|
|
74
87
|
*
|
|
@@ -76,6 +89,7 @@ async function askOnce(client, session, url, configKey, payload) {
|
|
|
76
89
|
* message and replies with nothing, so each attempt rotates to a new key. And a
|
|
77
90
|
* freshly launched instance replies before Zellij has pushed it a manifest, so
|
|
78
91
|
* a not-ready answer is retried once rather than reported as an empty session.
|
|
92
|
+
* If it is still cold after that, one same-title rename nudges Zellij to push.
|
|
79
93
|
*/
|
|
80
94
|
export async function busSnapshot(client, state, session, clock, env = process.env, payload = "status") {
|
|
81
95
|
const plan = planBus(client, state, env);
|
|
@@ -83,6 +97,7 @@ export async function busSnapshot(client, state, session, clock, env = process.e
|
|
|
83
97
|
if (!plan.enabled || !plan.url || !pluginPath)
|
|
84
98
|
return null;
|
|
85
99
|
let configKey = answeredWith.get(session) ?? plan.configKey;
|
|
100
|
+
let nudged = false;
|
|
86
101
|
for (let attempt = 0; attempt < MAX_KEY_ATTEMPTS; attempt++) {
|
|
87
102
|
let snapshot = await askOnce(client, session, plan.url, configKey, payload);
|
|
88
103
|
if (snapshot && !snapshot.ready) {
|
|
@@ -91,6 +106,18 @@ export async function busSnapshot(client, state, session, clock, env = process.e
|
|
|
91
106
|
(await askOnce(client, session, plan.url, configKey, payload)) ??
|
|
92
107
|
snapshot;
|
|
93
108
|
}
|
|
109
|
+
if (snapshot && !snapshot.ready && !nudged) {
|
|
110
|
+
nudged = true;
|
|
111
|
+
try {
|
|
112
|
+
await nudgeManifest(client, session);
|
|
113
|
+
snapshot =
|
|
114
|
+
(await askOnce(client, session, plan.url, configKey, payload)) ??
|
|
115
|
+
snapshot;
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// A failed nudge must not fail the op — the caller polls instead.
|
|
119
|
+
}
|
|
120
|
+
}
|
|
94
121
|
if (snapshot) {
|
|
95
122
|
answeredWith.set(session, configKey);
|
|
96
123
|
if (plan.installed && configKey !== plan.configKey) {
|
|
@@ -205,7 +232,7 @@ export async function busOp(client, state, args, clock, env = process.env, polic
|
|
|
205
232
|
}
|
|
206
233
|
const plugin = resolveBusPlugin(env);
|
|
207
234
|
if (!plugin) {
|
|
208
|
-
throw new ZellijError("bus_missing", "no plugin wasm found; build
|
|
235
|
+
throw new ZellijError("bus_missing", "no plugin wasm found; run pnpm build:plugin or set ZSWARM_BUS_PLUGIN");
|
|
209
236
|
}
|
|
210
237
|
const previous = state.readBus();
|
|
211
238
|
const force = isTrue(args.force);
|
package/dist/schema.d.ts
CHANGED
|
@@ -22,5 +22,4 @@ export declare const PARAMS: readonly ParamSpec[];
|
|
|
22
22
|
export declare function mcpInputSchema(): Record<string, unknown>;
|
|
23
23
|
export declare const MCP_TOOL_DESCRIPTION: string;
|
|
24
24
|
export declare function cliUsage(): string;
|
|
25
|
-
/** Turn argv (without the op) into dispatch args, driven by PARAMS. */
|
|
26
25
|
export declare function parseCliArgv(argv: string[]): Record<string, unknown>;
|
package/dist/schema.js
CHANGED
|
@@ -443,8 +443,27 @@ export function cliUsage() {
|
|
|
443
443
|
return lines.join("\n");
|
|
444
444
|
}
|
|
445
445
|
/** Turn argv (without the op) into dispatch args, driven by PARAMS. */
|
|
446
|
+
/**
|
|
447
|
+
* Pull the op out of argv, tolerating flags before it.
|
|
448
|
+
*
|
|
449
|
+
* The op normally comes first. When it does not — `zswarm --session crew list`
|
|
450
|
+
* — the first token is a flag, and taking argv[0] blindly reported the flag as
|
|
451
|
+
* an unknown op. Only positions that already errored are affected: if argv[0]
|
|
452
|
+
* is a real op it wins, so `send reviewer list` still sends the word "list".
|
|
453
|
+
*/
|
|
454
|
+
function extractOp(argv) {
|
|
455
|
+
const first = argv[0];
|
|
456
|
+
if (first && !first.startsWith("-")) {
|
|
457
|
+
return { op: first, rest: argv.slice(1) };
|
|
458
|
+
}
|
|
459
|
+
const names = OP_NAMES;
|
|
460
|
+
const at = argv.findIndex((token) => names.includes(token));
|
|
461
|
+
if (at === -1)
|
|
462
|
+
return { op: first ?? "", rest: argv.slice(1) };
|
|
463
|
+
return { op: argv[at], rest: [...argv.slice(0, at), ...argv.slice(at + 1)] };
|
|
464
|
+
}
|
|
446
465
|
export function parseCliArgv(argv) {
|
|
447
|
-
const
|
|
466
|
+
const { op, rest } = extractOp(argv);
|
|
448
467
|
if (!op)
|
|
449
468
|
throw new ZellijError("usage", "no op given");
|
|
450
469
|
const out = { op };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zswarm/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "zSwarm Zellij client and shared ops dispatch",
|
|
6
6
|
"exports": {
|
|
@@ -29,6 +29,6 @@
|
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"build": "tsc -p tsconfig.json",
|
|
32
|
-
"test": "pnpm run build && node --test
|
|
32
|
+
"test": "pnpm run build && node --test"
|
|
33
33
|
}
|
|
34
34
|
}
|