Files
deepseek-harness/packages/host/runtime
Turtle f0410d592d feat(web): permission presets and approval answering for the web UI
The web host now composes the sandboxed product path (sandbox-local +
sandbox-policy behind bash-sandbox/fs-sandbox, with user-approval and
permission on top); BootHostOptions.sandbox carries the deployment
defaults (workspace-write + ask).

createApiProxy owns the approval pending registry: a ctx.approval ask
becomes an answerable approval/requested mux frame with a stable rpcId,
replayed verbatim on every mux open until settled; respond routes by the
echoed rpcId, validates the ApprovalResponsePayload audit correlation,
and broadcasts approval/resolved; the ask's abort signal withdraws the
question as cancelled.

session.permissions / session.setPermission project ctx.permission into
a protocol-owned PermissionOption select; idle switches are held
last-write-wins and
flushed into the next prompted turn (the ACP bridge's anchoring
pattern). The shared hasOpenTurn fold moved to dsh-session,
deduplicating the private copies in user-approval, the ACP bridge, and
the proxy.

Client, per the designer draft: a pending approval takes over the
composer (ApprovalPanel replaces the InputBar — amber strip,
justification headline, paired command, one-shot refuse/allow, keyed by
rpcId so a queued second approval remounts live; the resolved frame
restores the composer); the sidebar session row shows an amber
waiting-approval dot that outranks the running ring (manager-tracked
approvalId set, idempotent under mux-open replays, cleared per
connection generation, lit for uninstantiated sessions too); the
permission selector is a composer bottom-row chip over an invisible
native select, with a presentation-only title-case transform
(workspace-write renders as Workspace Write; wire names untouched). Question placeholders stay in the message flow. The
connection fixture mirrors the host behavior for keyless browser
acceptance.
2026-07-24 19:15:04 +08:00
..

@deepseek-ai/dsh-host-runtime

Host runtime assembly for dsh: bootHost composes the core plugin spine (LLM service + DeepSeek adapter, sessions with JSONL persistence and immediate fallback titles, optional first-message model summaries, system prompt, tools, agents, agent loop, workspace instructions, the provider-neutral user-interaction service, and the sandboxed product path — dsh-sandbox-local + dsh-sandbox-policy behind the confined dsh-bash-sandbox/dsh-fs-sandbox families, with dsh-user-approval and dsh-permission on top), createApiProxy implements the dsh-host-apiproxy contract over that composition, and startHost is the one-step shell seam returning { api, handler, defaults, ctx, dispose }.

Which plugins mount and with what defaults is decided only here — shells must not ctx.plugin to alter the assembly. RunningHost.ctx is a formal seam with exactly two sanctioned uses: mounting protocol front-door plugins (e.g. a future dsh acp) and headless session-event subscription; consuming clients must not bypass api through it.

Configuration

Key Default Contract
persistenceRoot (required) Root directory for JSONL session persistence.
workspaceContext (required) AGENTS.md/CLAUDE.md loader config with an explicit maxBytes, or false to disable it.
provider 'deepseek' Default provider route injected as agentOptions on create/resume and reported by host.describe.
model 'deepseek-v4-flash' Default model id, same single source as provider.
cwd process.cwd() Default project directory for a session whose create request omits cwd.
sessionTitle 5 words / 40 fallback bytes / 80 accepted bytes Deterministic fallback and accepted-title limits.
sessionTitleLlm disabled true enables the 5-word / 10-CJK-character, 4,096-input-byte, 64-output-token, 60-second first-message policy; an explicit config overrides it. An omitted route inherits the logged main-request provider and model.
sandbox.mode 'workspace-write' File-sandbox mode sessions start from (ctx.sandboxPolicy default; per-session switches ride sandbox/mode events).
sandbox.approvalPolicy 'ask' Approval policy for sessions without an approval/policy override.

ApiProxy implementation notes

Unary methods take the narrow RpcRequest<P> and echo request.rpcId; a prompt's rpcId rides MessageSource into the user/message event so clients can promote optimistic echoes. history/prompt on a cold session implicitly resume it, deduplicating concurrent calls through an in-flight table; history paginates backwards on message boundaries (never mid-message). The mux stream replays a session/subscribed baseline per attached session and every still-pending question with its original rpcId. Question responses, including blank per-item answers, are validated against the owning session and exact request before an atomic first-wins claim; answer, whole-request cancellation, owner abort, and provider disposal broadcast question/resolved. The host stream carries session lifecycle, running flips, and agent/error as the only outlet for live failures with no turn position.

The proxy is also the approval channel for the agents this host owns: an ask through ctx.approval becomes an answerable approval/requested mux frame with a stable rpcId held in a pending table, replayed verbatim on every mux open until settled. respond routes by the echoed rpcId (approvals first, then questions), validates the ApprovalResponsePayload audit correlation at the wire boundary, resolves the answerer, and broadcasts approval/resolved; the ask's own abort signal withdraws the question as cancelled. session.permissions/session.setPermission project ctx.permission (empty select when not composed); idle switches are held last-write-wins and flushed into the next prompted turn on agent/prompt-submit, because knob events must stay turn-enclosed for durable replay (the ACP bridge's anchoring pattern).

Model Experience

Indirectly, through the non-blocking first-message title request owned by dsh-session-title-llm when sessionTitleLlm is enabled, the provider/model defaults injected into created and resumed agents, the other model-facing plugins bootHost mounts, and the logged workspace-instruction prefix when workspaceContext is enabled.

KV Cache effect

No main-request invalidation; when enabled, the auxiliary title request has its own cache behavior and leaves the conversation prefix unchanged.

Known Limitations and Deferred Work

  • Question and approval waits are process-memory state — browser reconnects recover them, but a host process restart aborts the owning tool call instead of restoring the wait from persistence.
  • host.describe.version is a placeholder — it does not yet report the apps/cli package version.
  • The assembly is fixed — per-deployment plugin selection (user profile, log sinks, alternative persistence) has a documented home here but no configuration surface yet.