chore(freebsd): align host baseline with Python 3.12 (Sam & Pi)
Some checks failed
CI / ci (pull_request) Has been cancelled
Some checks failed
CI / ci (pull_request) Has been cancelled
--- Build: FAIL | Tests: FAIL
This commit is contained in:
parent
1853dfdaf2
commit
e1d4fd4441
9 changed files with 59 additions and 64 deletions
|
|
@ -341,8 +341,8 @@ clawdie-iso/
|
|||
Derived from `setup/environment.ts` host baseline + desktop-installer + DE packages:
|
||||
|
||||
**Clawdie host baseline:**
|
||||
`node24`, `npm`, `bsddialog`, `bastille`, `git`, `tmux`, `python311`, `uv`,
|
||||
`ripgrep`, `fd-find`, `rsync`, `postgresql18-client`, `py311-pillow`, `dejavu`
|
||||
`node24`, `npm`, `bsddialog`, `bastille`, `git`, `tmux`, `python312`, `uv`,
|
||||
`ripgrep`, `fd-find`, `rsync`, `postgresql18-client`, `dejavu`
|
||||
|
||||
**Xorg baseline:**
|
||||
`xorg-minimal`, `xf86-video-intel`, `drm-kmod`,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ See [docs/public/architecture/warden.md](docs/public/architecture/warden.md).
|
|||
git clone https://codeberg.org/Clawdie/Clawdie-AI.git /home/clawdie/clawdie-ai
|
||||
cd /home/clawdie/clawdie-ai
|
||||
|
||||
pkg install node24 npm git python312 py312-uv rsync
|
||||
pkg install node24 npm git python312 uv rsync
|
||||
npm install
|
||||
npm install -g @earendil-works/pi-coding-agent
|
||||
# If setup.sh did not launch onboarding automatically:
|
||||
|
|
@ -102,12 +102,14 @@ The current FreeBSD deployment depends on:
|
|||
### `controlplane`
|
||||
|
||||
Role:
|
||||
|
||||
- main Clawdie control-plane jail
|
||||
- Telegram intake
|
||||
- scheduling
|
||||
- Warden task dispatch
|
||||
|
||||
Profile:
|
||||
|
||||
- `freebsd-jail`
|
||||
- `thick`
|
||||
- `vnet`
|
||||
|
|
@ -116,10 +118,12 @@ Profile:
|
|||
### `db`
|
||||
|
||||
Role:
|
||||
|
||||
- PostgreSQL memory backend
|
||||
- persistent service
|
||||
|
||||
Profile:
|
||||
|
||||
- `freebsd-jail`
|
||||
- `thick`
|
||||
- `vnet`
|
||||
|
|
@ -134,19 +138,23 @@ Profile:
|
|||
## Snapshot Policy
|
||||
|
||||
Manual milestone snapshots:
|
||||
|
||||
- human-named
|
||||
- day-first
|
||||
- month abbreviation
|
||||
|
||||
Examples:
|
||||
|
||||
- `@postgres18-ready-08.mar.2026`
|
||||
- `@fresh-08.mar.2026`
|
||||
|
||||
Automatic snapshots:
|
||||
|
||||
- handled by Sanoid
|
||||
- keep Sanoid's internal `autosnap_...` naming
|
||||
|
||||
Current automated Sanoid targets:
|
||||
|
||||
- `zroot/clawdie-runtime/jails/db`
|
||||
- `zroot/clawdie-runtime/jails/controlplane`
|
||||
|
||||
|
|
|
|||
17
README.md
17
README.md
|
|
@ -155,12 +155,12 @@ just setup-cms # npm run setup -- --step cms
|
|||
- Internet access for `pkg` and `npm`
|
||||
- `bash` and `git` available before first run
|
||||
- **`just`** — command runner (`pkg install just` on FreeBSD; preinstalled on Clawdie ISO)
|
||||
- **At least one agent CLI on `PATH`**: one of `pi`, `aider`, `claude`, `codex`, or `gemini`. The controlplane harness uses Aider+Pi as the primary driver. Onboarding fails fast if none are present (see [`doc/AGENT-CLI-VALIDATION.md`](doc/AGENT-CLI-VALIDATION.md) for the validated install paths). The Clawdie ISO ships claude/gemini/pi via the npm-globals bundle, aider via `py311-aider_chat` pkg, and codex via `pkg install codex`.
|
||||
- **At least one agent CLI on `PATH`**: one of `pi`, `aider`, `claude`, `codex`, or `gemini`. The controlplane harness uses Aider+Pi as the primary driver. Onboarding fails fast if none are present (see [`doc/AGENT-CLI-VALIDATION.md`](doc/AGENT-CLI-VALIDATION.md) for the validated install paths). The Clawdie ISO ships claude/gemini/pi via the npm-globals bundle, provisions Aider in a Python 3.12 venv, and includes codex via `pkg install codex`.
|
||||
|
||||
Recommended explicit host baseline before first run:
|
||||
|
||||
```sh
|
||||
sudo pkg install -y bash git bastille node24 npm tmux btop python311 uv ripgrep fd-find rsync postgresql18-client py311-pillow dejavu py311-aider_chat edk2-bhyve just
|
||||
sudo pkg install -y bash git bastille node24 npm tmux btop python312 uv ripgrep fd-find rsync postgresql18-client dejavu edk2-bhyve just
|
||||
```
|
||||
|
||||
The `edk2-bhyve` package provides UEFI firmware required for optional browser-vm support
|
||||
|
|
@ -169,15 +169,16 @@ The `edk2-bhyve` package provides UEFI firmware required for optional browser-vm
|
|||
On FreeBSD, use `fd-find`. It provides the `fd` command that `pi` expects and
|
||||
avoids colliding with the unrelated `fd` file manager package.
|
||||
|
||||
The host baseline also includes `py311-pillow` and `dejavu` so tmux screenshot
|
||||
capture works without a separate `uv pip install Pillow` step.
|
||||
Python package-flavored extras stay out of the baseline until the FreeBSD
|
||||
quarterly repository publishes Python 3.12 flavors. Install Aider/Pillow-style
|
||||
tools into explicit Python 3.12 venvs when needed.
|
||||
|
||||
If the host still has both Python 3.11 and 3.12 installed, pin `uv` to 3.11
|
||||
If the host still has multiple Python minors installed, pin `uv` to 3.12
|
||||
explicitly until the generic `python3` path is cleaned up:
|
||||
|
||||
```sh
|
||||
uv venv --python 3.11
|
||||
uv run --python 3.11 <command>
|
||||
uv venv --python 3.12
|
||||
uv run --python 3.12 <command>
|
||||
```
|
||||
|
||||
### Operator Glasspane
|
||||
|
|
@ -215,7 +216,7 @@ First use:
|
|||
|
||||
```bash
|
||||
# 1. Install the recommended FreeBSD host baseline
|
||||
sudo pkg install -y bash git bastille node24 npm tmux btop python311 uv ripgrep fd-find rsync postgresql18-client py311-pillow dejavu py311-aider_chat just
|
||||
sudo pkg install -y bash git bastille node24 npm tmux btop python312 uv ripgrep fd-find rsync postgresql18-client dejavu just
|
||||
|
||||
# 2. Clone the repository
|
||||
git clone https://codeberg.org/Clawdie/Clawdie-AI.git /home/clawdie/clawdie-ai
|
||||
|
|
|
|||
|
|
@ -30,26 +30,22 @@ export PATH=/opt/clawdie/cargo/bin:$PATH
|
|||
|
||||
## Working install (tested)
|
||||
|
||||
1) Install Aider from packages (adds many deps but works):
|
||||
1. Create a project-local Python 3.12 venv. The FreeBSD quarterly repo still
|
||||
publishes only older Python-flavored Aider packages, so keep Aider out of the
|
||||
host pkg baseline and install it into a venv:
|
||||
|
||||
```sh
|
||||
sudo pkg install py311-aider_chat
|
||||
python3.12 -m venv /home/clawdie/clawdie-ai/tmp/aider-venv
|
||||
```
|
||||
|
||||
2) Create a project-local venv that can override litellm:
|
||||
|
||||
```sh
|
||||
python3.11 -m venv --system-site-packages /home/clawdie/clawdie-ai/tmp/aider-venv
|
||||
```
|
||||
|
||||
3) Upgrade Aider + pin litellm to the expected version inside the venv:
|
||||
2. Upgrade Aider + pin litellm to the expected version inside the venv:
|
||||
|
||||
```sh
|
||||
/home/clawdie/clawdie-ai/tmp/aider-venv/bin/pip install --no-user --no-deps --upgrade --ignore-installed aider-chat==0.86.2
|
||||
/home/clawdie/clawdie-ai/tmp/aider-venv/bin/pip install --no-user --no-deps --upgrade --ignore-installed litellm==1.81.10
|
||||
```
|
||||
|
||||
4) Align tree-sitter with the system tree-sitter-languages package (fixes repo-map crash):
|
||||
3. Align tree-sitter with the system tree-sitter-languages package (fixes repo-map crash):
|
||||
|
||||
```sh
|
||||
env TMPDIR=/home/clawdie/clawdie-ai/tmp \
|
||||
|
|
@ -63,7 +59,7 @@ FreeBSD ships `tree_sitter_languages` from packages (1.10.2) which expects
|
|||
TypeError: __init__() takes exactly 1 argument (2 given)
|
||||
```
|
||||
|
||||
4) Run Aider (use the venv binary):
|
||||
4. Run Aider (use the venv binary):
|
||||
|
||||
```sh
|
||||
env AIDER_ANALYTICS_DISABLE=1 /home/clawdie/clawdie-ai/tmp/aider-venv/bin/aider \
|
||||
|
|
|
|||
|
|
@ -9,19 +9,18 @@ tmux
|
|||
btop
|
||||
bsddialog
|
||||
codex
|
||||
python311
|
||||
python312
|
||||
uv
|
||||
ripgrep
|
||||
fd-find
|
||||
rsync
|
||||
postgresql18-client
|
||||
dnsmasq
|
||||
py311-pillow
|
||||
dejavu
|
||||
rust
|
||||
|
||||
# Controlplane harness (Aider + Pi multi-agent orchestrator)
|
||||
py311-aider_chat
|
||||
# Controlplane harness helpers. Aider is installed into a venv until the
|
||||
# quarterly FreeBSD repo publishes a Python 3.12 package flavor.
|
||||
just
|
||||
|
||||
# Wayland display stack — used by worker jails (cage) and operator sessions
|
||||
|
|
|
|||
7
setup.sh
7
setup.sh
|
|
@ -71,8 +71,8 @@ install_host_pkg_baseline() {
|
|||
tmux)
|
||||
command -v tmux >/dev/null 2>&1 || missing_pkgs+=("$pkg")
|
||||
;;
|
||||
python311)
|
||||
command -v python3 >/dev/null 2>&1 || missing_pkgs+=("$pkg")
|
||||
python312)
|
||||
command -v python3.12 >/dev/null 2>&1 || missing_pkgs+=("$pkg")
|
||||
;;
|
||||
uv)
|
||||
command -v uv >/dev/null 2>&1 || missing_pkgs+=("$pkg")
|
||||
|
|
@ -92,9 +92,6 @@ install_host_pkg_baseline() {
|
|||
rust)
|
||||
command -v rustc >/dev/null 2>&1 || missing_pkgs+=("$pkg")
|
||||
;;
|
||||
py311-pillow)
|
||||
python3 -c "import PIL" >/dev/null 2>&1 || missing_pkgs+=("$pkg")
|
||||
;;
|
||||
dejavu)
|
||||
[ -f /usr/local/share/fonts/dejavu/DejaVuSansMono.ttf ] || missing_pkgs+=("$pkg")
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export class NoAgentCliError extends Error {
|
|||
[
|
||||
'No agent CLI found on PATH.',
|
||||
'Clawdie needs pi and aider for the Aider+Pi controlplane harness.',
|
||||
'Install via the ISO bundle or: pkg install py311-aider_chat, npm install -g @earendil-works/pi-coding-agent.',
|
||||
'Install via the ISO bundle or: npm install -g @earendil-works/pi-coding-agent; install Aider in a Python 3.12 venv if needed.',
|
||||
'Alternative CLIs (claude, codex, gemini) are also accepted.',
|
||||
].join(' '),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ const HOST_PREREQUISITE_CHECKS: Record<
|
|||
dnsmasq: { key: 'DNSMASQ', check: () => commandExists('dnsmasq') },
|
||||
tmux: { key: 'TMUX', check: () => commandExists('tmux') },
|
||||
btop: { key: 'BTOP', check: () => commandExists('btop') },
|
||||
python311: { key: 'PYTHON3', check: () => commandExists('python3') },
|
||||
python312: { key: 'PYTHON3', check: () => commandExists('python3.12') },
|
||||
uv: { key: 'UV', check: () => commandExists('uv') },
|
||||
ripgrep: { key: 'RIPGREP', check: () => commandExists('rg') },
|
||||
'fd-find': { key: 'FD', check: () => commandExists('fd') },
|
||||
|
|
@ -60,20 +60,8 @@ const HOST_PREREQUISITE_CHECKS: Record<
|
|||
tailscale: { key: 'TAILSCALE', check: () => commandExists('tailscale') },
|
||||
just: { key: 'JUST', check: () => commandExists('just') },
|
||||
rust: { key: 'RUST', check: () => commandExists('rustc') },
|
||||
'py311-aider_chat': { key: 'AIDER', check: () => commandExists('aider') },
|
||||
node24: { key: 'NODE', check: () => commandExists('node') },
|
||||
npm: { key: 'NPM', check: () => commandExists('npm') },
|
||||
'py311-pillow': {
|
||||
key: 'PILLOW',
|
||||
check: () => {
|
||||
try {
|
||||
execSync('python3 -c "import PIL"', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
dejavu: {
|
||||
key: 'DEJAVU_FONT',
|
||||
check: () =>
|
||||
|
|
@ -111,11 +99,9 @@ export async function run(_args: string[]): Promise<void> {
|
|||
const service = commandExists('service');
|
||||
const sudo = commandExists('sudo');
|
||||
const jailConf = fs.existsSync('/etc/jail.conf');
|
||||
const hasPython311 = commandExists('python3.11');
|
||||
const hasPython312 = commandExists('python3.12');
|
||||
const python3Version = commandVersion('python3');
|
||||
const python3NeedsPinning =
|
||||
hasPython311 && hasPython312 && python3Version.includes('3.12');
|
||||
const python3NeedsPinning = hasPython312 && !python3Version.includes('3.12');
|
||||
|
||||
// Check for pi binary (path from env or default 'pi')
|
||||
const piBin = PI_TUI_BIN;
|
||||
|
|
@ -257,7 +243,6 @@ export async function run(_args: string[]): Promise<void> {
|
|||
const psql = getPrereq('PSQL');
|
||||
const node = getPrereq('NODE');
|
||||
const npm = getPrereq('NPM');
|
||||
const pillow = getPrereq('PILLOW');
|
||||
const dejavuFont = getPrereq('DEJAVU_FONT');
|
||||
const seatd = getPrereq('SEATD');
|
||||
const weston = getPrereq('WESTON');
|
||||
|
|
@ -322,13 +307,11 @@ export async function run(_args: string[]): Promise<void> {
|
|||
psql: psql.present,
|
||||
node: node.present,
|
||||
npm: npm.present,
|
||||
pillow: pillow.present,
|
||||
dejavuFont: dejavuFont.present,
|
||||
seatd: seatd.present,
|
||||
cage: cage.present,
|
||||
weston: weston.present,
|
||||
vmBhyve: vmBhyve.present,
|
||||
hasPython311,
|
||||
hasPython312,
|
||||
python3Version,
|
||||
python3NeedsPinning,
|
||||
|
|
@ -349,7 +332,7 @@ export async function run(_args: string[]): Promise<void> {
|
|||
{
|
||||
python3Version,
|
||||
},
|
||||
'Multiple Python versions detected. Pin uv to Python 3.11 until python3 is repointed to 3.11.',
|
||||
'Python 3.12 is installed but python3 is not pinned to 3.12; use an explicit python3.12/uv pin for setup commands.',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -381,12 +364,11 @@ export async function run(_args: string[]): Promise<void> {
|
|||
PYTHON3: python3.present,
|
||||
PYTHON3_STATUS: python3.status,
|
||||
PYTHON3_INSTALL_CMD: python3.installCmd,
|
||||
PYTHON311: hasPython311,
|
||||
PYTHON312: hasPython312,
|
||||
PYTHON3_VERSION: python3Version || 'unknown',
|
||||
UV_PYTHON_PIN_REQUIRED: python3NeedsPinning,
|
||||
UV_PYTHON_HINT: python3NeedsPinning
|
||||
? 'uv venv --python 3.11 && uv run --python 3.11 <command>'
|
||||
? 'uv venv --python 3.12 && uv run --python 3.12 <command>'
|
||||
: 'not_required',
|
||||
NODE: node.present,
|
||||
NODE_STATUS: node.status,
|
||||
|
|
@ -409,9 +391,6 @@ export async function run(_args: string[]): Promise<void> {
|
|||
PSQL: psql.present,
|
||||
PSQL_STATUS: psql.status,
|
||||
PSQL_INSTALL_CMD: psql.installCmd,
|
||||
PILLOW: pillow.present,
|
||||
PILLOW_STATUS: pillow.status,
|
||||
PILLOW_INSTALL_CMD: pillow.installCmd,
|
||||
DEJAVU_FONT: dejavuFont.present,
|
||||
DEJAVU_FONT_STATUS: dejavuFont.status,
|
||||
DEJAVU_FONT_INSTALL_CMD: dejavuFont.installCmd,
|
||||
|
|
|
|||
|
|
@ -408,12 +408,21 @@ function printStep(
|
|||
}
|
||||
|
||||
function hasPiAuthProvider(provider: string): boolean {
|
||||
const authFile = path.join(process.env.HOME || '', '.pi', 'agent', 'auth.json');
|
||||
const authFile = path.join(
|
||||
process.env.HOME || '',
|
||||
'.pi',
|
||||
'agent',
|
||||
'auth.json',
|
||||
);
|
||||
try {
|
||||
const parsed = JSON.parse(fs.readFileSync(authFile, 'utf-8')) as Record<string, unknown>;
|
||||
const parsed = JSON.parse(fs.readFileSync(authFile, 'utf-8')) as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
const entry = parsed?.[provider];
|
||||
if (typeof entry === 'string') return entry.trim().length > 0;
|
||||
if (entry && typeof entry === 'object') return Object.keys(entry).length > 0;
|
||||
if (entry && typeof entry === 'object')
|
||||
return Object.keys(entry).length > 0;
|
||||
return false;
|
||||
} catch {
|
||||
return false;
|
||||
|
|
@ -460,8 +469,12 @@ function printLlmStatus(envFile: string): void {
|
|||
console.log(
|
||||
`\n ${COLS.warn}No LLM provider auth found. Configure one after install and restart:${COLS.reset}`,
|
||||
);
|
||||
console.log(` ${COLS.skipped} Recommended: run pi, then /login and select ChatGPT Plus/Pro (Codex).${COLS.reset}`);
|
||||
console.log(` ${COLS.skipped} Or add an API key such as ANTHROPIC_API_KEY=sk-ant-...${COLS.reset}`);
|
||||
console.log(
|
||||
` ${COLS.skipped} Recommended: run pi, then /login and select ChatGPT Plus/Pro (Codex).${COLS.reset}`,
|
||||
);
|
||||
console.log(
|
||||
` ${COLS.skipped} Or add an API key such as ANTHROPIC_API_KEY=sk-ant-...${COLS.reset}`,
|
||||
);
|
||||
console.log(
|
||||
` ${COLS.skipped} sudo service ${SERVICE_NAME} restart${COLS.reset}`,
|
||||
);
|
||||
|
|
@ -509,7 +522,7 @@ function printAiderTip(): void {
|
|||
);
|
||||
if (!hasAider) {
|
||||
console.log(
|
||||
` install: ${COLS.skipped}pkg install -y py311-aider_chat${COLS.reset}`,
|
||||
` install: ${COLS.skipped}python3.12 -m venv /opt/clawdie/venv/aider && /opt/clawdie/venv/aider/bin/pip install aider-chat${COLS.reset}`,
|
||||
);
|
||||
}
|
||||
console.log(` docs : ${COLS.skipped}https://aider.chat/docs/${COLS.reset}`);
|
||||
|
|
@ -570,7 +583,9 @@ export async function run(argv: string[]): Promise<void> {
|
|||
const opts = parseArgs(argv);
|
||||
const projectRoot = process.cwd();
|
||||
const envFile = path.join(projectRoot, '.env');
|
||||
const envContent = fs.existsSync(envFile) ? fs.readFileSync(envFile, 'utf-8') : '';
|
||||
const envContent = fs.existsSync(envFile)
|
||||
? fs.readFileSync(envFile, 'utf-8')
|
||||
: '';
|
||||
|
||||
if (getPlatform() !== 'freebsd') {
|
||||
console.error('install orchestrator is FreeBSD only.');
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue