Add SSH connection information to web UI
This commit implements:
1. Added SSH information display to the web UI info button
2. Shows SSH connection information only when running inside Docker container
3. Constructs the full SSH hostname as "sketch-[session_id]"
4. Added copy-to-clipboard buttons for SSH commands
5. Styles the VSCode URL as a proper clickable link
6. Shows a warning message when SSH is not available
7. Modified container naming to use only SessionID instead of imgName+SessionID
Co-Authored-By: sketch <hello@sketch.dev>
diff --git a/loop/agent.go b/loop/agent.go
index f7e7033..ab48533 100644
--- a/loop/agent.go
+++ b/loop/agent.go
@@ -74,6 +74,9 @@
// OS returns the operating system of the client.
OS() string
+ // SessionID returns the unique session identifier.
+ SessionID() string
+
// OutstandingLLMCallCount returns the number of outstanding LLM calls.
OutstandingLLMCallCount() int
@@ -338,6 +341,10 @@
return a.config.ClientGOOS
}
+func (a *Agent) SessionID() string {
+ return a.config.SessionID
+}
+
// OutsideOS returns the operating system of the outside system.
func (a *Agent) OutsideOS() string {
return a.outsideOS
diff --git a/loop/server/loophttp.go b/loop/server/loophttp.go
index 3ef540b..b0aa65e 100644
--- a/loop/server/loophttp.go
+++ b/loop/server/loophttp.go
@@ -60,6 +60,9 @@
GitOrigin string `json:"git_origin,omitempty"`
OutstandingLLMCalls int `json:"outstanding_llm_calls"`
OutstandingToolCalls []string `json:"outstanding_tool_calls"`
+ SessionID string `json:"session_id"`
+ SSHAvailable bool `json:"ssh_available"`
+ SSHError string `json:"ssh_error,omitempty"`
OutsideHostname string `json:"outside_hostname,omitempty"`
InsideHostname string `json:"inside_hostname,omitempty"`
@@ -75,6 +78,8 @@
Commit string `json:"commit"`
SSHAuthorizedKeys []byte `json:"ssh_authorized_keys"`
SSHServerIdentity []byte `json:"ssh_server_identity"`
+ SSHAvailable bool `json:"ssh_available"`
+ SSHError string `json:"ssh_error,omitempty"`
}
// Server serves sketch HTTP. Server implements http.Handler.
@@ -86,6 +91,8 @@
// Mutex to protect terminalSessions
ptyMutex sync.Mutex
terminalSessions map[string]*terminalSession
+ sshAvailable bool
+ sshError string
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -100,6 +107,8 @@
hostname: getHostname(),
logFile: logFile,
terminalSessions: make(map[string]*terminalSession),
+ sshAvailable: false,
+ sshError: "",
}
webBundle, err := webui.Build()
@@ -164,12 +173,19 @@
return
}
+ // Store SSH availability info
+ s.sshAvailable = m.SSHAvailable
+ s.sshError = m.SSHError
+
// Start the SSH server if the init request included ssh keys.
if len(m.SSHAuthorizedKeys) > 0 && len(m.SSHServerIdentity) > 0 {
go func() {
ctx := context.Background()
if err := s.ServeSSH(ctx, m.SSHServerIdentity, m.SSHAuthorizedKeys); err != nil {
slog.ErrorContext(r.Context(), "/init ServeSSH", slog.String("err", err.Error()))
+ // Update SSH error if server fails to start
+ s.sshAvailable = false
+ s.sshError = err.Error()
}
}()
}
@@ -367,6 +383,9 @@
GitOrigin: agent.GitOrigin(),
OutstandingLLMCalls: agent.OutstandingLLMCallCount(),
OutstandingToolCalls: agent.OutstandingToolCalls(),
+ SessionID: agent.SessionID(),
+ SSHAvailable: s.sshAvailable,
+ SSHError: s.sshError,
}
// Create a JSON encoder with indentation for pretty-printing