all: use make to build
This overhauls the build system.
We used to use a just-in-time clever build system
so that 'go run' and 'go install' Just Worked.
This was really nice, except that it make it
all but impossible to ship a single binary.
It also required our uses to install npm,
which some folks have an understandably negative reaction to.
This migrates to a makefile for building.
The core typescript building logic is mostly still in Go,
and untouched (boy did I learn that lesson the hard way).
The output is a single file that includes the webui, innie, and outie.
(There are still very mild shenanigans in which we write outie
out to a temp file and then 'docker cp' it into the docker container.
But this is pretty manageable.)
There are some significant follow-ups left after this commit:
- convert the nightly release builds to use the makefile
- lots of dead code removal
- maybe add -race support using a dockerfile for the cgo compilation
- maybe use 'docker cp' stdin reading with tar to avoid the temp outtie file
- all the rest of the "better release" todos (brew install, etc.)
diff --git a/loop/server/loophttp.go b/loop/server/loophttp.go
index 3f90f8b..e223a60 100644
--- a/loop/server/loophttp.go
+++ b/loop/server/loophttp.go
@@ -10,7 +10,6 @@
"fmt"
"html"
"io"
- "io/fs"
"log/slog"
"net/http"
"net/http/httputil"
@@ -26,14 +25,13 @@
"syscall"
"time"
- "sketch.dev/git_tools"
- "sketch.dev/loop/server/gzhandler"
-
"github.com/creack/pty"
"sketch.dev/claudetool/browse"
+ "sketch.dev/embedded"
+ "sketch.dev/git_tools"
"sketch.dev/llm/conversation"
"sketch.dev/loop"
- "sketch.dev/webui"
+ "sketch.dev/loop/server/gzhandler"
)
// terminalSession represents a terminal session with its PTY and the event channel
@@ -216,11 +214,6 @@
sshError: "",
}
- webBundle, err := webui.Build()
- if err != nil {
- return nil, fmt.Errorf("failed to build web bundle, did you run 'go generate sketch.dev/loop/...'?: %w", err)
- }
-
s.mux.HandleFunc("/stream", s.handleSSEStream)
// Git tool endpoints
@@ -488,7 +481,7 @@
}
})
- s.mux.Handle("/static/", http.StripPrefix("/static/", gzhandler.New(webBundle)))
+ s.mux.Handle("/static/", http.StripPrefix("/static/", gzhandler.New(embedded.WebUIFS())))
// Terminal WebSocket handler
// Terminal endpoints - predefined terminals 1-9
@@ -528,33 +521,14 @@
s.handleTerminalInput(w, r, sessionID)
})
- // Handler for interface selection via URL parameters (?m for mobile, ?d for desktop, auto-detect by default)
+ // Handler for interface selection via URL parameters (?m for mobile)
s.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- // Check URL parameters for interface selection
- queryParams := r.URL.Query()
-
- // Check if mobile interface is requested (?m parameter)
- if queryParams.Has("m") {
- // Serve the mobile-app-shell.html file
- data, err := fs.ReadFile(webBundle, "mobile-app-shell.html")
- if err != nil {
- http.Error(w, "Mobile interface not found", http.StatusNotFound)
- return
- }
- w.Header().Set("Content-Type", "text/html")
- w.Write(data)
- return
+ webuiFS := embedded.WebUIFS()
+ appShell := "sketch-app-shell.html"
+ if r.URL.Query().Has("m") {
+ appShell = "mobile-app-shell.html"
}
-
- // Check if desktop interface is explicitly requested (?d parameter)
- // or serve desktop by default
- data, err := fs.ReadFile(webBundle, "sketch-app-shell.html")
- if err != nil {
- http.Error(w, "File not found", http.StatusNotFound)
- return
- }
- w.Header().Set("Content-Type", "text/html")
- w.Write(data)
+ http.ServeFileFS(w, r, webuiFS, appShell)
})
// Handler for /commit-description - returns the description of a git commit