Record the setups model, and put the transport above the drivers
Two decisions from Bryan today, written down before they are built, since this file is where the reasoning is supposed to live rather than in a conversation. A setup is a machine carrying the providers that machine has, and spawning picks a setup then one of its providers. The independent providers × hosts model it replaces is left in place below it, because its reasoning is worth keeping and the code still implements it. What that model got wrong is that the axes are not independent: it offers combinations that cannot work, and "Run on" is already a control that does nothing for the echo driver, which takes no host at all. The transport wraps the driver rather than the driver reaching for the transport. ClaudeDriver::spawn calls ssh::command itself today, which puts transport knowledge inside a translator whose job is a wire format, and obliges every future driver to remember the same. Inverted, a driver that emits no command has nothing to wrap, which is the same "Run on" problem solved structurally instead of by a special case. Also noted: llama.cpp is the case where "wrap a command" is not enough on its own, since a managed llama-server is spawned but then spoken to over HTTP, so a transport is "run this" plus "reach this port". And this section's claim that remote attachments need scp was never true of the code -- images are base64 inside the stream-json message in both directions, so nothing has to exist on the remote filesystem. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xn8nHw1tw1R6PtiY1eEtw
This commit is contained in:
1 parent
8bf99f4b76
commit
ba6c770be3
1 file changed
+49
-3
@@ -44,7 +44,35 @@ Decisions already made (2026-08-24):
|
||||
|
||||
## Architecture
|
||||
|
||||
### Providers and hosts (decided 2026-08-25)
|
||||
### Setups and providers (decided 2026-08-28, superseding the below)
|
||||
|
||||
**A setup is a machine, and it carries the providers that machine has.**
|
||||
Optional ssh details, plus the list of what can be run there. Spawning is
|
||||
then two choices in order: pick a setup, then pick one of its providers.
|
||||
|
||||
This replaces the independent providers × hosts model recorded below,
|
||||
which is what the code does today. What went wrong with it: the two axes
|
||||
are not actually independent. A provider is only real on a machine where
|
||||
that CLI is installed, so a free cross-product offers combinations that
|
||||
cannot work — `claude-cli` on a machine with no `claude`, and every
|
||||
provider paired with a host the driver ignores entirely (`EchoDriver`
|
||||
takes no host, so "Run on" is a control that silently does nothing for
|
||||
it). Grouping providers under the machine they exist on makes the picker
|
||||
show only what is true.
|
||||
|
||||
Open, and worth settling before this is built:
|
||||
|
||||
- **Where the built-in echo provider lives.** It needs no configuration
|
||||
and is the connectivity check that costs no tokens, so probably a
|
||||
provider of an implicit local setup rather than something configured.
|
||||
- **Migration.** Sessions store the provider and host names they were
|
||||
spawned with; they would store a setup and a provider instead.
|
||||
- **Setups are edited from the phone**, not by hand in `config.ron` — the
|
||||
standing preference for this app. Key material is the exception that
|
||||
cannot travel, so a setup names an identity file that must already exist
|
||||
on the backend machine.
|
||||
|
||||
The superseded model, for the reasoning it recorded:
|
||||
|
||||
Two independent axes, configured separately and chosen per session:
|
||||
|
||||
@@ -225,8 +253,26 @@ host) and **hosts**. The manager runs at most one llama-server per
|
||||
`ssh -T host …`. Process death ≙ connection death; the session shows as
|
||||
`exited` and both dialects resume (`--resume` / pi session file) on respawn,
|
||||
so a dropped SSH connection is an annoyance, not data loss.
|
||||
- Images and attachments for remote sessions are written to the remote
|
||||
session dir via `scp`/stdin before the message referencing them is sent.
|
||||
- **The transport wraps the driver, not the other way round** (decided
|
||||
2026-08-28). A driver says what to run — program, arguments, working
|
||||
directory — and something above it turns that into a process, locally or
|
||||
through ssh. Today `ClaudeDriver::spawn` calls `ssh::command` itself,
|
||||
which puts transport knowledge inside a translator whose job is a wire
|
||||
format, and means every future driver has to remember to do the same.
|
||||
Inverting it also removes the "Run on" lie for free: a driver that emits
|
||||
no command, like the echo one, has nothing for a transport to wrap, and
|
||||
the picker can say so.
|
||||
- The interface that inversion needs is **not just "run a command"**, and
|
||||
llama.cpp is the case that shows it: a managed `llama-server` is started
|
||||
as a process but then spoken to over HTTP, so a remote one needs a
|
||||
forwarded port (`ssh -L`) as well as a spawned process. A transport is
|
||||
therefore "run this" plus "reach this port", and the second operation is
|
||||
a no-op locally.
|
||||
- Attachments need no file transfer, contrary to what this section said
|
||||
before: `attachment_block` base64s an uploaded image into the
|
||||
stream-json message itself, and produced images come back the same way
|
||||
for the translator to write out locally. Nothing has to exist on the
|
||||
remote filesystem, so there is no `scp` step to get wrong.
|
||||
|
||||
### Usage limits (Claude)
|
||||
|
||||
|
||||
Reference in new issue
Block a user