broker_offline_client_test_helpers_test.go RawHistoryFolder
1package app
2
3import (
4 "context"
5 "errors"
6 "io"
7 "log/slog"
8
9 "github.com/bnema/vev/internal/adapters/brokeripc"
10 "github.com/bnema/vev/internal/adapters/clock"
11 "github.com/bnema/vev/internal/adapters/uiterm"
12 "github.com/bnema/vev/internal/ports"
13 "github.com/bnema/vev/internal/usecase/client"
14)
15
16// runOfflineClient is the sandbox terminal harness over the shared broker
17// client composition. It supplies the real broker IPC connector for one
18// offline root and the no-argument ephemeral local creation, then delegates the
19// whole run to runBrokerClient: the sandbox adds no picker, supervisor, dialer,
20// or stream of its own.
21func runOfflineClient(ctx context.Context, socket string, terminal ports.Terminal, ui *client.UI, log *slog.Logger, onState func(client.State), onFailure func(error)) error {
22 if terminal == nil {
23 return errors.New("offline client requires a terminal")
24 }
25 if log != nil {
26 log.Debug("broker_offline_client", "socket", socket)
27 }
28 return runBrokerClient(ctx, brokerClientConfig{
29 Connector: brokeripc.NewConnector(socket, brokeripc.Config{}).Navigator(),
30 Terminal: terminal,
31 UI: ui,
32 // No-argument composition creates one ephemeral local session through
33 // the closed initial-navigation union; there is no special attach path.
34 InitialNavigation: localEphemeralNavigation(),
35 AttachmentEnvironment: terminalAttachmentEnvironment(),
36 SessionEnvironment: client.SessionEnvironment{Provenance: client.SessionEnvironmentLocalCLI},
37 OnState: onState,
38 OnFailure: onFailure,
39 })
40}
41
42// offlineUIDriverHarness is the sandbox harness input: one explicitly supplied
43// offline broker socket, the virtual terminal and UI service built over it, the
44// one-shot navigation the harness was asked to perform, and the stream the JSONL
45// protocol is served on. The CLI's `--picker` selects the zero picker intent; the
46// default is the same no-argument local ephemeral creation every frontend uses.
47type offlineUIDriverHarness struct {
48 socket string
49 terminal *uiterm.Terminal
50 ui *client.UI
51 log *slog.Logger
52 navigation client.InitialNavigation
53 resolver client.InitialNavigationResolver
54 stream io.ReadWriteCloser
55}
56
57// runOfflineUIDriverClient composes the sandbox UI-driver harness over the same
58// runUIDriverClient path production uses. Its connector is the real broker IPC
59// connector of one explicitly supplied offline root: the sandbox adds no
60// production fallback, starts no broker of its own, and never reaches the
61// production XDG runtime or state. No session, endpoint, or process is
62// provisioned here: the harness reaches sessions only through the broker of its
63// own root, exactly like the production driver.
64func runOfflineUIDriverClient(ctx context.Context, harness offlineUIDriverHarness) error {
65 if harness.log != nil {
66 harness.log.Debug("broker_offline_ui_driver", "socket", harness.socket)
67 }
68 return runUIDriverClient(ctx, brokerClientConfig{
69 Connector: brokeripc.NewConnector(harness.socket, brokeripc.Config{}).Navigator(),
70 Terminal: harness.terminal,
71 Clock: clock.New(),
72 UI: harness.ui,
73 InitialNavigation: harness.navigation,
74 ResolveInitialNavigation: harness.resolver,
75 AttachmentEnvironment: terminalAttachmentEnvironment(),
76 SessionEnvironment: client.SessionEnvironment{Provenance: client.SessionEnvironmentLocalCLI},
77 }, harness.stream)
78}