pi-reasoning-field-remap1.0.0
omp/pi extension: remap non-standard reasoning wire fields (e.g. delta.thinking) from OpenAI-compatible gateways to reasoning_content, in-process, no proxy.
Built for omp
The author tagged this package oh-my-pi.
Reports 0
No reports yet.
Readme
reasoning-field-remap
An Oh My Pi (omp) / pi extension for OpenAI-compatible gateways that return chain-of-thought reasoning in non-standard response fields.
The problem
omp reads model reasoning from reasoning_content, reasoning, or reasoning_text — the
fields used by DeepSeek, Kimi, and most OpenAI-compatible hosts. But some gateways ship
reasoning in their own field instead (for example delta.thinking /
message.thinking). The result: the model thinks, tokens are billed, but the thinking
blocks are invisible in the TUI — or multi-turn tool use breaks on strict hosts that
require reasoning replay.
Typical fix is a local rewrite proxy. This extension does it in-process, with no extra process: it re-registers your marked provider so the response body is rewritten on the fly, and omp's own streaming implementation (tool calls, usage, retries, auth) does all the real work.
Install
Copy index.ts into your agent extensions directory:
~/.omp/agent/extensions/reasoning-field-remap.ts (user scope)
<project>/.omp/extensions/reasoning-field-remap.ts (project scope)
or install from npm (single package, no dependencies):
omp install npm:pi-reasoning-field-remap
# in pi:
pi install npm:pi-reasoning-field-remap
Restart the session. That's it — no dependencies, no build step.
Configure
Mark any provider in ~/.omp/agent/models.yml with a compat marker:
providers:
my-gateway:
baseUrl: https://api.example.com/v1
api: openai-completions # must be openai-completions
apiKey: ...
compat:
wireReasoningSource: thinking # wire field to remap
# wireReasoningSourceStream: thinking # delta field (defaults to source)
# wireReasoningDropFields: # fields to strip (defaults to
# - thinking_signature # [<source>_signature])
models:
- id: vendor/model-x
reasoning: true
input: [text, image]
contextWindow: 1048576
maxTokens: 32768
On startup the extension logs:
[reasoning-field-remap] provider "my-gateway": reasoning wire field "thinking" -> reasoning_content (1 model(s))
Unmarked providers are never touched.
Options
| compat key | meaning | default |
|---|---|---|
wireReasoningSource |
response field carrying reasoning (message.<field> + delta.<field>) |
required |
wireReasoningSourceStream |
separate delta field name, if it differs from the source | same as source |
wireReasoningDropFields |
list of fields to strip from deltas and messages | [<source>_signature] |
The remapped value always lands in reasoning_content (omp's canonical field). The
source field is removed from the response so providers that echo it back never anchor
on it.
How it works
- At session start the extension reads
models.ymlvia omp's ownModelsConfigFileloader and finds providers carryingwireReasoningSource. - Each marked provider is re-registered under the same name with a custom internal API
whose
streamSimpledelegates to the built-inopenai-completionsimplementation from@oh-my-pi/pi-ai. - Before delegation the model is rebuilt through
@oh-my-pi/pi-catalogbuildModelwithapi: "openai-completions", materializing the resolved compat record the builtin requires (custom API names get none otherwise). - A fetch wrapper rewrites the response stream:
delta.<source>→delta.reasoning_content(line-buffered, safe for chunk-split JSON),message.<source>→message.reasoning_content, drop-fields removed.
Limitations
- Only
api: openai-completionsproviders are supported (that's where the wire-field zoo lives). - Config is read once at session start; edit
models.yml→ restart the session. - The extension uses omp's host package rewrites (
@oh-my-pi/pi-ai,@oh-my-pi/pi-coding-agent,@oh-my-pi/pi-catalog/build), so it must be loaded by omp/pi — not standalone.
License
MIT
Tests
bun test
The suite mocks omp's host packages and exercises the rewrite matrix: default marker, chunk-split JSON, and non-stream bodies.