dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
会话标题 provider 替换插件:先把过长或代码密集的首条 Prompt 压缩再调用模型(实测 DSH 版本的内建 provider 在超过 4096 bytes 时直接拒绝、不调用模型),遇到纯问候则等待真正的任务。默认使用该会话自身的 provider 与 model,保护人工标题;标题规则支持字数上限、可选日期前后缀、风格、语言与排除词,并可按会话锁定标题。还可批量重优化历史会话标题,进度浮层在关闭设置页后继续运行。
English | 简体中文
Smarter automatic session titles for DeepSeek Harness (DSH).
0.5.0-rc.18 — release candidate, intended for the npm next tag.
This release adds title preview and batch before/after comparison: generate candidates without replacing titles, then apply only those you select. It also fixes exclusion reassembly, final title limits, settings bounds, live locks, fallback route ownership, permanent-error retries, and repeated Goal retitling.
The redesigned interface uses grouped forms, blue action buttons, and Title settings / Batch optimize navigation. Both pages share the same responsive panel width, so switching tabs keeps the border aligned. Common title rules stay visible; advanced parameters and detailed help are collapsed. A footer Save settings button saves all edits and shows the result. Batch processing supports automatic loading, title/ID search and project filters, with side-by-side title comparisons that stack in narrow panels. Batch routing reflects saved settings; fixed-model mode hides redundant automatic fallback. Date format appears only when a date affix is enabled.
Summarizes the first meaningful task into a short session title. By default, the title uses the exact provider and model used by that conversation. No separate model setup is required.
/retitle and a header button for explicit regeneration; an explicit
request also outranks the weak-prompt filter, so a session whose messages are
only terse commands (继续写 / 发布) can still be retitled.DSH retains ownership of fallback titles, persistence, projections, cancellation, and stale-result protection. This plugin replaces only the title provider.
In the tested DSH version, the built-in provider rejects inputs above 4096 bytes
before calling the model. This plugin compresses them first. A 15,536-byte prompt
has been validated with a real model. Neither DSH Core nor app.asar is modified;
all model calls use DSH's existing LLM service.
Package: smart-session-title@next.
The next tag deliberately identifies a release candidate.
Use your DSH profile's package-management workflow to install the package into that profile. For a manually managed profile, run this inside the profile directory:
npm install smart-session-title@next --legacy-peer-deps
DSH supplies the runtime peers; --legacy-peer-deps prevents npm from
installing a separate Core stack. Follow the compatibility requirements below.
For local installation, copying this package into the profile's
node_modules/smart-session-title is also supported and has been verified on Desktop.
Back up the profile's package.json and cordis.patch.yml. Add the bundle after
the base and Web bundles, preserving all other existing bundles:
{
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"smart-session-title"
]
}
}
}
Restart DSH. The bundle disables the built-in session-title-llm provider before
registering this one. The startup log includes
smart-session-title provider registered ... automatic=all-prompts.
To uninstall, remove the bundle entry and restart, then remove the package. This restores the built-in provider. Disabling only this plugin's row while leaving its replacement patch active does not restore the built-in provider.
The last live installation and startup verification used DSH Desktop 2.0.9,
Core 0.1.5-rc.1, Cordis 4.0.2, Schemastery 3.18.2, and Node ≥22.15.0.
The official deepseek-harness v0.2.0-rc.1 release and its matching
registry packages use Core 0.2.0-rc.1. The current local DSH Desktop 2.0.9
app.asar provides Core 0.2.0-rc.2, Cordis 4.0.4, and
Schemastery 3.18.4. The plugin's required contracts were checked against
the official rc.1 documentation and the local rc.2 bundle, but it has not
yet had a live startup verification on Core 0.2. Peer ranges cover both Core
generations: ^0.1.5-rc.1 || ^0.2.0-rc.1 for DSH runtime packages and
~3.18.2 for Schemastery. Other Core versions have not been verified.
Startup checks the title and LLM services, then validates settings before the
provider is registered. Core 0.1 uses settings.register and settingsScope;
Core 0.2 uses volatile plugin Config and configForms. The Web client uses
official slots, locale, and Remote commands. No version-string hard rejection
is used.
Open Settings → Smart Session Title on Core 0.1. Core 0.2 offers the same
settings from both Settings → Smart Session Title and
Plugins → Installed → smart-session-title. Core 0.1 persists the
smart-session-title namespace in $DSH_HOME/settings.yaml. Core 0.2
stores the same fields in this plugin's
volatile Config in the active DSH profile. Both use DSH's own atomic writes,
revisions, and change notifications. Changes affect the next generation; an
in-flight request keeps its initial policy, except that a new title lock aborts it and prevents accepting its result. The plugin creates no sidecar file,
custom watcher, or HTTP server.
The footer of the page shows the loaded plugin version, so a bug report can name
the exact build.
| Field | Default | Purpose |
|---|---|---|
enabled | true | Master AI-title switch |
mode | Follow the session¹ | current-session, configured, or disabled |
provider | Unset | Existing DSH provider ID |
model | Unset | Model ID belonging to that provider |
timeoutMs | 15000 | Per-attempt timeout; UI range 1000–120000 ms |
maxAttempts | 2 | Total attempts; range 1–3 |
maxTitleCharacters | Unset (inherits 80 bytes) | Entire title character cap, including the date (Unicode code points); range 8–120 |
titleDatePosition | Unset (no date) | prefix / suffix: put the session's creation date before or after the title |
titleDateFormat | ymd | ymd (2026-09-13) or md (09-13); unused while no position is chosen |
titleStyle | Unset (plugin default, currently action + object) | action-object or short-name |
titleLanguage | Unset (follows the task's main language) | zh or en, forced |
titleExclusions | Unset (nothing excluded) | String list of words that must not appear in a generated title; at most 50 entries of at most 64 characters |
lockedSessionIds | Unset (nothing locked) | String list of session ids whose title no entry point may rewrite; at most 500 entries |
¹ For older deployments only, an explicit provider/model pin in the bundle row
remains effective until the user chooses a mode. The shipped bundle has no pin.
Explicit current-session always uses the session route.
Edit settings, then click Save settings in the page footer. Changes stay local until saved; model and title rules are written together. Failed saves and page navigation retain your edits. Batch optimization uses the last saved route. Provider and model must both be selected in fixed-model mode.
Advanced exposes timeout and attempts. Empty numeric fields inherit the bundle
configuration; deployment-level compression options are in cordis.patch.yml.
Title shape and content is shown directly, separately from Advanced:
maxTitleBytes: 80 (about 26 CJK characters or 80 Latin characters). A value
between 8 and 120 applies a code-point cap on top of the byte cap, and the
cut prefers a separator so a word is not sliced in half.session.header.createdAt, local time), not the moment of generation —
regenerating a title, or batch-retitling an old session, keeps that session's
own day. Choose a prefix (2026-09-13 Title), a suffix
(Title · 2026-09-13), or none.createdAt, or an
unresolvable time zone) the plugin adds no affix instead of a broken title.| Setting | Title for the same task ("检查登录接口并解决超时问题") |
|---|---|
| Default (action + object) + Auto | 修复登录接口超时 |
| Short task name + Chinese | 登录接口超时 |
| Action + object + English | Fix login API timeout |
Fill one word per line under Title exclusions (customer names, internal project codes), at most 50 entries of at most 64 characters:
Acme Corp
internal-project-x
With the task "修复客户甲的订单导出错误", an accepted result is "修复订单导出错误". Two layers:
If the last attempt still contains the term, the plugin deletes the term from the title rather than giving the title up — because giving it up leaves DSH's fallback title on the sidebar, and that fallback is the opening of the raw first message, i.e. precisely the path that would display the name. If deleting the term leaves nothing that passes validation, the generation fails outright and the sidebar keeps what it had.
Matching is literal: terms containing ASCII letters ignore case (Acme hides
ACME), everything else matches exactly. There is no stemming, alias or
translation — add 客户甲, ClientA and 甲方 separately.
It constrains only titles this plugin generates. That boundary is deliberate:
settings.yaml
on Core 0.1 or the active profile configuration on Core 0.2.So its accurate name is "title exclusions", not a privacy or redaction feature. Its most practical use is alongside Optimize past titles, to strip a name out of a whole batch of historical titles.
The lock button beside a session title (to the right of "Regenerate title") pins that title. The button shows the state itself: a closed padlock means locked, and the hover text and accessible label always name what a click will do ("Lock title" / "Unlock title").
Automatic generation, /retitle, preview, application and batch processing honour it:
| Rule | Actual behaviour |
|---|---|
| Automatic generation skips locked sessions | the provider abstains (locked) without a model call |
| Regeneration says why it will not run | the button is disabled and reads "Title is locked; unlock it first" |
| The batch list excludes locked sessions | they are not listed, and the count is joined by "Locked sessions skipped: N" |
| A batch run cannot reach them | even "Select all" cannot select a locked row |
lockedSessionIds),
not in browser localStorage: it survives a new window, a cleared browser
profile, and a DSH restart.The same page lists your stored sessions with the title each one currently has, so you can batch-regenerate titles written before this plugin was installed. Pick the rows (filter by project, select all within the current filter), then start the run. Up to 300 rows are rendered at once — narrow with the project filter for larger histories.
maxAttempts model calls; an automatic fallback pass can add calls. Preview also calls the model, while applying a candidate does not./retitle path is DSH's documented way to unpin a manual title.commands/execute accepts a trailing AbortSignal, so
the in-flight generation is cancelled rather than waited out, the queue does not
continue, and the interrupted session is counted as neither success nor failure.
Stop is reachable both in the settings page and from a small global progress
pill (shell.overlay), which is what makes a background run stoppable after the
settings page is closed.modelSelection
projection) and flags the ones DSH no longer serves, with a count, before
the run: those sessions cannot succeed while following the session model.Click Preview title beside a conversation title to see its previous title and a candidate. Generating the preview calls the configured title model but does not write a session/title event. Apply this title saves that exact candidate through DSH's official sessionTitle.rename(); application makes no new model call. The accepted title has user ownership and is protected from automatic regeneration.
In Batch optimize, select sessions and click Preview selected. Review the side-by-side previous/candidate pairs, which stack in narrow panels. After preview, the session picker collapses; expand Change session selection to edit it. Search and project filters also apply to candidates. Filtering keeps existing selections, and the footer counts all selected candidates. Uncheck any you do not want, then click Apply selected in the footer. Applied rows are marked; failed applications retain their reason. Optimize directly still regenerates and writes immediately; its fallback option is under Direct optimization and fallback. Both preview and application run serially and support Stop. Closing Settings retains progress and comparisons; reloading the window clears the client queue and comparison view.
Previews use the current saved route without the temporary automatic fallback, which would invalidate their settings revision. Fix a failed route, save it, and preview again. The host keeps at most 500 candidates for one hour. New user input, Goal changes, title changes, or relevant title setting/route changes require a new preview. Locks and the AI switch are checked again at application. A host restart or plugin unload clears the cache.
Command equivalents are /title-preview (returns a JSON candidate with previewId) and /title-apply <previewId>. Tokens belong to one session and can be applied once. DSH records command lifecycle/results as usual; a preview changes no title and adds no synthetic user message.
request.route, never a
substituted global default model.enabled=false: zero title-model calls and zero provider-title
events. Fallback titles, manual renaming, and title projections keep working.Configured mode supports using a different provider and model from the conversation.
Run /retitle or click the regenerate button beside the session title.
Ordinary user-input sessions invoke DSH's official SessionTitleService.refresh(); Goal-only sessions use the guarded recovery described below.
The button shows loading, prevents duplicate requests, and returns to idle afterward.
Explicit regeneration can replace a manual title. Automatic generation cannot.
Failures preserve the previous title; cancellation never retries.
When AI titles are disabled, /retitle returns AI title generation is disabled.
without a model call. A third party calling bare refresh() does not receive the
plugin's explicit permission token for replacing a manual title.
Explicit /retitle outranks the weak-prompt filter. When no message names a
task — typically a writing-mode session whose only human messages are terse
commands such as 继续写 or 发布 — /retitle generates from the newest such
command instead of failing. Automatic scheduling keeps the filter unchanged:
greetings, bare URLs, paths, code-only and punctuation-only prompts still abstain.
A session driven only by DSH /goal commands is also retitleable on explicit
request. Core does not include Goal-source messages in its ordinary title input,
so the plugin reads the newest Goal objective as an explicit-only temporary input;
it does not append a synthetic conversation message or use this path for automatic
title scheduling. Repeated /retitle after /goal edit uses the new objective even when a previous title exists. A newer generation supersedes an older one, and intervening input, route changes or manual renaming prevents stale output from being saved. Accepted Goal titles use the official rename() API and have user ownership.
Permanent adapter failures such as UNKNOWN_MODEL, NO_ADAPTER, AUTH and invalid credentials do not retry. Transient failures use cancellable backoff (250 ms, then 500 ms), respecting providerRetryAfterMs only within a bounded window of at most 5 seconds and no longer than timeoutMs. A longer retry-after is reported as a failure instead of retrying early. Output-quality retries remain bounded by maxAttempts.
Hello → Thanks → Are you there? → Help me audit database performance spends no
title calls on the greetings and generates a title when the task appears.
Accepted provider titles do not drift with later messages. Child sessions do not
automatically receive titles.
The policy reads messages and titles replayed by Core, rather than maintaining its
own history. Reopening a greeting-only session after a real process restart and
sending a meaningful task has been verified through the Web UI.
/retitle is an explicit request and relaxes exactly one weak shape: the newest
short imperative becomes an eligible source. Every other weak shape (greeting,
bare URL/path/code, punctuation-only, demonstrative) still abstains even then.
Title generation is an additional model request, bounded by maxAttempts.
By default it uses the conversation's model. Configured mode sends the compressed
first meaningful task to the explicitly selected provider, which may be different.
Titles never enter model context. The plugin does not append an extra
session/title-llm-request prompt copy to the