seatmesh 0.1.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/chat-cli.d.ts +4 -0
- package/dist/chat-cli.d.ts.map +1 -0
- package/dist/chat-cli.js +162 -0
- package/dist/chat-cli.js.map +1 -0
- package/dist/checkback-cli.d.ts +4 -0
- package/dist/checkback-cli.d.ts.map +1 -0
- package/dist/checkback-cli.js +103 -0
- package/dist/checkback-cli.js.map +1 -0
- package/dist/contract-lock-cli.d.ts +4 -0
- package/dist/contract-lock-cli.d.ts.map +1 -0
- package/dist/contract-lock-cli.js +180 -0
- package/dist/contract-lock-cli.js.map +1 -0
- package/dist/init.d.ts +19 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +63 -0
- package/dist/init.js.map +1 -0
- package/dist/init.test.d.ts +2 -0
- package/dist/init.test.d.ts.map +1 -0
- package/dist/init.test.js +37 -0
- package/dist/init.test.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +868 -0
- package/dist/main.js.map +1 -0
- package/dist/migrate-runtime.d.ts +15 -0
- package/dist/migrate-runtime.d.ts.map +1 -0
- package/dist/migrate-runtime.js +67 -0
- package/dist/migrate-runtime.js.map +1 -0
- package/dist/room-cli.d.ts +5 -0
- package/dist/room-cli.d.ts.map +1 -0
- package/dist/room-cli.js +301 -0
- package/dist/room-cli.js.map +1 -0
- package/dist/room.d.ts +4 -0
- package/dist/room.d.ts.map +1 -0
- package/dist/room.js +149 -0
- package/dist/room.js.map +1 -0
- package/dist/status-report.d.ts +20 -0
- package/dist/status-report.d.ts.map +1 -0
- package/dist/status-report.js +218 -0
- package/dist/status-report.js.map +1 -0
- package/dist/update.d.ts +15 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +89 -0
- package/dist/update.js.map +1 -0
- package/dist/watch-daemon.d.ts +2 -0
- package/dist/watch-daemon.d.ts.map +1 -0
- package/dist/watch-daemon.js +41 -0
- package/dist/watch-daemon.js.map +1 -0
- package/dist/work-daemon.d.ts +2 -0
- package/dist/work-daemon.d.ts.map +1 -0
- package/dist/work-daemon.js +42 -0
- package/dist/work-daemon.js.map +1 -0
- package/package.json +29 -0
- package/templates/init/README.md +20 -0
- package/templates/init/mesh-agents.json +16 -0
- package/templates/init/mesh.config.yaml +94 -0
- package/templates/init/roles/common.yaml +5 -0
- package/templates/init/roles/master.yaml +5 -0
- package/templates/init/roles/secretary.yaml +2 -0
- package/templates/init/roles/worker.yaml +2 -0
package/dist/main.js
ADDED
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { loadProfile, profilePaths, loadRoleIndex, renderRoleIndex, validateRoleIndex, runStackPassthrough, } from "seat-mesh-core";
|
|
3
|
+
import { snapshotConnectivity, formatStatus } from "seat-mesh-connectivity";
|
|
4
|
+
import { createRegistryForProfile } from "seat-mesh-providers";
|
|
5
|
+
import { printWhoami, printAgentCard, runWhoami, capturePaneSnapshot, listSessionPanes, sessionAttach, sessionUp, sessionStatus, relayoutMeshSession, reloadMesh, ensureMeshInbox, startMeshInbox, stopMeshInbox, restartMeshInbox, printMeshInboxStatus, sendToMaster, secretaryLaunch, secretaryRestart, secretaryDispatch, secretaryCollect, secretaryMeshWatch, secretarySupervise, secretaryStatus, printMiniList, miniSpawn, miniPrompt, miniDone, miniSpawnAll, runMeshSmoke, printSmokeResults, launchSession, printLaunchResults, enqueuePrompt, runRemind, printRemindResults, verifyMeshSession, printVerify, labelMeshSession, liveMeshSession, ensureBaseLayout, applyMeshSessionBorders, runFlush, printFlushResults, runSwitch, setPaneTitle, setPaneStatus, printSeatContexts, runPeek, runPpa, runToSlot, runToMini, applyMeshState, saveMeshSession, submitPaneOp, clearPaneOpsQueue, printPaneOpsList, printRelayoutPlan, assertRelayoutSafe, buildFullColdStartBrief, enqueueColdStart, runSeatInit, } from "seat-mesh-tmux";
|
|
6
|
+
import { buildChatCommands } from "./chat-cli.js";
|
|
7
|
+
import { buildCheckbackCommands } from "./checkback-cli.js";
|
|
8
|
+
import { buildContractLockCommands } from "./contract-lock-cli.js";
|
|
9
|
+
import { buildRoomCommands } from "./room-cli.js";
|
|
10
|
+
import { runInit } from "./init.js";
|
|
11
|
+
function parseArgs(argv) {
|
|
12
|
+
const profileFlag = [];
|
|
13
|
+
const rest = [];
|
|
14
|
+
for (let i = 0; i < argv.length; i++) {
|
|
15
|
+
const a = argv[i];
|
|
16
|
+
if (a === "--profile" || a === "-p") {
|
|
17
|
+
const v = argv[++i];
|
|
18
|
+
if (!v)
|
|
19
|
+
throw new Error("--profile requires a path");
|
|
20
|
+
profileFlag.push(v);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
rest.push(a);
|
|
24
|
+
}
|
|
25
|
+
return { profile: profileFlag[0], rest };
|
|
26
|
+
}
|
|
27
|
+
/** Profile yaml + mesh-agents.json layout overrides (yaml is fallback only). */
|
|
28
|
+
function meshLoaded(profileArg) {
|
|
29
|
+
return applyMeshState(loadProfile(profileArg));
|
|
30
|
+
}
|
|
31
|
+
function usage(loaded) {
|
|
32
|
+
const prof = loaded ? `profile=${loaded.profile.name}` : "";
|
|
33
|
+
console.log(`seat-mesh${prof ? ` (${prof})` : ""} — profile-driven tmux multi-agent CLI
|
|
34
|
+
|
|
35
|
+
Docs: README.md + docs/ONE-PATH.md + docs/QUICKSTART.md
|
|
36
|
+
Cold start: bin/seat-mesh auto-runs npm install + build when dist is stale
|
|
37
|
+
|
|
38
|
+
init [--force] [--seats-root PATH] [--name NAME] create .sm/ dotdir
|
|
39
|
+
update [--dry-run] [--migrate] refresh _vendor templates + paths.json
|
|
40
|
+
report [--json] full stack report (same as bare npx seat-mesh)
|
|
41
|
+
session attach|up|status
|
|
42
|
+
verify layout + labels health
|
|
43
|
+
reload [--layout] rebuild engine + labels (no session kill; --layout re-grids)
|
|
44
|
+
layout [--no-leads] [--dry-run] [--yes] workers + minis grid (queued)
|
|
45
|
+
ops list|clear pane-op queue (serial)
|
|
46
|
+
save|auto scrape session -> mesh-agents.json (daemon also auto-scrapes every 10m)
|
|
47
|
+
labels re-apply @mesh_* + border strip
|
|
48
|
+
inbox [--json] | inbox stop|restart
|
|
49
|
+
peer <target> <msg...> manager -> any pane (one path; alias: prompt -m)
|
|
50
|
+
to-master | to-slot | to-mini <msg...> enqueue (daemon injects)
|
|
51
|
+
secretary start|dispatch|collect|status|watch …
|
|
52
|
+
mini list|spawn|prompt|done|dispatch-all
|
|
53
|
+
checkback start|list|cancel|cancel-all (alias: patience)
|
|
54
|
+
test smoke: layout, providers, inbox, proxy
|
|
55
|
+
launch [--now] [targets…]
|
|
56
|
+
prompt | remind | flush
|
|
57
|
+
contexts [--json] | peek | ppa
|
|
58
|
+
switch | handoff | title | status
|
|
59
|
+
agent [target] scoped can/cannot for this pane (profile role)
|
|
60
|
+
whoami [target] | cold-start [--inject] | seat init
|
|
61
|
+
room | chat | index | proxy | providers | manager | stack | profile show
|
|
62
|
+
|
|
63
|
+
--profile <dir|yaml> override config (default: .sm/ walk-up or bundled profile)
|
|
64
|
+
`);
|
|
65
|
+
}
|
|
66
|
+
async function main() {
|
|
67
|
+
const { profile: profileArg, rest } = parseArgs(process.argv.slice(2));
|
|
68
|
+
const [cmd, sub, ...tail] = rest;
|
|
69
|
+
if (!cmd) {
|
|
70
|
+
const loaded = meshLoaded(profileArg);
|
|
71
|
+
const { printStatusReport } = await import("./status-report.js");
|
|
72
|
+
const report = await printStatusReport(loaded, { json: rest.includes("--json") });
|
|
73
|
+
process.exit(report.ok ? 0 : 1);
|
|
74
|
+
}
|
|
75
|
+
if (cmd === "-h" || cmd === "--help" || cmd === "help") {
|
|
76
|
+
usage(meshLoaded(profileArg));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (cmd === "update") {
|
|
80
|
+
const { runUpdate } = await import("./update.js");
|
|
81
|
+
const dryRun = rest.includes("--dry-run");
|
|
82
|
+
const migrate = rest.includes("--migrate");
|
|
83
|
+
const r = runUpdate({ profileArg, dryRun, migrate });
|
|
84
|
+
console.log(`OK: update dryRun=${dryRun} migrate=${migrate}`);
|
|
85
|
+
console.log(` paths: ${r.pathsManifest}`);
|
|
86
|
+
for (const line of r.refreshed)
|
|
87
|
+
console.log(` refreshed: ${line}`);
|
|
88
|
+
for (const line of r.skipped)
|
|
89
|
+
console.log(` skipped (exists): ${line}`);
|
|
90
|
+
if (r.migrate) {
|
|
91
|
+
for (const line of r.migrate.copied)
|
|
92
|
+
console.log(` migrate copied: ${line}`);
|
|
93
|
+
for (const line of r.migrate.skipped)
|
|
94
|
+
console.log(` migrate skipped: ${line}`);
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (cmd === "migrate-runtime") {
|
|
99
|
+
const { runMigrateRuntime } = await import("./migrate-runtime.js");
|
|
100
|
+
const dryRun = rest.includes("--dry-run");
|
|
101
|
+
const noSeats = rest.includes("--no-seats");
|
|
102
|
+
const r = runMigrateRuntime({ profileArg, dryRun, seats: !noSeats });
|
|
103
|
+
console.log(`OK: migrate-runtime dryRun=${dryRun}`);
|
|
104
|
+
for (const line of r.copied)
|
|
105
|
+
console.log(` copied: ${line}`);
|
|
106
|
+
for (const line of r.skipped)
|
|
107
|
+
console.log(` skipped: ${line}`);
|
|
108
|
+
for (const line of r.notes)
|
|
109
|
+
console.log(` note: ${line}`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (cmd === "init") {
|
|
113
|
+
const force = rest.includes("--force");
|
|
114
|
+
const seatsIdx = rest.indexOf("--seats-root");
|
|
115
|
+
const seatsRoot = seatsIdx >= 0 && rest[seatsIdx + 1] ? rest[seatsIdx + 1] : undefined;
|
|
116
|
+
const nameIdx = rest.indexOf("--name");
|
|
117
|
+
const name = nameIdx >= 0 && rest[nameIdx + 1] ? rest[nameIdx + 1] : undefined;
|
|
118
|
+
const r = runInit({ force, seatsRoot, name });
|
|
119
|
+
console.log(`OK: init ${r.smDir}`);
|
|
120
|
+
console.log(` config: ${r.configPath}`);
|
|
121
|
+
console.log(` created: ${r.created.length} file(s)`);
|
|
122
|
+
if (r.skipped.length)
|
|
123
|
+
console.log(` skipped (exists): ${r.skipped.length}`);
|
|
124
|
+
console.log(" next: npx seat-mesh session up (or ./sm.sh if wired)");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (cmd === "profile" && sub === "show") {
|
|
128
|
+
const loaded = meshLoaded(profileArg);
|
|
129
|
+
const paths = profilePaths(loaded);
|
|
130
|
+
console.log(`name=${loaded.profile.name}`);
|
|
131
|
+
console.log(`path=${loaded.profilePath}`);
|
|
132
|
+
console.log(`workspace=${loaded.workspace}`);
|
|
133
|
+
console.log(`workspace_id=${loaded.workspaceId}`);
|
|
134
|
+
console.log(`session_name=${loaded.sessionName}`);
|
|
135
|
+
console.log(`daemon_port=${paths.daemonPort}`);
|
|
136
|
+
console.log(`data_root=${paths.dataRoot}`);
|
|
137
|
+
console.log(`daemon_dir=${paths.daemonDir}`);
|
|
138
|
+
console.log(`seats_root=${paths.seatsRoot}`);
|
|
139
|
+
console.log(`roles_dir=${paths.rolesDir}`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (cmd === "session") {
|
|
143
|
+
const loaded = meshLoaded(profileArg);
|
|
144
|
+
if (sub === "up") {
|
|
145
|
+
sessionUp(loaded);
|
|
146
|
+
console.log(`OK: session '${loaded.sessionName}' created`);
|
|
147
|
+
printMeshInboxStatus(loaded);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (sub === "attach" || !sub) {
|
|
151
|
+
sessionAttach(loaded);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (sub === "status") {
|
|
155
|
+
sessionStatus(loaded);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
console.error("usage: session attach|up|status");
|
|
159
|
+
process.exit(2);
|
|
160
|
+
}
|
|
161
|
+
if (cmd === "verify") {
|
|
162
|
+
const loaded = meshLoaded(profileArg);
|
|
163
|
+
ensureMeshInbox(loaded, { quiet: true });
|
|
164
|
+
const layoutOk = printVerify(verifyMeshSession(loaded));
|
|
165
|
+
const inboxOk = printMeshInboxStatus(loaded);
|
|
166
|
+
process.exit(layoutOk && inboxOk ? 0 : 1);
|
|
167
|
+
}
|
|
168
|
+
if (cmd === "reload") {
|
|
169
|
+
const loaded = meshLoaded(profileArg);
|
|
170
|
+
const layout = rest.includes("--layout");
|
|
171
|
+
reloadMesh(loaded, { layout });
|
|
172
|
+
console.log(layout
|
|
173
|
+
? `OK: reload + relayout session ${loaded.sessionName}`
|
|
174
|
+
: `OK: reload (build + labels) session ${loaded.sessionName}`);
|
|
175
|
+
printMeshInboxStatus(loaded);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (cmd === "layout") {
|
|
179
|
+
const loaded = meshLoaded(profileArg);
|
|
180
|
+
const skipLeads = rest.includes("--no-leads");
|
|
181
|
+
const force = rest.includes("--yes");
|
|
182
|
+
const dryRun = rest.includes("--dry-run");
|
|
183
|
+
const m = loaded.profile.layout?.minis;
|
|
184
|
+
if (dryRun) {
|
|
185
|
+
printRelayoutPlan(loaded);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
submitPaneOp(loaded, "relayout", { skipMinisLeads: skipLeads, force }, `layout ${m?.grid ?? "grid"}`, () => {
|
|
189
|
+
assertRelayoutSafe(loaded, force);
|
|
190
|
+
relayoutMeshSession(loaded, { skipMinisLeads: skipLeads, force });
|
|
191
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
192
|
+
const saved = saveMeshSession(loaded, reg);
|
|
193
|
+
const grid = m?.grid ?? "4x2";
|
|
194
|
+
const leadNote = skipLeads || !m
|
|
195
|
+
? ""
|
|
196
|
+
: ` leads=[${Array.isArray(m.leads) ? m.leads.join(",") : "1,2"}]`;
|
|
197
|
+
console.log(`OK: relayout ${loaded.sessionName} (workers 3x2, minis ${grid}${leadNote})`);
|
|
198
|
+
console.log(`OK: layout saved ${saved}`);
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (cmd === "ops") {
|
|
203
|
+
const loaded = meshLoaded(profileArg);
|
|
204
|
+
if (sub === "list" || !sub) {
|
|
205
|
+
printPaneOpsList(loaded);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (sub === "clear") {
|
|
209
|
+
const n = clearPaneOpsQueue(loaded);
|
|
210
|
+
if (n < 0) {
|
|
211
|
+
console.error("pane-ops clear: inbox unavailable");
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
console.log(`OK: pane-ops cleared ${n} open`);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
console.error("usage: ops list|clear");
|
|
218
|
+
process.exit(2);
|
|
219
|
+
}
|
|
220
|
+
if (cmd === "inbox") {
|
|
221
|
+
const loaded = meshLoaded(profileArg);
|
|
222
|
+
const json = rest.includes("--json");
|
|
223
|
+
if (sub === "stop") {
|
|
224
|
+
stopMeshInbox(loaded);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (sub === "restart") {
|
|
228
|
+
restartMeshInbox(loaded);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (sub === "start") {
|
|
232
|
+
startMeshInbox(loaded);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
// status (default): engine auto-starts, then one-line status
|
|
236
|
+
ensureMeshInbox(loaded, { quiet: true });
|
|
237
|
+
const ok = printMeshInboxStatus(loaded, { json });
|
|
238
|
+
process.exit(ok ? 0 : 1);
|
|
239
|
+
}
|
|
240
|
+
if (cmd === "to-master") {
|
|
241
|
+
const loaded = meshLoaded(profileArg);
|
|
242
|
+
let from;
|
|
243
|
+
let slot;
|
|
244
|
+
const parts = [];
|
|
245
|
+
const args = [sub, ...tail].filter((a) => a != null && a !== "");
|
|
246
|
+
for (let i = 0; i < args.length; i++) {
|
|
247
|
+
const a = args[i];
|
|
248
|
+
if (a === "--from" && args[i + 1])
|
|
249
|
+
from = args[++i];
|
|
250
|
+
else if (a === "--slot" && args[i + 1])
|
|
251
|
+
slot = args[++i];
|
|
252
|
+
else
|
|
253
|
+
parts.push(a);
|
|
254
|
+
}
|
|
255
|
+
const msg = parts.join(" ").trim();
|
|
256
|
+
if (!msg) {
|
|
257
|
+
console.error("usage: to-master [--from <who>] [--slot <N|label>] <msg...>");
|
|
258
|
+
process.exit(2);
|
|
259
|
+
}
|
|
260
|
+
const entry = sendToMaster(loaded, msg, { from, slot });
|
|
261
|
+
if (!entry || entry.ok !== true) {
|
|
262
|
+
console.error("FAIL: to-master enqueue (inbox down?) — run: ./sm.sh inbox");
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
console.log(JSON.stringify(entry, null, 2));
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (cmd === "to-slot") {
|
|
269
|
+
const loaded = meshLoaded(profileArg);
|
|
270
|
+
const dest = sub;
|
|
271
|
+
const msg = tail.join(" ").trim();
|
|
272
|
+
try {
|
|
273
|
+
runToSlot(loaded, dest ?? "", msg);
|
|
274
|
+
}
|
|
275
|
+
catch (e) {
|
|
276
|
+
console.error(e.message);
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (cmd === "to-mini") {
|
|
282
|
+
const loaded = meshLoaded(profileArg);
|
|
283
|
+
const mid = sub;
|
|
284
|
+
const msg = tail.join(" ").trim();
|
|
285
|
+
try {
|
|
286
|
+
runToMini(loaded, mid ?? "", msg);
|
|
287
|
+
}
|
|
288
|
+
catch (e) {
|
|
289
|
+
console.error(e.message);
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (cmd === "peer") {
|
|
295
|
+
const loaded = meshLoaded(profileArg);
|
|
296
|
+
const target = sub;
|
|
297
|
+
const msg = tail.join(" ").trim();
|
|
298
|
+
if (!target || !msg) {
|
|
299
|
+
console.error("usage: peer <manager|secretary|slot-N|mini-N|pane> <msg...>");
|
|
300
|
+
process.exit(2);
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
const { paneId, targetLabel } = enqueuePrompt(loaded, target, msg, { manager: true });
|
|
304
|
+
console.log(`OK: peer -> ${targetLabel} pane=${paneId} (daemon inject when idle)`);
|
|
305
|
+
}
|
|
306
|
+
catch (e) {
|
|
307
|
+
console.error(e.message);
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (cmd === "mini") {
|
|
313
|
+
const loaded = meshLoaded(profileArg);
|
|
314
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
315
|
+
if (sub === "list" || !sub) {
|
|
316
|
+
printMiniList(loaded);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (sub === "dispatch-all") {
|
|
320
|
+
miniSpawnAll(loaded, reg);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (sub === "spawn") {
|
|
324
|
+
const args = tail.filter((a) => a !== "--");
|
|
325
|
+
let role = "helper";
|
|
326
|
+
const ids = [];
|
|
327
|
+
const taskParts = [];
|
|
328
|
+
for (let i = 0; i < args.length; i++) {
|
|
329
|
+
const a = args[i];
|
|
330
|
+
if (a === "--role" && args[i + 1]) {
|
|
331
|
+
role = args[++i];
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (a === "all") {
|
|
335
|
+
for (let n = 1; n <= loaded.profile.session.miniMax; n++)
|
|
336
|
+
ids.push(n);
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
const m = a.match(/^mini-?(\d+)$/);
|
|
340
|
+
if (m) {
|
|
341
|
+
ids.push(Number(m[1]));
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (/^\d+$/.test(a)) {
|
|
345
|
+
ids.push(Number(a));
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
taskParts.push(a);
|
|
349
|
+
}
|
|
350
|
+
const task = taskParts.join(" ").trim();
|
|
351
|
+
if (!ids.length || !task) {
|
|
352
|
+
console.error("usage: mini spawn <1-8|all|mini-N> [--role helper] <task...>");
|
|
353
|
+
process.exit(2);
|
|
354
|
+
}
|
|
355
|
+
for (const n of ids) {
|
|
356
|
+
submitPaneOp(loaded, "mini-spawn", { n, role, task, viaSecretary: false }, `mini spawn ${n} role=${role}`, () => miniSpawn(loaded, reg, n, role, task, { viaSecretary: false }));
|
|
357
|
+
}
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
if (sub === "prompt") {
|
|
361
|
+
const n = Number(tail[0]);
|
|
362
|
+
const text = tail.slice(1).join(" ");
|
|
363
|
+
if (!n || !text) {
|
|
364
|
+
console.error("usage: mini prompt <N> <text...>");
|
|
365
|
+
process.exit(2);
|
|
366
|
+
}
|
|
367
|
+
miniPrompt(loaded, reg, n, text);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (sub === "done") {
|
|
371
|
+
const n = Number(tail[0]);
|
|
372
|
+
const report = tail.slice(1).join(" ");
|
|
373
|
+
if (!n || !report) {
|
|
374
|
+
console.error("usage: mini done <N> PASS|FAIL: <evidence>");
|
|
375
|
+
process.exit(2);
|
|
376
|
+
}
|
|
377
|
+
miniDone(loaded, n, report);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
console.error("usage: mini list|spawn|prompt|done|dispatch-all");
|
|
381
|
+
process.exit(2);
|
|
382
|
+
}
|
|
383
|
+
if (cmd === "secretary") {
|
|
384
|
+
const loaded = meshLoaded(profileArg);
|
|
385
|
+
if (sub === "start") {
|
|
386
|
+
secretaryLaunch(loaded);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (sub === "restart") {
|
|
390
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
391
|
+
secretaryRestart(loaded, reg);
|
|
392
|
+
saveMeshSession(loaded, reg);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
if (sub === "dispatch") {
|
|
396
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
397
|
+
secretaryDispatch(loaded, reg);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
if (sub === "collect") {
|
|
401
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
402
|
+
const send = rest.includes("--send");
|
|
403
|
+
const nudge = rest.includes("--nudge");
|
|
404
|
+
const digest = secretaryCollect(loaded, reg, { sendManager: send, nudgeOpen: nudge });
|
|
405
|
+
process.exit(digest.allDone ? 0 : 1);
|
|
406
|
+
}
|
|
407
|
+
if (sub === "status" || !sub) {
|
|
408
|
+
secretaryStatus(loaded);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (sub === "watch") {
|
|
412
|
+
const action = (tail[0] ?? "status").toLowerCase();
|
|
413
|
+
if (action === "on") {
|
|
414
|
+
secretaryMeshWatch(loaded, "on", tail[1] ?? "5m");
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if (action === "off") {
|
|
418
|
+
secretaryMeshWatch(loaded, "off");
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
secretaryMeshWatch(loaded, "status");
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (sub === "supervise") {
|
|
425
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
426
|
+
const action = (tail[0] ?? "status").toLowerCase();
|
|
427
|
+
if (action === "on") {
|
|
428
|
+
secretarySupervise(loaded, reg, "on", tail[1] ?? "5m");
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
if (action === "off") {
|
|
432
|
+
secretarySupervise(loaded, reg, "off");
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
secretarySupervise(loaded, reg, "status");
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
console.error("usage: secretary start|restart|status|supervise on [5m]|supervise off|watch on [5m]|watch off");
|
|
439
|
+
process.exit(2);
|
|
440
|
+
}
|
|
441
|
+
if (cmd === "peek") {
|
|
442
|
+
const loaded = meshLoaded(profileArg);
|
|
443
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
444
|
+
const target = sub ?? "here";
|
|
445
|
+
const modeRaw = (tail[0] ?? "status").toLowerCase();
|
|
446
|
+
const mode = modeRaw === "full" ? "full" : "status";
|
|
447
|
+
try {
|
|
448
|
+
runPeek(loaded, reg, target, mode);
|
|
449
|
+
}
|
|
450
|
+
catch (e) {
|
|
451
|
+
console.error(e.message);
|
|
452
|
+
process.exit(1);
|
|
453
|
+
}
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (cmd === "ppa") {
|
|
457
|
+
const loaded = meshLoaded(profileArg);
|
|
458
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
459
|
+
const ppaSub = sub ?? "perf-index";
|
|
460
|
+
if (ppaSub !== "perf-index" && ppaSub !== "index") {
|
|
461
|
+
console.error("usage: ppa [perf-index]");
|
|
462
|
+
process.exit(2);
|
|
463
|
+
}
|
|
464
|
+
try {
|
|
465
|
+
runPpa(loaded, reg);
|
|
466
|
+
}
|
|
467
|
+
catch (e) {
|
|
468
|
+
console.error(e.message);
|
|
469
|
+
process.exit(1);
|
|
470
|
+
}
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
if (cmd === "contexts" || cmd === "seats") {
|
|
474
|
+
const loaded = meshLoaded(profileArg);
|
|
475
|
+
printSeatContexts(loaded, rest.includes("--json"));
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
if (cmd === "cold-start" || cmd === "coldstart") {
|
|
479
|
+
const loaded = meshLoaded(profileArg);
|
|
480
|
+
const inject = rest.includes("--inject");
|
|
481
|
+
const force = rest.includes("--force");
|
|
482
|
+
const targetArg = sub && sub !== "--inject" ? sub : undefined;
|
|
483
|
+
const w = runWhoami(loaded, targetArg);
|
|
484
|
+
const miniMatch = targetArg?.match(/^mini-(\d+)$/);
|
|
485
|
+
const mini = miniMatch?.[1] ?? (w.role === "manager-mini" ? targetArg : undefined);
|
|
486
|
+
const target = targetArg ?? "here";
|
|
487
|
+
if (inject) {
|
|
488
|
+
const r = enqueueColdStart(loaded, target, {
|
|
489
|
+
mini: mini ?? null,
|
|
490
|
+
force,
|
|
491
|
+
});
|
|
492
|
+
console.log(r.skipped
|
|
493
|
+
? `OK: cold-start skipped (idempotent fingerprint=${r.fingerprint}) -> ${target}`
|
|
494
|
+
: `OK: cold-start enqueued fingerprint=${r.fingerprint} -> ${target}`);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
console.log(buildFullColdStartBrief(loaded, w, { mini: mini ?? null }));
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (cmd === "seat" && sub === "init") {
|
|
501
|
+
const loaded = meshLoaded(profileArg);
|
|
502
|
+
const { created, ensured } = runSeatInit(loaded);
|
|
503
|
+
console.log(`OK: seat init (ensured=${ensured.length} created=${created.length} — idempotent, never overwrites FOCUS/TASKS)`);
|
|
504
|
+
for (const p of created.slice(0, 12))
|
|
505
|
+
console.log(` + ${p}`);
|
|
506
|
+
if (created.length > 12)
|
|
507
|
+
console.log(` ... +${created.length - 12} more`);
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
if (cmd === "test") {
|
|
511
|
+
const loaded = meshLoaded(profileArg);
|
|
512
|
+
ensureMeshInbox(loaded, { quiet: true });
|
|
513
|
+
const results = await runMeshSmoke(loaded);
|
|
514
|
+
const ok = printSmokeResults(results);
|
|
515
|
+
process.exit(ok ? 0 : 1);
|
|
516
|
+
}
|
|
517
|
+
if (cmd === "labels") {
|
|
518
|
+
const loaded = meshLoaded(profileArg);
|
|
519
|
+
const session = liveMeshSession(loaded);
|
|
520
|
+
const layout = loaded.profile.layout;
|
|
521
|
+
if (!layout) {
|
|
522
|
+
console.error("profile missing layout");
|
|
523
|
+
process.exit(1);
|
|
524
|
+
}
|
|
525
|
+
labelMeshSession(loaded, session);
|
|
526
|
+
applyMeshSessionBorders(session, [
|
|
527
|
+
layout.nvim.window,
|
|
528
|
+
layout.base.window,
|
|
529
|
+
layout.workers.window,
|
|
530
|
+
layout.minis.window,
|
|
531
|
+
]);
|
|
532
|
+
console.log(`OK: labels + borders on session ${session}`);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
if (cmd === "launch") {
|
|
536
|
+
const loaded = meshLoaded(profileArg);
|
|
537
|
+
const rawArgs = [sub, ...tail].filter((a) => Boolean(a) && a !== "--");
|
|
538
|
+
const launchNow = rawArgs.includes("--now");
|
|
539
|
+
const targets = rawArgs.filter((a) => a !== "--now");
|
|
540
|
+
const label = targets.length ? targets.join(",") : "all";
|
|
541
|
+
const runLaunch = () => {
|
|
542
|
+
const results = launchSession(loaded, {
|
|
543
|
+
targets: targets.length ? targets : undefined,
|
|
544
|
+
});
|
|
545
|
+
printLaunchResults(results);
|
|
546
|
+
if (results.some((r) => r.status === "failed"))
|
|
547
|
+
process.exit(1);
|
|
548
|
+
};
|
|
549
|
+
if (launchNow) {
|
|
550
|
+
runLaunch();
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
submitPaneOp(loaded, "launch", { targets: targets.length ? targets : undefined }, `launch ${label}`, runLaunch);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
if (cmd === "prompt") {
|
|
557
|
+
const loaded = meshLoaded(profileArg);
|
|
558
|
+
let manager = false;
|
|
559
|
+
const args = [];
|
|
560
|
+
for (const a of [sub, ...tail].filter((x) => x != null && x !== "")) {
|
|
561
|
+
if (a === "--manager" || a === "-m")
|
|
562
|
+
manager = true;
|
|
563
|
+
else
|
|
564
|
+
args.push(a);
|
|
565
|
+
}
|
|
566
|
+
const [target, ...textParts] = args;
|
|
567
|
+
if (!target || !textParts.length) {
|
|
568
|
+
console.error("usage: prompt [--manager] <target> <text...>");
|
|
569
|
+
process.exit(2);
|
|
570
|
+
}
|
|
571
|
+
const text = textParts.join(" ");
|
|
572
|
+
const { paneId, targetLabel } = enqueuePrompt(loaded, target, text, { manager });
|
|
573
|
+
console.log(`OK: queued -> ${targetLabel} pane=${paneId} (daemon inject when idle)`);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
if (cmd === "remind") {
|
|
577
|
+
const loaded = meshLoaded(profileArg);
|
|
578
|
+
const workerCount = loaded.profile.session.workerCount;
|
|
579
|
+
const [target, ...noteParts] = [sub, ...tail].filter(Boolean);
|
|
580
|
+
if (!target) {
|
|
581
|
+
console.error(`usage: remind <slot|all> [note...] (manager-only, workers 1-${workerCount})`);
|
|
582
|
+
process.exit(2);
|
|
583
|
+
}
|
|
584
|
+
const parsed = /^(?:slot-)?(\d+)$/.exec(target);
|
|
585
|
+
if (target !== "all" && !parsed) {
|
|
586
|
+
console.error(`usage: remind <slot|all> [note...] (manager-only, workers 1-${workerCount})`);
|
|
587
|
+
process.exit(2);
|
|
588
|
+
}
|
|
589
|
+
if (parsed) {
|
|
590
|
+
const n = Number(parsed[1]);
|
|
591
|
+
if (n < 1 || n > workerCount) {
|
|
592
|
+
console.error(`refused: remind targets worker slots 1-${workerCount} only (got ${n})`);
|
|
593
|
+
process.exit(2);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
const results = runRemind(loaded, target, {
|
|
597
|
+
note: noteParts.length ? noteParts.join(" ") : undefined,
|
|
598
|
+
});
|
|
599
|
+
printRemindResults(results);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
if (cmd === "flush") {
|
|
603
|
+
const loaded = meshLoaded(profileArg);
|
|
604
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
605
|
+
const target = sub ?? "all";
|
|
606
|
+
if (!sub) {
|
|
607
|
+
console.error("usage: flush <slot|all|manager|mini-N>");
|
|
608
|
+
process.exit(2);
|
|
609
|
+
}
|
|
610
|
+
const results = runFlush(loaded, reg, target);
|
|
611
|
+
printFlushResults(results);
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
if (cmd === "switch" || cmd === "handoff") {
|
|
615
|
+
const loaded = meshLoaded(profileArg);
|
|
616
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
617
|
+
const args = [sub, ...tail].filter(Boolean);
|
|
618
|
+
if (args.length < 2) {
|
|
619
|
+
console.error("usage: switch <target> <agent|kiro|claude|opencode|empty> [--fresh|--resume ID] [reason...]");
|
|
620
|
+
process.exit(2);
|
|
621
|
+
}
|
|
622
|
+
const target = args[0];
|
|
623
|
+
const newType = args[1];
|
|
624
|
+
let fresh = false;
|
|
625
|
+
let resumeId;
|
|
626
|
+
const reasonParts = [];
|
|
627
|
+
for (let i = 2; i < args.length; i++) {
|
|
628
|
+
const a = args[i];
|
|
629
|
+
if (a === "--fresh")
|
|
630
|
+
fresh = true;
|
|
631
|
+
else if (a === "--resume" && args[i + 1])
|
|
632
|
+
resumeId = args[++i];
|
|
633
|
+
else if (a.startsWith("--resume="))
|
|
634
|
+
resumeId = a.slice("--resume=".length);
|
|
635
|
+
else
|
|
636
|
+
reasonParts.push(a);
|
|
637
|
+
}
|
|
638
|
+
const reason = reasonParts.join(" ") || undefined;
|
|
639
|
+
submitPaneOp(loaded, "switch", { target, newType, fresh, resumeId, reason }, `switch ${target} -> ${newType}`, () => runSwitch(loaded, reg, target, newType, {
|
|
640
|
+
fresh,
|
|
641
|
+
resumeId,
|
|
642
|
+
reason,
|
|
643
|
+
}));
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if (cmd === "report") {
|
|
647
|
+
const loaded = meshLoaded(profileArg);
|
|
648
|
+
const { printStatusReport } = await import("./status-report.js");
|
|
649
|
+
const report = await printStatusReport(loaded, { json: rest.includes("--json") });
|
|
650
|
+
process.exit(report.ok ? 0 : 1);
|
|
651
|
+
}
|
|
652
|
+
if (cmd === "title") {
|
|
653
|
+
const loaded = meshLoaded(profileArg);
|
|
654
|
+
const [target, ...parts] = [sub, ...tail].filter(Boolean);
|
|
655
|
+
if (!target || !parts.length) {
|
|
656
|
+
console.error("usage: title <target> <text...>");
|
|
657
|
+
process.exit(2);
|
|
658
|
+
}
|
|
659
|
+
setPaneTitle(loaded, target, parts.join(" "));
|
|
660
|
+
console.log(`OK: title ${target}`);
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (cmd === "status") {
|
|
664
|
+
const loaded = meshLoaded(profileArg);
|
|
665
|
+
const [target, ...parts] = [sub, ...tail].filter(Boolean);
|
|
666
|
+
if (!target || !parts.length) {
|
|
667
|
+
console.error("usage: status <target> <text...>");
|
|
668
|
+
process.exit(2);
|
|
669
|
+
}
|
|
670
|
+
setPaneStatus(loaded, target, parts.join(" "));
|
|
671
|
+
console.log(`OK: status ${target}`);
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
if (cmd === "agent") {
|
|
675
|
+
const loaded = meshLoaded(profileArg);
|
|
676
|
+
const w = runWhoami(loaded, sub || tail[0]);
|
|
677
|
+
printAgentCard(w);
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
if (cmd === "whoami" || cmd === "where") {
|
|
681
|
+
if (cmd === "where") {
|
|
682
|
+
console.error("note: where is deprecated — use ./sm.sh whoami");
|
|
683
|
+
}
|
|
684
|
+
const loaded = meshLoaded(profileArg);
|
|
685
|
+
printWhoami(loaded, sub || tail[0]);
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (cmd === "index") {
|
|
689
|
+
const loaded = meshLoaded(profileArg);
|
|
690
|
+
const paths = profilePaths(loaded);
|
|
691
|
+
if (sub === "show") {
|
|
692
|
+
let role = "worker";
|
|
693
|
+
for (let i = 0; i < tail.length; i++) {
|
|
694
|
+
if (tail[i] === "--role" && tail[i + 1])
|
|
695
|
+
role = tail[++i];
|
|
696
|
+
}
|
|
697
|
+
const index = loadRoleIndex(paths.rolesDir, role);
|
|
698
|
+
if (tail.includes("--json")) {
|
|
699
|
+
console.log(JSON.stringify(index, null, 2));
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
console.log(renderRoleIndex(index));
|
|
703
|
+
}
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
if (sub === "validate") {
|
|
707
|
+
let role = "worker";
|
|
708
|
+
for (let i = 0; i < tail.length; i++) {
|
|
709
|
+
if (tail[i] === "--role" && tail[i + 1])
|
|
710
|
+
role = tail[++i];
|
|
711
|
+
}
|
|
712
|
+
const index = loadRoleIndex(paths.rolesDir, role);
|
|
713
|
+
const result = validateRoleIndex(index, loaded.workspace);
|
|
714
|
+
if (!result.ok) {
|
|
715
|
+
console.error(`FAIL: missing paths:\n${result.missing.map((m) => ` - ${m}`).join("\n")}`);
|
|
716
|
+
process.exit(1);
|
|
717
|
+
}
|
|
718
|
+
console.log(`OK: role=${role} paths exist under ${loaded.workspace}`);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
console.error("usage: index show|validate");
|
|
722
|
+
process.exit(2);
|
|
723
|
+
}
|
|
724
|
+
if (cmd === "proxy") {
|
|
725
|
+
const loaded = meshLoaded(profileArg);
|
|
726
|
+
const snap = await snapshotConnectivity(loaded.profile);
|
|
727
|
+
if (sub === "status" || sub === "check" || !sub) {
|
|
728
|
+
console.log(formatStatus(snap));
|
|
729
|
+
if (sub === "check" && snap.pendingTriggers.length)
|
|
730
|
+
process.exit(1);
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
if (sub === "reset") {
|
|
734
|
+
const { spawnSync } = await import("node:child_process");
|
|
735
|
+
const path = await import("node:path");
|
|
736
|
+
const script = path.join(loaded.workspace, "scripts/oc-proxy-reset.sh");
|
|
737
|
+
const r = spawnSync("bash", [script], {
|
|
738
|
+
cwd: loaded.workspace,
|
|
739
|
+
encoding: "utf8",
|
|
740
|
+
stdio: "inherit",
|
|
741
|
+
});
|
|
742
|
+
process.exit(r.status ?? 1);
|
|
743
|
+
}
|
|
744
|
+
console.error("usage: proxy status|check|reset");
|
|
745
|
+
process.exit(2);
|
|
746
|
+
}
|
|
747
|
+
if (cmd === "providers") {
|
|
748
|
+
const loaded = meshLoaded(profileArg);
|
|
749
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
750
|
+
if (sub === "list") {
|
|
751
|
+
for (const p of reg.all())
|
|
752
|
+
console.log(p.id);
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
if (sub === "scan") {
|
|
756
|
+
const session = tail[0] ?? liveMeshSession(loaded);
|
|
757
|
+
const panes = listSessionPanes(session);
|
|
758
|
+
if (!panes.length) {
|
|
759
|
+
console.error(`no panes in session ${session} (tmux running?)`);
|
|
760
|
+
process.exit(1);
|
|
761
|
+
}
|
|
762
|
+
for (const paneId of panes) {
|
|
763
|
+
const snap = capturePaneSnapshot(paneId);
|
|
764
|
+
if (!snap)
|
|
765
|
+
continue;
|
|
766
|
+
const prov = reg.detect(snap);
|
|
767
|
+
const det = prov?.detect(snap);
|
|
768
|
+
const state = prov?.composerState(snap) ?? { phase: "plain_shell" };
|
|
769
|
+
const slot = snap.options.mesh_slot || "-";
|
|
770
|
+
const ports = snap.options.mesh_ports || "-";
|
|
771
|
+
console.log(`${paneId}\t${prov?.id ?? "?"}\t${det?.resumeId ?? "-"}\t${state.phase}${state.limitKind ? `:${state.limitKind}` : ""}\tslot=${slot}\tports=${ports}\t${snap.windowName}`);
|
|
772
|
+
}
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
console.error("usage: providers list|scan [session]");
|
|
776
|
+
process.exit(2);
|
|
777
|
+
}
|
|
778
|
+
if (cmd === "manager") {
|
|
779
|
+
const loaded = meshLoaded(profileArg);
|
|
780
|
+
const w = runWhoami(loaded);
|
|
781
|
+
const isManager = w.role === "manager" || w.role === "manager-2";
|
|
782
|
+
const label = w.role === "manager-2"
|
|
783
|
+
? "yes: manager-2"
|
|
784
|
+
: isManager
|
|
785
|
+
? "yes: manager"
|
|
786
|
+
: `no: role=${w.role}`;
|
|
787
|
+
console.log(label);
|
|
788
|
+
process.exit(isManager ? 0 : 1);
|
|
789
|
+
}
|
|
790
|
+
if (cmd === "base") {
|
|
791
|
+
const loaded = meshLoaded(profileArg);
|
|
792
|
+
if (sub === "ensure") {
|
|
793
|
+
const session = liveMeshSession(loaded);
|
|
794
|
+
const panes = ensureBaseLayout(loaded, session);
|
|
795
|
+
labelMeshSession(loaded, session);
|
|
796
|
+
console.log(`OK: base panes=${panes.length} columns=${loaded.profile.layout?.base.columns?.join("|") ?? "?"}`);
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
console.error("usage: base ensure");
|
|
800
|
+
process.exit(2);
|
|
801
|
+
}
|
|
802
|
+
if (cmd === "stack" || cmd === "dc") {
|
|
803
|
+
const loaded = meshLoaded(profileArg);
|
|
804
|
+
const args = [sub, ...tail].filter((a) => a != null && a !== "");
|
|
805
|
+
process.exit(runStackPassthrough(loaded, args));
|
|
806
|
+
}
|
|
807
|
+
if (cmd === "room" || cmd === "contract" || cmd === "chat") {
|
|
808
|
+
const loaded = meshLoaded(profileArg);
|
|
809
|
+
const getLoaded = () => loaded;
|
|
810
|
+
const branch = cmd === "room"
|
|
811
|
+
? buildRoomCommands(getLoaded)
|
|
812
|
+
: cmd === "contract"
|
|
813
|
+
? buildContractLockCommands(getLoaded)
|
|
814
|
+
: buildChatCommands(getLoaded);
|
|
815
|
+
if (!sub) {
|
|
816
|
+
branch.outputHelp();
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
try {
|
|
820
|
+
await branch.parseAsync([sub, ...tail], { from: "user" });
|
|
821
|
+
}
|
|
822
|
+
catch (e) {
|
|
823
|
+
const err = e;
|
|
824
|
+
if (err.code === "commander.helpDisplayed" || err.code === "commander.version")
|
|
825
|
+
return;
|
|
826
|
+
throw e;
|
|
827
|
+
}
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
if (cmd === "save" || cmd === "auto") {
|
|
831
|
+
const loaded = meshLoaded(profileArg);
|
|
832
|
+
const reg = createRegistryForProfile(loaded.profile);
|
|
833
|
+
const file = saveMeshSession(loaded, reg);
|
|
834
|
+
const m = loaded.profile.layout?.minis;
|
|
835
|
+
const layoutNote = m
|
|
836
|
+
? ` minis=${m.grid} max=${m.max} leads=[${Array.isArray(m.leads) ? m.leads.join(",") : "?"}]`
|
|
837
|
+
: "";
|
|
838
|
+
console.log(`OK: saved ${file}${layoutNote}`);
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
if (cmd === "checkback" || cmd === "patience") {
|
|
842
|
+
const loaded = meshLoaded(profileArg);
|
|
843
|
+
const getLoaded = () => loaded;
|
|
844
|
+
const branch = buildCheckbackCommands(getLoaded);
|
|
845
|
+
if (!sub) {
|
|
846
|
+
branch.outputHelp();
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
try {
|
|
850
|
+
await branch.parseAsync([sub, ...tail], { from: "user" });
|
|
851
|
+
}
|
|
852
|
+
catch (e) {
|
|
853
|
+
const err = e;
|
|
854
|
+
if (err.code === "commander.helpDisplayed" || err.code === "commander.version")
|
|
855
|
+
return;
|
|
856
|
+
throw e;
|
|
857
|
+
}
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
console.error(`unknown command: ${cmd}`);
|
|
861
|
+
usage();
|
|
862
|
+
process.exit(2);
|
|
863
|
+
}
|
|
864
|
+
main().catch((e) => {
|
|
865
|
+
console.error(e.message);
|
|
866
|
+
process.exit(1);
|
|
867
|
+
});
|
|
868
|
+
//# sourceMappingURL=main.js.map
|