Files
deepseek-harness/packages/workspace/workspace
imccyu 013e6f8769 feat(workspace): persistent workspace entity over the domain form
ctx.workspace registry owns WorkspaceId-branded records: realpath-
normalized unique paths (create rejects collisions; resolveByPath shares
the normalization), ordered sessionIds as the single source of ownership
truth, attachSession gated on the session header cwd matching the
workspace path (double-booking structurally impossible), dead session
ids filtered on projection and pruned on the next mutate, status()
reporting missing directories. No delete surface this phase — deletion
ships together with the session-side primitives as future work.
2026-07-25 11:08:04 +08:00
..

@deepseek-ai/dsh-workspace

Workspace entity registry (ctx.workspace) for the DeepSeek Harness: durable workspace records — a stable WorkspaceId, a canonical directory path, a display title, and the ordered account of owned sessions — stored through the domain data form (workspaceDomainSpec, table workspaces). Consumers see the Workspace interface only; the entity implementation stays package-private.

Design rationale, the path/uniqueness canon, and the consistency rules live in the Agent Note.

Shape

  • ctx.workspace.create(path, title?) — canonicalizes path via fs.realpath (trailing slashes, .., symlinks), rejects a nonexistent directory (the original ENOENT) and a canonical path another workspace already owns. Title defaults to basename(path).
  • ctx.workspace.get(id) / list() / resolveByPath(path) — cache-served lookups; resolveByPath is async because it runs the same realpath canon first.
  • Workspace.attachSession(id) — idempotent; validates that the session's stored header cwd, canonicalized the same way, equals the workspace path. A missing persistence service, unknown session, absent or unresolvable cwd, or mismatch rejects without writing (what cannot be validated is not recorded). detachSession removes from the account only, never touching the session's own log.
  • Workspace.sessionIds — the ordered ownership account (array order is display order). Accounted ids whose session no longer exists are filtered from the projection and pruned durably on the next mutation; a medium accounting one session under two workspaces rejects at startup (external edit — the attach check makes it unwritable).
  • Workspace.status() — uncached directory check, 'ok' | 'missing-dir'; a missing directory never mutates the record.

Session persistence is an optional peer resolved with ctx.get: absent, attach rejects and projections serve the account unfiltered.

Model Experience

No model-visible surface: the package registers no tools, injects no prompts, and emits no context. Token and KV-cache cost are zero.

Known Limitations and Deferred Work

  • No delete entry point in this phase — workspace deletion ships as one complete semantic together with the session-delete primitive and cascade orchestration (future-work section of the Agent Note); a half "drop the record, keep the sessions" operation is deliberately not exposed.
  • No RPC surface or GUI wiring yet; the record schema is the direct source of the next phase's wire projection.
  • The known-session view refreshes at startup and on attach validation; a session deleted by an external process during this one is filtered only after the next refresh.