glorious purpose

This commit is contained in:
Chris Wanstrath 2025-10-02 14:38:50 -07:00
parent e384bce2ee
commit 7be77d5a69
5 changed files with 60 additions and 19 deletions

View File

@ -1,5 +1,5 @@
//// ////
// Dispatch Messages received via WebSocket // Dispatch client->server Messages received via WebSocket
import { basename } from "path" import { basename } from "path"
import type { Message, InputMessage, SaveFileMessage } from "./shared/types" import type { Message, InputMessage, SaveFileMessage } from "./shared/types"

View File

@ -1,10 +1,12 @@
////
// Dispatch server->client Messages received via WebSocket
import type { Message } from "@/shared/types" import type { Message } from "@/shared/types"
import { cacheCommands } from "./commands" import { cacheCommands } from "./commands"
import { handleOutput } from "./scrollback" import { handleOutput } from "./scrollback"
import { handleStreamStart, handleStreamAppend, handleStreamReplace, handleStreamEnd } from "./stream" import { handleStreamStart, handleStreamAppend, handleStreamReplace, handleStreamEnd } from "./stream"
import { handleGameStart } from "./game" import { handleGameStart } from "./game"
import { browserCommands } from "./commands" import { handleSessionStart, handleSessionUpdate } from "./session"
import { handleSessionUpdate } from "./session"
// message received from server // message received from server
export async function dispatchMessage(msg: Message) { export async function dispatchMessage(msg: Message) {
@ -25,8 +27,8 @@ export async function dispatchMessage(msg: Message) {
handleStreamReplace(msg); break handleStreamReplace(msg); break
case "game:start": case "game:start":
await handleGameStart(msg); break await handleGameStart(msg); break
case "ui:mode": case "session:start":
browserCommands.mode?.(msg.data as string); break handleSessionStart(msg); break
case "session:update": case "session:update":
handleSessionUpdate(msg); break handleSessionUpdate(msg); break
default: default:

View File

@ -2,26 +2,47 @@
// Each browser tab is a shell session. This means you can run multiple sessions // Each browser tab is a shell session. This means you can run multiple sessions
// in the same browser. // in the same browser.
import type { Message } from "@/shared/types" import type { SessionStartMessage, SessionUpdateMessage } from "@/shared/types"
import { browserCommands } from "./commands"
import { randomId } from "../shared/utils" import { randomId } from "../shared/utils"
import { $ } from "./dom" import { $ } from "./dom"
export const sessionId = randomId() export const sessionId = randomId()
export const projectName = $("project-name") as HTMLSpanElement export const projectName = $("project-name") as HTMLSpanElement
export const projectCwd = $("project-cwd") as HTMLSpanElement export const projectCwd = $("project-cwd") as HTMLSpanElement
export const sessionStore = new Map<string, string>()
export function handleSessionUpdate(msg: Message) { export function handleSessionStart(msg: SessionStartMessage) {
sessionStore.set("NOSE_DIR", msg.data.NOSE_DIR)
updateProjectName(msg.data.project)
updateCwd(msg.data.cwd)
browserCommands.mode?.(msg.data.mode)
}
export function handleSessionUpdate(msg: SessionUpdateMessage) {
const data = msg.data as Record<string, string> const data = msg.data as Record<string, string>
if (data.project) { if (data.project)
projectName.textContent = data.project updateProjectName(data.project)
if (data.cwd)
updateCwd(data.cwd)
} }
if (data.cwd) { function updateProjectName(project: string) {
projectCwd.textContent = displayProjectPath(data.cwd) sessionStore.set("project", project)
projectName.textContent = project
} }
function updateCwd(cwd: string) {
cwd = displayProjectPath(cwd)
sessionStore.set("cwd", cwd)
projectCwd.textContent = cwd
} }
function displayProjectPath(path: string): string { function displayProjectPath(path: string): string {
return path let prefix = sessionStore.get("NOSE_DIR") || ""
prefix += "/" + sessionStore.get("project")
return path.replace(prefix, "")
} }

View File

@ -7,7 +7,7 @@ import { prettyJSON } from "hono/pretty-json"
import color from "kleur" import color from "kleur"
import type { Message } from "./shared/types" import type { Message } from "./shared/types"
import { NOSE_ICON, NOSE_BIN, NOSE_DATA, NOSE_DIR, NOSE_ROOT_BIN } from "./config" import { NOSE_ICON, NOSE_BIN, NOSE_DATA, NOSE_DIR, NOSE_ROOT_BIN, DEFAULT_PROJECT } from "./config"
import { transpile, isFile, tilde, isDir } from "./utils" import { transpile, isFile, tilde, isDir } from "./utils"
import { serveApp } from "./webapp" import { serveApp } from "./webapp"
import { commands, commandPath, loadCommandModule } from "./commands" import { commands, commandPath, loadCommandModule } from "./commands"
@ -137,8 +137,15 @@ app.get("/ws", c => {
addWebsocket(ws) addWebsocket(ws)
send(ws, { type: "commands", data: await commands() }) send(ws, { type: "commands", data: await commands() })
const mode = getState("ui:mode") || "tall" send(ws, {
send(ws, { type: "ui:mode", data: mode }) type: "session:start",
data: {
NOSE_DIR: NOSE_DIR,
project: DEFAULT_PROJECT,
cwd: "/",
mode: getState("ui:mode") || "tall"
}
})
}, },
async onMessage(event, ws) { async onMessage(event, ws) {
let data: Message | undefined let data: Message | undefined

View File

@ -6,6 +6,7 @@ export type Message = {
} }
| InputMessage | InputMessage
| SaveFileMessage | SaveFileMessage
| SessionStartMessage
| SessionUpdateMessage | SessionUpdateMessage
export type MessageType = "error" | "input" | "output" | "commands" | "save-file" export type MessageType = "error" | "input" | "output" | "commands" | "save-file"
@ -38,7 +39,17 @@ export type SaveFileMessage = {
data: CommandResult | CommandOutput data: CommandResult | CommandOutput
} }
export type SessionStartMessage = {
type: "session:start"
data: {
NOSE_DIR: string
project: string
cwd: string
mode: string
}
}
export type SessionUpdateMessage = { export type SessionUpdateMessage = {
type: "session:update", type: "session:update"
data: Record<string, string> data: Record<string, string>
} }