Remove opencode package + vm acp command (dead code)

The `internal/opencode` package and the `opencodeCapability` that
consumed it were hard-wired to wait for opencode on guest port 4096
when an image shipped an initrd. After the prune commits (void /
alpine / customize.sh / image build all removed), nothing banger
produces today carries an initrd, so the capability's wait path was
unreachable: every startup short-circuited to the "direct-boot, skip
opencode" branch.

Same logic for `banger vm acp`: it SSHes to `opencode acp --cwd
<path>`, a binary the golden image no longer ships. Users who run
their own image with opencode can still invoke
`ssh vm -- opencode acp --cwd /root/repo` directly — no banger
scaffolding required.

Removed:
- internal/opencode/ (whole package, 255 LOC incl. tests)
- internal/daemon/opencode.go (opencodeCapability)
- cli `vm acp` command + its helpers (runVMACP, sshACPCommandArgs,
  vmACPRemoteCommand) + their tests
- The opencodeCapability{} entry in registeredCapabilities() plus
  the test that pinned its presence
- `wait_opencode` progress-stage label from the vm-create renderer
- Stale mentions in daemon/doc.go, README, and webui test fixtures

~480 lines gone, 12 added. `banger/internal` is now 25 packages
instead of 26.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Thales Maciel 2026-04-18 16:54:37 -03:00
parent 0933deaeb1
commit b5c13e3938
No known key found for this signature in database
GPG key ID: 33112E6833C34679
10 changed files with 12 additions and 482 deletions

View file

@ -736,7 +736,6 @@ func newVMCommand() *cobra.Command {
newVMActionCommand("delete", "Delete a VM", "vm.delete"),
newVMSetCommand(),
newVMSSHCommand(),
newVMACPCommand(),
newVMWorkspaceCommand(),
newVMSessionCommand(),
newVMLogsCommand(),
@ -1140,27 +1139,6 @@ func newVMSSHCommand() *cobra.Command {
}
}
func newVMACPCommand() *cobra.Command {
var cwd string
cmd := &cobra.Command{
Use: "acp <id-or-name>",
Short: "Bridge local stdio to guest opencode acp over SSH",
Args: exactArgsUsage(1, "usage: banger vm acp [--cwd PATH] <id-or-name>"),
RunE: func(cmd *cobra.Command, args []string) error {
layout, cfg, err := ensureDaemon(cmd.Context())
if err != nil {
return err
}
if err := validateSSHPrereqs(cfg); err != nil {
return err
}
return runVMACP(cmd.Context(), layout.SocketPath, cfg, cmd.InOrStdin(), cmd.OutOrStdout(), cmd.ErrOrStderr(), args[0], cwd)
},
}
cmd.Flags().StringVar(&cwd, "cwd", "", "guest working directory for opencode acp")
return cmd
}
func newVMWorkspaceCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "workspace",
@ -2497,18 +2475,6 @@ func runSSHSession(ctx context.Context, socketPath, vmRef string, stdin io.Reade
return sshErr
}
func runVMACP(ctx context.Context, socketPath string, cfg model.DaemonConfig, stdin io.Reader, stdout, stderr io.Writer, idOrName, cwd string) error {
result, err := vmSSHFunc(ctx, socketPath, idOrName)
if err != nil {
return err
}
sshArgs, err := sshACPCommandArgs(cfg, result.GuestIP, vmACPRemoteCommand(cwd))
if err != nil {
return err
}
return sshExecFunc(ctx, stdin, stdout, stderr, sshArgs)
}
func shouldCheckSSHReminder(err error) bool {
if err == nil {
return true
@ -2544,30 +2510,6 @@ func sshCommandArgs(cfg model.DaemonConfig, guestIP string, extra []string) ([]s
return args, nil
}
func sshACPCommandArgs(cfg model.DaemonConfig, guestIP, remoteCommand string) ([]string, error) {
if guestIP == "" {
return nil, errors.New("vm has no guest IP")
}
args := []string{"-T", "-F", "/dev/null"}
if cfg.SSHKeyPath != "" {
args = append(args, "-i", cfg.SSHKeyPath)
}
args = append(
args,
"-o", "IdentitiesOnly=yes",
"-o", "BatchMode=yes",
"-o", "PreferredAuthentications=publickey",
"-o", "PasswordAuthentication=no",
"-o", "KbdInteractiveAuthentication=no",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "LogLevel=ERROR",
"root@"+guestIP,
"bash", "-lc", remoteCommand,
)
return args, nil
}
func validateSSHPrereqs(cfg model.DaemonConfig) error {
checks := system.NewPreflight()
checks.RequireCommand("ssh", "install openssh-client")
@ -3175,24 +3117,6 @@ func printVMRunWarning(out io.Writer, detail string) {
_, _ = fmt.Fprintln(out, "[vm run] warning: "+detail)
}
func vmACPRemoteCommand(cwd string) string {
var script strings.Builder
script.WriteString("set -euo pipefail\n")
if strings.TrimSpace(cwd) != "" {
fmt.Fprintf(&script, "DIR=%s\n", shellQuote(cwd))
} else {
fmt.Fprintf(&script, "REPO_DIR=%s\n", shellQuote(vmRunGuestDir()))
fmt.Fprintf(&script, "DEFAULT_DIR=%s\n", shellQuote("/root"))
script.WriteString(`if [ -d "$REPO_DIR" ]; then DIR="$REPO_DIR"; else DIR="$DEFAULT_DIR"; fi
`)
}
script.WriteString(`cd "$DIR"
`)
script.WriteString(`exec opencode acp --cwd "$DIR"
`)
return script.String()
}
func shellQuote(value string) string {
return "'" + strings.ReplaceAll(value, "'", `'"'"'`) + "'"
}
@ -3530,8 +3454,6 @@ func vmCreateStageLabel(stage string) string {
return "waiting for vsock agent"
case "wait_guest_ready":
return "waiting for guest services"
case "wait_opencode":
return "waiting for opencode"
case "apply_dns":
return "publishing dns"
case "apply_nat":

View file

@ -268,21 +268,6 @@ func TestVMRunFlagsExist(t *testing.T) {
}
}
func TestVMACPFlagsExist(t *testing.T) {
root := NewBangerCommand()
vm, _, err := root.Find([]string{"vm"})
if err != nil {
t.Fatalf("find vm: %v", err)
}
acp, _, err := vm.Find([]string{"acp"})
if err != nil {
t.Fatalf("find acp: %v", err)
}
if acp.Flags().Lookup("cwd") == nil {
t.Fatal("missing flag \"cwd\"")
}
}
func TestVMCreateFlagsShowStaticDefaults(t *testing.T) {
root := NewBangerCommand()
vm, _, err := root.Find([]string{"vm"})
@ -516,8 +501,8 @@ func TestRunVMCreatePollsUntilDone(t *testing.T) {
return api.VMCreateStatusResult{
Operation: api.VMCreateOperation{
ID: "op-1",
Stage: "wait_opencode",
Detail: "waiting for opencode on guest port 4096",
Stage: "wait_vsock_agent",
Detail: "waiting for guest vsock agent",
},
}, nil
}
@ -555,7 +540,7 @@ func TestVMCreateProgressRendererSuppressesDuplicateLines(t *testing.T) {
renderer.render(api.VMCreateOperation{Stage: "prepare_work_disk", Detail: "cloning work seed"})
renderer.render(api.VMCreateOperation{Stage: "prepare_work_disk", Detail: "cloning work seed"})
renderer.render(api.VMCreateOperation{Stage: "wait_opencode", Detail: "waiting for opencode on guest port 4096"})
renderer.render(api.VMCreateOperation{Stage: "wait_vsock_agent", Detail: "waiting for guest vsock agent"})
lines := strings.Split(strings.TrimSpace(stderr.String()), "\n")
if len(lines) != 2 {
@ -564,7 +549,7 @@ func TestVMCreateProgressRendererSuppressesDuplicateLines(t *testing.T) {
if lines[0] != "[vm create] preparing work disk: cloning work seed" {
t.Fatalf("first line = %q", lines[0])
}
if lines[1] != "[vm create] waiting for opencode: waiting for opencode on guest port 4096" {
if lines[1] != "[vm create] waiting for vsock agent: waiting for guest vsock agent" {
t.Fatalf("second line = %q", lines[1])
}
}
@ -1017,98 +1002,6 @@ func TestSSHCommandArgs(t *testing.T) {
}
}
func TestRunVMACPBridgesOverSSH(t *testing.T) {
origVMSSH := vmSSHFunc
origSSHExec := sshExecFunc
t.Cleanup(func() {
vmSSHFunc = origVMSSH
sshExecFunc = origSSHExec
})
vmSSHFunc = func(ctx context.Context, socketPath, idOrName string) (api.VMSSHResult, error) {
if socketPath != "/tmp/bangerd.sock" {
t.Fatalf("socketPath = %q, want /tmp/bangerd.sock", socketPath)
}
if idOrName != "devbox" {
t.Fatalf("idOrName = %q, want devbox", idOrName)
}
return api.VMSSHResult{Name: "devbox", GuestIP: "172.16.0.2"}, nil
}
var gotArgs []string
var gotStdin string
sshExecFunc = func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args []string) error {
gotArgs = append([]string(nil), args...)
data, err := io.ReadAll(stdin)
if err != nil {
t.Fatalf("ReadAll(stdin): %v", err)
}
gotStdin = string(data)
return nil
}
if err := runVMACP(
context.Background(),
"/tmp/bangerd.sock",
model.DaemonConfig{SSHKeyPath: "/tmp/id_ed25519"},
strings.NewReader("client stream"),
&bytes.Buffer{},
&bytes.Buffer{},
"devbox",
"",
); err != nil {
t.Fatalf("runVMACP: %v", err)
}
if gotStdin != "client stream" {
t.Fatalf("stdin = %q, want client stream", gotStdin)
}
joined := strings.Join(gotArgs, " ")
for _, want := range []string{
"-T",
"-F /dev/null",
"-i /tmp/id_ed25519",
"-o LogLevel=ERROR",
"root@172.16.0.2",
"bash -lc",
} {
if !strings.Contains(joined, want) {
t.Fatalf("ssh args = %q, want %q", joined, want)
}
}
remoteCommand := gotArgs[len(gotArgs)-1]
if !strings.Contains(remoteCommand, `exec opencode acp --cwd "$DIR"`) {
t.Fatalf("remote command = %q, want ACP exec", remoteCommand)
}
if !strings.Contains(remoteCommand, "REPO_DIR='/root/repo'") {
t.Fatalf("remote command = %q, want repo fallback", remoteCommand)
}
}
func TestVMACPRemoteCommandDefaultsToRepoThenRoot(t *testing.T) {
got := vmACPRemoteCommand("")
for _, want := range []string{
"REPO_DIR='/root/repo'",
"DEFAULT_DIR='/root'",
`if [ -d "$REPO_DIR" ]; then DIR="$REPO_DIR"; else DIR="$DEFAULT_DIR"; fi`,
`exec opencode acp --cwd "$DIR"`,
} {
if !strings.Contains(got, want) {
t.Fatalf("vmACPRemoteCommand() = %q, want %q", got, want)
}
}
}
func TestVMACPRemoteCommandUsesExplicitCWD(t *testing.T) {
got := vmACPRemoteCommand("/workspace/project")
if !strings.Contains(got, "DIR='/workspace/project'") {
t.Fatalf("vmACPRemoteCommand() = %q, want explicit cwd", got)
}
if strings.Contains(got, "REPO_DIR=") {
t.Fatalf("vmACPRemoteCommand() = %q, want no repo fallback", got)
}
}
func TestValidateSSHPrereqs(t *testing.T) {
dir := t.TempDir()
keyPath := filepath.Join(dir, "id_ed25519")