Skip to main content

DSH contracts

The core package supports DSH >=0.2.1-rc.2 <0.2.2; 0.2.0 is no longer supported, because 0.2.1 removed the sub-agent start options and the invariant packages this code used and changed how a stored chat is adopted. Most integration uses public Cordis services and slots. Helper agents with tools of their own also use only public API: DSH's sub-agent activation under a bundle-provided preset. Development dependencies and contract tests stay pinned to one exact tested DSH release; every DSH upgrade requires a fresh review before the supported range is widened.

Chat and workspace lifecycle​

All roleplay chats share one DSH workspace rooted at the roleplay data directory. A chat id is derived as session-<roleplay-session-uuid>; the roleplay database remains the source of truth. Opening a missing chat recreates it. DSH reuses a stored chat in create only while it has no turn and otherwise makes a chat under another id, so a chat that already exists is never created again: a stored chat (it holds an opening) is attached to the project and only a chat that does not exist is created, and a chat made under another id than the one asked for is refused. Archiving or deleting a roleplay session stops and hides its DSH chat before touching the session directory.

The opening message is persisted as a complete first turn before the live agent is created. Its stored header must contain the workspace's canonical path and the roleplay preset. Appending an opening to an already constructed live loop causes turn-number conflicts and is not supported.

The browser resolves uiWorkspace when an action is used. Do not add it to the client injection list merely to open a chat; doing so prevents the roleplay panel from rendering in profiles where that service is not present at initial composition.

Services and ownership​

Use sessionController for create/adopt/rename, workspaceRegistry for the roleplay workspace and archive operations, sessionPersistence for stored opening events, agent/subagent services for model execution, tool registries for validated calls, and the user-approval service for authoring mutations in the default approval mode. Resolve optional services lazily through the context. Secrets follow DSH's credential seam: configuration holds a reference (apiKeyRef, a POSIX-style name), ctx.credentials holds the value and is resolved for each request, and the host writes through set/unset because ctx.remote.credentials is not available to out-of-tree plugins. The seam is typed locally and the service is looked up on use, so a profile without it still loads.

Every listener, HTTP route, timer, client slot, and service must be registered on ctx; use ctx.effect when an API returns a manual disposer. A reload must leave no duplicate route, tool, timer, or listener.

runChild starts a child through startActivation under the roleplay-helper preset and, when the child is created, restricts its global tools and registers its own on its scope. If DSH changes this, port this layer rather than weakening character isolation or exposing tools globally.

Rendering and approval​

The roleplay renderer recognises the <roleplay-output> protocol emitted through the narrate tool result. Protocol markers, JSON fields, and stored event ordering are compatibility surfaces. User-facing prose may be localised; protocol vocabulary may not.

World-authoring edits use DSH approval by default. Approval applies to the proposed mutation, not to a broad session capability. A rejected call must leave files unchanged and the conversation able to continue with a revised proposal. Explicit automatic mode bypasses the approval request, not validation, atomic replacement, or recoverable deletion.

Upgrade audit​

Before widening the DSH version range, verify package exports and composition helpers, opening-message adoption, session naming, workspace association, archive/stop behaviour, user approval and follow-up, client slots, rendering, compaction, cancellation, and hot reload. Run the DSH contract test against the installed target version and perform a live start → play → rewind → branch → reopen cycle.

The DSH API contract lists each concrete host and browser API, its owner in this repository, and the version-sensitive composition boundary.