session maangement updates
This commit is contained in:
@@ -339,13 +339,14 @@
|
||||
|
||||
;; Screen size presets for different device orientations
|
||||
(def ^:private screen-sizes
|
||||
{:desktop {:width 180 :height 50}
|
||||
:landscape {:width 100 :height 30}
|
||||
:portrait {:width 40 :height 35}})
|
||||
{:fullscreen {:width 180 :height 60}
|
||||
:desktop {:width 100 :height 40}
|
||||
:landscape {:width 65 :height 24}
|
||||
:portrait {:width 40 :height 35}})
|
||||
|
||||
(defn resize-session
|
||||
"Resize a tmux session window to a preset size.
|
||||
mode should be :desktop, :landscape, or :portrait.
|
||||
mode should be :fullscreen, :desktop, :landscape, or :portrait.
|
||||
Returns true on success, nil on failure."
|
||||
[session-name mode]
|
||||
(when (and session-name mode)
|
||||
@@ -388,3 +389,34 @@
|
||||
;; Only return the mode if it's an exact match or very close
|
||||
(when (and closest (<= (:distance closest) 5))
|
||||
(:mode closest)))))
|
||||
|
||||
(defn list-external-sessions
|
||||
"List all tmux sessions that are NOT managed by spiceflow (don't have spiceflow- prefix).
|
||||
Returns a list of maps with :name and :working-dir keys."
|
||||
[]
|
||||
(when-let [output (run-tmux "list-sessions" "-F" "#{session_name}:#{pane_current_path}")]
|
||||
(->> (str/split-lines output)
|
||||
(remove #(str/starts-with? % session-prefix))
|
||||
(map (fn [line]
|
||||
(let [[name path] (str/split line #":" 2)]
|
||||
{:name name
|
||||
:working-dir (or path (System/getProperty "user.home"))})))
|
||||
vec)))
|
||||
|
||||
(defn import-session
|
||||
"Import an external tmux session by renaming it to have the spiceflow prefix.
|
||||
Returns the new session info on success, nil on failure."
|
||||
[external-name]
|
||||
(when external-name
|
||||
;; Don't import if already a spiceflow session
|
||||
(when-not (str/starts-with? external-name session-prefix)
|
||||
(let [new-name (str session-prefix external-name)]
|
||||
(when (rename-session external-name new-name)
|
||||
;; Set up pipe-pane for the imported session
|
||||
(let [output-file (output-file-path new-name)]
|
||||
(spit output-file "")
|
||||
(run-tmux "pipe-pane" "-t" new-name (str "cat >> " output-file)))
|
||||
{:id new-name
|
||||
:name new-name
|
||||
:working-dir (or (run-tmux "display-message" "-t" new-name "-p" "#{pane_current_path}")
|
||||
(System/getProperty "user.home"))})))))
|
||||
|
||||
@@ -265,44 +265,56 @@
|
||||
(do
|
||||
(tmux/send-keys-raw id input)
|
||||
;; Broadcast terminal update with diff after input
|
||||
;; Always broadcast to ensure client receives update, even if content unchanged
|
||||
(future
|
||||
(Thread/sleep 100) ;; Small delay to let terminal update
|
||||
(let [{:keys [content diff changed]} (terminal-diff/capture-with-diff id tmux/capture-pane)]
|
||||
(when changed
|
||||
(broadcast-fn id {:event :terminal-update
|
||||
:content (or content "")
|
||||
:diff diff}))))
|
||||
(let [{:keys [content diff]} (terminal-diff/capture-with-diff id tmux/capture-pane)]
|
||||
(broadcast-fn id {:event :terminal-update
|
||||
:content (or content "")
|
||||
:diff diff})))
|
||||
(json-response {:status "sent"}))
|
||||
(error-response 400 "Tmux session not alive"))
|
||||
(error-response 400 "Not a tmux session")))))
|
||||
|
||||
(defn terminal-resize-handler
|
||||
"Resize a tmux session to a preset screen size.
|
||||
Mode can be: desktop, landscape, or portrait."
|
||||
Mode can be: fullscreen, desktop, landscape, or portrait."
|
||||
[_store]
|
||||
(fn [request]
|
||||
(let [id (get-in request [:path-params :id])
|
||||
mode (keyword (get-in request [:body :mode]))]
|
||||
(if (tmux-session-id? id)
|
||||
(if (tmux/session-alive? id)
|
||||
(if (#{:desktop :landscape :portrait} mode)
|
||||
(if (#{:fullscreen :desktop :landscape :portrait} mode)
|
||||
(if (tmux/resize-session id mode)
|
||||
(json-response {:status "resized" :mode (name mode)})
|
||||
(error-response 500 "Failed to resize tmux session"))
|
||||
(error-response 400 "Invalid mode. Must be: desktop, landscape, or portrait"))
|
||||
(error-response 400 "Invalid mode. Must be: fullscreen, desktop, landscape, or portrait"))
|
||||
(error-response 400 "Tmux session not alive"))
|
||||
(error-response 400 "Not a tmux session")))))
|
||||
|
||||
;; External tmux session handlers
|
||||
(defn list-external-tmux-handler
|
||||
"List all external tmux sessions (not managed by spiceflow)"
|
||||
[_request]
|
||||
(json-response (tmux/list-external-sessions)))
|
||||
|
||||
(defn import-tmux-handler
|
||||
"Import an external tmux session by renaming it to be managed by spiceflow"
|
||||
[request]
|
||||
(let [session-name (get-in request [:body :name])]
|
||||
(if session-name
|
||||
(if-let [result (tmux/import-session session-name)]
|
||||
(-> (json-response result)
|
||||
(response/status 201))
|
||||
(error-response 400 "Failed to import session. It may not exist or is already managed by spiceflow."))
|
||||
(error-response 400 "Session name is required"))))
|
||||
|
||||
;; Health check
|
||||
(defn health-handler
|
||||
[_request]
|
||||
(json-response {:status "ok" :service "spiceflow"}))
|
||||
|
||||
;; Test endpoint for verifying hot reload
|
||||
(defn ping-handler
|
||||
[_request]
|
||||
(json-response {:pong true :time (str (java.time.Instant/now))}))
|
||||
|
||||
;; Push notification handlers
|
||||
(defn vapid-key-handler
|
||||
"Return the public VAPID key for push subscriptions"
|
||||
@@ -345,7 +357,6 @@
|
||||
[store broadcast-fn push-store]
|
||||
[["/api"
|
||||
["/health" {:get health-handler}]
|
||||
["/ping" {:get ping-handler}]
|
||||
["/sessions" {:get (list-sessions-handler store)
|
||||
:post (create-session-handler store)}]
|
||||
["/sessions/:id" {:get (get-session-handler store)
|
||||
@@ -356,6 +367,8 @@
|
||||
["/sessions/:id/terminal" {:get (terminal-capture-handler store)}]
|
||||
["/sessions/:id/terminal/input" {:post (terminal-input-handler store broadcast-fn)}]
|
||||
["/sessions/:id/terminal/resize" {:post (terminal-resize-handler store)}]
|
||||
["/tmux/external" {:get list-external-tmux-handler}]
|
||||
["/tmux/import" {:post import-tmux-handler}]
|
||||
["/push/vapid-key" {:get (vapid-key-handler push-store)}]
|
||||
["/push/subscribe" {:post (subscribe-handler push-store)}]
|
||||
["/push/unsubscribe" {:post (unsubscribe-handler push-store)}]]])
|
||||
|
||||
Reference in New Issue
Block a user