diff --git a/packages/opencode/src/cli/cmd/tui.ts b/packages/opencode/src/cli/cmd/tui.ts index d9bba202..3d8028af 100644 --- a/packages/opencode/src/cli/cmd/tui.ts +++ b/packages/opencode/src/cli/cmd/tui.ts @@ -14,6 +14,7 @@ import { FileWatcher } from "../../file/watch" import { Ide } from "../../ide" import { Agent } from "../../agent/agent" import { Flag } from "../../flag/flag" +import { Session } from "../../session" declare global { const OPENCODE_TUI_PATH: string @@ -39,6 +40,16 @@ export const TuiCommand = cmd({ alias: ["m"], describe: "model to use in the format of provider/model", }) + .option("continue", { + alias: ["c"], + describe: "continue the last session", + type: "boolean", + }) + .option("session", { + alias: ["s"], + describe: "session id to continue", + type: "string", + }) .option("prompt", { alias: ["p"], type: "string", @@ -69,6 +80,19 @@ export const TuiCommand = cmd({ return } const result = await bootstrap({ cwd }, async (app) => { + const sessionID = await (async () => { + if (args.continue) { + const list = Session.list() + const first = await list.next() + await list.return() + if (first.done) return + return first.value.id + } + if (args.session) { + return args.session + } + return undefined + })() FileWatcher.init() const providers = await Provider.list() if (Object.keys(providers).length === 0) { @@ -106,6 +130,7 @@ export const TuiCommand = cmd({ ...(args.model ? ["--model", args.model] : []), ...(args.prompt ? ["--prompt", args.prompt] : []), ...(args.mode ? ["--mode", args.mode] : []), + ...(sessionID ? ["--session", sessionID] : []), ], cwd, stdout: "inherit", diff --git a/packages/tui/cmd/opencode/main.go b/packages/tui/cmd/opencode/main.go index 654eb0ad..c242a737 100644 --- a/packages/tui/cmd/opencode/main.go +++ b/packages/tui/cmd/opencode/main.go @@ -32,6 +32,7 @@ func main() { var model *string = flag.String("model", "", "model to begin with") var prompt *string = flag.String("prompt", "", "prompt to begin with") var agent *string = flag.String("agent", "", "agent to begin with") + var sessionID *string = flag.String("session", "", "session ID") flag.Parse() url := os.Getenv("OPENCODE_SERVER") @@ -96,7 +97,7 @@ func main() { }() // Create main context for the application - app_, err := app.New(ctx, version, appInfo, agents, httpClient, model, prompt, agent) + app_, err := app.New(ctx, version, appInfo, agents, httpClient, model, prompt, agent, sessionID) if err != nil { panic(err) } diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go index a0763779..47520257 100644 --- a/packages/tui/internal/app/app.go +++ b/packages/tui/internal/app/app.go @@ -46,6 +46,7 @@ type App struct { InitialModel *string InitialPrompt *string InitialAgent *string + InitialSession *string compactCancel context.CancelFunc IsLeaderSequence bool } @@ -95,6 +96,7 @@ func New( initialModel *string, initialPrompt *string, initialAgent *string, + initialSession *string, ) (*App, error) { util.RootPath = appInfo.Path.Root util.CwdPath = appInfo.Path.Cwd @@ -175,20 +177,21 @@ func New( slog.Debug("Loaded config", "config", configInfo) app := &App{ - Info: appInfo, - Agents: agents, - Version: version, - StatePath: appStatePath, - Config: configInfo, - State: appState, - Client: httpClient, - AgentIndex: agentIndex, - Session: &opencode.Session{}, - Messages: []Message{}, - Commands: commands.LoadFromConfig(configInfo), - InitialModel: initialModel, - InitialPrompt: initialPrompt, - InitialAgent: initialAgent, + Info: appInfo, + Agents: agents, + Version: version, + StatePath: appStatePath, + Config: configInfo, + State: appState, + Client: httpClient, + AgentIndex: agentIndex, + Session: &opencode.Session{}, + Messages: []Message{}, + Commands: commands.LoadFromConfig(configInfo), + InitialModel: initialModel, + InitialPrompt: initialPrompt, + InitialAgent: initialAgent, + InitialSession: initialSession, } return app, nil @@ -504,6 +507,28 @@ func (a *App) InitializeProvider() tea.Cmd { Provider: *selectedProvider, Model: *selectedModel, })) + + // Load initial session if provided + if a.InitialSession != nil && *a.InitialSession != "" { + cmds = append(cmds, func() tea.Msg { + // Find the session by ID + sessions, err := a.ListSessions(context.Background()) + if err != nil { + slog.Error("Failed to list sessions for initial session", "error", err) + return toast.NewErrorToast("Failed to load initial session")() + } + + for _, session := range sessions { + if session.ID == *a.InitialSession { + return SessionSelectedMsg(&session) + } + } + + slog.Warn("Initial session not found", "sessionID", *a.InitialSession) + return toast.NewErrorToast("Session not found: " + *a.InitialSession)() + }) + } + if a.InitialPrompt != nil && *a.InitialPrompt != "" { cmds = append(cmds, util.CmdHandler(SendPrompt{Text: *a.InitialPrompt})) }