Skip to content
dsh-market Browse plugins GitHub 中文

Pummelchen/TinyTitan#dsh-tinytitan

Keeps a local TinyTitan model server reachable from the harness: refreshes the llm-pi-ai route from the installed models and mounts a compaction backend that does not think.

Stars ★ 54 Category Models & Providers Listed 2026-09-19

Install

Inside DeepSeek Harness, with dsh-market

dsh plugin --profile web add dshmarket

Or from the command line

dsh plugin --profile web add github:Pummelchen/TinyTitan#path:/plugins/dsh-tinytitan

Installing runs third-party code with your own permissions — it can read your files, use your credentials and reach the network. Review the source first, and pin a commit (github:owner/repo#sha) when you can.

README

A DeepSeek Harness bundle for running models from a local TinyTitan server. It is deliberately thin: the harness's own llm-pi-ai adapter serves these models, so this package adds configuration, not a protocol implementation.

Two jobs, both at boot, both idempotent:

  1. Keeps the route current. tools/dsh_route.sh in this checkout turns the installed models under models/ into the llm-pi-ai route block — served ids, each template's thinking levels, and the three switches that are easy to get wrong by hand (thinkingFormat: chat-template, the keyless-route auth header, the long stream idle timeout). The plugin applies that block through the harness's own settings service, so the change lands in the active profile patch and hot-reloads; the model picker follows models/ instead of a copy someone typed once. A plugin installed from a catalogue is a plain package beside no checkout, so there is no script to run: only then the same block is generated in-process from the server's own catalog (generate.js), and the log says so. Wherever tools/dsh_route.sh exists it stays the source of truth, so a checkout user has one implementation, not two.
  2. Mounts a compaction backend that does not think. Compaction and session titles are marked purpose: "compaction" / "session-title" and name no reasoning level, so the harness fills in the route's default. On a local thinking model that spends a summariser's own output cap on thinking and costs tens of seconds on the title of every new session. The plugin registers an agent preset built from the harness's shipped standard composition with that row pointed at dsh-tinytitan/backend, which forces thinking off for those calls only — ordinary turns keep the route's level. While your profile has selected no preset of its own, this one becomes the default; an explicit choice on the Agent presets page is never overwritten.

Supported harness version

This bundle supports exactly one DeepSeek Harness release: 0.2.0-rc.2 — not older, not newer, and not a build from main. Both jobs above are written against that release: the preset is generated from its shipped standard composition (the preset-standard row of @deepseek-ai/dsh-web-app/presets/standard.patch.yml, read through @deepseek-ai/dsh-agent-preset's agentPresets.register), so the row ids move when the harness does, and the compaction backend subclasses that release's dsh-compaction-basic. It is also the release tools/dsh_local.sh installs.

The pin lives in three places that cannot import each other — package.json's peerDependencies (exact, no range), the launcher's DSH_VERSION default, and SUPPORTED_DSH_VERSION in src/support.js — and test/support.test.js fails if they disagree.

On any other release — older, newer, or a build from main — the plugin refuses to run. It writes one line to stderr naming both versions and does nothing else: no route, no preset, no watcher, and no writes into your harness home. It never throws, so DSH boots normally, every other plugin loads, and removing this plugin leaves nothing to undo. A version that cannot be read at all is refused the same way, because a plugin that writes into the harness home has no business proceeding on a harness it cannot identify.

stderr is not a style choice. The harness collects a plugin's log records and prints them only when the boot itself fails, and its startup exporter takes level ≥ 2, so a refusal logged through the host logger is invisible on a healthy boot — which would be indistinguishable from a plugin that silently stopped working. Found by booting a throwaway harness, not by reading.

Install

dsh plugin --profile web add file:/path/to/TinyTitan/plugins/dsh-tinytitan

Restart DSH (or start a new session) and the plugin logs what it did. It writes through the harness's own services, so the changes are part of your profile configuration and hot-reload with it:

What Change
the llm-pi-ai entry the route block, refreshed from the catalog
the agent-preset registry a tinytitan preset, built from the harness's shipped standard composition with the compaction row on this backend
the selected agent preset set to tinytitan only while the profile names no selection of its own

There is no settings file to edit and no preset file to copy: DSH 0.2.0 removed both, and the plugin uses the replacements. If you would rather select the preset yourself, set setDefaultWhenUnset: false — then the plugin registers tinytitan and leaves your choice alone.

If you remove the plugin, set another preset on the Agent presets page first: the selection it made is a normal setting, and nothing is left behind to clean it up.

A file: install is a copy, not a link: after editing this package, re-install it (dsh plugin --profile web remove dsh-tinytitan then add again) or DSH keeps running the copy it made.

Upgrading from 0.1.6-alpha.2

The preset keeps its id (tinytitan), so sessions that were already on it keep working — the id is what a session records, and only its declaration changed from a generated file to a registry entry. Three things are worth knowing:

  • On 0.2.0 the default preset is a registry field. The plugin points it at tinytitan only while nothing else is selected. If you had picked another preset, open the Agent presets page and pick TinyTitan to get the quiet compaction back; a choice you make there is never overwritten.
  • ~/.dsh/.agent-presets/tinytitan/ (the 0.1.6 generated preset) is inert — 0.2.0 does not read that directory. Deleting it is optional cleanup.
  • ~/.dsh/settings.yaml.imported is your old settings file, moved there by the harness when it imported it into the profile patch. Keep it; it is the record of what was migrated.

Configure

Every field is optional; these are the defaults the cordis.patch.yml row writes out, and TINYTITAN_PORT / TINYTITAN_REASONING / TINYTITAN_REPO / TINYTITAN_SERVER / TINYTITAN_MODELS_DIR / DSH_HOME are the environment fallbacks.

Field Default Meaning
port resolved: config.port, else TINYTITAN_PORT, else 8080 the port the TinyTitan server serves on. Nothing in this bundle pins it, so the environment can point the route at a server on another port
provider tinytitan the llm-pi-ai provider route name
reasoning resolved: config.reasoning, else TINYTITAN_REASONING, else medium the route's declared default reasoning level. It must match how the server was started: a route that says "think" against a server running --reasoning off makes a dense Qwen spend its whole output budget inside the reasoning block and never answer
presetId tinytitan the agent preset this plugin registers
registerRoute true refresh the route block from tools/dsh_route.sh
watchModels true keep watching models/ and refresh when an install appears or disappears
watchDebounceMs 2000 how long the folder has to be quiet before the refresh runs
selfContained false use the built-in generator even where tools/dsh_route.sh exists
serverBinary discovered the TinyTitanServer the built-in generator runs ($TINYTITAN_SERVER)
modelsDir <repoRoot>/models the installs it describes ($TINYTITAN_MODELS_DIR)
writeCompactionPreset true register the tinytitan preset
setDefaultWhenUnset true select that preset only while the profile has selected none
compactionHeadroomTokens unset (the harness's 65536) the compaction engine's headroom in the generated preset — see below
repoRoot this checkout where tools/dsh_route.sh lives
dshHome $DSH_HOME or ~/.dsh the harness home, for the built-in generator's file fallback

The built-in generator looks for the server at serverBinary, then TINYTITAN_SERVER, then TinyTitanServer on PATH, then the checkout's release build; it looks for models at modelsDir, then TINYTITAN_MODELS_DIR, then <repoRoot>/models. On a harness with no settings service it falls back to editing the home's settings.yaml — the 0.1.6 shape — and refuses to write when that file does not exist; through the service it makes no write at all when the refresh would not change a byte.

0.1.6's adoptDefaultPreset (re-point the current default preset's stock compaction row) has no counterpart here and the field is gone: presets are declared rows now, so adopting a shipped one would mean freezing its whole plugin list in your patch — the drift the generated preset exists to avoid. Select the tinytitan preset instead; it is the default whenever you have chosen nothing.

The compaction trigger is why compactionHeadroomTokens exists. The engine compacts at min(window × thresholdRatio, window − maxTokens − headroomTokens). The harness's default headroom is 65,536 tokens, and the generated preset leaves that default alone, so on the route this project declares (262,144 window, 32,768 cap) the trigger sits at ~62% of the window rather than the documented 80%. That is a safe direction — less context, less KV on a local server — but on a narrow declared window the arithmetic flips: below roughly cap + 65,536 the pressure budget goes negative, the engine logs one warning and then never compacts, and the session eventually fails on the context wall. If you generate a route with tools/dsh_route.sh --context <smaller>, set the plugin's compactionHeadroomTokens, e.g. 0 to let the ratio govern again or the cap's quarter (8192) to keep a guard: both leave a positive budget at every window where window > maxTokens.

With no server built, the folder is read directly. The catalog normally comes from TinyTitanServer --catalog, which is the authority on what an install is. A profile that has installed models but has not built the server yet has nothing to ask, so src/catalog-scan.js walks models/ itself — the same rules, mirroring ModelCatalog.swift, and test/catalog-scan.test.js compares its rows against the binary's own output on the same folder so the two cannot drift. A binary that exists but fails is treated the same way, and the reason goes to the log.

The route follows the folder while the harness runs. An install is a long download someone starts and then wants to use, so models/ is watched and the route is rebuilt once the folder goes quiet (watchDebounceMs). Deletions count too: a removed model stops being offered. The watcher is non-persistent and unref'd — it never keeps the process alive — and a platform where watching fails falls back to the boot-time refresh with a log line.

What it does not do

  • No adapter. It registers no LLM provider: the harness's llm-pi-ai route does the work, so a harness upgrade cannot leave a copied protocol implementation behind.
  • No budgets, no vision, no dialects. TinyTitan accepts reasoning_budget_tokens and does not enforce it; the models are text-only; llama.cpp/TabbyAPI are other servers with their own routes. None of that is here.
  • No session-title override. Titles are issued by a host-plane plugin with its own context, which a bundle cannot wrap; that half is upstream ask 1 in docs/dsh-upstream-asks.md. Until it lands, the route's reasoning: off is the only way to keep titles unthinking — at the cost of chat starting unthinking too.

Uninstall

dsh plugin --profile web remove dsh-tinytitan

Nothing is left on disk to clean up: the route and the preset are profile configuration, and removing the row stops both being refreshed. One thing to undo by hand — if this plugin selected the tinytitan preset for you, pick another preset on the Agent presets page before you remove it, because the selection outlives the plugin that made it.

Test

cd plugins/dsh-tinytitan && node --test test/

Seventy-nine tests, no harness packages required: the compaction seam is exercised against a stub base, the preset builder, the default-preset rule and the route preferences against stubs and temporary homes, and the route call against a stubbed runner. The built-in generator's block is compared byte-for-byte with tools/dsh_route.sh --print — on the real catalog when the checkout's server binary is built, and on a synthetic catalog (mixed backends, re-sorted thinking levels) whenever the shell tool is present; both comparisons skip with a clear message when the pieces are absent, so the suite stays runnable elsewhere. The dsh-tinytitan/backend import itself is resolved from the profile's own node_modules once installed.

Licence

MIT, deliberately. The repository it lives in is Apache-2.0, and this package says MIT on purpose: it is an independent work that talks to the server over its public HTTP API and copies no code from the project's lineage, so it stays under the licence its own author chose. Do not "align" it with the repository's LICENSE — that would be a claim about provenance this package does not make.

Publishing it

docs/dsh-plugin-publication.md in this repository is the research: how a DeepSeek Harness plugin is distributed, the community catalogue that lists it, and exactly what this package still needs before it can be submitted.

Content from the project README on GitHub ↗

Comments

Comments live in GitHub Discussions. Sign in with GitHub to post or react.