refactor: persist pi-agent LM config across Codespace rebuilds - #42
Conversation
|
| Filename | Overview |
|---|---|
| .devcontainer/pi-config/models.json | Defines matching OmniRoute and ModelRelay providers using the auto-fastest model. |
| .devcontainer/pi-config/settings.json | Correctly selects the defined OmniRoute provider, resolving the previously reported undefined-provider configuration. |
| .devcontainer/start-hermes.sh | Adds an idempotent per-file repair guard for the two persisted Pi configuration files. |
| .devcontainer/post-create-cmd.sh | Pins and globally installs Pi-agent when it is not already available. |
| .github/workflows/devcontainer-ci.yml | Provisions Node.js 24 for CI jobs that invoke npm-dependent scripts. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Tracked .devcontainer/pi-config] -->|start-hermes repair guard| B[~/.pi/agent symlinks]
B --> C[Pi-agent]
C --> D[OmniRoute localhost:20128]
C --> E[ModelRelay localhost:7352]
Reviews (10): Last reviewed commit: "refactor: persist pi-agent LM config acr..." | Re-trigger Greptile
| raise FirstmateError(f"invalid mode {mode!r}; expected {VALID_MODES}") | ||
| if yolo not in VALID_YOLO: | ||
| raise FirstmateError(f"invalid yolo {yolo!r}; expected {VALID_YOLO}") | ||
| tid = task_id or _slugify_task_id(request) |
There was a problem hiding this comment.
When a caller supplies an explicit task_id containing an absolute path or parent-directory components, dispatch() bypasses slugification and passes the resulting path to shutil.rmtree, causing stale-task cleanup to delete an unrelated existing directory outside FM_HOME/data.
| tid = task_id or _slugify_task_id(request) | |
| if task_id and task_id != _slugify_task_id(task_id): | |
| raise FirstmateError( | |
| f"invalid task_id {task_id!r}; expected a lowercase a-z0-9 slug" | |
| ) | |
| tid = task_id or _slugify_task_id(request) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .devcontainer/skills/firstmate-bridge/firstmate_bridge.py
Line: 243
Comment:
**Task ID escapes cleanup root**
When a caller supplies an explicit `task_id` containing an absolute path or parent-directory components, `dispatch()` bypasses slugification and passes the resulting path to `shutil.rmtree`, causing stale-task cleanup to delete an unrelated existing directory outside `FM_HOME/data`.
```suggestion
if task_id and task_id != _slugify_task_id(task_id):
raise FirstmateError(
f"invalid task_id {task_id!r}; expected a lowercase a-z0-9 slug"
)
tid = task_id or _slugify_task_id(request)
```
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.a03fc6f to
7681cad
Compare
7681cad to
e320b9e
Compare
75a80f3 to
71087bb
Compare
…-agent
- Track pi-agent LM config under .devcontainer/pi-config/{models,settings}.json
(renamed from firstmate/; it is pi's config, not the skill's)
pointed at the local OmniRoute relay, symlinked into ~/.pi/agent/
- start-hermes.sh §5.6 relinks those config files on every Codespace start
(pi writes its own stub on first launch) so they survive rebuilds
- post-create-cmd.sh: pre-install pi-agent (PyAgent) via npm so it's available
on every fresh Codespace (like omniroute/modelrelay) for firstmate-bridge
- codespace-persistent-symlinks/SKILL.md documents the per-file symlink
exception this relies on (mixed-state runtime dirs: ~/.pi/agent/)
Note: the firstmate-bridge skill itself is NOT vendored here — installed live
via its one-shot install.sh and discovered from ~/.hermes/skills, keeping this
repo free of upstream third-party skill/CI noise.
Verified: ci-lint-check ALL CHECKS PASSED; Greptile P1 fixed (settings.json
defaultProvider x -> omniroute); live scout dispatch proved the pipeline E2E.
71087bb to
4148d9b
Compare
Summary
Thinned from the original fat version: this PR persists only the pi-agent LM provider config so it survives Codespace rebuilds. The
firstmate-bridgeskill itself is deliberately not vendored — it is installed live via its one-shotinstall.shand discovered from~/.hermes/skills, keeping this repo free of upstream third-party skill/CI noise..devcontainer/pi-config/{models,settings}.json— pi's LM config pointing at the local OmniRoute relay (http://localhost:20128/v1, modelauto-fastest) and ModelRelay fallback (http://localhost:7352/v1, modelauto-fastest)start-hermes.sh§5.6 relinks those config files on every Codespace start (pi writes its own stub on first launch) so they survive rebuildspost-create-cmd.sh: pre-installs Pi-agent (@${PI_AGENT_VERSION}) via npm so it's available on every fresh Codespace for firstmate-bridge.devcontainer/skills/codespace-persistent-symlinks/SKILL.mddocuments the per-file symlink exception this relies on (mixed-state runtime dirs:~/.pi/agent/)Why not vendor the skill?
The
firstmate-bridgeskill is ~50KB of upstream code + its own CI workflow (github:gitricko/hermes-firstmate-bridge). Vendoring it would bloat this repo with third-party maintenance burden. Instead, the skill is installed once via its one-shotinstall.shand Hermes discovers it from~/.hermes/skills. This PR only tracks the user's small, idempotent config + boot guards.Verification
ci-lint-check✅ ALL CHECKS PASSEDsettings.jsondefaultProviderwasx(leaked from rebuild simulation); corrected toomniroutepi modelsreads both providers correctly;dispatch(kind="scout")proved the E2E pipelineFollow-up (not in this PR)
PI_AGENT_VERSIONinpost-create-cmd.shgit fetch originworks to seed the worktree pin; in isolated environments that may need--unshallow~/.local/bin(protocol 16); the skill's backend check prefers herdr over tmux