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