DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-short-tool-ids

d

dsh-short-tool-ids

Manifest valid

DeepSeek Harness plugin that shortens tool-call IDs over 64 characters for OpenAI-compatible Chat Completions providers, with a per-provider toggle

UI (client)hasBundlePatch

dsh-short-tool-ids

An experimental DeepSeek Harness (DSH) plugin that fixes chats failing with errors like maximum length 64, got length 81. Some OpenAI-compatible Chat Completions providers reject tool-call IDs longer than 64 characters. This plugin shortens those IDs in outgoing requests, only for the providers you switch on in Settings → Short tool-call IDs. Saved sessions are never edited.

Source repository

Contents: Supported DSH versions · Why this plugin exists · Install · Settings tab · What it changes · Upgrading · Compatibility and risk · Development

Supported DSH versions

Supported range: DSH 0.1.5-rc.1 up to (not including) 0.3.0, with dsh-short-tool-ids 0.4.0 or later. Check yours with dsh --version.

DSH versionnpm tag (at the time of this release)StatusWhere the switches are stored
0.2.0-rc.2latest, next✅ Testedthis plugin's entry in the profile patch (cordis.patch.yml)
0.2.0-rc.1—✅ Testedthis plugin's entry in the profile patch (cordis.patch.yml)
0.1.7-rc.2—✅ Testedthis plugin's entry in the profile patch (cordis.patch.yml)
0.1.5-rc.3—✅ Testedsettings.yaml, section short-tool-ids
0.1.5-rc.2—✅ Testedsettings.yaml, section short-tool-ids
0.1.5-rc.1—✅ Testedsettings.yaml, section short-tool-ids
other releases from 0.1.5-rc.1 up to 0.3.0 (not included)—⚠️ Untested but should work: loads with a warning if the API check passesdetected automatically
older than 0.1.5-rc.1—❌ Not supported—
0.3.0 and newer (prereleases included)—❌ Refused until tested (you can override with allowUntestedHarness: true)—

Tested pi-ai (@earendil-works/pi-ai) versions: 0.85.1 (DSH 0.1.5 – 0.2.0-rc.1) and 0.87.1 (DSH 0.2.0-rc.2). The plugin does not pin pi-ai: it never loads the model catalog, and pi-ai 0.87.1 still skips ID shortening for same-model history on providers not named exactly openai, so the workaround is still needed.

Node.js: ^22.19.0 or >=24.0.0, the same floor as pi-ai itself. The test suite passes on Node 22.19.0 and 24.12.0.

Which plugin version do I need?

dsh-short-tool-idsWorks with DSH
0.4.0 and later0.1.5-rc.1 up to 0.3.0 (not included): the 0.1.5, 0.1.7 and 0.2 releases. Node ^22.19.0 or >=24.
0.3.0 and olderonly 0.1.5-rc.2 (pi-ai adapter 0.1.5-rc.2, pi-ai 0.85.1), Node >=24. Refuses to load on DSH 0.1.7 and 0.2 (untested versions … refusing to patch).

A refused plugin logs a clear error at startup and does not load. It never half-loads and never touches your sessions. When a refusal happens, the Settings tab says the host plugin is not running. Whatever the version, the plugin also checks that the pi-ai adapter still has the methods it wraps (stream, prepareCall, current, modelOf) and refuses to load if one is missing.

Why this plugin exists

This plugin was built to recover a real DSH chat session that had stopped accepting messages. The session history held tool-call IDs of 81 characters, but the OpenAI-compatible API it was sending to accepts at most 64. Every new turn resent that history, so each request failed before the model could respond:

Invalid 'input[5].call_id': string too long. Expected a string with maximum length 64, but got a string with length 81 instead.

The chat used a custom provider named cc. pi-ai only shortens IDs when the history comes from a different model, and only for a provider named exactly openai. Renaming the provider to openai: cc does not match that exact name, and even openai would still skip same-model history. This plugin closes that gap. It is a targeted workaround, not a general fix for Responses or Anthropic message IDs.

Install from npm

dsh plugin --profile web add dsh-short-tool-ids

Stop the running DSH Web process when your active work is finished, then start it again normally, e.g. dsh web --no-open --port 3080, and refresh the page. Open Settings → Short tool-call IDs and switch on the provider that returns the ID-length error, then retry the chat.

To install from a local checkout instead:

dsh plugin --profile web add "/absolute/path/to/dsh-short-tool-ids"

To remove it:

dsh plugin --profile web remove dsh-short-tool-ids

Alternatively, switch a provider off: the next request goes out unchanged.

The Settings tab

The plugin adds its own Short tool-call IDs tab to Settings, containing:

  • a heading and a short explanation;
  • a notice that it is an experimental workaround;
  • every model provider, each with its own switch, which is off by default.

