Skip to content

cordis-plugin-aux-reasoning

Verified

@argszero/cordis-plugin-aux-reasoning Β· v0.1.0 Β· MIT

Auxiliary-call reasoning policy for dsh: the harness marks its own background calls (compaction checkpoints, session titles) with a `purpose` and names no reasoning level for them, so `dsh-llm` fills the gap from the route's declared default and they thin

Install

dsh plugin add @argszero/cordis-plugin-aux-reasoning

Confirm the layer applied with dsh --profile default --dump-config β€” see the install guide.

Source

Tags

Readme

@argszero/cordis-plugin-aux-reasoning

Stop the harness's own background model calls from thinking.

A deepseek-harness plugin. Source discussion: #7109 β€” Honor purpose when an auxiliary call names no reasoning level.

npm install @argszero/cordis-plugin-aux-reasoning

The gap

The harness marks the model calls it makes on its own behalf β€” not on the user's β€” with a purpose:

  • dsh-compaction-basic streams a context checkpoint with purpose: 'compaction';
  • dsh-session-title-llm streams a session title with purpose: 'session-title'.

Neither names a reasoningEffort. dsh-llm fills that gap from the route:

const requested = defaulted.reasoningEffort
const effective = requested ?? reasoning.defaultEffort

So on any route whose profile default is a thinking level, compaction and session titles think β€” at full length β€” inside a maxTokens cap the caller chose. That is the wrong default for a call whose entire job is to produce a bounded amount of visible text:

  • thinking spends the cap first, so a summariser whose thinking eats the cap truncates the checkpoint;
  • on a local model the cost is wall-clock rather than quota β€” a few hundred thinking tokens is minutes per compaction at single-digit tok/s.

The harness has already decided this for its own adapter: dsh-llm-deepseek returns { thinking: 'disabled' } for purpose === 'session-title', and the compaction call carries x-deepseek-harness-compact: 1 for the server to act on. A pi-ai-backed route has no equivalent β€” so the same harness behaves two ways depending on which adapter serves the model. This plugin supplies the missing half from outside the adapter.

What it does

It joins the public llm/stream waterfall and, for a request that

  1. carries a configured auxiliary purpose,
  2. names no reasoningEffort of its own,
  3. targets a route that genuinely offers the configured level, and
  4. would otherwise inherit a different level from the route's declared default,

re-dispatches the request as a new object with that level named.

Every other request takes the identity path: next() is called with the original object. Nothing is copied, and nothing is re-dispatched.

aux-reasoning: purpose=session-title pi-ai/local-qwen: high -> off

Why the level is looked up, not assumed

Naming reasoningEffort is not a preference, it is a claim that the route supports that level. dsh-llm rejects the call with UNSUPPORTED_REASONING_EFFORT when the route declares no reasoning metadata at all, and again when the named level is missing from the route's efforts. A plugin that named off unconditionally would therefore convert a working (merely expensive) configuration into a hard failure on every non-reasoning route: compaction and session titles would stop working entirely.

So the plugin asks ctx.llm.resolveModelInfo() β€” the very query the dispatch itself resolves against β€” and substitutes only when the level is genuinely offered. Every skip is a pass-through.

situation what happens
route offers the level, default differs level named, request re-dispatched
route offers the level, default already the target left alone
route does not offer the level left alone, reported
route declares no reasoning levels left alone, reported
route declares no default left alone, reported
call names its own level left alone, never overridden
purpose not in the configured set left alone
route cannot describe itself left alone, reported

Configuration

With no configuration the plugin treats compaction and session-title as auxiliary and names off.

- insert:
    - id: aux-reasoning
      name: '@argszero/cordis-plugin-aux-reasoning'
      config:
        purposes: [compaction, session-title]
        effort: off          # the level named for those calls
        reportLimit: 5       # bounded diagnostics; 0 silences them
        observeOnly: false   # true = report what would change, change nothing

observeOnly: true is the safe way to see what the plugin would do on your routes before letting it act.

Install and mount

The package ships a bundle patch, so adding it to a profile's plugin list is enough; dsh.bundle.patch points at cordis.patch.yml, which inserts the plugin under the id aux-reasoning. To mount it by hand, add the same entry to your own cordis.yml:

- name: '@argszero/cordis-plugin-aux-reasoning'
  config:
    effort: off

Scope and honesty

  • Ordinary turns are never touched. Only requests carrying a configured purpose are considered, and only when they name no level themselves. Your interactive thinking configuration is not this plugin's business.
  • The plugin changes the request, not the route. It cannot make a provider behave differently when the adapter sends no reasoning option for either the named level or the default β€” on such a route the two requests are byte-for- byte identical, and the plugin is a no-op there by construction.
  • A substitution is a re-dispatch. The requests other llm/stream listeners see are exactly the requests that are sent (the plugin registers with prepend: true), and each proposed call reaches the adapter exactly once β€” never a discarded call plus a real one.
  • Complementary, not overlapping, with @argszero/cordis-plugin-thinking-level-fallback, which re-sends a call after a provider rejects the level it was sent. This plugin decides before the first dispatch; that one reacts after a failure.

Compatibility

Peer-tested against the dsh-llm prerelease lines 0.1.2-rc.1, 0.1.3-alpha.2, 0.1.5-* and 0.1.6-* (the peerDependencies range lists each line explicitly, because semver caret ranges silently exclude prereleases of other versions).

Tests

npm test

25 tests: the decision rules in isolation, plus integration tests against a real @deepseek-ai/cordis context and the published @deepseek-ai/dsh-llm runtime, asserting what the adapter receives β€” including the negative control that naming off on a route with no reasoning metadata fails with UNSUPPORTED_REASONING_EFFORT, which is exactly what the unconditional form of this plugin would have done.

The suite passes against each dsh-llm prerelease line this manifest claims (0.1.2-rc.1, 0.1.3-alpha.2, 0.1.5-rc.2, 0.1.6-alpha.2), installed one at a time.

What the wire shows

Mounting the plugin next to @deepseek-ai/dsh-llm-deepseek (installed from npm, pointed at a loopback server, route configured reasoningEffort: high) makes the change visible in the HTTP body:

request without the plugin with the plugin
purpose: 'compaction' "thinking":{"type":"enabled"}, "reasoning_effort":"high" "thinking":{"type":"disabled"}, no effort
purpose: 'session-title' "thinking":{"type":"disabled"} unchanged β€” the adapter already decides this
no purpose "thinking":{"type":"enabled"}, "reasoning_effort":"high" unchanged β€” ordinary turns are not this plugin's business

The first row is worth reading twice: even on DeepSeek's own route the compaction call is sent with thinking enabled. The adapter disables it for session-title and otherwise relies on x-deepseek-harness-compact: 1 for the server to act on β€” the header is still sent, but it is advice, not a local decision. So the missing decision is not specific to pi-ai-backed routes.

License

MIT