@nonbot/cli 0.9.12 → 0.9.13
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/commands/daemon.js +10 -1
- package/dist/index.js +1 -1
- package/dist/lib/daemon-lifecycle.js +29 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/commands/daemon.js
CHANGED
|
@@ -12,7 +12,7 @@ import { groupBySession, launchCoordinatedSet, setIsIsolated, } from '../lib/cho
|
|
|
12
12
|
import { IsolatedSessionTracker, reconcileAndCleanup as defaultReconcileAndCleanup, resolveBaseBranch as defaultResolveBaseBranch, } from '../lib/choir/isolated-session.js';
|
|
13
13
|
import { applyPaneTitle, applyPaneState } from '../lib/pane-title.js';
|
|
14
14
|
import { installService, uninstallService } from '../lib/service.js';
|
|
15
|
-
import { probeTmuxAttached, postDaemonStopAck, requestRemoteDaemonStop, stopDaemonLocally, writePidFile, removePidFile, } from '../lib/daemon-lifecycle.js';
|
|
15
|
+
import { probeTmuxAttached, postDaemonStopAck, requestRemoteDaemonStop, stopDaemonLocally, attachDaemonSession, writePidFile, removePidFile, } from '../lib/daemon-lifecycle.js';
|
|
16
16
|
import { detectTmuxSession, inTmuxSession, nonbotTmuxOptOut, resolveTerminal, } from '../lib/terminal.js';
|
|
17
17
|
import { VERSION } from '../version.js';
|
|
18
18
|
import { errorBlock, statusRow, daemonOpener, daemonCloser, activationCard, runSummary, formatElapsed, liveFooter, needsYouBanner, resumedLine, buildPaneBorderFormat, buildTmuxStatusLeft, buildTmuxStatusRight, WORDMARK_WIDTH, c, } from '../lib/output.js';
|
|
@@ -182,6 +182,15 @@ export async function runDaemonCommand(args = [], options = {}, deps = {}) {
|
|
|
182
182
|
spawnImpl: deps.spawnSync,
|
|
183
183
|
});
|
|
184
184
|
}
|
|
185
|
+
if (args[0] === 'attach') {
|
|
186
|
+
const sessionFlag = args.indexOf('--session');
|
|
187
|
+
const sessionName = sessionFlag >= 0 ? args[sessionFlag + 1] : undefined;
|
|
188
|
+
return attachDaemonSession({
|
|
189
|
+
log: rawLog, errLog,
|
|
190
|
+
spawnImpl: deps.spawnSync,
|
|
191
|
+
...(sessionName ? { sessionName } : {}),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
185
194
|
if (args.includes('--install')) {
|
|
186
195
|
const install = deps.installService ?? installService;
|
|
187
196
|
const res = await install();
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ const COMMANDS = [
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
name: 'daemon',
|
|
24
|
-
description: 'Long-running listener — polls /api/cli/activations/pending every 2s. `nonbot daemon stop` stops it (local; --machine <id> / --all go remote).',
|
|
24
|
+
description: 'Long-running listener — polls /api/cli/activations/pending every 2s. `nonbot daemon stop` stops it (local; --machine <id> / --all go remote); `nonbot daemon attach` reattaches a lost tmux window.',
|
|
25
25
|
run: (args) => runDaemonCommand(args),
|
|
26
26
|
},
|
|
27
27
|
{
|
|
@@ -106,6 +106,35 @@ export async function requestRemoteDaemonStop(opts) {
|
|
|
106
106
|
return 1;
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
export function attachDaemonSession(deps) {
|
|
110
|
+
const spawn = deps.spawnImpl ?? nodeSpawnSync;
|
|
111
|
+
const sessionName = deps.sessionName ?? 'nonbot';
|
|
112
|
+
try {
|
|
113
|
+
const probe = spawn('tmux', ['has-session', '-t', sessionName], {
|
|
114
|
+
encoding: 'utf-8', timeout: 2000, windowsHide: true,
|
|
115
|
+
});
|
|
116
|
+
if (probe.status !== 0) {
|
|
117
|
+
deps.errLog(`✗ no tmux session '${sessionName}' to attach to.\n Start the daemon first: nonbot daemon\n`);
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
deps.errLog('✗ tmux not found — install it (brew install tmux) or run the daemon without tmux.\n');
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
125
|
+
deps.log(`↳ attaching to tmux session '${sessionName}' — press Ctrl-B then D to detach again.\n`);
|
|
126
|
+
try {
|
|
127
|
+
const res = spawn('tmux', ['attach', '-t', sessionName], {
|
|
128
|
+
...{ stdio: 'inherit' },
|
|
129
|
+
windowsHide: true,
|
|
130
|
+
});
|
|
131
|
+
return res.status === 0 ? 0 : 1;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
deps.errLog(`✗ could not attach to '${sessionName}'.\n`);
|
|
135
|
+
return 1;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
109
138
|
export async function stopDaemonLocally(deps) {
|
|
110
139
|
const kill = deps.kill ?? ((pid, sig) => process.kill(pid, sig));
|
|
111
140
|
const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.9.
|
|
1
|
+
export const VERSION = '0.9.13';
|
package/package.json
CHANGED