deepseek-office
Verifieddeepseek-office Β· v0.7.1 Β· Apache-2.0 Β· Web UI
DeepSeek Office: persistent AI teammates in a detailed, interactive 2.5D office for DeepSeek Harness
Install
dsh plugin add deepseek-office Confirm the layer applied with dsh --profile default --dump-config β see the install guide.
Source
Tags
Creators
Readme
DeepSeek Office
The DeepSeek Office plugin, based on DS Bot, for DeepSeek Harness (dsh). It turns dsh into a team of long-lived Bots that talk to you, to each other and in group chats. See the project page for an overview, install steps and screenshots.
Version 0.7.1 fixes updates on newer DSH profiles, verifies installed versions and attempts to restore the previous release when replacement fails. It retains the existing UI, scene and agent behavior. Version 0.7.0 brings in-scene phone chat and web reading, illustrated face-to-face dialogue, compact navigation and activity controls, an updated character model, and warmer details in work studios, coffee studios and screening rooms. Conversations still use the existing Harness Sessions and native composer. The screening-room TV remains a static display. Features, tools and the saved data format can still change.
The office uses a bundled Three.js orthographic view over the existing Phaser simulation. Camera rotation, zoom, overview, screen-relative movement and the responsive game HUD do not change the Harness Bot or conversation contracts. Architecture is original and procedural; the worker is derived from the owner's supplied generated GLB. All resources are bundled locally. The wardrobe combines skin, hair, shirt, trouser and shoe colors and saves each identity in browser storage. A background AI portrait does not overwrite these choices; an explicit user direction can. Characters share the supplied long-haired model with a jacket, skirt and boots; the existing trouser-color channel colors the skirt. See the character checks and the design and verification.
The owner's elevator GLB supplies a walk-in cabin on the right of every corridor. The map's Lift button inspects it; clicking or walking inside opens the adjacent destination panel. Travel closes doors, fades the old scene, waits for the new renderer, reveals the destination and walks out. IDs identify floors throughout; duplicate trips are locked, unavailable destinations recover safely and closing the office cancels pending work. See elevator checks.
Every group floor reserves a meeting room. Confirm entry to sit at the head of the table; coworkers queue, enter in roster order, then take up to eight seats or orderly perimeter positions. The lower meeting pane and centered wall display borrow the same group Session and native conversation/composer. History, live replies, attachments and full messages stay in the original chat. Recent messages also show truncated overhead captions. Ending a meeting restores daily routines; sofas and workstation chairs support seated breaks. See meeting checks.
The development harness is pinned to dsh 0.2.0-rc.2. Current office browser
checks use an isolated Web profile on Windows; see the linked verification records.
Features
Long-lived Bots: each Bot is a dsh Session in the "DS Bot" workspace, with its own name, role, instructions and model.
Working folders: a Bot can work in a folder you choose instead of the team workspace, and a group chat can set one folder for all its members there. Pick it in the Bot's settings or details panel or in the group's settings, or ask a Bot (
update_bot,update_group). After a change, the chat goes on in a fresh part that starts in the new folder. When a Bot sets a folder outside the team workspace, or adds a Bot to a group that works in one, it asks for your approval if those Bots can only write in their folder. Folders that hold dsh data ($DSH_HOME, the team's data) are refused.Permission presets: each Bot runs with its own dsh permission preset (Read only, Workspace or Full access), set in its details panel. A group chat can run all its members with one preset there, in place of their own: turn on Same for every member under Permissions in the group's settings. Only you set permissions; Bots cannot change them.
Bots work together:
message_botsends a message to another Bot,create_botandupdate_botadd and set up Bots, andask_userasks you a question without blocking the other Bots.Group chats: members speak one at a time, and each one reads the latest messages first. A message can
@Namea member to pass the turn on; type@to pick one from a list. + β Reference a chat adds another Bot's chat to a message as context, and in a group the members who answer get it. A member with nothing new to add stays quiet ([PASS]). Each member has its own hidden Session per group, so a group never reads a Bot's private chat.Roles and permissions:
Who Can do You Everything Main Bot (there can be more than one) Manage every group; change and delete Bots Group admin Manage its own group only (name, notice, members, reply mode) Member Speak in the group and @another memberLong chats stay inside the model's window: dsh's own compaction never runs on a Bot's Session. When a turn ends past the check line (a share of the model's context window), a small separate model call, the context steward, reads the latest messages of the chat and decides once. If the work is still under way, the chat is condensed in place into a checkpoint: a handoff summary plus your recent messages word for word. If the work has reached a stopping point, the Bot writes a handoff note and continues in a new part. Either way you still see one chat, with no marker. Earlier parts and condensed messages stay searchable in a full-text index (
node:sqliteFTS5) throughread_own_chat.Memory: each Bot keeps notes across all its conversations, and the team shares one more. See Memory.
Web search: see Web search.
Bot browser (dsh Desktop only): see Bot browser.
Images: for a model that cannot read images, a vision model first turns the image into text.
Secrets: a Bot asks for an API key or token with a card in its own chat and never sees the value. See Secrets.
Usage: Settings β Usage shows token usage by time (24 hours to 12 months, or days picked on a calendar), by Bot and by model, with a page for each Bot and each model. Calls that a Session logs are read from the logs, so older chats count too. Calls that leave no log (checkpoints, handoff notes, the steward, image readings, dsh titles and compaction) are counted while they stream, from the time the plugin runs. Tokens only, no cost.
Make it yours: name, role, instructions, model and look (20 characters and 12 colors, or your own photo) for each Bot; a theme, an accent color and an avatar animation level (quiet, normal or lively) for the team. A pinned Bot or group chat shows a small pushpin in the sidebar. Settings has these pages: General (look), Bots (Main Bots and each Bot's settings), Group chats (each group's settings), Connectors, Capabilities, Scheduled tasks, Usage, Secrets, Feedback and About DS Bot (versions, updates and links).
Install
Install the local deepseek-office-0.7.1.tgz build using DSH's Plugins page or dsh plugin --profile web add /absolute/path/deepseek-office-0.7.1.tgz. Disable the original ds-bot / legacy dsh-bot plugin in that profile first; both variants share the internal Bot identity. Keep your data. The Update button supports DSH 0.2.0-rc.2 and 0.2.1-rc.2: older profiles require a restart; hot-reload profiles replace the bundle live and attempt to restore the previous version if installation fails. Keep the same profile and DSH_HOME.
When updating from 0.6.1 or 0.7.0, already-installed means the old updater cannot replace an installed package on newer DSH. In DSH Settings > Plugins, uninstall DeepSeek Office and add the new release archive or published deepseek-office package in the same profile. Keep the team data. If installation fails, add the previous version there again. For CLI replacement, stop the profile first, then run dsh plugin --profile web remove deepseek-office and dsh plugin --profile web add deepseek-office; use your actual profile name. See the project install guide. Installing by package name requires that an owner has published that version to the selected npm registry.
2.5D offices
Each group becomes one office floor. The lobby lists the team's offices; members own workstations and show real activity. Use click-to-walk, WASD/arrows and E to interact, or use the accessible member list. Chat uses the same send actions as the original interface. No groups means no office entry, canvas or automatic generation.
Version 0.7.0 uses Three.js 0.186.1 for an orthographic 3D view and Phaser 4.2.1 for movement and simulation. Animated coworkers use the supplied rigged model with independently assigned skin, hair and clothing colors. Every four employees occupy one work room; members five and nine add connected work rooms. Each group floor reserves one meeting room, two seeded leisure facilities and a screening room in the east wing. Reception has its own welcome studio and three leisure facilities, plus a screening room. Unused room slots become gardens. Walls and furniture have physical footprints, automatic doors connect rooms to the corridor, and the map supports room inspection and camera following.
Work studios now include desk pads, stationery, lamps or headphones, cable trays, corkboards and rugs. Coffee studios add cup shelves, bean jars, saucers and botanical prints. Screening rooms add acoustic panels, a wall light, backrest fabric and television cabinet vents. These original procedural details fit existing furniture and wall footprints; they preserve the UI, paths, seats, interaction targets and agent behavior. Other leisure facilities retain their existing furnishings. See the decoration scope.
Facilities support brewing, seated page turns, a scored 30-second arcade round, lunch assembly, timed mocktail mixing and a six-stretch rhythm activity. Nearby prompts and compact activity cards show the available interaction and keyboard controls. Coworkers reserve reachable break spots and use individual sofa seats; real Harness work preempts leisure. Closing a panel cancels its activity. Quiet motion pauses autonomous movement and reduces ambient effects. Sunlight and evening lighting follow local time. The upper-right HUD provides a room map, camera rotation, zoom, overview, follow, Floors and Team; More holds decoration, Quiet motion and help. Face-to-face conversations use illustrated portraits and message-history controls, with private chat or a group mention through the native composer. All game interface text is English.
While exploring, take out the phone with the Phone button below the HUD map or the P key. The character holds it, its screen appears in the bottom-right corner, and Esc puts it away. The chat app lists every group and teammate, with search, unread marks and recent-message previews. Conversations use the same Sessions and native composer as ordinary chat, including attachments, voice, models, queues, questions, mentions and slash commands.
The Browser app has an address bar, back, forward, reload and a menu. The plugin host fetches pages using a phone user agent, the network and system proxy of the computer running DSH, then shows them in a sandboxed mobile layout without access to DSH. Pages requiring sign-in, form submission or complex scripts can be opened in the system browser.
The player pauses while holding the phone; the world, agent turns and scene activity continue. Simple questions can be answered on the spot; an agent that needs a workstation goes there while the player stays put. See the phone design.
Licenses, pinned sources and asset manifests are retained under src/client/assets/. Architecture and furnishings are procedural; characters, the lift and TV use owner-supplied models with source records in office-worker/, elevator/ and cinema/. Momo retains its separately credited CC0 sprite. Older LPC resources keep their existing licenses and credits. The new project logo and its generation prompt are recorded in brand sources.
Portraits and bounded appearance traits can be generated by each Bot's configured text model and saved on bot.officeAvatar. Regenerate with a description from the character card. Invalid output leaves the previous or built-in appearance intact. Background portrait generation preserves the independent 3D wardrobe; explicit user descriptions can influence its colors. AI design consumes tokens; saved appearances are reused. Per-room office.theme stores validated wall/floor/accent colors and day/night state. Geometry uses stable seeded templates; free-form layout editing and cross-device multiplayer remain planned work. The screening-room TV currently shows a static illustration.
Office development
Build with npm ci && npm run build. Install test dependencies with npm run harness. For a mock preview, run node dev/office-bench.mjs from this directory. It prints the local address and writes a login URL to the private .dsh-test-office/web.log file. Do not share that URL.
The first run creates an isolated profile. Stop it, then install this source directory into that profile with the public DSH CLI. In PowerShell, from ds-bot/:
$env:DSH_HOME = [IO.Path]::GetFullPath('../.dsh-test-office')
node dev/harness/node_modules/@deepseek-ai/dsh/lib/bin.js plugin --profile web add (Get-Location).Path
Remove-Item Env:DSH_HOME
node dev/office-bench.mjs
This bench uses ports 3106/8806 and mock models, never your normal DSH home. During browser acceptance, pause all repository writes, including temporary reports and audit copies: development hot reload may otherwise restart the active scene. Stop with Ctrl+C. The original API smoke test can use it with node dev/smoke.mjs office 3106 on fresh test data.
Configuration
Options go in the profile's cordis.patch.yml, under the bot entry. All of them are optional.
- id: bot
name: deepseek-office
config:
workspace: /path/to/workspace # where the Bots work; default <home>/workspace
home: /path/to/bot-data # where the team is saved; default $DSH_HOME/bot
checkRatio: 0.8 # share of the model's usable window where the steward decides
browser: true # force the Bot browser on or off; default on in Desktop only
memory: true # false turns memory off: no memory tools, section or panel
memoryReview: true # false leaves memory to the Bots' own remember calls
diagnosticsFile: false # keep the error log in memory only; default <home>/logs/diagnostics.jsonl
updateCheck: true # look for a newer DS Bot when a window opens; default true
updateRegistry: https://registry.example/ # ask only this npm registry for updates
github: false # hide the GitHub connector; default shown in Connectors
Updates: when a window opens, DS Bot asks where it was installed from for a newer release: the npm registry (the one the DSH plugin manager installs from, then its fallbacks), or the latest GitHub release for a github:β¦#vX.Y.Z install. A newer version shows a cloud button at the top right of the sidebar; Update reinstalls DS Bot through the DSH plugin manager, and the new version runs from the next DSH start. A linked or local checkout is never offered an update. Settings β About DS Bot shows the same state, with Check for updates to ask again at once.
The same card can carry DSH itself: a DS Bot release may name the DSH release it was verified against (dsBot.verifiedDsh in its package.json), and only that version is offered β running something newer is a downgrade offer too. A release that names no version offers no DSH update. A DSH installed from npm is swapped by npm install -g @deepseek-ai/dsh@<version>. DSH Desktop installs the newest release its own updater finds, so the card shows DSH there only when that release is the verified one, and Open updates opens the app's update panel. A release may raise the floor with dsBot.minBot: until the bot itself is that new, the DSH row waits.
Models
Model providers are set up with dsh's llm-pi-ai plugin in cordis.patch.yml. Every Bot runs on one model of its own, from the models DSH serves. A new team's first Main Bot has none: its chat opens on a model card and it greets the user only after a pick. The Create Bot form starts on the DSH default model. The Bot's details panel and settings (or a Main Bot's update_bot) change it; a Bot whose model is no longer served shows the card again. A team saved by an older version keeps the model each Bot last ran on.
- Give every model a
contextWindow. DS Bot takes its lines from it: the usable window is the window minus the reply reserve (maxTokens), the hard line is 95% of that, and the check line ischeckRatioof it. A model withoutcontextWindowgets the adapter's default (262,144 tokens forllm-pi-ai), which may be wrong for that model; a model that reports no window at all counts as 500,000. - To send images, the provider needs
defaultInput: [ text, image ]. - Keep API keys out of the repository. Use dsh's own key storage or environment variables.
Memory
A Bot remembers what should last beyond one conversation: your preferences, decisions, corrections and facts it should not ask again. Memory is plain Markdown in the Agent Memory Repo format: one entry per line, ending in [source: β¦; added: β¦].
After each turn, a memory review reads what is new in the Bot's chat (and in each group, per member) and keeps, updates or removes entries itself, so memory does not depend on the Bot deciding to call remember. It keeps only what you say, writes entries in your language, and refuses keys, passwords and ID numbers.
- Two scopes: each Bot has its own memory, and the team memory is read by every Bot. A Bot writes its own. Main Bots and group admins (of any group) also write the team memory; a Main Bot can read and change another Bot's memory when you ask.
- Tools:
remembersaves an entry or replaces one (replace),forgetremoves one, andrecallsearches every entry, reads a topic whole, or lists what is saved. The Bot adds the source (a part anchor such aspart 2 #1234, whichread_own_chatopens) and the date; a Bot that writes for others is named withby:. - Files:
MEMORY.mdholds what every conversation needs, and details go in topic files linked from its## Indexas[[topic]]. - In the prompt: both
MEMORY.mdfiles go into the Bot's system prompt. The section is frozen when a Session starts, so the provider's prompt cache holds; a change shows from the next part or checkpoint, andrecallfinds it at once. - Fixed sizes: an entry has at most 300 characters, a
MEMORY.md4,000, a topic 16,000, and a scope 40 topics. A save past a limit fails and says how to make room. - Safety: memory is data, not instructions. An entry that looks like a key or token is refused, and a Bot is told not to save what a web page, file or tool result asks it to remember.
- History: files change in place, and
journal.jsonlkeeps every change with the line before and after. When a Bot is deleted, its memory moves toarchive/.
The memory panel: the Bot's details panel has a Memory row with the entry count; Manage opens the memory panel.
- Memory summary: the Bot's model writes a short summary in prose from every entry, in the interface language. It is written again when the entries change, and the β― menu can regenerate it.
- All entries: the β― menu lists every entry by scope and topic, with its date and author, and the size of each
MEMORY.md. Remove takes two clicks. - Ask or update: ask what the Bot remembers, or tell it what to add, correct or remove. One model call answers from the entries only, and its changes go through the same checks as the tools.
- A line in the chat ("Memory updated") shows when a Bot changes memory and opens the panel. When memory changes in the background, the Bot's capsule at the top of its chat stretches to say "Memory updated" for a moment; clicking it opens the memory panel.
A read-only dsh (see Data and backups) shows memory but cannot change it.
Web search
The package includes a second plugin, ds-bot/web-search. It registers the search provider auto, and cordis.patch.yml makes it the default. Each search goes in this order:
- If the profile names another
searchProvider, that one is used. - The current model route's own search, with that route's key and host. The plugin knows the Anthropic Messages, OpenAI Responses and Gemini protocols, and a few search APIs (Ollama, Kimi, Zhipu, MiMo). Add more with
searchApis. - A fallback without a key: the public result pages of Bing and DuckDuckGo.
- If nothing works, the search fails and tells the model not to guess addresses.
Each result starts with a Search backend: β¦ line that names the path it took.
Turning auto off: the web row still names auto when you turn off only the web-search-auto row (in the sidebar's Plugins page or with disabled: true in a profile patch). Then web_search fails in every session, Bot or not, with WEB_PROVIDER_CONFIGURED_MISSING (configured web provider "auto" is not registered). When you turn that row off, also name another searchProvider for the web row in the profile's cordis.patch.yml. The override replaces the row's whole config, so restate fetchProvider:
- id: web-search-auto
name: deepseek-office/web-search
disabled: true
- id: web
name: '@deepseek-ai/dsh-web'
config:
searchProvider: deepseek-official
fetchProvider: http
Another plugin can also set the search provider while dsh runs, after the profile patch. When you turn such a plugin off, check this setting again.
Bot browser
In dsh Desktop, a Bot's chat header has a globe button. It opens that Bot's own browser panel.
- One partition per Bot (
bot:<id>): logins and cookies belong to that Bot only. - The Bot can read the page: the
read_browsertool reads the page's DOM, not a screenshot. The text becomes Markdown with headings, nested lists, tables, code blocks and quotes. Links and form controls are marked[#n]in place and listed below with their targets and values. The tool also reads the text you selected. Long pages are read in parts (from). Page content is treated as data, never as instructions.- It reads open Shadow DOM (with
<slot>) and same-origin iframes up to 3 levels deep. - It reads only what is visible:
display:none,visibility:hidden, zero-height and closed<details>content is skipped. - It never reads the values of password, credit card (
autocomplete="cc-*") or one-time code fields. - Limits: 400,000 characters, 150,000 nodes, 5,000 rows per table, 3,000 links and controls, 1.5 seconds. A cut result says so.
- It cannot read cross-origin iframes (one line with the address), closed shadow roots, canvas content (online editors, maps), or text in CSS
::before/::after. On pages that render on demand, only the rendered part is read. - Read only: the Bot cannot click, type, scroll or open addresses yet.
- It reads open Shadow DOM (with
- Addresses: http and https only. localhost and LAN addresses are allowed; cloud metadata addresses (such as
169.254.x.x) and dsh's own ports are not. - The browser panel and the details drawer share the right column; opening one closes the other. Switching chats switches the panel to that Bot. Deleting a Bot clears its browser and saved address.
dsh Web has no browser panel and no read_browser tool.
Secrets
When a Bot needs an API key, token or password, it calls request_secret, and a secret card shows in its own chat. The Bot never sees the value.
- Fill in: the field hides what you type, is not part of a form and is not autofilled. Choose "All Bots" or "Only this Bot" and select Save. A value must have at least 4 characters (a 4-digit PIN works). A value of 8 characters or more is hidden wherever it appears; a shorter one only where no letter or digit touches it, so ordinary words stay intact.
- Allow: if the secret is already saved but this Bot is not allowed to use it, the card only asks whether to allow it. You can also replace the value there.
- Use: the value goes into the Bot's shell environment as
DSH_SECRET_<NAME>($DSH_SECRET_NAMEin bash,$env:DSH_SECRET_NAMEin PowerShell).list_secretslists the names a Bot can use. An MCP capability can also take$DSH_SECRET_<NAME>in its env, its headers and its URL (path or query); in the URL the value is URL-encoded. Use headers when the server accepts them. - Masking: before a tool result is saved and before each request goes to the model, every copy of a secret value is replaced with
[secret:<NAME>]. - Manage: Settings β Secrets lists every secret by name, purpose, the Bot that asked and the last use. You can change who may use it, replace the value, delete it or add one. Deleting a Bot removes it from every secret.
- Storage:
<DSH_HOME>/bot/secrets.json, file mode 600, written atomically. Values are never instate.jsonor logs.
Limits:
- On Windows, the file mode has no effect; the file is protected by your user folder only.
- Only exact copies of a value are masked. A Bot that encodes, splits or reverses a value can still print it. Do not give important secrets to a Bot you do not trust.
- On a page that is not HTTPS (for example dsh Web opened over http on a LAN), the value crosses the network in clear text. The card warns you.
- Group chats show no cards; a Bot asks in its own chat.
Data and backups
The plugin saves its data in config.home. Without it, the folder is $DSH_HOME/bot, or ~/.dsh/bot when DSH_HOME is not set.
| System | Default folder |
|---|---|
| Linux, macOS | ~/.dsh/bot/ |
| Windows | C:\Users\<user>\.dsh\bot\ |
- To move all dsh data (Sessions, profiles and plugin data), set
DSH_HOME. - To move only the plugin data, set
homein the configuration (see Configuration).
Files in bot/:
| File | Content |
|---|---|
state.json |
The team: Bots, groups, Bot-to-Bot messages, preferences and open questions. A long message keeps only its first 2,000 characters here; all of it is in the Session it went to. |
group-lines/ |
Long group lines, up to the 20,000 characters a member reads, one file per line; each is removed when its line leaves the group's latest 60 lines or the group is deleted |
state.lock |
The dsh that is using this data (pid and host). It is removed when that dsh exits. |
chat-index.sqlite |
Full-text index of older chat parts (read_own_chat); rebuilt if deleted |
usage.sqlite |
Token counts for the Usage page; rebuilt from the Session logs if deleted, losing only the calls outside the logs and the names of deleted Bots |
memory/ |
Memory (see Memory): bots/<id>/ and team/ (MEMORY.md and topics), journal.jsonl (every change), snapshots/ (the section each Session froze), summaries/ (the panel's summary; safe to delete), reviewed.json (how far the memory review has read) and archive/ (deleted Bots) |
ocr.json |
Cache of image text; safe to delete |
workspace |
The team workspace: the working folder of every Bot without one of its own (config.workspace changes it) |
secrets.json |
Saved secrets. Treat backups of it like passwords. |
logs/diagnostics.jsonl |
Recent errors and warnings, with keys, tokens, saved secrets and the home folder removed. It moves to diagnostics.jsonl.1 past 1 MB. Safe to delete. |
The chats themselves are dsh Sessions and are not in bot/: they are in ~/.dsh/sessions/. dsh keeps its workspace list in ~/.dsh/storages/workspace.json and profiles (with model settings) in ~/.dsh/profiles/. Bot browser logins are not saved: Desktop keeps each Bot's partition in memory only.
Back up and restore
- Quit dsh completely (both the Web server and Desktop), so
state.jsonis current. - Copy all of
~/.dsh/(at leastbot/,sessions/andstorages/). A copy ofbot/alone loses the chats. - To restore, quit dsh, put the folder back in the same place, then start dsh.
Move to another computer: state.json has no absolute paths except the working folders you set for Bots and groups, but dsh's storages/workspace.json and the Session folder names contain the workspace's absolute path. If the path is the same on the new computer, copy the folder. If it is different (another user name or system), it is not yet tested whether dsh finds the old Sessions.
dsh Web and Desktop at the same time: by default both use the same ~/.dsh. The dsh that loads the team first takes bot/state.lock and can change the team. The other one is read-only: it shows the team and follows changes to the file, but refuses changes (bot/read-only, "open in another dsh"), and its Bots cannot start new Sessions. When the first one exits, the other one takes over on its next request. To change the team from both at once, give one of them a different DSH_HOME (two separate teams).
Development
Work from ds-bot/ with Node.js 22.19 or later and npm. The default setup uses npm run harness to install the pinned test and lint packages into dev/harness/; a separate Harness checkout is optional for those checks. For a cross-platform office preview, follow Office development.
The optional shell benches below require pnpm, a Unix-like environment and a deepseek-harness checkout with its dependencies installed, next to this repository (../deepseek-harness, or set DSH_HARNESS). The Linux Desktop bench also needs xvfb-run and ffmpeg. Scripted Web screenshots need Chrome or Chromium (CHROME_BIN; by default google-chrome or chromium).
npm ci # build and runtime dependencies
npm run harness # pinned test dependencies and oxlint
npm run build # src/client β client.js
npm test # unit tests
node scripts/build-client.mjs --check # verify the generated client
npm run lint # oxlint using .oxlintrc.json
# Optional checkout-based shell benches:
dev/bench.sh dev 3100 8800 start # Web test bench: mock model + dsh Web, data in ../.dsh-test-dev
dev/desktop-linux/desktop.sh dev start # Desktop test bench: mock model + dsh Desktop in Xvfb
CONTEXT_WINDOW=100000 CHECK_RATIO=0.45 dev/bench.sh smoke 3101 8801 reset && node dev/smoke.mjs smoke 3101
dev/check.sh # all checks (see below)
client.jsis built fromsrc/client/and committed, solink:and Git installs need no build. Do not editclient.jsby hand;npm testchecks that it matches the source. After a change insrc/client/, runnpm run buildand reload the page. After a change inindex.jsorsrc/host/, restart dsh.- Web test bench
dev/bench.sh <name> <web port> <mock port> [start|stop|reset|status]: a scripted mock model (dev/mock-llm.mjs, no real tokens; its commands are listed at the top of the file) and a dsh Web server. Data goes in../.dsh-test-<name>/;resetclears the team and Sessions first. The login address with its token is in../.dsh-test-<name>/web.log. - Desktop test bench
dev/desktop-linux/desktop.sh <name> [start|stop|reset|status]: dsh does not run Desktop on Linux;launch.mtsruns the unpackaged Desktop in Xvfb. The first start downloads Electron and a Linux runtime (a few minutes).startreturns when the team shows in a 1400Γ860 window. - All checks
dev/check.sh [--skip steps] [--only steps] [--out dir]:unit,build,lint,smoke,web(screenshots of the sidebar, a chat, a group, Bot settings, the Bots page and group settings) anddesktop(the same screenshots, then the Bot browser checks). It stops everything it started. On failure it names the step and its log and exits non-zero. A full run takes about 3 minutes after the first download. - Ports: every script takes
SLOT=n(0-9, default 0) so that several people or sessions on one machine do not collide: Web bench31n0and mock88n0, smoke31n1and88n1, Desktop mock88n2, and so on. A Desktop uses about 1 GB of memory; stop it when you are done. - Real models (these cost tokens):
dev/steward-eval.mjssends hand-written conversation endings through the context steward's own prompt to an OpenAI-compatible route (or, with--api messages, an Anthropic Messages route such as DeepSeek's official one) and checks each decision.dev/llm-tap.mjs <port> <upstream base URL> <log.jsonl> [body dir]is a logging pass-through for either format: point a provider'sbaseURLat it, and it writes one JSON line per call (steward, checkpoint, handoff note or main turn, the Bot's name, token usage, the answer, and where the request first differs from the same Bot's previous one, which is what a provider's cache can reuse; never headers). With a body dir it also saves every request body. Each file explains its use at the top. - Screenshots:
dev/ui-shots.mjsworks for both apps (desktop <dsh repo> <dir> <renderer port>orweb <dsh repo> <dir> <bench name> <web port>). npm testloads the@deepseek-ai/*packages fromdev/harness/by default;DSH_HARNESScan select an external Harness installation or checkout instead.
Layout
| Path | Purpose |
|---|---|
index.js |
Host entry: installs the src/host/ modules in order |
src/host/ |
Host: team and storage (roster, store), tools (tools), turns and delivery (turns, delivery), group chats (groups), chat parts, the context steward and the index (parts, steward, chat-index), image text (images), secrets (secrets), Bot browser (browser), the POST api/bot route (channel) |
src/client/ |
Browser source: sidebar, chat header, transcript cells, panels and dialogs, themes, Bot browser panel |
client.js |
Built from src/client/ by scripts/build-client.mjs (esbuild); committed |
web-search.js |
The auto search provider; independent of the team code |
test/ |
Unit tests and fixtures |
dev/characters.mjs |
Builds the characters (small 3D models traced to outlines) into the CHARACTERS table in src/client/characters.js |
dev/ |
Mock model, test benches, smoke test, Desktop scripts, real-model tools (steward evaluation, logging pass-through) |