Updates channel prefixes, log messages, comments, and configuration values across daemon, mcp-server, and related packages to complete the rebrand from gsd to sf-run naming. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1108 lines
33 KiB
TypeScript
1108 lines
33 KiB
TypeScript
import type { BrowserSlashCommandDispatchResult, BrowserSlashCommandSurface } from "./browser-slash-command-dispatch"
|
|
import type { DoctorFixResult, DoctorReport, ForensicReport, SkillHealthReport } from "./diagnostics-types"
|
|
import type { KnowledgeData, CapturesData, CaptureResolveResult } from "./knowledge-captures-types"
|
|
import type { SettingsData } from "./settings-types"
|
|
import type {
|
|
HistoryData,
|
|
InspectData,
|
|
HooksData,
|
|
ExportResult,
|
|
UndoInfo,
|
|
CleanupData,
|
|
SteerData,
|
|
} from "./remaining-command-types"
|
|
import type { GitSummaryResponse } from "./git-summary-contract"
|
|
import type {
|
|
SessionBrowserNameFilter,
|
|
SessionBrowserSession,
|
|
SessionBrowserSortMode,
|
|
} from "./session-browser-contract"
|
|
|
|
export const COMMAND_SURFACE_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"] as const
|
|
|
|
export type CommandSurfaceThinkingLevel = (typeof COMMAND_SURFACE_THINKING_LEVELS)[number]
|
|
export type CommandSurfaceSection =
|
|
| "general"
|
|
| "model"
|
|
| "thinking"
|
|
| "queue"
|
|
| "compaction"
|
|
| "retry"
|
|
| "session-behavior"
|
|
| "recovery"
|
|
| "auth"
|
|
| "admin"
|
|
| "git"
|
|
| "resume"
|
|
| "name"
|
|
| "fork"
|
|
| "session"
|
|
| "compact"
|
|
| "workspace"
|
|
| "integrations"
|
|
| "experimental"
|
|
// SF subcommand surfaces (S02)
|
|
| "sf-status"
|
|
| "sf-visualize"
|
|
| "sf-forensics"
|
|
| "sf-doctor"
|
|
| "sf-skill-health"
|
|
| "sf-knowledge"
|
|
| "sf-capture"
|
|
| "sf-triage"
|
|
| "sf-quick"
|
|
| "sf-history"
|
|
| "sf-undo"
|
|
| "sf-inspect"
|
|
| "sf-prefs"
|
|
| "sf-config"
|
|
| "sf-hooks"
|
|
| "sf-mode"
|
|
| "sf-steer"
|
|
| "sf-export"
|
|
| "sf-cleanup"
|
|
| "sf-queue"
|
|
export type CommandSurfaceSource = "slash" | "sidebar" | "surface"
|
|
export type CommandSurfacePendingAction =
|
|
| "loading_models"
|
|
| "set_model"
|
|
| "set_thinking_level"
|
|
| "set_steering_mode"
|
|
| "set_follow_up_mode"
|
|
| "set_auto_compaction"
|
|
| "set_auto_retry"
|
|
| "abort_retry"
|
|
| "load_git_summary"
|
|
| "load_recovery_diagnostics"
|
|
| "load_session_browser"
|
|
| "rename_session"
|
|
| "save_api_key"
|
|
| "start_provider_flow"
|
|
| "submit_provider_flow_input"
|
|
| "cancel_provider_flow"
|
|
| "logout_provider"
|
|
| "switch_session"
|
|
| "load_fork_messages"
|
|
| "fork_session"
|
|
| "load_session_stats"
|
|
| "export_html"
|
|
| "compact_session"
|
|
|
|
export interface CommandSurfaceModelOption {
|
|
provider: string
|
|
modelId: string
|
|
name?: string
|
|
reasoning: boolean
|
|
isCurrent: boolean
|
|
}
|
|
|
|
export interface CommandSurfaceForkMessage {
|
|
entryId: string
|
|
text: string
|
|
}
|
|
|
|
export interface CommandSurfaceSessionStats {
|
|
sessionFile: string | undefined
|
|
sessionId: string
|
|
userMessages: number
|
|
assistantMessages: number
|
|
toolCalls: number
|
|
toolResults: number
|
|
totalMessages: number
|
|
tokens: {
|
|
input: number
|
|
output: number
|
|
cacheRead: number
|
|
cacheWrite: number
|
|
total: number
|
|
}
|
|
cost: number
|
|
}
|
|
|
|
export interface CommandSurfaceCompactionResult {
|
|
summary: string
|
|
firstKeptEntryId: string
|
|
tokensBefore: number
|
|
details?: unknown
|
|
}
|
|
|
|
export interface CommandSurfaceResumableSession {
|
|
id: string
|
|
path: string
|
|
name?: string
|
|
isActive: boolean
|
|
}
|
|
|
|
export interface CommandSurfaceSessionBrowserState {
|
|
scope: "current_project" | null
|
|
projectCwd: string | null
|
|
projectSessionsDir: string | null
|
|
activeSessionPath: string | null
|
|
query: string
|
|
sortMode: SessionBrowserSortMode
|
|
nameFilter: SessionBrowserNameFilter
|
|
totalSessions: number
|
|
returnedSessions: number
|
|
sessions: SessionBrowserSession[]
|
|
loaded: boolean
|
|
error: string | null
|
|
}
|
|
|
|
export interface CommandSurfaceSessionMutationState {
|
|
pending: boolean
|
|
sessionPath: string | null
|
|
result: string | null
|
|
error: string | null
|
|
}
|
|
|
|
export interface CommandSurfaceSettingMutationState {
|
|
pending: boolean
|
|
result: string | null
|
|
error: string | null
|
|
}
|
|
|
|
export interface CommandSurfaceSettingsMutationState {
|
|
steeringMode: CommandSurfaceSettingMutationState
|
|
followUpMode: CommandSurfaceSettingMutationState
|
|
autoCompaction: CommandSurfaceSettingMutationState
|
|
autoRetry: CommandSurfaceSettingMutationState
|
|
abortRetry: CommandSurfaceSettingMutationState
|
|
}
|
|
|
|
export interface CommandSurfaceGitSummaryState {
|
|
pending: boolean
|
|
loaded: boolean
|
|
result: GitSummaryResponse | null
|
|
error: string | null
|
|
}
|
|
|
|
export type WorkspaceRecoverySummaryTone = "healthy" | "warning" | "danger"
|
|
export type WorkspaceRecoveryDiagnosticsStatus = "ready" | "unavailable"
|
|
export type WorkspaceRecoveryBrowserActionId =
|
|
| "refresh_diagnostics"
|
|
| "refresh_workspace"
|
|
| "open_retry_controls"
|
|
| "open_resume_controls"
|
|
| "open_auth_controls"
|
|
export type CommandSurfaceRecoveryPhase = "idle" | "loading" | "ready" | "unavailable" | "error"
|
|
|
|
export interface WorkspaceRecoveryBrowserAction {
|
|
id: WorkspaceRecoveryBrowserActionId
|
|
label: string
|
|
detail: string
|
|
emphasis?: "primary" | "secondary" | "danger"
|
|
}
|
|
|
|
export interface WorkspaceRecoveryCommandSuggestion {
|
|
label: string
|
|
command: string
|
|
}
|
|
|
|
export interface WorkspaceRecoveryCodeSummary {
|
|
code: string
|
|
count: number
|
|
label: string
|
|
severity: "info" | "warning" | "error"
|
|
}
|
|
|
|
export interface WorkspaceRecoveryIssueDigest {
|
|
code: string
|
|
severity: "info" | "warning" | "error"
|
|
scope: string
|
|
message: string
|
|
file?: string
|
|
suggestion?: string
|
|
unitId?: string
|
|
}
|
|
|
|
export interface WorkspaceRecoveryDiagnostics {
|
|
status: WorkspaceRecoveryDiagnosticsStatus
|
|
loadedAt: string
|
|
project: {
|
|
cwd: string
|
|
activeScope: string | null
|
|
activeSessionPath: string | null
|
|
activeSessionId: string | null
|
|
}
|
|
summary: {
|
|
tone: WorkspaceRecoverySummaryTone
|
|
label: string
|
|
detail: string
|
|
validationCount: number
|
|
doctorIssueCount: number
|
|
lastFailurePhase: string | null
|
|
currentUnitId: string | null
|
|
retryAttempt: number
|
|
retryInProgress: boolean
|
|
compactionActive: boolean
|
|
}
|
|
bridge: {
|
|
phase: string
|
|
retry: {
|
|
enabled: boolean
|
|
inProgress: boolean
|
|
attempt: number
|
|
label: string
|
|
}
|
|
compaction: {
|
|
active: boolean
|
|
label: string
|
|
}
|
|
lastFailure: {
|
|
message: string
|
|
phase: string
|
|
at: string
|
|
commandType: string | null
|
|
afterSessionAttachment: boolean
|
|
} | null
|
|
authRefresh: {
|
|
phase: string
|
|
error: string | null
|
|
label: string
|
|
}
|
|
}
|
|
validation: {
|
|
total: number
|
|
bySeverity: {
|
|
errors: number
|
|
warnings: number
|
|
infos: number
|
|
}
|
|
codes: WorkspaceRecoveryCodeSummary[]
|
|
topIssues: WorkspaceRecoveryIssueDigest[]
|
|
}
|
|
doctor: {
|
|
scope: string | null
|
|
total: number
|
|
errors: number
|
|
warnings: number
|
|
infos: number
|
|
fixable: number
|
|
codes: Array<{ code: string; count: number }>
|
|
topIssues: WorkspaceRecoveryIssueDigest[]
|
|
}
|
|
interruptedRun: {
|
|
available: boolean
|
|
detected: boolean
|
|
label: string
|
|
detail: string
|
|
unit: {
|
|
type: string
|
|
id: string
|
|
} | null
|
|
counts: {
|
|
toolCalls: number
|
|
filesWritten: number
|
|
commandsRun: number
|
|
errors: number
|
|
}
|
|
gitChangesDetected: boolean
|
|
lastError: string | null
|
|
}
|
|
actions: {
|
|
browser: WorkspaceRecoveryBrowserAction[]
|
|
commands: WorkspaceRecoveryCommandSuggestion[]
|
|
}
|
|
}
|
|
|
|
export interface CommandSurfaceRecoveryState {
|
|
phase: CommandSurfaceRecoveryPhase
|
|
pending: boolean
|
|
loaded: boolean
|
|
stale: boolean
|
|
diagnostics: WorkspaceRecoveryDiagnostics | null
|
|
error: string | null
|
|
lastLoadedAt: string | null
|
|
lastInvalidatedAt: string | null
|
|
lastFailureAt: string | null
|
|
}
|
|
|
|
export interface WorkspaceRecoverySummary {
|
|
visible: boolean
|
|
tone: WorkspaceRecoverySummaryTone
|
|
label: string
|
|
detail: string
|
|
validationCount: number
|
|
retryInProgress: boolean
|
|
retryAttempt: number
|
|
autoRetryEnabled: boolean
|
|
isCompacting: boolean
|
|
currentUnitId: string | null
|
|
freshness: "idle" | "fresh" | "stale" | "error"
|
|
entrypointLabel: string
|
|
lastError: {
|
|
message: string
|
|
phase: string
|
|
at: string
|
|
} | null
|
|
}
|
|
|
|
export type CommandSurfaceTarget =
|
|
| { kind: "settings"; section: CommandSurfaceSection }
|
|
| { kind: "model"; provider?: string; modelId?: string; query?: string }
|
|
| { kind: "thinking"; level: CommandSurfaceThinkingLevel }
|
|
| { kind: "auth"; providerId?: string; intent: "login" | "logout" | "manage" }
|
|
| { kind: "resume"; sessionPath?: string }
|
|
| { kind: "name"; sessionPath?: string; name: string }
|
|
| { kind: "fork"; entryId?: string }
|
|
| { kind: "session"; outputPath?: string }
|
|
| { kind: "compact"; customInstructions: string }
|
|
| { kind: "sf"; surface: string; subcommand: string; args: string }
|
|
|
|
// ─── Diagnostics panel state ──────────────────────────────────────────────────
|
|
|
|
export type CommandSurfaceDiagnosticsPhase = "idle" | "loading" | "loaded" | "error"
|
|
|
|
export interface CommandSurfaceDiagnosticsPhaseState<T> {
|
|
phase: CommandSurfaceDiagnosticsPhase
|
|
data: T | null
|
|
error: string | null
|
|
lastLoadedAt: string | null
|
|
}
|
|
|
|
export interface CommandSurfaceDoctorState extends CommandSurfaceDiagnosticsPhaseState<DoctorReport> {
|
|
fixPending: boolean
|
|
lastFixResult: DoctorFixResult | null
|
|
lastFixError: string | null
|
|
}
|
|
|
|
export interface CommandSurfaceDiagnosticsState {
|
|
forensics: CommandSurfaceDiagnosticsPhaseState<ForensicReport>
|
|
doctor: CommandSurfaceDoctorState
|
|
skillHealth: CommandSurfaceDiagnosticsPhaseState<SkillHealthReport>
|
|
}
|
|
|
|
export function createInitialDiagnosticsPhaseState<T>(): CommandSurfaceDiagnosticsPhaseState<T> {
|
|
return { phase: "idle", data: null, error: null, lastLoadedAt: null }
|
|
}
|
|
|
|
export function createInitialDoctorState(): CommandSurfaceDoctorState {
|
|
return { phase: "idle", data: null, error: null, lastLoadedAt: null, fixPending: false, lastFixResult: null, lastFixError: null }
|
|
}
|
|
|
|
export function createInitialDiagnosticsState(): CommandSurfaceDiagnosticsState {
|
|
return {
|
|
forensics: createInitialDiagnosticsPhaseState<ForensicReport>(),
|
|
doctor: createInitialDoctorState(),
|
|
skillHealth: createInitialDiagnosticsPhaseState<SkillHealthReport>(),
|
|
}
|
|
}
|
|
|
|
// ─── Knowledge/Captures panel state ──────────────────────────────────────────
|
|
|
|
export interface CommandSurfaceKnowledgeCapturesResolveState {
|
|
pending: boolean
|
|
lastError: string | null
|
|
lastResult: CaptureResolveResult | null
|
|
}
|
|
|
|
export interface CommandSurfaceKnowledgeCapturesState {
|
|
knowledge: CommandSurfaceDiagnosticsPhaseState<KnowledgeData>
|
|
captures: CommandSurfaceDiagnosticsPhaseState<CapturesData>
|
|
resolveRequest: CommandSurfaceKnowledgeCapturesResolveState
|
|
}
|
|
|
|
export function createInitialKnowledgeCapturesState(): CommandSurfaceKnowledgeCapturesState {
|
|
return {
|
|
knowledge: createInitialDiagnosticsPhaseState<KnowledgeData>(),
|
|
captures: createInitialDiagnosticsPhaseState<CapturesData>(),
|
|
resolveRequest: { pending: false, lastError: null, lastResult: null },
|
|
}
|
|
}
|
|
|
|
// ─── Settings panel state ────────────────────────────────────────────────────
|
|
|
|
export type CommandSurfaceSettingsState = CommandSurfaceDiagnosticsPhaseState<SettingsData>
|
|
|
|
export function createInitialSettingsState(): CommandSurfaceSettingsState {
|
|
return createInitialDiagnosticsPhaseState<SettingsData>()
|
|
}
|
|
|
|
// ─── Remaining command surfaces state ────────────────────────────────────────
|
|
|
|
export interface CommandSurfaceRemainingState {
|
|
history: CommandSurfaceDiagnosticsPhaseState<HistoryData>
|
|
inspect: CommandSurfaceDiagnosticsPhaseState<InspectData>
|
|
hooks: CommandSurfaceDiagnosticsPhaseState<HooksData>
|
|
exportData: CommandSurfaceDiagnosticsPhaseState<ExportResult>
|
|
undo: CommandSurfaceDiagnosticsPhaseState<UndoInfo>
|
|
cleanup: CommandSurfaceDiagnosticsPhaseState<CleanupData>
|
|
steer: CommandSurfaceDiagnosticsPhaseState<SteerData>
|
|
}
|
|
|
|
export function createInitialRemainingState(): CommandSurfaceRemainingState {
|
|
return {
|
|
history: createInitialDiagnosticsPhaseState<HistoryData>(),
|
|
inspect: createInitialDiagnosticsPhaseState<InspectData>(),
|
|
hooks: createInitialDiagnosticsPhaseState<HooksData>(),
|
|
exportData: createInitialDiagnosticsPhaseState<ExportResult>(),
|
|
undo: createInitialDiagnosticsPhaseState<UndoInfo>(),
|
|
cleanup: createInitialDiagnosticsPhaseState<CleanupData>(),
|
|
steer: createInitialDiagnosticsPhaseState<SteerData>(),
|
|
}
|
|
}
|
|
|
|
export interface WorkspaceCommandSurfaceState {
|
|
open: boolean
|
|
activeSurface: BrowserSlashCommandSurface | null
|
|
source: CommandSurfaceSource | null
|
|
section: CommandSurfaceSection | null
|
|
args: string
|
|
pendingAction: CommandSurfacePendingAction | null
|
|
selectedTarget: CommandSurfaceTarget | null
|
|
lastError: string | null
|
|
lastResult: string | null
|
|
availableModels: CommandSurfaceModelOption[]
|
|
forkMessages: CommandSurfaceForkMessage[]
|
|
sessionStats: CommandSurfaceSessionStats | null
|
|
lastCompaction: CommandSurfaceCompactionResult | null
|
|
gitSummary: CommandSurfaceGitSummaryState
|
|
recovery: CommandSurfaceRecoveryState
|
|
diagnostics: CommandSurfaceDiagnosticsState
|
|
knowledgeCaptures: CommandSurfaceKnowledgeCapturesState
|
|
settingsData: CommandSurfaceSettingsState
|
|
remainingCommands: CommandSurfaceRemainingState
|
|
sessionBrowser: CommandSurfaceSessionBrowserState
|
|
resumeRequest: CommandSurfaceSessionMutationState
|
|
renameRequest: CommandSurfaceSessionMutationState
|
|
settingsRequests: CommandSurfaceSettingsMutationState
|
|
}
|
|
|
|
export interface CommandSurfaceOpenContext {
|
|
onboardingLocked?: boolean
|
|
currentModel?: { provider?: string; modelId?: string } | null
|
|
currentThinkingLevel?: string | null
|
|
preferredProviderId?: string | null
|
|
resumableSessions?: CommandSurfaceResumableSession[]
|
|
currentSessionPath?: string | null
|
|
currentSessionName?: string | null
|
|
projectCwd?: string | null
|
|
projectSessionsDir?: string | null
|
|
}
|
|
|
|
export interface CommandSurfaceOpenRequest extends CommandSurfaceOpenContext {
|
|
surface: BrowserSlashCommandSurface
|
|
source: CommandSurfaceSource
|
|
args?: string
|
|
selectedTarget?: CommandSurfaceTarget | null
|
|
}
|
|
|
|
export interface CommandSurfaceActionResult {
|
|
action: CommandSurfacePendingAction
|
|
success: boolean
|
|
message: string
|
|
selectedTarget?: CommandSurfaceTarget | null
|
|
availableModels?: CommandSurfaceModelOption[]
|
|
forkMessages?: CommandSurfaceForkMessage[]
|
|
sessionStats?: CommandSurfaceSessionStats | null
|
|
lastCompaction?: CommandSurfaceCompactionResult | null
|
|
gitSummary?: CommandSurfaceGitSummaryState
|
|
recovery?: CommandSurfaceRecoveryState
|
|
sessionBrowser?: CommandSurfaceSessionBrowserState
|
|
}
|
|
|
|
const AUTH_SURFACE_COMMANDS = new Set<BrowserSlashCommandSurface>(["settings", "login", "logout"])
|
|
const SETTINGS_MUTATION_ACTION_TO_REQUEST: Partial<
|
|
Record<CommandSurfacePendingAction, keyof CommandSurfaceSettingsMutationState>
|
|
> = {
|
|
set_steering_mode: "steeringMode",
|
|
set_follow_up_mode: "followUpMode",
|
|
set_auto_compaction: "autoCompaction",
|
|
set_auto_retry: "autoRetry",
|
|
abort_retry: "abortRetry",
|
|
}
|
|
|
|
function matchingSessionPath(
|
|
sessions: CommandSurfaceResumableSession[] | undefined,
|
|
query: string | undefined,
|
|
): string | undefined {
|
|
if (!sessions?.length) return undefined
|
|
const normalizedQuery = query?.trim().toLowerCase()
|
|
if (!normalizedQuery) {
|
|
return sessions.find((session) => !session.isActive)?.path ?? sessions[0]?.path
|
|
}
|
|
|
|
const exactMatch = sessions.find((session) => {
|
|
const values = [session.id, session.name, session.path].filter(Boolean).map((value) => value!.toLowerCase())
|
|
return values.includes(normalizedQuery)
|
|
})
|
|
if (exactMatch) return exactMatch.path
|
|
|
|
return sessions.find((session) => {
|
|
const values = [session.id, session.name, session.path].filter(Boolean).map((value) => value!.toLowerCase())
|
|
return values.some((value) => value.includes(normalizedQuery))
|
|
})?.path
|
|
}
|
|
|
|
function createInitialCommandSurfaceSessionBrowserState(
|
|
overrides: Partial<CommandSurfaceSessionBrowserState> = {},
|
|
): CommandSurfaceSessionBrowserState {
|
|
return {
|
|
scope: null,
|
|
projectCwd: null,
|
|
projectSessionsDir: null,
|
|
activeSessionPath: null,
|
|
query: "",
|
|
sortMode: "threaded",
|
|
nameFilter: "all",
|
|
totalSessions: 0,
|
|
returnedSessions: 0,
|
|
sessions: [],
|
|
loaded: false,
|
|
error: null,
|
|
...overrides,
|
|
}
|
|
}
|
|
|
|
function createInitialCommandSurfaceSessionMutationState(): CommandSurfaceSessionMutationState {
|
|
return {
|
|
pending: false,
|
|
sessionPath: null,
|
|
result: null,
|
|
error: null,
|
|
}
|
|
}
|
|
|
|
function createInitialCommandSurfaceSettingMutationState(): CommandSurfaceSettingMutationState {
|
|
return {
|
|
pending: false,
|
|
result: null,
|
|
error: null,
|
|
}
|
|
}
|
|
|
|
function createInitialCommandSurfaceSettingsMutationState(): CommandSurfaceSettingsMutationState {
|
|
return {
|
|
steeringMode: createInitialCommandSurfaceSettingMutationState(),
|
|
followUpMode: createInitialCommandSurfaceSettingMutationState(),
|
|
autoCompaction: createInitialCommandSurfaceSettingMutationState(),
|
|
autoRetry: createInitialCommandSurfaceSettingMutationState(),
|
|
abortRetry: createInitialCommandSurfaceSettingMutationState(),
|
|
}
|
|
}
|
|
|
|
function createInitialCommandSurfaceGitSummaryState(): CommandSurfaceGitSummaryState {
|
|
return {
|
|
pending: false,
|
|
loaded: false,
|
|
result: null,
|
|
error: null,
|
|
}
|
|
}
|
|
|
|
export function createInitialCommandSurfaceRecoveryState(): CommandSurfaceRecoveryState {
|
|
return {
|
|
phase: "idle",
|
|
pending: false,
|
|
loaded: false,
|
|
stale: false,
|
|
diagnostics: null,
|
|
error: null,
|
|
lastLoadedAt: null,
|
|
lastInvalidatedAt: null,
|
|
lastFailureAt: null,
|
|
}
|
|
}
|
|
|
|
function buildInitialSessionBrowserState(request: CommandSurfaceOpenRequest): CommandSurfaceSessionBrowserState {
|
|
const initialQuery = request.surface === "resume" ? request.args?.trim() ?? "" : ""
|
|
return createInitialCommandSurfaceSessionBrowserState({
|
|
activeSessionPath: request.currentSessionPath ?? null,
|
|
projectCwd: request.projectCwd ?? null,
|
|
projectSessionsDir: request.projectSessionsDir ?? null,
|
|
query: initialQuery,
|
|
sortMode: initialQuery ? "relevance" : "threaded",
|
|
})
|
|
}
|
|
|
|
export function isCommandSurfaceThinkingLevel(value: string | null | undefined): value is CommandSurfaceThinkingLevel {
|
|
return COMMAND_SURFACE_THINKING_LEVELS.includes((value ?? "") as CommandSurfaceThinkingLevel)
|
|
}
|
|
|
|
export function createInitialCommandSurfaceState(): WorkspaceCommandSurfaceState {
|
|
return {
|
|
open: false,
|
|
activeSurface: null,
|
|
source: null,
|
|
section: null,
|
|
args: "",
|
|
pendingAction: null,
|
|
selectedTarget: null,
|
|
lastError: null,
|
|
lastResult: null,
|
|
availableModels: [],
|
|
forkMessages: [],
|
|
sessionStats: null,
|
|
lastCompaction: null,
|
|
gitSummary: createInitialCommandSurfaceGitSummaryState(),
|
|
recovery: createInitialCommandSurfaceRecoveryState(),
|
|
diagnostics: createInitialDiagnosticsState(),
|
|
knowledgeCaptures: createInitialKnowledgeCapturesState(),
|
|
settingsData: createInitialSettingsState(),
|
|
remainingCommands: createInitialRemainingState(),
|
|
sessionBrowser: createInitialCommandSurfaceSessionBrowserState(),
|
|
resumeRequest: createInitialCommandSurfaceSessionMutationState(),
|
|
renameRequest: createInitialCommandSurfaceSessionMutationState(),
|
|
settingsRequests: createInitialCommandSurfaceSettingsMutationState(),
|
|
}
|
|
}
|
|
|
|
export function commandSurfaceSectionForRequest(request: CommandSurfaceOpenRequest): CommandSurfaceSection | null {
|
|
switch (request.surface) {
|
|
case "model":
|
|
return "model"
|
|
case "thinking":
|
|
return "thinking"
|
|
case "settings":
|
|
return request.onboardingLocked ? "auth" : "general"
|
|
case "git":
|
|
return "git"
|
|
case "login":
|
|
case "logout":
|
|
return "auth"
|
|
case "resume":
|
|
return "resume"
|
|
case "name":
|
|
return "name"
|
|
case "fork":
|
|
return "fork"
|
|
case "session":
|
|
case "export":
|
|
return "session"
|
|
case "compact":
|
|
return "compact"
|
|
// SF subcommand surfaces (S02)
|
|
case "sf-status": return "sf-status"
|
|
case "sf-visualize": return "sf-visualize"
|
|
case "sf-forensics": return "sf-forensics"
|
|
case "sf-doctor": return "sf-doctor"
|
|
case "sf-skill-health": return "sf-skill-health"
|
|
case "sf-knowledge": return "sf-knowledge"
|
|
case "sf-capture": return "sf-capture"
|
|
case "sf-triage": return "sf-triage"
|
|
case "sf-quick": return "sf-quick"
|
|
case "sf-history": return "sf-history"
|
|
case "sf-undo": return "sf-undo"
|
|
case "sf-inspect": return "sf-inspect"
|
|
case "sf-prefs": return "sf-prefs"
|
|
case "sf-config": return "sf-config"
|
|
case "sf-hooks": return "sf-hooks"
|
|
case "sf-mode": return "sf-mode"
|
|
case "sf-steer": return "sf-steer"
|
|
case "sf-export": return "sf-export"
|
|
case "sf-cleanup": return "sf-cleanup"
|
|
case "sf-queue": return "sf-queue"
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
|
|
function buildSettingsTarget(section: CommandSurfaceSection): CommandSurfaceTarget {
|
|
return { kind: "settings", section }
|
|
}
|
|
|
|
function buildModelTarget(request: CommandSurfaceOpenRequest): CommandSurfaceTarget {
|
|
const query = request.args?.trim() || undefined
|
|
return {
|
|
kind: "model",
|
|
provider: request.currentModel?.provider,
|
|
modelId: request.currentModel?.modelId,
|
|
query,
|
|
}
|
|
}
|
|
|
|
function buildThinkingTarget(request: CommandSurfaceOpenRequest): CommandSurfaceTarget {
|
|
const requestedLevel = request.args?.trim().toLowerCase() || ""
|
|
const level = isCommandSurfaceThinkingLevel(requestedLevel)
|
|
? requestedLevel
|
|
: isCommandSurfaceThinkingLevel(request.currentThinkingLevel)
|
|
? request.currentThinkingLevel
|
|
: "off"
|
|
|
|
return {
|
|
kind: "thinking",
|
|
level,
|
|
}
|
|
}
|
|
|
|
function buildAuthTarget(request: CommandSurfaceOpenRequest): CommandSurfaceTarget {
|
|
const requestedProviderId = request.args?.trim() || undefined
|
|
return {
|
|
kind: "auth",
|
|
providerId: requestedProviderId ?? request.preferredProviderId ?? undefined,
|
|
intent: request.surface === "login" ? "login" : request.surface === "logout" ? "logout" : "manage",
|
|
}
|
|
}
|
|
|
|
function buildResumeTarget(request: CommandSurfaceOpenRequest): Extract<CommandSurfaceTarget, { kind: "resume" }> {
|
|
const selectedPath = matchingSessionPath(request.resumableSessions, request.args)
|
|
return {
|
|
kind: "resume",
|
|
sessionPath: selectedPath,
|
|
}
|
|
}
|
|
|
|
function buildNameTarget(request: CommandSurfaceOpenRequest): CommandSurfaceTarget {
|
|
const providedName = request.args?.trim()
|
|
return {
|
|
kind: "name",
|
|
sessionPath: request.currentSessionPath ?? undefined,
|
|
name: providedName !== undefined && providedName.length > 0 ? providedName : request.currentSessionName?.trim() ?? "",
|
|
}
|
|
}
|
|
|
|
function buildForkTarget(request: CommandSurfaceOpenRequest): CommandSurfaceTarget {
|
|
const entryId = request.args?.trim() || undefined
|
|
return {
|
|
kind: "fork",
|
|
entryId,
|
|
}
|
|
}
|
|
|
|
function buildSessionTarget(request: CommandSurfaceOpenRequest): CommandSurfaceTarget {
|
|
const outputPath = request.args?.trim() || undefined
|
|
return {
|
|
kind: "session",
|
|
outputPath,
|
|
}
|
|
}
|
|
|
|
function buildCompactTarget(request: CommandSurfaceOpenRequest): CommandSurfaceTarget {
|
|
return {
|
|
kind: "compact",
|
|
customInstructions: request.args?.trim() ?? "",
|
|
}
|
|
}
|
|
|
|
export function buildCommandSurfaceTarget(request: CommandSurfaceOpenRequest): CommandSurfaceTarget | null {
|
|
if (request.selectedTarget !== undefined) {
|
|
return request.selectedTarget
|
|
}
|
|
|
|
const section = commandSurfaceSectionForRequest(request)
|
|
if (!section) return null
|
|
|
|
if (request.surface === "settings") {
|
|
return buildSettingsTarget(section)
|
|
}
|
|
|
|
if (request.surface === "model") {
|
|
return buildModelTarget(request)
|
|
}
|
|
|
|
if (request.surface === "thinking") {
|
|
return buildThinkingTarget(request)
|
|
}
|
|
|
|
if (AUTH_SURFACE_COMMANDS.has(request.surface)) {
|
|
return buildAuthTarget(request)
|
|
}
|
|
|
|
if (request.surface === "resume") {
|
|
return buildResumeTarget(request)
|
|
}
|
|
|
|
if (request.surface === "name") {
|
|
return buildNameTarget(request)
|
|
}
|
|
|
|
if (request.surface === "fork") {
|
|
return buildForkTarget(request)
|
|
}
|
|
|
|
if (request.surface === "session" || request.surface === "export") {
|
|
return buildSessionTarget(request)
|
|
}
|
|
|
|
if (request.surface === "compact") {
|
|
return buildCompactTarget(request)
|
|
}
|
|
|
|
// SF subcommand surfaces — generic target (S02)
|
|
if (request.surface?.startsWith("sf-")) {
|
|
const subcommand = request.surface.slice(4) // "sf-forensics" -> "forensics"
|
|
return { kind: "sf", surface: request.surface, subcommand, args: request.args ?? "" }
|
|
}
|
|
|
|
return buildSettingsTarget(section)
|
|
}
|
|
|
|
export function openCommandSurfaceState(
|
|
current: WorkspaceCommandSurfaceState,
|
|
request: CommandSurfaceOpenRequest,
|
|
): WorkspaceCommandSurfaceState {
|
|
const section = commandSurfaceSectionForRequest(request)
|
|
return {
|
|
...current,
|
|
open: true,
|
|
activeSurface: request.surface,
|
|
source: request.source,
|
|
section,
|
|
args: request.args?.trim() ?? "",
|
|
pendingAction: null,
|
|
selectedTarget: buildCommandSurfaceTarget(request),
|
|
lastError: null,
|
|
lastResult: null,
|
|
sessionStats: null,
|
|
forkMessages: [],
|
|
lastCompaction: null,
|
|
gitSummary: createInitialCommandSurfaceGitSummaryState(),
|
|
recovery: createInitialCommandSurfaceRecoveryState(),
|
|
diagnostics: createInitialDiagnosticsState(),
|
|
knowledgeCaptures: createInitialKnowledgeCapturesState(),
|
|
settingsData: createInitialSettingsState(),
|
|
remainingCommands: createInitialRemainingState(),
|
|
sessionBrowser: buildInitialSessionBrowserState(request),
|
|
resumeRequest: createInitialCommandSurfaceSessionMutationState(),
|
|
renameRequest: createInitialCommandSurfaceSessionMutationState(),
|
|
settingsRequests: createInitialCommandSurfaceSettingsMutationState(),
|
|
}
|
|
}
|
|
|
|
export function closeCommandSurfaceState(current: WorkspaceCommandSurfaceState): WorkspaceCommandSurfaceState {
|
|
return {
|
|
...current,
|
|
open: false,
|
|
pendingAction: null,
|
|
}
|
|
}
|
|
|
|
export function setCommandSurfaceSection(
|
|
current: WorkspaceCommandSurfaceState,
|
|
section: CommandSurfaceSection,
|
|
context: CommandSurfaceOpenContext = {},
|
|
): WorkspaceCommandSurfaceState {
|
|
const request: CommandSurfaceOpenRequest = {
|
|
surface: current.activeSurface ?? "settings",
|
|
source: current.source ?? "surface",
|
|
args: current.args,
|
|
...context,
|
|
}
|
|
|
|
const currentSessionPath =
|
|
current.selectedTarget?.kind === "resume"
|
|
? current.selectedTarget.sessionPath
|
|
: current.selectedTarget?.kind === "name"
|
|
? current.selectedTarget.sessionPath
|
|
: undefined
|
|
const currentDraftName = current.selectedTarget?.kind === "name" ? current.selectedTarget.name : undefined
|
|
|
|
let selectedTarget: CommandSurfaceTarget | null = current.selectedTarget
|
|
if (section === "model") {
|
|
selectedTarget = buildModelTarget(request)
|
|
} else if (section === "thinking") {
|
|
selectedTarget = buildThinkingTarget(request)
|
|
} else if (section === "general" || section === "session-behavior" || section === "queue" || section === "compaction" || section === "retry" || section === "recovery" || section === "git" || section === "admin") {
|
|
selectedTarget = buildSettingsTarget(section)
|
|
} else if (section === "auth") {
|
|
selectedTarget = buildAuthTarget({
|
|
...request,
|
|
surface:
|
|
current.activeSurface === "logout"
|
|
? "logout"
|
|
: current.activeSurface === "login"
|
|
? "login"
|
|
: "settings",
|
|
})
|
|
} else if (section === "resume") {
|
|
selectedTarget = { kind: "resume", sessionPath: currentSessionPath ?? buildResumeTarget(request).sessionPath }
|
|
} else if (section === "name") {
|
|
selectedTarget = {
|
|
kind: "name",
|
|
sessionPath: currentSessionPath ?? request.currentSessionPath ?? undefined,
|
|
name: currentDraftName ?? request.currentSessionName?.trim() ?? "",
|
|
}
|
|
} else if (section === "fork") {
|
|
selectedTarget = buildForkTarget(request)
|
|
} else if (section === "session") {
|
|
selectedTarget = buildSessionTarget(request)
|
|
} else if (section === "compact") {
|
|
selectedTarget = buildCompactTarget(request)
|
|
}
|
|
|
|
return {
|
|
...current,
|
|
section,
|
|
selectedTarget,
|
|
}
|
|
}
|
|
|
|
export function selectCommandSurfaceStateTarget(
|
|
current: WorkspaceCommandSurfaceState,
|
|
target: CommandSurfaceTarget,
|
|
): WorkspaceCommandSurfaceState {
|
|
const nextSection =
|
|
target.kind === "settings"
|
|
? target.section
|
|
: target.kind === "model"
|
|
? "model"
|
|
: target.kind === "thinking"
|
|
? "thinking"
|
|
: target.kind === "auth"
|
|
? "auth"
|
|
: target.kind === "resume"
|
|
? "resume"
|
|
: target.kind === "name"
|
|
? "name"
|
|
: target.kind === "fork"
|
|
? "fork"
|
|
: target.kind === "session"
|
|
? "session"
|
|
: "compact"
|
|
|
|
return {
|
|
...current,
|
|
section: nextSection,
|
|
selectedTarget: target,
|
|
lastError: null,
|
|
lastResult: null,
|
|
}
|
|
}
|
|
|
|
export function setCommandSurfacePending(
|
|
current: WorkspaceCommandSurfaceState,
|
|
action: CommandSurfacePendingAction,
|
|
selectedTarget: CommandSurfaceTarget | null = current.selectedTarget,
|
|
): WorkspaceCommandSurfaceState {
|
|
const nextResumeRequest =
|
|
action === "switch_session"
|
|
? {
|
|
pending: true,
|
|
sessionPath: selectedTarget?.kind === "resume" ? selectedTarget.sessionPath ?? null : null,
|
|
result: null,
|
|
error: null,
|
|
}
|
|
: current.resumeRequest
|
|
|
|
const nextRenameRequest =
|
|
action === "rename_session"
|
|
? {
|
|
pending: true,
|
|
sessionPath: selectedTarget?.kind === "name" ? selectedTarget.sessionPath ?? null : null,
|
|
result: null,
|
|
error: null,
|
|
}
|
|
: current.renameRequest
|
|
|
|
const settingsRequestKey = SETTINGS_MUTATION_ACTION_TO_REQUEST[action]
|
|
const nextSettingsRequests = settingsRequestKey
|
|
? {
|
|
...current.settingsRequests,
|
|
[settingsRequestKey]: {
|
|
pending: true,
|
|
result: null,
|
|
error: null,
|
|
},
|
|
}
|
|
: current.settingsRequests
|
|
|
|
return {
|
|
...current,
|
|
pendingAction: action,
|
|
selectedTarget,
|
|
lastError: null,
|
|
lastResult: null,
|
|
gitSummary:
|
|
action === "load_git_summary"
|
|
? {
|
|
...current.gitSummary,
|
|
pending: true,
|
|
error: null,
|
|
}
|
|
: current.gitSummary,
|
|
recovery:
|
|
action === "load_recovery_diagnostics"
|
|
? {
|
|
...current.recovery,
|
|
pending: true,
|
|
error: null,
|
|
phase: current.recovery.loaded ? current.recovery.phase : "loading",
|
|
}
|
|
: current.recovery,
|
|
sessionBrowser:
|
|
action === "load_session_browser"
|
|
? {
|
|
...current.sessionBrowser,
|
|
error: null,
|
|
}
|
|
: current.sessionBrowser,
|
|
resumeRequest: nextResumeRequest,
|
|
renameRequest: nextRenameRequest,
|
|
settingsRequests: nextSettingsRequests,
|
|
}
|
|
}
|
|
|
|
export function applyCommandSurfaceActionResult(
|
|
current: WorkspaceCommandSurfaceState,
|
|
result: CommandSurfaceActionResult,
|
|
): WorkspaceCommandSurfaceState {
|
|
const nextSelectedTarget = result.selectedTarget === undefined ? current.selectedTarget : result.selectedTarget
|
|
const resumeSessionPath =
|
|
(nextSelectedTarget?.kind === "resume" ? nextSelectedTarget.sessionPath : undefined) ?? current.resumeRequest.sessionPath
|
|
const renameSessionPath =
|
|
(nextSelectedTarget?.kind === "name" ? nextSelectedTarget.sessionPath : undefined) ?? current.renameRequest.sessionPath
|
|
const settingsRequestKey = SETTINGS_MUTATION_ACTION_TO_REQUEST[result.action]
|
|
const nextSettingsRequests = settingsRequestKey
|
|
? {
|
|
...current.settingsRequests,
|
|
[settingsRequestKey]: {
|
|
pending: false,
|
|
result: result.success ? result.message : null,
|
|
error: result.success ? null : result.message,
|
|
},
|
|
}
|
|
: current.settingsRequests
|
|
|
|
return {
|
|
...current,
|
|
pendingAction: null,
|
|
selectedTarget: nextSelectedTarget,
|
|
availableModels: result.availableModels ?? current.availableModels,
|
|
forkMessages: result.forkMessages ?? current.forkMessages,
|
|
sessionStats: result.sessionStats === undefined ? current.sessionStats : result.sessionStats,
|
|
lastCompaction: result.lastCompaction === undefined ? current.lastCompaction : result.lastCompaction,
|
|
gitSummary:
|
|
result.gitSummary === undefined
|
|
? current.gitSummary
|
|
: {
|
|
...result.gitSummary,
|
|
pending: false,
|
|
loaded: result.gitSummary.loaded || result.success,
|
|
},
|
|
recovery: result.recovery ?? current.recovery,
|
|
sessionBrowser: result.sessionBrowser ?? current.sessionBrowser,
|
|
resumeRequest:
|
|
result.action === "switch_session"
|
|
? {
|
|
pending: false,
|
|
sessionPath: resumeSessionPath ?? null,
|
|
result: result.success ? result.message : null,
|
|
error: result.success ? null : result.message,
|
|
}
|
|
: current.resumeRequest,
|
|
renameRequest:
|
|
result.action === "rename_session"
|
|
? {
|
|
pending: false,
|
|
sessionPath: renameSessionPath ?? null,
|
|
result: result.success ? result.message : null,
|
|
error: result.success ? null : result.message,
|
|
}
|
|
: current.renameRequest,
|
|
settingsRequests: nextSettingsRequests,
|
|
lastError: result.success ? null : result.message,
|
|
lastResult: result.success ? result.message : null,
|
|
}
|
|
}
|
|
|
|
export function surfaceOutcomeToOpenRequest(
|
|
outcome: Extract<BrowserSlashCommandDispatchResult, { kind: "surface" }>,
|
|
context: CommandSurfaceOpenContext = {},
|
|
): CommandSurfaceOpenRequest {
|
|
return {
|
|
surface: outcome.surface,
|
|
source: "slash",
|
|
args: outcome.args,
|
|
...context,
|
|
}
|
|
}
|