feat(setup): per-checkout service name and docker image tag
Two NanoClaw installs on the same host used to fight over the shared `com.nanoclaw` launchd label / `nanoclaw.service` systemd unit and the `nanoclaw-agent:latest` docker tag — the second install silently rewrote the service pointer and rebuilt the image out from under the first. Introduces a deterministic per-checkout slug (sha1(projectRoot)[:8]) and namespaces everything off it: - Service: `com.nanoclaw-v2-<slug>` / `nanoclaw-v2-<slug>.service` - Image: `nanoclaw-agent-v2-<slug>:latest` (base), `nanoclaw-agent-v2-<slug>:<agentGroupId>` (per-group) New shared helpers: src/install-slug.ts (host) + setup/lib/install-slug.sh (bash). Both compute the same slug so verify/probe/add-*.sh/build.sh/container-runner all agree. Any v1 `com.nanoclaw` service left on the host stays untouched and can coexist. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ 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 { getLaunchdLabel, getSystemdUnit } from '../src/install-slug.js';
|
||||
import {
|
||||
getPlatform,
|
||||
getServiceManager,
|
||||
@@ -45,10 +46,13 @@ export async function run(_args: string[]): Promise<void> {
|
||||
let runningFromPath: string | null = null;
|
||||
const mgr = getServiceManager();
|
||||
|
||||
const launchdLabel = getLaunchdLabel(projectRoot);
|
||||
const systemdUnit = getSystemdUnit(projectRoot);
|
||||
|
||||
if (mgr === 'launchd') {
|
||||
try {
|
||||
const output = execSync('launchctl list', { encoding: 'utf-8' });
|
||||
const line = output.split('\n').find((l) => l.includes('com.nanoclaw'));
|
||||
const line = output.split('\n').find((l) => l.includes(launchdLabel));
|
||||
if (line) {
|
||||
const pidField = line.trim().split(/\s+/)[0];
|
||||
if (pidField !== '-' && pidField) {
|
||||
@@ -67,11 +71,11 @@ export async function run(_args: string[]): Promise<void> {
|
||||
} else if (mgr === 'systemd') {
|
||||
const prefix = isRoot() ? 'systemctl' : 'systemctl --user';
|
||||
try {
|
||||
execSync(`${prefix} is-active nanoclaw`, { stdio: 'ignore' });
|
||||
execSync(`${prefix} is-active ${systemdUnit}`, { stdio: 'ignore' });
|
||||
service = 'running';
|
||||
try {
|
||||
const pidStr = execSync(
|
||||
`${prefix} show nanoclaw -p MainPID --value`,
|
||||
`${prefix} show ${systemdUnit} -p MainPID --value`,
|
||||
{ encoding: 'utf-8' },
|
||||
).trim();
|
||||
const pid = Number(pidStr);
|
||||
@@ -86,7 +90,7 @@ export async function run(_args: string[]): Promise<void> {
|
||||
const output = execSync(`${prefix} list-unit-files`, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
if (output.includes('nanoclaw')) {
|
||||
if (output.includes(systemdUnit)) {
|
||||
service = 'stopped';
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user