dsh-short-tool-ids
Đã xác minhdsh-short-tool-ids · v0.4.0 · MIT · Giao diện web
Scoped, reversible tool-call ID compatibility plugin for DeepSeek Harness
Cài đặt
dsh plugin add dsh-short-tool-ids Xác nhận layer đã áp bằng dsh --profile default --dump-config — xem hướng dẫn cài plugin.
Mã nguồn
Thẻ
Tác giả
Readme
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.
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 version | npm tag (at the time of this release) | Status | Where the switches are stored |
|---|---|---|---|
0.2.0-rc.2 |
latest, next |
✅ Tested | this plugin's entry in the profile patch (cordis.patch.yml) |
0.2.0-rc.1 |
— | ✅ Tested | this plugin's entry in the profile patch (cordis.patch.yml) |
0.1.7-rc.2 |
— | ✅ Tested | this plugin's entry in the profile patch (cordis.patch.yml) |
0.1.5-rc.3 |
— | ✅ Tested | settings.yaml, section short-tool-ids |
0.1.5-rc.2 |
— | ✅ Tested | settings.yaml, section short-tool-ids |
0.1.5-rc.1 |
— | ✅ Tested | settings.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 passes | detected 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-ids | Works with DSH |
|---|---|
0.4.0 and later |
0.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 older |
only 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-completionsonly. 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-resultblocks inside a message; - 0.1.7 and later store each result as its own
toolmessage.
- 0.1.5 stores results as
- 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_idIDs 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-idssection ofsettings.yaml. When DSH 0.1.7+ first starts, it movessettings.yamlinto the profile (the file is renamed tosettings.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):
| Key | Meaning |
|---|---|
enabled: false |
Load without patching the adapter. |
harnessEntry |
Path of the running dsh CLI entry (detected automatically). |
allowUntestedHarness: true |
Load on a DSH outside the supported range. Not recommended. |
providers |
DSH 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.
| File | Role |
|---|---|
index.mjs |
Host entry: version gate, settings (both DSH generations), adapter shim. |
normalize.mjs |
ID rewriting and the reversible adapter shim. |
client/index.mjs |
Source of the Settings tab. |
lib/client.js |
Generated 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/[email protected] --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.