Each row shows the provider's display name, its route id and its protocol. Non-pi-ai providers (the built-in DeepSeek ones, for example) are listed, but their switches are disabled because the plugin never changes their requests. A pi-ai provider on another protocol, such as anthropic-messages, is marked "not affected". A provider that was switched on and has since been removed stays listed so you can switch it off.

A change applies from the next request, including a request that has been prepared but not yet sent, and needs no restart. A failed or conflicting save shows an error instead of false success. If the host plugin is not running (for example on an unsupported DSH), the tab says so and the switches are disabled.

What it changes

  • It changes pi-ai providers using openai-completions only. Other protocols and native adapters are untouched, even if their switch is on.
  • Ordinary IDs longer than 64 characters become call_ plus 48 SHA-256 hex characters (53 in total). Each call and its matching result get the same ID.
  • Both DSH history formats are handled:
    • 0.1.5 stores results as tool-result blocks inside a message;
    • 0.1.7 and later store each result as its own tool message.
  • Valid IDs, arguments, outputs, replay metadata, tool execution identities and saved session files are left unchanged. The fix works on existing history as well as new requests.
  • If a shortened ID would collide with another ID, the plugin refuses the request instead of pairing the wrong result.
  • Compound Responses call_id|item_id IDs are left untouched. Unsupported signed or native history that would need an unsafe rewrite is refused rather than stripped.

Upgrading from 0.3.x or older

  • The switch has moved. It used to be a checkbox on each provider card under Settings → Models. It now lives in its own Short tool-call IDs tab.
  • The dsh-rpm rate-limit row has been removed. Version 0.3.0 showed dsh-rpm's "Rate limit" input under its checkbox. This plugin is now fully independent: it never reads or writes another plugin's settings and does not register on the provider cards.
  • Existing switches carry over. On DSH 0.1.5 they stay in the short-tool-ids section of settings.yaml. When DSH 0.1.7+ first starts, it moves settings.yaml into the profile (the file is renamed to settings.yaml.imported), so your old values end up as this plugin's config.
  • Stop DSH, reinstall the plugin, start DSH again and refresh the page. The browser bundle is cached until the server restarts.

Compatibility and risk

Zero regressions are not guaranteed. This is a prototype wrapper, not an officially supported adapter-decorator API. DSH's ordinary llm/stream middleware only sees frozen durable requests and cannot replace their history.

The plugin finds the adapter through the running CLI's own dependency tree. It wraps PiAiAdapter.stream() and prepareCall() in a reversible way and keeps the original prepared handles and model snapshots. It must not be combined with another wrapper of the same methods; a second copy of this plugin is refused (already installed).

Plugin config keys (optional, set on the short-tool-ids entry):

KeyMeaning
enabled: falseLoad without patching the adapter.
harnessEntryPath of the running dsh CLI entry (detected automatically).
allowUntestedHarness: trueLoad on a DSH outside the supported range. Not recommended.
providersDSH 0.1.7+: the per-provider switches edited by the Settings tab.

Development

The plugin has zero npm runtime or build dependencies. The host code is plain ESM, and a dependency-free builder writes the browser bundle in DSH's ModuleLoader format, using the shell's own React.

FileRole
index.mjsHost entry: version gate, settings (both DSH generations), adapter shim.
normalize.mjsID rewriting and the reversible adapter shim.
client/index.mjsSource of the Settings tab.
lib/client.jsGenerated by npm run build; never edit it by hand.
npm run build
npm test
DSH_TEST_HARNESS_ENTRY="/absolute/path/to/dsh/lib/bin.js" npm run test:integration
npm run pack:check

To run the integration suite against another DSH version, install that version in a scratch folder and point DSH_TEST_HARNESS_ENTRY at it:

npm install --prefix /tmp/dsh-017 @deepseek-ai/dsh@0.1.7-rc.2 --ignore-scripts
DSH_TEST_HARNESS_ENTRY=/tmp/dsh-017/node_modules/@deepseek-ai/dsh/lib/bin.js npm run test:integration

The integration suite sends the real adapter's HTTP requests to a loopback mock server (fake credentials, no paid API calls), in the history format of the DSH under test. It also mounts the plugin on that DSH's real settings API. The optional DSH_TEST_SESSION=/path/to/decoded-session.jsonl enables private-history replay checks. Never package or commit real session history.

The UI tests use a fake React harness rather than a browser. Version 0.4.0 was also checked in the real DSH Web app on 0.2.0-rc.2 (under Node 22.19.0), 0.2.0-rc.1, 0.1.7-rc.2 and 0.1.5-rc.3, by installing the packed tarball into an isolated DSH_HOME and chatting with a mock provider that returns 81-character IDs. On each version:

  • the tab rendered;
  • the switch saved, and on 0.2 persisted across a restart;
  • the provider received 53-character IDs while the switch was on;
  • the saved session kept the original IDs;
  • switching off restored the original IDs on the next request (checked on 0.2).

License

MIT. Maintainer release steps are in RELEASE.md.

Comments

Loading…