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>
34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
/**
|
|
* Per-checkout install identifiers. Lets two NanoClaw installs coexist on
|
|
* one host without clobbering each other's service registration or the
|
|
* shared `nanoclaw-agent:latest` docker image tag.
|
|
*
|
|
* Slug is sha1(projectRoot)[:8] — deterministic per checkout path, stable
|
|
* across re-runs, unique enough across installs.
|
|
*/
|
|
import { createHash } from 'crypto';
|
|
|
|
export function getInstallSlug(projectRoot: string = process.cwd()): string {
|
|
return createHash('sha1').update(projectRoot).digest('hex').slice(0, 8);
|
|
}
|
|
|
|
/** launchd Label + plist basename. e.g. `com.nanoclaw-v2-ab12cd34`. */
|
|
export function getLaunchdLabel(projectRoot?: string): string {
|
|
return `com.nanoclaw-v2-${getInstallSlug(projectRoot)}`;
|
|
}
|
|
|
|
/** systemd unit name (no .service suffix). e.g. `nanoclaw-v2-ab12cd34`. */
|
|
export function getSystemdUnit(projectRoot?: string): string {
|
|
return `nanoclaw-v2-${getInstallSlug(projectRoot)}`;
|
|
}
|
|
|
|
/** Docker image base (no tag). e.g. `nanoclaw-agent-v2-ab12cd34`. */
|
|
export function getContainerImageBase(projectRoot?: string): string {
|
|
return `nanoclaw-agent-v2-${getInstallSlug(projectRoot)}`;
|
|
}
|
|
|
|
/** Default full container image reference with `:latest` tag. */
|
|
export function getDefaultContainerImage(projectRoot?: string): string {
|
|
return `${getContainerImageBase(projectRoot)}:latest`;
|
|
}
|