init claude-code
This commit is contained in:
@@ -0,0 +1,569 @@
|
||||
import type { Notification } from 'src/context/notifications.js'
|
||||
import type { TodoList } from 'src/utils/todo/types.js'
|
||||
import type { BridgePermissionCallbacks } from '../bridge/bridgePermissionCallbacks.js'
|
||||
import type { Command } from '../commands.js'
|
||||
import type { ChannelPermissionCallbacks } from '../services/mcp/channelPermissions.js'
|
||||
import type { ElicitationRequestEvent } from '../services/mcp/elicitationHandler.js'
|
||||
import type {
|
||||
MCPServerConnection,
|
||||
ServerResource,
|
||||
} from '../services/mcp/types.js'
|
||||
import { shouldEnablePromptSuggestion } from '../services/PromptSuggestion/promptSuggestion.js'
|
||||
import {
|
||||
getEmptyToolPermissionContext,
|
||||
type Tool,
|
||||
type ToolPermissionContext,
|
||||
} from '../Tool.js'
|
||||
import type { TaskState } from '../tasks/types.js'
|
||||
import type { AgentColorName } from '../tools/AgentTool/agentColorManager.js'
|
||||
import type { AgentDefinitionsResult } from '../tools/AgentTool/loadAgentsDir.js'
|
||||
import type { AllowedPrompt } from '../tools/ExitPlanModeTool/ExitPlanModeV2Tool.js'
|
||||
import type { AgentId } from '../types/ids.js'
|
||||
import type { Message, UserMessage } from '../types/message.js'
|
||||
import type { LoadedPlugin, PluginError } from '../types/plugin.js'
|
||||
import type { DeepImmutable } from '../types/utils.js'
|
||||
import {
|
||||
type AttributionState,
|
||||
createEmptyAttributionState,
|
||||
} from '../utils/commitAttribution.js'
|
||||
import type { EffortValue } from '../utils/effort.js'
|
||||
import type { FileHistoryState } from '../utils/fileHistory.js'
|
||||
import type { REPLHookContext } from '../utils/hooks/postSamplingHooks.js'
|
||||
import type { SessionHooksState } from '../utils/hooks/sessionHooks.js'
|
||||
import type { ModelSetting } from '../utils/model/model.js'
|
||||
import type { DenialTrackingState } from '../utils/permissions/denialTracking.js'
|
||||
import type { PermissionMode } from '../utils/permissions/PermissionMode.js'
|
||||
import { getInitialSettings } from '../utils/settings/settings.js'
|
||||
import type { SettingsJson } from '../utils/settings/types.js'
|
||||
import { shouldEnableThinkingByDefault } from '../utils/thinking.js'
|
||||
import type { Store } from './store.js'
|
||||
|
||||
export type CompletionBoundary =
|
||||
| { type: 'complete'; completedAt: number; outputTokens: number }
|
||||
| { type: 'bash'; command: string; completedAt: number }
|
||||
| { type: 'edit'; toolName: string; filePath: string; completedAt: number }
|
||||
| {
|
||||
type: 'denied_tool'
|
||||
toolName: string
|
||||
detail: string
|
||||
completedAt: number
|
||||
}
|
||||
|
||||
export type SpeculationResult = {
|
||||
messages: Message[]
|
||||
boundary: CompletionBoundary | null
|
||||
timeSavedMs: number
|
||||
}
|
||||
|
||||
export type SpeculationState =
|
||||
| { status: 'idle' }
|
||||
| {
|
||||
status: 'active'
|
||||
id: string
|
||||
abort: () => void
|
||||
startTime: number
|
||||
messagesRef: { current: Message[] } // Mutable ref - avoids array spreading per message
|
||||
writtenPathsRef: { current: Set<string> } // Mutable ref - relative paths written to overlay
|
||||
boundary: CompletionBoundary | null
|
||||
suggestionLength: number
|
||||
toolUseCount: number
|
||||
isPipelined: boolean
|
||||
contextRef: { current: REPLHookContext }
|
||||
pipelinedSuggestion?: {
|
||||
text: string
|
||||
promptId: 'user_intent' | 'stated_intent'
|
||||
generationRequestId: string | null
|
||||
} | null
|
||||
}
|
||||
|
||||
export const IDLE_SPECULATION_STATE: SpeculationState = { status: 'idle' }
|
||||
|
||||
export type FooterItem =
|
||||
| 'tasks'
|
||||
| 'tmux'
|
||||
| 'bagel'
|
||||
| 'teams'
|
||||
| 'bridge'
|
||||
| 'companion'
|
||||
|
||||
export type AppState = DeepImmutable<{
|
||||
settings: SettingsJson
|
||||
verbose: boolean
|
||||
mainLoopModel: ModelSetting
|
||||
mainLoopModelForSession: ModelSetting
|
||||
statusLineText: string | undefined
|
||||
expandedView: 'none' | 'tasks' | 'teammates'
|
||||
isBriefOnly: boolean
|
||||
// Optional - only present when ENABLE_AGENT_SWARMS is true (for dead code elimination)
|
||||
showTeammateMessagePreview?: boolean
|
||||
selectedIPAgentIndex: number
|
||||
// CoordinatorTaskPanel selection: -1 = pill, 0 = main, 1..N = agent rows.
|
||||
// AppState (not local) so the panel can read it directly without prop-drilling
|
||||
// through PromptInput → PromptInputFooter.
|
||||
coordinatorTaskIndex: number
|
||||
viewSelectionMode: 'none' | 'selecting-agent' | 'viewing-agent'
|
||||
// Which footer pill is focused (arrow-key navigation below the prompt).
|
||||
// Lives in AppState so pill components rendered outside PromptInput
|
||||
// (CompanionSprite in REPL.tsx) can read their own focused state.
|
||||
footerSelection: FooterItem | null
|
||||
toolPermissionContext: ToolPermissionContext
|
||||
spinnerTip?: string
|
||||
// Agent name from --agent CLI flag or settings (for logo display)
|
||||
agent: string | undefined
|
||||
// Assistant mode fully enabled (settings + GrowthBook gate + trust).
|
||||
// Single source of truth - computed once in main.tsx before option
|
||||
// mutation, consumers read this instead of re-calling isAssistantMode().
|
||||
kairosEnabled: boolean
|
||||
// Remote session URL for --remote mode (shown in footer indicator)
|
||||
remoteSessionUrl: string | undefined
|
||||
// Remote session WS state (`claude assistant` viewer). 'connected' means the
|
||||
// live event stream is open; 'reconnecting' = transient WS drop, backoff
|
||||
// in progress; 'disconnected' = permanent close or reconnects exhausted.
|
||||
remoteConnectionStatus:
|
||||
| 'connecting'
|
||||
| 'connected'
|
||||
| 'reconnecting'
|
||||
| 'disconnected'
|
||||
// `claude assistant`: count of background tasks (Agent calls, teammates,
|
||||
// workflows) running inside the REMOTE daemon child. Event-sourced from
|
||||
// system/task_started and system/task_notification on the WS. The local
|
||||
// AppState.tasks is always empty in viewer mode — the tasks live in a
|
||||
// different process.
|
||||
remoteBackgroundTaskCount: number
|
||||
// Always-on bridge: desired state (controlled by /config or footer toggle)
|
||||
replBridgeEnabled: boolean
|
||||
// Always-on bridge: true when activated via /remote-control command, false when config-driven
|
||||
replBridgeExplicit: boolean
|
||||
// Outbound-only mode: forward events to CCR but reject inbound prompts/control
|
||||
replBridgeOutboundOnly: boolean
|
||||
// Always-on bridge: env registered + session created (= "Ready")
|
||||
replBridgeConnected: boolean
|
||||
// Always-on bridge: ingress WebSocket is open (= "Connected" - user on claude.ai)
|
||||
replBridgeSessionActive: boolean
|
||||
// Always-on bridge: poll loop is in error backoff (= "Reconnecting")
|
||||
replBridgeReconnecting: boolean
|
||||
// Always-on bridge: connect URL for Ready state (?bridge=envId)
|
||||
replBridgeConnectUrl: string | undefined
|
||||
// Always-on bridge: session URL on claude.ai (set when connected)
|
||||
replBridgeSessionUrl: string | undefined
|
||||
// Always-on bridge: IDs for debugging (shown in dialog when --verbose)
|
||||
replBridgeEnvironmentId: string | undefined
|
||||
replBridgeSessionId: string | undefined
|
||||
// Always-on bridge: error message when connection fails (shown in BridgeDialog)
|
||||
replBridgeError: string | undefined
|
||||
// Always-on bridge: session name set via `/remote-control <name>` (used as session title)
|
||||
replBridgeInitialName: string | undefined
|
||||
// Always-on bridge: first-time remote dialog pending (set by /remote-control command)
|
||||
showRemoteCallout: boolean
|
||||
}> & {
|
||||
// Unified task state - excluded from DeepImmutable because TaskState contains function types
|
||||
tasks: { [taskId: string]: TaskState }
|
||||
// Name → AgentId registry populated by Agent tool when `name` is provided.
|
||||
// Latest-wins on collision. Used by SendMessage to route by name.
|
||||
agentNameRegistry: Map<string, AgentId>
|
||||
// Task ID that has been foregrounded - its messages are shown in main view
|
||||
foregroundedTaskId?: string
|
||||
// Task ID of in-process teammate whose transcript is being viewed (undefined = leader's view)
|
||||
viewingAgentTaskId?: string
|
||||
// Latest companion reaction from the friend observer (src/buddy/observer.ts)
|
||||
companionReaction?: string
|
||||
// Timestamp of last /buddy pet — CompanionSprite renders hearts while recent
|
||||
companionPetAt?: number
|
||||
// TODO (ashwin): see if we can use utility-types DeepReadonly for this
|
||||
mcp: {
|
||||
clients: MCPServerConnection[]
|
||||
tools: Tool[]
|
||||
commands: Command[]
|
||||
resources: Record<string, ServerResource[]>
|
||||
/**
|
||||
* Incremented by /reload-plugins to trigger MCP effects to re-run
|
||||
* and pick up newly-enabled plugin MCP servers. Effects read this
|
||||
* as a dependency; the value itself is not consumed.
|
||||
*/
|
||||
pluginReconnectKey: number
|
||||
}
|
||||
plugins: {
|
||||
enabled: LoadedPlugin[]
|
||||
disabled: LoadedPlugin[]
|
||||
commands: Command[]
|
||||
/**
|
||||
* Plugin system errors collected during loading and initialization.
|
||||
* See {@link PluginError} type documentation for complete details on error
|
||||
* structure, context fields, and display format.
|
||||
*/
|
||||
errors: PluginError[]
|
||||
// Installation status for background plugin/marketplace installation
|
||||
installationStatus: {
|
||||
marketplaces: Array<{
|
||||
name: string
|
||||
status: 'pending' | 'installing' | 'installed' | 'failed'
|
||||
error?: string
|
||||
}>
|
||||
plugins: Array<{
|
||||
id: string
|
||||
name: string
|
||||
status: 'pending' | 'installing' | 'installed' | 'failed'
|
||||
error?: string
|
||||
}>
|
||||
}
|
||||
/**
|
||||
* Set to true when plugin state on disk has changed (background reconcile,
|
||||
* /plugin menu install, external settings edit) and active components are
|
||||
* stale. In interactive mode, user runs /reload-plugins to consume. In
|
||||
* headless mode, refreshPluginState() auto-consumes via refreshActivePlugins().
|
||||
*/
|
||||
needsRefresh: boolean
|
||||
}
|
||||
agentDefinitions: AgentDefinitionsResult
|
||||
fileHistory: FileHistoryState
|
||||
attribution: AttributionState
|
||||
todos: { [agentId: string]: TodoList }
|
||||
remoteAgentTaskSuggestions: { summary: string; task: string }[]
|
||||
notifications: {
|
||||
current: Notification | null
|
||||
queue: Notification[]
|
||||
}
|
||||
elicitation: {
|
||||
queue: ElicitationRequestEvent[]
|
||||
}
|
||||
thinkingEnabled: boolean | undefined
|
||||
promptSuggestionEnabled: boolean
|
||||
sessionHooks: SessionHooksState
|
||||
tungstenActiveSession?: {
|
||||
sessionName: string
|
||||
socketName: string
|
||||
target: string // The tmux target (e.g., "session:window.pane")
|
||||
}
|
||||
tungstenLastCapturedTime?: number // Timestamp when frame was captured for model
|
||||
tungstenLastCommand?: {
|
||||
command: string // The command string to display (e.g., "Enter", "echo hello")
|
||||
timestamp: number // When the command was sent
|
||||
}
|
||||
// Sticky tmux panel visibility — mirrors globalConfig.tungstenPanelVisible for reactivity.
|
||||
tungstenPanelVisible?: boolean
|
||||
// Transient auto-hide at turn end — separate from tungstenPanelVisible so the
|
||||
// pill stays in the footer (user can reopen) but the panel content doesn't take
|
||||
// screen space when idle. Cleared on next Tmux tool use or user toggle. NOT persisted.
|
||||
tungstenPanelAutoHidden?: boolean
|
||||
// WebBrowser tool (codename bagel): pill visible in footer
|
||||
bagelActive?: boolean
|
||||
// WebBrowser tool: current page URL shown in pill label
|
||||
bagelUrl?: string
|
||||
// WebBrowser tool: sticky panel visibility toggle
|
||||
bagelPanelVisible?: boolean
|
||||
// chicago MCP session state. Types inlined (not imported from
|
||||
// @ant/computer-use-mcp/types) so external typecheck passes without the
|
||||
// ant-scoped dep resolved. Shapes match `AppGrant`/`CuGrantFlags`
|
||||
// structurally — wrapper.tsx assigns via structural compatibility. Only
|
||||
// populated when feature('CHICAGO_MCP') is active.
|
||||
computerUseMcpState?: {
|
||||
// Session-scoped app allowlist. NOT persisted across resume.
|
||||
allowedApps?: readonly {
|
||||
bundleId: string
|
||||
displayName: string
|
||||
grantedAt: number
|
||||
}[]
|
||||
// Clipboard/system-key grant flags (orthogonal to allowlist).
|
||||
grantFlags?: {
|
||||
clipboardRead: boolean
|
||||
clipboardWrite: boolean
|
||||
systemKeyCombos: boolean
|
||||
}
|
||||
// Dims-only (NOT the blob) for scaleCoord after compaction. The full
|
||||
// `ScreenshotResult` including base64 is process-local in wrapper.tsx.
|
||||
lastScreenshotDims?: {
|
||||
width: number
|
||||
height: number
|
||||
displayWidth: number
|
||||
displayHeight: number
|
||||
displayId?: number
|
||||
originX?: number
|
||||
originY?: number
|
||||
}
|
||||
// Accumulated by onAppsHidden, cleared + unhidden at turn end.
|
||||
hiddenDuringTurn?: ReadonlySet<string>
|
||||
// Which display CU targets. Written back by the package's
|
||||
// `autoTargetDisplay` resolver via `onResolvedDisplayUpdated`. Persisted
|
||||
// across resume so clicks stay on the display the model last saw.
|
||||
selectedDisplayId?: number
|
||||
// True when the model explicitly picked a display via `switch_display`.
|
||||
// Makes `handleScreenshot` skip the resolver chase chain and honor
|
||||
// `selectedDisplayId` directly. Cleared on resolver writeback (pinned
|
||||
// display unplugged → Swift fell back to main) and on
|
||||
// `switch_display("auto")`.
|
||||
displayPinnedByModel?: boolean
|
||||
// Sorted comma-joined bundle-ID set the display was last auto-resolved
|
||||
// for. `handleScreenshot` only re-resolves when the allowed set has
|
||||
// changed since — keeps the resolver from yanking on every screenshot.
|
||||
displayResolvedForApps?: string
|
||||
}
|
||||
// REPL tool VM context - persists across REPL calls for state sharing
|
||||
replContext?: {
|
||||
vmContext: import('vm').Context
|
||||
registeredTools: Map<
|
||||
string,
|
||||
{
|
||||
name: string
|
||||
description: string
|
||||
schema: Record<string, unknown>
|
||||
handler: (args: Record<string, unknown>) => Promise<unknown>
|
||||
}
|
||||
>
|
||||
console: {
|
||||
log: (...args: unknown[]) => void
|
||||
error: (...args: unknown[]) => void
|
||||
warn: (...args: unknown[]) => void
|
||||
info: (...args: unknown[]) => void
|
||||
debug: (...args: unknown[]) => void
|
||||
getStdout: () => string
|
||||
getStderr: () => string
|
||||
clear: () => void
|
||||
}
|
||||
}
|
||||
teamContext?: {
|
||||
teamName: string
|
||||
teamFilePath: string
|
||||
leadAgentId: string
|
||||
// Self-identity for swarm members (separate processes in tmux panes)
|
||||
// Note: This is different from toolUseContext.agentId which is for in-process subagents
|
||||
selfAgentId?: string // Swarm member's own ID (same as leadAgentId for leaders)
|
||||
selfAgentName?: string // Swarm member's name ('team-lead' for leaders)
|
||||
isLeader?: boolean // True if this swarm member is the team leader
|
||||
selfAgentColor?: string // Assigned color for UI (used by dynamically joined sessions)
|
||||
teammates: {
|
||||
[teammateId: string]: {
|
||||
name: string
|
||||
agentType?: string
|
||||
color?: string
|
||||
tmuxSessionName: string
|
||||
tmuxPaneId: string
|
||||
cwd: string
|
||||
worktreePath?: string
|
||||
spawnedAt: number
|
||||
}
|
||||
}
|
||||
}
|
||||
// Standalone agent context for non-swarm sessions with custom name/color
|
||||
standaloneAgentContext?: {
|
||||
name: string
|
||||
color?: AgentColorName
|
||||
}
|
||||
inbox: {
|
||||
messages: Array<{
|
||||
id: string
|
||||
from: string
|
||||
text: string
|
||||
timestamp: string
|
||||
status: 'pending' | 'processing' | 'processed'
|
||||
color?: string
|
||||
summary?: string
|
||||
}>
|
||||
}
|
||||
// Worker sandbox permission requests (leader side) - for network access approval
|
||||
workerSandboxPermissions: {
|
||||
queue: Array<{
|
||||
requestId: string
|
||||
workerId: string
|
||||
workerName: string
|
||||
workerColor?: string
|
||||
host: string
|
||||
createdAt: number
|
||||
}>
|
||||
selectedIndex: number
|
||||
}
|
||||
// Pending permission request on worker side (shown while waiting for leader approval)
|
||||
pendingWorkerRequest: {
|
||||
toolName: string
|
||||
toolUseId: string
|
||||
description: string
|
||||
} | null
|
||||
// Pending sandbox permission request on worker side
|
||||
pendingSandboxRequest: {
|
||||
requestId: string
|
||||
host: string
|
||||
} | null
|
||||
promptSuggestion: {
|
||||
text: string | null
|
||||
promptId: 'user_intent' | 'stated_intent' | null
|
||||
shownAt: number
|
||||
acceptedAt: number
|
||||
generationRequestId: string | null
|
||||
}
|
||||
speculation: SpeculationState
|
||||
speculationSessionTimeSavedMs: number
|
||||
skillImprovement: {
|
||||
suggestion: {
|
||||
skillName: string
|
||||
updates: { section: string; change: string; reason: string }[]
|
||||
} | null
|
||||
}
|
||||
// Auth version - incremented on login/logout to trigger re-fetching of auth-dependent data
|
||||
authVersion: number
|
||||
// Initial message to process (from CLI args or plan mode exit)
|
||||
// When set, REPL will process the message and trigger a query
|
||||
initialMessage: {
|
||||
message: UserMessage
|
||||
clearContext?: boolean
|
||||
mode?: PermissionMode
|
||||
// Session-scoped permission rules from plan mode (e.g., "run tests", "install dependencies")
|
||||
allowedPrompts?: AllowedPrompt[]
|
||||
} | null
|
||||
// Pending plan verification state (set when exiting plan mode)
|
||||
// Used by VerifyPlanExecution tool to trigger background verification
|
||||
pendingPlanVerification?: {
|
||||
plan: string
|
||||
verificationStarted: boolean
|
||||
verificationCompleted: boolean
|
||||
}
|
||||
// Denial tracking for classifier modes (YOLO, headless, etc.) - falls back to prompting when limits exceeded
|
||||
denialTracking?: DenialTrackingState
|
||||
// Active overlays (Select dialogs, etc.) for Escape key coordination
|
||||
activeOverlays: ReadonlySet<string>
|
||||
// Fast mode
|
||||
fastMode?: boolean
|
||||
// Advisor model for server-side advisor tool (undefined = disabled).
|
||||
advisorModel?: string
|
||||
// Effort value
|
||||
effortValue?: EffortValue
|
||||
// Set synchronously in launchUltraplan before the detached flow starts.
|
||||
// Prevents duplicate launches during the ~5s window before
|
||||
// ultraplanSessionUrl is set by teleportToRemote. Cleared by launchDetached
|
||||
// once the URL is set or on failure.
|
||||
ultraplanLaunching?: boolean
|
||||
// Active ultraplan CCR session URL. Set while the RemoteAgentTask runs;
|
||||
// truthy disables the keyword trigger + rainbow. Cleared when the poll
|
||||
// reaches terminal state.
|
||||
ultraplanSessionUrl?: string
|
||||
// Approved ultraplan awaiting user choice (implement here vs fresh session).
|
||||
// Set by RemoteAgentTask poll on approval; cleared by UltraplanChoiceDialog.
|
||||
ultraplanPendingChoice?: { plan: string; sessionId: string; taskId: string }
|
||||
// Pre-launch permission dialog. Set by /ultraplan (slash or keyword);
|
||||
// cleared by UltraplanLaunchDialog on choice.
|
||||
ultraplanLaunchPending?: { blurb: string }
|
||||
// Remote-harness side: set via set_permission_mode control_request,
|
||||
// pushed to CCR external_metadata.is_ultraplan_mode by onChangeAppState.
|
||||
isUltraplanMode?: boolean
|
||||
// Always-on bridge: permission callbacks for bidirectional permission checks
|
||||
replBridgePermissionCallbacks?: BridgePermissionCallbacks
|
||||
// Channel permission callbacks — permission prompts over Telegram/iMessage/etc.
|
||||
// Races against local UI + bridge + hooks + classifier via claim() in
|
||||
// interactiveHandler.ts. Constructed once in useManageMCPConnections.
|
||||
channelPermissionCallbacks?: ChannelPermissionCallbacks
|
||||
}
|
||||
|
||||
export type AppStateStore = Store<AppState>
|
||||
|
||||
export function getDefaultAppState(): AppState {
|
||||
// Determine initial permission mode for teammates spawned with plan_mode_required
|
||||
// Use lazy require to avoid circular dependency with teammate.ts
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const teammateUtils =
|
||||
require('../utils/teammate.js') as typeof import('../utils/teammate.js')
|
||||
/* eslint-enable @typescript-eslint/no-require-imports */
|
||||
const initialMode: PermissionMode =
|
||||
teammateUtils.isTeammate() && teammateUtils.isPlanModeRequired()
|
||||
? 'plan'
|
||||
: 'default'
|
||||
|
||||
return {
|
||||
settings: getInitialSettings(),
|
||||
tasks: {},
|
||||
agentNameRegistry: new Map(),
|
||||
verbose: false,
|
||||
mainLoopModel: null, // alias, full name (as with --model or env var), or null (default)
|
||||
mainLoopModelForSession: null,
|
||||
statusLineText: undefined,
|
||||
expandedView: 'none',
|
||||
isBriefOnly: false,
|
||||
showTeammateMessagePreview: false,
|
||||
selectedIPAgentIndex: -1,
|
||||
coordinatorTaskIndex: -1,
|
||||
viewSelectionMode: 'none',
|
||||
footerSelection: null,
|
||||
kairosEnabled: false,
|
||||
remoteSessionUrl: undefined,
|
||||
remoteConnectionStatus: 'connecting',
|
||||
remoteBackgroundTaskCount: 0,
|
||||
replBridgeEnabled: false,
|
||||
replBridgeExplicit: false,
|
||||
replBridgeOutboundOnly: false,
|
||||
replBridgeConnected: false,
|
||||
replBridgeSessionActive: false,
|
||||
replBridgeReconnecting: false,
|
||||
replBridgeConnectUrl: undefined,
|
||||
replBridgeSessionUrl: undefined,
|
||||
replBridgeEnvironmentId: undefined,
|
||||
replBridgeSessionId: undefined,
|
||||
replBridgeError: undefined,
|
||||
replBridgeInitialName: undefined,
|
||||
showRemoteCallout: false,
|
||||
toolPermissionContext: {
|
||||
...getEmptyToolPermissionContext(),
|
||||
mode: initialMode,
|
||||
},
|
||||
agent: undefined,
|
||||
agentDefinitions: { activeAgents: [], allAgents: [] },
|
||||
fileHistory: {
|
||||
snapshots: [],
|
||||
trackedFiles: new Set(),
|
||||
snapshotSequence: 0,
|
||||
},
|
||||
attribution: createEmptyAttributionState(),
|
||||
mcp: {
|
||||
clients: [],
|
||||
tools: [],
|
||||
commands: [],
|
||||
resources: {},
|
||||
pluginReconnectKey: 0,
|
||||
},
|
||||
plugins: {
|
||||
enabled: [],
|
||||
disabled: [],
|
||||
commands: [],
|
||||
errors: [],
|
||||
installationStatus: {
|
||||
marketplaces: [],
|
||||
plugins: [],
|
||||
},
|
||||
needsRefresh: false,
|
||||
},
|
||||
todos: {},
|
||||
remoteAgentTaskSuggestions: [],
|
||||
notifications: {
|
||||
current: null,
|
||||
queue: [],
|
||||
},
|
||||
elicitation: {
|
||||
queue: [],
|
||||
},
|
||||
thinkingEnabled: shouldEnableThinkingByDefault(),
|
||||
promptSuggestionEnabled: shouldEnablePromptSuggestion(),
|
||||
sessionHooks: new Map(),
|
||||
inbox: {
|
||||
messages: [],
|
||||
},
|
||||
workerSandboxPermissions: {
|
||||
queue: [],
|
||||
selectedIndex: 0,
|
||||
},
|
||||
pendingWorkerRequest: null,
|
||||
pendingSandboxRequest: null,
|
||||
promptSuggestion: {
|
||||
text: null,
|
||||
promptId: null,
|
||||
shownAt: 0,
|
||||
acceptedAt: 0,
|
||||
generationRequestId: null,
|
||||
},
|
||||
speculation: IDLE_SPECULATION_STATE,
|
||||
speculationSessionTimeSavedMs: 0,
|
||||
skillImprovement: {
|
||||
suggestion: null,
|
||||
},
|
||||
authVersion: 0,
|
||||
initialMessage: null,
|
||||
effortValue: undefined,
|
||||
activeOverlays: new Set<string>(),
|
||||
fastMode: false,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user