feat(integrations): add Oh My Pi (omp) client integration - #1140
feat(integrations): add Oh My Pi (omp) client integration#1140hanbinnoh wants to merge 6 commits into
Conversation
omp 17.x reads custom providers from ~/.omp/agent/models.yml, so the existing pi integration (legacy ~/.pi/agent/models.json) cannot reach it. Add an 'omp' export/integration client that writes the opencodex provider block as models.yml, honoring omp's profile and agent-dir overrides, and wire it through the CLI, management API, GUI and docs.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAdds Oh My Pi as a seventh export client. The change generates OMP provider YAML, registers its paths and integration state, exposes GUI integration controls and translations, updates CLI help, and adds documentation and tests. ChangesOh My Pi export and integration
Estimated code review effort: 3 (Moderate) | ~30 minutes Sequence Diagram(s)sequenceDiagram
participant CLI as ocx export
participant Export as config-export
participant Registry as integrations registry
participant OMP as OMP models.yml
CLI->>Export: select --client omp
Export->>Registry: resolve OMP path and metadata
Export->>OMP: write provider YAML
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
✅ Deterministic PR hygiene checks passed. |
⏳ DRAFT
What to do
Review readiness checklist
0/4 boxes ticked. This PR stays in draft until every box above is ticked. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3a53748d27
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const profile = env.OMP_PROFILE?.trim() ?? env.PI_PROFILE?.trim(); | ||
| const agentOverride = env.PI_CODING_AGENT_DIR?.trim(); | ||
| if (profile && profile !== "default") return join(root, "profiles", profile, "agent"); | ||
| if (agentOverride && agentOverride.length > 0) return agentOverride; |
There was a problem hiding this comment.
Reject relative omp agent-directory overrides
When PI_CODING_AGENT_DIR is relative, this returns a relative config path, so the dashboard integration reads and writes it relative to opencodex's working directory while separately launched omp resolves the same variable relative to its own working directory. The switch can therefore report the integration as current after modifying a file omp never reads, and later disable/restore operations can target another file if the proxy's working directory changes. Expand only stable absolute or ~ paths, or refuse the mutation as the existing OpenClaw path handling does.
AGENTS.md reference: src/AGENTS.md:L10-L10
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs-site/src/content/docs/guides/oh-my-pi.md`:
- Line 3: Update the frontmatter description for the Oh My Pi guide to
accurately state that `ocx export --client omp` prints the custom provider YAML,
destination, and merge instructions rather than writing
`~/.omp/agent/models.yml` directly; alternatively, explicitly attribute the
write operation to the dashboard.
- Around line 28-29: Clarify the Oh My Pi configuration example around the
exported YAML by stating that openai-completions is the OMP adapter and
OPENCODEX_OMP_API_KEY is only a local OMP provider key, not an opencodex OAuth
or access-token credential. Add this explanation near the YAML exports without
changing the generated example content.
In `@gui/src/components/apikeys-workspace/client-config-clients.ts`:
- Around line 11-17: Update the OMP entry in CLIENT_LABEL_KEYS and its related
client-config UI copy to avoid JSON-specific wording, using format-neutral
“config” keys or selecting YAML-specific i18n keys based on the client format
declared in config-export. Add or update all user-visible text through the i18n
locale files, including copy buttons, ARIA labels, and announcements.
In `@src/clients/config-export.ts`:
- Around line 368-372: Update the profile selection in ompAgentDir to treat a
trimmed, blank OMP_PROFILE as unset before falling back to PI_PROFILE, while
preserving the existing non-default profile and agentOverride behavior. Add a
regression case covering blank OMP_PROFILE with a configured PI_PROFILE and
assert the PI_PROFILE agent directory is returned.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: e51bac55-a2e7-4f23-96a5-e4685e8e2a78
⛔ Files ignored due to path filters (1)
gui-screenshot.pngis excluded by!**/*.png
📒 Files selected for processing (23)
docs-site/astro.config.mjsdocs-site/src/content/docs/guides/integrations.mddocs-site/src/content/docs/guides/oh-my-pi.mdgui/src/components/apikeys-workspace/client-config-clients.tsgui/src/i18n/de.tsgui/src/i18n/en.tsgui/src/i18n/ja.tsgui/src/i18n/ko.tsgui/src/i18n/ru.tsgui/src/i18n/zh.tsgui/src/pages/Integrations.tsxgui/src/pages/integrations/FileIntegrationPage.tsxgui/src/pages/integrations/integration-api.tsgui/src/pages/integrations/overview-clients.tssrc/cli/help.tssrc/clients/config-export.tssrc/integrations/registry.tstests/cli-export-command.test.tstests/client-config-export-new-clients.test.tstests/client-config-export.test.tstests/integrations-invariants.test.tstests/integrations-state.test.tstests/management-client-config-route.test.ts
| @@ -0,0 +1,58 @@ | |||
| --- | |||
| title: Oh My Pi | |||
| description: Use any routed model from Oh My Pi (omp) — ocx export writes a custom provider block for omp's ~/.omp/agent/models.yml, wired to the running proxy. | |||
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Change the description to match ocx export behavior.
ocx export --client omp prints the YAML, destination, and merge instructions. It does not directly write ~/.omp/agent/models.yml. Change “writes” to “prints” or state that the dashboard performs the write.
Proposed fix
-description: Use any routed model from Oh My Pi (omp) — ocx export writes a custom provider block for omp's ~/.omp/agent/models.yml, wired to the running proxy.
+description: Use any routed model from Oh My Pi (omp) — ocx export prints a custom provider block for omp's ~/.omp/agent/models.yml, wired to the running proxy.As per path instructions, keep the user-facing guide synchronized with actual CLI behavior.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| description: Use any routed model from Oh My Pi (omp) — ocx export writes a custom provider block for omp's ~/.omp/agent/models.yml, wired to the running proxy. | |
| description: Use any routed model from Oh My Pi (omp) — ocx export prints a custom provider block for omp's ~/.omp/agent/models.yml, wired to the running proxy. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs-site/src/content/docs/guides/oh-my-pi.md` at line 3, Update the
frontmatter description for the Oh My Pi guide to accurately state that `ocx
export --client omp` prints the custom provider YAML, destination, and merge
instructions rather than writing `~/.omp/agent/models.yml` directly;
alternatively, explicitly attribute the write operation to the dashboard.
Source: Path instructions
| api: openai-completions | ||
| apiKey: "$OPENCODEX_OMP_API_KEY" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Files:"
git ls-files 'docs-site/src/content/docs/**/oh-my-pi.md' 'docs-site/src/content/docs/reference/adapters.md' 'docs-site/src/content/docs/guides/providers.md' 2>/dev/null || true
echo
echo "oh-my-pi outline/context:"
for f in $(git ls-files 'docs-site/src/content/docs/**/oh-my-pi.md'); do
echo "== $f =="
wc -l "$f"
sed -n '1,120p' "$f" | nl -ba
done
echo
echo "Reference adapter and providers docs relevant lines:"
for f in docs-site/src/content/docs/reference/adapters.md docs-site/src/content/docs/guides/providers.md; do
if [ -f "$f" ]; then
echo "== $f =="
wc -l "$f"
sed -n '1,220p' "$f" | nl -ba | rg -i "openai-completions|OpenAI Chat|OAuth|forward|authentication|apiKey|api:" -C 3 || sed -n '1,220p' "$f" | nl -ba
fi
done
echo
echo "All OMP docs references to auth/adapters/api config:"
rg -n -S "Oh My Pi|oh-my-pi|OMP|openai-completions|OPENCODEX_OMP_API_KEY|authentication|OAuth|forward" docs-site/src/content/docs || trueRepository: lidge-jun/opencodex
Length of output: 475
🏁 Script executed:
#!/bin/bash
set -euo pipefail
for f in docs-site/src/content/docs/guides/oh-my-pi.md docs-site/src/content/docs/reference/adapters.md docs-site/src/content/docs/guides/providers.md; do
echo "== $f =="
wc -l "$f"
cat -n "$f" | sed -n '1,180p'
echo
done
echo "All OMP docs references to auth/adapters/api config:"
rg -n -S "Oh My Pi|oh-my-pi|OMP|openai-completions|OPENCODEX_OMP_API_KEY|authentication|OAuth|forward" docs-site/src/content/docs || true
echo
echo "Git diff stat/name status:"
git diff --stat || true
git diff -- docs-site/src/content/docs/guides/oh-my-pi.md docs-site/src/content/docs/reference/adapters.md docs-site/src/content/docs/guides/providers.md | sed -n '1,220p' || trueRepository: lidge-jun/opencodex
Length of output: 50378
Clarify the OMP adapter and credential boundary.
docs-site/src/content/docs/guides/oh-my-pi.md:28 and :45 show the OMP export, but the example does not say what openai-completions means or that $OPENCODEX_OMP_API_KEY is only a local OMP provider key, not an opencodex OAuth/access-token credential. Add one clear sentence before or after the exported YAML, or use prose instead of comments if the generated example must stay exact.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs-site/src/content/docs/guides/oh-my-pi.md` around lines 28 - 29, Clarify
the Oh My Pi configuration example around the exported YAML by stating that
openai-completions is the OMP adapter and OPENCODEX_OMP_API_KEY is only a local
OMP provider key, not an opencodex OAuth or access-token credential. Add this
explanation near the YAML exports without changing the generated example
content.
Source: Path instructions
| export const CLIENTS = ["opencode", "pi", "omp", "hermes", "openclaw", "kimi", "gajae"] as const; | ||
| export type ExportClientId = (typeof CLIENTS)[number]; | ||
|
|
||
| export const CLIENT_LABEL_KEYS = { | ||
| opencode: "api.clientConfig.clientOpencode", | ||
| pi: "api.clientConfig.clientPi", | ||
| omp: "api.clientConfig.clientOmp", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use format-neutral or format-specific copy for OMP.
Adding omp to CLIENTS exposes it in the client-config UI. The shared keys in gui/src/i18n/en.ts:1589-1612 still describe copied configurations as JSON. The backend declares OMP with format: "yaml" in src/clients/config-export.ts:1043-1143. OMP users will see incorrect copy buttons, ARIA labels, and announcements. Use “config” wording or select JSON/YAML-specific i18n keys from the client format.
As per path instructions, user-visible strings must go through the i18n locale files.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@gui/src/components/apikeys-workspace/client-config-clients.ts` around lines
11 - 17, Update the OMP entry in CLIENT_LABEL_KEYS and its related client-config
UI copy to avoid JSON-specific wording, using format-neutral “config” keys or
selecting YAML-specific i18n keys based on the client format declared in
config-export. Add or update all user-visible text through the i18n locale
files, including copy buttons, ARIA labels, and announcements.
Source: Path instructions
| const profile = env.OMP_PROFILE?.trim() ?? env.PI_PROFILE?.trim(); | ||
| const agentOverride = env.PI_CODING_AGENT_DIR?.trim(); | ||
| if (profile && profile !== "default") return join(root, "profiles", profile, "agent"); | ||
| if (agentOverride && agentOverride.length > 0) return agentOverride; | ||
| return join(root, "agent"); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Treat a blank OMP_PROFILE as unset before applying PI_PROFILE.
Line 368 uses ??, which only falls back for undefined or null. If OMP_PROFILE=" " and PI_PROFILE="legacy", profile becomes "" and ompAgentDir returns the default agent directory instead of the legacy profile directory. This contradicts the documented PI_PROFILE fallback behavior.
Use a truthy normalized OMP profile before reading PI_PROFILE. Add a regression case for blank OMP_PROFILE.
Proposed fix
- const profile = env.OMP_PROFILE?.trim() ?? env.PI_PROFILE?.trim();
+ const ompProfile = env.OMP_PROFILE?.trim();
+ const profile = ompProfile || env.PI_PROFILE?.trim();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const profile = env.OMP_PROFILE?.trim() ?? env.PI_PROFILE?.trim(); | |
| const agentOverride = env.PI_CODING_AGENT_DIR?.trim(); | |
| if (profile && profile !== "default") return join(root, "profiles", profile, "agent"); | |
| if (agentOverride && agentOverride.length > 0) return agentOverride; | |
| return join(root, "agent"); | |
| const ompProfile = env.OMP_PROFILE?.trim(); | |
| const profile = ompProfile || env.PI_PROFILE?.trim(); | |
| const agentOverride = env.PI_CODING_AGENT_DIR?.trim(); | |
| if (profile && profile !== "default") return join(root, "profiles", profile, "agent"); | |
| if (agentOverride && agentOverride.length > 0) return agentOverride; | |
| return join(root, "agent"); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/clients/config-export.ts` around lines 368 - 372, Update the profile
selection in ompAgentDir to treat a trimmed, blank OMP_PROFILE as unset before
falling back to PI_PROFILE, while preserving the existing non-default profile
and agentOverride behavior. Add a regression case covering blank OMP_PROFILE
with a configured PI_PROFILE and assert the PI_PROFILE agent directory is
returned.
- Reject a relative PI_CODING_AGENT_DIR instead of silently anchoring it to opencodex's cwd, so the toggle cannot report current against a file omp never reads (Codex P2). - Treat a blank OMP_PROFILE as unset so the legacy PI_PROFILE falls through, matching omp's own env precedence (CodeRabbit). - Register integrations/omp in the app router so the Oh My Pi tab does not bounce back to Overview (the user-visible tab bug). - Make client-config UI copy format-neutral (config instead of JSON) in all six locales and their tests. - Clarify the oh-my-pi guide: ocx export prints, the dashboard writes; openai-completions is the OMP adapter and OPENCODEX_OMP_API_KEY is a local provider key, not an opencodex credential.
The omp integration dropped every model's reasoning metadata because ExportModel never carried reasoningEfforts/defaultReasoningEffort and toExportModel did not pass them through. omp only exposes a reasoning effort control when the model entry declares a thinking block, so without this the omp picker showed no effort selector at all. - ExportModel gains reasoningEfforts/defaultReasoningEffort and model-rows passes them through from the live catalog. - The omp builder emits a thinking block (mode effort) per model with efforts, dropping out-of-vocabulary values so one bad entry cannot fail the whole provider config. - Add moonshotai/Kimi-K3 to the Command Code official effort table (high/max, verified on commandcode.ai/models/kimi-k3) so OAuth-linked Kimi K3 also gets an effort picker. - Tests cover the omp thinking emission and the registry entry.
omp's resolveModelThinking returns undefined unless the model entry sets reasoning: true, so the thinking block alone was silently dropped and the omp picker showed no effort selector for command-code models. Emit reasoning: true alongside the thinking block; verified with a scratch omp agent dir that command-code/deepseek and Kimi-K3 now list high,max.
The official Command Code CLI (v1.14.0) marks Kimi K3 reasoning:true but does not give it a reasoningEfforts array — there is no effort selector in the original client. Adding high/max advertised an effort tier the upstream does not offer. Remove the entry; the existing test already pinned Kimi-K3 as absent from the official effort table.
Summary
Adds Oh My Pi (omp) as a first-class client integration. omp 17.x reads custom providers from
~/.omp/agent/models.yml, so the existingpiintegration (which targets the legacy~/.pi/agent/models.json) cannot reach it.The new
ompclient:opencodexprovider block into~/.omp/agent/models.yml(YAML,api: openai-completions,$OPENCODEX_OMP_API_KEYenv reference — never a serialized key).PI_CONFIG_DIR,PI_CODING_AGENT_DIR, andOMP_PROFILE/PI_PROFILE(profile wins over the agent-dir override, matching omp'sDirResolver).ocx export --client omp, the management API, and the CLI help.x-opencodex-api-keyheader a non-loopback bind requires, so a remote bind is refused rather than handed a config that 401s.The generated document was validated against omp 17.2.10's own
ModelsConfigSchemaandvalidateProviderConfiguration.Verification
bun run typecheck— cleanbun run test— 9460 pass, 0 failbun run lint:gui— cleanbun run privacy:scan— passedbun run build:gui— buildsPI_CONFIG_DIR/PI_CODING_AGENT_DIR/ profiles), and the full integration lifecycle (apply/disable round trip)models.ymlvalidated against the installed@oh-my-pi/pi-coding-agent@17.2.10schemaScreenshot
Oh My Pi tab in the Integrations dashboard:
Checklist
Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
All CI tests are green on my local testing.
I pushed my PR to the latest dev commit.
I resolved all correct Codex and CodeRabbit findings.
My PR is ready for review.
Summary by CodeRabbit
New Features
ocx export --client ompto generate Oh My Pi provider configuration.Documentation