6.2 KiB
DS4Server implementation plan
Bundle/application identifier: DS4Server.rfc1437.de
The GUI is a Rust/Iced reimplementation of the user-facing model server and
coding-agent workflows in ../ds4. The existing engine remains the behavioral
reference: ds4.c/ds4.h define model and session behavior,
ds4_server.c defines the compatible API, and ds4_agent.c defines agent
sessions, tools, and turn orchestration.
Phase 0 — project and session shell (implemented)
- Show projects in a sidebar with their sessions nested underneath.
- Create projects with a native macOS folder picker and a project-name dialog.
- Create, select, and delete projects and sessions.
- Persist projects and sessions in SQLite under
~/Library/Application Support/DS4Server.rfc1437.de/, using Diesel ORM queries and embedded Diesel migrations. - Never delete workspace contents when removing app metadata.
Exit criterion: restart the app and see the same project/session tree.
Phase 1 — model library and on-demand loading
- Port the narrow GGUF loader, tokenizer, prompt renderer, and Metal session
API behind a small Rust
Enginesurface modeled onds4.h:open,close,create_session,sync,sample, and KV save/load. - Retain the tested model restrictions from DwarfStar; reject unsupported shapes and quantizations before allocating model state.
- Reuse the existing
.metalkernels and preserve mmap-backed resident loading plus the explicit SSD-streaming path. Keep Objective-C only at the Metal interop boundary. - Add a model library screen that records GGUF paths and loading options.
Load only after the user chooses a model. Expose
Unloaded → Loading → Ready/Failed → Unloadingstate and progress in Iced. - Keep one engine resident initially, matching DwarfStar's instance-lock and memory assumptions. Switching models unloads the current engine first.
- Move engine work off the UI thread and support cooperative cancellation at
the safe session boundaries already defined by
ds4_session_sync.
Persist model references and tuning options in Application Support. For a sandboxed distribution, store security-scoped bookmarks rather than assuming raw paths remain accessible.
Exit criterion: select a supported DeepSeek V4 or GLM 5.2 GGUF, load it without
blocking the UI, run a deterministic prompt, unload it, and pass the matching
../ds4 token-output fixture.
Phase 2 — OpenAI-compatible local endpoint
- Add a localhost-only HTTP service owned by the loaded engine. Start and stop it from the GUI; never expose a LAN listener without an explicit setting.
- Implement the DwarfStar compatibility surface in this order:
GET /v1/modelsPOST /v1/chat/completionsPOST /v1/responsesPOST /v1/completions
- Support streaming SSE, reasoning output, usage accounting, cancellation, sampling parameters, tool schemas, and tool choice.
- Port exact sampled tool-call replay and deterministic canonicalization from
ds4_server.cso a client's normalized JSON does not destroy KV-prefix reuse. - Bind API conversations to engine sessions and persist/restore KV payloads using the engine-owned serialization format. Add resident batching only after single-session correctness is established.
- Display endpoint address, model, active requests, token rates, and errors in the GUI.
Exit criterion: the upstream DwarfStar server tests pass against the app for non-streaming and streaming Chat Completions and Responses calls, including a multi-turn tool call.
Phase 3 — durable agent sessions
Replace each metadata-only session with a directory:
Application Support/DS4Server.rfc1437.de/
data.sqlite3
sessions/<session-id>/
kv.bin
- Add migrated message/transcript tables to SQLite. Keep only the engine-owned large KV payload in per-session files, written with atomic replacement.
- Record model identity, context size, rendered token history, title, timestamps, and working directory.
- Restore compatible KV immediately. If KV is absent or incompatible, rebuild from the transcript and show prefill progress.
- Add strip/archive behavior equivalent to the native agent: retain transcript while removing the large KV payload.
- Version formats before the first release and add migrations only when a real format change exists.
Exit criterion: quit during normal use, relaunch, select a session, and resume the same conversation without prefill when its KV payload is compatible.
Phase 4 — agent chat and tools
- Build the classic chat surface: transcript, reasoning disclosure, tool-call cards, composer, queued input, stop button, prefill progress, and generation statistics.
- Port the native agent turn loop from
ds4_agent.c, including model-specific system prompts and DeepSeek DSML/GLM tool-call parsing. - Implement the local tool set with the project directory as its boundary:
- shell command execution
- file read and continuation
- file write
- anchored edit
- text/file search
- Stream assistant tokens and partial tool calls into Iced while inference and tools run on workers. Preserve cooperative interruption and a valid KV prefix at every stop point.
- Require confirmation for commands or writes outside the project boundary, destructive actions, and network tools. Add web search/page visiting only after the local tool loop is stable.
- Port context compaction and system-prompt reinjection after ordinary multi-turn operation is correct.
Exit criterion: create a project session, ask the model to inspect and edit a small fixture repository, review each tool result in the GUI, restart, and continue from the persisted session.
Verification and packaging
- Keep unit coverage narrow: persistence round trips, format compatibility, request parsing, and tool-boundary checks.
- Reuse
../ds4fixtures for prompt rendering, sampling, server streaming, and KV correctness; run live Metal tests only when a supported GGUF is available. - Preserve the DwarfStar/llama.cpp notices required by
../ds4/LICENSEfor reused or adapted source and kernels. - Produce a signed
.appwith the exact identifier above, then add hardened runtime, entitlements, notarization, and update delivery as release work.