Skip to content

refactor: persist pi-agent LM config across Codespace rebuilds - #42

Merged
gitricko merged 1 commit into
mainfrom
feat/install-firstmate-bridge
Aug 21, 2026
Merged

gitricko merged 1 commit into
mainfrom
feat/install-firstmate-bridge

Conversation

@gitricko

@gitricko gitricko commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Summary

Thinned from the original fat version: this PR persists only the pi-agent LM provider config so it survives Codespace rebuilds. The firstmate-bridge skill itself is deliberately not vendored — it is installed live via its one-shot install.sh and discovered from ~/.hermes/skills, keeping this repo free of upstream third-party skill/CI noise.

  • Adds .devcontainer/pi-config/{models,settings}.json — pi's LM config pointing at the local OmniRoute relay (http://localhost:20128/v1, model auto-fastest) and ModelRelay fallback (http://localhost:7352/v1, model auto-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 rebuilds
  • post-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.md documents the per-file symlink exception this relies on (mixed-state runtime dirs: ~/.pi/agent/)

Why not vendor the skill?

The firstmate-bridge skill 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-shot install.sh and Hermes discovers it from ~/.hermes/skills. This PR only tracks the user's small, idempotent config + boot guards.

Verification

  • ci-lint-check ✅ ALL CHECKS PASSED
  • Full CI (CodeQL, Build, Greptile, etc.) ✅ green
  • Greptile P1 fix: settings.json defaultProvider was x (leaked from rebuild simulation); corrected to omniroute
  • Live pi models reads both providers correctly; dispatch(kind="scout") proved the E2E pipeline

Follow-up (not in this PR)

  • If ModelRelay backend changes, update PI_AGENT_VERSION in post-create-cmd.sh
  • The firstmate-bridge installer assumes git fetch origin works to seed the worktree pin; in isolated environments that may need --unshallow
  • herdr v0.7.4+ is already installed to ~/.local/bin (protocol 16); the skill's backend check prefers herdr over tmux

Copilot AI lite review requested due to automatic review settings August 21, 2026 07:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown

Greptile Summary

The PR persists Pi-agent’s language-model configuration across Codespace rebuilds and installs the matching Pi-agent release during container creation.

  • Adds tracked OmniRoute and ModelRelay provider configuration with OmniRoute as the default.
  • Repairs per-file links into the mixed-state ~/.pi/agent runtime directory on every start.
  • Adds Node.js setup to CI jobs that execute npm-dependent provisioning and lint steps.
  • Documents the per-file persistence exception for runtime directories containing secrets or ephemeral state.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure is established in the current code.

No blocking failure remains; the prior undefined-provider issue is fixed by selecting the provider defined in models.json.

Important Files Changed

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]
Loading

Reviews (10): Last reviewed commit: "refactor: persist pi-agent LM config acr..." | Re-trigger Greptile

Comment thread .devcontainer/firstmate/settings.json Outdated
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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Suggested change
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.

@gitricko
gitricko force-pushed the feat/install-firstmate-bridge branch 2 times, most recently from a03fc6f to 7681cad Compare August 21, 2026 07:47
@gitricko gitricko changed the title feat: install firstmate-bridge skill + persist pi LM config refactor: persist pi-agent LM config across Codespace rebuilds Aug 21, 2026
@gitricko
gitricko force-pushed the feat/install-firstmate-bridge branch from 7681cad to e320b9e Compare August 21, 2026 08:01
@gitricko
gitricko force-pushed the feat/install-firstmate-bridge branch 6 times, most recently from 75a80f3 to 71087bb Compare August 21, 2026 09:01
…-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.
@gitricko
gitricko force-pushed the feat/install-firstmate-bridge branch from 71087bb to 4148d9b Compare August 21, 2026 09:16
@gitricko
gitricko merged commit 8d07d26 into main Aug 21, 2026
7 checks passed
@gitricko
gitricko deleted the feat/install-firstmate-bridge branch August 21, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants