4.5 KiB
Wiring: mplex and uiflow (hooks for the integrator)
Everything below is applied outside src/mplex and src/plexer/plexer_flow.*, which the mplex
port does not own. Nothing here changes behavior of the ported classes.
Build
Add src/mplex/mplex.mk to the module list (the top Makefile already has -include src/*/*.mk,
so the file is picked up as is). It appends every mplex source and src/plexer/plexer_flow.cpp
to SRCS. ALL_SRCS = $(shell find src -name '*.cpp') already compiles them into build/detz
and build/detz_test; there is no duplicate main in src/ (the standalone binary
tests/mplex_cli_main.cpp is compiled only by the $(BUILD)/mplex_cli rule inside mplex.mk).
Includes: the headers use flat names prefixed mplex_ / plexer_flow.h; the Makefile's
-I for every src/* directory is enough. Link needs only libc (no sqlite, no curl).
Extra targets defined in mplex.mk: make build/mplex_cli, make build/mplex_flow_test,
make mplex-flow-test, make mplex-e2e.
--mplex [COMMAND...]
tai.py declares --mplex with nargs=argparse.REMAINDER, default=None: everything after the flag
belongs to mplex, bare --mplex means a new session. src/cli/cli.cpp:130 already parses this into
o.mplex (std::optional<std::vector<std::string>>, set to an empty vector for bare --mplex).
Dispatch (tai.py 40125-40128): after --version, --cap*, --serve-mcp, --update-models,
--demo* and the theme check, before --plexer-wrap and --tui:
#include "mplex_client.h"
...
if (opts.mplex.has_value()) {
std::string home = Env("TAI_HOME").empty() ? HomeDir() + "/.tai" : Env("TAI_HOME");
return detz::mplex::MplexCli::main(home, *opts.mplex);
}
MplexCli::main returns the process exit code and writes its own diagnostics to stderr, exactly
like the Python (sessions should be nested with care, unset TAI_PLEXER_ACTIVE to force,
open terminal failed: not a terminal, no server running on <sock>, ...).
Argument quirk to keep in step with tai.py: argparse's nargs=REMAINDER swallows a literal --
inside the mplex words (tai.py: --mplex send-keys -X -- cursor-up loses the --), while
tests/mplex_cli_main.cpp passes argv through untouched. The src/cli parser must drop/keep --
exactly as argparse.REMAINDER does (verify against python3 tai.py --mplex ls -- x).
The version format variable is detz::kVersion when the build puts the generated version.hpp
on the include path (the Makefile's -I$(GEN_INC) does), 1.44.2 otherwise.
--plexer-wrap
tai.py 40129-40133: same home computation, profile = args.profile or "default":
if (opts.plexer_wrap) {
std::string home = ...; // same as above
detz::mplex::NativePlexerBackend backend(home, opts.profile.empty() ? "default" : opts.profile);
return backend.run();
}
NativePlexerBackend::run() starts or joins the server and attaches this terminal to a fresh
session (MplexCli::main(home, {"new-session"})).
Shell hook text and detection
detz::mplex::PLEXER_BASHRC_BLOCK, FISH_PLEXER_BLOCK, PLEXER_BASHRC_MARK_BEGIN/END and
plexer_should_wrap(env) (header mplex_client.h) are byte-identical to the Python constants. The
installer (--install) must write these strings, not copy its own.
Agent tools (plexer_send, plexer_read, plexer_type, plexer_status, plexer_show)
Use detz::plexer::PlexerControllerFactory::detect() from plexer_flow.h (native when
TAI_PLEXER_SOCKET is set, tmux when TMUX_PANE is set, null otherwise, which hides the tools).
plexer_show is validate_flow_spec(spec) followed by PlexerFlow(app).run(*controller); its
result JSON is the return value. The existing skeleton detz::plexer::Controller/Native/Tmux in
src/plexer/plexer.h is superseded by PlexerController and friends and can be deleted by the
foundation owner once the tool handlers call the new classes (both can coexist: names differ).
Server process
MplexServer::ensure_running(home) double-forks a detached daemon that runs the select loop in the
same binary, so detz needs no extra executable. Its stdout/stderr go to
<TAI_HOME>/plexer/server.log. The daemon inherits the environment; TERM, SHELL and TAI_HOME
behave as in tai.py.
Verified
See the report of the porting run: tests/mplex_flow_test.cpp (spec/flow corpus against tai.py),
tests/mplex_e2e.py (seven scenarios run through a pty against both tai.py --mplex and
build/mplex_cli --mplex, observations compared), tests/mplex_tmux_oracle.py (tmux 3.6 oracle for
the tmux controller).