better-codex 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/apps/backend/README.md +46 -0
- package/apps/backend/bun.lock +64 -0
- package/apps/backend/package.json +18 -0
- package/apps/backend/scripts/generate-protocol.ts +32 -0
- package/apps/backend/src/analytics/service.ts +219 -0
- package/apps/backend/src/analytics/store.ts +284 -0
- package/apps/backend/src/config.ts +98 -0
- package/apps/backend/src/core/app-server.ts +131 -0
- package/apps/backend/src/core/jsonrpc.ts +166 -0
- package/apps/backend/src/protocol/AbsolutePathBuf.ts +14 -0
- package/apps/backend/src/protocol/AddConversationListenerParams.ts +6 -0
- package/apps/backend/src/protocol/AddConversationSubscriptionResponse.ts +5 -0
- package/apps/backend/src/protocol/AgentMessageContent.ts +5 -0
- package/apps/backend/src/protocol/AgentMessageContentDeltaEvent.ts +5 -0
- package/apps/backend/src/protocol/AgentMessageDeltaEvent.ts +5 -0
- package/apps/backend/src/protocol/AgentMessageEvent.ts +5 -0
- package/apps/backend/src/protocol/AgentMessageItem.ts +6 -0
- package/apps/backend/src/protocol/AgentReasoningDeltaEvent.ts +5 -0
- package/apps/backend/src/protocol/AgentReasoningEvent.ts +5 -0
- package/apps/backend/src/protocol/AgentReasoningRawContentDeltaEvent.ts +5 -0
- package/apps/backend/src/protocol/AgentReasoningRawContentEvent.ts +5 -0
- package/apps/backend/src/protocol/AgentReasoningSectionBreakEvent.ts +5 -0
- package/apps/backend/src/protocol/Annotations.ts +9 -0
- package/apps/backend/src/protocol/ApplyPatchApprovalParams.ts +21 -0
- package/apps/backend/src/protocol/ApplyPatchApprovalRequestEvent.ts +23 -0
- package/apps/backend/src/protocol/ApplyPatchApprovalResponse.ts +6 -0
- package/apps/backend/src/protocol/ArchiveConversationParams.ts +6 -0
- package/apps/backend/src/protocol/ArchiveConversationResponse.ts +5 -0
- package/apps/backend/src/protocol/AskForApproval.ts +9 -0
- package/apps/backend/src/protocol/AudioContent.ts +9 -0
- package/apps/backend/src/protocol/AuthMode.ts +5 -0
- package/apps/backend/src/protocol/AuthStatusChangeNotification.ts +9 -0
- package/apps/backend/src/protocol/BackgroundEventEvent.ts +5 -0
- package/apps/backend/src/protocol/BlobResourceContents.ts +5 -0
- package/apps/backend/src/protocol/CallToolResult.ts +10 -0
- package/apps/backend/src/protocol/CancelLoginChatGptParams.ts +5 -0
- package/apps/backend/src/protocol/CancelLoginChatGptResponse.ts +5 -0
- package/apps/backend/src/protocol/ClientInfo.ts +5 -0
- package/apps/backend/src/protocol/ClientNotification.ts +5 -0
- package/apps/backend/src/protocol/ClientRequest.ts +46 -0
- package/apps/backend/src/protocol/CodexErrorInfo.ts +8 -0
- package/apps/backend/src/protocol/ContentBlock.ts +10 -0
- package/apps/backend/src/protocol/ContentItem.ts +5 -0
- package/apps/backend/src/protocol/ContextCompactedEvent.ts +5 -0
- package/apps/backend/src/protocol/ConversationGitInfo.ts +5 -0
- package/apps/backend/src/protocol/ConversationId.ts +5 -0
- package/apps/backend/src/protocol/ConversationSummary.ts +8 -0
- package/apps/backend/src/protocol/CreditsSnapshot.ts +5 -0
- package/apps/backend/src/protocol/CustomPrompt.ts +5 -0
- package/apps/backend/src/protocol/DeprecationNoticeEvent.ts +13 -0
- package/apps/backend/src/protocol/ElicitationRequestEvent.ts +6 -0
- package/apps/backend/src/protocol/EmbeddedResource.ts +13 -0
- package/apps/backend/src/protocol/EmbeddedResourceResource.ts +7 -0
- package/apps/backend/src/protocol/ErrorEvent.ts +6 -0
- package/apps/backend/src/protocol/EventMsg.ts +60 -0
- package/apps/backend/src/protocol/ExecApprovalRequestEvent.ts +32 -0
- package/apps/backend/src/protocol/ExecCommandApprovalParams.ts +12 -0
- package/apps/backend/src/protocol/ExecCommandApprovalResponse.ts +6 -0
- package/apps/backend/src/protocol/ExecCommandBeginEvent.ts +35 -0
- package/apps/backend/src/protocol/ExecCommandEndEvent.ts +59 -0
- package/apps/backend/src/protocol/ExecCommandOutputDeltaEvent.ts +18 -0
- package/apps/backend/src/protocol/ExecCommandSource.ts +5 -0
- package/apps/backend/src/protocol/ExecOneOffCommandParams.ts +6 -0
- package/apps/backend/src/protocol/ExecOneOffCommandResponse.ts +5 -0
- package/apps/backend/src/protocol/ExecOutputStream.ts +5 -0
- package/apps/backend/src/protocol/ExecPolicyAmendment.ts +12 -0
- package/apps/backend/src/protocol/ExitedReviewModeEvent.ts +6 -0
- package/apps/backend/src/protocol/FileChange.ts +5 -0
- package/apps/backend/src/protocol/ForcedLoginMethod.ts +5 -0
- package/apps/backend/src/protocol/FunctionCallOutputContentItem.ts +9 -0
- package/apps/backend/src/protocol/FunctionCallOutputPayload.ts +15 -0
- package/apps/backend/src/protocol/FuzzyFileSearchParams.ts +5 -0
- package/apps/backend/src/protocol/FuzzyFileSearchResponse.ts +6 -0
- package/apps/backend/src/protocol/FuzzyFileSearchResult.ts +8 -0
- package/apps/backend/src/protocol/GetAuthStatusParams.ts +5 -0
- package/apps/backend/src/protocol/GetAuthStatusResponse.ts +6 -0
- package/apps/backend/src/protocol/GetConversationSummaryParams.ts +6 -0
- package/apps/backend/src/protocol/GetConversationSummaryResponse.ts +6 -0
- package/apps/backend/src/protocol/GetHistoryEntryResponseEvent.ts +10 -0
- package/apps/backend/src/protocol/GetUserAgentResponse.ts +5 -0
- package/apps/backend/src/protocol/GetUserSavedConfigResponse.ts +6 -0
- package/apps/backend/src/protocol/GhostCommit.ts +8 -0
- package/apps/backend/src/protocol/GitDiffToRemoteParams.ts +5 -0
- package/apps/backend/src/protocol/GitDiffToRemoteResponse.ts +6 -0
- package/apps/backend/src/protocol/GitSha.ts +5 -0
- package/apps/backend/src/protocol/HistoryEntry.ts +5 -0
- package/apps/backend/src/protocol/ImageContent.ts +9 -0
- package/apps/backend/src/protocol/InitializeParams.ts +6 -0
- package/apps/backend/src/protocol/InitializeResponse.ts +5 -0
- package/apps/backend/src/protocol/InputItem.ts +5 -0
- package/apps/backend/src/protocol/InterruptConversationParams.ts +6 -0
- package/apps/backend/src/protocol/InterruptConversationResponse.ts +6 -0
- package/apps/backend/src/protocol/ItemCompletedEvent.ts +7 -0
- package/apps/backend/src/protocol/ItemStartedEvent.ts +7 -0
- package/apps/backend/src/protocol/ListConversationsParams.ts +5 -0
- package/apps/backend/src/protocol/ListConversationsResponse.ts +6 -0
- package/apps/backend/src/protocol/ListCustomPromptsResponseEvent.ts +9 -0
- package/apps/backend/src/protocol/ListSkillsResponseEvent.ts +9 -0
- package/apps/backend/src/protocol/LocalShellAction.ts +6 -0
- package/apps/backend/src/protocol/LocalShellExecAction.ts +5 -0
- package/apps/backend/src/protocol/LocalShellStatus.ts +5 -0
- package/apps/backend/src/protocol/LoginApiKeyParams.ts +5 -0
- package/apps/backend/src/protocol/LoginApiKeyResponse.ts +5 -0
- package/apps/backend/src/protocol/LoginChatGptCompleteNotification.ts +8 -0
- package/apps/backend/src/protocol/LoginChatGptResponse.ts +5 -0
- package/apps/backend/src/protocol/LogoutChatGptResponse.ts +5 -0
- package/apps/backend/src/protocol/McpAuthStatus.ts +5 -0
- package/apps/backend/src/protocol/McpInvocation.ts +18 -0
- package/apps/backend/src/protocol/McpListToolsResponseEvent.ts +25 -0
- package/apps/backend/src/protocol/McpStartupCompleteEvent.ts +6 -0
- package/apps/backend/src/protocol/McpStartupFailure.ts +5 -0
- package/apps/backend/src/protocol/McpStartupStatus.ts +5 -0
- package/apps/backend/src/protocol/McpStartupUpdateEvent.ts +14 -0
- package/apps/backend/src/protocol/McpToolCallBeginEvent.ts +10 -0
- package/apps/backend/src/protocol/McpToolCallEndEvent.ts +15 -0
- package/apps/backend/src/protocol/NetworkAccess.ts +8 -0
- package/apps/backend/src/protocol/NewConversationParams.ts +8 -0
- package/apps/backend/src/protocol/NewConversationResponse.ts +7 -0
- package/apps/backend/src/protocol/ParsedCommand.ts +12 -0
- package/apps/backend/src/protocol/PatchApplyBeginEvent.ts +23 -0
- package/apps/backend/src/protocol/PatchApplyEndEvent.ts +31 -0
- package/apps/backend/src/protocol/PlanItemArg.ts +6 -0
- package/apps/backend/src/protocol/PlanType.ts +5 -0
- package/apps/backend/src/protocol/Profile.ts +9 -0
- package/apps/backend/src/protocol/README.md +11 -0
- package/apps/backend/src/protocol/RateLimitSnapshot.ts +8 -0
- package/apps/backend/src/protocol/RateLimitWindow.ts +17 -0
- package/apps/backend/src/protocol/RawResponseItemEvent.ts +6 -0
- package/apps/backend/src/protocol/ReasoningContentDeltaEvent.ts +5 -0
- package/apps/backend/src/protocol/ReasoningEffort.ts +8 -0
- package/apps/backend/src/protocol/ReasoningItem.ts +5 -0
- package/apps/backend/src/protocol/ReasoningItemContent.ts +5 -0
- package/apps/backend/src/protocol/ReasoningItemReasoningSummary.ts +5 -0
- package/apps/backend/src/protocol/ReasoningRawContentDeltaEvent.ts +5 -0
- package/apps/backend/src/protocol/ReasoningSummary.ts +10 -0
- package/apps/backend/src/protocol/RemoveConversationListenerParams.ts +5 -0
- package/apps/backend/src/protocol/RemoveConversationSubscriptionResponse.ts +5 -0
- package/apps/backend/src/protocol/RequestId.ts +5 -0
- package/apps/backend/src/protocol/Resource.ts +9 -0
- package/apps/backend/src/protocol/ResourceLink.ts +11 -0
- package/apps/backend/src/protocol/ResourceTemplate.ts +9 -0
- package/apps/backend/src/protocol/ResponseItem.ts +17 -0
- package/apps/backend/src/protocol/ResumeConversationParams.ts +8 -0
- package/apps/backend/src/protocol/ResumeConversationResponse.ts +7 -0
- package/apps/backend/src/protocol/ReviewCodeLocation.ts +9 -0
- package/apps/backend/src/protocol/ReviewDecision.ts +9 -0
- package/apps/backend/src/protocol/ReviewFinding.ts +9 -0
- package/apps/backend/src/protocol/ReviewLineRange.ts +8 -0
- package/apps/backend/src/protocol/ReviewOutputEvent.ts +9 -0
- package/apps/backend/src/protocol/ReviewRequest.ts +9 -0
- package/apps/backend/src/protocol/ReviewTarget.ts +9 -0
- package/apps/backend/src/protocol/Role.ts +8 -0
- package/apps/backend/src/protocol/SandboxMode.ts +5 -0
- package/apps/backend/src/protocol/SandboxPolicy.ts +35 -0
- package/apps/backend/src/protocol/SandboxSettings.ts +6 -0
- package/apps/backend/src/protocol/SendUserMessageParams.ts +7 -0
- package/apps/backend/src/protocol/SendUserMessageResponse.ts +5 -0
- package/apps/backend/src/protocol/SendUserTurnParams.ts +11 -0
- package/apps/backend/src/protocol/SendUserTurnResponse.ts +5 -0
- package/apps/backend/src/protocol/ServerNotification.ts +36 -0
- package/apps/backend/src/protocol/ServerRequest.ts +13 -0
- package/apps/backend/src/protocol/SessionConfiguredEvent.ts +48 -0
- package/apps/backend/src/protocol/SessionConfiguredNotification.ts +8 -0
- package/apps/backend/src/protocol/SessionSource.ts +6 -0
- package/apps/backend/src/protocol/SetDefaultModelParams.ts +6 -0
- package/apps/backend/src/protocol/SetDefaultModelResponse.ts +5 -0
- package/apps/backend/src/protocol/SkillErrorInfo.ts +5 -0
- package/apps/backend/src/protocol/SkillMetadata.ts +6 -0
- package/apps/backend/src/protocol/SkillScope.ts +5 -0
- package/apps/backend/src/protocol/SkillsListEntry.ts +7 -0
- package/apps/backend/src/protocol/StepStatus.ts +5 -0
- package/apps/backend/src/protocol/StreamErrorEvent.ts +6 -0
- package/apps/backend/src/protocol/SubAgentSource.ts +5 -0
- package/apps/backend/src/protocol/TaskCompleteEvent.ts +5 -0
- package/apps/backend/src/protocol/TaskStartedEvent.ts +5 -0
- package/apps/backend/src/protocol/TerminalInteractionEvent.ts +17 -0
- package/apps/backend/src/protocol/TextContent.ts +9 -0
- package/apps/backend/src/protocol/TextResourceContents.ts +5 -0
- package/apps/backend/src/protocol/TokenCountEvent.ts +7 -0
- package/apps/backend/src/protocol/TokenUsage.ts +5 -0
- package/apps/backend/src/protocol/TokenUsageInfo.ts +6 -0
- package/apps/backend/src/protocol/Tool.ts +11 -0
- package/apps/backend/src/protocol/ToolAnnotations.ts +15 -0
- package/apps/backend/src/protocol/ToolInputSchema.ts +9 -0
- package/apps/backend/src/protocol/ToolOutputSchema.ts +10 -0
- package/apps/backend/src/protocol/Tools.ts +5 -0
- package/apps/backend/src/protocol/TurnAbortReason.ts +5 -0
- package/apps/backend/src/protocol/TurnAbortedEvent.ts +6 -0
- package/apps/backend/src/protocol/TurnDiffEvent.ts +5 -0
- package/apps/backend/src/protocol/TurnItem.ts +9 -0
- package/apps/backend/src/protocol/UndoCompletedEvent.ts +5 -0
- package/apps/backend/src/protocol/UndoStartedEvent.ts +5 -0
- package/apps/backend/src/protocol/UpdatePlanArgs.ts +6 -0
- package/apps/backend/src/protocol/UserInfoResponse.ts +5 -0
- package/apps/backend/src/protocol/UserInput.ts +8 -0
- package/apps/backend/src/protocol/UserMessageEvent.ts +5 -0
- package/apps/backend/src/protocol/UserMessageItem.ts +6 -0
- package/apps/backend/src/protocol/UserSavedConfig.ts +14 -0
- package/apps/backend/src/protocol/Verbosity.ts +9 -0
- package/apps/backend/src/protocol/ViewImageToolCallEvent.ts +13 -0
- package/apps/backend/src/protocol/WarningEvent.ts +5 -0
- package/apps/backend/src/protocol/WebSearchAction.ts +5 -0
- package/apps/backend/src/protocol/WebSearchBeginEvent.ts +5 -0
- package/apps/backend/src/protocol/WebSearchEndEvent.ts +5 -0
- package/apps/backend/src/protocol/WebSearchItem.ts +5 -0
- package/apps/backend/src/protocol/index.ts +198 -0
- package/apps/backend/src/protocol/serde_json/JsonValue.ts +5 -0
- package/apps/backend/src/protocol/v2/Account.ts +6 -0
- package/apps/backend/src/protocol/v2/AccountLoginCompletedNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/AccountRateLimitsUpdatedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/AccountUpdatedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/AgentMessageDeltaNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/ApprovalDecision.ts +6 -0
- package/apps/backend/src/protocol/v2/AskForApproval.ts +5 -0
- package/apps/backend/src/protocol/v2/CancelLoginAccountParams.ts +5 -0
- package/apps/backend/src/protocol/v2/CancelLoginAccountResponse.ts +6 -0
- package/apps/backend/src/protocol/v2/CancelLoginAccountStatus.ts +5 -0
- package/apps/backend/src/protocol/v2/CodexErrorInfo.ts +11 -0
- package/apps/backend/src/protocol/v2/CommandAction.ts +5 -0
- package/apps/backend/src/protocol/v2/CommandExecParams.ts +6 -0
- package/apps/backend/src/protocol/v2/CommandExecResponse.ts +5 -0
- package/apps/backend/src/protocol/v2/CommandExecutionOutputDeltaNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/CommandExecutionRequestApprovalParams.ts +14 -0
- package/apps/backend/src/protocol/v2/CommandExecutionRequestApprovalResponse.ts +6 -0
- package/apps/backend/src/protocol/v2/CommandExecutionStatus.ts +5 -0
- package/apps/backend/src/protocol/v2/Config.ts +15 -0
- package/apps/backend/src/protocol/v2/ConfigBatchWriteParams.ts +10 -0
- package/apps/backend/src/protocol/v2/ConfigEdit.ts +7 -0
- package/apps/backend/src/protocol/v2/ConfigLayer.ts +7 -0
- package/apps/backend/src/protocol/v2/ConfigLayerMetadata.ts +6 -0
- package/apps/backend/src/protocol/v2/ConfigLayerSource.ts +6 -0
- package/apps/backend/src/protocol/v2/ConfigReadParams.ts +5 -0
- package/apps/backend/src/protocol/v2/ConfigReadResponse.ts +8 -0
- package/apps/backend/src/protocol/v2/ConfigValueWriteParams.ts +11 -0
- package/apps/backend/src/protocol/v2/ConfigWriteResponse.ts +12 -0
- package/apps/backend/src/protocol/v2/ContextCompactedNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/CreditsSnapshot.ts +5 -0
- package/apps/backend/src/protocol/v2/DeprecationNoticeNotification.ts +13 -0
- package/apps/backend/src/protocol/v2/ErrorNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/ExecPolicyAmendment.ts +5 -0
- package/apps/backend/src/protocol/v2/FeedbackUploadParams.ts +5 -0
- package/apps/backend/src/protocol/v2/FeedbackUploadResponse.ts +5 -0
- package/apps/backend/src/protocol/v2/FileChangeOutputDeltaNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/FileChangeRequestApprovalParams.ts +14 -0
- package/apps/backend/src/protocol/v2/FileChangeRequestApprovalResponse.ts +6 -0
- package/apps/backend/src/protocol/v2/FileUpdateChange.ts +6 -0
- package/apps/backend/src/protocol/v2/GetAccountParams.ts +5 -0
- package/apps/backend/src/protocol/v2/GetAccountRateLimitsResponse.ts +6 -0
- package/apps/backend/src/protocol/v2/GetAccountResponse.ts +6 -0
- package/apps/backend/src/protocol/v2/GitInfo.ts +5 -0
- package/apps/backend/src/protocol/v2/ItemCompletedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/ItemStartedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/ListMcpServerStatusParams.ts +13 -0
- package/apps/backend/src/protocol/v2/ListMcpServerStatusResponse.ts +11 -0
- package/apps/backend/src/protocol/v2/LoginAccountParams.ts +5 -0
- package/apps/backend/src/protocol/v2/LoginAccountResponse.ts +9 -0
- package/apps/backend/src/protocol/v2/LogoutAccountResponse.ts +5 -0
- package/apps/backend/src/protocol/v2/McpAuthStatus.ts +5 -0
- package/apps/backend/src/protocol/v2/McpServerOauthLoginCompletedNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/McpServerOauthLoginParams.ts +5 -0
- package/apps/backend/src/protocol/v2/McpServerOauthLoginResponse.ts +5 -0
- package/apps/backend/src/protocol/v2/McpServerStatus.ts +9 -0
- package/apps/backend/src/protocol/v2/McpToolCallError.ts +5 -0
- package/apps/backend/src/protocol/v2/McpToolCallProgressNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/McpToolCallResult.ts +7 -0
- package/apps/backend/src/protocol/v2/McpToolCallStatus.ts +5 -0
- package/apps/backend/src/protocol/v2/MergeStrategy.ts +5 -0
- package/apps/backend/src/protocol/v2/Model.ts +7 -0
- package/apps/backend/src/protocol/v2/ModelListParams.ts +13 -0
- package/apps/backend/src/protocol/v2/ModelListResponse.ts +11 -0
- package/apps/backend/src/protocol/v2/NetworkAccess.ts +5 -0
- package/apps/backend/src/protocol/v2/OverriddenMetadata.ts +7 -0
- package/apps/backend/src/protocol/v2/PatchApplyStatus.ts +5 -0
- package/apps/backend/src/protocol/v2/PatchChangeKind.ts +5 -0
- package/apps/backend/src/protocol/v2/ProfileV2.ts +10 -0
- package/apps/backend/src/protocol/v2/RateLimitSnapshot.ts +8 -0
- package/apps/backend/src/protocol/v2/RateLimitWindow.ts +5 -0
- package/apps/backend/src/protocol/v2/RawResponseItemCompletedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/ReasoningEffortOption.ts +6 -0
- package/apps/backend/src/protocol/v2/ReasoningSummaryPartAddedNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/ReasoningSummaryTextDeltaNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/ReasoningTextDeltaNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/ReviewDelivery.ts +5 -0
- package/apps/backend/src/protocol/v2/ReviewStartParams.ts +12 -0
- package/apps/backend/src/protocol/v2/ReviewStartResponse.ts +13 -0
- package/apps/backend/src/protocol/v2/ReviewTarget.ts +9 -0
- package/apps/backend/src/protocol/v2/SandboxMode.ts +5 -0
- package/apps/backend/src/protocol/v2/SandboxPolicy.ts +7 -0
- package/apps/backend/src/protocol/v2/SandboxWorkspaceWrite.ts +5 -0
- package/apps/backend/src/protocol/v2/SessionSource.ts +5 -0
- package/apps/backend/src/protocol/v2/SkillErrorInfo.ts +5 -0
- package/apps/backend/src/protocol/v2/SkillMetadata.ts +6 -0
- package/apps/backend/src/protocol/v2/SkillScope.ts +5 -0
- package/apps/backend/src/protocol/v2/SkillsListEntry.ts +7 -0
- package/apps/backend/src/protocol/v2/SkillsListParams.ts +13 -0
- package/apps/backend/src/protocol/v2/SkillsListResponse.ts +6 -0
- package/apps/backend/src/protocol/v2/TerminalInteractionNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/Thread.ts +46 -0
- package/apps/backend/src/protocol/v2/ThreadArchiveParams.ts +5 -0
- package/apps/backend/src/protocol/v2/ThreadArchiveResponse.ts +5 -0
- package/apps/backend/src/protocol/v2/ThreadItem.ts +48 -0
- package/apps/backend/src/protocol/v2/ThreadListParams.ts +18 -0
- package/apps/backend/src/protocol/v2/ThreadListResponse.ts +11 -0
- package/apps/backend/src/protocol/v2/ThreadResumeParams.ts +35 -0
- package/apps/backend/src/protocol/v2/ThreadResumeResponse.ts +9 -0
- package/apps/backend/src/protocol/v2/ThreadStartParams.ts +15 -0
- package/apps/backend/src/protocol/v2/ThreadStartResponse.ts +9 -0
- package/apps/backend/src/protocol/v2/ThreadStartedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/ThreadTokenUsage.ts +6 -0
- package/apps/backend/src/protocol/v2/ThreadTokenUsageUpdatedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/TokenUsageBreakdown.ts +5 -0
- package/apps/backend/src/protocol/v2/ToolsV2.ts +5 -0
- package/apps/backend/src/protocol/v2/Turn.ts +18 -0
- package/apps/backend/src/protocol/v2/TurnCompletedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/TurnDiffUpdatedNotification.ts +9 -0
- package/apps/backend/src/protocol/v2/TurnError.ts +6 -0
- package/apps/backend/src/protocol/v2/TurnInterruptParams.ts +5 -0
- package/apps/backend/src/protocol/v2/TurnInterruptResponse.ts +5 -0
- package/apps/backend/src/protocol/v2/TurnPlanStep.ts +6 -0
- package/apps/backend/src/protocol/v2/TurnPlanStepStatus.ts +5 -0
- package/apps/backend/src/protocol/v2/TurnPlanUpdatedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/TurnStartParams.ts +34 -0
- package/apps/backend/src/protocol/v2/TurnStartResponse.ts +6 -0
- package/apps/backend/src/protocol/v2/TurnStartedNotification.ts +6 -0
- package/apps/backend/src/protocol/v2/TurnStatus.ts +5 -0
- package/apps/backend/src/protocol/v2/UserInput.ts +5 -0
- package/apps/backend/src/protocol/v2/WindowsWorldWritableWarningNotification.ts +5 -0
- package/apps/backend/src/protocol/v2/WriteStatus.ts +5 -0
- package/apps/backend/src/protocol/v2/index.ts +123 -0
- package/apps/backend/src/reviews/service.ts +27 -0
- package/apps/backend/src/reviews/store.ts +124 -0
- package/apps/backend/src/server.ts +531 -0
- package/apps/backend/src/services/profile-store.ts +114 -0
- package/apps/backend/src/services/supervisor.ts +102 -0
- package/apps/backend/src/thread-index/service.ts +75 -0
- package/apps/backend/src/thread-index/store.ts +195 -0
- package/apps/backend/src/ws/messages.ts +73 -0
- package/apps/backend/tsconfig.json +20 -0
- package/apps/web/README.md +24 -0
- package/apps/web/bun.lock +1062 -0
- package/apps/web/eslint.config.js +23 -0
- package/apps/web/index.html +16 -0
- package/apps/web/package.json +38 -0
- package/apps/web/src/app.tsx +83 -0
- package/apps/web/src/components/composer/slash-command-menu.tsx +47 -0
- package/apps/web/src/components/index.ts +2 -0
- package/apps/web/src/components/layout/account-usage-panel.tsx +167 -0
- package/apps/web/src/components/layout/analytics-view.tsx +296 -0
- package/apps/web/src/components/layout/index.ts +7 -0
- package/apps/web/src/components/layout/mobile-header.tsx +56 -0
- package/apps/web/src/components/layout/reviews-view.tsx +848 -0
- package/apps/web/src/components/layout/session-view.tsx +1374 -0
- package/apps/web/src/components/layout/settings-dialog.tsx +322 -0
- package/apps/web/src/components/layout/side-bar.tsx +417 -0
- package/apps/web/src/components/layout/thread-list.tsx +488 -0
- package/apps/web/src/components/layout/virtualized-message-list.tsx +748 -0
- package/apps/web/src/components/loading/startup-ascii.ts +652 -0
- package/apps/web/src/components/loading/startup-loader.tsx +37 -0
- package/apps/web/src/components/session-view/file-mention-menu.tsx +46 -0
- package/apps/web/src/components/session-view/session-auth-banner.tsx +61 -0
- package/apps/web/src/components/session-view/session-composer.tsx +328 -0
- package/apps/web/src/components/session-view/session-dialogs.tsx +280 -0
- package/apps/web/src/components/session-view/session-empty.tsx +47 -0
- package/apps/web/src/components/session-view/session-header.tsx +49 -0
- package/apps/web/src/components/ui/avatar.tsx +19 -0
- package/apps/web/src/components/ui/badge.tsx +21 -0
- package/apps/web/src/components/ui/button.tsx +47 -0
- package/apps/web/src/components/ui/collapsible-content.tsx +114 -0
- package/apps/web/src/components/ui/contribution-graph.tsx +182 -0
- package/apps/web/src/components/ui/dialog-box.tsx +203 -0
- package/apps/web/src/components/ui/icon-button.tsx +32 -0
- package/apps/web/src/components/ui/icons.tsx +187 -0
- package/apps/web/src/components/ui/index.tsx +15 -0
- package/apps/web/src/components/ui/input.tsx +43 -0
- package/apps/web/src/components/ui/markdown-stream.tsx +21 -0
- package/apps/web/src/components/ui/mobile-drawer.tsx +124 -0
- package/apps/web/src/components/ui/section-header.tsx +13 -0
- package/apps/web/src/components/ui/select.tsx +217 -0
- package/apps/web/src/components/ui/shimmer.tsx +138 -0
- package/apps/web/src/components/ui/status-dot.tsx +24 -0
- package/apps/web/src/config.ts +5 -0
- package/apps/web/src/hooks/index.ts +3 -0
- package/apps/web/src/hooks/use-analytics.ts +122 -0
- package/apps/web/src/hooks/use-hub-connection.ts +587 -0
- package/apps/web/src/hooks/use-mobile.ts +76 -0
- package/apps/web/src/hooks/use-thread-history.ts +210 -0
- package/apps/web/src/index.css +269 -0
- package/apps/web/src/main.tsx +10 -0
- package/apps/web/src/services/hub-client.ts +358 -0
- package/apps/web/src/store/index.ts +528 -0
- package/apps/web/src/types/index.ts +119 -0
- package/apps/web/src/utils/account-refresh.ts +168 -0
- package/apps/web/src/utils/approval-policy.ts +53 -0
- package/apps/web/src/utils/init-prompt.ts +41 -0
- package/apps/web/src/utils/item-format.ts +170 -0
- package/apps/web/src/utils/prompt-expander.ts +62 -0
- package/apps/web/src/utils/reasoning-summary.ts +48 -0
- package/apps/web/src/utils/slash-commands.ts +98 -0
- package/apps/web/tsconfig.app.json +28 -0
- package/apps/web/tsconfig.json +7 -0
- package/apps/web/tsconfig.node.json +26 -0
- package/apps/web/vite.config.ts +8 -0
- package/bin/better-codex.cjs +199 -0
- package/package.json +20 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import type { ApprovalPolicy, ReasoningEffort, ReasoningSummary } from '../../types'
|
|
2
|
+
import { AlertDialog, Button, CopyDialog, Dialog, PromptDialog, Select, type SelectOption } from '../ui'
|
|
3
|
+
|
|
4
|
+
interface SessionDialogsProps {
|
|
5
|
+
showModelDialog: boolean
|
|
6
|
+
onCloseModelDialog: () => void
|
|
7
|
+
modelOptions: SelectOption[]
|
|
8
|
+
pendingModelId: string
|
|
9
|
+
setPendingModelId: (value: string) => void
|
|
10
|
+
pendingEffortOptions: SelectOption[]
|
|
11
|
+
pendingEffort: ReasoningEffort | ''
|
|
12
|
+
setPendingEffort: (value: ReasoningEffort | '') => void
|
|
13
|
+
summaryOptions: SelectOption[]
|
|
14
|
+
pendingSummary: ReasoningSummary | ''
|
|
15
|
+
setPendingSummary: (value: ReasoningSummary | '') => void
|
|
16
|
+
pendingCwd: string
|
|
17
|
+
setPendingCwd: (value: string) => void
|
|
18
|
+
onApplyModel: () => void
|
|
19
|
+
showApprovalsDialog: boolean
|
|
20
|
+
onCloseApprovalsDialog: () => void
|
|
21
|
+
approvalOptions: Array<{ value: ApprovalPolicy; label: string; description: string }>
|
|
22
|
+
pendingApproval: ApprovalPolicy
|
|
23
|
+
setPendingApproval: (value: ApprovalPolicy) => void
|
|
24
|
+
onApplyApproval: () => void
|
|
25
|
+
showSkillsDialog: boolean
|
|
26
|
+
onCloseSkillsDialog: () => void
|
|
27
|
+
skillsLoading: boolean
|
|
28
|
+
skillsError: string | null
|
|
29
|
+
skillsList: Array<{ name: string; description: string; path: string }>
|
|
30
|
+
onSelectSkill: (name: string) => void
|
|
31
|
+
showResumeDialog: boolean
|
|
32
|
+
onCloseResumeDialog: () => void
|
|
33
|
+
resumeCandidates: Array<{ id: string; title: string; preview: string }>
|
|
34
|
+
onResumeThread: (threadId: string) => void
|
|
35
|
+
showFeedbackDialog: boolean
|
|
36
|
+
onCloseFeedbackDialog: () => void
|
|
37
|
+
feedbackCategory: string
|
|
38
|
+
setFeedbackCategory: (value: string) => void
|
|
39
|
+
feedbackReason: string
|
|
40
|
+
setFeedbackReason: (value: string) => void
|
|
41
|
+
feedbackIncludeLogs: boolean
|
|
42
|
+
setFeedbackIncludeLogs: (value: boolean) => void
|
|
43
|
+
onSendFeedback: () => void
|
|
44
|
+
showApiKeyPrompt: boolean
|
|
45
|
+
onCloseApiKeyPrompt: () => void
|
|
46
|
+
onApiKeySubmit: (value: string) => void
|
|
47
|
+
copyDialog: { open: boolean; url: string }
|
|
48
|
+
setCopyDialog: (state: { open: boolean; url: string }) => void
|
|
49
|
+
alertDialog: { open: boolean; title: string; message: string; variant: 'info' | 'warning' | 'error' }
|
|
50
|
+
setAlertDialog: (state: { open: boolean; title: string; message: string; variant: 'info' | 'warning' | 'error' }) => void
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const SessionDialogs = ({
|
|
54
|
+
showModelDialog,
|
|
55
|
+
onCloseModelDialog,
|
|
56
|
+
modelOptions,
|
|
57
|
+
pendingModelId,
|
|
58
|
+
setPendingModelId,
|
|
59
|
+
pendingEffortOptions,
|
|
60
|
+
pendingEffort,
|
|
61
|
+
setPendingEffort,
|
|
62
|
+
summaryOptions,
|
|
63
|
+
pendingSummary,
|
|
64
|
+
setPendingSummary,
|
|
65
|
+
pendingCwd,
|
|
66
|
+
setPendingCwd,
|
|
67
|
+
onApplyModel,
|
|
68
|
+
showApprovalsDialog,
|
|
69
|
+
onCloseApprovalsDialog,
|
|
70
|
+
approvalOptions,
|
|
71
|
+
pendingApproval,
|
|
72
|
+
setPendingApproval,
|
|
73
|
+
onApplyApproval,
|
|
74
|
+
showSkillsDialog,
|
|
75
|
+
onCloseSkillsDialog,
|
|
76
|
+
skillsLoading,
|
|
77
|
+
skillsError,
|
|
78
|
+
skillsList,
|
|
79
|
+
onSelectSkill,
|
|
80
|
+
showResumeDialog,
|
|
81
|
+
onCloseResumeDialog,
|
|
82
|
+
resumeCandidates,
|
|
83
|
+
onResumeThread,
|
|
84
|
+
showFeedbackDialog,
|
|
85
|
+
onCloseFeedbackDialog,
|
|
86
|
+
feedbackCategory,
|
|
87
|
+
setFeedbackCategory,
|
|
88
|
+
feedbackReason,
|
|
89
|
+
setFeedbackReason,
|
|
90
|
+
feedbackIncludeLogs,
|
|
91
|
+
setFeedbackIncludeLogs,
|
|
92
|
+
onSendFeedback,
|
|
93
|
+
showApiKeyPrompt,
|
|
94
|
+
onCloseApiKeyPrompt,
|
|
95
|
+
onApiKeySubmit,
|
|
96
|
+
copyDialog,
|
|
97
|
+
setCopyDialog,
|
|
98
|
+
alertDialog,
|
|
99
|
+
setAlertDialog,
|
|
100
|
+
}: SessionDialogsProps) => {
|
|
101
|
+
return (
|
|
102
|
+
<>
|
|
103
|
+
<Dialog open={showModelDialog} onClose={onCloseModelDialog} title="Model & Reasoning">
|
|
104
|
+
<div className="space-y-3">
|
|
105
|
+
<Select
|
|
106
|
+
options={modelOptions}
|
|
107
|
+
value={pendingModelId}
|
|
108
|
+
onChange={(value) => setPendingModelId(value)}
|
|
109
|
+
placeholder="Select model"
|
|
110
|
+
/>
|
|
111
|
+
{pendingEffortOptions.length > 0 && (
|
|
112
|
+
<Select
|
|
113
|
+
options={pendingEffortOptions}
|
|
114
|
+
value={pendingEffort || ''}
|
|
115
|
+
onChange={(value) => setPendingEffort(value as ReasoningEffort)}
|
|
116
|
+
placeholder="Effort"
|
|
117
|
+
/>
|
|
118
|
+
)}
|
|
119
|
+
<Select
|
|
120
|
+
options={summaryOptions}
|
|
121
|
+
value={pendingSummary || ''}
|
|
122
|
+
onChange={(value) => setPendingSummary(value as ReasoningSummary)}
|
|
123
|
+
placeholder="Summary"
|
|
124
|
+
/>
|
|
125
|
+
<div className="space-y-1">
|
|
126
|
+
<div className="text-[10px] uppercase tracking-[0.2em] text-text-muted">
|
|
127
|
+
Working directory
|
|
128
|
+
</div>
|
|
129
|
+
<input
|
|
130
|
+
value={pendingCwd}
|
|
131
|
+
onChange={(event) => setPendingCwd(event.target.value)}
|
|
132
|
+
placeholder="/path/to/repo"
|
|
133
|
+
className="w-full bg-bg-tertiary border border-border rounded-lg px-3 py-2 text-xs text-text-primary placeholder:text-text-muted outline-none focus:border-text-muted transition-colors"
|
|
134
|
+
/>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
<div className="flex justify-end gap-2 mt-4">
|
|
138
|
+
<Button variant="ghost" size="sm" onClick={onCloseModelDialog}>
|
|
139
|
+
Cancel
|
|
140
|
+
</Button>
|
|
141
|
+
<Button variant="primary" size="sm" onClick={onApplyModel}>
|
|
142
|
+
Apply
|
|
143
|
+
</Button>
|
|
144
|
+
</div>
|
|
145
|
+
</Dialog>
|
|
146
|
+
|
|
147
|
+
<Dialog open={showApprovalsDialog} onClose={onCloseApprovalsDialog} title="Approvals">
|
|
148
|
+
<div className="space-y-2">
|
|
149
|
+
{approvalOptions.map((option) => (
|
|
150
|
+
<button
|
|
151
|
+
key={option.value}
|
|
152
|
+
type="button"
|
|
153
|
+
onClick={() => setPendingApproval(option.value)}
|
|
154
|
+
className={`w-full text-left px-3 py-2 rounded-lg border transition-colors ${
|
|
155
|
+
pendingApproval === option.value
|
|
156
|
+
? 'border-text-muted bg-bg-elevated text-text-primary'
|
|
157
|
+
: 'border-border bg-bg-tertiary text-text-secondary hover:bg-bg-hover'
|
|
158
|
+
}`}
|
|
159
|
+
>
|
|
160
|
+
<div className="text-xs font-semibold">{option.label}</div>
|
|
161
|
+
<div className="text-[10px] text-text-muted mt-0.5">{option.description}</div>
|
|
162
|
+
</button>
|
|
163
|
+
))}
|
|
164
|
+
</div>
|
|
165
|
+
<div className="flex justify-end gap-2 mt-4">
|
|
166
|
+
<Button variant="ghost" size="sm" onClick={onCloseApprovalsDialog}>
|
|
167
|
+
Cancel
|
|
168
|
+
</Button>
|
|
169
|
+
<Button variant="primary" size="sm" onClick={onApplyApproval}>
|
|
170
|
+
Apply
|
|
171
|
+
</Button>
|
|
172
|
+
</div>
|
|
173
|
+
</Dialog>
|
|
174
|
+
|
|
175
|
+
<Dialog open={showSkillsDialog} onClose={onCloseSkillsDialog} title="Skills">
|
|
176
|
+
<div className="space-y-2 max-h-[240px] overflow-y-auto">
|
|
177
|
+
{skillsLoading && <div className="text-xs text-text-muted">Loading skills...</div>}
|
|
178
|
+
{skillsError && <div className="text-xs text-accent-red">{skillsError}</div>}
|
|
179
|
+
{!skillsLoading && !skillsError && skillsList.length === 0 && (
|
|
180
|
+
<div className="text-xs text-text-muted">No skills found.</div>
|
|
181
|
+
)}
|
|
182
|
+
{!skillsLoading && !skillsError && skillsList.map((skill) => (
|
|
183
|
+
<button
|
|
184
|
+
key={skill.path}
|
|
185
|
+
type="button"
|
|
186
|
+
onClick={() => onSelectSkill(skill.name)}
|
|
187
|
+
className="w-full text-left px-3 py-2 rounded-lg border border-border bg-bg-tertiary text-text-secondary hover:bg-bg-hover transition-colors"
|
|
188
|
+
>
|
|
189
|
+
<div className="text-xs font-semibold text-text-primary">{skill.name}</div>
|
|
190
|
+
<div className="text-[10px] text-text-muted mt-0.5">{skill.description}</div>
|
|
191
|
+
</button>
|
|
192
|
+
))}
|
|
193
|
+
</div>
|
|
194
|
+
</Dialog>
|
|
195
|
+
|
|
196
|
+
<Dialog open={showResumeDialog} onClose={onCloseResumeDialog} title="Resume Session">
|
|
197
|
+
<div className="space-y-2 max-h-[240px] overflow-y-auto">
|
|
198
|
+
{resumeCandidates.length === 0 && (
|
|
199
|
+
<div className="text-xs text-text-muted">No sessions available.</div>
|
|
200
|
+
)}
|
|
201
|
+
{resumeCandidates.map((thread) => (
|
|
202
|
+
<button
|
|
203
|
+
key={thread.id}
|
|
204
|
+
type="button"
|
|
205
|
+
onClick={() => onResumeThread(thread.id)}
|
|
206
|
+
className="w-full text-left px-3 py-2 rounded-lg border border-border bg-bg-tertiary text-text-secondary hover:bg-bg-hover transition-colors"
|
|
207
|
+
>
|
|
208
|
+
<div className="text-xs font-semibold text-text-primary truncate">{thread.title}</div>
|
|
209
|
+
<div className="text-[10px] text-text-muted mt-0.5 truncate">{thread.preview}</div>
|
|
210
|
+
</button>
|
|
211
|
+
))}
|
|
212
|
+
</div>
|
|
213
|
+
</Dialog>
|
|
214
|
+
|
|
215
|
+
<Dialog open={showFeedbackDialog} onClose={onCloseFeedbackDialog} title="Send Feedback">
|
|
216
|
+
<div className="space-y-3">
|
|
217
|
+
<Select
|
|
218
|
+
options={[
|
|
219
|
+
{ value: 'bug', label: 'Bug' },
|
|
220
|
+
{ value: 'feature', label: 'Feature request' },
|
|
221
|
+
{ value: 'ux', label: 'UX' },
|
|
222
|
+
{ value: 'other', label: 'Other' },
|
|
223
|
+
]}
|
|
224
|
+
value={feedbackCategory}
|
|
225
|
+
onChange={(value) => setFeedbackCategory(value)}
|
|
226
|
+
/>
|
|
227
|
+
<textarea
|
|
228
|
+
value={feedbackReason}
|
|
229
|
+
onChange={(event) => setFeedbackReason(event.target.value)}
|
|
230
|
+
rows={3}
|
|
231
|
+
placeholder="Describe the issue or suggestion..."
|
|
232
|
+
className="w-full bg-bg-tertiary border border-border rounded-lg px-3 py-2 text-sm text-text-primary placeholder:text-text-muted outline-none focus:border-text-muted transition-colors"
|
|
233
|
+
/>
|
|
234
|
+
<label className="flex items-center gap-2 text-xs text-text-muted">
|
|
235
|
+
<input
|
|
236
|
+
type="checkbox"
|
|
237
|
+
checked={feedbackIncludeLogs}
|
|
238
|
+
onChange={(event) => setFeedbackIncludeLogs(event.target.checked)}
|
|
239
|
+
className="accent-accent-green"
|
|
240
|
+
/>
|
|
241
|
+
Include logs
|
|
242
|
+
</label>
|
|
243
|
+
</div>
|
|
244
|
+
<div className="flex justify-end gap-2 mt-4">
|
|
245
|
+
<Button variant="ghost" size="sm" onClick={onCloseFeedbackDialog}>
|
|
246
|
+
Cancel
|
|
247
|
+
</Button>
|
|
248
|
+
<Button variant="primary" size="sm" onClick={onSendFeedback}>
|
|
249
|
+
Send
|
|
250
|
+
</Button>
|
|
251
|
+
</div>
|
|
252
|
+
</Dialog>
|
|
253
|
+
|
|
254
|
+
<PromptDialog
|
|
255
|
+
open={showApiKeyPrompt}
|
|
256
|
+
onClose={onCloseApiKeyPrompt}
|
|
257
|
+
onSubmit={onApiKeySubmit}
|
|
258
|
+
title="Use API Key"
|
|
259
|
+
placeholder="Paste OpenAI API key..."
|
|
260
|
+
submitLabel="Connect"
|
|
261
|
+
/>
|
|
262
|
+
|
|
263
|
+
<CopyDialog
|
|
264
|
+
open={copyDialog.open}
|
|
265
|
+
onClose={() => setCopyDialog({ open: false, url: '' })}
|
|
266
|
+
title="Sign In"
|
|
267
|
+
message="Open this URL in your browser to sign in to your OpenAI account:"
|
|
268
|
+
copyText={copyDialog.url}
|
|
269
|
+
/>
|
|
270
|
+
|
|
271
|
+
<AlertDialog
|
|
272
|
+
open={alertDialog.open}
|
|
273
|
+
onClose={() => setAlertDialog({ ...alertDialog, open: false })}
|
|
274
|
+
title={alertDialog.title}
|
|
275
|
+
message={alertDialog.message}
|
|
276
|
+
variant={alertDialog.variant}
|
|
277
|
+
/>
|
|
278
|
+
</>
|
|
279
|
+
)
|
|
280
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
import { Button, Icons } from '../ui'
|
|
3
|
+
import { STARTUP_FRAMES, STARTUP_FRAME_TICK_MS } from '../loading/startup-ascii'
|
|
4
|
+
import { useAppStore } from '../../store'
|
|
5
|
+
|
|
6
|
+
interface SessionEmptyProps {
|
|
7
|
+
onNewSession?: () => void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const SessionEmpty = ({ onNewSession }: SessionEmptyProps) => {
|
|
11
|
+
const [frameIndex, setFrameIndex] = useState(0)
|
|
12
|
+
const { setMobileThreadListOpen } = useAppStore()
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const intervalId = window.setInterval(() => {
|
|
16
|
+
setFrameIndex((current) => (current + 1) % STARTUP_FRAMES.length)
|
|
17
|
+
}, STARTUP_FRAME_TICK_MS)
|
|
18
|
+
return () => window.clearInterval(intervalId)
|
|
19
|
+
}, [])
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<main className="flex-1 flex flex-col items-center justify-center px-4 md:px-6 bg-bg-primary">
|
|
23
|
+
<pre className="whitespace-pre font-mono text-[9px] sm:text-[11px] leading-tight text-text-secondary mb-5 overflow-hidden max-w-full">
|
|
24
|
+
{STARTUP_FRAMES[frameIndex]}
|
|
25
|
+
</pre>
|
|
26
|
+
<h2 className="text-base sm:text-lg font-semibold text-text-primary mb-2 text-center">Select a session</h2>
|
|
27
|
+
<p className="text-xs text-text-muted text-center max-w-xs mb-5 leading-relaxed">
|
|
28
|
+
Choose a session from the list to view the conversation, or start a new one to begin coding.
|
|
29
|
+
</p>
|
|
30
|
+
<div className="flex flex-col sm:flex-row gap-2">
|
|
31
|
+
<Button
|
|
32
|
+
variant="ghost"
|
|
33
|
+
size="lg"
|
|
34
|
+
onClick={() => setMobileThreadListOpen(true)}
|
|
35
|
+
className="md:hidden"
|
|
36
|
+
>
|
|
37
|
+
<Icons.List className="w-4 h-4" />
|
|
38
|
+
View Sessions
|
|
39
|
+
</Button>
|
|
40
|
+
<Button variant="primary" size="lg" onClick={onNewSession}>
|
|
41
|
+
<Icons.Plus className="w-4 h-4" />
|
|
42
|
+
New Session
|
|
43
|
+
</Button>
|
|
44
|
+
</div>
|
|
45
|
+
</main>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { IconButton, Icons } from '../ui'
|
|
2
|
+
|
|
3
|
+
interface SessionHeaderProps {
|
|
4
|
+
title: string
|
|
5
|
+
accountName?: string
|
|
6
|
+
model?: string
|
|
7
|
+
status?: string
|
|
8
|
+
canInteract: boolean
|
|
9
|
+
onArchive: () => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const SessionHeader = ({
|
|
13
|
+
title,
|
|
14
|
+
accountName,
|
|
15
|
+
model,
|
|
16
|
+
status,
|
|
17
|
+
canInteract,
|
|
18
|
+
onArchive,
|
|
19
|
+
}: SessionHeaderProps) => {
|
|
20
|
+
const isActive = status === 'active'
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<header className="hidden md:flex px-4 py-3 border-b border-border items-center justify-between shrink-0 gap-4">
|
|
24
|
+
<div className="min-w-0 flex-1 overflow-hidden">
|
|
25
|
+
<h2 className="text-sm font-semibold text-text-primary truncate">{title}</h2>
|
|
26
|
+
<div className="flex items-center gap-2 mt-0.5 text-[10px] text-text-muted">
|
|
27
|
+
<span className="truncate max-w-[100px]">{accountName || 'Unknown account'}</span>
|
|
28
|
+
<span>·</span>
|
|
29
|
+
<span>{model || 'unknown'}</span>
|
|
30
|
+
<span>·</span>
|
|
31
|
+
<span className={`flex items-center gap-1 ${isActive ? 'text-accent-green' : ''}`}>
|
|
32
|
+
{isActive && <span className="w-1.5 h-1.5 rounded-full bg-accent-green animate-pulse" />}
|
|
33
|
+
{status || 'idle'}
|
|
34
|
+
</span>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
<div className="flex items-center gap-2 shrink-0">
|
|
38
|
+
<IconButton icon={<Icons.Copy className="w-4 h-4 text-text-muted" />} size="sm" />
|
|
39
|
+
<IconButton
|
|
40
|
+
icon={<Icons.Archive className="w-4 h-4 text-text-muted" />}
|
|
41
|
+
size="sm"
|
|
42
|
+
disabled={!canInteract}
|
|
43
|
+
onClick={onArchive}
|
|
44
|
+
/>
|
|
45
|
+
<IconButton icon={<Icons.MoreVertical className="w-4 h-4 text-text-muted" />} size="sm" />
|
|
46
|
+
</div>
|
|
47
|
+
</header>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface AvatarProps {
|
|
2
|
+
name: string
|
|
3
|
+
size?: 'sm' | 'md' | 'lg'
|
|
4
|
+
className?: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function Avatar({ name, size = 'md', className = '' }: AvatarProps) {
|
|
8
|
+
const sizeStyles = {
|
|
9
|
+
sm: 'w-6 h-6 text-xs',
|
|
10
|
+
md: 'w-8 h-8 text-sm',
|
|
11
|
+
lg: 'w-10 h-10 text-base',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div className={`rounded-full bg-bg-tertiary flex items-center justify-center font-medium text-text-primary ${sizeStyles[size]} ${className}`}>
|
|
16
|
+
{name[0].toUpperCase()}
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
interface BadgeProps {
|
|
4
|
+
children: ReactNode
|
|
5
|
+
variant?: 'default' | 'success' | 'warning' | 'error'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function Badge({ children, variant = 'default' }: BadgeProps) {
|
|
9
|
+
const variantStyles = {
|
|
10
|
+
default: 'bg-bg-elevated text-text-secondary border-border',
|
|
11
|
+
success: 'bg-accent-green/15 text-accent-green border-accent-green/20',
|
|
12
|
+
warning: 'bg-yellow-500/15 text-yellow-500 border-yellow-500/20',
|
|
13
|
+
error: 'bg-accent-red/15 text-accent-red border-accent-red/20',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border ${variantStyles[variant]}`}>
|
|
18
|
+
{children}
|
|
19
|
+
</span>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
interface ButtonProps {
|
|
4
|
+
children: ReactNode
|
|
5
|
+
onClick?: () => void
|
|
6
|
+
variant?: 'primary' | 'secondary' | 'ghost' | 'danger'
|
|
7
|
+
size?: 'sm' | 'md' | 'lg'
|
|
8
|
+
className?: string
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
fullWidth?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function Button({
|
|
14
|
+
children,
|
|
15
|
+
onClick,
|
|
16
|
+
variant = 'secondary',
|
|
17
|
+
size = 'md',
|
|
18
|
+
className = '',
|
|
19
|
+
disabled = false,
|
|
20
|
+
fullWidth = false,
|
|
21
|
+
}: ButtonProps) {
|
|
22
|
+
const baseStyles =
|
|
23
|
+
'inline-flex items-center justify-center gap-2 font-medium transition-colors rounded-lg disabled:opacity-50 disabled:cursor-not-allowed'
|
|
24
|
+
|
|
25
|
+
const variantStyles = {
|
|
26
|
+
primary: 'bg-accent-green text-black hover:bg-accent-green/90',
|
|
27
|
+
secondary: 'bg-bg-elevated border border-border text-text-secondary hover:bg-bg-hover',
|
|
28
|
+
ghost: 'text-text-muted hover:text-text-secondary hover:bg-bg-hover',
|
|
29
|
+
danger: 'bg-accent-red text-white hover:bg-accent-red/90',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const sizeStyles = {
|
|
33
|
+
sm: 'px-2.5 py-1 text-xs',
|
|
34
|
+
md: 'px-3 py-1.5 text-sm',
|
|
35
|
+
lg: 'px-4 py-2 text-sm',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<button
|
|
40
|
+
onClick={onClick}
|
|
41
|
+
disabled={disabled}
|
|
42
|
+
className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${fullWidth ? 'w-full' : ''} ${className}`}
|
|
43
|
+
>
|
|
44
|
+
{children}
|
|
45
|
+
</button>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { useState, useRef, useEffect } from 'react'
|
|
2
|
+
import { Icons } from './icons'
|
|
3
|
+
|
|
4
|
+
interface CollapsibleContentProps {
|
|
5
|
+
children: React.ReactNode
|
|
6
|
+
maxHeight?: number
|
|
7
|
+
className?: string
|
|
8
|
+
showLineCount?: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function CollapsibleContent({
|
|
12
|
+
children,
|
|
13
|
+
maxHeight = 200,
|
|
14
|
+
className = '',
|
|
15
|
+
showLineCount = true,
|
|
16
|
+
}: CollapsibleContentProps) {
|
|
17
|
+
const [isExpanded, setIsExpanded] = useState(false)
|
|
18
|
+
const [needsCollapse, setNeedsCollapse] = useState(false)
|
|
19
|
+
const [lineCount, setLineCount] = useState(0)
|
|
20
|
+
const contentRef = useRef<HTMLDivElement>(null)
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (contentRef.current) {
|
|
24
|
+
const height = contentRef.current.scrollHeight
|
|
25
|
+
setNeedsCollapse(height > maxHeight)
|
|
26
|
+
|
|
27
|
+
const text = contentRef.current.textContent || ''
|
|
28
|
+
const lines = text.split('\n').length
|
|
29
|
+
setLineCount(lines)
|
|
30
|
+
}
|
|
31
|
+
}, [children, maxHeight])
|
|
32
|
+
|
|
33
|
+
if (!needsCollapse) {
|
|
34
|
+
return <div className={className}>{children}</div>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div className={className}>
|
|
39
|
+
<div
|
|
40
|
+
ref={contentRef}
|
|
41
|
+
className="relative overflow-hidden transition-[max-height] duration-300 ease-in-out"
|
|
42
|
+
style={{ maxHeight: isExpanded ? 'none' : maxHeight }}
|
|
43
|
+
>
|
|
44
|
+
{children}
|
|
45
|
+
{!isExpanded && (
|
|
46
|
+
<div className="absolute bottom-0 left-0 right-0 h-12 bg-gradient-to-t from-bg-tertiary to-transparent pointer-events-none" />
|
|
47
|
+
)}
|
|
48
|
+
</div>
|
|
49
|
+
<button
|
|
50
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
51
|
+
className="flex items-center gap-1.5 mt-2 text-xs text-text-muted hover:text-text-primary transition-colors group"
|
|
52
|
+
>
|
|
53
|
+
<Icons.ChevronDown
|
|
54
|
+
className={`w-3 h-3 transition-transform duration-200 ${isExpanded ? 'rotate-180' : ''}`}
|
|
55
|
+
/>
|
|
56
|
+
<span>
|
|
57
|
+
{isExpanded ? 'Collapse' : 'Expand'}
|
|
58
|
+
{showLineCount && lineCount > 0 && (
|
|
59
|
+
<span className="text-text-muted/60 ml-1">({lineCount} lines)</span>
|
|
60
|
+
)}
|
|
61
|
+
</span>
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface CollapsibleCodeBlockProps {
|
|
68
|
+
code: string
|
|
69
|
+
language?: string
|
|
70
|
+
maxLines?: number
|
|
71
|
+
className?: string
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function CollapsibleCodeBlock({
|
|
75
|
+
code,
|
|
76
|
+
language,
|
|
77
|
+
maxLines = 15,
|
|
78
|
+
className = '',
|
|
79
|
+
}: CollapsibleCodeBlockProps) {
|
|
80
|
+
const [isExpanded, setIsExpanded] = useState(false)
|
|
81
|
+
const lines = code.split('\n')
|
|
82
|
+
const needsCollapse = lines.length > maxLines
|
|
83
|
+
const visibleCode = needsCollapse && !isExpanded
|
|
84
|
+
? lines.slice(0, maxLines).join('\n')
|
|
85
|
+
: code
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div className={className}>
|
|
89
|
+
<div className="relative">
|
|
90
|
+
<pre className="text-xs font-mono whitespace-pre-wrap leading-relaxed break-words overflow-wrap-anywhere">
|
|
91
|
+
<code className={language ? `language-${language}` : ''}>
|
|
92
|
+
{visibleCode}
|
|
93
|
+
</code>
|
|
94
|
+
</pre>
|
|
95
|
+
{needsCollapse && !isExpanded && (
|
|
96
|
+
<div className="absolute bottom-0 left-0 right-0 h-8 bg-gradient-to-t from-bg-primary to-transparent pointer-events-none" />
|
|
97
|
+
)}
|
|
98
|
+
</div>
|
|
99
|
+
{needsCollapse && (
|
|
100
|
+
<button
|
|
101
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
102
|
+
className="flex items-center gap-1.5 mt-2 text-xs text-text-muted hover:text-text-primary transition-colors"
|
|
103
|
+
>
|
|
104
|
+
<Icons.ChevronDown
|
|
105
|
+
className={`w-3 h-3 transition-transform duration-200 ${isExpanded ? 'rotate-180' : ''}`}
|
|
106
|
+
/>
|
|
107
|
+
<span>
|
|
108
|
+
{isExpanded ? 'Show less' : `Show ${lines.length - maxLines} more lines`}
|
|
109
|
+
</span>
|
|
110
|
+
</button>
|
|
111
|
+
)}
|
|
112
|
+
</div>
|
|
113
|
+
)
|
|
114
|
+
}
|