fix(setup): accept CLI-only verify success

This commit is contained in:
glifocat
2026-04-24 11:44:35 +02:00
parent a4346f566c
commit 1de5a0356b
+34 -35
View File
@@ -14,14 +14,9 @@ import Database from 'better-sqlite3';
import { DATA_DIR } from '../src/config.js';
import { readEnvFile } from '../src/env.js';
import { log } from '../src/log.js';
import { pingCliAgent } from './lib/agent-ping.js';
import { pingCliAgent, type PingResult } from './lib/agent-ping.js';
import { getLaunchdLabel, getSystemdUnit } from '../src/install-slug.js';
import {
getPlatform,
getServiceManager,
hasSystemd,
isRoot,
} from './platform.js';
import { getPlatform, getServiceManager, hasSystemd, isRoot } from './platform.js';
import { emitStatus } from './status.js';
export async function run(_args: string[]): Promise<void> {
@@ -38,11 +33,7 @@ export async function run(_args: string[]): Promise<void> {
// a sibling checkout (common for developers with multiple clones), this
// repo's `data/cli.sock` won't exist — AGENT_PING would return a
// misleading `socket_error`. Surface the mismatch directly instead.
let service:
| 'not_found'
| 'stopped'
| 'running'
| 'running_other_checkout' = 'not_found';
let service: 'not_found' | 'stopped' | 'running' | 'running_other_checkout' = 'not_found';
let runningFromPath: string | null = null;
const mgr = getServiceManager();
@@ -74,10 +65,7 @@ export async function run(_args: string[]): Promise<void> {
execSync(`${prefix} is-active ${systemdUnit}`, { stdio: 'ignore' });
service = 'running';
try {
const pidStr = execSync(
`${prefix} show ${systemdUnit} -p MainPID --value`,
{ encoding: 'utf-8' },
).trim();
const pidStr = execSync(`${prefix} show ${systemdUnit} -p MainPID --value`, { encoding: 'utf-8' }).trim();
const pid = Number(pidStr);
if (Number.isInteger(pid) && pid > 0) {
runningFromPath = resolveBinaryScript(pid);
@@ -115,11 +103,7 @@ export async function run(_args: string[]): Promise<void> {
}
}
if (
service === 'running' &&
runningFromPath &&
!isPathInside(runningFromPath, projectRoot)
) {
if (service === 'running' && runningFromPath && !isPathInside(runningFromPath, projectRoot)) {
service = 'running_other_checkout';
}
@@ -210,11 +194,7 @@ export async function run(_args: string[]): Promise<void> {
// 6. Check mount allowlist
let mountAllowlist = 'missing';
if (
fs.existsSync(
path.join(homeDir, '.config', 'nanoclaw', 'mount-allowlist.json'),
)
) {
if (fs.existsSync(path.join(homeDir, '.config', 'nanoclaw', 'mount-allowlist.json'))) {
mountAllowlist = 'configured';
}
@@ -227,15 +207,15 @@ export async function run(_args: string[]): Promise<void> {
log.info('Agent ping result', { agentPing });
}
// Determine overall status
const status =
service === 'running' &&
credentials !== 'missing' &&
anyChannelConfigured &&
registeredGroups > 0 &&
(agentPing === 'ok' || agentPing === 'skipped')
? 'success'
: 'failed';
// Determine overall status. A CLI-only install is valid when the local
// agent round-trip succeeds; messaging app credentials are optional.
const status = determineVerifyStatus({
service,
credentials,
anyChannelConfigured,
registeredGroups,
agentPing,
});
log.info('Verification complete', { status, channelAuth });
@@ -255,6 +235,25 @@ export async function run(_args: string[]): Promise<void> {
if (status === 'failed') process.exit(1);
}
export function determineVerifyStatus(input: {
service: 'not_found' | 'stopped' | 'running' | 'running_other_checkout';
credentials: string;
anyChannelConfigured: boolean;
registeredGroups: number;
agentPing: PingResult | 'skipped';
}): 'success' | 'failed' {
const cliAgentResponds = input.agentPing === 'ok';
const hasUsableChannel = input.anyChannelConfigured || cliAgentResponds;
return input.service === 'running' &&
input.credentials !== 'missing' &&
hasUsableChannel &&
input.registeredGroups > 0 &&
(cliAgentResponds || input.agentPing === 'skipped')
? 'success'
: 'failed';
}
/**
* Given a PID, resolve the script path the process is executing (i.e. the
* first `.js` / `.ts` / `.mjs` arg after `node`). Returns null on any