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,182 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
import type { DailyDataPoint } from '../../hooks/use-analytics'
|
|
3
|
+
|
|
4
|
+
interface ContributionGraphProps {
|
|
5
|
+
data: DailyDataPoint[]
|
|
6
|
+
days?: number
|
|
7
|
+
label?: string
|
|
8
|
+
colorScheme?: 'green' | 'blue' | 'purple'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const COLOR_SCHEMES = {
|
|
12
|
+
green: ['bg-bg-elevated', 'bg-emerald-900/50', 'bg-emerald-700/70', 'bg-emerald-500/80', 'bg-emerald-400'],
|
|
13
|
+
blue: ['bg-bg-elevated', 'bg-blue-900/50', 'bg-blue-700/70', 'bg-blue-500/80', 'bg-blue-400'],
|
|
14
|
+
purple: ['bg-bg-elevated', 'bg-purple-900/50', 'bg-purple-700/70', 'bg-purple-500/80', 'bg-purple-400'],
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
|
18
|
+
const DAYS = ['', 'Mon', '', 'Wed', '', 'Fri', '']
|
|
19
|
+
|
|
20
|
+
export function ContributionGraph({
|
|
21
|
+
data,
|
|
22
|
+
days = 365,
|
|
23
|
+
label = 'contributions',
|
|
24
|
+
colorScheme = 'green'
|
|
25
|
+
}: ContributionGraphProps) {
|
|
26
|
+
const { grid, monthLabels, totalCount, maxCount } = useMemo(() => {
|
|
27
|
+
const dataMap = new Map<string, number>()
|
|
28
|
+
for (const point of data) {
|
|
29
|
+
dataMap.set(point.date, point.count)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const today = new Date()
|
|
33
|
+
const endDate = new Date(today.getFullYear(), today.getMonth(), today.getDate())
|
|
34
|
+
const startDate = new Date(endDate)
|
|
35
|
+
startDate.setDate(startDate.getDate() - days + 1)
|
|
36
|
+
|
|
37
|
+
const dayOfWeek = startDate.getDay()
|
|
38
|
+
startDate.setDate(startDate.getDate() - dayOfWeek)
|
|
39
|
+
|
|
40
|
+
const weeks: Array<Array<{ date: string; count: number; isInRange: boolean }>> = []
|
|
41
|
+
const monthLabels: Array<{ label: string; weekIndex: number }> = []
|
|
42
|
+
let currentDate = new Date(startDate)
|
|
43
|
+
let lastMonth = -1
|
|
44
|
+
let totalCount = 0
|
|
45
|
+
let maxCount = 0
|
|
46
|
+
|
|
47
|
+
while (currentDate <= endDate) {
|
|
48
|
+
const week: Array<{ date: string; count: number; isInRange: boolean }> = []
|
|
49
|
+
|
|
50
|
+
for (let d = 0; d < 7; d++) {
|
|
51
|
+
const dateKey = formatDate(currentDate)
|
|
52
|
+
const count = dataMap.get(dateKey) ?? 0
|
|
53
|
+
const isInRange = currentDate >= startDate && currentDate <= endDate
|
|
54
|
+
|
|
55
|
+
if (isInRange && currentDate.getMonth() !== lastMonth) {
|
|
56
|
+
monthLabels.push({ label: MONTHS[currentDate.getMonth()], weekIndex: weeks.length })
|
|
57
|
+
lastMonth = currentDate.getMonth()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
week.push({ date: dateKey, count, isInRange })
|
|
61
|
+
|
|
62
|
+
if (isInRange) {
|
|
63
|
+
totalCount += count
|
|
64
|
+
maxCount = Math.max(maxCount, count)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
currentDate.setDate(currentDate.getDate() + 1)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
weeks.push(week)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { grid: weeks, monthLabels, totalCount, maxCount }
|
|
74
|
+
}, [data, days])
|
|
75
|
+
|
|
76
|
+
const colors = COLOR_SCHEMES[colorScheme]
|
|
77
|
+
|
|
78
|
+
const getColorLevel = (count: number): number => {
|
|
79
|
+
if (count === 0) return 0
|
|
80
|
+
if (maxCount === 0) return 0
|
|
81
|
+
const ratio = count / maxCount
|
|
82
|
+
if (ratio <= 0.25) return 1
|
|
83
|
+
if (ratio <= 0.5) return 2
|
|
84
|
+
if (ratio <= 0.75) return 3
|
|
85
|
+
return 4
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<div className="space-y-2">
|
|
90
|
+
<div className="flex items-center justify-between">
|
|
91
|
+
<span className="text-sm text-text-primary font-medium">
|
|
92
|
+
{totalCount.toLocaleString()} {label} in the last {days === 365 ? 'year' : `${days} days`}
|
|
93
|
+
</span>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div className="overflow-x-auto">
|
|
97
|
+
<div className="inline-block">
|
|
98
|
+
<div className="flex text-[10px] text-text-muted mb-1 pl-7">
|
|
99
|
+
{monthLabels.map((month, i) => (
|
|
100
|
+
<div
|
|
101
|
+
key={i}
|
|
102
|
+
className="absolute"
|
|
103
|
+
style={{ marginLeft: `${month.weekIndex * 12}px` }}
|
|
104
|
+
>
|
|
105
|
+
{month.label}
|
|
106
|
+
</div>
|
|
107
|
+
))}
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div className="flex gap-0.5 relative mt-4">
|
|
111
|
+
<div className="flex flex-col gap-0.5 text-[10px] text-text-muted pr-1 w-6">
|
|
112
|
+
{DAYS.map((day, i) => (
|
|
113
|
+
<div key={i} className="h-[10px] flex items-center justify-end">
|
|
114
|
+
{day}
|
|
115
|
+
</div>
|
|
116
|
+
))}
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
{grid.map((week, weekIndex) => (
|
|
120
|
+
<div key={weekIndex} className="flex flex-col gap-0.5">
|
|
121
|
+
{week.map((day, dayIndex) => (
|
|
122
|
+
<div
|
|
123
|
+
key={dayIndex}
|
|
124
|
+
className={`w-[10px] h-[10px] rounded-sm ${
|
|
125
|
+
day.isInRange ? colors[getColorLevel(day.count)] : 'bg-transparent'
|
|
126
|
+
}`}
|
|
127
|
+
title={day.isInRange ? `${day.date}: ${day.count} ${label}` : undefined}
|
|
128
|
+
/>
|
|
129
|
+
))}
|
|
130
|
+
</div>
|
|
131
|
+
))}
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<div className="flex items-center justify-end gap-1 mt-2 text-[10px] text-text-muted">
|
|
135
|
+
<span>Less</span>
|
|
136
|
+
{colors.map((color, i) => (
|
|
137
|
+
<div key={i} className={`w-[10px] h-[10px] rounded-sm ${color}`} />
|
|
138
|
+
))}
|
|
139
|
+
<span>More</span>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function formatDate(date: Date): string {
|
|
148
|
+
const year = date.getFullYear()
|
|
149
|
+
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
150
|
+
const day = String(date.getDate()).padStart(2, '0')
|
|
151
|
+
return `${year}-${month}-${day}`
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
interface StatCardProps {
|
|
155
|
+
label: string
|
|
156
|
+
value: number | string
|
|
157
|
+
change?: number
|
|
158
|
+
icon?: React.ReactNode
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function StatCard({ label, value, change, icon }: StatCardProps) {
|
|
162
|
+
return (
|
|
163
|
+
<div className="bg-bg-elevated border border-border rounded-lg p-4">
|
|
164
|
+
<div className="flex items-start justify-between">
|
|
165
|
+
<div>
|
|
166
|
+
<p className="text-xs text-text-muted mb-1">{label}</p>
|
|
167
|
+
<p className="text-2xl font-semibold text-text-primary">{value}</p>
|
|
168
|
+
{change !== undefined && (
|
|
169
|
+
<p className={`text-xs mt-1 ${change >= 0 ? 'text-success' : 'text-error'}`}>
|
|
170
|
+
{change >= 0 ? '+' : ''}{change}% from last period
|
|
171
|
+
</p>
|
|
172
|
+
)}
|
|
173
|
+
</div>
|
|
174
|
+
{icon && (
|
|
175
|
+
<div className="p-2 bg-bg-hover rounded-lg text-text-muted">
|
|
176
|
+
{icon}
|
|
177
|
+
</div>
|
|
178
|
+
)}
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { useEffect, useRef, type ReactNode } from 'react'
|
|
2
|
+
import { Icons } from './icons'
|
|
3
|
+
import { Button } from './button'
|
|
4
|
+
|
|
5
|
+
interface DialogProps {
|
|
6
|
+
open: boolean
|
|
7
|
+
onClose: () => void
|
|
8
|
+
title?: string
|
|
9
|
+
children: ReactNode
|
|
10
|
+
size?: 'small' | 'medium' | 'large'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function Dialog({ open, onClose, title, children, size = 'medium' }: DialogProps) {
|
|
14
|
+
const dialogRef = useRef<HTMLDivElement>(null)
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (!open) return
|
|
18
|
+
|
|
19
|
+
const handleEscape = (e: KeyboardEvent) => {
|
|
20
|
+
if (e.key === 'Escape') onClose()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
document.addEventListener('keydown', handleEscape)
|
|
24
|
+
document.body.style.overflow = 'hidden'
|
|
25
|
+
|
|
26
|
+
return () => {
|
|
27
|
+
document.removeEventListener('keydown', handleEscape)
|
|
28
|
+
document.body.style.overflow = ''
|
|
29
|
+
}
|
|
30
|
+
}, [open, onClose])
|
|
31
|
+
|
|
32
|
+
if (!open) return null
|
|
33
|
+
|
|
34
|
+
const sizeClasses = {
|
|
35
|
+
small: 'max-w-md',
|
|
36
|
+
medium: 'max-w-lg',
|
|
37
|
+
large: 'max-w-4xl',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6">
|
|
42
|
+
<div
|
|
43
|
+
className="absolute inset-0 bg-black/60 backdrop-blur-sm"
|
|
44
|
+
onClick={onClose}
|
|
45
|
+
/>
|
|
46
|
+
|
|
47
|
+
<div
|
|
48
|
+
ref={dialogRef}
|
|
49
|
+
role="dialog"
|
|
50
|
+
aria-modal="true"
|
|
51
|
+
className={`relative bg-bg-secondary border border-border rounded-xl shadow-2xl w-full ${sizeClasses[size]} max-h-[85vh] overflow-y-auto touch-scroll`}
|
|
52
|
+
>
|
|
53
|
+
{title && (
|
|
54
|
+
<div className="flex items-center justify-between px-4 py-3 border-b border-border">
|
|
55
|
+
<h2 className="text-sm font-semibold text-text-primary">{title}</h2>
|
|
56
|
+
<button
|
|
57
|
+
onClick={onClose}
|
|
58
|
+
className="p-1 rounded-md hover:bg-bg-hover transition-colors"
|
|
59
|
+
>
|
|
60
|
+
<Icons.X className="w-4 h-4 text-text-muted" />
|
|
61
|
+
</button>
|
|
62
|
+
</div>
|
|
63
|
+
)}
|
|
64
|
+
{!title && (
|
|
65
|
+
<button
|
|
66
|
+
onClick={onClose}
|
|
67
|
+
className="absolute top-3 right-3 z-10 p-1 rounded-md hover:bg-bg-hover transition-colors"
|
|
68
|
+
>
|
|
69
|
+
<Icons.X className="w-4 h-4 text-text-muted" />
|
|
70
|
+
</button>
|
|
71
|
+
)}
|
|
72
|
+
|
|
73
|
+
<div className={title ? 'p-4' : ''}>{children}</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface AlertDialogProps {
|
|
80
|
+
open: boolean
|
|
81
|
+
onClose: () => void
|
|
82
|
+
title: string
|
|
83
|
+
message: string
|
|
84
|
+
variant?: 'info' | 'warning' | 'error'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function AlertDialog({ open, onClose, title, message, variant = 'info' }: AlertDialogProps) {
|
|
88
|
+
const iconColors = {
|
|
89
|
+
info: 'text-accent-blue bg-accent-blue/10',
|
|
90
|
+
warning: 'text-yellow-500 bg-yellow-500/10',
|
|
91
|
+
error: 'text-accent-red bg-accent-red/10',
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<Dialog open={open} onClose={onClose} title={title}>
|
|
96
|
+
<div className="flex gap-3">
|
|
97
|
+
<div className={`shrink-0 w-10 h-10 rounded-lg flex items-center justify-center ${iconColors[variant]}`}>
|
|
98
|
+
<Icons.Warning className="w-5 h-5" />
|
|
99
|
+
</div>
|
|
100
|
+
<div className="flex-1">
|
|
101
|
+
<p className="text-sm text-text-secondary leading-relaxed mb-4">{message}</p>
|
|
102
|
+
<div className="flex justify-end">
|
|
103
|
+
<Button variant="primary" size="sm" onClick={onClose}>
|
|
104
|
+
OK
|
|
105
|
+
</Button>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</Dialog>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
interface PromptDialogProps {
|
|
114
|
+
open: boolean
|
|
115
|
+
onClose: () => void
|
|
116
|
+
onSubmit: (value: string) => void
|
|
117
|
+
title: string
|
|
118
|
+
placeholder?: string
|
|
119
|
+
submitLabel?: string
|
|
120
|
+
defaultValue?: string
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function PromptDialog({
|
|
124
|
+
open,
|
|
125
|
+
onClose,
|
|
126
|
+
onSubmit,
|
|
127
|
+
title,
|
|
128
|
+
placeholder = '',
|
|
129
|
+
submitLabel = 'Submit',
|
|
130
|
+
defaultValue = '',
|
|
131
|
+
}: PromptDialogProps) {
|
|
132
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
133
|
+
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
if (open && inputRef.current) {
|
|
136
|
+
inputRef.current.focus()
|
|
137
|
+
inputRef.current.value = defaultValue
|
|
138
|
+
}
|
|
139
|
+
}, [open, defaultValue])
|
|
140
|
+
|
|
141
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
142
|
+
e.preventDefault()
|
|
143
|
+
const value = inputRef.current?.value.trim()
|
|
144
|
+
if (value) {
|
|
145
|
+
onSubmit(value)
|
|
146
|
+
onClose()
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<Dialog open={open} onClose={onClose} title={title}>
|
|
152
|
+
<form onSubmit={handleSubmit}>
|
|
153
|
+
<input
|
|
154
|
+
ref={inputRef}
|
|
155
|
+
type="text"
|
|
156
|
+
placeholder={placeholder}
|
|
157
|
+
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 mb-4"
|
|
158
|
+
/>
|
|
159
|
+
<div className="flex justify-end gap-2">
|
|
160
|
+
<Button variant="ghost" size="sm" onClick={onClose}>
|
|
161
|
+
Cancel
|
|
162
|
+
</Button>
|
|
163
|
+
<Button variant="primary" size="sm">
|
|
164
|
+
{submitLabel}
|
|
165
|
+
</Button>
|
|
166
|
+
</div>
|
|
167
|
+
</form>
|
|
168
|
+
</Dialog>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
interface CopyDialogProps {
|
|
173
|
+
open: boolean
|
|
174
|
+
onClose: () => void
|
|
175
|
+
title: string
|
|
176
|
+
message: string
|
|
177
|
+
copyText: string
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function CopyDialog({ open, onClose, title, message, copyText }: CopyDialogProps) {
|
|
181
|
+
const handleCopy = async () => {
|
|
182
|
+
await navigator.clipboard.writeText(copyText)
|
|
183
|
+
onClose()
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return (
|
|
187
|
+
<Dialog open={open} onClose={onClose} title={title}>
|
|
188
|
+
<p className="text-sm text-text-secondary leading-relaxed mb-3">{message}</p>
|
|
189
|
+
<div className="bg-bg-primary border border-border rounded-lg p-3 mb-4">
|
|
190
|
+
<code className="text-xs text-accent-blue break-all">{copyText}</code>
|
|
191
|
+
</div>
|
|
192
|
+
<div className="flex justify-end gap-2">
|
|
193
|
+
<Button variant="ghost" size="sm" onClick={onClose}>
|
|
194
|
+
Close
|
|
195
|
+
</Button>
|
|
196
|
+
<Button variant="primary" size="sm" onClick={handleCopy}>
|
|
197
|
+
<Icons.Copy className="w-3.5 h-3.5" />
|
|
198
|
+
Copy URL
|
|
199
|
+
</Button>
|
|
200
|
+
</div>
|
|
201
|
+
</Dialog>
|
|
202
|
+
)
|
|
203
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ReactNode, MouseEvent } from 'react'
|
|
2
|
+
|
|
3
|
+
export interface IconButtonProps {
|
|
4
|
+
icon: ReactNode
|
|
5
|
+
onClick?: (e?: MouseEvent<HTMLButtonElement>) => void
|
|
6
|
+
className?: string
|
|
7
|
+
size?: 'sm' | 'md'
|
|
8
|
+
disabled?: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function IconButton({
|
|
12
|
+
icon,
|
|
13
|
+
onClick,
|
|
14
|
+
className = '',
|
|
15
|
+
size = 'md',
|
|
16
|
+
disabled = false,
|
|
17
|
+
}: IconButtonProps) {
|
|
18
|
+
const sizeStyles = {
|
|
19
|
+
sm: 'p-1.5',
|
|
20
|
+
md: 'p-2',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<button
|
|
25
|
+
onClick={onClick}
|
|
26
|
+
disabled={disabled}
|
|
27
|
+
className={`rounded-lg transition-colors ${sizeStyles[size]} ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-bg-hover'} ${className}`}
|
|
28
|
+
>
|
|
29
|
+
{icon}
|
|
30
|
+
</button>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
interface IconProps {
|
|
2
|
+
className?: string
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export const Icons = {
|
|
6
|
+
Plus: ({ className }: IconProps) => (
|
|
7
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
8
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M12 4v16m8-8H4" />
|
|
9
|
+
</svg>
|
|
10
|
+
),
|
|
11
|
+
|
|
12
|
+
Search: ({ className }: IconProps) => (
|
|
13
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
14
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
15
|
+
</svg>
|
|
16
|
+
),
|
|
17
|
+
|
|
18
|
+
Settings: ({ className }: IconProps) => (
|
|
19
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
20
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
|
21
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
22
|
+
</svg>
|
|
23
|
+
),
|
|
24
|
+
|
|
25
|
+
Help: ({ className }: IconProps) => (
|
|
26
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
27
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
28
|
+
</svg>
|
|
29
|
+
),
|
|
30
|
+
|
|
31
|
+
Grid: ({ className }: IconProps) => (
|
|
32
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
33
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
|
|
34
|
+
</svg>
|
|
35
|
+
),
|
|
36
|
+
|
|
37
|
+
Clipboard: ({ className }: IconProps) => (
|
|
38
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
39
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
|
|
40
|
+
</svg>
|
|
41
|
+
),
|
|
42
|
+
|
|
43
|
+
Archive: ({ className }: IconProps) => (
|
|
44
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
45
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4" />
|
|
46
|
+
</svg>
|
|
47
|
+
),
|
|
48
|
+
|
|
49
|
+
Bolt: ({ className }: IconProps) => (
|
|
50
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
51
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M13 10V3L4 14h7v7l9-11h-7z" />
|
|
52
|
+
</svg>
|
|
53
|
+
),
|
|
54
|
+
|
|
55
|
+
BarChart: ({ className }: IconProps) => (
|
|
56
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
57
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
|
58
|
+
</svg>
|
|
59
|
+
),
|
|
60
|
+
|
|
61
|
+
ChevronDown: ({ className }: IconProps) => (
|
|
62
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
63
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
64
|
+
</svg>
|
|
65
|
+
),
|
|
66
|
+
|
|
67
|
+
ChevronUp: ({ className }: IconProps) => (
|
|
68
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
69
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 15l7-7 7 7" />
|
|
70
|
+
</svg>
|
|
71
|
+
),
|
|
72
|
+
|
|
73
|
+
Copy: ({ className }: IconProps) => (
|
|
74
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
75
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
|
|
76
|
+
</svg>
|
|
77
|
+
),
|
|
78
|
+
|
|
79
|
+
MoreVertical: ({ className }: IconProps) => (
|
|
80
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
81
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
|
|
82
|
+
</svg>
|
|
83
|
+
),
|
|
84
|
+
|
|
85
|
+
Paperclip: ({ className }: IconProps) => (
|
|
86
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
87
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13" />
|
|
88
|
+
</svg>
|
|
89
|
+
),
|
|
90
|
+
|
|
91
|
+
Microphone: ({ className }: IconProps) => (
|
|
92
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
93
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" />
|
|
94
|
+
</svg>
|
|
95
|
+
),
|
|
96
|
+
|
|
97
|
+
Send: ({ className }: IconProps) => (
|
|
98
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
99
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 10l7-7m0 0l7 7m-7-7v18" />
|
|
100
|
+
</svg>
|
|
101
|
+
),
|
|
102
|
+
|
|
103
|
+
Warning: ({ className }: IconProps) => (
|
|
104
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
105
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
106
|
+
</svg>
|
|
107
|
+
),
|
|
108
|
+
|
|
109
|
+
Check: ({ className }: IconProps) => (
|
|
110
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
111
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
112
|
+
</svg>
|
|
113
|
+
),
|
|
114
|
+
|
|
115
|
+
X: ({ className }: IconProps) => (
|
|
116
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
117
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
118
|
+
</svg>
|
|
119
|
+
),
|
|
120
|
+
|
|
121
|
+
Trash: ({ className }: IconProps) => (
|
|
122
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
123
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M6 7h12M9 7V5a1 1 0 011-1h4a1 1 0 011 1v2m-7 0l1 12a1 1 0 001 1h4a1 1 0 001-1l1-12" />
|
|
124
|
+
</svg>
|
|
125
|
+
),
|
|
126
|
+
|
|
127
|
+
ArrowUp: ({ className }: IconProps) => (
|
|
128
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
129
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 10l7-7m0 0l7 7m-7-7v18" />
|
|
130
|
+
</svg>
|
|
131
|
+
),
|
|
132
|
+
|
|
133
|
+
Loader: ({ className }: IconProps) => (
|
|
134
|
+
<svg className={`animate-spin ${className}`} fill="none" viewBox="0 0 24 24">
|
|
135
|
+
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
|
136
|
+
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
|
137
|
+
</svg>
|
|
138
|
+
),
|
|
139
|
+
|
|
140
|
+
Sparkles: ({ className }: IconProps) => (
|
|
141
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
142
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
|
|
143
|
+
</svg>
|
|
144
|
+
),
|
|
145
|
+
|
|
146
|
+
Terminal: ({ className }: IconProps) => (
|
|
147
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
148
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
|
149
|
+
</svg>
|
|
150
|
+
),
|
|
151
|
+
|
|
152
|
+
File: ({ className }: IconProps) => (
|
|
153
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
154
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
155
|
+
</svg>
|
|
156
|
+
),
|
|
157
|
+
|
|
158
|
+
Globe: ({ className }: IconProps) => (
|
|
159
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
160
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
|
|
161
|
+
</svg>
|
|
162
|
+
),
|
|
163
|
+
|
|
164
|
+
Menu: ({ className }: IconProps) => (
|
|
165
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
166
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M4 6h16M4 12h16M4 18h16" />
|
|
167
|
+
</svg>
|
|
168
|
+
),
|
|
169
|
+
|
|
170
|
+
List: ({ className }: IconProps) => (
|
|
171
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
172
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M4 6h16M4 10h16M4 14h16M4 18h16" />
|
|
173
|
+
</svg>
|
|
174
|
+
),
|
|
175
|
+
|
|
176
|
+
ChevronLeft: ({ className }: IconProps) => (
|
|
177
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
178
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
|
179
|
+
</svg>
|
|
180
|
+
),
|
|
181
|
+
|
|
182
|
+
ChevronRight: ({ className }: IconProps) => (
|
|
183
|
+
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
184
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
185
|
+
</svg>
|
|
186
|
+
),
|
|
187
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { Icons } from './icons'
|
|
2
|
+
export { Button } from './button'
|
|
3
|
+
export { IconButton } from './icon-button'
|
|
4
|
+
export { Avatar } from './avatar'
|
|
5
|
+
export { StatusDot } from './status-dot'
|
|
6
|
+
export { Badge } from './badge'
|
|
7
|
+
export { Input } from './input'
|
|
8
|
+
export { Select, type SelectOption } from './select'
|
|
9
|
+
export { SectionHeader } from './section-header'
|
|
10
|
+
export { Dialog, AlertDialog, PromptDialog, CopyDialog } from './dialog-box'
|
|
11
|
+
export { Markdown } from './markdown-stream'
|
|
12
|
+
export { ShimmerText, ShimmerDots, ThinkingIndicator, PulsingDot } from './shimmer'
|
|
13
|
+
export { CollapsibleContent, CollapsibleCodeBlock } from './collapsible-content'
|
|
14
|
+
export { MobileDrawer, MobileSheet } from './mobile-drawer'
|
|
15
|
+
export { ContributionGraph, StatCard } from './contribution-graph'
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
interface InputProps {
|
|
4
|
+
placeholder?: string
|
|
5
|
+
value?: string
|
|
6
|
+
onChange?: (value: string) => void
|
|
7
|
+
onFocus?: () => void
|
|
8
|
+
onBlur?: () => void
|
|
9
|
+
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void
|
|
10
|
+
className?: string
|
|
11
|
+
icon?: ReactNode
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function Input({
|
|
15
|
+
placeholder,
|
|
16
|
+
value,
|
|
17
|
+
onChange,
|
|
18
|
+
onFocus,
|
|
19
|
+
onBlur,
|
|
20
|
+
onKeyDown,
|
|
21
|
+
className = '',
|
|
22
|
+
icon,
|
|
23
|
+
}: InputProps) {
|
|
24
|
+
return (
|
|
25
|
+
<div className={`relative ${className}`}>
|
|
26
|
+
{icon && (
|
|
27
|
+
<div className="absolute left-3 top-1/2 -translate-y-1/2 text-text-muted">
|
|
28
|
+
{icon}
|
|
29
|
+
</div>
|
|
30
|
+
)}
|
|
31
|
+
<input
|
|
32
|
+
type="text"
|
|
33
|
+
placeholder={placeholder}
|
|
34
|
+
value={value}
|
|
35
|
+
onChange={(e) => onChange?.(e.target.value)}
|
|
36
|
+
onFocus={onFocus}
|
|
37
|
+
onBlur={onBlur}
|
|
38
|
+
onKeyDown={onKeyDown}
|
|
39
|
+
className={`w-full bg-bg-tertiary border border-border rounded-lg py-2 text-sm text-text-primary placeholder:text-text-muted outline-none focus:border-text-muted transition-colors ${icon ? 'pl-10 pr-4' : 'px-4'}`}
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Streamdown } from 'streamdown'
|
|
2
|
+
|
|
3
|
+
interface MarkdownProps {
|
|
4
|
+
content: string
|
|
5
|
+
className?: string
|
|
6
|
+
streaming?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Markdown({ content, className = '', streaming = false }: MarkdownProps) {
|
|
10
|
+
return (
|
|
11
|
+
<div className={`markdown-content ${className}`}>
|
|
12
|
+
<Streamdown
|
|
13
|
+
mode={streaming ? 'streaming' : 'static'}
|
|
14
|
+
controls={false}
|
|
15
|
+
shikiTheme={['tokyo-night', 'tokyo-night']}
|
|
16
|
+
>
|
|
17
|
+
{content}
|
|
18
|
+
</Streamdown>
|
|
19
|
+
</div>
|
|
20
|
+
)
|
|
21
|
+
}
|