SPB Git

Repository Public

session-actions.ts 2.9 KB 61 lines typescript

1'use client';2import type { QueryClient } from '@tanstack/react-query';3import type { CreateSession, TerminalSession } from '@cr/shared';4import { api } from './api';5import { qk, upsertSession } from './queries';6import { useTerminals } from '@/stores/terminals';7import { disposeController, getController } from '@/components/terminal/registry';89export type NewSessionInput = Partial<CreateSession> & { kind: 'claude' | 'shell' };1011export async function createSession(qc: QueryClient, input: NewSessionInput): Promise<TerminalSession> {12  const s = await api.post<TerminalSession>('/sessions', input);13  upsertSession(qc, s);14  useTerminals.getState().open(s.id, true);15  void qc.invalidateQueries({ queryKey: qk.projects });16  return s;17}18export async function patchSession(qc: QueryClient, id: string, patch: { title?: string; pinned?: boolean; archived?: boolean }): Promise<TerminalSession> {19  const s = await api.patch<TerminalSession>(`/sessions/${id}`, patch);20  upsertSession(qc, s);21  if (s.archived) closeTab(id);22  return s;23}24export async function terminateSession(qc: QueryClient, id: string): Promise<void> {25  await api.post(`/sessions/${id}/terminate`);26  // The exit event may already have arrived over the events channel: refetch instead of27  // writing the (possibly older) HTTP response into the cache.28  await qc.invalidateQueries({ queryKey: ['sessions'] });29}30/** RECOVERABLE only: starts a fresh process (claude --resume when the conversation is known). */31export async function restartSession(qc: QueryClient, id: string): Promise<void> {32  const s = await api.post<TerminalSession>(`/sessions/${id}/reconnect`, { restart: true });33  if (s && typeof s === 'object' && 'id' in s) upsertSession(qc, s);34  getController(id)?.reconnectNow();35}36/** Re-sync the server's view of the session with the runtime, then re-attach. */37export async function resyncSession(qc: QueryClient, id: string): Promise<void> {38  const s = await api.post<TerminalSession>(`/sessions/${id}/reconnect`, {});39  if (s && typeof s === 'object' && 'id' in s) upsertSession(qc, s);40  getController(id)?.reconnectNow();41}42export function closeTab(id: string): void {43  useTerminals.getState().close(id);44  disposeController(id); // closes only this browser's attach; the session keeps running on the server45}46/** A new session that replaces an ended one (same project/kind/cwd, optionally resuming the conversation). */47export async function replaceEndedSession(qc: QueryClient, old: TerminalSession, resume: boolean): Promise<TerminalSession> {48  const s = await api.post<TerminalSession>('/sessions', {49    projectId: old.projectId,50    kind: old.kind,51    cwd: old.cwd,52    title: old.title,53    ...(resume && old.kind === 'claude' ? (old.claudeConversationId ? { resumeConversationId: old.claudeConversationId } : { continueLast: true }) : {}),54  });55  upsertSession(qc, s);56  const st = useTerminals.getState();57  st.open(s.id, true);58  closeTab(old.id);59  return s;60}61
Files main
Menu

Theme