fe82a248ec
- Add Alembic migration to update built-in pi-agent manifest:
* repo mount target from /workspace to ~/{{WORKSPACE_NAME}}
* keep /workspace as compatibility symlink via working_dir
* update startup chown target to $HOME/$WORKSPACE_NAME
- Pass REPO_NAME and WORKSPACE_NAME to compile_compose from instance_service
- Substitute {{WORKSPACE_NAME}} in manifest mount targets and expose it as
a container env var so the entrypoint can create the /workspace symlink
- Generate entrypoint workspace symlink from runtime WORKSPACE_NAME env var
- Install npm_global packages into {home_dir}/.npm-global with PATH so the
non-root container user can update global packages
- Update manifest compiler unit tests for the new behavior
Quality gates:
- pytest tests/unit: 207 passed
- ruff: clean on changed files
- mypy: clean on changed files
- alembic heads: single head
39 lines
2.4 KiB
Markdown
39 lines
2.4 KiB
Markdown
# Fix pi container repo mount and npm update permissions
|
|
|
|
## Problem
|
|
|
|
After implementing configurable tool container home directories, new `pi-agent` containers still bind-mount the git repository at `/workspace` instead of under `/home/user/{repo_name}`. In addition, users cannot run `npm update -g @earendil-works/pi-coding-agent` inside the container because the global npm prefix (`/usr/lib/node_modules`) is owned by root.
|
|
|
|
## Root cause
|
|
|
|
1. The built-in `pi-agent` manifest in `tool_definition_manifests` still declares an explicit repo mount with `"target": "/workspace"` and `"working_dir": "/workspace"`. This masks the generated `/workspace → /home/user/{repo}` compatibility symlink.
|
|
2. `manifest_compiler.py` does not substitute the instance-specific `{{WORKSPACE_NAME}}` placeholder in explicit mount targets, and `instance_service.py` does not pass `WORKSPACE_NAME`/`REPO_NAME` to `compile_compose` for manifest-based tools.
|
|
3. The generated entrypoint hardcodes the literal string `{{WORKSPACE_NAME}}` as the symlink target.
|
|
4. `npm_global` packages are installed with `RUN npm install -g ...` as root into the system npm prefix, so the non-root container user cannot update them.
|
|
|
|
## Fix
|
|
|
|
1. Add an Alembic data migration that updates the built-in `pi-agent` manifest:
|
|
- Change the repo mount target to `~/{{WORKSPACE_NAME}}`.
|
|
- Keep `runtime.working_dir` as `/workspace` (the compatibility symlink).
|
|
- Update the startup script to chown the real mount path (`$HOME/$WORKSPACE_NAME`).
|
|
2. Update `manifest_compiler.py`:
|
|
- Substitute `{{WORKSPACE_NAME}}` in mount targets in `compile_compose`.
|
|
- Pass `WORKSPACE_NAME` as a container environment variable.
|
|
- Generate the entrypoint symlink from the runtime `WORKSPACE_NAME` environment variable.
|
|
- Install `npm_global` packages into a user-writable prefix (`{home_dir}/.npm-global`) and add it to `PATH`.
|
|
3. Update `instance_service.py` to pass `REPO_NAME` and `WORKSPACE_NAME` into manifest compilation.
|
|
4. Update unit tests for the new behavior.
|
|
|
|
## Affected files
|
|
|
|
- `apps/api/alembic/versions/<new>_fix_pi_agent_home_directory_mount.py`
|
|
- `apps/api/src/services/build/manifest_compiler.py`
|
|
- `apps/api/src/services/tool/instance_service.py`
|
|
- `apps/api/tests/unit/test_manifest_compiler.py`
|
|
|
|
## Verification
|
|
|
|
- `pytest apps/api/tests/unit/test_manifest_compiler.py`
|
|
- `pytest apps/api/tests/unit/test_alembic_migrations.py`
|
|
- `ruff`, `mypy`, `npm run typecheck`, `npm run lint` |