@shawnstack/quickforge 1.7.6 → 1.7.7

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.
@@ -1,5 +1,5 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/esm-sdsK6gaB.js","assets/pi-ai-Cr2ee4a0.js","assets/rolldown-runtime-DWdDZTNf.js","assets/dist-yDHbi5ux.js","assets/ChatPanelHost-D3987TUJ.js","assets/pi-web-ui-DV5jKjSg.js","assets/lit-vendor-DvaQX_UQ.js","assets/icons-2D18YbSI.js","assets/react-vendor-3UaA-C9W.js","assets/plugin-api-Uu2xAB4d.js","assets/model-display-label-C6-0eDxF.js","assets/model-reference-o41fJ6jQ.js","assets/mermaid-renderer-jEbqFaTe.js","assets/SharedConversationPage-B9BUVCri.js","assets/model-identity-CgA6_Pbm.js","assets/WorkspaceInspector-BnfDLf9a.js","assets/monaco-DvXErxp2.js","assets/TerminalDock-CT1nYo7P.js","assets/xterm-Bm_IbozX.js","assets/xterm-BrP-ENHg.css","assets/SettingsWorkspacePage-DSy66Tuw.js"])))=>i.map(i=>d[i]);
2
- import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,B as n,C as r,Ct as i,D as a,E as o,Et as s,F as c,Ft as l,G as u,Gt as d,Ht as f,It as p,J as m,Kt as h,M as g,Mt as _,N as v,Nt as y,O as b,Ot as x,Pt as S,Q as C,Rt as w,St as T,Ut as E,V as D,W as O,Z as k,_ as ee,_t as te,at as A,d as j,f as ne,g as re,h as M,i as N,it as P,j as ie,jt as F,k as ae,kt as I,l as L,m as R,mt as oe,n as z,nt as se,o as ce,ot as le,p as ue,q as B,qt as de,r as fe,rt as pe,s as me,st as he,tt as ge,u as _e,ut as ve,w as ye,wt as be,xt as xe,y as Se,yt as Ce,z as we,zt as Te}from"./icons-2D18YbSI.js";import{i as Ee,n as De,r as Oe,t as ke}from"./react-vendor-3UaA-C9W.js";import{i as Ae,n as je,t as Me}from"./dist-yDHbi5ux.js";import{f as Ne,p as Pe,u as Fe}from"./lit-vendor-DvaQX_UQ.js";import{n as Ie,r as Le,t as Re}from"./css-utils-31qzCXsk.js";import{C as ze,D as Be,E as Ve,S as He,T as Ue,b as We,d as Ge,f as Ke,p as qe,u as Je,w as Ye}from"./pi-web-ui-DV5jKjSg.js";import{J as Xe,U as Ze,W as Qe}from"./pi-ai-Cr2ee4a0.js";import{n as V,t as $e}from"./model-display-label-C6-0eDxF.js";import{t as et}from"./skills-dialog-BTJ7mzk_.js";import{n as tt,r as nt,t as rt}from"./model-reference-o41fJ6jQ.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var H=e(de(),1),it=Oe(),at=`language`,ot=[`en`,`zh`],st={en:{language:`Language`,displayLanguage:`Display language`,languageDescription:`Choose the display language for 速构 QuickForge. The page will reload to apply the change.`,simplifiedChinese:`Simplified Chinese`,english:`English`,apply:`Apply`,noLanguageChange:`The selected language is already active.`,newChat:`New chat`,startNewChat:`Start new chat`,newChatEmptyTitle:`What do you want to get done today?`,chooseProject:`Select project`,searchProjects:`Search projects`,newProject:`Add project`,createBlankProject:`Add project`,useExistingFolder:`Select project directory`,useNoProject:`No project`,noMatchingProjects:`No matching projects`,loadingChatWorkspace:`Loading chat workspace...`,loadingConversation:`Loading conversation`,loadingConversationPreparing:`Preparing history and tool records`,conversationLoadFailed:`Failed to load conversation`,localServiceUnavailableTitle:`Local QuickForge service unavailable`,localServiceUnavailableDescription:`QuickForge requires the local service for storage. Start QuickForge with npm run dev or the quickforge command, then reload this page.`,project:`Project`,projects:`Projects`,loadingProject:`Loading project...`,addProject:`Add project`,noProjects:`No projects yet.`,expandProject:`Expand project`,collapseProject:`Collapse project`,expandAllProjects:`Expand all projects`,collapseAllProjects:`Collapse all projects`,dragToReorder:`Drag to reorder`,newProjectChat:`New project chat`,projectChat:`Project chat`,normalChat:`Chat`,conversations:`Conversations`,turnNavigationLabel:`Conversation turns`,turnNavigationUserMessage:`User message`,turnNavigationFinalAnswer:`Final Answer`,turnNavigationGenerating:`Generating answer…`,turnNavigationNoAnswer:`No final answer yet`,turnNavigationAttachmentOnly:`Message with attachments`,turnNavigationJumpLabel:`Jump to turn {index}: {preview}`,pinnedConversations:`Pinned`,noConversations:`No conversations`,filterSort:`Filter and sort`,sidebarView:`View`,sidebarViewByProject:`By project`,sidebarViewTimeline:`Timeline`,sortBy:`Sort by`,sortByUpdatedAt:`Updated time`,sortByCreatedAt:`Created time`,filter:`Filter`,selecting:`Selecting...`,chooseFolder:`Choose folder`,selectProjectDirectory:`Select project directory`,selectProjectDirectoryDescription:`Browse local folders or paste a path, then choose the folder to add it as a project.`,quickAccess:`Quick access`,path:`Path`,go:`Go`,parentDirectory:`Parent directory`,noFolders:`No folders in this directory.`,selectThisFolder:`Select this folder`,folderPickerPathPlaceholder:`Enter or paste a folder path`,filesystemRootsFailed:`Failed to load filesystem roots.`,directoryLoadFailed:`Failed to load directory.`,noSavedConversations:`No saved conversations yet.`,rename:`Rename`,renameSession:`Rename conversation`,sessionName:`Conversation name`,deleteProject:`Delete project`,deleteProjectConfirm:`Are you sure you want to delete project "{name}"? Its conversations will be kept.`,deleteSession:`Delete session`,deleteSessionConfirm:`Are you sure you want to delete this conversation? This cannot be undone.`,deleteSessionFailed:`Failed to delete conversation.`,archiveSession:`Archive conversation`,confirmArchive:`Archive`,archivedConversations:`Archived conversations`,archivedConversationsDescription:`Archived conversations are hidden from the sidebar. Restore them here or delete them permanently.`,searchArchivedConversations:`Search archived conversations`,noArchivedConversations:`No archived conversations yet.`,archivedAt:`Archived at`,lastModified:`Last modified`,restoreSession:`Restore`,restoreSessionFailed:`Failed to restore conversation.`,sessionRestored:`Conversation restored.`,sessionNotFound:`Conversation not found.`,deletePermanently:`Delete`,deleteAll:`Delete all`,deleteArchivedSessionConfirm:`Permanently delete "{title}"? This cannot be undone.`,deleteAllArchivedSessionsConfirm:`Permanently delete all archived conversations? This cannot be undone.`,archivedSessionDeleted:`Archived conversation deleted.`,archivedSessionsDeleted:`Archived conversations deleted.`,shareLinks:`Share links`,shareLinksDescription:`Manage all conversation share links on this QuickForge instance, including expiration, disable, restore, and permanent deletion.`,cloudAccount:`QuickForge Cloud`,cloudAccountDescription:`Configure the QuickForge Cloud connection, identity, quota, model catalog, and connected devices. Local features remain available without an account.`,cloudServiceConnection:`Connection`,cloudServiceEnabled:`Enable cloud service`,cloudServiceEnabledDescription:`Allow this QuickForge instance to connect to QuickForge Cloud for remote access, managed models, account usage, and devices.`,cloudServiceDisabledDescription:`Cloud service is turned off. Local credentials are preserved, but remote access and managed cloud features are paused.`,cloudServiceEnabledSaved:`QuickForge Cloud is enabled.`,cloudServiceDisabledSaved:`QuickForge Cloud is disabled. Local credentials were preserved.`,cloudDisabledError:`QuickForge Cloud is turned off. Enable it in Cloud settings to continue.`,cloudRemoteAccess:`Remote access`,cloudRemoteAccessDescription:`QuickForge manages a separate local agent that securely connects this runtime to QuickForge Cloud.`,cloudRemoteServerUrl:`Bound server`,cloudRemotePid:`Agent PID`,cloudRemoteAuthorization:`Device authorization`,cloudRemoteOpenAuthorization:`Open authorization page`,cloudRemoteStatusLoading:`Loading`,cloudRemoteStatusDisabled:`Disabled`,cloudRemoteStatusUnavailable:`Agent unavailable`,cloudRemoteStatusStopped:`Stopped`,cloudRemoteStatusStarting:`Connecting`,cloudRemoteStatusAuthorizing:`Authorization required`,cloudRemoteStatusRunning:`Connected`,cloudRemoteStatusConflict:`Used by another runtime`,cloudRemoteStatusError:`Error`,cloudServiceType:`Service type`,cloudUrl:`Cloud API URL`,cloudUrlPlaceholder:`http://127.0.0.1:8082/`,cloudUrlInvalid:`Invalid URL`,cloudUrlInvalidProtocol:`http/https only`,cloudUrlHttpRestricted:`HTTP: localhost only`,cloudUrlAdminPort:`8081: admin console port`,cloudConfigSource:`Source`,cloudConfigSourceSaved:`Saved setting`,cloudConfigSourceEnv:`Environment`,cloudConfigSourceDefault:`Product default`,cloudTestConnection:`Test connection`,cloudConnectionTestSucceeded:`QuickForge Cloud health and readiness checks succeeded.`,cloudConnectionSaved:`QuickForge Cloud connection saved.`,cloudConnectionTestResult:`Connection test`,cloudHealth:`Health`,cloudReady:`Ready`,cloudConnectionOk:`OK`,cloudConnectionError:`Failed`,cloudConnectionUnknown:`Unknown`,cloudConnectionFailed:`Failed to connect to QuickForge Cloud.`,cloudRequestFailed:`QuickForge Cloud request failed.`,cloudRequestFailedWithStatus:`QuickForge Cloud request failed ({status}).`,cloudLocalOnlyError:`QuickForge Cloud is available only on this computer or an authenticated remote client.`,cloudConfigurationError:`The QuickForge Cloud configuration is invalid. Check the Cloud API URL.`,cloudSessionServiceMismatch:`This cloud session belongs to another service. Rebuild the cloud identity before continuing.`,cloudSessionExpired:`The cloud session is no longer valid. Sign in or start again.`,cloudDeviceFlowExpiredError:`The device sign-in code expired. Start account sign-in again.`,cloudDeviceFlowDeniedError:`The account authorization was denied.`,cloudSessionActiveGuidance:`A cloud session is active. Sign out this device first, or use “Rebuild identity and switch” after reviewing the warning.`,cloudForceSwitch:`Rebuild identity and switch`,cloudForceSwitchTitle:`Rebuild the cloud identity and switch services?`,cloudForceSwitchDescription:`This permanently clears the local cloud session and rotates the installation identity without sending its Refresh Token to either service. Existing guest quota cannot be recovered. The new URL is saved only after the reset succeeds.`,cloudForceSwitchConfirm:`Reset and switch`,cloudForceSwitchSucceeded:`The cloud identity was rebuilt and the service URL was switched. Start a new guest only when you are ready.`,cloudIdentityRebuiltUrlSaveFailed:`The cloud identity was rebuilt, but the new Cloud API URL was not saved. The previous saved URL is still active; review the URL above and retry saving.`,cloudSessionMismatchLabel:`Identity rebuild required`,cloudUnavailableDescription:`The local cloud session exists, but QuickForge Cloud cannot be reached. Check the service and retry.`,cloudUsageLoadFailed:`Failed to load cloud usage. Retry to refresh the quota.`,cloudModelsLoadFailed:`Failed to load the cloud model catalog. Retry to refresh it.`,cloudDevicesLoadFailed:`Failed to load connected devices. Retry to refresh them.`,cloudModels:`Cloud model catalog`,cloudNoModels:`No available cloud models were returned.`,cloudCapabilityTools:`Tools`,cloudCapabilityVision:`Vision`,cloudCapabilityReasoning:`Reasoning`,cloudCapabilityText:`Text`,cloudIdentityStatus:`Cloud identity`,cloudNotConfiguredDescription:`QuickForge Cloud is not configured on this instance.`,cloudConnectedDescription:`Cloud credentials are held by the local QuickForge service and are never exposed to the browser.`,cloudLocalOnlyDescription:`Local features remain anonymous and available. A cloud guest is created only after you choose to start.`,cloudFormalAccount:`Account`,cloudNotConnected:`Not connected`,cloudRemainingQuota:`Remaining quota`,cloudQuotaExpiresAt:`Quota resets or expires at`,cloudLoginOrRegister:`Sign in or register`,cloudLoginOrRegisterDescription:`QuickForge opens the Cloud verification page. Email and password are entered only there, never in QuickForge.`,cloudDeviceFlowTitle:`Complete sign-in in your browser`,cloudDeviceFlowDescription:`Open the Cloud verification page and enter the code if it is not filled automatically.`,cloudDeviceCode:`Device code`,cloudOpenVerificationPage:`Open verification page`,cloudDeviceFlowCountdown:`{seconds}s remaining`,cloudDeviceFlowSlowDown:`Cloud asked QuickForge to poll less often. Automatic polling will continue.`,cloudDeviceFlowSucceeded:`The account is connected.`,cloudDeviceFlowDenied:`The account authorization was denied. The guest session was kept.`,cloudDeviceFlowExpired:`The sign-in code expired. The guest session was kept.`,cloudDeviceFlowNetwork:`QuickForge Cloud is temporarily unreachable. Automatic polling will retry.`,cloudDeviceFlowCancelled:`Account sign-in cancelled. The guest session was kept.`,cloudDeviceCodeCopied:`Device code copied.`,cloudAccountEmail:`Email`,cloudAccountPlan:`Plan`,cloudDevices:`Connected devices`,cloudCurrentDevice:`Current device`,cloudUnnamedDevice:`Unnamed device`,cloudRegisteredAt:`Registered`,cloudLastSeenAt:`Last active`,cloudDuplicateDevicesHint:`{count} devices share the same name (e.g. “{name}”) — likely duplicates from repeated sign-ins. Revoke the ones you no longer need.`,cloudNoDevices:`No connected devices were returned.`,cloudRevokeDevice:`Revoke`,cloudRevokeDeviceConfirm:`Revoke cloud access for “{name}”? Its cloud sessions will stop working.`,cloudDeviceRevoked:`Device access revoked.`,cloudLogout:`Sign out this device`,cloudLogoutTitle:`Sign out this device?`,cloudLogoutDescription:`QuickForge will first revoke this device in the cloud, then clear its local cloud session. If the cloud cannot be reached, local credentials are kept so you can retry safely.`,cloudLogoutRowDescription:`This does not affect local projects, conversations, custom model providers, or API keys. Starting again creates a new guest identity and quota.`,cloudLoggedOut:`This device has been signed out of QuickForge Cloud.`,cloudLoadFailed:`Failed to load QuickForge Cloud status.`,cloudNotAvailable:`Not available`,searchShareLinks:`Search by conversation title or link ID`,shareLinksCount:`{count} links`,noShareLinks:`No share links yet.`,noMatchingShareLinks:`No matching share links.`,shareLinksLoadFailed:`Failed to load share links.`,shareStatusActive:`Active`,shareStatusDisabled:`Disabled`,shareStatusExpired:`Expired`,sharePermissionRead:`Read-only`,sharePermissionOperate:`Operate`,sharePasswordProtected:`Password protected`,shareCreatedAt:`Created`,shareExpiresAt:`Expires`,shareNeverExpires:`Never`,shareAccessCount:`{count} accesses`,shareLastAccessedAt:`Last accessed`,shareRestoreExpiration:`Expiration after restore`,shareUpdateExpiration:`New expiration`,updateShareExpiration:`Update expiration`,editShare:`Edit`,manageShare:`More`,editShareTitle:`Edit share link`,sharePermissionTitle:`Permission`,sharePermissionReadHint:`View-only access to this conversation.`,sharePermissionOperateHint:`Allows operating the original conversation. Password required.`,sharePasswordTitle:`Password`,sharePasswordPlaceholderKeep:`Leave blank to keep the current password`,sharePasswordPlaceholderNone:`Leave blank to keep it passwordless`,sharePasswordEditHint:`Leave blank to keep the current password. A new password invalidates previous ones.`,sharePasswordSetHint:`Filling a password adds protection and invalidates previous unlocks.`,sharePasswordRemovalSelected:`Password protection will be removed after saving.`,removePassword:`Remove password`,keepCurrentExpiration:`Keep current expiration`,saveChanges:`Save changes`,shareUpdated:`Share settings updated.`,operateRequiresPassword:`Operate shares require a non-empty password.`,oneHour:`1 hour`,twentyFourHours:`24 hours`,sevenDays:`7 days`,copyShareLink:`Copy share link`,openShareLink:`Open share link`,disableShare:`Disable`,restoreShare:`Restore`,deleteShare:`Delete permanently`,disableShareConfirm:`Disable the share link for "{title}"? Existing access and live connections will stop immediately.`,deleteShareConfirm:`Permanently delete the share link for "{title}"? This cannot be undone.`,shareLinkCopied:`Share link copied.`,shareDisabled:`Share link disabled.`,shareRestored:`Share link restored.`,shareExpirationUpdated:`Share link expiration updated.`,shareDeleted:`Share link permanently deleted.`,untitledConversation:`Untitled conversation`,allProjects:`All projects`,unknownProject:`Unknown project`,conversationCount:`{count} conversations`,confirm:`Confirm`,confirmDelete:`Delete`,settings:`Settings`,toggleSidebar:`Toggle sidebar`,failedToSelectProjectDirectory:`Failed to select project directory.`,projectSwitchFailed:`Failed to switch to the project for this conversation. Workspace tools were not started.`,copy:`Copy`,copied:`Copied`,svgDisplayMode:`SVG display mode`,svgPreviewMode:`Preview`,svgSourceMode:`Source`,svgEnlargePreview:`Click to enlarge SVG preview`,copySvgSource:`Copy SVG source`,downloadSvg:`Download SVG`,mermaidPreviewLabel:`Mermaid diagram preview`,mermaidEnlargePreview:`Click to enlarge Mermaid diagram`,copyMermaidSource:`Copy Mermaid source`,downloadMermaidSvg:`Download Mermaid SVG`,mermaidRendering:`Rendering Mermaid diagram...`,mermaidRenderFailed:`Could not render this Mermaid diagram. Source is shown instead.`,rollback:`Rollback`,retry:`Retry`,reloadPage:`Reload page`,fork:`Fork`,forkConversation:`Fork conversation from here`,yoloEnabledTitle:`Workspace access enabled: local tools can use this project`,yoloDisabledTitle:`Workspace access locked: local tools are blocked`,agentAccessMenuLabel:`Agent access mode`,agentAccessDefaultLabel:`Default permissions`,agentAccessFullLabel:`Full access`,agentAccessDefaultTitle:`Default permissions: work inside the current repository; ask before actions that may affect the system.`,agentAccessFullTitle:`Full access: developer-level authorization; tools can run automatically within the configured workspace boundaries.`,agentAccessModeSyncFailed:`Failed to sync Agent access mode.`,planModeLabel:`Plan`,planModeEnabledTitle:`Plan mode enabled: send the next message as /plan. Click to remove. Shortcut: Shift+Tab`,planModeDisabledTitle:`Plan mode: send the next message as /plan. Shortcut: Shift+Tab`,composerPlaceholder:`Describe what you want to do`,assistantWaitingThinking:`Thinking`,assistantWaitingOrganizing:`Organizing the answer`,assistantWaitingContinuing:`This may take a little longer`,assistantWaitingAriaLabel:`Assistant is preparing a response`,customCommandsHint:`Custom commands`,customCommandsEmptyHint:`No project commands yet.`,customCommandsListDescription:`List project custom commands`,customCommandsNewDescription:`Create a project custom command`,initCommandDescription:`Generate or update a concise AGENTS.md contributor guide for the current repository.`,planCommandDescription:`Create a plan first; this turn cannot edit files or run commands.`,reviewCommandDescription:`Review pending code changes before commit; this turn cannot edit files.`,summaryCommandDescription:`Create a new chat with this conversation summarized to reduce context usage.`,compactCommandDescription:`Compact this conversation context in place using the same rolling summary as auto-compaction.`,clearCommandDescription:`Clear the current chat history and context without calling the model.`,helpCommandDescription:`Show all available commands and their usage.`,yoloBlockedReason:`Local tool {name} was blocked by the current Agent permission mode. Switch to Full access or approve the tool call when prompted.`,globalToolBlockedReason:`Local tool {name} was blocked because this is a normal chat with no project attached. Start or open a project chat to use workspace tools.`,noActiveProjectToolBlockedReason:`Local tool {name} was blocked because there is no active project. Add or select a project to use workspace tools.`,generationAlreadyRunning:`Generation is still running. Stop it or wait until it finishes.`,generationStillRunning:`Generation is still running. Stop it or wait until it finishes before rolling back.`,noConversationTurnToRollback:`There is no conversation turn to roll back.`,rollbackConfirmTitle:`Confirm rollback?`,rollbackConfirm:`Roll back to before this message? This message and all following conversation history will be removed, and the message content will be restored to the composer.`,sharedRollbackConfirmTitle:`Confirm shared conversation rollback?`,sharedRollbackConfirm:`This will directly modify the sharer's original conversation. This message and all following conversation history will be removed, and the message content will be restored to the composer.`,confirmRollback:`Confirm rollback`,rollingBack:`Rolling back...`,rollbackFailed:`Rollback failed.`,retryFailed:`Retry failed.`,openCodeMessageHistoryActionUnavailable:`OpenCode does not support rollback, retry, or forking from a message position. These actions are unavailable for OpenCode conversations.`,openCodeConfigMenuLabel:`OpenCode config`,openCodeConfigButtonLabel:`Config`,openCodeConfigDisabledWhileStreaming:`OpenCode config is disabled while a generation is running.`,openCodeConfigModesTitle:`Mode`,openCodeConfigOptionsTitle:`Options`,openCodeModeMenuLabel:`OpenCode mode`,openCodeModeDisabledWhileStreaming:`OpenCode mode is disabled while a generation is running.`,openCodeUsageTokensTitle:`Used {used} / {size} tokens`,openCodeUsageCostTitle:`Cost: {amount} {currency}`,forkCurrentSession:`Duplicate current conversation`,forkCurrentSessionTitle:`Create a full copy of this OpenCode conversation as a new session.`,openCodeForkUnavailable:`This OpenCode conversation cannot be duplicated because no ACP session is available.`,openCodeForkFailed:`Failed to duplicate the conversation.`,copyFailed:`Copy failed. Please check clipboard permissions.`,errorBoundaryTitle:`Something went wrong`,errorBoundaryUnexpected:`An unexpected error occurred.`,errorBoundaryTryAgain:`Try again`,execute:`Run`,addCustomModelFirst:`Please add a custom model in Settings and make sure the model ID is filled in before saving.`,modelSetupRequired:`Please add a model before starting a new chat.`,modelSetupTitle:`No model configured yet`,modelSetupDescription:`Add an OpenAI-Compatible or Anthropic-compatible model to start chatting. QuickForge will only use models that you configure.`,modelSetupSupports:`Supports LiteLLM, OpenRouter, DeepSeek, Qwen, Zhipu, Ollama, and most /v1/chat/completions services.`,modelSetupLocalStorage:`Providers, model IDs, and API keys are stored locally by the QuickForge service on this machine.`,modelSetupAddModel:`Add model`,modelSetupUseLiteLlmExample:`Use LiteLLM example`,firstUseGuideTitle:`Start with a safe workflow`,firstUseGuideDescription:`Add a project, ask QuickForge to understand it, and use /plan before granting local tool access for code changes.`,firstUseGuideStepModel:`Confirm the model you want to use.`,firstUseGuideStepProject:`Add a local project so AI can use workspace context.`,firstUseGuideStepPlan:`Use /plan first; that turn cannot edit files or run commands.`,firstUseGuideConfigureModel:`Configure model`,firstUseGuideAddProject:`Add project`,firstUseGuideUsePrompt:`Try example prompt`,firstUseGuideCopyPrompt:`Copy /plan example`,firstUseGuideDismiss:`Got it`,firstUseGuideProjectPrompt:`/plan Read this project and explain its structure, run commands, and main risks. Do not modify files yet.`,firstUseGuideGeneralPrompt:`/plan Break this request into implementation steps and risks first. Do not modify files yet.`,defaultOptions:`General`,defaultOptionsDescription:`Configure language, default model, thinking level, tool display, and context management for new chats and scheduled tasks.`,memory:`Memory`,memoryDescription:`Let QuickForge remember useful preferences and habits across chats and projects.`,globalMemory:`Global memory`,globalMemoryDescription:`When enabled, QuickForge uses existing memory and can proactively remember durable preferences, habits, background, workflows, and goals that may help in future conversations.`,globalMemoryInfo:`Memory is stored locally and shared by all chats and projects. QuickForge avoids temporary task details, uncertain inferences, and sensitive credentials. Turn memory off to stop future reads and writes while keeping the existing file.`,memoryFile:`Memory file`,memoryFileDescription:`Saved as a readable Markdown file in the local QuickForge data directory.`,memoryCurrentSessionNote:`Changes are loaded by running chats before their next message. Turning memory off stops future reads and writes while keeping the existing file.`,memoryEnabledSaved:`Global memory enabled.`,memoryDisabledSaved:`Global memory disabled. Existing memory was kept.`,memoryContent:`Memory content`,memoryContentDescription:`View or edit the complete free-form Markdown document. Content and formatting are saved exactly as written.`,memoryContentDisabledDescription:`Turn global memory on to edit and save this file. Existing content remains available after reloading.`,memoryReload:`Reload`,memorySave:`Save memory`,memoryReloaded:`Memory reloaded.`,memoryContentSaved:`Global memory saved.`,memoryContentEmpty:`Global user memory is empty.`,defaultModel:`Default model`,defaultModelDescription:`Used by new chats and scheduled tasks unless overridden.`,defaultHarness:`Default Harness`,defaultHarnessDescription:`Used by new chats. The current blank chat updates immediately; existing chats keep their Harness.`,claudeCodeHarnessUnavailable:`Claude Code (not available yet)`,defaultThinkingLevel:`Default thinking level`,defaultThinkingLevelDescription:`Choose the default reasoning effort for supported models.`,toolDisplay:`Tool display`,toolDisplayModeDescription:`Compact shows summaries with details collapsed. Detailed shows full parameters and details with tool calls expanded.`,toolDisplayCompact:`Compact`,toolDisplayDetailed:`Detailed`,showContextUsage:`Show context usage`,showContextUsageDescription:`Show the context usage ring and details next to the model selector.`,fontSize:`Font size`,fontSizeDescription:`Adjust interface and conversation text size.`,fontSizeRangeDescription:`Drag to preview immediately; release to save.`,appearance:`Appearance`,appearanceDescription:`Customize the interface theme and font size.`,theme:`Theme`,themeDescription:`Switch between light and dark. Changes apply instantly.`,lightTheme:`Light`,darkTheme:`Dark`,appearanceSaved:`Appearance saved`,interfaceFontSize:`Interface font size`,messageFontSize:`Conversation font size`,messageFontSizeNote:`Applies to the main text in chat messages.`,fontSizeSaved:`Font size saved`,toolDetailsHidden:`Tool details are hidden in compact mode. Switch Tool display to Detailed in Settings to view full parameters.`,toolArgsSummary:`Arguments summary`,saveDefaultOptions:`Save defaults`,saving:`Saving...`,defaultOptionsSaved:`Default options saved`,networkConnection:`Network connection`,networkProxyMode:`Proxy mode`,networkProxyDirect:`Direct`,networkProxySystem:`Follow system`,networkProxyManual:`Manual proxy`,networkProxyPac:`PAC URL`,networkProxyDescription:`Controls supported external HTTP requests made by QuickForge. Localhost always connects directly. Follow system reads the operating-system proxy configuration, including PAC/WPAD when supported. Custom PAC URLs are supported by Desktop only.`,networkProxyAddress:`Proxy address`,networkProxyAddressDescription:`Enter an HTTP or HTTPS proxy URL with a port. Paths, query strings, fragments, and proxy credentials are not supported.`,networkProxyAddressRequired:`Enter a proxy address before saving.`,networkProxyAddressInvalid:`Enter a valid HTTP or HTTPS proxy address.`,networkProxyAddressProtocolError:`Only HTTP and HTTPS proxy addresses are supported.`,networkProxyAddressPortError:`The proxy address must include a host and port.`,networkProxyAddressCredentialsError:`Proxy credentials are not supported in the address.`,networkProxyAddressPathError:`The proxy address cannot contain a path, query string, or fragment.`,networkProxyPacUrl:`PAC URL`,networkProxyPacUrlDescription:`Enter an HTTP or HTTPS URL for a PAC script. Paths and query strings are supported; credentials and fragments are not.`,networkProxyPacUrlRequired:`Enter a PAC URL before saving.`,networkProxyPacUrlInvalid:`Enter a valid HTTP or HTTPS PAC URL.`,networkProxyPacUrlProtocolError:`Only HTTP and HTTPS PAC URLs are supported.`,networkProxyPacUrlHostError:`The PAC URL must include a host.`,networkProxyPacUrlCredentialsError:`Credentials are not supported in the PAC URL.`,networkProxyPacUrlFragmentError:`The PAC URL cannot contain a fragment.`,networkProxyPacUnsupported:`Custom PAC URLs are supported only by the Desktop runtime.`,networkProxySave:`Save proxy`,networkProxyRefresh:`Reload system proxy`,networkProxyRefreshDescription:`Reload the current operating-system proxy configuration and close existing network connections.`,networkProxyStatus:`Source: {source}; runtime: {runtime}.`,networkProxyUnsupported:`The operating-system proxy is not supported by this runtime.`,networkProxyLoadFailed:`Unable to load the current proxy configuration. Proxy controls are disabled.`,networkProxySaved:`Network proxy setting saved`,networkProxyRefreshed:`System proxy reloaded`,contextManagement:`Context Management`,contextUsageTitle:`Context usage`,contextUsageAriaLabel:`Context usage: {percent}%. Show details`,contextUsageTotal:`{used} / {limit} tokens`,contextUsageInputLabel:`Input / context`,contextUsageReservedOutputLabel:`Reserved output`,contextUsageSystemPromptLabel:`System prompt`,contextUsageToolsSchemaLabel:`Tools schema`,contextUsageMessagesLabel:`Messages`,contextUsageSourceServerShort:`Server calculated`,contextUsageSourceLocalShort:`Local estimate`,contextUsageScopeCompactedShort:`Compacted model context`,contextUsageScopeFullShort:`Full model context`,contextUsageUsed:`Context used: {percent}% ({used} / {limit} tokens)`,contextUsageInput:`Input/context: {tokens} ({source})`,contextUsageSourceProvider:`provider context`,contextUsageSourceMixed:`provider/local mixed context`,contextUsageSourceEstimated:`estimated context`,contextUsageLocalEstimate:`Local estimate: {tokens}`,contextUsageSystemPrompt:` System prompt: {tokens}`,contextUsageToolsSchema:` Tools schema: {tokens}`,contextUsageMessages:` Messages: {tokens}`,contextUsageProviderBaseline:` Provider usage baseline: {tokens}`,contextUsageTrailingMessages:` Trailing messages after usage: {tokens}`,contextUsageReservedOutput:`Reserved output: {tokens}`,contextUsageServerCalculated:`Source: server calculated via pi-agent-core/pi-ai`,contextUsageScopeCompacted:`Scope: compacted model context, not full visible chat history`,contextUsageScopeFull:`Scope: full model context`,contextUsageEffectiveMessages:`Messages: {effective} effective / {visible} visible`,contextUsageProviderTokens:`Provider context tokens: {tokens}`,autoCompactEnabled:`Automatically compact context`,autoCompactRequireConfirmation:`Ask before compacting automatically`,autoCompactRequireConfirmationDescription:`Ask for approval before QuickForge summarizes older history.`,autoCompactTriggerNote:`Checks run before each model request. Lower the threshold or reduce the model Context Window to test triggering.`,autoCompactThresholdPercent:`Compact when context reaches (%)`,autoCompactThresholdDescription:`Percentage of the model context window that triggers compaction.`,autoCompactKeepRecentTurns:`Keep recent user turns`,autoCompactKeepRecentTurnsDescription:`Recent turns stay in full detail after older context is summarized.`,autoCompactDescription:`When the estimated next request reaches the configured share of the model context window, QuickForge summarizes older history and continues the current task. This uses one extra model call.`,autoCompactHistoryPreserved:`The full chat history remains visible; only the context sent to the model is compacted.`,autoArchiveEnabled:`Automatically archive old conversations`,autoArchiveTriggerNote:`Conversations not updated for more than 30 days are moved to Archived conversations.`,autoArchiveDescription:`Archived conversations are not deleted. Turning this off only stops future automatic archiving; existing archived conversations can still be viewed and restored.`,autoArchiveSaved:`Automatic archive setting saved`,thinkingLevel:`Thinking level`,thinkingOff:`Off`,thinkingLow:`Low`,thinkingMedium:`Medium`,thinkingHigh:`High`,thinkingXHigh:`XHigh`,currentConfiguration:`Current configuration`,thinkingSupported:`Thinking`,thinkingNotSupported:`This model does not support thinking levels.`,thinkingRequiresReasoningModel:`Thinking levels require a reasoning / thinking model.`,customModels:`Custom Models`,customModelsTitle:`Custom models`,customModelsDescription:`Only use custom OpenAI-Compatible models that you configure.`,addModel:`Add model`,editModel:`Edit model`,delete:`Delete`,editCustomModel:`Edit custom model`,addCustomModel:`Add custom model`,providerName:`Provider name`,providerNamePlaceholder:`e.g., LiteLLM`,protocolType:`Protocol type`,protocolHelp:`Use OpenAI Compatible for LiteLLM, OpenRouter, and most /v1/chat/completions services. Use Anthropic Messages only for the direct Anthropic API.`,apiKey:`API Key`,apiKeyPlaceholder:`Leave empty if not required`,showApiKey:`Show API Key`,hideApiKey:`Hide API Key`,customHeaders:`Custom Headers JSON`,customHeadersPlaceholder:`{
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/esm-sdsK6gaB.js","assets/pi-ai-Cr2ee4a0.js","assets/rolldown-runtime-DWdDZTNf.js","assets/dist-yDHbi5ux.js","assets/ChatPanelHost-Dul1ahKj.js","assets/pi-web-ui-DV5jKjSg.js","assets/lit-vendor-DvaQX_UQ.js","assets/icons-2D18YbSI.js","assets/react-vendor-3UaA-C9W.js","assets/plugin-api-Uu2xAB4d.js","assets/model-display-label-C6-0eDxF.js","assets/model-reference-o41fJ6jQ.js","assets/mermaid-renderer-jEbqFaTe.js","assets/SharedConversationPage-BK9XJnEe.js","assets/model-identity-CgA6_Pbm.js","assets/WorkspaceInspector-MNBLIKMn.js","assets/monaco-DvXErxp2.js","assets/TerminalDock-CL7HU9DI.js","assets/xterm-Bm_IbozX.js","assets/xterm-BrP-ENHg.css","assets/SettingsWorkspacePage-BE2T4d3P.js"])))=>i.map(i=>d[i]);
2
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,B as n,C as r,Ct as i,D as a,E as o,Et as s,F as c,Ft as l,G as u,Gt as d,Ht as f,It as p,J as m,Kt as h,M as g,Mt as _,N as v,Nt as y,O as b,Ot as x,Pt as S,Q as C,Rt as w,St as T,Ut as E,V as D,W as O,Z as k,_ as ee,_t as te,at as A,d as j,f as ne,g as re,h as M,i as N,it as P,j as ie,jt as F,k as ae,kt as I,l as L,m as R,mt as oe,n as z,nt as se,o as ce,ot as le,p as ue,q as B,qt as de,r as fe,rt as pe,s as me,st as he,tt as ge,u as _e,ut as ve,w as ye,wt as be,xt as xe,y as Se,yt as Ce,z as we,zt as Te}from"./icons-2D18YbSI.js";import{i as Ee,n as De,r as Oe,t as ke}from"./react-vendor-3UaA-C9W.js";import{i as Ae,n as je,t as Me}from"./dist-yDHbi5ux.js";import{f as Ne,p as Pe,u as Fe}from"./lit-vendor-DvaQX_UQ.js";import{n as Ie,r as Le,t as Re}from"./css-utils-31qzCXsk.js";import{C as ze,D as Be,E as Ve,S as He,T as Ue,b as We,d as Ge,f as Ke,p as qe,u as Je,w as Ye}from"./pi-web-ui-DV5jKjSg.js";import{J as Xe,U as Ze,W as Qe}from"./pi-ai-Cr2ee4a0.js";import{n as V,t as $e}from"./model-display-label-C6-0eDxF.js";import{t as et}from"./skills-dialog-C1fJ1Jl7.js";import{n as tt,r as nt,t as rt}from"./model-reference-o41fJ6jQ.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var H=e(de(),1),it=Oe(),at=`language`,ot=[`en`,`zh`],st={en:{language:`Language`,displayLanguage:`Display language`,languageDescription:`Choose the display language for 速构 QuickForge. The page will reload to apply the change.`,simplifiedChinese:`Simplified Chinese`,english:`English`,apply:`Apply`,noLanguageChange:`The selected language is already active.`,newChat:`New chat`,startNewChat:`Start new chat`,newChatEmptyTitle:`What do you want to get done today?`,chooseProject:`Select project`,searchProjects:`Search projects`,newProject:`Add project`,createBlankProject:`Add project`,useExistingFolder:`Select project directory`,useNoProject:`No project`,noMatchingProjects:`No matching projects`,loadingChatWorkspace:`Loading chat workspace...`,loadingConversation:`Loading conversation`,loadingConversationPreparing:`Preparing history and tool records`,conversationLoadFailed:`Failed to load conversation`,localServiceUnavailableTitle:`Local QuickForge service unavailable`,localServiceUnavailableDescription:`QuickForge requires the local service for storage. Start QuickForge with npm run dev or the quickforge command, then reload this page.`,project:`Project`,projects:`Projects`,loadingProject:`Loading project...`,addProject:`Add project`,noProjects:`No projects yet.`,expandProject:`Expand project`,collapseProject:`Collapse project`,expandAllProjects:`Expand all projects`,collapseAllProjects:`Collapse all projects`,dragToReorder:`Drag to reorder`,newProjectChat:`New project chat`,projectChat:`Project chat`,normalChat:`Chat`,conversations:`Conversations`,turnNavigationLabel:`Conversation turns`,turnNavigationUserMessage:`User message`,turnNavigationFinalAnswer:`Final Answer`,turnNavigationGenerating:`Generating answer…`,turnNavigationNoAnswer:`No final answer yet`,turnNavigationAttachmentOnly:`Message with attachments`,turnNavigationJumpLabel:`Jump to turn {index}: {preview}`,pinnedConversations:`Pinned`,noConversations:`No conversations`,filterSort:`Filter and sort`,sidebarView:`View`,sidebarViewByProject:`By project`,sidebarViewTimeline:`Timeline`,sortBy:`Sort by`,sortByUpdatedAt:`Updated time`,sortByCreatedAt:`Created time`,filter:`Filter`,selecting:`Selecting...`,chooseFolder:`Choose folder`,selectProjectDirectory:`Select project directory`,selectProjectDirectoryDescription:`Browse local folders or paste a path, then choose the folder to add it as a project.`,quickAccess:`Quick access`,path:`Path`,go:`Go`,parentDirectory:`Parent directory`,noFolders:`No folders in this directory.`,selectThisFolder:`Select this folder`,folderPickerPathPlaceholder:`Enter or paste a folder path`,filesystemRootsFailed:`Failed to load filesystem roots.`,directoryLoadFailed:`Failed to load directory.`,noSavedConversations:`No saved conversations yet.`,rename:`Rename`,renameSession:`Rename conversation`,sessionName:`Conversation name`,deleteProject:`Delete project`,deleteProjectConfirm:`Are you sure you want to delete project "{name}"? Its conversations will be kept.`,deleteSession:`Delete session`,deleteSessionConfirm:`Are you sure you want to delete this conversation? This cannot be undone.`,deleteSessionFailed:`Failed to delete conversation.`,archiveSession:`Archive conversation`,confirmArchive:`Archive`,archivedConversations:`Archived conversations`,archivedConversationsDescription:`Archived conversations are hidden from the sidebar. Restore them here or delete them permanently.`,searchArchivedConversations:`Search archived conversations`,noArchivedConversations:`No archived conversations yet.`,archivedAt:`Archived at`,lastModified:`Last modified`,restoreSession:`Restore`,restoreSessionFailed:`Failed to restore conversation.`,sessionRestored:`Conversation restored.`,sessionNotFound:`Conversation not found.`,deletePermanently:`Delete`,deleteAll:`Delete all`,deleteArchivedSessionConfirm:`Permanently delete "{title}"? This cannot be undone.`,deleteAllArchivedSessionsConfirm:`Permanently delete all archived conversations? This cannot be undone.`,archivedSessionDeleted:`Archived conversation deleted.`,archivedSessionsDeleted:`Archived conversations deleted.`,shareLinks:`Share links`,shareLinksDescription:`Manage all conversation share links on this QuickForge instance, including expiration, disable, restore, and permanent deletion.`,cloudAccount:`QuickForge Cloud`,cloudAccountDescription:`Configure the QuickForge Cloud connection, identity, quota, model catalog, and connected devices. Local features remain available without an account.`,cloudServiceConnection:`Connection`,cloudServiceEnabled:`Enable cloud service`,cloudServiceEnabledDescription:`Allow this QuickForge instance to connect to QuickForge Cloud for remote access, managed models, account usage, and devices.`,cloudServiceDisabledDescription:`Cloud service is turned off. Local credentials are preserved, but remote access and managed cloud features are paused.`,cloudServiceEnabledSaved:`QuickForge Cloud is enabled.`,cloudServiceDisabledSaved:`QuickForge Cloud is disabled. Local credentials were preserved.`,cloudDisabledError:`QuickForge Cloud is turned off. Enable it in Cloud settings to continue.`,cloudRemoteAccess:`Remote access`,cloudRemoteAccessDescription:`QuickForge manages a separate local agent that securely connects this runtime to QuickForge Cloud.`,cloudRemoteServerUrl:`Bound server`,cloudRemotePid:`Agent PID`,cloudRemoteAuthorization:`Device authorization`,cloudRemoteOpenAuthorization:`Open authorization page`,cloudRemoteStatusLoading:`Loading`,cloudRemoteStatusDisabled:`Disabled`,cloudRemoteStatusUnavailable:`Agent unavailable`,cloudRemoteStatusStopped:`Stopped`,cloudRemoteStatusStarting:`Connecting`,cloudRemoteStatusAuthorizing:`Authorization required`,cloudRemoteStatusRunning:`Connected`,cloudRemoteStatusConflict:`Used by another runtime`,cloudRemoteStatusError:`Error`,cloudServiceType:`Service type`,cloudUrl:`Cloud API URL`,cloudUrlPlaceholder:`http://127.0.0.1:8082/`,cloudUrlInvalid:`Invalid URL`,cloudUrlInvalidProtocol:`http/https only`,cloudUrlHttpRestricted:`HTTP: localhost only`,cloudUrlAdminPort:`8081: admin console port`,cloudConfigSource:`Source`,cloudConfigSourceSaved:`Saved setting`,cloudConfigSourceEnv:`Environment`,cloudConfigSourceDefault:`Product default`,cloudTestConnection:`Test connection`,cloudConnectionTestSucceeded:`QuickForge Cloud health and readiness checks succeeded.`,cloudConnectionSaved:`QuickForge Cloud connection saved.`,cloudConnectionTestResult:`Connection test`,cloudHealth:`Health`,cloudReady:`Ready`,cloudConnectionOk:`OK`,cloudConnectionError:`Failed`,cloudConnectionUnknown:`Unknown`,cloudConnectionFailed:`Failed to connect to QuickForge Cloud.`,cloudRequestFailed:`QuickForge Cloud request failed.`,cloudRequestFailedWithStatus:`QuickForge Cloud request failed ({status}).`,cloudLocalOnlyError:`QuickForge Cloud is available only on this computer or an authenticated remote client.`,cloudConfigurationError:`The QuickForge Cloud configuration is invalid. Check the Cloud API URL.`,cloudSessionServiceMismatch:`This cloud session belongs to another service. Rebuild the cloud identity before continuing.`,cloudSessionExpired:`The cloud session is no longer valid. Sign in or start again.`,cloudDeviceFlowExpiredError:`The device sign-in code expired. Start account sign-in again.`,cloudDeviceFlowDeniedError:`The account authorization was denied.`,cloudSessionActiveGuidance:`A cloud session is active. Sign out this device first, or use “Rebuild identity and switch” after reviewing the warning.`,cloudForceSwitch:`Rebuild identity and switch`,cloudForceSwitchTitle:`Rebuild the cloud identity and switch services?`,cloudForceSwitchDescription:`This permanently clears the local cloud session and rotates the installation identity without sending its Refresh Token to either service. Existing guest quota cannot be recovered. The new URL is saved only after the reset succeeds.`,cloudForceSwitchConfirm:`Reset and switch`,cloudForceSwitchSucceeded:`The cloud identity was rebuilt and the service URL was switched. Start a new guest only when you are ready.`,cloudIdentityRebuiltUrlSaveFailed:`The cloud identity was rebuilt, but the new Cloud API URL was not saved. The previous saved URL is still active; review the URL above and retry saving.`,cloudSessionMismatchLabel:`Identity rebuild required`,cloudUnavailableDescription:`The local cloud session exists, but QuickForge Cloud cannot be reached. Check the service and retry.`,cloudUsageLoadFailed:`Failed to load cloud usage. Retry to refresh the quota.`,cloudModelsLoadFailed:`Failed to load the cloud model catalog. Retry to refresh it.`,cloudDevicesLoadFailed:`Failed to load connected devices. Retry to refresh them.`,cloudModels:`Cloud model catalog`,cloudNoModels:`No available cloud models were returned.`,cloudCapabilityTools:`Tools`,cloudCapabilityVision:`Vision`,cloudCapabilityReasoning:`Reasoning`,cloudCapabilityText:`Text`,cloudIdentityStatus:`Cloud identity`,cloudNotConfiguredDescription:`QuickForge Cloud is not configured on this instance.`,cloudConnectedDescription:`Cloud credentials are held by the local QuickForge service and are never exposed to the browser.`,cloudLocalOnlyDescription:`Local features remain anonymous and available. A cloud guest is created only after you choose to start.`,cloudFormalAccount:`Account`,cloudNotConnected:`Not connected`,cloudRemainingQuota:`Remaining quota`,cloudQuotaExpiresAt:`Quota resets or expires at`,cloudLoginOrRegister:`Sign in or register`,cloudLoginOrRegisterDescription:`QuickForge opens the Cloud verification page. Email and password are entered only there, never in QuickForge.`,cloudDeviceFlowTitle:`Complete sign-in in your browser`,cloudDeviceFlowDescription:`Open the Cloud verification page and enter the code if it is not filled automatically.`,cloudDeviceCode:`Device code`,cloudOpenVerificationPage:`Open verification page`,cloudDeviceFlowCountdown:`{seconds}s remaining`,cloudDeviceFlowSlowDown:`Cloud asked QuickForge to poll less often. Automatic polling will continue.`,cloudDeviceFlowSucceeded:`The account is connected.`,cloudDeviceFlowDenied:`The account authorization was denied. The guest session was kept.`,cloudDeviceFlowExpired:`The sign-in code expired. The guest session was kept.`,cloudDeviceFlowNetwork:`QuickForge Cloud is temporarily unreachable. Automatic polling will retry.`,cloudDeviceFlowCancelled:`Account sign-in cancelled. The guest session was kept.`,cloudDeviceCodeCopied:`Device code copied.`,cloudAccountEmail:`Email`,cloudAccountPlan:`Plan`,cloudDevices:`Connected devices`,cloudCurrentDevice:`Current device`,cloudUnnamedDevice:`Unnamed device`,cloudRegisteredAt:`Registered`,cloudLastSeenAt:`Last active`,cloudDuplicateDevicesHint:`{count} devices share the same name (e.g. “{name}”) — likely duplicates from repeated sign-ins. Revoke the ones you no longer need.`,cloudNoDevices:`No connected devices were returned.`,cloudRevokeDevice:`Revoke`,cloudRevokeDeviceConfirm:`Revoke cloud access for “{name}”? Its cloud sessions will stop working.`,cloudDeviceRevoked:`Device access revoked.`,cloudLogout:`Sign out this device`,cloudLogoutTitle:`Sign out this device?`,cloudLogoutDescription:`QuickForge will first revoke this device in the cloud, then clear its local cloud session. If the cloud cannot be reached, local credentials are kept so you can retry safely.`,cloudLogoutRowDescription:`This does not affect local projects, conversations, custom model providers, or API keys. Starting again creates a new guest identity and quota.`,cloudLoggedOut:`This device has been signed out of QuickForge Cloud.`,cloudLoadFailed:`Failed to load QuickForge Cloud status.`,cloudNotAvailable:`Not available`,searchShareLinks:`Search by conversation title or link ID`,shareLinksCount:`{count} links`,noShareLinks:`No share links yet.`,noMatchingShareLinks:`No matching share links.`,shareLinksLoadFailed:`Failed to load share links.`,shareStatusActive:`Active`,shareStatusDisabled:`Disabled`,shareStatusExpired:`Expired`,sharePermissionRead:`Read-only`,sharePermissionOperate:`Operate`,sharePasswordProtected:`Password protected`,shareCreatedAt:`Created`,shareExpiresAt:`Expires`,shareNeverExpires:`Never`,shareAccessCount:`{count} accesses`,shareLastAccessedAt:`Last accessed`,shareRestoreExpiration:`Expiration after restore`,shareUpdateExpiration:`New expiration`,updateShareExpiration:`Update expiration`,editShare:`Edit`,manageShare:`More`,editShareTitle:`Edit share link`,sharePermissionTitle:`Permission`,sharePermissionReadHint:`View-only access to this conversation.`,sharePermissionOperateHint:`Allows operating the original conversation. Password required.`,sharePasswordTitle:`Password`,sharePasswordPlaceholderKeep:`Leave blank to keep the current password`,sharePasswordPlaceholderNone:`Leave blank to keep it passwordless`,sharePasswordEditHint:`Leave blank to keep the current password. A new password invalidates previous ones.`,sharePasswordSetHint:`Filling a password adds protection and invalidates previous unlocks.`,sharePasswordRemovalSelected:`Password protection will be removed after saving.`,removePassword:`Remove password`,keepCurrentExpiration:`Keep current expiration`,saveChanges:`Save changes`,shareUpdated:`Share settings updated.`,operateRequiresPassword:`Operate shares require a non-empty password.`,oneHour:`1 hour`,twentyFourHours:`24 hours`,sevenDays:`7 days`,copyShareLink:`Copy share link`,openShareLink:`Open share link`,disableShare:`Disable`,restoreShare:`Restore`,deleteShare:`Delete permanently`,disableShareConfirm:`Disable the share link for "{title}"? Existing access and live connections will stop immediately.`,deleteShareConfirm:`Permanently delete the share link for "{title}"? This cannot be undone.`,shareLinkCopied:`Share link copied.`,shareDisabled:`Share link disabled.`,shareRestored:`Share link restored.`,shareExpirationUpdated:`Share link expiration updated.`,shareDeleted:`Share link permanently deleted.`,untitledConversation:`Untitled conversation`,allProjects:`All projects`,unknownProject:`Unknown project`,conversationCount:`{count} conversations`,confirm:`Confirm`,confirmDelete:`Delete`,settings:`Settings`,toggleSidebar:`Toggle sidebar`,failedToSelectProjectDirectory:`Failed to select project directory.`,projectSwitchFailed:`Failed to switch to the project for this conversation. Workspace tools were not started.`,copy:`Copy`,copied:`Copied`,svgDisplayMode:`SVG display mode`,svgPreviewMode:`Preview`,svgSourceMode:`Source`,svgEnlargePreview:`Click to enlarge SVG preview`,copySvgSource:`Copy SVG source`,downloadSvg:`Download SVG`,mermaidPreviewLabel:`Mermaid diagram preview`,mermaidEnlargePreview:`Click to enlarge Mermaid diagram`,copyMermaidSource:`Copy Mermaid source`,downloadMermaidSvg:`Download Mermaid SVG`,mermaidRendering:`Rendering Mermaid diagram...`,mermaidRenderFailed:`Could not render this Mermaid diagram. Source is shown instead.`,rollback:`Rollback`,retry:`Retry`,reloadPage:`Reload page`,fork:`Fork`,forkConversation:`Fork conversation from here`,yoloEnabledTitle:`Workspace access enabled: local tools can use this project`,yoloDisabledTitle:`Workspace access locked: local tools are blocked`,agentAccessMenuLabel:`Agent access mode`,agentAccessDefaultLabel:`Default permissions`,agentAccessFullLabel:`Full access`,agentAccessDefaultTitle:`Default permissions: work inside the current repository; ask before actions that may affect the system.`,agentAccessFullTitle:`Full access: developer-level authorization; tools can run automatically within the configured workspace boundaries.`,agentAccessModeSyncFailed:`Failed to sync Agent access mode.`,planModeLabel:`Plan`,planModeEnabledTitle:`Plan mode enabled: send the next message as /plan. Click to remove. Shortcut: Shift+Tab`,planModeDisabledTitle:`Plan mode: send the next message as /plan. Shortcut: Shift+Tab`,composerPlaceholder:`Describe what you want to do`,assistantWaitingThinking:`Thinking`,assistantWaitingOrganizing:`Organizing the answer`,assistantWaitingContinuing:`This may take a little longer`,assistantWaitingAriaLabel:`Assistant is preparing a response`,customCommandsHint:`Custom commands`,customCommandsEmptyHint:`No project commands yet.`,customCommandsListDescription:`List project custom commands`,customCommandsNewDescription:`Create a project custom command`,initCommandDescription:`Generate or update a concise AGENTS.md contributor guide for the current repository.`,planCommandDescription:`Create a plan first; this turn cannot edit files or run commands.`,reviewCommandDescription:`Review pending code changes before commit; this turn cannot edit files.`,summaryCommandDescription:`Create a new chat with this conversation summarized to reduce context usage.`,compactCommandDescription:`Compact this conversation context in place using the same rolling summary as auto-compaction.`,clearCommandDescription:`Clear the current chat history and context without calling the model.`,helpCommandDescription:`Show all available commands and their usage.`,yoloBlockedReason:`Local tool {name} was blocked by the current Agent permission mode. Switch to Full access or approve the tool call when prompted.`,globalToolBlockedReason:`Local tool {name} was blocked because this is a normal chat with no project attached. Start or open a project chat to use workspace tools.`,noActiveProjectToolBlockedReason:`Local tool {name} was blocked because there is no active project. Add or select a project to use workspace tools.`,generationAlreadyRunning:`Generation is still running. Stop it or wait until it finishes.`,generationStillRunning:`Generation is still running. Stop it or wait until it finishes before rolling back.`,noConversationTurnToRollback:`There is no conversation turn to roll back.`,rollbackConfirmTitle:`Confirm rollback?`,rollbackConfirm:`Roll back to before this message? This message and all following conversation history will be removed, and the message content will be restored to the composer.`,sharedRollbackConfirmTitle:`Confirm shared conversation rollback?`,sharedRollbackConfirm:`This will directly modify the sharer's original conversation. This message and all following conversation history will be removed, and the message content will be restored to the composer.`,confirmRollback:`Confirm rollback`,rollingBack:`Rolling back...`,rollbackFailed:`Rollback failed.`,retryFailed:`Retry failed.`,openCodeMessageHistoryActionUnavailable:`OpenCode does not support rollback, retry, or forking from a message position. These actions are unavailable for OpenCode conversations.`,openCodeConfigMenuLabel:`OpenCode config`,openCodeConfigButtonLabel:`Config`,openCodeConfigDisabledWhileStreaming:`OpenCode config is disabled while a generation is running.`,openCodeConfigModesTitle:`Mode`,openCodeConfigOptionsTitle:`Options`,openCodeModeMenuLabel:`OpenCode mode`,openCodeModeDisabledWhileStreaming:`OpenCode mode is disabled while a generation is running.`,openCodeUsageTokensTitle:`Used {used} / {size} tokens`,openCodeUsageCostTitle:`Cost: {amount} {currency}`,forkCurrentSession:`Duplicate current conversation`,forkCurrentSessionTitle:`Create a full copy of this OpenCode conversation as a new session.`,openCodeForkUnavailable:`This OpenCode conversation cannot be duplicated because no ACP session is available.`,openCodeForkFailed:`Failed to duplicate the conversation.`,copyFailed:`Copy failed. Please check clipboard permissions.`,errorBoundaryTitle:`Something went wrong`,errorBoundaryUnexpected:`An unexpected error occurred.`,errorBoundaryTryAgain:`Try again`,execute:`Run`,addCustomModelFirst:`Please add a custom model in Settings and make sure the model ID is filled in before saving.`,modelSetupRequired:`Please add a model before starting a new chat.`,modelSetupTitle:`No model configured yet`,modelSetupDescription:`Add an OpenAI-Compatible or Anthropic-compatible model to start chatting. QuickForge will only use models that you configure.`,modelSetupSupports:`Supports LiteLLM, OpenRouter, DeepSeek, Qwen, Zhipu, Ollama, and most /v1/chat/completions services.`,modelSetupLocalStorage:`Providers, model IDs, and API keys are stored locally by the QuickForge service on this machine.`,modelSetupAddModel:`Add model`,modelSetupUseLiteLlmExample:`Use LiteLLM example`,firstUseGuideTitle:`Start with a safe workflow`,firstUseGuideDescription:`Add a project, ask QuickForge to understand it, and use /plan before granting local tool access for code changes.`,firstUseGuideStepModel:`Confirm the model you want to use.`,firstUseGuideStepProject:`Add a local project so AI can use workspace context.`,firstUseGuideStepPlan:`Use /plan first; that turn cannot edit files or run commands.`,firstUseGuideConfigureModel:`Configure model`,firstUseGuideAddProject:`Add project`,firstUseGuideUsePrompt:`Try example prompt`,firstUseGuideCopyPrompt:`Copy /plan example`,firstUseGuideDismiss:`Got it`,firstUseGuideProjectPrompt:`/plan Read this project and explain its structure, run commands, and main risks. Do not modify files yet.`,firstUseGuideGeneralPrompt:`/plan Break this request into implementation steps and risks first. Do not modify files yet.`,defaultOptions:`General`,defaultOptionsDescription:`Configure language, default model, thinking level, tool display, and context management for new chats and scheduled tasks.`,memory:`Memory`,memoryDescription:`Let QuickForge remember useful preferences and habits across chats and projects.`,globalMemory:`Global memory`,globalMemoryDescription:`When enabled, QuickForge uses existing memory and can proactively remember durable preferences, habits, background, workflows, and goals that may help in future conversations.`,globalMemoryInfo:`Memory is stored locally and shared by all chats and projects. QuickForge avoids temporary task details, uncertain inferences, and sensitive credentials. Turn memory off to stop future reads and writes while keeping the existing file.`,memoryFile:`Memory file`,memoryFileDescription:`Saved as a readable Markdown file in the local QuickForge data directory.`,memoryCurrentSessionNote:`Changes are loaded by running chats before their next message. Turning memory off stops future reads and writes while keeping the existing file.`,memoryEnabledSaved:`Global memory enabled.`,memoryDisabledSaved:`Global memory disabled. Existing memory was kept.`,memoryContent:`Memory content`,memoryContentDescription:`View or edit the complete free-form Markdown document. Content and formatting are saved exactly as written.`,memoryContentDisabledDescription:`Turn global memory on to edit and save this file. Existing content remains available after reloading.`,memoryReload:`Reload`,memorySave:`Save memory`,memoryReloaded:`Memory reloaded.`,memoryContentSaved:`Global memory saved.`,memoryContentEmpty:`Global user memory is empty.`,defaultModel:`Default model`,defaultModelDescription:`Used by new chats and scheduled tasks unless overridden.`,defaultHarness:`Default Harness`,defaultHarnessDescription:`Used by new chats. The current blank chat updates immediately; existing chats keep their Harness.`,claudeCodeHarnessUnavailable:`Claude Code (not available yet)`,defaultThinkingLevel:`Default thinking level`,defaultThinkingLevelDescription:`Choose the default reasoning effort for supported models.`,toolDisplay:`Tool display`,toolDisplayModeDescription:`Compact shows summaries with details collapsed. Detailed shows full parameters and details with tool calls expanded.`,toolDisplayCompact:`Compact`,toolDisplayDetailed:`Detailed`,showContextUsage:`Show context usage`,showContextUsageDescription:`Show the context usage ring and details next to the model selector.`,fontSize:`Font size`,fontSizeDescription:`Adjust interface and conversation text size.`,fontSizeRangeDescription:`Drag to preview immediately; release to save.`,appearance:`Appearance`,appearanceDescription:`Customize the interface theme and font size.`,theme:`Theme`,themeDescription:`Switch between light and dark. Changes apply instantly.`,lightTheme:`Light`,darkTheme:`Dark`,appearanceSaved:`Appearance saved`,interfaceFontSize:`Interface font size`,messageFontSize:`Conversation font size`,messageFontSizeNote:`Applies to the main text in chat messages.`,fontSizeSaved:`Font size saved`,toolDetailsHidden:`Tool details are hidden in compact mode. Switch Tool display to Detailed in Settings to view full parameters.`,toolArgsSummary:`Arguments summary`,saveDefaultOptions:`Save defaults`,saving:`Saving...`,defaultOptionsSaved:`Default options saved`,networkConnection:`Network connection`,networkProxyMode:`Proxy mode`,networkProxyDirect:`Direct`,networkProxySystem:`Follow system`,networkProxyManual:`Manual proxy`,networkProxyPac:`PAC URL`,networkProxyDescription:`Controls supported external HTTP requests made by QuickForge. Localhost always connects directly. Follow system reads the operating-system proxy configuration, including PAC/WPAD when supported. Custom PAC URLs are supported by Desktop only.`,networkProxyAddress:`Proxy address`,networkProxyAddressDescription:`Enter an HTTP or HTTPS proxy URL with a port. Paths, query strings, fragments, and proxy credentials are not supported.`,networkProxyAddressRequired:`Enter a proxy address before saving.`,networkProxyAddressInvalid:`Enter a valid HTTP or HTTPS proxy address.`,networkProxyAddressProtocolError:`Only HTTP and HTTPS proxy addresses are supported.`,networkProxyAddressPortError:`The proxy address must include a host and port.`,networkProxyAddressCredentialsError:`Proxy credentials are not supported in the address.`,networkProxyAddressPathError:`The proxy address cannot contain a path, query string, or fragment.`,networkProxyPacUrl:`PAC URL`,networkProxyPacUrlDescription:`Enter an HTTP or HTTPS URL for a PAC script. Paths and query strings are supported; credentials and fragments are not.`,networkProxyPacUrlRequired:`Enter a PAC URL before saving.`,networkProxyPacUrlInvalid:`Enter a valid HTTP or HTTPS PAC URL.`,networkProxyPacUrlProtocolError:`Only HTTP and HTTPS PAC URLs are supported.`,networkProxyPacUrlHostError:`The PAC URL must include a host.`,networkProxyPacUrlCredentialsError:`Credentials are not supported in the PAC URL.`,networkProxyPacUrlFragmentError:`The PAC URL cannot contain a fragment.`,networkProxyPacUnsupported:`Custom PAC URLs are supported only by the Desktop runtime.`,networkProxySave:`Save proxy`,networkProxyRefresh:`Reload system proxy`,networkProxyRefreshDescription:`Reload the current operating-system proxy configuration and close existing network connections.`,networkProxyStatus:`Source: {source}; runtime: {runtime}.`,networkProxyUnsupported:`The operating-system proxy is not supported by this runtime.`,networkProxyLoadFailed:`Unable to load the current proxy configuration. Proxy controls are disabled.`,networkProxySaved:`Network proxy setting saved`,networkProxyRefreshed:`System proxy reloaded`,contextManagement:`Context Management`,contextUsageTitle:`Context usage`,contextUsageAriaLabel:`Context usage: {percent}%. Show details`,contextUsageTotal:`{used} / {limit} tokens`,contextUsageInputLabel:`Input / context`,contextUsageReservedOutputLabel:`Reserved output`,contextUsageSystemPromptLabel:`System prompt`,contextUsageToolsSchemaLabel:`Tools schema`,contextUsageMessagesLabel:`Messages`,contextUsageSourceServerShort:`Server calculated`,contextUsageSourceLocalShort:`Local estimate`,contextUsageScopeCompactedShort:`Compacted model context`,contextUsageScopeFullShort:`Full model context`,contextUsageUsed:`Context used: {percent}% ({used} / {limit} tokens)`,contextUsageInput:`Input/context: {tokens} ({source})`,contextUsageSourceProvider:`provider context`,contextUsageSourceMixed:`provider/local mixed context`,contextUsageSourceEstimated:`estimated context`,contextUsageLocalEstimate:`Local estimate: {tokens}`,contextUsageSystemPrompt:` System prompt: {tokens}`,contextUsageToolsSchema:` Tools schema: {tokens}`,contextUsageMessages:` Messages: {tokens}`,contextUsageProviderBaseline:` Provider usage baseline: {tokens}`,contextUsageTrailingMessages:` Trailing messages after usage: {tokens}`,contextUsageReservedOutput:`Reserved output: {tokens}`,contextUsageServerCalculated:`Source: server calculated via pi-agent-core/pi-ai`,contextUsageScopeCompacted:`Scope: compacted model context, not full visible chat history`,contextUsageScopeFull:`Scope: full model context`,contextUsageEffectiveMessages:`Messages: {effective} effective / {visible} visible`,contextUsageProviderTokens:`Provider context tokens: {tokens}`,autoCompactEnabled:`Automatically compact context`,autoCompactRequireConfirmation:`Ask before compacting automatically`,autoCompactRequireConfirmationDescription:`Ask for approval before QuickForge summarizes older history.`,autoCompactTriggerNote:`Checks run before each model request. Lower the threshold or reduce the model Context Window to test triggering.`,autoCompactThresholdPercent:`Compact when context reaches (%)`,autoCompactThresholdDescription:`Percentage of the model context window that triggers compaction.`,autoCompactKeepRecentTurns:`Keep recent user turns`,autoCompactKeepRecentTurnsDescription:`Recent turns stay in full detail after older context is summarized.`,autoCompactDescription:`When the estimated next request reaches the configured share of the model context window, QuickForge summarizes older history and continues the current task. This uses one extra model call.`,autoCompactHistoryPreserved:`The full chat history remains visible; only the context sent to the model is compacted.`,autoArchiveEnabled:`Automatically archive old conversations`,autoArchiveTriggerNote:`Conversations not updated for more than 30 days are moved to Archived conversations.`,autoArchiveDescription:`Archived conversations are not deleted. Turning this off only stops future automatic archiving; existing archived conversations can still be viewed and restored.`,autoArchiveSaved:`Automatic archive setting saved`,thinkingLevel:`Thinking level`,thinkingOff:`Off`,thinkingLow:`Low`,thinkingMedium:`Medium`,thinkingHigh:`High`,thinkingXHigh:`XHigh`,currentConfiguration:`Current configuration`,thinkingSupported:`Thinking`,thinkingNotSupported:`This model does not support thinking levels.`,thinkingRequiresReasoningModel:`Thinking levels require a reasoning / thinking model.`,customModels:`Custom Models`,customModelsTitle:`Custom models`,customModelsDescription:`Only use custom OpenAI-Compatible models that you configure.`,addModel:`Add model`,editModel:`Edit model`,delete:`Delete`,editCustomModel:`Edit custom model`,addCustomModel:`Add custom model`,providerName:`Provider name`,providerNamePlaceholder:`e.g., LiteLLM`,protocolType:`Protocol type`,protocolHelp:`Use OpenAI Compatible for LiteLLM, OpenRouter, and most /v1/chat/completions services. Use Anthropic Messages only for the direct Anthropic API.`,apiKey:`API Key`,apiKeyPlaceholder:`Leave empty if not required`,showApiKey:`Show API Key`,hideApiKey:`Hide API Key`,customHeaders:`Custom Headers JSON`,customHeadersPlaceholder:`{
3
3
  "X-Custom-Header": "value"
4
4
  }`,customHeadersHelp:`Optional provider-level HTTP headers. Must be a JSON object with string values. Headers are saved locally with this model configuration.`,invalidHeadersJson:`Custom headers must be a valid JSON object with string key-value pairs.`,modelId:`Model ID`,modelIdPlaceholder:`e.g., anthropic/claude-sonnet-4`,contextWindow:`Context Window`,maxTokens:`Max Tokens`,reasoningModel:`Reasoning / Thinking model (DeepSeek V4, Qwen, etc.)`,imageInputModel:`Image input / vision model`,imageInputModelHelp:`Enable only when the model documentation confirms image input support. When disabled, attached images are omitted before the request is sent so non-vision models do not fail.`,showModelInSelectors:`Show in model selectors`,showModelInSelectorsHelp:`Turn off to keep this model configured while hiding it from model selection lists.`,providerProtocol:`Protocol`,model:`Model`,reasoning:`Reasoning`,noModelAdded:`No model added`,modelsCount:`{count} model(s)`,modelIndex:`Model #{index}`,modelsList:`Models`,atLeastOneModel:`At least one model is required.`,duplicateModelId:`Duplicate model IDs are not allowed.`,cancel:`Cancel`,save:`Save`,yes:`Yes`,no:`No`,loading:`Loading...`,noCustomModels:`No custom models yet. Click "Add model".`,fillProviderBaseUrlModel:`Please fill in provider name and Base URL.`,saveCustomModelFailed:`Failed to save custom model.`,confirmDeleteProvider:`Delete {name}?`,deleteFailed:`Delete failed.`,selectCustomModel:`Select custom model`,close:`Close`,back:`Back`,more:`More`,searchModels:`Search models...`,searchSettings:`Search settings...`,noSettingsResults:`No matching settings found`,noMatchingCustomModels:`No matching custom models`,presets:`Quick templates`,presetOpenai:`OpenAI`,presetDeepseek:`DeepSeek`,presetGlm:`Zhipu GLM`,presetOllama:`Local Ollama`,presetLitellm:`LiteLLM Proxy`,presetCustom:`Custom`,providerAdvanced:`Advanced options`,expandModel:`Adjust context window, max tokens, reasoning, image input`,addHeader:`Add header`,headerName:`Header name`,headerValue:`Value`,removeHeader:`Remove header`,testConnection:`Test connection`,testingConnection:`Testing...`,connectionOk:`Connection OK`,connectionFailed:`Connection failed`,testRequiresFields:`Fill in Base URL and at least one model ID.`,readFile:`Read File`,manageGlobalMemory:`Manage Memory`,searchFiles:`Search Files`,writeFile:`Write File`,editFile:`Edit File`,runCommand:`Run Command`,presentFiles:`Present Files`,generateImage:`Generate Image`,generatingImage:`Generating image...`,generatedImageAlt:`Generated image {index}`,openGeneratedImage:`Open generated image`,downloadGeneratedImage:`Download generated image`,executeInTerminal:`Run in terminal`,confirmExecuteCommandTitle:`Run command in terminal?`,confirmExecuteMultipleCommands:`This will run multiple lines in your local terminal. Continue?`,confirmExecuteDangerousCommand:`This command may modify your system, publish packages, push code, or run a remote script. Continue?`,terminalCommandExecuteFailed:`Failed to run command in terminal.`,runSubagent:`Run subagent`,subagentGeneral:`General`,subagentExplore:`Explore`,subagentRunning:`{name} running`,subagentCompleted:`{name} completed`,subagentFailed:`{name} failed`,subagentTask:`Task`,subagentContext:`Context`,subagentExpectedOutput:`Expected output`,subagentResult:`Result`,subagentToolCalls:`Tool calls`,subagentToolApprovalWaiting:`{source} requests approval: {toolName}`,toolApprovalSourceSubagent:`Source: {source} subagent`,activateSkill:`Activate Skill`,readSkillResource:`Read Skill Resource`,yoloModeSyncFailed:`Failed to sync Agent access mode. The previous state has been restored.`,toolApprovalFailed:`Failed to submit tool approval. Please try again.`,toolApprovalSubmitting:`Submitting...`,toolApprovalRetry:`Retry submission`,toolApprovalNeedsConfirmation:`Confirmation required`,toolApprovalRiskCommand:`This operation will execute a Shell command in the current workspace.`,toolApprovalRiskFileChange:`This operation will modify files in the current workspace.`,toolApprovalRiskExternal:`This operation may send data to an external service and change remote content.`,toolApprovalRiskGeneric:`This tool may change local or external state. Review the parameters before continuing.`,toolApprovalViewDetails:`View full parameters`,toolApprovalHideDetails:`Hide full parameters`,toolApprovalSource:`Source`,toolApprovalServer:`Server`,toolApprovalPlugin:`Plugin`,toolApprovalTool:`Tool`,toolApprovalPath:`Path`,toolApprovalCommand:`Command`,toolApprovalDisabled:`This approval cannot be handled here.`,autoCompactApprovalStatus:`Context near limit`,autoCompactApprovalTitle:`Compact older conversation content`,autoCompactApprovalRisk:`QuickForge will summarize older history and keep the latest {keepRecentTurns} user turn(s). It will not modify workspace files.`,autoCompactApprovalAccept:`Compact now`,autoCompactApprovalReject:`Not now`,autoCompactApprovalUnavailable:`Context compaction approval is unavailable in this view.`,sharedApprovalReadOnly:`Please handle this approval in the sharer’s original conversation.`,terminateCommand:`Terminate`,terminateCommandTitle:`Terminate this running command`,commandTerminateRequested:`Terminating...`,running:`Running`,done:`Done`,error:`Error`,taskCompleted:`Task completed`,taskError:`Task error`,systemNotifications:`System notifications`,systemNotificationsDescription:`Show a browser or Android notification when a chat or scheduled task finishes while QuickForge is running in the background.`,systemNotificationsPermissionGranted:`Permission granted on this device. Foreground activity continues to use in-app messages only.`,systemNotificationsPermissionPrompt:`Permission has not been requested on this device.`,systemNotificationsPermissionDenied:`Permission was denied on this device.`,systemNotificationsUnsupported:`System notifications are not supported in this environment.`,systemNotificationsDeniedHelp:`Notification permission was denied. Allow it in the browser site settings or Android app settings, then try again.`,systemNotificationsEnabled:`System notifications enabled on this device.`,systemNotificationsDisabled:`System notifications disabled on this device.`,systemNotificationsTest:`Send test`,systemNotificationTestTitle:`QuickForge notification test`,systemNotificationTestFailed:`The test notification could not be displayed. Check the system permission and try again.`,systemNotificationOpenDetails:`Tap to open QuickForge for details.`,called:`Called`,input:`Input`,output:`Output`,details:`Details`,scheduledTasks:`Scheduled Tasks`,scheduledTasksDescription:`Tasks are saved in the local backend service and run by the cron expression parsed by AI.`,createTask:`Create task`,editTask:`Edit`,cancelEditTask:`Cancel edit`,saveTask:`Save task`,taskScheduleDescriptionLabel:`Schedule description`,taskScheduleDescriptionPlaceholder:`e.g., Every day at 9 AM, send this to AI: generate my daily sales report.`,quickAiParseTask:`AI parses this description into a cron expression. The system stores and runs by cron.`,taskTitleLabel:`Task name`,taskTitlePlaceholder:`e.g., Daily work summary`,promptContentLabel:`AI will send this content`,promptContentPlaceholder:`Write the exact content that should be sent to AI when this task runs.`,taskEnabledSwitch:`Enable this task`,taskInstructionPlaceholder:`e.g., Generate a daily sales report at 9 AM every day`,aiParseTask:`AI Parse`,confirmCreate:`Confirm create`,taskList:`Task list`,noScheduledTasks:`No scheduled tasks yet. Enter a natural language instruction above to create one.`,taskEnabled:`Enabled`,taskRunning:`Running`,taskPaused:`Paused`,taskFinished:`Completed`,taskFailed:`Failed`,executeNow:`Run now`,enable:`Enable`,pauseTask:`Pause`,deleteTask:`Delete`,recentExecutions:`Recent executions`,executionSuccess:`Success`,executionRunning:`Running`,nextExecution:`Next`,lastExecution:`Last`,noModelAvailable:`No models available`,noProjectBound:`No project`,aiParsed:`AI parsed, please confirm`,taskName:`Task name`,executionRule:`Execution rule`,nextExecutionTime:`Next execution`,taskProject:`Project`,taskThinkingLevel:`Thinking`,aiInstruction:`AI instruction`,taskModel:`Model`,taskThinking:`Thinking`,taskProjectLabel:`Project`,taskExecutionMode:`Execution mode`,taskExecutionModeSerial:`Serial`,taskExecutionModeParallel:`Parallel`,taskExecutionModeHelp:`This only controls whether the same task may overlap. Different scheduled tasks still run in parallel.`,tasksCount:`{total} tasks, {enabled} enabled`,confirmDeleteTask:`Are you sure you want to delete this scheduled task? This cannot be undone.`,waitingForResult:`Waiting for result`,autoRun:`Auto`,manualRun:`Manual test`,runInputContent:`Sent to AI`,runAiResult:`AI result`,runDuration:`Duration: `,taskListTab:`Task list`,executionHistoryTab:`Execution history`,agentsTab:`Agents`,agentsDescription:`Create reusable Agent Profiles for scheduled tasks and run_subagent delegation.`,createAgent:`Create agent`,editAgent:`Edit agent`,builtinAgent:`Built-in`,builtinAgentReadonly:`Built-in agents are read-only in this version.`,builtinAgentModelSettings:`Model & thinking settings`,builtinAgentModelOnly:`This built-in Agent is system-managed. Only its model and thinking level can be changed.`,readonlyAgentDescription:`This Agent is loaded from a read-only source and cannot be edited here.`,enabledAsSubagent:`Enabled as subagent`,enableAsSubagent:`Enable as subagent`,disableAsSubagent:`Disable as subagent`,noDescription:`No description.`,maxRuntimeMs:`Max runtime: `,maxToolCalls:`Max tool calls: `,defaultAgent:`Default Agent`,executionAgent:`Execution Agent: `,agentName:`Agent name`,agentLabel:`Display name`,agentLabelPlaceholder:`e.g., Code Review Agent`,agentDescription:`Description`,agentSystemPrompt:`System prompt`,agentModelMode:`Model mode`,agentModelInherit:`Inherit parent model`,agentModelFixed:`Use fixed model`,agentFixedModel:`Fixed model`,agentThinkingLevel:`Thinking level`,agentThinkingInherit:`Inherit caller setting`,agentThinkingDescription:`When the runtime model does not support reasoning, this automatically falls back to Off.`,agentThinkingUnsupported:`The selected fixed model does not support reasoning, so thinking is Off.`,allowedTools:`Allowed tools`,agentSourcePath:`Source path`,highRiskTool:`High risk`,confirmDeleteAgent:`Are you sure you want to delete this custom agent? Scheduled tasks using it will fall back to the default agent.`,aiFillAgent:`AI fill`,aiFillAgentDescription:`Describe the agent you want. AI will only fill agent name, display name, description, and system prompt.`,aiFillAgentPlaceholder:`e.g., Create a read-only code review agent focused on architecture, bugs, and test coverage.`,aiFillAgentLoading:`Generating...`,aiFillAgentNoModel:`Please configure a default model first.`,aiFillAgentFailed:`AI fill failed. Please check model configuration and API key, then try again.`,aiFillAgentInputRequired:`Please describe the agent you want to create.`,taskContent:`Task content`,viewDetails:`View details`,moreActions:`More actions`,historyFilters:`Filters`,allTasks:`All tasks`,allStatuses:`All statuses`,allTriggers:`All triggers`,triggerType:`Trigger`,keyword:`Keyword`,keywordPlaceholder:`Search input, result, or error`,startTime:`Start time`,endTime:`End time`,query:`Search`,reset:`Reset`,previousPage:`Previous`,nextPage:`Next`,pageSize:`{size} / page`,paginationSummary:`Page {page} / {pages}, {total} total`,noExecutionHistory:`No execution history yet.`,viewConversation:`View conversation`,createdAt:`Created at`,status:`Status`,search:`Search`,noMatchingOptions:`No matching options`,searchDialog:`Search conversations...`,noSearchResults:`No matching conversations found`,searchHint:`Enter keywords to search loaded conversations`,scheduledTasksLabel:`Scheduled Tasks`,skills:`Skills`,mcp:`MCP`,mcpServers:`MCP Servers`,plugins:`Plugins`,pluginMentionHeader:`Plugins`,composerAddMenu:`Add`,composerAddAttachment:`Attachment`,composerAddPlugins:`Plugins`,composerAddBack:`Back`,pluginDocumentsName:`Documents`,pluginDocumentsDescription:`Create and edit document artifacts`,pluginSpreadsheetsName:`Spreadsheets`,pluginSpreadsheetsDescription:`Create, analyze, and structure spreadsheet files`,pluginPresentationsName:`Presentations`,pluginPresentationsDescription:`Create and edit presentations`,pluginsDescription:`Manage local QuickForge plugins. This first version supports manifest-based plugins that contribute Agent tools.`,pluginsReload:`Reload plugins`,loadingPlugins:`Loading plugins...`,noPlugins:`No plugins found`,noPluginsDescription:`Place a plugin folder with plugin.json under one of these search paths, then reload.`,pluginsCount:`{total} plugins, {enabled} enabled`,pluginToolsCount:`{count} tools`,pluginPermissionsCount:`{count} permissions`,pluginDetails:`Plugin details`,pluginVersion:`Version`,pluginStatusLoaded:`Loaded`,pluginStatusDisabled:`Disabled`,pluginStatusError:`Error`,pluginTools:`Tools`,pluginPermissions:`Declared permissions`,pluginNoTools:`No tools declared.`,pluginNoPermissions:`No permissions declared.`,pluginTrustedNotice:`Plugins are local trusted Node.js code in this MVP; permissions are displayed for review and future enforcement.`,pluginDiscoveryErrors:`Plugin discovery errors`,enablePlugin:`Enable`,disablePlugin:`Disable`,pluginsLoadFailed:`Failed to load plugins.`,pluginsSaveFailed:`Failed to update plugin.`,manageMcpServers:`Manage MCP servers`,mcpNoServersDescription:`No MCP servers configured yet. Click "Add server" or paste an mcpServers JSON on the right.`,mcpConfiguredServers:`Configured servers`,mcpAddServer:`Add server`,mcpEditServer:`Edit server`,mcpServerName:`Server name`,mcpCommand:`Command`,mcpTransport:`Transport`,mcpUrl:`URL`,mcpArgs:`Arguments, one per line`,mcpCwd:`Working directory`,mcpEnv:`Environment variables, KEY=value per line`,mcpToolsCount:`{count} tools`,mcpLoadFailed:`Failed to load MCP servers.`,mcpSaveFailed:`Failed to save MCP server.`,mcpDeleteFailed:`Failed to delete MCP server.`,mcpReconnectFailed:`Failed to reconnect MCP server.`,mcpDeleteConfirm:`Delete MCP server "{name}"?`,mcpImportConfig:`Import MCP JSON`,mcpImportConfigDescription:"Paste an MCP JSON configuration in mcpServers format. QuickForge supports stdio, HTTP, and SSE transports. For remote servers, headers are accepted and resolved from backend environment variables when using ${...}.",mcpUseExample:`Use example`,mcpImportUpdate:`Import / update`,mcpReplaceAll:`Replace all`,mcpReplaceConfirm:`This will remove MCP servers that are not included in the JSON. Continue?`,mcpInvalidJson:`MCP configuration must be valid JSON.`,mcpInvalidConfigJson:`MCP configuration must contain a mcpServers object.`,mcpEmptyConfigJson:`mcpServers cannot be empty.`,mcpInvalidServerName:`Invalid MCP server name: {name}. Use lowercase letters, numbers, and hyphens only.`,mcpInvalidServerConfig:`MCP server "{name}" must be an object.`,mcpInvalidTransport:`MCP server "{name}" transport must be stdio, http, or sse.`,mcpMissingCommand:`MCP server "{name}" requires command for stdio transport.`,mcpMissingUrl:`MCP server "{name}" requires url for HTTP/SSE transport.`,mcpArgsMustBeArray:`MCP server "{name}" args must be an array.`,mcpEnvMustBeObject:`MCP server "{name}" env must be an object.`,mcpHeadersMustBeObject:`MCP server "{name}" headers must be an object.`,mcpHeaders:`Headers, KEY=value per line`,mcpReconnectServer:`Reconnect`,mcpMoreTools:`+{count}`,mcpNamePlaceholder:`e.g. my-server`,mcpUrlPlaceholder:`https://example.com/mcp`,mcpCommandPlaceholder:`e.g. npx`,mcpTabServer:`Server`,mcpTabJson:`JSON`,optional:`Optional`,globalSkills:`Global Skills`,projectSkills:`Project Skills`,help:`Help`,projectCommands:`Project Commands`,projectCommandsDescription:`Configure extra Markdown slash-command directories for the current project. QuickForge also reads user-level commands from ~/.quickforge/commands/ (shared across all projects), then project directories .claude/commands, .opencode/commands, .ai/commands, and these configured directories in order. Later duplicate command names override earlier ones.`,projectCommandsProjectDescription:`Choose the project whose command directories should be configured.`,selectProjectForCommands:`Please select or add a project before configuring project commands.`,commandDirectory:`Command directory`,commandDirectories:`Command directories`,commandDirectoriesDescription:`Add one directory per line. Relative paths are resolved from the selected project root.`,commandDirectoryPlaceholder:`.claude/commands
5
5
  .opencode/commands
@@ -62,4 +62,4 @@ D:\\shared\\ai-commands`,commandDirectoryHelp:`一行一个目录。支持相对
62
62
  `).trim():``}function zc(e,t){let n=t;if(e[t]?.role===`assistant`){for(let r=t-1;r>=0;r--)if(e[r].role===`user`||e[r].role===`user-with-attachments`){n=r;break}}let r=e[n];return!r||r.role!==`user`&&r.role!==`user-with-attachments`?-1:n}function Bc(e){return e.role!==`user`&&e.role!==`user-with-attachments`?``:typeof e.content==`string`?e.content:Lc(e.content,`
63
63
 
64
64
  `)}async function Vc(e){if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(e);return}let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.left=`-9999px`,document.body.append(t),t.select(),document.execCommand(`copy`),t.remove()}function Hc(e){let t=e.find(e=>e.role===`user`||e.role===`user-with-attachments`);if(!t||t.role!==`user`&&t.role!==`user-with-attachments`)return`New chat`;let n=t.content,r=(typeof n==`string`?n:Lc(n)).trim().replace(/\s+/g,` `);return r?r.length>46?`${r.slice(0,43)}...`:r:`New chat`}function Uc(e){return e===`New chat`||e===W(`newChat`)}function Wc(e){return e.some(e=>e.role===`user`||e.role===`user-with-attachments`)}function Gc(e){return Wc(e)&&e.some(e=>e.role===`assistant`)}var Kc=new Set([`idle`,`error`,`aborted`]);function qc(e,t=Date.now()){e.lastAccessedAt=t}function Jc(e,t,n=5){let r=Array.from(e).filter(e=>e.sessionId!==t&&e.status!==`running`&&!e.agent.state.isStreaming&&Kc.has(e.status));return r.length<=n?[]:(r.sort((e,t)=>(e.lastAccessedAt??0)-(t.lastAccessedAt??0)),r.slice(0,r.length-n).map(e=>e.sessionId))}function Yc(e,t){let n=e.get(t);return n?(n.unsubscribe(),n.agent.dispose(),e.delete(t),!0):!1}function Xc(e){for(let t of[...e.keys()])Yc(e,t)}function Zc({title:e,description:t,actions:n,onCancel:r}){let i=(0,H.useRef)(null),a=(0,H.useRef)(!1),o=(0,H.useCallback)(()=>{a.current||(a.current=!0,r())},[r]),s=(0,H.useCallback)(e=>{a.current||(a.current=!0,e.onClick())},[]);return(0,H.useEffect)(()=>{i.current?.focus();let e=e=>{if(e.key===`Escape`&&o(),e.key===`Enter`){let e;for(let t=n.length-1;t>=0;t--)if(n[t].enter!==!1){e=n[t];break}e&&s(e)}};return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[o,s,n]),(0,qr.createPortal)((0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/45 px-4 py-6`,onMouseDown:e=>{e.target===e.currentTarget&&o()},children:(0,K.jsxs)(`div`,{className:G(`w-full max-w-[420px] rounded-2xl border border-border bg-background p-5 shadow-quickforge`),role:`dialog`,"aria-modal":`true`,"aria-labelledby":e?`message-dialog-title`:void 0,"aria-describedby":`message-dialog-description`,onMouseDown:e=>e.stopPropagation(),children:[e?(0,K.jsx)(`h2`,{id:`message-dialog-title`,className:`text-base font-semibold text-foreground/90`,children:e}):null,(0,K.jsx)(`p`,{id:`message-dialog-description`,className:G(`text-sm leading-6 text-muted-foreground/72`,e?`mt-2`:void 0),children:t}),(0,K.jsx)(`div`,{className:`mt-6 flex justify-end gap-2`,children:n.map((e,t)=>(0,K.jsx)(q,{ref:e.autoFocus?i:void 0,variant:e.variant,size:`sm`,onClick:()=>s(e),children:e.label},`${e.label}-${t}`))})]})}),document.body)}function Qc(e){return new Promise(t=>{let n=document.createElement(`div`);document.body.appendChild(n);let r=(0,it.createRoot)(n);function i(){r.unmount(),setTimeout(()=>n.remove(),0)}function a(e){i(),t(e)}r.render(e(a))})}function $c(e){return Qc(t=>(0,K.jsx)(Zc,{title:e.title,description:e.description,onCancel:()=>t(!1),actions:[{label:e.cancelLabel??`Cancel`,variant:`outline`,onClick:()=>t(!1),autoFocus:e.variant===`destructive`},{label:e.confirmLabel??`Confirm`,variant:e.variant===`destructive`?`destructive`:`default`,autoFocus:e.variant!==`destructive`,enter:e.variant!==`destructive`,onClick:()=>t(!0)}]}))}function $(e){let t=typeof e==`string`?{description:e}:e;return Qc(e=>(0,K.jsx)(Zc,{title:t.title,description:t.description,onCancel:()=>e(),actions:[{label:t.confirmLabel??`OK`,autoFocus:!0,onClick:()=>e()}]}))}function el(e){let{storageRef:t,activeModelRef:n,agentAccessModeRef:r,activeProjectRef:i,defaultWorkspaceRef:a,setAgentAccessMode:o,switchActiveProject:s,refreshSessions:c,updateSessionTitle:l,loadCloudModels:u}=e,d=(0,H.useRef)(null),f=(0,H.useRef)(new Map),p=(0,H.useRef)(`global`),m=(0,H.useRef)(void 0),h=(0,H.useRef)(`New chat`),g=(0,H.useRef)(void 0),_=(0,H.useRef)(null),v=(0,H.useRef)(0),y=(0,H.useRef)(null),b=(0,H.useRef)(null),x=(0,H.useRef)(0),S=(0,H.useRef)(e.onTaskComplete);(0,H.useEffect)(()=>{S.current=e.onTaskComplete}),(0,H.useEffect)(()=>()=>{y.current?.abort()},[]);let[C,w]=(0,H.useState)(null),[T,E]=(0,H.useState)(),[D,O]=(0,H.useState)(`New chat`),[k,ee]=(0,H.useState)(`global`),[te,A]=(0,H.useState)(),[j,ne]=(0,H.useState)({}),[re,M]=(0,H.useState)(0),[N,P]=(0,H.useState)(),ie=(0,H.useCallback)(e=>{e.length!==0&&ne(t=>{let n={...t},r=!1;for(let t of e)Object.prototype.hasOwnProperty.call(n,t)&&(delete n[t],r=!0);return r?n:t})},[]),F=(0,H.useCallback)(e=>{let t=Jc(f.current.values(),e);for(let e of t)Yc(f.current,e);ie(t)},[ie]),ae=(0,H.useCallback)((e,t)=>{!e||e===t||[...f.current.values()].some(t=>t.agent===e)||e.dispose()},[f]),I=(0,H.useCallback)(async e=>{if(m.current===e.sessionId){let t=e.agent.state.messages,n=e.title;Uc(n)&&(n=Hc(t)),g.current=e.createdAt??new Date().toISOString(),h.current=n,O(n)}await c({broadcast:!0})},[c]),L=(0,H.useCallback)(e=>{ae(d.current,e.agent),qc(e),p.current=e.scope,m.current=e.sessionId,g.current=e.createdAt,h.current=e.title,ee(e.scope),E(e.sessionId),O(e.title),A(e.project),d.current=e.agent,w(e.agent);let t=new URL(window.location.href);t.searchParams.set(`session`,e.sessionId),window.history.replaceState({},``,t)},[ae]),R=(0,H.useCallback)(async(e,s=X(),g)=>{let v=d.current,y=f.current.get(s);if(y)return g?.attachToView!==!1&&g?.shouldAttachToView?.()!==!1&&(ae(v,y.agent),L(y)),y.agent;let b=g?.scope??p.current,x=b===`project`?g?.project??i.current:g?.project??a.current;if(b===`project`&&!x?.id)throw Error(`Cannot create project chat without an active project.`);let C=new Date().toISOString(),{model:w,thinkingLevel:T,tools:E,...D}=e??{},k=t.current,ee=k?await ir(k):{},te=g?.harness??ee.harness??`quickforge`,A=w??ee.model??n.current,j=w!==void 0&&!!D.messages?.length,re=te===`opencode`?wn():j?k?await mr(k,A):Jn(A):await hr(k,A,u),M=te===`opencode`?`off`:T??ee.thinkingLevel??tr(re);te===`quickforge`&&(n.current=re);let N=Nn(g?.accessMode,g?.yoloMode??r.current);r.current=N,o(N);let P=await Mc.create(s,{scope:b,projectId:b===`project`?x?.id:void 0,source:g?.source,channelId:g?.channelId,channelName:g?.channelName,harness:te,sourceHarnessSessionId:g?.sourceHarnessSessionId,accessMode:N,yoloMode:Pn(N),model:re,thinkingLevel:M,messages:D.messages??[],title:g?.title,contextCompaction:D.contextCompaction});D.contextCompaction&&!P.state.contextCompaction&&(P.state.contextCompaction=D.contextCompaction);let ie=P.state.isStreaming?`running`:P.state.errorMessage?`error`:`idle`,R={sessionId:P.sessionId,agent:P,scope:b,project:x,title:g?.title??`New chat`,createdAt:g?.createdAt??C,status:ie,startedAt:C,lastAccessedAt:Date.now(),unsubscribe:()=>void 0};return R.unsubscribe=P.subscribe(e=>{if(e.type===`agent_start`&&(R.status=`running`,R.startedAt=R.startedAt??new Date().toISOString(),R.finishedAt=void 0,ne(e=>({...e,[R.sessionId]:R.status}))),e.type===`message_end`&&(P.state.messages=[...P.state.messages]),e.type===`agent_end`){let t=R.status===`running`,n=e;R.status=n.status===`aborted`?`aborted`:n.errorMessage||P.state.errorMessage?`error`:`idle`,R.finishedAt=new Date().toISOString(),qc(R),ne(e=>({...e,[R.sessionId]:R.status})),I(R).catch(e=>V.error(`Failed to sync session UI:`,e)),t&&S.current?.(R.sessionId,R.title,R.status),F(m.current)}if(e.type===`title_updated`){let t=e;t.title&&(R.title=t.title),R.sessionId===m.current&&t.title&&(h.current=t.title,O(t.title)),t.title&&l(R.sessionId,t.title)}if(e.type===`session_forked`){let t=e;if(!t.targetSessionId)return;c({broadcast:!0}).catch(e=>V.error(`Failed to refresh sessions:`,e)),_.current?.(t.targetSessionId,{title:t.title,createdAt:t.createdAt,scope:t.scope,projectId:t.projectId??void 0})}}),f.current.set(s,R),R.status!==`idle`&&ne(e=>({...e,[R.sessionId]:R.status})),g?.attachToView!==!1&&g?.shouldAttachToView?.()!==!1&&(v instanceof Nc?v.promoteTo(R.agent):d.current===v&&ae(v,R.agent),L(R)),F(m.current),g?.refreshSessions!==!1&&P.state.messages.length>0&&await c({broadcast:!0}),P},[L,ae,F,c,I,l,u,t,n,r,i,a,o]),oe=(0,H.useCallback)(async e=>{let i=++x.current,o=t.current,s=o?await ir(o):{},c=e.harness??s.harness??`quickforge`,l=s.model??n.current,f=c===`opencode`?wn():await hr(o,l,u),_=c===`opencode`?`off`:s.thinkingLevel??tr(f);c===`quickforge`&&(n.current=f);let v=e.scope,y=v===`project`?e.project:e.project??a.current,b=new Nc({scope:v,project:y,model:f,thinkingLevel:_,accessMode:r.current,harness:c,yoloMode:Pn(r.current),createAgent:R});if(b.subscribe(e=>{d.current===b&&(e.type===`message_start`||e.type===`agent_end`)&&M(e=>e+1)}),i!==x.current||e.shouldAttachToView?.()===!1)return b.dispose(),b;ae(d.current),p.current=v,m.current=void 0,g.current=void 0,h.current=`New chat`,ee(v),E(void 0),O(`New chat`),A(y),d.current=b,w(b);let S=new URL(window.location.href);return S.searchParams.delete(`session`),window.history.replaceState({},``,S),b},[n,R,a,ae,u,t,r]),z=(0,H.useCallback)(async e=>{let n=d.current,r=x.current,i=e??(t.current?(await ir(t.current)).harness??`quickforge`:`quickforge`);if(x.current!==r||!Fc({isDeferredSession:n instanceof Nc&&d.current===n,isStreaming:n?.state.isStreaming??!1,messageCount:n?.state.messages.length??0,currentScope:p.current,targetScope:`global`,currentHarness:n?.harness??`quickforge`,defaultHarness:i}))return!1;let a=n,o=x.current+1;return await oe({scope:`global`,harness:i,shouldAttachToView:()=>{let e=d.current;return e===a&&e instanceof Nc&&!e.state.isStreaming&&e.state.messages.length===0&&p.current===`global`}}),x.current===o&&d.current!==a},[d,p,oe,t]);(0,H.useEffect)(()=>{let e=e=>{let t=e.detail;z(t?.harness).catch(e=>{V.error(`Failed to apply the default Harness to the blank chat:`,e)})};return window.addEventListener(ac,e),()=>window.removeEventListener(ac,e)},[z]);let se=(0,H.useCallback)(async(e,t)=>{let u=++v.current;y.current?.abort();let d=new AbortController;y.current=d;let p=()=>v.current===u&&!d.signal.aborted;P(e);try{if(!p())return!1;let u=f.current.get(e);if(u){if(u.scope===`project`&&u.project?.id&&i.current?.id!==u.project.id)try{await s(u.project.id)}catch(e){V.error(`Failed to switch project for running session:`,e)}return p()?(L(u),F(u.sessionId),!0):!1}let g,v;try{let t=await Mc.restore(e,{signal:d.signal});g=t.agent,v=t.snapshot}catch(e){return d.signal.aborted||!p()||V.error(`Failed to restore session:`,e),!1}if(!p())return g.dispose(),!1;let y=t?.scope??v.scope??`global`,b=t?.projectId??v.projectId??void 0,x;if(y===`project`&&b)if(i.current?.id!==b)try{x=await s(b)}catch(e){return g.dispose(),V.error(`Failed to switch project for session:`,e),p()&&$(W(`projectSwitchFailed`)),!1}else x=i.current;if(!p())return g.dispose(),!1;n.current=g.state.model;let C=Nn(g.state.accessMode,g.state.yoloMode);r.current=C,o(C);let w={sessionId:e,agent:g,scope:y,project:y===`project`?x:a.current,title:v.title??t?.title??`New chat`,createdAt:v.createdAt??t?.createdAt??new Date().toISOString(),status:v.status===`running`||g.state.isStreaming?`running`:g.state.errorMessage?`error`:v.status===`aborted`?`aborted`:`idle`,startedAt:v.startedAt??void 0,finishedAt:v.finishedAt??void 0,lastAccessedAt:Date.now(),unsubscribe:()=>void 0};return w.unsubscribe=g.subscribe(e=>{if(e.type===`agent_start`&&(w.status=`running`,w.startedAt=w.startedAt??new Date().toISOString(),w.finishedAt=void 0,ne(e=>({...e,[w.sessionId]:w.status}))),e.type===`message_end`&&(g.state.messages=[...g.state.messages]),e.type===`agent_end`){let t=w.status===`running`,n=e;w.status=n.status===`aborted`?`aborted`:n.errorMessage||g.state.errorMessage?`error`:`idle`,w.finishedAt=new Date().toISOString(),qc(w),ne(e=>({...e,[w.sessionId]:w.status})),I(w).catch(e=>V.error(`Failed to sync session UI:`,e)),t&&S.current?.(w.sessionId,w.title,w.status),F(m.current)}if(e.type===`title_updated`){let t=e;t.title&&(w.title=t.title),w.sessionId===m.current&&t.title&&(h.current=t.title,O(t.title)),t.title&&l(w.sessionId,t.title)}if(e.type===`session_forked`){let t=e;if(!t.targetSessionId)return;c({broadcast:!0}).catch(e=>V.error(`Failed to refresh sessions:`,e)),_.current?.(t.targetSessionId,{title:t.title,createdAt:t.createdAt,scope:t.scope,projectId:t.projectId??void 0})}}),f.current.set(e,w),w.status!==`idle`&&ne(e=>({...e,[w.sessionId]:w.status})),L(w),F(e),!0}finally{y.current===d&&(y.current=null),v.current===u&&P(void 0)}},[n,i,r,L,a,F,c,o,s,I,l]),ce=(0,H.useCallback)((e,t)=>{let n=b.current;if(n?.sessionId===e)return n.promise;let r=se(e,t);return b.current={sessionId:e,promise:r},r.then(()=>{b.current?.promise===r&&(b.current=null)},()=>{b.current?.promise===r&&(b.current=null)}),r},[se]);return(0,H.useEffect)(()=>{_.current=ce},[ce]),{agentRef:d,taskMapRef:f,currentSessionIdRef:m,currentChatScopeRef:p,agent:C,currentSessionId:T,currentTitle:D,chatScope:k,currentToolProject:te,taskStatuses:j,chatPanelRevision:re,loadingSessionId:N,createAgent:R,startDeferredSession:oe,applyDefaultHarnessToBlankSession:z,loadSession:ce,syncSessionUI:I,setChatPanelRevision:M,setCurrentAgentMessages:(0,H.useCallback)(e=>{d.current&&(d.current.state.messages=e)},[]),updateCurrentAgentModel:(0,H.useCallback)(e=>{d.current&&(d.current.state.model=e,d.current.updateModel(e).catch(e=>{V.error(`Failed to sync model to server:`,e)}))},[]),setCurrentTitleRef:(0,H.useCallback)(e=>{h.current=e,O(e)},[])}}function tl(e){if(!e)return 0;let t=new Date(e).getTime();return Number.isNaN(t)?0:t}function nl(e,t){let n=t===`createdAt`?`createdAt`:`lastModified`;return[...e].sort((e,t)=>{let r=tl(t.pinnedAt)-tl(e.pinnedAt);return r===0?e.pinnedAt&&!t.pinnedAt?-1:!e.pinnedAt&&t.pinnedAt?1:tl(t[n])-tl(e[n]):r})}function rl(e){let t=new Set;return e.filter(e=>t.has(e.id)?!1:(t.add(e.id),!0))}function il(e,t,n){let r=e.items.some(e=>e.id===t.id);return{...e,items:nl(rl([t,...e.items.filter(e=>e.id!==t.id)]),n),total:r?e.total:e.total+1}}function al(e,t,n){return e.items.some(e=>e.id===t)?{...e,items:e.items.map(e=>e.id===t?{...e,title:n}:e)}:e}var ol=20;function sl(e){if(!e)return!1;let t=e.trim();return!t||t===`undefined`||t===`null`||t===`false`?!1:!Number.isNaN(Date.parse(t))}function cl({backendRef:e,expandedProjectIds:t,externalProjectIds:n,viewMode:r,sortMode:i,onBroadcastSessionsChanged:a}){let[o,s]=(0,H.useState)({items:[],total:0,loading:!1}),[c,l]=(0,H.useState)({items:[],total:0,loading:!1}),[u,d]=(0,H.useState)({}),[f,p]=(0,H.useState)({items:[],total:0,loading:!1}),m=(0,H.useRef)(u),h=(0,H.useRef)(t),g=(0,H.useRef)(n??new Set),_=(0,H.useRef)(0);(0,H.useEffect)(()=>{m.current=u},[u]),(0,H.useEffect)(()=>{h.current=t},[t]),(0,H.useEffect)(()=>{g.current=n??new Set},[n]);let v=(0,H.useCallback)(()=>(_.current+=1,_.current),[]),y=(0,H.useCallback)(e=>e===_.current,[]),b=(0,H.useMemo)(()=>rl([...c.items,...o.items,...Object.values(u).flatMap(e=>e.items),...f.items]),[c.items,o.items,u,f.items]),x=(0,H.useCallback)(async(t,n=_.current)=>{let r=e.current;if(r){l(e=>({...e,loading:!0}));try{let e=await r.fetchPaginatedFromIndex(`sessions-metadata`,`pinnedAt`,{direction:`desc`,limit:ol,offset:t,pinned:`only`});if(!y(n))return;let a=e.values.filter(e=>sl(e.pinnedAt));l(n=>({items:nl(t===0?a:rl([...n.items,...a]),i),total:e.total,loading:!1}))}catch{if(!y(n))return;l(e=>({...e,loading:!1}))}}},[e,y,i]),S=(0,H.useCallback)(async(t,n=_.current)=>{let r=e.current;if(r){s(e=>({...e,loading:!0}));try{let e=i===`createdAt`?`createdAt`:`lastModified`,a=await r.fetchPaginatedFromIndex(`sessions-metadata`,e,{direction:`desc`,limit:ol,offset:t,scope:`global`});if(!y(n))return;s(e=>({items:nl(t===0?a.values:rl([...e.items,...a.values]),i),total:a.total,loading:!1}))}catch{if(!y(n))return;s(e=>({...e,loading:!1}))}}},[e,y,i]),C=(0,H.useCallback)(async(t,n,r=_.current)=>{let a=e.current;if(a){d(e=>{let n=e[t];return{...e,[t]:{...n??{items:[],total:0},loading:!0}}});try{let e=i===`createdAt`?`createdAt`:`lastModified`,o=await a.fetchPaginatedFromIndex(`sessions-metadata`,e,{direction:`desc`,limit:ol,offset:n,scope:`project`,projectId:t});if(!y(r))return;d(e=>{let r=e[t]?.items??[];return{...e,[t]:{items:nl(n===0?o.values:rl([...r,...o.values]),i),total:o.total,loading:!1}}})}catch{if(!y(r))return;d(e=>{let n=e[t];return{...e,[t]:{...n??{items:[],total:0},loading:!1}}})}}},[e,y,i]),w=(0,H.useCallback)(async(t,n=_.current)=>{let r=e.current;if(r){p(e=>({...e,loading:!0}));try{let e=i===`createdAt`?`createdAt`:`lastModified`,a=await r.fetchPaginatedFromIndex(`sessions-metadata`,e,{direction:`desc`,limit:ol,offset:t,scope:`projects`});if(!y(n))return;p(e=>({items:nl(t===0?a.values:rl([...e.items,...a.values]),i),total:a.total,loading:!1}))}catch{if(!y(n))return;p(e=>({...e,loading:!1}))}}},[e,y,i]),T=(0,H.useCallback)(async t=>{if(!e.current)return;let n=v();if(await Promise.all([x(0,n),S(0,n)]),!y(n))return;if(r===`timeline`){d(e=>{let t={};for(let[n,r]of Object.entries(e))t[n]={...r,loading:!1};return t}),await w(0,n),t?.broadcast&&y(n)&&a?.();return}p(e=>({...e,loading:!1}));let i=new Set([...Object.keys(m.current),...h.current,...g.current]);i.size===0?d({}):await Promise.all([...i].map(e=>C(e,0,n))),t?.broadcast&&y(n)&&a?.()},[e,y,S,x,C,w,v,a,r]),E=(0,H.useCallback)(e=>{if(sl(e.pinnedAt)&&l(t=>il(t,e,i)),e.scope===`project`&&e.projectId){d(t=>{let n=t[e.projectId];return n?{...t,[e.projectId]:il(n,e,i)}:t}),r===`timeline`&&p(t=>il(t,e,i));return}s(t=>il(t,e,i))},[i,r]),D=(0,H.useCallback)((e,t)=>{l(n=>al(n,e,t)),s(n=>al(n,e,t)),p(n=>al(n,e,t)),d(n=>{let r=!1,i=Object.fromEntries(Object.entries(n).map(([n,i])=>{let a=al(i,e,t);return a!==i&&(r=!0),[n,a]}));return r?i:n})},[]),O=(0,H.useCallback)(e=>u[e]?.items??[],[u]),k=(0,H.useCallback)(e=>{let t=u[e];return t?t.items.length<t.total:!0},[u]),ee=(0,H.useCallback)(e=>u[e]?.loading??!1,[u]),te=(0,H.useCallback)(e=>e in u,[u]),A=(0,H.useCallback)(()=>{c.loading||c.items.length>=c.total||x(c.items.length)},[x,c.items.length,c.loading,c.total]),j=(0,H.useCallback)(()=>{S(o.items.length)},[o.items.length,S]),ne=(0,H.useCallback)(e=>{let t=u[e];C(e,t?.items.length??0)},[C,u]),re=(0,H.useCallback)(()=>{f.loading||f.items.length>=f.total||w(f.items.length)},[w,f.items.length,f.loading,f.total]);return(0,H.useEffect)(()=>{Promise.resolve().then(()=>T())},[T]),{allLoadedSessions:b,pinnedSessions:c.items,pinnedHasMore:c.items.length<c.total,pinnedLoading:c.loading,globalSessions:o.items,sessionsForProject:O,projectTimelineSessions:f.items,projectTimelineHasMore:f.items.length<f.total,projectTimelineLoading:f.loading,globalHasMore:o.items.length<o.total,projectHasMore:k,globalLoading:o.loading,projectLoading:ee,projectLoaded:te,loadGlobalSessions:S,loadProjectSessions:C,refreshSessions:T,upsertSessionMetadata:E,updateSessionTitle:D,loadMorePinned:A,loadMoreGlobal:j,loadMoreProject:ne,loadMoreProjectTimeline:re}}function ll(){let[e,t]=(0,H.useState)([]),n=(0,H.useCallback)(e=>{t(t=>[...t,{...e,id:X(),createdAt:Date.now()}])},[]);return{toasts:e,handleTaskComplete:(0,H.useCallback)((e,t,r)=>{n({sessionId:e,title:t,status:r})},[n]),addToast:n,dismissToast:(0,H.useCallback)(e=>{t(t=>t.filter(t=>t.id!==e))},[])}}var ul=`tool-display-settings`,dl={toolDisplayMode:`compact`,showContextUsage:!1},fl={...dl};function pl(e){if(!e||typeof e!=`object`)return{...dl};let t=e;return{toolDisplayMode:t.toolDisplayMode===`detailed`?`detailed`:`compact`,showContextUsage:t.showContextUsage===!0}}function ml(){return fl}async function hl(e){let t=pl(await e.settings.get(ul));return fl=t,t}async function gl(e,t){let n=pl(t);await e.settings.set(ul,n),fl=n}var _l=`font-size-settings`,vl=`font-size-settings-force-13px-v1`,yl={min:12,max:18},bl={interfaceFontSizePx:13,messageFontSizePx:13},xl=`quickforge:font-size-settings-changed`;function Sl(){if(typeof document>`u`)return bl.interfaceFontSizePx;let e=Number.parseFloat(getComputedStyle(document.documentElement).fontSize);return Number.isFinite(e)?e:bl.interfaceFontSizePx}function Cl(e=Sl()){let t=Tl(e-1,13,yl.min,yl.max);return{fontSize:t,lineHeight:Math.round(t*1.54)}}function wl(e=Sl()){return{fontSize:Tl(e-2,12,yl.min,yl.max),lineHeight:1.2}}function Tl(e,t,n,r){let i=Number(e);return Number.isFinite(i)?Math.min(r,Math.max(n,Math.round(i))):t}function El(e){if(!e||typeof e!=`object`)return{...bl};let t=e;return{interfaceFontSizePx:Tl(t.interfaceFontSizePx??t.baseFontSizePx??t.bodyFontSizePx,bl.interfaceFontSizePx,yl.min,yl.max),messageFontSizePx:Tl(t.messageFontSizePx,bl.messageFontSizePx,yl.min,yl.max)}}function Dl(e){if(typeof document>`u`)return;let t=El(e),n=document.documentElement;n.style.fontSize=`${t.interfaceFontSizePx}px`,n.style.setProperty(`--quickforge-message-font-size`,`${t.messageFontSizePx}px`),n.style.setProperty(`--quickforge-message-line-height`,`1.625`),window.dispatchEvent(new CustomEvent(xl,{detail:t}))}async function Ol(e){if(!await e.settings.get(vl)){let t={...bl};return await e.settings.set(_l,t),await e.settings.set(vl,!0),t}return El(await e.settings.get(_l))}async function kl(e){let t=await Ol(e);return Dl(t),t}async function Al(e,t){let n=El(t);await e.settings.set(_l,n),Dl(n)}var jl=`appearance-settings`,Ml={theme:`light`};function Nl(e){return!e||typeof e!=`object`?{...Ml}:{theme:e.theme===`dark`?`dark`:`light`}}function Pl(e){if(typeof document>`u`)return;let t=Nl(e),n=document.documentElement;n.classList.toggle(`dark`,t.theme===`dark`),n.style.setProperty(`color-scheme`,t.theme)}function Fl(){return typeof document>`u`?Ml.theme:document.documentElement.classList.contains(`dark`)?`dark`:`light`}async function Il(e){return Nl(await e.settings.get(jl))}async function Ll(e){let t=await Il(e);return Pl(t),t}async function Rl(e,t){let n=Nl(t);await e.settings.set(jl,n),Pl(n)}function zl({storageRef:e,backendRef:t,activeModelRef:n,agentAccessModeRef:r,taskMapRef:i,refreshSessions:a,loadProject:o,initAgentAccessMode:s,createAgent:c,loadSession:l,loadCloudModels:u,setNeedsModelSetup:d,onStorageReady:f}){let[p,m]=(0,H.useState)(!1),[h,g]=(0,H.useState)(),[_,v]=(0,H.useState)(0),y=(0,H.useRef)({refreshSessions:a,loadProject:o,initAgentAccessMode:s,createAgent:c,loadSession:l,loadCloudModels:u,setNeedsModelSetup:d,onStorageReady:f});return(0,H.useEffect)(()=>{y.current={refreshSessions:a,loadProject:o,initAgentAccessMode:s,createAgent:c,loadSession:l,loadCloudModels:u,setNeedsModelSetup:d,onStorageReady:f}}),(0,H.useEffect)(()=>{let a=!1;async function o(){let{refreshSessions:i,loadProject:o,initAgentAccessMode:s,createAgent:c,loadSession:l,loadCloudModels:u,setNeedsModelSetup:d,onStorageReady:f}=y.current;try{m(!1),g(void 0);let p=await $n();if(a)return;e.current=p,f?.(p),t.current=p.backend,await _t(p),await hl(p),await Ll(p),await kl(p),await Promise.all([i(),o()]),r.current=await s(p);let h=[];try{h=await u()}catch(e){V.warn(`Failed to restore QuickForge Cloud models:`,e)}let _=await ir(p),v=jn(_.harness),y=v===`opencode`?null:await fr(p,h,_.model),b=y??(v===`opencode`?wn():null);y&&(n.current=y);let x=()=>c({model:b,thinkingLevel:_.thinkingLevel,tools:[]},X(),{scope:`global`,attachToView:!0,harness:v}),S=new URLSearchParams(window.location.search).get(`session`);S&&await l(S)?d(!1):(d(v===`quickforge`&&!y),b&&await x()),m(!0)}catch(e){V.error(`Failed to bootstrap QuickForge:`,e),a||g(W(`localServiceUnavailableDescription`))}}o();let s=i.current;return()=>{a=!0,Xc(s)}},[e,t,n,r,i,_]),{ready:p,startupError:h,retryBootstrap:(0,H.useCallback)(()=>{m(!1),g(void 0),v(e=>e+1)},[])}}var Bl=`update-check-settings`,Vl={frequency:`startup`,lastCheckAt:null,ignoredVersion:null};function Hl(e){if(!e||typeof e!=`object`)return{...Vl};let t=e;return{frequency:[`startup`,`daily`,`weekly`,`off`].includes(t.frequency)?t.frequency:Vl.frequency,lastCheckAt:typeof t.lastCheckAt==`string`?t.lastCheckAt:null,ignoredVersion:typeof t.ignoredVersion==`string`?t.ignoredVersion:null}}var Ul=1440*60*1e3;function Wl(e,t=Date.now()){switch(e.frequency){case`off`:return!1;case`startup`:return!0;case`daily`:case`weekly`:{if(!e.lastCheckAt)return!0;let n=Date.parse(e.lastCheckAt);if(Number.isNaN(n))return!0;let r=e.frequency===`daily`?Ul:7*Ul;return t-n>=r}default:return!1}}async function Gl(e){return Hl(await e.settings.get(Bl))}async function Kl(e,t){await e.settings.set(Bl,Hl(t))}var ql={status:`idle`,updateAvailable:!1};function Jl(){if(typeof document>`u`)return!1;let e=window;return document.body.classList.contains(`quickforge-desktop-app`)||e.__quickforgeDesktopApp===!0}function Yl(e,t){let[n,r]=(0,H.useState)(ql),i=(0,H.useRef)(!1);return(0,H.useEffect)(()=>{if(!t||i.current||Jl())return;let n=e.current;n&&(i.current=!0,(async()=>{let e;try{e=await Gl(n)}catch(e){V.error(`Failed to load update-check settings:`,e);return}if(Wl(e)){r(e=>({...e,status:`checking`}));try{let t=await fetch(`/api/system/update/check`,{cache:`no-store`});if(!t.ok){r(e=>({...e,status:`error`}));return}let i=await t.json(),a=i.updateAvailable&&i.latestVersion!==e.ignoredVersion;try{await Kl(n,{...e,lastCheckAt:new Date().toISOString()})}catch(e){V.error(`Failed to persist last update-check time:`,e)}r({status:`done`,currentVersion:i.currentVersion,latestVersion:i.latestVersion,updateAvailable:a})}catch(e){V.error(`Startup update check failed:`,e),r(e=>({...e,status:`error`}))}}})())},[t,e]),{result:n,dismissUpdate:(0,H.useCallback)(()=>{let t=e.current,i=n.latestVersion;!t||!i||(r(e=>({...e,updateAvailable:!1})),(async()=>{try{await Kl(t,{...await Gl(t),ignoredVersion:i})}catch(e){V.error(`Failed to persist ignored update version:`,e)}})())},[n.latestVersion,e])}}var Xl=[`low`,`medium`,`high`,`xhigh`];function Zl(e){switch(e){case`low`:return W(`thinkingLow`);case`medium`:return W(`thinkingMedium`);case`high`:return W(`thinkingHigh`);case`xhigh`:return W(`thinkingXHigh`);default:return W(`thinkingOff`)}}function Ql(e,t=``){let n=document.createElement(`button`);return n.type=`button`,n.className=e,n.textContent=t,n}function $l(e){document.querySelectorAll(`.quickforge-model-menu, .quickforge-model-submenu, .quickforge-model-sheet-backdrop`).forEach(e=>{e.__quickforgeCleanup?.(),e.remove()}),e?.setAttribute(`aria-expanded`,`false`)}function eu(e){return e??document.querySelector(`.quickforge-model-trigger`)}function tu(e,t){let n=eu(t),r=Math.min(260,window.innerWidth-24);e.style.width=`${r}px`;let i=e.offsetHeight||360;if(!n){e.style.left=`${Math.max(12,Math.round((window.innerWidth-r)/2))}px`,e.style.top=`${Math.max(12,Math.round((window.innerHeight-i)/2))}px`;return}let a=n.getBoundingClientRect(),o=Math.max(12,Math.min(a.right-r,window.innerWidth-r-12)),s=a.top-i-8,c=a.bottom+8,l=s>=12?s:Math.min(c,window.innerHeight-i-12);e.style.left=`${o}px`,e.style.top=`${Math.max(12,l)}px`}function nu(e,t){let n=Math.min(252,window.innerWidth-24);e.style.width=`${n}px`;let r=t.getBoundingClientRect(),i=e.offsetHeight||320,a=r.left-n-0>=12?r.left-n-0:Math.min(r.right+0,window.innerWidth-n-12),o=Math.max(12,Math.min(r.top,window.innerHeight-i-12));e.style.left=`${a}px`,e.style.top=`${o}px`}function ru(e){let t=Ql(`quickforge-model-menu-item`);t.setAttribute(`role`,`menuitemradio`),t.setAttribute(`aria-checked`,String(!!e.selected)),e.disabled&&(t.disabled=!0);let n=document.createElement(`span`);n.className=`quickforge-model-menu-item-label`,n.textContent=e.label;let r=document.createElement(`span`);return r.className=`quickforge-model-menu-item-suffix`,r.textContent=e.chevron?`›`:e.selected?`✓`:``,t.append(n,r),e.onPointerDown&&(t.onpointerdown=e.onPointerDown),e.onPointerEnter&&(t.onpointerenter=e.onPointerEnter),e.onClick&&t.addEventListener(`click`,e.onClick),t}function iu(e,t,n,r,i){let a=r.thinkingLevel??`off`,o=e,s=document.createElement(`div`);s.className=`quickforge-model-sheet-backdrop`;let c=document.createElement(`div`);c.className=`quickforge-model-sheet`,c.setAttribute(`role`,`dialog`),c.setAttribute(`aria-modal`,`true`),c.setAttribute(`aria-label`,W(`selectCustomModel`));let l=document.createElement(`div`);l.className=`quickforge-model-sheet-drag-zone`;let u=document.createElement(`div`);u.className=`quickforge-model-sheet-handle`,l.append(u);let d=document.createElement(`div`);d.className=`quickforge-model-sheet-header`;let f=document.createElement(`div`);f.className=`quickforge-model-sheet-title`,f.textContent=W(`selectCustomModel`);let p=Ql(`quickforge-model-sheet-close`,`×`);p.setAttribute(`aria-label`,W(`close`)),p.title=W(`close`),p.onpointerdown=e=>{e.preventDefault(),e.stopPropagation(),$l(i)},d.append(f,p);let m=r.showThinking===!1?null:document.createElement(`div`),h;if(m){m.className=`quickforge-model-sheet-section`;let e=document.createElement(`div`);e.className=`quickforge-model-sheet-section-label`,e.textContent=W(`reasoning`),h=()=>{if(m.replaceChildren(e),o?.reasoning===!0){let e=document.createElement(`div`);e.className=`quickforge-model-sheet-thinking-options`;let t=new Map;for(let n of Xl){let i=Ql(`quickforge-model-sheet-thinking-option`,Zl(n));t.set(n,i),i.onpointerdown=e=>{e.preventDefault(),e.stopPropagation(),a=n,r.onThinkingLevelSelect?.(n);for(let[e,n]of t){let t=e===a;n.classList.toggle(`is-selected`,t),n.setAttribute(`aria-pressed`,String(t))}};let o=n===a;i.classList.toggle(`is-selected`,o),i.setAttribute(`aria-pressed`,String(o)),e.append(i)}m.append(e)}else{let e=document.createElement(`div`);e.className=`quickforge-model-menu-note`,e.textContent=W(`thinkingNotSupported`),m.append(e)}},h()}let g=document.createElement(`div`);g.className=`quickforge-model-sheet-section-label quickforge-model-sheet-model-label`,g.textContent=W(`model`);let _=document.createElement(`div`);_.className=`quickforge-model-sheet-model-list`,_.setAttribute(`role`,`menu`),_.setAttribute(`aria-label`,W(`model`));let v=0;_.addEventListener(`scroll`,()=>{v=Date.now()});let y=new Map,b=e=>{o=e,!e.reasoning&&a!==`off`&&(a=`off`,r.onThinkingLevelSelect?.(`off`));for(let[t,n]of y){let r=Qe(n,e);t.setAttribute(`aria-checked`,String(r));let i=t.querySelector(`.quickforge-model-menu-item-suffix`);i&&(i.textContent=r?`✓`:``)}h?.(),n(e)};if(r.noneLabel){let t=ru({label:r.noneLabel,selected:e===null});t.addEventListener(`click`,e=>{e.preventDefault(),e.stopPropagation(),!(Date.now()-v<300)&&(r.onNoneSelect?.(),$l(i))}),_.append(t)}let x=[...t].sort((e,t)=>$e(e).localeCompare($e(t)));for(let e of x){let t=ru({label:r.modelLabelOverride?r.modelLabelOverride(e):$e(e),selected:Qe(o,e),onClick:t=>{t.preventDefault(),t.stopPropagation(),!(Date.now()-v<300)&&b(e)}});y.set(t,e),_.append(t)}c.append(l,d,...m?[m]:[],g,_),c.addEventListener(`pointerdown`,e=>e.stopPropagation()),s.addEventListener(`pointerdown`,e=>{e.target===s&&$l(i)});let S=0,C=!1,w=!1,T,E=e=>{e.pointerType===`mouse`&&e.button!==0||(S=e.clientY,C=!0,w=!1,c.style.transition=`none`)},D=e=>{if(!C)return;let t=e.clientY-S;t>0&&(w=!0,c.style.transform=`translateY(${t}px)`,s.style.background=`rgb(15 23 42 / ${Math.max(0,.34*(1-t/480))})`)},O=()=>{C&&(C=!1,c.style.transition=`transform 0.24s ease`,(w&&Number.parseFloat(c.style.transform.replace(/[^0-9.-]/g,``))||0)>=112?(c.style.transform=`translateY(110%)`,s.style.background=`rgb(15 23 42 / 0)`,T=setTimeout(()=>$l(i),220)):(c.style.transform=``,s.style.background=``))};l.addEventListener(`pointerdown`,E),window.addEventListener(`pointermove`,D),window.addEventListener(`pointerup`,O),window.addEventListener(`pointercancel`,O);let k=e=>{if(e.type===`resize`){window.innerWidth>768&&$l(i);return}!(e instanceof KeyboardEvent)||e.key!==`Escape`||(e.preventDefault(),$l(i))};s.__quickforgeCleanup=()=>{T&&clearTimeout(T),document.removeEventListener(`keydown`,k,!0),window.removeEventListener(`resize`,k,!0),window.removeEventListener(`pointermove`,D),window.removeEventListener(`pointerup`,O),window.removeEventListener(`pointercancel`,O)},s.append(c),document.body.append(s),i?.setAttribute(`aria-expanded`,`true`),document.addEventListener(`keydown`,k,!0),window.addEventListener(`resize`,k,!0)}function au(e,t,n,r={}){let i=eu(r.anchor);if(document.querySelector(`.quickforge-model-menu, .quickforge-model-sheet-backdrop`)){$l(i);return}iu(e,t,n,{...r,showThinking:!1,onNoneSelect:r.noneLabel?()=>n(null):void 0},i)}function ou(e,t,n,r,i={}){let a=eu(i.anchor);if(document.querySelector(`.quickforge-model-menu, .quickforge-model-sheet-backdrop`)){$l(a);return}if(window.innerWidth<=768){iu(e,t,n,i,a);return}let o=i.thinkingLevel??`off`,s=e,c=null,l=document.createElement(`div`);l.className=`quickforge-model-menu`,l.setAttribute(`role`,`menu`),l.setAttribute(`aria-label`,W(`selectCustomModel`));let u=()=>{c?.remove(),c=document.createElement(`div`),c.className=`quickforge-model-submenu`,c.setAttribute(`role`,`menu`),c.setAttribute(`aria-label`,W(`model`));let e=document.createElement(`div`);e.className=`quickforge-model-menu-header`,e.textContent=W(`model`),c.append(e);let r=[...t].sort((e,t)=>$e(e).localeCompare($e(t)));for(let e of r)c.append(ru({label:$e(e),selected:Qe(s,e),onPointerDown:t=>{t.preventDefault(),t.stopPropagation(),!e.reasoning&&o!==`off`&&(o=`off`,i.onThinkingLevelSelect?.(`off`)),s=e,n(e),$l(a)}}));c.addEventListener(`pointerdown`,e=>e.stopPropagation()),document.body.append(c),nu(c,l)},d=()=>{l.replaceChildren();let e=document.createElement(`div`);if(e.className=`quickforge-model-menu-header`,e.textContent=W(`reasoning`),l.append(e),s?.reasoning===!0)for(let e of Xl)l.append(ru({label:Zl(e),selected:o===e,onPointerDown:t=>{t.preventDefault(),t.stopPropagation(),o=e,i.onThinkingLevelSelect?.(e),d(),tu(l,a)}}));else{let e=document.createElement(`div`);e.className=`quickforge-model-menu-note`,e.textContent=W(`thinkingNotSupported`),l.append(e)}let t=document.createElement(`div`);t.className=`quickforge-model-menu-separator`,l.append(t),l.append(ru({label:s?$e(s):W(`noModelAdded`),chevron:!0,onPointerEnter:u,onPointerDown:e=>{e.preventDefault(),e.stopPropagation(),u()}}))},f=()=>$l(a),p=e=>{if(e.type===`resize`||e.type===`scroll`){tu(l,a),c&&nu(c,l);return}if(e instanceof KeyboardEvent){if(e.key!==`Escape`)return;e.preventDefault()}else{let t=e.target;if(l.contains(t)||c?.contains(t)||a?.contains(t))return}f()};l.__quickforgeCleanup=()=>{document.removeEventListener(`pointerdown`,p,!0),document.removeEventListener(`keydown`,p,!0),window.removeEventListener(`resize`,p,!0),window.removeEventListener(`scroll`,p,!0)},l.addEventListener(`pointerdown`,e=>e.stopPropagation()),d(),document.body.append(l),tu(l,a),a?.setAttribute(`aria-expanded`,`true`),document.addEventListener(`pointerdown`,p,!0),document.addEventListener(`keydown`,p,!0),window.addEventListener(`resize`,p,!0),window.addEventListener(`scroll`,p,!0)}function su({storageRef:e,activeModelRef:t,agentRef:n,createAgent:r,updateCurrentAgentModel:i,setChatPanelRevision:a,setNeedsModelSetup:o,setRestoredDraft:s,notifySettingsChanged:c,openSettingsPage:l,loadCloudModels:u}){let d=(0,H.useCallback)(async()=>{let s=e.current;if(!s)return!1;let l=await fr(s);return l?(t.current=l,o(!1),await er(s,l),n.current?(i(l),a(e=>e+1)):await r({model:l,tools:[]},X(),{scope:`global`,attachToView:!0}),c(),!0):(o(!0),!1)},[e,t,n,r,i,a,o,c]),f=(0,H.useCallback)((e,t)=>{l(e,t)},[l]),p=(0,H.useCallback)(()=>{f(`customModels`)},[f]);return{activateConfiguredModel:d,openModelSettings:p,openDefaultOptionsSettings:(0,H.useCallback)(()=>{f(`defaults`)},[f]),openAboutSettings:(0,H.useCallback)(()=>{f(`about`)},[f]),activateLiteLlmExampleModel:(0,H.useCallback)(async()=>{let s=e.current;if(!s)return;let l=Yn(Hn);await vr(s,Hn,l),await er(s,l),t.current=l,o(!1),n.current?(i(l),a(e=>e+1)):await r({model:l,tools:[]},X(),{scope:`global`,attachToView:!0}),c()},[e,t,n,r,i,a,o,c]),openCustomModelSelector:(0,H.useCallback)(async r=>{let o=e.current,c=n.current;if(!o||!c)return;let l=r instanceof HTMLElement?r:r?.currentTarget instanceof HTMLElement?r.currentTarget:document.querySelector(`.quickforge-model-trigger`),d=document.querySelector(`agent-interface message-editor textarea`),m=document.querySelector(`agent-interface message-editor`),h=d?.value??``,g=m?.attachments?[...m.attachments]:[],_=mn();if(!_){try{_=await ur(o),gn(_)}catch(e){V.error(`Failed to load custom models, falling back to cache:`,e),_=hn()}if(!_)return}let v=await u().catch(e=>(V.warn(`Failed to load QuickForge Cloud models:`,e),[])),y=dr(_,v);if(y.length===0){await $c({description:W(`addCustomModelFirst`),confirmLabel:W(`modelSetupAddModel`),cancelLabel:W(`cancel`)})&&p();return}ou(c.state.model??t.current,y,e=>{let n=e,r=n.reasoning?c.state.thinkingLevel:`off`;c.state.thinkingLevel!==r&&(c.state.thinkingLevel=r,c.updateThinkingLevel(r).catch(e=>{V.error(`Failed to sync thinking level to server:`,e)})),t.current=n,i(n),(h||g.length>0)&&s({id:Date.now(),sessionId:c.sessionId,text:h,attachments:g}),a(e=>e+1),er(o,n).catch(e=>{V.error(`Failed to save active model:`,e)})},async e=>{e.provider!==`quickforge-cloud`&&f(`customModels`,e.provider)},{thinkingLevel:c.state.thinkingLevel,anchor:l,onThinkingLevelSelect:e=>{c.state.thinkingLevel=e,c.updateThinkingLevel(e).catch(e=>{V.error(`Failed to sync thinking level to server:`,e)}),a(e=>e+1)}})},[e,t,n,i,a,s,p,f,u])}}var cu=`x-quickforge-action`,lu=`cloud-action`,uu=new Set([`GET`,`HEAD`,`OPTIONS`]),du=class extends Error{status;code;details;constructor(e,{status:t=0,code:n=`cloud_request_failed`,details:r}={}){super(e),this.name=`CloudClientError`,this.status=t,this.code=n,this.details=r}};async function fu(e,t={}){let n=String(t.method||`GET`).toUpperCase(),r=await fetch(e,{...t,cache:`no-store`,headers:{Accept:`application/json`,...t.headers||{},...uu.has(n)?{}:{[cu]:lu},...t.body===void 0?{}:{"Content-Type":`application/json`}}});if(!r.ok){let e=`QuickForge Cloud request failed (${r.status})`,t=`cloud_request_failed`,n;try{let i=await r.json();typeof i.error==`string`?e=i.error:i.error?.message&&(e=i.error.message),typeof i.code==`string`?t=i.code:typeof i.error==`object`&&typeof i.error?.code==`string`&&(t=i.error.code),typeof i.error==`object`&&(n=i.error?.details)}catch{}throw new du(e,{status:r.status,code:t,details:n})}return r.json()}function pu(e){return fu(`/api/cloud/config`,{signal:e})}function mu(e,t){return fu(`/api/cloud/config`,{method:`PUT`,body:JSON.stringify(e),signal:t})}function hu(e,t){return fu(`/api/cloud/test-connection`,{method:`POST`,body:JSON.stringify({cloudUrl:e}),signal:t})}function gu(e){return fu(`/api/cloud/identity/reset`,{method:`POST`,body:JSON.stringify({confirm:`reset-cloud-identity`}),signal:e})}function _u(e){return fu(`/api/cloud/status`,{signal:e})}function vu(e){return fu(`/api/cloud/remote/status`,{signal:e})}function yu(e){return fu(`/api/cloud/device/start`,{method:`POST`,body:`{}`,signal:e})}function bu(e){return fu(`/api/cloud/device/poll`,{method:`POST`,body:`{}`,signal:e})}function xu(e){return fu(`/api/cloud/device/cancel`,{method:`POST`,body:`{}`,signal:e})}async function Su(e){let t=await fu(`/api/cloud/models`,{signal:e});return Array.isArray(t.items)?t.items:[]}function Cu(e){return fu(`/api/cloud/usage`,{signal:e})}async function wu(e){let t=await fu(`/api/cloud/installations`,{signal:e});return Array.isArray(t.items)?t.items:[]}function Tu(e,t){return fu(`/api/cloud/installations/${encodeURIComponent(e)}`,{method:`DELETE`,signal:t})}function Eu(e){return fu(`/api/cloud/logout`,{method:`POST`,signal:e})}var Du=`quickforge:cloud-state-changed`;function Ou(e=!0){let[t,n]=(0,H.useState)(!1),r=(0,H.useRef)([]),i=(0,H.useRef)(null),a=(0,H.useRef)(null),o=(0,H.useRef)(null),s=(0,H.useRef)(0),c=(0,H.useRef)(!0),l=(0,H.useCallback)(()=>{s.current+=1,a.current?.abort(),o.current?.abort(),a.current=null,o.current=null,i.current=null,r.current=[]},[]),u=(0,H.useCallback)(async(t=!1)=>{if(!e||!c.current)return[];if(t&&(r.current=[]),!t&&r.current.length>0)return r.current;if(i.current)return i.current;let o=s.current,l=new AbortController;a.current=l;let u=(async()=>{try{let e=await _u(l.signal);if(!c.current||o!==s.current||l.signal.aborted)return[];if(n(!!(e.enabled!==!1&&e.configured)),e.enabled===!1||!e.configured||e.mode===`local`||!e.hasSession)return r.current=[],[];let t=await Su(l.signal);return!c.current||o!==s.current||l.signal.aborted?[]:(r.current=t,t)}catch(e){if(!c.current||o!==s.current||l.signal.aborted)return[];throw e}})().finally(()=>{i.current===u&&(i.current=null),a.current===l&&(a.current=null)});return i.current=u,u},[e]);return(0,H.useEffect)(()=>{c.current=!0;let e=()=>{if(l(),!c.current)return;let e=s.current,t=new AbortController;o.current=t,_u(t.signal).then(r=>{c.current&&e===s.current&&!t.signal.aborted&&n(!!(r.enabled!==!1&&r.configured))}).catch(()=>void 0).finally(()=>{o.current===t&&(o.current=null)})};return window.addEventListener(Du,e),()=>{window.removeEventListener(Du,e),c.current=!1,l()}},[l]),(0,H.useEffect)(()=>{e||l()},[e,l]),{configured:t,loadCloudModels:u}}function ku(){let e=new URL(window.location.href);e.searchParams.delete(`session`),window.history.replaceState({},``,e)}function Au({storageRef:e,activeModelRef:t,activeProjectRef:n,currentChatScopeRef:r,currentSessionIdRef:i,taskMapRef:a,agentRef:o,startDeferredSession:s,createAgent:c,syncSessionUI:l,setCurrentAgentMessages:u,setChatPanelRevision:d,refreshSessions:f,needsModelSetup:p,setNeedsModelSetup:m,switchActiveProject:h,closeWorkspacePage:g,setRestoredDraft:_}){let v=(0,H.useCallback)(async()=>{if(p){if(((e.current?await ir(e.current):{}).harness??`quickforge`)!==`opencode`){$(W(`modelSetupRequired`));return}m(!1)}g();let t=o.current,n=await Ic({isDeferredSession:t instanceof Nc,isStreaming:t?.state.isStreaming??!1,messageCount:t?.state.messages.length??0,currentScope:r.current,targetScope:`global`,currentHarness:t?.harness??`quickforge`},async()=>(e.current?await ir(e.current):{}).harness??`quickforge`);if(n.action!==`reuse`){if(n.action===`replace`){_(void 0),ku(),await s({scope:`global`,harness:n.defaultHarness});return}_(void 0),ku(),await s({scope:`global`})}},[o,r,p,m,_,g,s,e]),y=(0,H.useCallback)(async t=>{if(p){if(((e.current?await ir(e.current):{}).harness??`quickforge`)!==`opencode`){$(W(`modelSetupRequired`));return}m(!1)}g();let i=t??n.current;if(!i)return;let a=o.current,c=await Ic({isDeferredSession:a instanceof Nc,isStreaming:a?.state.isStreaming??!1,messageCount:a?.state.messages.length??0,currentScope:r.current,targetScope:`project`,currentHarness:a?.harness??`quickforge`},async()=>(e.current?await ir(e.current):{}).harness??`quickforge`),l=n.current?.id===i.id;if(!(l&&c.action===`reuse`)){if(l&&c.action===`replace`){_(void 0),ku(),await s({scope:`project`,project:i,harness:c.defaultHarness});return}l||await h(i.id),_(void 0),ku(),await s({scope:`project`,project:i})}},[n,o,r,p,m,_,g,s,e,h]),b=(0,H.useCallback)(async s=>{let p=o.current;if(!p)return;if(p.harness===`opencode`){$(W(`openCodeMessageHistoryActionUnavailable`));return}if(p.state.isStreaming){$(W(`generationStillRunning`));return}let m=zc(p.state.messages,s),h=m>=0?p.state.messages[m]:void 0;if(m<0||!h){$(W(`noConversationTurnToRollback`));return}let g={id:Date.now(),sessionId:p.sessionId,text:Bc(h),attachments:h.role===`user-with-attachments`?h.attachments:void 0},v=p.state.messages.slice(0,m);try{v=(await p.rollback(s)).session.messages??v}catch(e){V.error(`Failed to rollback conversation:`,e),$(e instanceof Error?e.message:W(`rollbackFailed`));return}u(v);let y=i.current?a.current.get(i.current):void 0;if(Gc(v)&&y){g&&_(g),d(e=>e+1),l(y).catch(e=>V.error(`Failed to sync session UI:`,e));return}let b=e.current,x=i.current,S=r.current,C=S===`project`?n.current:void 0,w=p.state.model??t.current,T=p.state.thinkingLevel;if(x&&Yc(a.current,x),b&&x)try{await b.sessions.delete(x),await f({broadcast:!0})}catch(e){V.error(`Failed to delete rolled back empty session:`,e)}let E=X();await c({model:w,thinkingLevel:T,messages:[],tools:[]},E,{scope:S,project:C,attachToView:!0,title:`New chat`,harness:p.harness,sourceHarnessSessionId:void 0}),_({...g,sessionId:E}),d(e=>e+1)},[t,n,o,c,r,i,f,d,u,_,e,l,a]),x=(0,H.useCallback)(async e=>{try{await Vc(e)}catch(e){throw V.error(`Failed to copy answer:`,e),$(W(`copyFailed`)),e}},[]),S=(0,H.useCallback)(async()=>{let t=o.current;if(!(!t||!(t instanceof Mc))&&t.harness===`opencode`){if(t.state.isStreaming){$(W(`generationAlreadyRunning`));return}if(!t.harnessSessionId){$(W(`openCodeForkUnavailable`));return}try{await t.forkSession()}catch(e){V.error(`Failed to fork current conversation:`,e),$(e instanceof Error?e.message:W(`openCodeForkFailed`));return}e.current&&f({broadcast:!0}).catch(e=>V.error(`Failed to refresh sessions:`,e))}},[o,f,e]),C=(0,H.useCallback)(async i=>{let a=o.current;if(!a)return;if(a.harness===`opencode`){$(W(`openCodeMessageHistoryActionUnavailable`));return}if(a.state.isStreaming){$(W(`generationAlreadyRunning`));return}let s=a.state.messages.slice(0,i+1);if(!Wc(s))return;let l=r.current,u=l===`project`?n.current:void 0,d=X(),p=Hc(s),m=e.current;await c({model:a.state.model??t.current,thinkingLevel:a.state.thinkingLevel,messages:s,tools:[]},d,{scope:l,project:u,attachToView:!0,title:p,harness:a.harness,sourceHarnessSessionId:void 0}),m&&f({broadcast:!0}).catch(e=>V.error(`Failed to refresh sessions:`,e))},[t,n,o,c,r,f,e]);return{startNewGlobalChat:v,startNewProjectChat:y,rollbackFromMessage:b,retryFromMessage:(0,H.useCallback)(async e=>{let t=o.current;if(!t)return;if(t.harness===`opencode`){$(W(`openCodeMessageHistoryActionUnavailable`));return}if(t.state.isStreaming){$(W(`generationAlreadyRunning`));return}let n=t.state.messages;if(e<0||e>=n.length)return;let r=n[e];if(r.role!==`user`&&r.role!==`user-with-attachments`)return;u(n.slice(0,e+1)),d(e=>e+1);try{await t.continue()}catch(e){V.error(`Failed to retry:`,e),$(e instanceof Error?e.message:W(`retryFailed`));return}let s=i.current?a.current.get(i.current):void 0;s&&(l(s).catch(e=>V.error(`Failed to sync session UI after retry:`,e)),d(e=>e+1))},[o,i,d,u,l,a]),copyAnswer:x,forkFromMessage:C,forkCurrentSession:S}}function ju({activeProjectRef:e,refreshSessions:t,notifyProjectsChanged:n,setActiveProject:r,setProjects:i,setExpandedProjectIds:a,setChatPanelRevision:o}){return{deleteProjectInline:(0,H.useCallback)(async s=>{let c=await fetch(`/api/project/${encodeURIComponent(s)}`,{method:`DELETE`}),l=await c.json().catch(()=>null);if(!c.ok)throw Error(l?.error||`Failed to delete project`);r(l.project),i(l.projects),a(e=>{let t=new Set(e);return t.delete(s),t}),Js(`/api/project`),await t({broadcast:!0}),n(),e.current?.id===s&&(e.current=l.project,o(e=>e+1))},[e,t,n,r,i,a,o])}}var Mu=H.forwardRef(({className:e,type:t,...n},r)=>(0,K.jsx)(`input`,{type:t,className:G(`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:border-primary focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50`,e),ref:r,...n}));Mu.displayName=`Input`;function Nu({options:e,onResolve:t}){let n=(0,H.useRef)(null),[r,i]=(0,H.useState)(e.defaultValue??``),a=(0,H.useRef)(r);return(0,H.useEffect)(()=>{a.current=r},[r]),(0,H.useEffect)(()=>{n.current?.focus(),n.current?.select()},[]),(0,H.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t(null),e.key===`Enter`&&a.current.trim()&&t(a.current.trim())};return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[t]),(0,qr.createPortal)((0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50`,onClick:e=>{e.target===e.currentTarget&&t(null)},children:(0,K.jsxs)(`div`,{className:G(`w-full max-w-sm rounded-lg border border-border bg-background p-6 shadow-quickforge`,`mx-4`),children:[(0,K.jsx)(`h2`,{className:`text-base font-semibold text-foreground`,children:e.title}),e.description?(0,K.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:e.description}):null,(0,K.jsx)(`div`,{className:`mt-4`,children:(0,K.jsx)(Mu,{ref:n,value:r,onChange:e=>i(e.target.value),placeholder:e.placeholder,className:`w-full`})}),(0,K.jsxs)(`div`,{className:`mt-5 flex justify-end gap-2`,children:[(0,K.jsx)(q,{variant:`outline`,size:`sm`,onClick:()=>t(null),children:e.cancelLabel??`Cancel`}),(0,K.jsx)(q,{size:`sm`,onClick:()=>r.trim()?t(r.trim()):void 0,disabled:!r.trim(),children:e.confirmLabel??`Save`})]})]})}),document.body)}function Pu(e){return new Promise(t=>{let n=document.createElement(`div`);document.body.appendChild(n);let r=(0,it.createRoot)(n);function i(){r.unmount(),setTimeout(()=>n.remove(),0)}function a(e){i(),t(e)}r.render((0,K.jsx)(Nu,{options:e,onResolve:a}))})}function Fu({storageRef:e,taskMapRef:t,currentSessionIdRef:n,loadAgentSession:r,setCurrentTitleRef:i,refreshSessions:a,updateSessionTitle:o,closeWorkspacePage:s,startNewGlobalChat:c}){return{loadSession:(0,H.useCallback)(e=>(s(),r(e)),[r,s]),renameSession:(0,H.useCallback)(async(t,r)=>{if(!e.current)return;let a=await Pu({title:W(`renameSession`),description:W(`sessionName`),defaultValue:r,confirmLabel:W(`save`),cancelLabel:W(`cancel`)});if(!a||a===r)return;let s=await fetch(`/api/agents/${encodeURIComponent(t)}/title`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({title:a})});if(!s.ok)throw Error(`Failed to rename session: HTTP ${s.status}`);o(t,a),n.current===t&&i(a)},[n,i,e,o]),togglePinSession:(0,H.useCallback)(async t=>{let n=e.current;if(!n)return;let r=await n.sessions.getMetadata(t);if(!r)return;let i=r.pinnedAt?void 0:new Date().toISOString(),o={...r,pinnedAt:i};await n.backend.set(`sessions-metadata`,t,o),await a({broadcast:!0})},[a,e]),archiveSession:(0,H.useCallback)(async r=>{let i=e.current;if(!i)return;Yc(t.current,r);let o=await i.sessions.get(r);if(!o)return;let l=await i.sessions.getMetadata(r);if(!l)return;let u=new Date().toISOString(),d={...o,archivedAt:u},f={...l,archivedAt:u};await i.sessions.save(d,f),await a({broadcast:!0}),n.current===r&&(s(),await c())},[n,a,s,c,e,t]),startNewGlobalSession:(0,H.useCallback)(()=>{s(),c()},[s,c])}}var Iu=e=>e===`full-access`;function Lu({storageRef:e,agentAccessModeRef:t,setAgentAccessMode:n,agentRef:r,setChatPanelRevision:i,notifySettingsChanged:a}){let o=(0,H.useCallback)(o=>{let s=e.current,c=r.current,l=t.current;if(l===o)return;n(o),t.current=o;let u=()=>{t.current=l,n(l),i(e=>e+1)};(async()=>{try{c&&await c.updateAccessMode(o),s&&await gr(s,o),i(e=>e+1),a()}catch(e){V.error(`Failed to sync agent access mode:`,e),u(),$(e instanceof Error?e.message:W(`agentAccessModeSyncFailed`))}})()},[t,r,a,n,i,e]);return{setAccessMode:o,toggleYoloMode:(0,H.useCallback)(()=>{o(Iu(t.current)?`default`:`full-access`)},[t,o])}}function Ru(){let[e,t]=(0,H.useState)(!0),[n,r]=(0,H.useState)(!1),[i,a]=(0,H.useState)(!1),[o,s]=(0,H.useState)(!1),[c,l]=(0,H.useState)(!1),[u,d]=(0,H.useState)(),[f,p]=(0,H.useState)(!1),[m,h]=(0,H.useState)(!1),[g,_]=(0,H.useState)(!1),[v,y]=(0,H.useState)(),[b,x]=(0,H.useState)(!1),[S,C]=(0,H.useState)(),[w,T]=(0,H.useState)(!1),[E,D]=(0,H.useState)(!1),[O,k]=(0,H.useState)(`defaults`),[ee,te]=(0,H.useState)();return{sidebarOpen:e,setSidebarOpen:t,mobileSidebarOpen:n,setMobileSidebarOpen:r,projectsCollapsed:i,setProjectsCollapsed:a,pinnedCollapsed:o,setPinnedCollapsed:s,conversationsCollapsed:c,setConversationsCollapsed:l,skillsDialog:u,setSkillsDialog:d,shareDialogOpen:f,setShareDialogOpen:p,conversationMenuOpen:m,setConversationMenuOpen:h,workspaceInspectorOpen:g,setWorkspaceInspectorOpen:_,workspaceInspectorRequest:v,setWorkspaceInspectorRequest:y,artifactPreviewOpen:b,setArtifactPreviewOpen:x,activeArtifactPath:S,setActiveArtifactPath:C,firstUseGuideDismissed:w,setFirstUseGuideDismissed:T,settingsDialogOpen:E,setSettingsDialogOpen:D,settingsInitialTab:O,setSettingsInitialTab:k,settingsCustomProvider:ee,setSettingsCustomProvider:te,toggleProjectsCollapsed:(0,H.useCallback)(()=>a(e=>!e),[]),togglePinnedCollapsed:(0,H.useCallback)(()=>s(e=>!e),[]),toggleConversationsCollapsed:(0,H.useCallback)(()=>l(e=>!e),[])}}function zu(e){return e===`running`||e===`idle`||e===`error`||e===`aborted`?e:void 0}function Bu(e){let[t,n]=(0,H.useState)({}),r=(0,H.useMemo)(()=>new Set(e.map(e=>e.id)),[e]),i=(0,H.useMemo)(()=>e.map(e=>e.id).sort().join(`
65
- `),[e]),a=(0,H.useCallback)(async()=>{if(r.size===0){n({});return}try{let e=await Ac(),t=new Map(e.map(e=>[e.sessionId,zu(e.status)]).filter(e=>!!e[1]));n(e=>{let n={};for(let i of r){let r=t.get(i),a=e[i];r?n[i]=r:a===`running`?n[i]=`idle`:a&&a!==`idle`&&(n[i]=a)}return n})}catch(e){V.error(`Failed to refresh visible agent statuses:`,e)}},[r]);return(0,H.useEffect)(()=>{let e=window.setTimeout(()=>{a()},0);return()=>window.clearTimeout(e)},[a,i]),(0,H.useEffect)(()=>jc(e=>{let t=e.sessionId;if(!(!t||!r.has(t))){if(e.type===`agent_start`){n(e=>({...e,[t]:`running`}));return}if(e.type===`agent_end`){let r=zu(e.status)===`aborted`?`aborted`:e.errorMessage?`error`:`idle`;n(e=>({...e,[t]:r}))}}}),[r]),(0,H.useEffect)(()=>{let e=()=>{document.visibilityState===`visible`&&a()};return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[a]),t}function Vu(e,t=window.requestAnimationFrame.bind(window),n=window.cancelAnimationFrame.bind(window)){let r=!1,i=t(()=>{r||(i=t(()=>{r||e()}))});return()=>{r=!0,n(i)}}var Hu=`quickforge:tunnel-recovered`,Uu=null;async function Wu(e){if(Uu)return{status:`deferred`,reason:`in-flight`};Uu=Gu(e);try{return await Uu}finally{Uu=null}}async function Gu(e){let t=e.fetchImpl??globalThis.fetch,n=e.reload??(()=>window.location.reload()),r=e.dispatchEvent??(e=>window.dispatchEvent(e)),i=e.maxAttempts??2,a=e.retryDelayMs??700,o=e.timeoutMs??3e3,s=e.recoveryWaitTimeoutMs??5e3;if(!await Ku(e.probe))return{status:`deferred`,reason:`probe-failed`};for(let e=0;e<i;e++)if(e>0&&await Xu(a),await qu(t,o)){if(await Yu(r,s))return{status:`recovered`};break}try{n()}catch{}return{status:`reloaded`}}async function Ku(e){try{return await e()}catch{return!1}}async function qu(e,t){let[n,r]=await Promise.all([Ju(e,`/api/health`,t),Ju(e,`/api/agents`,t)]);if(!n?.ok||!r?.ok)return!1;let i=r.body;return Array.isArray(i?.sessions)}async function Ju(e,t,n){let r=new AbortController,i=globalThis.setTimeout(()=>r.abort(),n);try{let n=await e(t,{cache:`no-store`,signal:r.signal}),i=n.ok?await n.json().catch(()=>null):null;return{ok:n.ok,body:i}}catch{return null}finally{globalThis.clearTimeout(i)}}async function Yu(e,t){let n=0,r=[],i={at:Date.now(),waitUntil:e=>{n+=1,r.push(e)}};try{e(new Event(`online`)),e(new CustomEvent(Hu,{detail:i}))}catch{return!1}if(n===0)return!1;let a=Promise.all(r),o,s=new Promise((e,n)=>{o=globalThis.setTimeout(()=>n(Error(`tunnel recovery waitUntil timeout`)),t)});try{return await Promise.race([a,s]),!0}catch{return!1}finally{globalThis.clearTimeout(o)}}function Xu(e){return new Promise(t=>setTimeout(t,e))}var Zu=`quickforge:sidebar-session-view-mode:v1`,Qu=`quickforge:sidebar-session-sort-mode:v1`,$u=`project`,ed=`updatedAt`;function td(){try{return globalThis.localStorage}catch{return}}function nd(){let e=td();if(!e)return $u;try{let t=e.getItem(Zu);return t===`timeline`||t===`project`?t:$u}catch{return $u}}function rd(e){let t=td();if(t)try{t.setItem(Zu,e)}catch{}}function id(){let e=td();if(!e)return ed;try{let t=e.getItem(Qu);return t===`createdAt`||t===`updatedAt`?t:ed}catch{return ed}}function ad(e){let t=td();if(t)try{t.setItem(Qu,e)}catch{}}function od({ready:e,currentToolProjectId:t,projects:n,activeProject:r,recoveringProjectId:i}){return!e||!t||t===`default`||n.some(e=>e.id===t)||i===t?{type:`none`}:r?{type:`project`,deletedProjectId:t,project:r}:{type:`global`,deletedProjectId:t}}function sd(e,t,n){return e.projectId===t&&e.requestId===n}var cd=new Set([`write_file`,`edit_file`,`run_command`,`run_subagent`]);function ld(e,t,n){return e.type!==`tool_execution_end`||!t||e.sessionId!==t||!n?!1:typeof e.toolName==`string`&&cd.has(e.toolName)}function ud(e){return e===`idle`?{tone:`success`,message:W(`taskCompleted`)}:e===`error`?{tone:`error`,message:W(`taskError`)}:e===`aborted`?{tone:`aborted`,message:W(`processAborted`)}:e===`running`?{tone:`running`,message:W(`taskRunning`)}:{tone:`neutral`,message:W(`taskRunning`)}}function dd({toast:e,onDismiss:t,onClick:n}){let[r,i]=(0,H.useState)(!1),[a,o]=(0,H.useState)(!1),c=(0,H.useRef)(null);(0,H.useEffect)(()=>{let n=window.setTimeout(()=>i(!0),10);return c.current=window.setTimeout(()=>{o(!0),c.current=window.setTimeout(()=>t(e.id),200)},5e3),()=>{window.clearTimeout(n),c.current!==null&&window.clearTimeout(c.current)}},[e.id,t]);let l=()=>{o(!0),c.current!==null&&window.clearTimeout(c.current),c.current=window.setTimeout(()=>t(e.id),200)},u=ud(e.status),d=u.tone===`error`,f=u.tone===`success`,p=G(`size-5`,d&&`text-destructive`,f&&`text-emerald-500`,u.tone===`aborted`&&`text-amber-600`,u.tone===`running`&&`text-blue-600`,u.tone===`neutral`&&`text-muted-foreground`);return(0,K.jsxs)(`div`,{role:`alert`,onClick:()=>n(e.sessionId),className:G(`pointer-events-auto flex w-80 cursor-pointer items-start gap-3 rounded-xl border border-border bg-background p-3 shadow-quickforge transition-all duration-200 ease-out`,r&&!a?`translate-x-0 opacity-100`:`translate-x-4 opacity-0`),children:[(0,K.jsx)(`div`,{className:`mt-0.5 shrink-0`,children:f?(0,K.jsx)(x,{className:p}):(0,K.jsx)(s,{className:p})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`truncate text-sm font-medium text-foreground/90`,children:e.title}),(0,K.jsx)(`p`,{className:`mt-0.5 line-clamp-3 text-xs text-muted-foreground`,children:e.message||u.message})]}),(0,K.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),l()},className:`shrink-0 rounded-md p-0.5 text-muted-foreground/60 transition-colors hover:text-foreground`,"aria-label":W(`close`),children:(0,K.jsx)(z,{className:`size-4`})})]})}function fd({toasts:e,onDismiss:t,onClick:n}){return e.length===0?null:(0,K.jsx)(`div`,{className:`pointer-events-none fixed right-4 top-16 z-50 flex flex-col gap-2`,children:e.map(e=>(0,K.jsx)(dd,{toast:e,onDismiss:t,onClick:n},e.id))})}async function pd(e){let t=await fetch(e,{cache:`no-store`}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||`Request failed: ${t.status}`);return n}async function md(e,t){let n=await fetch(e,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(t)}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||`Request failed: ${n.status}`);return r}function hd(e){return`projectId=${encodeURIComponent(e)}`}function gd(e){return pd(`/api/workspace/tree?${hd(e)}`)}function _d(e,t){return pd(`/api/workspace/file?${hd(e)}&path=${encodeURIComponent(t)}`)}function vd(e,t){return md(`/api/workspace/resolve-path`,{projectId:e,path:t})}function yd(e,t,n){return md(`/api/workspace/open-external`,{projectId:e,path:t,target:n})}function bd(e){return pd(`/api/git/status?${hd(e)}`)}function xd(e,t){return pd(`/api/git/file-diff?${hd(e)}&path=${encodeURIComponent(t)}`)}function Sd(e,t){return md(`/api/git/stage`,{projectId:e,path:t})}function Cd(e){return md(`/api/git/stage-all`,{projectId:e})}function wd(e,t){return md(`/api/git/unstage`,{projectId:e,path:t})}function Td(e){return md(`/api/git/unstage-all`,{projectId:e})}function Ed(e,t){return md(`/api/git/restore`,{projectId:e,path:t})}function Dd(e){return md(`/api/git/restore-all`,{projectId:e})}function Od(e){return pd(`/api/git/branches?${hd(e)}`)}function kd(e,t){return md(`/api/git/checkout`,{projectId:e,branch:t})}function Ad(e,t){return md(`/api/git/create-branch`,{projectId:e,branch:t})}function jd(e){return pd(`/api/git/log?${hd(e)}`)}function Md(e,t,n,r){return md(`/api/git/generate-commit-message`,{projectId:e,modelRef:t&&typeof t==`object`?tt(t):void 0,model:t,thinkingLevel:n,includeUnstaged:r})}function Nd(e,t,n){return md(`/api/git/commit`,{projectId:e,message:t,includeUnstaged:n})}function Pd(e){return md(`/api/git/push`,{projectId:e})}function Fd(e,t,n){return md(`/api/git/commit-and-push`,{projectId:e,message:t,includeUnstaged:n})}function Id({projectId:e,currentBranch:t,dirtyCount:n=0,className:r,openChangesClassName:i,onCheckout:a,onCreated:s,onOpenGraph:c,onOpenChanges:l}){let u=(0,H.useRef)(null),[d,f]=(0,H.useState)(``),[p,m]=(0,H.useState)([]),[h,g]=(0,H.useState)(!0),[_,v]=(0,H.useState)(),[y,b]=(0,H.useState)(),x=(0,H.useCallback)(async()=>{g(!0),v(void 0);try{m((await Od(e)).branches)}catch(e){v(e instanceof Error?e.message:W(`gitBranchesFailed`))}finally{g(!1)}},[e]);(0,H.useEffect)(()=>{let e=window.setTimeout(()=>{x(),u.current?.focus()},0);return()=>window.clearTimeout(e)},[x]);let S=(0,H.useMemo)(()=>{let e=d.trim().toLowerCase();return e?p.filter(t=>t.name.toLowerCase().includes(e)):p},[p,d]),C=(0,H.useCallback)(async e=>{if(!(e.current||y)){b(e.name);try{await a(e.name),await x()}finally{b(void 0)}}},[y,a,x]),w=(0,H.useCallback)(async()=>{let t=await Pu({title:W(`createBranchTitle`),description:W(`createBranchDescription`),placeholder:W(`createBranchPlaceholder`),confirmLabel:W(`createAndCheckoutBranch`),cancelLabel:W(`cancel`)});if(t){b(t);try{let n=await Ad(e,t);s?.(n),await x()}catch(e){$(e instanceof Error?e.message:W(`gitCheckoutFailed`))}finally{b(void 0)}}},[s,e,x]);return(0,K.jsxs)(`div`,{className:G(`absolute left-0 top-10 z-40 w-[340px] overflow-hidden rounded-2xl border border-border bg-popover shadow-quickforge`,r),onClick:e=>e.stopPropagation(),children:[(0,K.jsx)(`div`,{className:`border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] p-3`,children:(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsx)(Se,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground/70`}),(0,K.jsx)(Mu,{ref:u,value:d,onChange:e=>f(e.target.value),placeholder:W(`searchBranches`),className:`h-10 rounded-xl border-transparent bg-background pl-9 text-sm shadow-none focus-visible:border-border`})]})}),l?(0,K.jsxs)(`button`,{type:`button`,className:G(`flex w-full items-center justify-center gap-2 border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-3 py-3 text-sm text-muted-foreground transition-colors hover:bg-muted/20 hover:text-foreground`,i),onClick:l,children:[(0,K.jsx)(`span`,{children:W(`uncommittedChanges`)}),(0,K.jsx)(`span`,{children:W(`filesCount`,{count:n})})]}):null,(0,K.jsx)(`div`,{className:`max-h-[340px] overflow-y-auto p-2`,children:h?(0,K.jsxs)(`div`,{className:`flex items-center justify-center gap-2 px-3 py-8 text-sm text-muted-foreground`,children:[(0,K.jsx)(B,{className:`size-4 animate-spin`}),(0,K.jsx)(`span`,{children:W(`loading`)})]}):_?(0,K.jsx)(`div`,{className:`rounded-xl bg-muted/40 px-3 py-4 text-sm text-muted-foreground`,children:_}):S.length===0?(0,K.jsx)(`div`,{className:`rounded-xl bg-muted/40 px-3 py-4 text-sm text-muted-foreground`,children:W(`noBranchesFound`)}):S.map(e=>{let n=e.current||e.name===t,r=y===e.name;return(0,K.jsxs)(`button`,{type:`button`,className:G(`flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm transition-colors`,n?`bg-muted text-foreground`:`text-foreground/88 hover:bg-muted/70`),onClick:()=>void C(e),disabled:n||!!y,title:e.name,children:[r?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(pe,{className:G(`size-4 shrink-0`,n?`text-foreground`:`text-muted-foreground`)}),(0,K.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.name}),n?(0,K.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:W(`currentBranch`)}):null]},`${e.remote?`remote`:`local`}:${e.name}`)})}),s||c?(0,K.jsxs)(`div`,{className:`border-t-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] p-2`,children:[s?(0,K.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm text-foreground/88 transition-colors hover:bg-muted/70`,onClick:()=>void w(),disabled:!!y,children:[(0,K.jsx)(o,{className:`size-4 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`createAndCheckoutBranchEllipsis`)})]}):null,c?(0,K.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm text-foreground/88 transition-colors hover:bg-muted/70`,onClick:c,children:[(0,K.jsx)(ge,{className:`size-4 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`gitGraph`)})]}):null]}):null]})}function Ld(e){return e?.detached===!0||e?.branch===`HEAD`||!!e?.branch?.startsWith(`HEAD `)}function Rd(e,t){return e?.files?.length?e.files.filter(e=>!e.conflict&&(t||e.staged)):[]}function zd(e,t,n){return!!(e?.isGitRepository&&!e.counts?.conflicts&&!Ld(e)&&n.trim()&&Rd(e,t).length)}function Bd(e){return(e?.files??[]).reduce((e,t)=>(e.additions+=t.additions??0,e.deletions+=t.deletions??0,e),{additions:0,deletions:0})}function Vd(e){return e.conflict?`!`:e.status===`untracked`?`?`:e.status===`added`?`A`:e.status===`deleted`?`D`:e.status===`renamed`?`R`:`M`}function Hd({open:e,projectId:t,status:n,onClose:r,onCheckout:i,onRefreshStatus:a,onStatusChange:o,onCompleted:s}){let[c,l]=(0,H.useState)(``),[u,d]=(0,H.useState)(!1),[p,m]=(0,H.useState)(!1),[h,g]=(0,H.useState)(!1),[_,v]=(0,H.useState)(!0),[b,x]=(0,H.useState)(),[C,w]=(0,H.useState)(``),[E,D]=(0,H.useState)(``),[O,k]=(0,H.useState)(),[ee,te]=(0,H.useState)(`off`),A=(0,H.useMemo)(()=>Bd(n),[n]),ne=(0,H.useMemo)(()=>Rd(n,u),[u,n]),re=(0,H.useMemo)(()=>new Set(ne.map(e=>e.path)),[ne]),M=n?.counts?.total??n?.files.length??0,N=Ld(n),P=!_&&zd(n,u,c);if((0,H.useEffect)(()=>{if(!e)return;let t=!1;return a().then(e=>{!t&&!e&&w(W(`gitStatusRefreshFailed`))}).finally(()=>{t||v(!1)}),()=>{t=!0}},[a,e,t]),(0,H.useEffect)(()=>{if(!e)return;let t=!1;async function n(){try{let e=await $n(),n=await ir(e),r=await fr(e,[],n.model);if(t||!r)return;k(r),te(n.thinkingLevel??tr(r))}catch{}}return n(),()=>{t=!0}},[e]),(0,H.useEffect)(()=>{if(!p)return;let e=()=>m(!1);return window.addEventListener(`click`,e),window.addEventListener(`blur`,e),()=>{window.removeEventListener(`click`,e),window.removeEventListener(`blur`,e)}},[p]),(0,H.useEffect)(()=>{if(!e)return;function t(e){e.key===`Escape`&&!b&&(m(!1),r())}return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[b,r,e]),!e)return null;async function ie(){if(!t){w(W(`gitCommitNoProject`));return}if(!O){w(W(`gitCommitNoModel`));return}if(!ne.length){w(W(`gitNoStagedChanges`));return}x(`generate`),w(``);try{l((await Md(t,O,ee,u)).message)}catch(e){w(e instanceof Error?e.message:W(`gitGenerateCommitMessageFailed`))}finally{x(void 0)}}async function F(e){if(t){if(e!==`push`){if(!c.trim()){w(W(`gitCommitMessageRequired`));return}if(!P){w(W(N?`gitDetachedHeadBlocked`:`gitNoStagedChanges`));return}}if(N){w(W(`gitDetachedHeadBlocked`));return}x(e),w(``);try{if(e===`push`){let e=await Pd(t);D(``),s(e);return}if(e===`commit-push`){let e=await Fd(t,c.trim(),u);if(!e.pushed){o(e),l(``),D(e.pushError||W(`gitOperationFailed`));return}l(``),s(e);return}let n=await Nd(t,c.trim(),u);l(``),s(n)}catch(e){w(e instanceof Error?e.message:W(`gitOperationFailed`))}finally{x(void 0)}}}return(0,qr.createPortal)((0,K.jsx)(`div`,{className:`fixed inset-0 z-[80] flex items-center justify-center bg-black/50 px-6 py-8`,role:`dialog`,"aria-modal":`true`,onMouseDown:e=>{e.target===e.currentTarget&&!b&&(m(!1),r())},children:(0,K.jsxs)(`div`,{className:`flex max-h-[min(700px,calc(100vh-64px))] w-full max-w-[760px] flex-col overflow-hidden rounded-3xl border border-[color-mix(in_oklab,var(--border)_42%,transparent)] bg-background shadow-2xl`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-5`,children:[(0,K.jsxs)(`div`,{className:`relative min-w-0`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex max-w-[280px] items-center gap-2.5 rounded-xl px-2 py-1.5 text-base text-muted-foreground transition-colors hover:bg-muted hover:text-foreground`,onClick:()=>m(e=>!e),disabled:!t||!!b,"aria-label":W(`gitBranchMenu`),"aria-haspopup":`menu`,"aria-expanded":p,children:[(0,K.jsx)(pe,{className:`size-5 shrink-0`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:n?.branch||W(`unknown`)}),(0,K.jsx)(y,{className:`size-4 shrink-0`})]}),p&&t?(0,K.jsx)(Id,{projectId:t,currentBranch:n?.branch,className:`top-11`,onCheckout:async e=>{await i(e),m(!1)}}):null]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-3 text-base font-medium`,children:[(0,K.jsxs)(`span`,{className:`text-emerald-600`,children:[`+`,A.additions]}),(0,K.jsxs)(`span`,{className:`text-red-600`,children:[`-`,A.deletions]}),(0,K.jsx)(`button`,{type:`button`,className:`ml-2 rounded-full p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground`,onClick:()=>{m(!1),r()},disabled:!!b,"aria-label":W(`close`),children:(0,K.jsx)(z,{className:`size-5`})})]})]}),(0,K.jsxs)(`div`,{className:`relative min-h-44 px-6 pb-4`,children:[(0,K.jsx)(`textarea`,{value:c,onChange:e=>{l(e.target.value),w(``)},onKeyDown:e=>{(e.ctrlKey||e.metaKey)&&e.key===`Enter`&&(e.preventDefault(),!b&&P&&F(`commit`))},placeholder:W(`gitCommitMessagePlaceholder`),disabled:!!b,className:`min-h-40 w-full resize-none bg-transparent pr-12 text-base leading-7 text-foreground/90 outline-none placeholder:text-muted-foreground/72 disabled:opacity-60`}),(0,K.jsx)(`button`,{type:`button`,className:G(`absolute right-6 top-0 rounded-full p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground`,b===`generate`&&`pointer-events-none`),onClick:()=>void ie(),disabled:!!b||_||!ne.length||N,title:W(`gitGenerateCommitMessage`),"aria-label":W(`gitGenerateCommitMessage`),children:b===`generate`?(0,K.jsx)(B,{className:`size-5 animate-spin`}):(0,K.jsx)(j,{className:`size-5`})})]}),(0,K.jsxs)(`div`,{className:`border-t border-[color-mix(in_oklab,var(--border)_24%,transparent)] px-6 py-3 text-sm`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,K.jsxs)(`label`,{className:`flex min-w-0 items-center gap-3 text-foreground/92`,children:[(0,K.jsx)(`button`,{type:`button`,className:G(`flex size-5 shrink-0 items-center justify-center rounded-md border transition-colors`,u?`border-black bg-black text-white`:`border-border bg-background text-transparent`),onClick:()=>{d(e=>!e),D(``),w(``)},disabled:!!b||_,"aria-pressed":u,children:(0,K.jsx)(S,{className:`size-3.5`})}),(0,K.jsx)(`span`,{children:W(`gitIncludeUnstagedChanges`)})]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex shrink-0 items-center gap-1.5 text-muted-foreground transition-colors hover:text-foreground`,onClick:()=>g(e=>!e),disabled:!M,children:[(0,K.jsx)(`span`,{children:W(`gitCommitFilesSummary`,{selected:ne.length,total:M})}),(0,K.jsx)(y,{className:G(`size-4 transition-transform`,h&&`rotate-180`)})]})]}),u?(0,K.jsx)(`div`,{className:`mt-2 text-xs text-muted-foreground`,children:W(`gitIncludeUnstagedWarning`)}):null,h?(0,K.jsx)(`div`,{className:`mt-3 max-h-44 space-y-1 overflow-y-auto border-t border-[color-mix(in_oklab,var(--border)_24%,transparent)] pt-3`,children:(n?.files??[]).map(e=>{let t=re.has(e.path);return(0,K.jsxs)(`div`,{className:G(`flex items-center gap-2 rounded-lg px-2 py-1.5`,!t&&`opacity-45`),children:[(0,K.jsx)(`span`,{className:`w-4 shrink-0 text-center font-mono text-xs text-muted-foreground`,children:Vd(e)}),(0,K.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,title:e.path,children:e.oldPath?`${e.oldPath} → ${e.path}`:e.path}),t?null:(0,K.jsx)(`span`,{className:`shrink-0 text-xs text-muted-foreground`,children:W(`gitFileNotIncluded`)})]},`${e.oldPath??``}:${e.path}`)})}):null]}),_?(0,K.jsx)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-muted/55 px-4 py-3 text-sm text-muted-foreground`,children:W(`gitRefreshingStatus`)}):null,N?(0,K.jsx)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-destructive/10 px-4 py-3 text-sm text-destructive`,children:W(`gitDetachedHeadBlocked`)}):null,E?(0,K.jsxs)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-destructive/10 px-4 py-3 text-sm text-destructive`,children:[(0,K.jsx)(`div`,{className:`font-medium`,children:W(`gitCommitSucceededPushFailed`)}),(0,K.jsx)(`div`,{className:`mt-1 break-words text-xs opacity-90`,children:E})]}):null,C?(0,K.jsx)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-destructive/10 px-4 py-3 text-sm text-destructive`,children:C}):null,n?.counts?.conflicts?(0,K.jsx)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-destructive/10 px-4 py-3 text-sm text-destructive`,children:W(`gitCommitConflictsBlocked`)}):null,(0,K.jsx)(`div`,{className:`border-t border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-6 py-4`,children:E?(0,K.jsxs)(`button`,{type:`button`,className:`flex h-12 w-full items-center gap-3 rounded-2xl bg-muted/70 px-3 text-left transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-45`,disabled:!!b||N,onClick:()=>void F(`push`),children:[b===`push`?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(f,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`gitRetryPush`)})]}):(0,K.jsxs)(`div`,{className:`space-y-1.5 text-base`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex h-11 w-full items-center gap-3 rounded-2xl px-3 text-left transition-colors hover:bg-muted/55 disabled:cursor-not-allowed disabled:opacity-45`,disabled:!!b||!P,onClick:()=>void F(`commit`),children:[b===`commit`?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(se,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`gitCommitOnly`)})]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-12 w-full items-center gap-3 rounded-2xl bg-muted/70 px-3 text-left transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-45`,disabled:!!b||!P,onClick:()=>void F(`commit-push`),children:[b===`commit-push`?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(T,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`flex-1`,children:W(`gitCommitAndPush`)})]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-11 w-full items-center gap-3 rounded-2xl px-3 text-left text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-35`,disabled:!!b||_||N,onClick:()=>void F(`push`),children:[b===`push`?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(f,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`gitPushOnly`)})]})]})})]})}),document.body)}function Ud(e){return e.files.reduce((e,t)=>(e.additions+=t.additions??0,e.deletions+=t.deletions??0,e),{additions:0,deletions:0})}function Wd({projectId:e,status:t,expanded:n,onExpandedChange:r,onOpenChanges:i,onOpenCommitPush:a,onCheckout:o,onCreated:s,onOpenGraph:c,mobileShell:l=!1}){let u=(0,H.useRef)(null),[d,f]=(0,H.useState)(!1),p=(0,H.useMemo)(()=>Ud(t),[t]),h=t.counts?.total??t.files.length;return(0,H.useEffect)(()=>{if(!n)return;function e(){f(!1),r(!1)}function t(t){u.current?.contains(t.target)||e()}function i(t){t.key===`Escape`&&e()}return document.addEventListener(`pointerdown`,t),document.addEventListener(`keydown`,i),()=>{document.removeEventListener(`pointerdown`,t),document.removeEventListener(`keydown`,i)}},[n,r]),t.isGitRepository?(0,K.jsxs)(`div`,{ref:u,className:`relative`,onClick:e=>e.stopPropagation(),children:[(0,K.jsx)(`button`,{type:`button`,className:G(`inline-flex size-9 items-center justify-center rounded-2xl bg-transparent text-muted-foreground/85 transition-colors hover:bg-muted/45 hover:text-foreground/90`,n&&`bg-muted/45 text-foreground/90`),onClick:()=>r(!n),"aria-label":W(`togglePinnedSummary`),title:W(`togglePinnedSummary`),"aria-expanded":n,children:(0,K.jsx)(m,{className:`size-[18px]`})}),n?(0,K.jsxs)(`div`,{className:G(`fixed inset-x-2 top-14 z-40 max-h-[calc(100dvh-4rem)] overflow-y-auto overscroll-contain rounded-3xl border border-[color-mix(in_oklab,var(--border)_38%,transparent)] bg-background p-4 text-foreground shadow-quickforge md:absolute md:inset-x-auto md:-right-10 md:top-11 md:max-h-none md:w-[min(15rem,calc(100vw-1rem))] md:overflow-visible lg:-right-20`,l&&`md:fixed md:inset-x-2 md:right-auto md:top-14 md:max-h-[calc(100dvh-4rem)] md:w-auto md:overflow-y-auto lg:inset-x-2 lg:right-auto lg:top-14`),children:[(0,K.jsxs)(`div`,{className:`mb-4 flex items-center justify-between`,children:[(0,K.jsx)(`div`,{className:`text-sm font-medium text-muted-foreground`,children:W(`environmentInfo`)}),(0,K.jsx)(`button`,{type:`button`,className:`rounded-full p-1.5 text-foreground/85 transition-colors hover:bg-muted`,onClick:()=>{f(!1),r(!1)},"aria-label":W(`gitToolsCollapse`),title:W(`gitToolsCollapse`),children:(0,K.jsx)(z,{className:`size-4`})})]}),(0,K.jsxs)(`div`,{className:`space-y-1 text-sm`,children:[(0,K.jsxs)(`button`,{type:`button`,className:G(`hidden h-11 w-full items-center gap-3 rounded-2xl px-2.5 text-left text-foreground/88 transition-colors hover:bg-muted/45 hover:text-foreground md:flex`,l&&`md:hidden`),onClick:i,children:[(0,K.jsx)(ve,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`flex-1 font-medium`,children:W(`gitToolsChanges`)}),(0,K.jsxs)(`span`,{className:`font-medium text-emerald-600`,children:[`+`,p.additions]}),(0,K.jsxs)(`span`,{className:`font-medium text-red-600`,children:[`-`,p.deletions]})]}),(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex h-11 w-full items-center gap-3 rounded-2xl px-2.5 text-left text-foreground/88 transition-colors hover:bg-muted/45 hover:text-foreground`,onClick:()=>f(e=>!e),"aria-expanded":d,children:[(0,K.jsx)(pe,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-medium`,children:t.branch||W(`unknown`)}),(0,K.jsx)(y,{className:G(`size-4 shrink-0 text-muted-foreground transition-transform`,d&&`rotate-180`)})]}),d?(0,K.jsx)(Id,{projectId:e,currentBranch:t.branch,dirtyCount:h,className:G(`fixed inset-x-2 top-[7.75rem] max-h-[calc(100dvh-8.25rem)] w-auto overflow-y-auto md:absolute md:inset-x-auto md:left-auto md:right-0 md:top-full md:mt-2 md:max-h-none md:w-[min(340px,calc(100vw-1rem))] md:overflow-hidden lg:right-full lg:top-0 lg:mr-3 lg:mt-0`,l&&`md:fixed md:inset-x-2 md:right-auto md:top-[7.75rem] md:mt-0 md:max-h-[calc(100dvh-8.25rem)] md:w-auto md:overflow-y-auto lg:inset-x-2 lg:right-auto lg:top-[7.75rem] lg:mr-0`),openChangesClassName:G(`hidden md:flex`,l&&`md:hidden`),onCheckout:async e=>{await o(e),f(!1)},onCreated:e=>{s(e),f(!1)},onOpenGraph:()=>{f(!1),c()},onOpenChanges:()=>{f(!1),i()}}):null]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-11 w-full items-center gap-3 rounded-2xl px-2.5 text-left text-foreground/88 transition-colors hover:bg-muted/45 hover:text-foreground`,onClick:a,children:[(0,K.jsx)(ne,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`font-medium`,children:W(`gitToolsCommitOrPush`)})]})]})]}):null]}):null}function Gd(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:new Intl.DateTimeFormat(gt(),{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`}).format(t)}function Kd(e){return e.type===`head`?`border-amber-500 text-foreground`:e.type===`tag`?`border-emerald-600 text-emerald-700 dark:text-emerald-300`:e.type===`remote`?`border-border bg-muted/40 text-muted-foreground`:`border-border bg-muted/30 text-muted-foreground`}function qd({decoration:e}){return(0,K.jsxs)(`span`,{className:G(`inline-flex h-6 items-center gap-1 rounded-lg border px-2 text-xs`,Kd(e)),children:[e.type===`tag`?(0,K.jsx)(L,{className:`size-3`}):(0,K.jsx)(pe,{className:`size-3`}),(0,K.jsx)(`span`,{children:e.name})]})}function Jd({index:e,isLast:t}){return(0,K.jsxs)(`div`,{className:`relative flex h-full min-h-14 w-full justify-center`,"aria-hidden":`true`,children:[t?null:(0,K.jsx)(`div`,{className:`absolute left-1/2 top-0 h-full w-px -translate-x-1/2 bg-amber-500/20`}),e>0?(0,K.jsx)(`div`,{className:`absolute left-1/2 top-0 h-1/2 w-px -translate-x-1/2 bg-amber-500/20`}):null,(0,K.jsx)(`div`,{className:G(`relative z-10 mt-5 rounded-full border bg-background`,e===0?`size-3.5 border-2 border-amber-500/80`:`size-2.5 border-amber-500/65`)})]})}function Yd({projectId:e,projectName:t,onClose:n}){let[i,a]=(0,H.useState)([]),[o,s]=(0,H.useState)(!0),[c,l]=(0,H.useState)(),u=(0,H.useCallback)(async()=>{s(!0),l(void 0);try{a((await jd(e)).commits)}catch(e){l(e instanceof Error?e.message:W(`gitGraphFailed`))}finally{s(!1)}},[e]);(0,H.useEffect)(()=>{let e=window.setTimeout(()=>{u()},0);return()=>window.clearTimeout(e)},[u]),(0,H.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[n]);let d=(0,H.useMemo)(()=>i,[i]);return(0,qr.createPortal)((0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/45 p-6 backdrop-blur-sm`,onClick:e=>e.target===e.currentTarget?n():void 0,children:(0,K.jsxs)(`div`,{className:`flex h-[78vh] w-[86vw] max-w-[1500px] flex-col overflow-hidden rounded-2xl border border-border bg-background shadow-quickforge`,children:[(0,K.jsxs)(`div`,{className:`flex h-14 shrink-0 items-center gap-3 border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5`,children:[(0,K.jsx)(ge,{className:`size-5 text-muted-foreground`}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`div`,{className:`truncate text-base font-medium text-foreground`,children:W(`gitGraph`)}),(0,K.jsx)(`div`,{className:`truncate text-xs text-muted-foreground`,children:t})]}),(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:`size-8`,onClick:()=>void u(),"aria-label":W(`refresh`),disabled:o,children:o?(0,K.jsx)(B,{className:`size-4 animate-spin`}):(0,K.jsx)(r,{className:`size-4`})}),(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:`size-8`,onClick:n,"aria-label":W(`close`),children:(0,K.jsx)(z,{className:`size-4`})})]}),(0,K.jsxs)(`div`,{className:`grid shrink-0 grid-cols-[72px_minmax(360px,1fr)_160px_140px_120px] border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] bg-muted/20 text-sm font-medium text-muted-foreground`,children:[(0,K.jsx)(`div`,{className:`border-r-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3`,children:W(`graphColumn`)}),(0,K.jsx)(`div`,{className:`border-r-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3`,children:W(`description`)}),(0,K.jsx)(`div`,{className:`border-r-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3`,children:W(`date`)}),(0,K.jsx)(`div`,{className:`border-r-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3`,children:W(`author`)}),(0,K.jsx)(`div`,{className:`px-5 py-3`,children:W(`commit`)})]}),(0,K.jsx)(`div`,{className:`min-h-0 flex-1 overflow-auto`,children:o?(0,K.jsxs)(`div`,{className:`flex h-full items-center justify-center gap-2 text-sm text-muted-foreground`,children:[(0,K.jsx)(B,{className:`size-4 animate-spin`}),(0,K.jsx)(`span`,{children:W(`loading`)})]}):c?(0,K.jsx)(`div`,{className:`m-5 rounded-2xl border border-border bg-muted/30 p-5 text-sm text-muted-foreground`,children:c}):d.length===0?(0,K.jsx)(`div`,{className:`m-5 rounded-2xl border border-border bg-muted/30 p-5 text-sm text-muted-foreground`,children:W(`noGitCommits`)}):d.map((e,t)=>(0,K.jsxs)(`div`,{className:G(`grid min-h-14 grid-cols-[72px_minmax(360px,1fr)_160px_140px_120px] border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] text-sm`,e.decorations.some(e=>e.type===`head`||e.name===`HEAD`)?`bg-muted/28`:`bg-background`),children:[(0,K.jsx)(Jd,{index:t,isLast:t===d.length-1}),(0,K.jsx)(`div`,{className:`flex min-w-0 items-center gap-2 px-5 py-3`,children:(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-2`,children:[e.decorations.map(t=>(0,K.jsx)(qd,{decoration:t},`${e.hash}:${t.type}:${t.name}`)),(0,K.jsx)(`span`,{className:`min-w-0 break-words text-foreground/90`,children:e.subject})]})}),(0,K.jsx)(`div`,{className:`flex items-center border-l-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3 text-muted-foreground`,children:Gd(e.date)}),(0,K.jsx)(`div`,{className:`flex min-w-0 items-center border-l-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3 text-muted-foreground`,children:(0,K.jsx)(`span`,{className:`truncate`,children:e.author})}),(0,K.jsx)(`div`,{className:`flex items-center border-l-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3 font-mono text-muted-foreground`,children:e.shortHash})]},e.hash))})]})}),document.body)}async function Xd(e,t){let n=await fetch(e,{...t,cache:`no-store`,headers:{...t?.body?{"content-type":`application/json`}:void 0,...t?.headers}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||`Request failed: ${n.status}`);return r}function Zd(e){if(typeof crypto<`u`&&typeof crypto.getRandomValues==`function`){let t=new Uint8Array(1);return crypto.getRandomValues(t),e[t[0]%e.length]}return e[Math.floor(Math.random()*e.length)]}function Qd(){let e=()=>Array.from({length:6},()=>Zd(`ABCDEFGHJKLMNPQRSTUVWXYZ23456789`)).join(``);return`${e()}-${e()}`}function $d(e=24){return new Date(Date.now()+e*60*60*1e3).toISOString()}async function ef(e){return Xd(`/api/shares`,{method:`POST`,body:JSON.stringify(e)})}async function tf(e){return Xd(`/api/shares${e?`?sessionId=${encodeURIComponent(e)}`:``}`)}async function nf(e){return Xd(`/api/shares/${encodeURIComponent(e)}`,{method:`DELETE`})}async function rf(e){return Xd(`/api/shares/${encodeURIComponent(e)}/disable`,{method:`POST`})}async function af(e,t){return Xd(`/api/shares/${encodeURIComponent(e)}/restore`,{method:`POST`,body:JSON.stringify({expiresAt:t})})}async function of(e,t){return Xd(`/api/shares/${encodeURIComponent(e)}/expiration`,{method:`POST`,body:JSON.stringify({expiresAt:t})})}async function sf(e,t){return Xd(`/api/shares/${encodeURIComponent(e)}/update`,{method:`POST`,body:JSON.stringify(t)})}async function cf(e){return Xd(`/api/shares/${encodeURIComponent(e)}/permanent`,{method:`DELETE`})}function lf(e){return e.revokedAt?`disabled`:e.expiresAt&&Date.parse(e.expiresAt)<=Date.now()?`expired`:`active`}async function uf(e){return Xd(`/api/shared/${encodeURIComponent(e)}/meta`)}async function df(e,t=``){return Xd(`/api/shared/${encodeURIComponent(e)}/unlock`,{method:`POST`,body:JSON.stringify({password:t})})}async function ff(e){return Xd(`/api/shared/${encodeURIComponent(e)}/models`)}function pf({open:e,sessionId:t,title:n,onOpenChange:i}){let a=(0,H.useId)(),[o,s]=(0,H.useState)(`read`),[c,l]=(0,H.useState)(``),[u,d]=(0,H.useState)(`24h`),[f,p]=(0,H.useState)(!1),[m,h]=(0,H.useState)(!1),[g,_]=(0,H.useState)(``),[v,y]=(0,H.useState)([]),[b,x]=(0,H.useState)(!1),[S,C]=(0,H.useState)(),w=(0,H.useMemo)(()=>{if(u!==`never`)return $d(u===`1h`?1:u===`7d`?168:24)},[u]);if((0,H.useEffect)(()=>{!e||!t||tf(t).then(e=>y(e.shares)).catch(e=>C(e instanceof Error?e.message:`Failed to load shares`))},[e,t]),!e)return null;let T=o===`operate`,E=!!t&&(o!==`operate`||f&&c.trim()),D=async()=>{if(!(!t||!E)){if(T&&!c.trim()){C(`可操作分享必须设置密码。`);return}x(!0),C(void 0);try{let e=await ef({sessionId:t,permission:o,password:c.trim(),expiresAt:w,allowCloudUsage:o===`operate`&&m});_(e.url),await Vc(e.url),p(!1),y((await tf(t)).shares)}catch(e){C(e instanceof Error?e.message:`Failed to create share`)}finally{x(!1)}}},O=async e=>{let t=e.url||`${window.location.origin}/share/${encodeURIComponent(e.id)}`;_(t),await Vc(t)},k=async e=>{try{await nf(e),y(t=>t.map(t=>t.id===e?{...t,revokedAt:new Date().toISOString()}:t))}catch(e){C(e instanceof Error?e.message:`Failed to revoke share`)}};return(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,onMouseDown:e=>{e.target===e.currentTarget&&i(!1)},children:(0,K.jsxs)(`div`,{className:`flex max-h-[90vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl border border-border bg-background shadow-quickforge`,onMouseDown:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`shrink-0 border-b border-border px-5 py-4`,children:[(0,K.jsx)(`h2`,{className:`text-base font-semibold`,children:`分享到局域网`}),(0,K.jsxs)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:[`当前对话:`,n,`。同一个对话只会有一个固定分享链接;只读分享密码可选,可操作分享必须设置密码。`]})]}),(0,K.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-5 py-4`,children:(0,K.jsxs)(`div`,{className:`space-y-4`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`mb-2 text-sm font-medium`,children:`权限`}),(0,K.jsxs)(`div`,{className:`grid gap-2 sm:grid-cols-2`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`rounded-xl border p-3 text-left text-sm ${o===`read`?`border-primary bg-primary/10`:`border-border`}`,onClick:()=>s(`read`),children:[(0,K.jsx)(`div`,{className:`font-medium`,children:`仅阅读`}),(0,K.jsx)(`div`,{className:`mt-1 text-xs text-muted-foreground`,children:`只能查看这一个对话。`})]}),(0,K.jsxs)(`button`,{type:`button`,className:`rounded-xl border p-3 text-left text-sm ${o===`operate`?`border-red-400 bg-red-50 text-red-950`:`border-border`}`,onClick:()=>s(`operate`),children:[(0,K.jsx)(`div`,{className:`font-medium text-red-700`,children:`可操作(高危)`}),(0,K.jsx)(`div`,{className:`mt-1 text-xs text-red-700`,children:`允许对方操作这个原对话,禁止 Fork。`})]})]})]}),o===`operate`?(0,K.jsxs)(`div`,{className:`rounded-xl border border-red-300 bg-red-50 p-3 text-sm text-red-900`,children:[(0,K.jsxs)(`div`,{className:`flex gap-2 font-semibold`,children:[(0,K.jsx)(ce,{className:`mt-0.5 size-4`}),`高危可操作权限`]}),(0,K.jsx)(`p`,{className:`mt-2 text-xs leading-5`,children:`拥有链接和密码的人只能操作这一个原对话,但对方的消息、停止生成、回滚、模型/思考等级选择、YOLO 状态下可用工具等操作会按正常对话权限直接影响你的本机原对话。可操作分享必须设置密码。`}),(0,K.jsxs)(`label`,{className:`mt-3 flex items-center gap-2 text-xs font-medium`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:f,onChange:e=>p(e.target.checked)}),`我已了解风险,仍然允许可操作权限。`]}),(0,K.jsxs)(`label`,{className:`mt-3 flex items-start gap-2 text-xs font-medium`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:m,onChange:e=>h(e.target.checked)}),(0,K.jsx)(`span`,{children:`允许该分享使用我的 QuickForge Cloud 模型和额度。默认关闭。`})]})]}):null,(0,K.jsxs)(`div`,{className:`space-y-2`,children:[(0,K.jsx)(`label`,{htmlFor:a,className:`block text-sm font-medium`,children:T?`密码(可操作必填)`:`密码(可选)`}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-3 sm:flex-row sm:items-center`,children:[(0,K.jsx)(`input`,{id:a,value:c,onChange:e=>l(e.target.value),className:`h-10 w-full min-w-0 rounded-md border border-input bg-background px-3 text-sm`,placeholder:T?`可操作分享必须设置密码`:`留空则打开链接无需密码`}),(0,K.jsxs)(q,{variant:`outline`,className:`h-10 sm:shrink-0`,onClick:()=>l(Qd()),children:[(0,K.jsx)(r,{className:`mr-2 size-4`}),`生成密码`]})]}),(0,K.jsx)(`span`,{className:`block text-xs text-muted-foreground`,children:T?`可操作分享必须设置非空密码;修改密码后旧密码和已解锁状态会失效。`:`留空保存会取消密码保护;填写新密码保存后旧密码和已解锁状态会失效。`})]}),(0,K.jsxs)(`label`,{className:`block text-sm font-medium`,children:[`有效期`,(0,K.jsxs)(`select`,{value:u,onChange:e=>d(e.target.value),className:`mt-2 h-10 w-full rounded-md border border-input bg-background px-3 text-sm`,children:[(0,K.jsx)(`option`,{value:`1h`,children:`1 小时`}),(0,K.jsx)(`option`,{value:`24h`,children:`24 小时`}),(0,K.jsx)(`option`,{value:`7d`,children:`7 天`}),(0,K.jsx)(`option`,{value:`never`,children:`永久,需手动撤销`})]})]}),g?(0,K.jsxs)(`div`,{className:`rounded-xl border border-emerald-300 bg-emerald-50 p-3 text-sm text-emerald-900`,children:[`已复制到剪切板。`,(0,K.jsx)(`pre`,{className:`mt-2 max-h-36 overflow-auto whitespace-pre-wrap text-xs`,children:g})]}):null,S?(0,K.jsx)(`div`,{className:`rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:S}):null,v.length?(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`mb-2 text-sm font-medium`,children:`已有分享`}),(0,K.jsx)(`div`,{className:`space-y-2`,children:v.map(e=>(0,K.jsxs)(`div`,{className:`flex items-center gap-2 rounded-lg border border-border p-2 text-xs`,children:[(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`div`,{className:`truncate font-mono`,children:e.id}),(0,K.jsxs)(`div`,{className:`text-muted-foreground`,children:[e.permission===`operate`?`可操作`:`只读`,` · `,e.hasPassword?`有密码`:`无密码`,` · `,e.allowCloudUsage?`允许 Cloud`:`不允许 Cloud`,` · `,e.revokedAt?`已撤销`:e.expiresAt?`到期 ${new Date(e.expiresAt).toLocaleString()}`:`永久`]})]}),e.revokedAt?null:(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(q,{variant:`ghost`,size:`icon`,onClick:()=>void O(e),"aria-label":`复制分享链接`,title:`复制分享链接`,children:(0,K.jsx)(Ce,{className:`size-4`})}),(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:`text-destructive`,onClick:()=>void k(e.id),"aria-label":`撤销分享`,title:`撤销分享`,children:(0,K.jsx)(me,{className:`size-4`})})]})]},e.id))})]}):null]})}),(0,K.jsx)(`div`,{className:`shrink-0 border-t border-border px-5 py-4`,children:(0,K.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[(0,K.jsx)(q,{variant:`outline`,onClick:()=>i(!1),children:W(`cancel`)}),(0,K.jsxs)(q,{variant:o===`operate`?`destructive`:`default`,disabled:!E||b,onClick:()=>void D(),title:o===`operate`&&!c.trim()?`可操作分享必须设置密码`:void 0,children:[(0,K.jsx)(Ce,{className:`mr-2 size-4`}),o===`operate`?`保存配置并复制高危可操作链接`:`保存配置并复制链接`]})]})})]})})}function mf(e){let t=e.replace(/\\/g,`/`);return t.split(`/`).filter(Boolean).pop()||t||`artifact`}function hf(e){let t=e.toLowerCase(),n=t.replace(/\\/g,`/`).split(`/`).pop()||t;return t.endsWith(`.html`)||t.endsWith(`.htm`)?`html`:/\.(svg|png|jpe?g|webp|gif|ico)$/i.test(t)?`image`:/\.(md|mdx|markdown)$/i.test(t)?`markdown`:n===`dockerfile`||n.endsWith(`.dockerfile`)||n===`makefile`||/\.(ts|tsx|js|jsx|mjs|cjs|css|scss|less|json|jsonc|txt|csv|tsv|log|sql|xml|yml|yaml|toml|ini|py|rb|go|rs|java|swift|kt|kts|c|h|cpp|hpp|cs|php|sh|bash|zsh|ps1)$/i.test(t)?`code`:`unknown`}function gf(e){return hf(e)!==`unknown`}var _f=/\.(svg|png|jpe?g|webp|gif|ico)$/i;function vf(e){return hf(e)===`html`||_f.test(e)}function yf(e,t=hf(e)){if(t===`markdown`||t===`code`)return`reader`;if((t===`html`||t===`image`)&&vf(e))return`browser`}function bf(e,t){let n=t.replace(/\\/g,`/`);return!e?.trim()||n.startsWith(`/`)||/^[a-zA-Z]:\//.test(n)?t:`${e.trim().replace(/\\/g,`/`).replace(/\/+$/,``)}/${n.replace(/^\/+/,``)}`}function xf(e,t,n){let r=t.replace(/\\/g,`/`),i=r.match(/^\/+/)?.[0]??``,a=i+r.slice(i.length).split(`/`).filter(Boolean).map(e=>encodeURIComponent(e)).join(`/`),o=`/api/workspace/preview/${encodeURIComponent(e)}/${a}`;return n?`${o}?r=${n}`:o}function Sf(e){return e.replace(/\\/g,`/`).toLowerCase()}function Cf(e){let t=mf(e.path).toLowerCase();return e.defaultPreview?0:e.explicit&&e.preview?1:e.explicit?2:t===`index.html`?3:e.kind===`html`?4:e.kind===`image`?5:e.kind===`markdown`?6:e.kind===`code`?7:20}function wf(e){let t=new Map;for(let n of e){if(!n.path)continue;let e=Sf(n.path),r=n.kind??hf(n.path),i=t.get(e),a=n.preview??gf(n.path),o=n.source===`present_files`||n.presentation===`explicit`;if(!i){t.set(e,{id:e,path:n.path,title:n.title,description:n.description,kind:r,preview:a,defaultPreview:!!n.defaultPreview,explicit:o,addedLines:n.addedLines,removedLines:n.removedLines,sources:[n.source],toolCallIds:n.toolCallId?[n.toolCallId]:[]});continue}i.preview=i.preview||a,i.defaultPreview=i.defaultPreview||!!n.defaultPreview,i.explicit=i.explicit||o,i.title=n.title||i.title,i.description=n.description||i.description,typeof n.addedLines==`number`&&(i.addedLines=(i.addedLines??0)+n.addedLines),typeof n.removedLines==`number`&&(i.removedLines=(i.removedLines??0)+n.removedLines),i.kind=i.kind===`unknown`?r:i.kind,i.sources.includes(n.source)||i.sources.push(n.source),n.toolCallId&&!i.toolCallIds.includes(n.toolCallId)&&i.toolCallIds.push(n.toolCallId)}return[...t.values()].sort((e,t)=>Cf(e)-Cf(t))}function Tf(e){let t=wf(e).filter(e=>e.preview&&e.explicit);if(t.length<=1)return t[0];let n=new Map;for(let t=0;t<e.length;t++){let r=e[t]?.toolCallId;r&&n.set(r,t)}let r=e=>{let t=e.toolCallIds,r=-1;for(let e of t){let t=n.get(e);typeof t==`number`&&t>r&&(r=t)}return r};return[...t].sort((e,t)=>r(t)-r(e))[0]}var Ef=`http://42.194.187.88:8080`,Df=`quickforge-mobile`,Of=`1.0.0`,kf=`手机 (Android)`,Af=`android`,jf=`urn:ietf:params:oauth:grant-type:device_code`,Mf=`refresh_token`,Nf=5,Pf=60,Ff=600*1e3,If=class extends Error{status;code;constructor(e,t=0,n=`cloud_remote_request_failed`){super(e),this.name=`CloudRemoteClientError`,this.status=t,this.code=n}};function Lf(e){return typeof e==`object`&&e?e:{}}function Rf(e){if(typeof e==`object`&&e){let t=e,n=t.error;if(typeof n==`string`)return{message:n,code:typeof t.code==`string`?t.code:`cloud_remote_request_failed`};if(typeof n==`object`&&n){let e=n;return{message:typeof e.message==`string`?e.message:`云服务请求失败`,code:typeof e.code==`string`?e.code:`cloud_remote_request_failed`}}}return{message:`云服务请求失败`,code:`cloud_remote_request_failed`}}function zf(){if(globalThis.crypto!==void 0&&typeof globalThis.crypto.randomUUID==`function`)return globalThis.crypto.randomUUID();let e=new Uint8Array(16);globalThis.crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}async function Bf(){if(globalThis.crypto===void 0||globalThis.crypto.subtle===void 0)throw new If(`当前设备不支持安全登录,请升级系统`,0,`cloud_remote_unsupported_crypto`);try{return await globalThis.crypto.subtle.generateKey({name:`Ed25519`},!0,[`sign`,`verify`])}catch{throw new If(`当前设备不支持安全登录,请升级系统`,0,`cloud_remote_unsupported_crypto`)}}async function Vf(e){let t=new Uint8Array(await globalThis.crypto.subtle.exportKey(`raw`,e)),n=``;for(let e of t)n+=String.fromCharCode(e);return btoa(n).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function Hf(e){return new Promise(t=>{setTimeout(t,e)})}async function Uf(e,t,n,r){let i={Accept:`application/json`,...n.body===void 0?{}:{"Content-Type":`application/json`},...r?{Authorization:`Bearer ${r}`}:{},...n.headers};if(Me!==void 0&&typeof Me.isNativePlatform==`function`&&Me.isNativePlatform()){let r=await je.request({url:`${e}${t}`,method:n.method??`GET`,headers:i,data:n.body,connectTimeout:15e3,readTimeout:3e4});if(r.status<200||r.status>=300){let e=Rf(r.data);throw new If(e.message,r.status,e.code)}return r.data}let a=await fetch(`${e}${t}`,{method:n.method??`GET`,headers:i,body:n.body===void 0?void 0:JSON.stringify(n.body),cache:`no-store`});if(!a.ok){let e={};try{e=await a.json()}catch{}let t=Rf(e);throw new If(t.message===`云服务请求失败`?`云服务请求失败 (${a.status})`:t.message,a.status,t.code)}return a.json()}var Wf=class{baseUrl;accessToken=``;refreshToken=``;refreshPromise=null;constructor(e){this.baseUrl=e.replace(/\/+$/,``)}get cloudUrl(){return this.baseUrl}clearTokens(){this.accessToken=``,this.refreshToken=``}async deviceAuthorization(){let e=zf(),t=await Bf(),n=await Vf(t.publicKey),r=Lf(await this.request(`POST`,`/oauth/device_authorization`,{installationId:e,clientId:Df,publicKey:n,installationName:kf,platform:Af,clientVersion:Of})),i=r.deviceCode,a=r.userCode;if(typeof i!=`string`||i===``||typeof a!=`string`||a===``)throw new If(`无法获取设备授权码,请稍后重试`,0,`cloud_remote_request_failed`);return{deviceCode:i,userCode:a,interval:typeof r.interval==`number`&&r.interval>0?r.interval:Nf,privateKey:t.privateKey}}async login(e,t,n=``){let r=await this.request(`POST`,`/v1/accounts/login`,{userCode:n,email:e,password:t});return this.consumeSession(r)}async register(e,t,n=``){let r=await this.request(`POST`,`/v1/accounts/register`,{userCode:n,email:e,password:t});return this.consumeSession(r)}async pollDeviceToken(e,t){let n=t>0?t:Nf,r=Date.now()+Ff;for(;;){if(Date.now()>r)throw new If(`登录超时,请重新发起登录`,0,`device_flow_timeout`);try{let t=await this.request(`POST`,`/oauth/token`,{grantType:jf,deviceCode:e,clientId:Df}),n=this.parseTokenSet(t);return this.accessToken=n.accessToken,this.refreshToken=n.refreshToken,n}catch(e){if(!(e instanceof If)||e.status!==400)throw e;if(e.code!==`authorization_pending`)if(e.code===`slow_down`)n=Math.min(n+5,Pf);else if(e.code===`expired_token`)throw new If(`设备授权已过期,请重新发起登录`,400,`expired_token`);else if(e.code===`access_denied`)throw new If(`设备授权已被拒绝`,400,`access_denied`);else if(e.code===`invalid_grant`)throw new If(`授权请求无效,请重新登录`,400,`invalid_grant`);else throw e;await Hf(n*1e3)}}}refresh(){return this.refreshPromise||=this.doRefresh().finally(()=>{this.refreshPromise=null}),this.refreshPromise}async doRefresh(){if(this.refreshToken===``)throw new If(`登录已过期,请重新登录`,0,`auth_expired`);let e=await this.request(`POST`,`/oauth/token`,{grantType:Mf,refreshToken:this.refreshToken,clientId:Df}),t=this.parseTokenSet(e);return this.accessToken=t.accessToken,t.refreshToken!==``&&(this.refreshToken=t.refreshToken),t}async getMe(){let e=Lf(await this.request(`GET`,`/v1/me`,void 0,!0)),t=Lf(e.account??e);return{id:typeof t.id==`string`?t.id:``,email:typeof t.email==`string`?t.email:``,mode:typeof t.mode==`string`?t.mode:void 0,plan:typeof t.plan==`string`?t.plan:void 0}}async listDevices(){let e=Lf(await this.request(`GET`,`/v1/remote/devices`,void 0,!0)).items;return Array.isArray(e)?{items:e.map(e=>{let t=Lf(e),n=Array.isArray(t.services)?t.services.map(e=>{let t=Lf(e);return{id:typeof t.id==`number`?t.id:0,name:typeof t.name==`string`?t.name:``,port:typeof t.port==`number`?t.port:0,protocol:typeof t.protocol==`string`?t.protocol:``}}):void 0;return{installationId:typeof t.installationId==`string`?t.installationId:typeof t.id==`string`?t.id:``,name:typeof t.name==`string`?t.name:void 0,online:t.online===!0,services:n}})}:{items:[]}}async turnCredentials(){let e=Lf(await this.request(`POST`,`/v1/remote/turn-credentials`,void 0,!0));return{urls:Array.isArray(e.urls)?e.urls.filter(e=>typeof e==`string`):[],username:typeof e.username==`string`?e.username:``,credential:typeof e.credential==`string`?e.credential:``,ttl:typeof e.ttl==`number`?e.ttl:0}}async request(e,t,n,r=!1){try{return await Uf(this.baseUrl,t,{method:e,body:n},r&&this.accessToken||void 0)}catch(i){if(r&&i instanceof If&&i.status===401){try{await this.refresh()}catch{throw new If(`登录已过期,请重新登录`,0,`auth_expired`)}return Uf(this.baseUrl,t,{method:e,body:n},this.accessToken||void 0)}throw i instanceof If?i:new If(`无法连接云服务,请检查网络或云服务地址`,0,`network_error`)}}parseTokenSet(e){let t=Lf(e),n=t.access_token??t.accessToken,r=t.refresh_token??t.refreshToken;if(typeof n!=`string`||n===``)throw new If(`云服务返回了无效的令牌`,0,`cloud_remote_request_failed`);let i=t.token_type??t.tokenType,a=t.expires_in??t.expiresIn,o=t.refresh_token_expires_in??t.refreshTokenExpiresIn,s=t.installation_id??t.installationId,c=t.identity_mode??t.identityMode;return{accessToken:n,refreshToken:typeof r==`string`?r:``,tokenType:typeof i==`string`?i:`Bearer`,expiresIn:typeof a==`number`?a:0,refreshTokenExpiresIn:typeof o==`number`?o:0,installationId:typeof s==`string`?s:``,identityMode:typeof c==`string`?c:``}}consumeSession(e){let t=Lf(e),n=typeof t.token==`object`&&t.token!==null?t.token:t,r=n.access_token??n.accessToken,i=n.refresh_token??n.refreshToken,a=Lf(t.account??t.user),o=Object.keys(a).length>0?{id:typeof a.id==`string`?a.id:``,email:typeof a.email==`string`?a.email:``,mode:typeof a.mode==`string`?a.mode:void 0,plan:typeof a.plan==`string`?a.plan:void 0}:void 0;if(typeof r==`string`&&r!==``&&typeof i==`string`&&i!==``){let e=n.expires_in??n.expiresIn;return this.accessToken=r,this.refreshToken=i,{accessToken:r,refreshToken:i,expiresIn:typeof e==`number`?e:void 0,account:o,bound:!0}}return{accessToken:``,refreshToken:``,account:o,bound:!0}}},Gf=Ae(`RemoteTunnel`),Kf=`http://127.0.0.1:18080/?quickforgeRemote=1`,qf=`http://127.0.0.1:18080/`;async function Jf(){for(let e=0;e<3;e++){let t=new AbortController,n=window.setTimeout(()=>t.abort(),3e3);try{await fetch(qf,{mode:`no-cors`,cache:`no-store`,signal:t.signal}),window.clearTimeout(n),window.location.href=Kf;return}catch{window.clearTimeout(n),e<2&&await new Promise(e=>setTimeout(e,700))}}throw Error(`本地隧道端口未就绪,请断开后重试`)}function Yf(e){return e instanceof If?e.message||`云服务请求失败,请稍后重试`:e instanceof Error?e.message:`操作失败,请稍后重试`}function Xf(e){return e instanceof If?e.code===`cloud_remote_unsupported_crypto`||e.code===`access_denied`||e.code===`expired_token`||e.code===`device_flow_timeout`?e.message||`设备授权未完成,请重新尝试`:e.status===0?`无法连接云服务,请检查“云服务地址”与网络后重试`:e.message||`云服务请求失败,请稍后重试`:`无法连接云服务,请检查“云服务地址”与网络后重试`}function Zf(e){return e.name?.trim()||e.installationId}function Qf({onSessionChange:e}){let[t,n]=(0,H.useState)(`checking`),[i,a]=(0,H.useState)(`login`),[o,s]=(0,H.useState)(``),[l,d]=(0,H.useState)(``),[f,p]=(0,H.useState)(``),[m,h]=(0,H.useState)(!1),[g,_]=(0,H.useState)(Ef),[v,b]=(0,H.useState)(!1),[x,S]=(0,H.useState)(``),[C,w]=(0,H.useState)(``),[T,E]=(0,H.useState)(!1),[D,te]=(0,H.useState)(null),[A,j]=(0,H.useState)([]),[ne,re]=(0,H.useState)(null),[M,N]=(0,H.useState)(null),[P,ie]=(0,H.useState)(null),F=(0,H.useRef)(null),ae=()=>((!F.current||F.current.cloudUrl!==g.replace(/\/+$/,``))&&(F.current=new Wf(g)),F.current);(0,H.useEffect)(()=>{let e=!0;return Gf.addListener(`remoteStateChanged`,t=>{e&&(N(t),t.state===`connected`?Jf().catch(t=>{e&&(re(null),N({state:`error`,error:Yf(t)}),S(Yf(t)),Gf.disconnect().catch(()=>{}))}):t.state===`reconnecting`?(re(null),N(t)):t.state===`error`&&(re(null),S(t.error||`隧道连接失败,请重试`)))}).catch(()=>{}),()=>{e=!1}},[]);let I=async()=>{E(!0),S(``);try{j((await Gf.listDevices()).items??[]),n(`devices`)}catch{try{j((await ae().listDevices()).items),n(`devices`)}catch(e){S(Yf(e)),n(`sign-in`)}}finally{E(!1)}};(0,H.useEffect)(()=>{let t=!0;return(async()=>{try{let r=await Gf.hasSession();if(!t)return;ie(r),e?.(r);let i=r.cloudUrl;i&&_(e=>e===`http://42.194.187.88:8080`?i:e),n(r.signedIn?`session-choice`:`sign-in`)}catch{t&&n(`sign-in`)}})(),()=>{t=!1}},[e]);let L=async()=>{te(`continue`);try{await I()}finally{te(null)}},R=async()=>{E(!0),te(`switch`),S(``),w(``);try{await Gf.disconnect().catch(()=>{}),await Gf.signOut(),ae().clearTokens(),j([]),re(null),N(null),d(``),n(`sign-in`),e?.({signedIn:!1})}catch(e){S(Yf(e))}finally{te(null),E(!1)}},oe=async t=>{t.preventDefault();let n=o.trim(),r=f.trim();if(!n||!l){S(`请输入邮箱和密码`);return}E(!0),S(``),w(``);try{let t=ae();if(r){let a=i===`register`?await t.register(n,l,r):await t.login(n,l,r);a.accessToken&&a.refreshToken?(await Gf.setToken({accessToken:a.accessToken,refreshToken:a.refreshToken,cloudUrl:t.cloudUrl,email:n}),ie({signedIn:!0,email:n,cloudUrl:t.cloudUrl}),e?.({signedIn:!0,email:n,cloudUrl:t.cloudUrl}),await I()):w(`已在电脑端完成设备授权;若电脑端 QuickForge 正在等待授权,请返回电脑端确认。`);return}let a=await t.deviceAuthorization();await(i===`register`?t.register(n,l,a.userCode):t.login(n,l,a.userCode));let o=await t.pollDeviceToken(a.deviceCode,a.interval);await Gf.setToken({accessToken:o.accessToken,refreshToken:o.refreshToken,cloudUrl:t.cloudUrl,email:n}),ie({signedIn:!0,email:n,cloudUrl:t.cloudUrl}),e?.({signedIn:!0,email:n,cloudUrl:t.cloudUrl}),await I()}catch(e){S(Xf(e))}finally{E(!1)}},z=async e=>{S(``),re(e.installationId),N({state:`connecting`});try{(await Gf.getState()).state!==`idle`&&await Gf.disconnect().catch(()=>{}),await Gf.connect({installationId:e.installationId})}catch(e){re(null),S(Yf(e))}},se=async()=>{E(!0),S(``),w(``);try{await Gf.disconnect().catch(()=>{}),await Gf.signOut()}catch(e){S(Yf(e))}finally{ae().clearTokens(),j([]),re(null),N(null),d(``),n(`sign-in`),E(!1),e?.({signedIn:!1})}};return t===`checking`?(0,K.jsxs)(`main`,{className:`flex min-h-dvh flex-col items-center justify-center bg-background px-8 pb-[max(2rem,env(safe-area-inset-bottom))] pt-[max(2rem,env(safe-area-inset-top))] text-foreground`,role:`status`,"aria-live":`polite`,children:[(0,K.jsx)(B,{className:`size-7 animate-spin text-muted-foreground`,"aria-hidden":`true`}),(0,K.jsx)(`p`,{className:`mt-4 text-sm text-muted-foreground`,children:`正在检查云账户状态…`})]}):t===`session-choice`?(0,K.jsxs)(`section`,{"aria-labelledby":`quickforge-cloud-remote-session-choice`,children:[(0,K.jsxs)(`header`,{className:`mb-6 flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(xe,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 pt-0.5`,children:[(0,K.jsx)(`h1`,{id:`quickforge-cloud-remote-session-choice`,className:`text-lg font-semibold tracking-tight`,children:`云账户远程访问`}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:`检测到此设备已登录。选择是否继续当前会话。`})]})]}),(0,K.jsxs)(`div`,{className:`rounded-2xl border border-border bg-background p-4 shadow-quickforge`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`p`,{className:`truncate text-base font-semibold text-foreground`,children:P?.email||`已登录账号`}),(0,K.jsx)(`span`,{className:`shrink-0 rounded-full bg-emerald-500/10 px-2 py-0.5 text-[11px] font-medium text-emerald-600`,children:`会话有效`})]}),P?.cloudUrl?(0,K.jsx)(`p`,{className:`mt-1 truncate font-mono text-xs text-muted-foreground`,children:P.cloudUrl}):null]}),(0,K.jsxs)(`div`,{className:`mt-4 rounded-2xl border border-border bg-background p-5 shadow-quickforge`,children:[(0,K.jsxs)(`div`,{className:`flex gap-2.5 rounded-xl bg-muted/30 px-3 py-2.5 text-xs leading-5 text-muted-foreground`,children:[(0,K.jsx)(ue,{className:`mt-0.5 size-4 shrink-0`,"aria-hidden":`true`}),(0,K.jsx)(`p`,{children:`继续后才会加载当前账户的在线设备;也可以清理本机会话并重新登录。`})]}),x?(0,K.jsx)(`p`,{className:`mt-4 text-sm text-destructive`,role:`alert`,children:x}):null,(0,K.jsxs)(`button`,{type:`button`,className:`mt-5 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85 disabled:opacity-60`,onClick:()=>{L()},disabled:T,children:[D===`continue`?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(xe,{className:`size-4`,"aria-hidden":`true`}),`继续当前登录`]}),(0,K.jsxs)(`button`,{type:`button`,className:`mt-3 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl border border-border text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65 disabled:opacity-60`,onClick:()=>{R()},disabled:T,children:[D===`switch`?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(u,{className:`size-4`,"aria-hidden":`true`}),`使用其他账号`]}),T?(0,K.jsx)(`p`,{className:`mt-2 text-center text-xs text-muted-foreground`,role:`status`,"aria-live":`polite`,children:D===`switch`?`正在清理当前登录…`:`正在加载设备…`}):null]})]}):t===`devices`?(0,K.jsxs)(`section`,{"aria-labelledby":`quickforge-cloud-remote-devices`,children:[(0,K.jsxs)(`header`,{className:`mb-6 flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(xe,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1 pt-0.5`,children:[(0,K.jsx)(`h1`,{id:`quickforge-cloud-remote-devices`,className:`text-lg font-semibold tracking-tight`,children:`云账户远程访问`}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:`选择一台在线设备建立远程连接。`})]}),(0,K.jsx)(`button`,{type:`button`,className:`inline-flex size-10 shrink-0 items-center justify-center rounded-xl text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65`,onClick:()=>{I()},disabled:T,title:`刷新设备列表`,"aria-label":`刷新设备列表`,children:(0,K.jsx)(r,{className:`size-4 ${T?`animate-spin`:``}`,"aria-hidden":`true`})})]}),(0,K.jsxs)(`div`,{className:`mb-4 flex items-center justify-between gap-3 rounded-2xl border border-border bg-background p-4 shadow-quickforge`,children:[(0,K.jsxs)(`div`,{className:`min-w-0`,children:[(0,K.jsx)(`p`,{className:`text-xs font-medium text-muted-foreground`,children:`当前账号`}),(0,K.jsx)(`p`,{className:`mt-0.5 truncate text-sm font-medium text-foreground`,children:P?.email||`已登录账号`}),P?.cloudUrl?(0,K.jsx)(`p`,{className:`mt-0.5 truncate font-mono text-xs text-muted-foreground`,children:P.cloudUrl}):null]}),(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-11 shrink-0 items-center justify-center gap-2 rounded-xl border border-border px-4 text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65 disabled:opacity-60`,onClick:()=>{R()},disabled:T,children:[D===`switch`?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(r,{className:`size-4`,"aria-hidden":`true`}),`切换账号`]})]}),x?(0,K.jsx)(`p`,{className:`mb-4 text-sm text-destructive`,role:`alert`,children:x}):null,C?(0,K.jsx)(`p`,{className:`mb-4 text-sm text-muted-foreground`,role:`status`,children:C}):null,M&&M.state!==`idle`?(0,K.jsxs)(`div`,{className:`mb-4`,children:[(0,K.jsxs)(`p`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,role:`status`,"aria-live":`polite`,children:[M.state===`connecting`||M.state===`reconnecting`?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(fe,{className:`size-4`,"aria-hidden":`true`}),M.state===`connecting`?`正在建立加密隧道…`:M.state===`reconnecting`?`连接中断,正在自动重连…`:M.state===`connected`?`隧道已就绪,正在打开远程界面…`:`连接已断开`]}),M.state===`connected`||M.state===`reconnecting`?(0,K.jsxs)(`p`,{className:`mt-2 flex items-center gap-1.5 text-xs text-muted-foreground`,children:[(0,K.jsx)(ue,{className:`size-3.5 shrink-0`,"aria-hidden":`true`}),`断线自动重连已开启,网络恢复后自动恢复连接`]}):null]}):null,(0,K.jsx)(`div`,{className:`overflow-hidden rounded-2xl border border-border bg-background`,children:A.length===0?(0,K.jsxs)(`div`,{className:`px-5 py-10 text-center`,children:[(0,K.jsx)(c,{className:`mx-auto size-8 text-muted-foreground/50`,"aria-hidden":`true`}),(0,K.jsx)(`p`,{className:`mt-3 text-sm text-muted-foreground`,children:`没有可用的在线设备`}),(0,K.jsx)(`p`,{className:`mt-1 text-xs leading-5 text-muted-foreground/75`,children:`请确认电脑端 QuickForge 的云远程代理(agent)已登录并在线。`})]}):A.map(e=>{let t=ne===e.installationId;return(0,K.jsx)(`div`,{className:`border-b border-border last:border-b-0`,children:(0,K.jsxs)(`button`,{type:`button`,className:`flex min-h-[68px] w-full items-center gap-3 p-3 text-left transition-colors hover:bg-muted/45 active:bg-muted/65 disabled:opacity-60`,onClick:()=>{z(e)},disabled:T||ne!==null||e.online===!1,title:e.online===!1?`设备当前离线`:`连接 ${Zf(e)}`,children:[(0,K.jsx)(`span`,{className:`flex size-9 shrink-0 items-center justify-center rounded-xl bg-muted/45 text-muted-foreground`,children:(0,K.jsx)(ee,{className:`size-4`,"aria-hidden":`true`})}),(0,K.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`span`,{className:`truncate text-sm font-medium text-foreground`,children:Zf(e)}),(0,K.jsx)(`span`,{className:`shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium ${e.online===!1?`bg-muted text-muted-foreground`:`bg-emerald-500/10 text-emerald-600`}`,children:e.online===!1?`离线`:`在线`})]}),(0,K.jsx)(`span`,{className:`mt-1 block truncate font-mono text-xs text-muted-foreground`,children:e.installationId})]}),t?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin text-muted-foreground`,"aria-hidden":`true`}):(0,K.jsx)(y,{className:`size-4 shrink-0 -rotate-90 text-muted-foreground/65`,"aria-hidden":`true`})]})},e.installationId)})}),(0,K.jsxs)(`button`,{type:`button`,className:`mt-6 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl border border-border text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65 disabled:opacity-60`,onClick:()=>{se()},disabled:T,children:[(0,K.jsx)(u,{className:`size-4`,"aria-hidden":`true`}),`退出登录`]})]}):(0,K.jsxs)(`section`,{"aria-labelledby":`quickforge-cloud-remote-signin`,children:[(0,K.jsxs)(`header`,{className:`mb-6 flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(xe,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 pt-0.5`,children:[(0,K.jsx)(`h1`,{id:`quickforge-cloud-remote-signin`,className:`text-lg font-semibold tracking-tight`,children:`云账户远程访问`}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:`通过云账户加密隧道访问家中电脑:输入邮箱密码即可登录,手机自动完成设备授权。`})]})]}),(0,K.jsxs)(`form`,{className:`rounded-2xl border border-border bg-background p-5 shadow-quickforge`,onSubmit:oe,children:[(0,K.jsxs)(`div`,{className:`mb-5 grid grid-cols-2 gap-1 rounded-xl bg-muted/40 p-1`,role:`tablist`,"aria-label":`登录或注册`,children:[(0,K.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":i===`login`,className:`rounded-lg py-2 text-sm font-medium transition-colors ${i===`login`?`bg-background text-foreground shadow-sm`:`text-muted-foreground hover:text-foreground`}`,onClick:()=>{a(`login`),S(``),w(``)},children:`登录`}),(0,K.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":i===`register`,className:`rounded-lg py-2 text-sm font-medium transition-colors ${i===`register`?`bg-background text-foreground shadow-sm`:`text-muted-foreground hover:text-foreground`}`,onClick:()=>{a(`register`),S(``),w(``)},children:`注册`})]}),(0,K.jsxs)(`div`,{className:`mb-5 flex gap-2.5 rounded-xl bg-muted/30 px-3 py-2.5 text-xs leading-5 text-muted-foreground`,children:[(0,K.jsx)(ue,{className:`mt-0.5 size-4 shrink-0`,"aria-hidden":`true`}),(0,K.jsx)(`p`,{children:`直连云 API(原生通道绕 CORS)。令牌仅存于内存,刷新令牌由系统安全存储保护。`})]}),(0,K.jsx)(`label`,{className:`block text-sm font-medium`,htmlFor:`quickforge-cloud-remote-email`,children:`邮箱`}),(0,K.jsx)(`input`,{id:`quickforge-cloud-remote-email`,type:`email`,autoCapitalize:`none`,autoCorrect:`off`,spellCheck:!1,autoComplete:`email`,value:o,onChange:e=>{s(e.target.value),S(``),w(``)},placeholder:`you@example.com`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsx)(`label`,{className:`mt-4 block text-sm font-medium`,htmlFor:`quickforge-cloud-remote-password`,children:`密码`}),(0,K.jsx)(`input`,{id:`quickforge-cloud-remote-password`,type:`password`,autoComplete:i===`register`?`new-password`:`current-password`,value:l,onChange:e=>{d(e.target.value),S(``),w(``)},placeholder:i===`register`?`至少 8 个字符`:`输入密码`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsxs)(`button`,{type:`button`,className:`mt-4 flex w-full items-center justify-between rounded-xl px-1 py-2 text-sm text-muted-foreground transition-colors hover:text-foreground`,onClick:()=>h(e=>!e),"aria-expanded":m,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(k,{className:`size-4`,"aria-hidden":`true`}),`设备验证码`,(0,K.jsx)(`span`,{className:`text-xs text-muted-foreground/70`,children:`(高级)`})]}),(0,K.jsx)(y,{className:`size-4 transition-transform ${m?`rotate-180`:``}`,"aria-hidden":`true`})]}),m?(0,K.jsxs)(`div`,{className:`mt-1 rounded-xl bg-muted/30 px-3 py-2.5`,children:[(0,K.jsx)(`input`,{id:`quickforge-cloud-remote-usercode`,autoCapitalize:`characters`,autoCorrect:`off`,spellCheck:!1,value:f,onChange:e=>{p(e.target.value),S(``),w(``)},placeholder:`ABCD-2345`,className:`h-10 w-full rounded-lg border border-input bg-background px-3 font-mono text-sm tracking-widest outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/50 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsx)(`p`,{className:`mt-2 text-xs leading-5 text-muted-foreground`,children:`电脑端 QuickForge 已发起“云远程访问”授权时,可填写电脑端显示的验证码直接批准;通常无需填写。`})]}):null,(0,K.jsxs)(`button`,{type:`button`,className:`mt-2 flex w-full items-center justify-between rounded-xl px-1 py-2 text-sm text-muted-foreground transition-colors hover:text-foreground`,onClick:()=>b(e=>!e),"aria-expanded":v,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(xe,{className:`size-4`,"aria-hidden":`true`}),`云服务地址`]}),(0,K.jsx)(y,{className:`size-4 transition-transform ${v?`rotate-180`:``}`,"aria-hidden":`true`})]}),v?(0,K.jsxs)(`div`,{className:`mt-1 rounded-xl bg-muted/30 px-3 py-2.5`,children:[(0,K.jsx)(`input`,{id:`quickforge-cloud-remote-baseurl`,autoCapitalize:`none`,autoCorrect:`off`,inputMode:`url`,spellCheck:!1,value:g,onChange:e=>{_(e.target.value),S(``),w(``)},placeholder:`https://cloud.quickforge.app`,className:`h-10 w-full rounded-lg border border-input bg-background px-3 font-mono text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/50 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsx)(`p`,{className:`mt-2 text-xs leading-5 text-muted-foreground`,children:`正式域名确定前的占位地址;仅在本次会话内生效,不持久化。`})]}):null,x?(0,K.jsx)(`p`,{className:`mt-3 text-sm text-destructive`,role:`alert`,children:x}):null,C?(0,K.jsx)(`p`,{className:`mt-3 text-sm text-muted-foreground`,role:`status`,children:C}):null,(0,K.jsxs)(`button`,{type:`submit`,className:`mt-5 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85 disabled:opacity-60`,disabled:T,children:[T?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(O,{className:`size-4`,"aria-hidden":`true`}),i===`register`?`注册并授权`:`登录`]}),T?(0,K.jsx)(`p`,{className:`mt-2 text-center text-xs text-muted-foreground`,role:`status`,children:`正在发起安全登录…`}):null]}),(0,K.jsxs)(`p`,{className:`mt-4 px-1 text-xs leading-5 text-muted-foreground/80`,children:[`连接成功后将在本机 `,(0,K.jsx)(`span`,{className:`font-mono text-foreground/70`,children:`127.0.0.1:18080`}),` 打开远程 QuickForge 界面;远程会话沿用与 Tailscale 相同的安全裁剪(终端、系统代理等不可用)。`]})]})}var $f=800;function ep(){let e=(0,H.useMemo)(()=>Rt(),[]),[t,n]=(0,H.useState)(e),[r,i]=(0,H.useState)(null),[a,s]=(0,H.useState)(e.urls.length===0),[c,l]=(0,H.useState)(``),[u,d]=(0,H.useState)(``),[f,p]=(0,H.useState)(``),[m,h]=(0,H.useState)(!1),[g,_]=(0,H.useState)(null),[v,y]=(0,H.useState)(null),[b,x]=(0,H.useState)(``),[C,w]=(0,H.useState)(null),[T,D]=(0,H.useState)(()=>new URLSearchParams(location.search).get(`tab`)===`servers`?`servers`:`cloud`),[O,k]=(0,H.useState)({signedIn:!1});(0,H.useEffect)(()=>{if(!r)return;let e=window.setTimeout(()=>{window.location.assign(Vt(r))},$f);return()=>window.clearTimeout(e)},[r]),(0,H.useEffect)(()=>{let e=!0;return Gf.hasSession().then(t=>{e&&k(t)}).catch(()=>{}),()=>{e=!1}},[]);let te=(0,H.useMemo)(()=>{if(!c.trim())return``;try{return Ft(c)}catch{return``}},[c]),A=e=>{zt(e),n(e)},j=()=>{l(``),d(``),p(``)},ne=()=>{j(),h(!1),_(null),y(null),s(!0)},re=e=>{try{let n=Ft(c),r=t.urls.includes(n)?t.urls:[...t.urls,n],a=u.trim(),o={...t.aliases??{}};a&&(o[n]=a),A({urls:r,aliases:o,lastUsedUrl:e?n:t.lastUsedUrl||n}),j(),h(!0),e?i(n):s(!1)}catch(e){h(!1),p(e instanceof Error?e.message:`无法保存 QuickForge 服务地址`)}},M=e=>{e.preventDefault(),re(!0)},N=e=>{try{A({...t,lastUsedUrl:e}),i(e)}catch(e){p(e instanceof Error?e.message:`无法连接到 QuickForge 服务`)}},P=e=>{try{let n=t.urls.filter(t=>t!==e),r={...t.aliases??{}};delete r[e],A({urls:n,aliases:r,lastUsedUrl:t.lastUsedUrl===e?n[0]||``:t.lastUsedUrl}),_(null),w(null),v===e&&(y(null),x(``)),n.length===0&&s(!0),p(``),h(!1)}catch(e){w(null),p(e instanceof Error?e.message:`无法删除服务器地址`)}},ie=e=>{y(e),x(t.aliases?.[e]??``)},I=()=>{y(null),x(``)},L=e=>{let n=b.trim(),r={...t.aliases??{}};n?r[e]=n:delete r[e],A({...t,aliases:r}),I(),_(null)},R=C?t.aliases?.[C]?.trim()||C:``;if(r){let e=t.aliases?.[r]?.trim()||r;return(0,K.jsxs)(`main`,{className:`flex min-h-dvh flex-col items-center justify-center bg-background px-8 pb-[max(2rem,env(safe-area-inset-bottom))] pt-[max(2rem,env(safe-area-inset-top))] text-foreground`,role:`status`,"aria-live":`polite`,children:[(0,K.jsxs)(`div`,{className:`relative flex size-24 items-center justify-center`,"aria-hidden":`true`,children:[(0,K.jsx)(`span`,{className:`absolute inset-0 animate-ping rounded-full bg-primary/15`}),(0,K.jsx)(`span`,{className:`absolute inset-0 animate-ping rounded-full bg-primary/10 [animation-delay:0.45s]`}),(0,K.jsx)(`div`,{className:`relative flex size-14 items-center justify-center rounded-2xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(ee,{className:`size-6 text-foreground/75`})})]}),(0,K.jsx)(`p`,{className:`mt-9 text-sm font-medium text-foreground/85`,children:`正在建立连接…`}),(0,K.jsx)(`p`,{className:`mt-2 w-full max-w-xs truncate text-center font-mono text-xs text-muted-foreground`,children:e})]})}return(0,K.jsxs)(`main`,{className:`min-h-dvh bg-background px-5 pb-[max(2rem,env(safe-area-inset-bottom))] pt-[max(2rem,env(safe-area-inset-top))] text-foreground`,children:[(0,K.jsxs)(`div`,{className:`mx-auto w-full max-w-md`,children:[(0,K.jsxs)(`div`,{className:`mb-6 grid grid-cols-2 gap-1 rounded-xl bg-muted/40 p-1`,role:`tablist`,"aria-label":`连接方式`,children:[(0,K.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":T===`servers`,className:`flex items-center justify-center gap-1.5 rounded-lg py-2 text-sm font-medium transition-colors ${T===`servers`?`bg-background text-foreground shadow-sm`:`text-muted-foreground hover:text-foreground`}`,onClick:()=>D(`servers`),children:[(0,K.jsx)(ee,{className:`size-4`,"aria-hidden":`true`}),`服务器列表`]}),(0,K.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":T===`cloud`,className:`flex min-w-0 flex-col items-center justify-center gap-0.5 rounded-lg px-1.5 py-1.5 text-sm font-medium transition-colors ${T===`cloud`?`bg-background text-foreground shadow-sm`:`text-muted-foreground hover:text-foreground`}`,onClick:()=>D(`cloud`),children:[(0,K.jsxs)(`span`,{className:`flex items-center justify-center gap-1.5`,children:[(0,K.jsx)(xe,{className:`size-4`,"aria-hidden":`true`}),`云账户`]}),O.signedIn&&O.email?(0,K.jsx)(`span`,{className:`block w-full max-w-full truncate text-center text-xs leading-tight text-muted-foreground/80`,children:O.email}):null]})]}),T===`cloud`?(0,K.jsx)(Qf,{onSessionChange:k}):(0,K.jsxs)(`section`,{className:`mx-auto w-full max-w-md`,children:[(0,K.jsxs)(`header`,{className:`mb-8 flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(ee,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 pt-0.5`,children:[(0,K.jsx)(`h1`,{className:`text-lg font-semibold tracking-tight`,children:`连接 QuickForge`}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:`选择一台已保存的服务器,或添加新的 Tailscale 地址。`})]})]}),t.urls.length>0?(0,K.jsxs)(`section`,{"aria-labelledby":`quickforge-mobile-saved-servers`,children:[(0,K.jsxs)(`div`,{className:`mb-2.5 flex items-center justify-between px-1`,children:[(0,K.jsx)(`h2`,{id:`quickforge-mobile-saved-servers`,className:`text-xs font-medium text-muted-foreground`,children:`已保存的服务器`}),(0,K.jsxs)(`span`,{className:`text-xs text-muted-foreground/70`,children:[t.urls.length,` 台`]})]}),(0,K.jsx)(`div`,{className:`overflow-hidden rounded-2xl border border-border bg-background`,children:t.urls.map(e=>{let n=e===t.lastUsedUrl,r=t.aliases?.[e]?.trim(),i=g===e,a=v===e;return(0,K.jsxs)(`div`,{className:`border-b border-border last:border-b-0`,children:[(0,K.jsxs)(`div`,{className:`flex min-h-[68px] items-stretch gap-1 p-1.5`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex min-w-0 flex-1 items-center gap-3 rounded-xl px-2.5 py-2 text-left transition-colors hover:bg-muted/45 active:bg-muted/65`,onClick:()=>N(e),title:`连接 ${r||e}`,children:[(0,K.jsx)(`span`,{className:`flex size-9 shrink-0 items-center justify-center rounded-xl bg-muted/45 text-muted-foreground`,children:(0,K.jsx)(ee,{className:`size-4`,"aria-hidden":`true`})}),(0,K.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`span`,{className:`truncate text-sm font-medium text-foreground`,children:r||`QuickForge 服务器`}),n?(0,K.jsx)(`span`,{className:`shrink-0 rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground`,children:`上次使用`}):null]}),(0,K.jsx)(`span`,{className:`mt-1 block truncate font-mono text-xs text-muted-foreground`,children:e})]}),(0,K.jsx)(F,{className:`size-4 shrink-0 text-muted-foreground/65`,"aria-hidden":`true`})]}),(0,K.jsx)(`button`,{type:`button`,className:`inline-flex w-10 shrink-0 items-center justify-center rounded-xl text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65`,onClick:()=>{_(i?null:e),i&&I()},"aria-label":`管理 ${r||e}`,title:`管理服务器`,"aria-expanded":i,children:i?(0,K.jsx)(z,{className:`size-4`,"aria-hidden":`true`}):(0,K.jsx)(oe,{className:`size-5`,"aria-hidden":`true`})})]}),i?(0,K.jsx)(`div`,{className:`border-t border-border bg-muted/30 px-3 py-3`,children:a?(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-xs font-medium text-muted-foreground`,htmlFor:`quickforge-mobile-alias-${e}`,children:`服务器别名`}),(0,K.jsx)(`input`,{id:`quickforge-mobile-alias-${e}`,autoFocus:!0,autoCapitalize:`none`,autoCorrect:`off`,spellCheck:!1,value:b,onChange:e=>x(e.target.value),onKeyDown:t=>{t.key===`Enter`&&L(e),t.key===`Escape`&&I()},placeholder:`例如:公司开发机`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsxs)(`div`,{className:`mt-2.5 flex justify-end gap-2`,children:[(0,K.jsx)(`button`,{type:`button`,className:`inline-flex h-9 items-center justify-center rounded-xl px-3 text-sm text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground`,onClick:I,children:`取消`}),(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-9 items-center justify-center gap-1.5 rounded-xl bg-primary px-3.5 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85`,onClick:()=>L(e),children:[(0,K.jsx)(S,{className:`size-4`,"aria-hidden":`true`}),`保存`]})]})]}):(0,K.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-10 items-center justify-center gap-2 rounded-xl text-sm text-foreground/80 transition-colors hover:bg-muted/60`,onClick:()=>ie(e),children:[(0,K.jsx)(ae,{className:`size-4 text-muted-foreground`,"aria-hidden":`true`}),`编辑别名`]}),(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-10 items-center justify-center gap-2 rounded-xl text-sm text-foreground/80 transition-colors hover:bg-destructive/10 hover:text-destructive`,onClick:()=>w(e),children:[(0,K.jsx)(me,{className:`size-4 text-muted-foreground`,"aria-hidden":`true`}),`删除服务器`]})]})}):null]},e)})}),a?null:(0,K.jsxs)(`button`,{type:`button`,className:`mt-3 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 active:bg-muted/65`,onClick:ne,children:[(0,K.jsx)(o,{className:`size-4`,"aria-hidden":`true`}),`添加服务器`]}),m&&!a?(0,K.jsxs)(`p`,{className:`mt-2 flex items-center justify-center gap-1.5 text-sm text-muted-foreground`,role:`status`,children:[(0,K.jsx)(S,{className:`size-4`,"aria-hidden":`true`}),`服务器已保存`]}):null]}):null,a?(0,K.jsxs)(`section`,{className:t.urls.length>0?`mt-7`:``,"aria-labelledby":`quickforge-mobile-add-server`,children:[(0,K.jsxs)(`div`,{className:`mb-2.5 flex items-center justify-between px-1`,children:[(0,K.jsx)(`h2`,{id:`quickforge-mobile-add-server`,className:`text-xs font-medium text-muted-foreground`,children:t.urls.length>0?`添加服务器`:`添加第一台服务器`}),t.urls.length>0?(0,K.jsx)(`button`,{type:`button`,className:`rounded-lg px-2 py-1 text-xs text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground`,onClick:()=>{j(),s(!1)},children:`收起`}):null]}),(0,K.jsxs)(`form`,{className:`rounded-2xl border border-border bg-background p-5 shadow-quickforge`,onSubmit:M,children:[(0,K.jsxs)(`div`,{className:`mb-5 flex gap-2.5 rounded-xl bg-muted/30 px-3 py-2.5 text-xs leading-5 text-muted-foreground`,children:[(0,K.jsx)(ue,{className:`mt-0.5 size-4 shrink-0`,"aria-hidden":`true`}),(0,K.jsxs)(`p`,{children:[`仅支持 Tailnet 内的 `,(0,K.jsx)(`span`,{className:`font-mono text-foreground/75`,children:`.ts.net`}),` 或 `,(0,K.jsx)(`span`,{className:`font-mono text-foreground/75`,children:`100.64.0.0/10`}),` 地址,未填写端口时默认使用 5176。`]})]}),(0,K.jsx)(`label`,{className:`block text-sm font-medium`,htmlFor:`quickforge-mobile-server`,children:`服务器地址`}),(0,K.jsx)(`input`,{id:`quickforge-mobile-server`,autoCapitalize:`none`,autoCorrect:`off`,inputMode:`url`,spellCheck:!1,value:c,onChange:e=>{l(e.target.value),p(``),h(!1)},placeholder:`devbox.example.ts.net`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),te?(0,K.jsxs)(`p`,{className:`mt-2 break-all text-xs text-muted-foreground`,children:[`将连接到 `,(0,K.jsx)(`span`,{className:`font-mono text-foreground/70`,children:te})]}):(0,K.jsx)(`p`,{className:`mt-2 text-xs text-muted-foreground`,children:`请确保手机与服务器已登录同一个 Tailnet。`}),(0,K.jsxs)(`label`,{className:`mt-5 block text-sm font-medium`,htmlFor:`quickforge-mobile-server-alias`,children:[`服务器别名 `,(0,K.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`(可选)`})]}),(0,K.jsx)(`input`,{id:`quickforge-mobile-server-alias`,autoCapitalize:`none`,autoCorrect:`off`,spellCheck:!1,value:u,onChange:e=>{d(e.target.value),p(``),h(!1)},placeholder:`例如:公司开发机`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),f?(0,K.jsx)(`p`,{className:`mt-3 text-sm text-destructive`,role:`alert`,children:f}):null,(0,K.jsxs)(`button`,{type:`submit`,className:`mt-5 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85`,children:[`保存并连接`,(0,K.jsx)(E,{className:`size-4`,"aria-hidden":`true`})]}),(0,K.jsx)(`button`,{type:`button`,className:`mt-2 inline-flex h-10 w-full items-center justify-center rounded-xl text-sm text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65`,onClick:()=>re(!1),children:`仅保存,稍后连接`})]})]}):null]})]}),C?(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-end justify-center bg-black/35 p-4 pb-[max(1rem,env(safe-area-inset-bottom))] sm:items-center`,role:`presentation`,children:(0,K.jsxs)(`section`,{className:`w-full max-w-sm rounded-2xl border border-border bg-background p-5 shadow-xl`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`quickforge-mobile-delete-title`,children:[(0,K.jsx)(`h2`,{id:`quickforge-mobile-delete-title`,className:`text-base font-semibold`,children:`删除这台服务器?`}),(0,K.jsxs)(`p`,{className:`mt-2 break-all text-sm leading-6 text-muted-foreground`,children:[`“`,R,`”将从已保存列表中移除,之后仍可重新添加。`]}),(0,K.jsxs)(`div`,{className:`mt-5 grid grid-cols-2 gap-3`,children:[(0,K.jsx)(`button`,{type:`button`,className:`inline-flex h-11 items-center justify-center rounded-xl border border-border text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45`,onClick:()=>w(null),children:`取消`}),(0,K.jsx)(`button`,{type:`button`,className:`inline-flex h-11 items-center justify-center rounded-xl bg-destructive text-sm font-medium text-destructive-foreground transition-opacity hover:opacity-92 active:opacity-85`,onClick:()=>P(C),children:`删除`})]})]})}):null]})}var tp=`https://localhost/?connect=1&tab=cloud`,np=`http://127.0.0.1:18080/`;async function rp(){for(let e=0;e<3;e++){let t=new AbortController,n=window.setTimeout(()=>t.abort(),3e3);try{return await fetch(np,{mode:`no-cors`,cache:`no-store`,signal:t.signal}),window.clearTimeout(n),!0}catch{window.clearTimeout(n),e<2&&await new Promise(e=>setTimeout(e,700))}}return!1}function ip(){let[e,t]=(0,H.useState)(!1),[n,i]=(0,H.useState)(null),[a,o]=(0,H.useState)(!1),[s,c]=(0,H.useState)(0),[l,u]=(0,H.useState)(!1),d=(0,H.useRef)(!1),f=(0,H.useRef)(0),p=(0,H.useCallback)(async()=>{(await Wu({probe:rp})).status===`recovered`&&(d.current=!1,o(!1),i(null))},[]);if((0,H.useEffect)(()=>{let e=!0,n,r=()=>{d.current||(d.current=!0,o(!0))},a=t=>{e&&(i(t),t.state!==`connected`&&r(),t.state===`reconnecting`&&(f.current+=1,c(f.current)),t.state===`connected`&&d.current&&p())};return Gf.getState().then(t=>{if(e)return a(t),Gf.addListener(`remoteStateChanged`,a).then(e=>{n=e})}).catch(()=>{e&&t(!0)}),()=>{e=!1,n?.remove()}},[p]),(0,H.useEffect)(()=>{let e=()=>{document.visibilityState===`visible`&&d.current&&Gf.getState().then(e=>{e.state===`connected`&&d.current&&p()}).catch(()=>{})};return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[p]),!Gt()||e||!n||n.state===`connected`&&!a)return null;let m=n.state===`reconnecting`||n.state===`connecting`,h=n.state===`connected`&&a,g=async()=>{u(!0);try{await Gf.retry()}catch{}finally{u(!1)}},_=()=>{window.location.href=tp},v=`连接已断开`,y=`不会自动重连,请返回设备列表。`;m?y=`连接已断开,正在自动重连…(已重试 ${s} 次)`:h?(v=`正在恢复连接`,y=`连接已恢复,正在同步任务状态…`):n.state===`error`&&(v=`连接失败`,y=n.error||`隧道连接失败,请重试`,y.includes(`登录已过期`)&&(y=`${y},请重新登录`));let b=`inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85 disabled:opacity-60`;return(0,K.jsx)(`div`,{className:`fixed inset-0 z-[90] flex items-center justify-center bg-background/80 p-6 backdrop-blur-sm`,children:(0,K.jsxs)(`div`,{className:`w-full max-w-sm rounded-2xl border border-border bg-background p-5 shadow-quickforge`,role:`status`,"aria-live":`polite`,children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:m?(0,K.jsx)(B,{className:`size-5 animate-spin text-foreground/75`,"aria-hidden":`true`}):(0,K.jsx)(N,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 pt-0.5`,children:[(0,K.jsx)(`h2`,{className:`text-base font-semibold tracking-tight`,children:v}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:y})]})]}),(0,K.jsxs)(`div`,{className:`mt-5 flex flex-col gap-2.5`,children:[m?(0,K.jsxs)(`button`,{type:`button`,className:b,onClick:()=>{g()},disabled:l,children:[l?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(r,{className:`size-4`,"aria-hidden":`true`}),`立即重试`]}):null,(0,K.jsx)(`button`,{type:`button`,className:m?`inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl border border-border text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65 disabled:opacity-60`:b,onClick:_,children:`返回设备列表`})]})]})})}var ap=`quickforge:system-notifications-enabled`,op=`quickforge:android-remote-notification-permission-requested:v1`,sp=`quickforge:system-notifications-recent:v1`,cp=`quickforge:open-session`,lp=1e4,up=100,dp=!1,fp=!1;function pp(){if(!(typeof window>`u`||!Me.isNativePlatform()))return window.QuickForgeBridge}function mp(){if(typeof window>`u`)return;let e=window;e.__quickforgeOpenSession||=e=>{yp(e)}}function hp(){let e=pp();if(!e?.setNotificationService)return;let t=window.location.origin;if(t)try{e.setNotificationService(Cp(),t)}catch(e){V.warn(`Failed to sync native notification service:`,e)}}mp();function gp(){if(typeof document>`u`||typeof window>`u`)return!1;let e=window;return document.body?.classList.contains(`quickforge-desktop-app`)||e.__quickforgeDesktopApp===!0}function _p(){return Me.isNativePlatform()&&Me.isPluginAvailable(`LocalNotifications`)}function vp(e){return`${W(e===`idle`?`taskCompleted`:e===`error`?`taskError`:e===`aborted`?`processAborted`:`taskRunning`)}. ${W(`systemNotificationOpenDetails`)}`}function yp(e){typeof window>`u`||(window.focus(),e&&window.dispatchEvent(new CustomEvent(`quickforge:open-session-from-settings`,{detail:{sessionId:e}})))}function bp(e){let t=0;for(let n=0;n<e.length;n+=1)t=(t<<5)-t+e.charCodeAt(n)|0;return(t>>>0)%2147483646+1}function xp(){if(typeof localStorage>`u`)return{};try{let e=JSON.parse(localStorage.getItem(sp)||`{}`);return!e||typeof e!=`object`||Array.isArray(e)?{}:Object.fromEntries(Object.entries(e).filter(e=>typeof e[1]==`number`&&Number.isFinite(e[1])))}catch{return{}}}function Sp(e){if(typeof localStorage>`u`)return!0;let t=Date.now(),n=xp(),r=n[e];if(typeof r==`number`&&t-r<lp)return!1;let i=Object.entries({...n,[e]:t}).filter(([,e])=>t-e<lp).sort((e,t)=>t[1]-e[1]).slice(0,up);try{localStorage.setItem(sp,JSON.stringify(Object.fromEntries(i)))}catch{}return!0}function Cp(){if(typeof localStorage>`u`)return!1;try{return localStorage.getItem(ap)===`1`}catch{return!1}}function wp(e){if(!(typeof localStorage>`u`)){try{e?localStorage.setItem(ap,`1`):localStorage.removeItem(ap)}catch{}hp()}}function Tp(){if(!(typeof window>`u`||typeof navigator>`u`)&&!(Me.isNativePlatform()||!/Android/i.test(navigator.userAgent))&&!(!Gt()||!window.isSecureContext)&&!(typeof Notification>`u`||!navigator.serviceWorker)&&!(Notification.permission!==`default`||typeof localStorage>`u`)){try{if(localStorage.getItem(op))return;localStorage.setItem(op,`1`)}catch{return}Dp()}}async function Ep(){try{if(_p()){let{LocalNotifications:e}=await Xe(async()=>{let{LocalNotifications:e}=await import(`./esm-sdsK6gaB.js`);return{LocalNotifications:e}},__vite__mapDeps([0,1,2,3])),t=await e.checkPermissions();return t.display===`granted`?`granted`:t.display===`prompt`||t.display===`prompt-with-rationale`?`prompt`:`denied`}return gp()||typeof Notification>`u`?`unsupported`:Notification.permission===`granted`?`granted`:Notification.permission===`denied`?`denied`:`prompt`}catch(e){return V.warn(`Failed to check system notification permission:`,e),`unsupported`}}async function Dp(){try{let e;if(_p()){let{LocalNotifications:t}=await Xe(async()=>{let{LocalNotifications:e}=await import(`./esm-sdsK6gaB.js`);return{LocalNotifications:e}},__vite__mapDeps([0,1,2,3]));e=(await t.requestPermissions()).display===`granted`?`granted`:`denied`,await Op()}else if(!gp()&&typeof Notification<`u`){let t=await Notification.requestPermission();e=t===`granted`?`granted`:t===`denied`?`denied`:`prompt`}else e=`unsupported`;return wp(e===`granted`),e}catch(e){return V.warn(`Failed to request system notification permission:`,e),wp(!1),`denied`}}async function Op(){if(hp(),!fp&&typeof navigator<`u`&&navigator.serviceWorker&&(fp=!0,navigator.serviceWorker.addEventListener(`message`,e=>{let t=e.data;t?.type===cp&&yp(typeof t.sessionId==`string`?t.sessionId:void 0)})),!(!_p()||dp)){dp=!0;try{let{LocalNotifications:e}=await Xe(async()=>{let{LocalNotifications:e}=await import(`./esm-sdsK6gaB.js`);return{LocalNotifications:e}},__vite__mapDeps([0,1,2,3]));await e.addListener(`localNotificationActionPerformed`,e=>{let t=e.notification.extra?.sessionId;yp(typeof t==`string`?t:void 0)})}catch(e){dp=!1,V.warn(`Failed to initialize native notification listener:`,e)}}}async function kp(e){if(!Cp()||!e.force&&e.status===`running`&&typeof document<`u`&&document.visibilityState===`visible`&&document.hasFocus())return!1;try{if(await Ep()!==`granted`||!Sp(e.key))return!1;let t=vp(e.status);if(_p()){let{LocalNotifications:n}=await Xe(async()=>{let{LocalNotifications:e}=await import(`./esm-sdsK6gaB.js`);return{LocalNotifications:e}},__vite__mapDeps([0,1,2,3]));return await Op(),await n.schedule({notifications:[{id:bp(e.key),title:e.title,body:t,extra:{sessionId:e.sessionId}}]}),!0}if(typeof Notification>`u`)return!1;let n=typeof navigator<`u`&&/Android/i.test(navigator.userAgent);if(typeof navigator<`u`&&navigator.serviceWorker)try{let n=await navigator.serviceWorker.getRegistration();if(n?.showNotification)return await n.showNotification(e.title,{body:t,icon:`/pwa-icon-192.png`,tag:e.key,data:{sessionId:e.sessionId}}),!0}catch(e){V.warn(`Failed to show Service Worker notification:`,e)}if(n)return!1;let r=new Notification(e.title,{body:t,icon:`/pwa-icon-192.png`,tag:e.key});return r.onclick=()=>{r.close(),yp(e.sessionId)},!0}catch(e){return V.warn(`Failed to show system notification:`,e),!1}}var Ap=Object.freeze({modelSelection:!0,thinkingSelection:!0,clientApiKeyCheck:!0,planMode:!0,accessMode:!0,commands:!0,capabilitySuggestions:!0,contextUsage:!0,compaction:!0,rollback:!0,retry:!0,forkFromMessage:!0,forkSession:!1,harnessConfig:!1,attachments:!0}),jp=Object.freeze({modelSelection:!1,thinkingSelection:!1,clientApiKeyCheck:!1,planMode:!1,accessMode:!1,commands:!1,capabilitySuggestions:!1,contextUsage:!1,compaction:!1,rollback:!1,retry:!1,forkFromMessage:!1,forkSession:!0,harnessConfig:!0,attachments:!0});function Mp(e){return e===`opencode`?jp:Ap}function Np(e,t){return!t.readOnly&&!t.disableFork?e:{...e,rollback:e.rollback&&!t.readOnly,retry:e.retry&&!t.readOnly,forkFromMessage:e.forkFromMessage&&!t.readOnly&&!t.disableFork,forkSession:e.forkSession&&!t.readOnly&&!t.disableFork,harnessConfig:e.harnessConfig&&!t.readOnly,attachments:e.attachments&&!t.readOnly,planMode:e.planMode&&!t.readOnly,accessMode:e.accessMode&&!t.readOnly,commands:e.commands&&!t.readOnly,capabilitySuggestions:e.capabilitySuggestions&&!t.readOnly}}function Pp(e,t,n){let r=String(t??``).trim().length>0,i=(n?.length??0)>0;return!e.attachments&&i?!1:r||i}var Fp=(0,H.lazy)(()=>Xe(()=>import(`./ChatPanelHost-D3987TUJ.js`).then(e=>({default:e.ChatPanelHost})),__vite__mapDeps([4,2,5,1,6,7,8,9,10,11,12]))),Ip=(0,H.lazy)(()=>Xe(()=>import(`./SharedConversationPage-B9BUVCri.js`).then(e=>({default:e.SharedConversationPage})),__vite__mapDeps([13,2,1,5,6,7,8,4,9,10,11,12,14]))),Lp=(0,H.lazy)(()=>Xe(()=>import(`./WorkspaceInspector-BnfDLf9a.js`).then(e=>({default:e.WorkspaceInspector})),__vite__mapDeps([15,2,16,7,8,17,18,19,12,1]))),Rp=(0,H.lazy)(()=>Xe(()=>import(`./TerminalDock-CT1nYo7P.js`).then(e=>({default:e.TerminalDock})),__vite__mapDeps([17,2,18,19,7,8]))),zp=(0,H.lazy)(()=>Xe(()=>import(`./SettingsWorkspacePage-DSy66Tuw.js`).then(e=>({default:e.SettingsWorkspacePage})),__vite__mapDeps([20,2,1,5,6,7,8,10,11]))),Bp=`quickforge:auto-preview-seen-signatures`,Vp=200,Hp=`https://github.com/shawnstack/quickforge/releases/latest`,Up=1350,Wp=280,Gp=280;function Kp(){if(typeof window>`u`)return new Set;try{let e=window.sessionStorage.getItem(Bp),t=e?JSON.parse(e):void 0;return Array.isArray(t)?new Set(t.filter(e=>typeof e==`string`&&e.length>0)):new Set}catch{return new Set}}function qp(e){return Kp().has(e)}function Jp(e){if(!(typeof window>`u`))try{let t=[...Kp(),e].slice(-Vp);window.sessionStorage.setItem(Bp,JSON.stringify(t))}catch{}}function Yp(){return(0,K.jsx)(`div`,{className:`flex min-h-0 flex-1 items-center justify-center text-sm text-muted-foreground`,children:W(`loading`)})}function Xp(){return null}function Zp({exiting:e=!1}){let t=W(`loadingChatWorkspace`);return(0,K.jsxs)(`div`,{className:G(`quickforge-startup-splash`,e&&`quickforge-startup-splash-exit`),role:`status`,"aria-label":t,children:[(0,K.jsxs)(`svg`,{className:`quickforge-startup-splash-icon`,viewBox:`0 0 64 64`,fill:`none`,"aria-hidden":`true`,children:[(0,K.jsxs)(`defs`,{children:[(0,K.jsxs)(`linearGradient`,{id:`startupIconStroke`,x1:`0`,y1:`0`,x2:`1`,y2:`1`,children:[(0,K.jsx)(`stop`,{offset:`0`,stopColor:`#9ca3af`}),(0,K.jsx)(`stop`,{offset:`1`,stopColor:`#4b5563`})]}),(0,K.jsxs)(`linearGradient`,{id:`startupIconBolt`,x1:`0`,y1:`0`,x2:`1`,y2:`1`,children:[(0,K.jsx)(`stop`,{offset:`0`,stopColor:`#374151`}),(0,K.jsx)(`stop`,{offset:`1`,stopColor:`#0f172a`})]})]}),(0,K.jsx)(`polygon`,{className:`quickforge-startup-splash-outline`,points:`32,6 52.78,18 52.78,42 32,54 11.22,42 11.22,18`,fill:`none`,stroke:`url(#startupIconStroke)`,strokeWidth:`4.5`,strokeLinejoin:`round`}),(0,K.jsx)(`polygon`,{className:`quickforge-startup-splash-outline-final`,points:`32,6 52.78,18 52.78,42 32,54 11.22,42 11.22,18`,fill:`none`,stroke:`url(#startupIconStroke)`,strokeWidth:`4.5`,strokeLinejoin:`round`}),(0,K.jsx)(`path`,{className:`quickforge-startup-splash-bolt`,d:`M37.2 13 L22 34 L30.6 34 L26.8 50 L42.8 26 L33.8 26 Z`,fill:`url(#startupIconBolt)`}),(0,K.jsx)(`path`,{className:`quickforge-startup-splash-bolt-trace`,d:`M37.2 13 L22 34 L30.6 34 L26.8 50 L42.8 26 L33.8 26 Z`,fill:`none`,stroke:`#f8fafc`,strokeWidth:`2.5`,strokeLinecap:`round`,strokeLinejoin:`round`}),(0,K.jsx)(`path`,{className:`quickforge-startup-splash-bolt-highlight`,d:`M37.2 13 L22 34 L30.6 34 L33.8 26 Z`,fill:`#e5e7eb`})]}),(0,K.jsx)(`span`,{className:`sr-only`,children:t})]})}function Qp({exiting:e=!1}){let t=W(`loadingConversation`);return(0,K.jsxs)(`div`,{className:G(`quickforge-conversation-loading`,e&&`quickforge-conversation-loading-exit`),role:`status`,"aria-live":`polite`,"aria-label":t,children:[(0,K.jsxs)(`div`,{className:`quickforge-conversation-loading-status`,"aria-hidden":`true`,children:[(0,K.jsx)(`span`,{children:t}),(0,K.jsxs)(`span`,{className:`quickforge-conversation-loading-dots`,children:[(0,K.jsx)(`span`,{children:`•`}),(0,K.jsx)(`span`,{children:`•`}),(0,K.jsx)(`span`,{children:`•`})]})]}),(0,K.jsx)(`div`,{className:`quickforge-conversation-loading-track`,"aria-hidden":`true`,children:(0,K.jsx)(`div`,{className:`quickforge-conversation-loading-runner`})}),(0,K.jsx)(`span`,{className:`quickforge-conversation-loading-helper`,"aria-hidden":`true`,children:W(`loadingConversationPreparing`)})]})}function $p(e){return e===`idle`||e===`running`||e===`error`||e===`aborted`}function em(e){return e.type===`scheduled_task_notification`}function tm(e){return e.type===`scheduled_task_started`}function nm(e){return e.workspace?.kind===`project`&&typeof e.workspace.id==`string`&&e.workspace.id.length>0?e.workspace.id:typeof e.projectId==`string`&&e.projectId.length>0?e.projectId:void 0}function rm(){let e=Gt(),t=Kt(),n=Wt(),i=Ou(!0),o=n?window.location.origin:void 0,s=n?Ht():void 0,c=()=>qt(t?`cloud`:`servers`),l=(0,H.useRef)(null),f=(0,H.useRef)(Yn(Hn)),p=(0,H.useRef)(`default`),m=(0,H.useRef)(void 0),h=(0,H.useRef)(void 0),{activeProject:g,projects:_,defaultWorkspace:v,expandedProjectIds:x,selectingProject:S,projectPickerOpen:w,loadProject:T,switchActiveProject:E,handleSelectProjectPath:O,selectProjectDirectory:k,setProjectPickerOpen:ee,toggleProjectExpanded:te,toggleAllProjectsExpanded:j,reorderProjects:ne,setActiveProject:re,setProjects:M,setExpandedProjectIds:N}=rc(),{agentAccessMode:P,setAgentAccessMode:F,initialize:I}=ic(),L=Ru(),{setArtifactPreviewOpen:z,setWorkspaceInspectorOpen:se,setWorkspaceInspectorRequest:ce}=L,[le,ue]=(0,H.useState)(!1),[B,de]=(0,H.useState)(),[fe,me]=(0,H.useState)(!1),[he,ge]=(0,H.useState)(null),[ve,ye]=(0,H.useState)(!1),[be,xe]=(0,H.useState)(!1),[Se,we]=(0,H.useState)({artifacts:[]}),[Te,Ee]=(0,H.useState)(nd),[De,Oe]=(0,H.useState)(id),[ke,Ae]=(0,H.useState)(!1),je=(0,H.useRef)(!1),Me=(0,H.useRef)(``),[Ne,Pe]=(0,H.useState)(),[Fe,Ie]=(0,H.useState)(),Le=(0,H.useRef)(0),Re=(0,H.useRef)(void 0),[ze,Be]=(0,H.useState)(!1),[Ve,He]=(0,H.useState)(!1),[Ue,We]=(0,H.useState)(!1),[Ge,Ke]=(0,H.useState)(!1),[qe,Je]=(0,H.useState)(()=>new Set),Ye=(0,H.useRef)(0),Xe=(0,H.useRef)(0),Ze=(0,H.useRef)(0),Qe=(0,H.useRef)(0),$e=(0,H.useRef)(void 0),tt=(0,H.useRef)(void 0),[nt,rt]=(0,H.useState)(null),[it,at]=(0,H.useState)(!1),[ot,st]=(0,H.useState)(!1),[ct,lt]=(0,H.useState)(),ut=(0,H.useRef)(void 0),[dt,ft]=(0,H.useState)(),{toasts:pt,handleTaskComplete:mt,addToast:U,dismissToast:ht}=ll(),gt=(0,H.useCallback)((e,t,n)=>{mt(e,t,n),kp({key:`agent:${e}:${n}`,sessionId:e,title:t,status:n})},[mt]),_t=(0,H.useCallback)(()=>void 0,[]),vt=(0,H.useCallback)(()=>me(!1),[]),yt=(0,H.useCallback)(()=>{me(!1),window.open(Hp,`_blank`,`noopener,noreferrer`)},[]),bt=(0,H.useCallback)(()=>{me(!1),window.open(`quickforge://exit`,`_blank`,`noopener,noreferrer`)},[]);(0,H.useEffect)(()=>{rd(Te)},[Te]),(0,H.useEffect)(()=>{ad(De)},[De]);let xt=(0,H.useRef)(null),St=(0,H.useRef)(null),Ct=(0,H.useRef)(null),{allLoadedSessions:wt,pinnedSessions:Tt,pinnedHasMore:Et,pinnedLoading:Dt,globalSessions:Ot,sessionsForProject:kt,globalHasMore:At,projectTimelineSessions:jt,projectTimelineHasMore:Mt,projectTimelineLoading:Nt,projectHasMore:Pt,globalLoading:Ft,projectLoading:It,projectLoaded:Lt,loadGlobalSessions:Rt,loadProjectSessions:zt,refreshSessions:Bt,upsertSessionMetadata:Vt,updateSessionTitle:Ut,loadMorePinned:Jt,loadMoreGlobal:Xt,loadMoreProject:Qt,loadMoreProjectTimeline:$t}=cl({backendRef:Ct,expandedProjectIds:x,externalProjectIds:qe,viewMode:Te,sortMode:De,onBroadcastSessionsChanged:(0,H.useCallback)(()=>xt.current?.notifySessionsChanged(),[])}),en=dc({onSessionsChanged:()=>{Bt()},onProjectsChanged:()=>{T(!0)},onSettingsChanged:e=>{Bt(),e?.defaultHarness&&St.current?.(e.defaultHarness).catch(e=>{V.error(`Failed to apply the cross-tab default Harness change:`,e)})}});(0,H.useEffect)(()=>{p.current=P},[P]),(0,H.useEffect)(()=>{m.current=g},[g]),(0,H.useEffect)(()=>{h.current=v},[v]),(0,H.useEffect)(()=>{xt.current=en},[en]),(0,H.useEffect)(()=>{Op()},[]),(0,H.useEffect)(()=>{let e=window.setTimeout(()=>at(!0),Up);return()=>window.clearTimeout(e)},[]);let tn=(0,H.useCallback)((e,t)=>{Pe(n=>n?.sessionId===e&&Fr(n,t)?n:{sessionId:e,...t})},[]),J=el({storageRef:l,activeModelRef:f,agentAccessModeRef:p,activeProjectRef:m,defaultWorkspaceRef:h,setAgentAccessMode:F,switchActiveProject:E,sessions:wt,refreshSessions:Bt,updateSessionTitle:Ut,loadCloudModels:i.loadCloudModels,onTaskComplete:gt});(0,H.useEffect)(()=>{let e=J.loadingSessionId;if(!e||ut.current===e)return;let t=window.setTimeout(()=>{ut.current!==e&&($e.current?.(),$e.current=void 0,Qe.current+=1,ft(void 0),ut.current=e,lt(e))},0);return()=>window.clearTimeout(t)},[J.loadingSessionId]),(0,H.useEffect)(()=>{let e=ut.current;if(!e||dt!==e)return;let t=window.setTimeout(()=>{ut.current===e&&(ut.current=void 0,lt(void 0))},Gp);return()=>window.clearTimeout(t)},[J.loadingSessionId,dt,ct]);let{createAgent:rn,startDeferredSession:an,applyDefaultHarnessToBlankSession:on,loadSession:sn,syncSessionUI:cn,setCurrentAgentMessages:ln,updateCurrentAgentModel:un,setChatPanelRevision:dn,setCurrentTitleRef:fn,agentRef:Y,taskMapRef:pn,currentSessionIdRef:mn,currentChatScopeRef:hn}=J;(0,H.useEffect)(()=>{St.current=on},[on]),(0,H.useEffect)(()=>{Re.current=J.currentToolProject?.id,Le.current+=1,Ze.current+=1},[J.currentToolProject?.id]);let gn=(0,H.useCallback)(e=>{if(!e||e===mn.current)return;$e.current?.(),$e.current=void 0;let t=Qe.current+1;return Qe.current=t,ft(void 0),ut.current=e,lt(e),t},[mn]),_n=(0,H.useCallback)((e,t)=>{t!==void 0&&Qe.current!==t||ut.current===e&&($e.current?.(),$e.current=void 0,Qe.current+=1,ut.current=void 0,ft(void 0),lt(void 0))},[]),vn=(0,H.useCallback)(e=>{ut.current===e&&($e.current=void 0,ft(e))},[]),yn=(0,H.useCallback)((e,t)=>{V.error(`Failed to render conversation:`,t),_n(e),U({sessionId:e,title:W(`conversationLoadFailed`),status:`error`})},[U,_n]),bn=(0,H.useCallback)((e,t)=>{let n=gn(e);if(n===void 0){$e.current?.(),$e.current=void 0,Qe.current+=1,t();return}$e.current=Vu(()=>{$e.current=void 0,!(Qe.current!==n||ut.current!==e)&&t().then(t=>{t||_n(e,n)})})},[gn,_n]);(0,H.useEffect)(()=>()=>{$e.current?.()},[]);let xn=(0,H.useCallback)(e=>{e&&bn(e,()=>sn(e))},[sn,bn]);(0,H.useEffect)(()=>{let e=e=>{let t=e.detail;typeof t?.sessionId==`string`&&xn(t.sessionId)};return window.addEventListener(`quickforge:open-session-from-settings`,e),()=>window.removeEventListener(`quickforge:open-session-from-settings`,e)},[xn]);let Sn=(0,H.useCallback)(e=>{de(t=>t?.id===e?void 0:t)},[]),X=(0,H.useCallback)(e=>{Xe.current+=1,ce({...e,id:Xe.current}),se(!0)},[se,ce]),Cn=(0,H.useCallback)(e=>{ce(t=>t?.id===e?void 0:t)},[ce]),wn=(0,H.useCallback)(()=>{let e=J.currentToolProject?.id;e&&(z(!1),X({projectId:e,kind:`review`,view:`changes`}))},[J.currentToolProject?.id,X,z]),Tn=(0,H.useCallback)(async()=>{let e=J.currentToolProject?.id,t=Le.current+1;if(Le.current=t,!e){Ie(void 0);return}try{let n=await bd(e);return sd({projectId:e,requestId:t},Re.current,Le.current)?(Ie(n),n):void 0}catch(n){if(!sd({projectId:e,requestId:t},Re.current,Le.current))return;V.warn(`Failed to refresh title git status:`,n),Ie(void 0);return}},[J.currentToolProject?.id]);(0,H.useEffect)(()=>{let e=window.setTimeout(()=>{Tn()},0);return()=>window.clearTimeout(e)},[Tn]),(0,H.useEffect)(()=>{let e,t=jc(t=>{ld(t,mn.current,Re.current)&&(e!==void 0&&window.clearTimeout(e),e=window.setTimeout(()=>{e=void 0,Tn()},400))});return()=>{e!==void 0&&window.clearTimeout(e),t()}},[J.currentSessionId,mn,Tn]);let En=(0,H.useCallback)(async e=>{let t=J.currentToolProject?.id;if(!t)return;let n=Le.current+1;Le.current=n;try{let r=await kd(t,e);if(!sd({projectId:t,requestId:n},Re.current,Le.current))return;Ie(r),Be(!1),U({sessionId:J.currentSessionId??``,title:W(`gitBranchSwitched`),status:`idle`,message:e})}catch(e){if(!sd({projectId:t,requestId:n},Re.current,Le.current))return;throw V.error(`Failed to checkout git branch:`,e),$(e instanceof Error?e.message:W(`gitCheckoutFailed`)),e}},[U,J.currentSessionId,J.currentToolProject?.id]),Dn=(0,H.useCallback)(e=>{Ie(e),Be(!1),U({sessionId:J.currentSessionId??``,title:W(`gitBranchCreated`),status:`idle`,message:e.branch??``})},[U,J.currentSessionId]),On=(0,H.useCallback)(e=>{Ie(e),U({sessionId:J.currentSessionId??``,title:W(`gitOperationCompleted`),status:`idle`,message:e.branch??``})},[U,J.currentSessionId]),kn=(0,H.useCallback)(async e=>{let t=J.currentToolProject?.id;if(!t){U({sessionId:J.currentSessionId??``,title:`无法打开文件`,status:`error`,message:`当前对话没有关联项目。`});return}let n=Ze.current+1;Ze.current=n;try{let r=await vd(t,e);if(!sd({projectId:t,requestId:n},Re.current,Ze.current))return;X({projectId:t,kind:`reader`,path:r.relativePath})}catch(e){if(!sd({projectId:t,requestId:n},Re.current,Ze.current))return;let r=e instanceof Error?e.message:`打开文件失败`;U({sessionId:J.currentSessionId??``,title:`无法打开文件`,status:`error`,message:r})}},[U,J.currentSessionId,J.currentToolProject?.id,X]),An=(0,H.useCallback)((e,t,n)=>{let r=J.currentToolProject,i=yf(t,n);if(!(!r||r.id!==e||!i)){if(z(!1),i===`reader`){X({projectId:e,kind:`reader`,path:t});return}X({projectId:e,kind:`browser`,url:bf(r.path,t)})}},[J.currentToolProject,X,z]);(0,H.useEffect)(()=>{let e=J.currentToolProject,t=e?.id;if(!t||Se.projectId!==t||Se.sessionId!==J.currentSessionId)return;let n=Tf(Se.artifacts);if(!n?.path)return;let r=n.toolCallIds[n.toolCallIds.length-1],i=`${t}:${n.path}:${n.defaultPreview?`default`:n.explicit?`explicit`:`inferred`}:${r??``}`;if(i!==Me.current){if(qp(i)){Me.current=i;return}Me.current=i,Jp(i),queueMicrotask(()=>{let r=yf(n.path,n.kind);r&&(z(!1),X(r===`reader`?{projectId:t,kind:`reader`,path:n.path}:{projectId:t,kind:`browser`,url:bf(e.path,n.path)}))})}},[J.currentSessionId,J.currentToolProject,Se,X,z]),(0,H.useEffect)(()=>{Me.current=``,z(!1),ce(void 0)},[J.currentToolProject?.id,z,ce]),(0,H.useEffect)(()=>{if(!An)return;let e=e=>{let t=e.detail,n=J.currentToolProject?.id;n&&t&&typeof t.path==`string`&&An(n,t.path,t.kind)};return window.addEventListener(`quickforge:preview-artifact`,e),()=>window.removeEventListener(`quickforge:preview-artifact`,e)},[J.currentToolProject?.id,An]),(0,H.useEffect)(()=>{let e=e=>{let t=e.detail;if(!t||typeof t.waitUntil!=`function`)return;let n=(async()=>{let e=new Set,t=Y.current;t instanceof Mc&&e.add(t);for(let t of pn.current.values())t.agent instanceof Mc&&e.add(t.agent);await Promise.all([...e].map(async e=>{try{let t=await fetch(`/api/agents/${encodeURIComponent(e.sessionId)}/state`,{cache:`no-store`});if(!t.ok)throw Error(`HTTP ${t.status}`);await e.syncState()}catch(e){throw V.error(`Tunnel recovery failed to sync agent state:`,e),e}})),await Bt({broadcast:!0})})();t.waitUntil(n)};return window.addEventListener(Hu,e),()=>window.removeEventListener(Hu,e)},[Y,pn,Bt]),(0,H.useEffect)(()=>jc(e=>{if(tm(e)){let t=typeof e.projectId==`string`?e.projectId:void 0;t&&(N(e=>{let n=new Set(e);return n.add(t),n}),zt(t,0)),Bt({broadcast:!0});return}if(e.type===`session_created`){let t=e.metadata;t?.id&&Vt(t)}else if(e.type===`title_updated`){let t=typeof e.sessionId==`string`?e.sessionId:void 0,n=typeof e.title==`string`?e.title:void 0;t&&n&&Ut(t,n)}else (e.type===`agent_end`||e.type===`session_forked`)&&Bt({broadcast:!0});if(!em(e))return;let t=typeof e.sessionId==`string`?e.sessionId:void 0,n=typeof e.title==`string`?e.title:W(`scheduledTasks`),r=$p(e.status)?e.status:`idle`,i=typeof e.message==`string`?e.message:void 0;U({sessionId:t??``,title:n,status:r,message:i});let a=typeof e.runId==`string`?e.runId:void 0;kp({key:a?`scheduled:${a}`:`scheduled:${t??n}:${r}`,sessionId:t,title:n,status:r})}),[U,zt,Bt,N,Ut,Vt]);let{ready:jn,startupError:Mn,retryBootstrap:Nn}=zl({storageRef:l,backendRef:Ct,activeModelRef:f,agentAccessModeRef:p,taskMapRef:pn,refreshSessions:Bt,loadProject:T,initAgentAccessMode:I,createAgent:rn,loadSession:sn,loadCloudModels:i.loadCloudModels,setNeedsModelSetup:ue,onStorageReady:rt}),Pn=Yl(l,jn),In=jn&&it&&!!(J.agent||le);(0,H.useEffect)(()=>{if(!In)return;let e=window.setTimeout(()=>st(!0),Wp);return()=>window.clearTimeout(e)},[In]),(0,H.useEffect)(()=>{if(!jn)return;let e=new EventSource(`/api/channels/events`),t=e=>{try{let t=JSON.parse(e.data);if(t.type!==`sessions-changed`||typeof t.sessionId!=`string`)return;let n=nm(t);n&&Je(e=>e.has(n)?e:new Set([...e,n])),t.metadata?.id===t.sessionId?Vt(t.metadata):n?zt(n,0):Rt(0);let r=Y.current;t.sessionId===mn.current&&r instanceof Mc&&r.syncState()}catch{}};return e.addEventListener(`sessions-changed`,t),()=>{e.removeEventListener(`sessions-changed`,t),e.close()}},[Y,mn,Rt,zt,jn,Vt]),(0,H.useEffect)(()=>{if(jn)for(let e of x)!Lt(e)&&!It(e)&&zt(e,0)},[jn,x,Lt,It,zt]);let{startNewGlobalChat:Ln,startNewProjectChat:Rn,rollbackFromMessage:zn,retryFromMessage:Bn,copyAnswer:Vn,forkFromMessage:Un,forkCurrentSession:Wn}=Au({storageRef:l,activeModelRef:f,activeProjectRef:m,currentChatScopeRef:hn,currentSessionIdRef:mn,taskMapRef:pn,agentRef:Y,createAgent:rn,startDeferredSession:an,syncSessionUI:cn,setCurrentAgentMessages:ln,setChatPanelRevision:dn,refreshSessions:Bt,needsModelSetup:le,setNeedsModelSetup:ue,switchActiveProject:E,closeWorkspacePage:_t,setRestoredDraft:de}),{deleteProjectInline:Gn}=ju({activeProjectRef:m,refreshSessions:Bt,notifyProjectsChanged:en.notifyProjectsChanged,setActiveProject:re,setProjects:M,setExpandedProjectIds:N,setChatPanelRevision:dn});(0,H.useEffect)(()=>{let e=od({ready:jn,currentToolProjectId:J.currentToolProject?.id,projects:_,activeProject:g,recoveringProjectId:tt.current});if(e.type===`none`){let e=J.currentToolProject?.id;tt.current&&tt.current!==e&&(tt.current=void 0);return}tt.current=e.deletedProjectId,we({artifacts:[]}),ce(void 0),z(!1),ge(null),ye(!1),Ze.current+=1,an(e.type===`project`?{scope:`project`,project:e.project}:{scope:`global`}).catch(e=>{tt.current=void 0,V.error(`Failed to recover after the current project was deleted:`,e)})},[g,J.currentToolProject?.id,_,jn,z,ce,an]);let{setAccessMode:Kn}=Lu({storageRef:l,agentAccessModeRef:p,setAgentAccessMode:F,agentRef:Y,setChatPanelRevision:dn,notifySettingsChanged:en.notifySettingsChanged}),qn=(0,H.useCallback)(async e=>{let t=Y.current;if(!t)throw Error(W(`toolApprovalFailed`));try{await t.approveToolCall(e)}catch(e){throw V.error(`Failed to approve tool call:`,e),e instanceof Error?e:Error(W(`toolApprovalFailed`))}},[Y]),Jn=(0,H.useCallback)(async e=>{let t=Y.current;if(!t)throw Error(W(`toolApprovalFailed`));try{await t.rejectToolCall(e)}catch(e){throw V.error(`Failed to reject tool call:`,e),e instanceof Error?e:Error(W(`toolApprovalFailed`))}},[Y]),Xn=(0,H.useCallback)(async e=>{let t=Y.current;if(!t?.approveAutoCompact)throw Error(W(`toolApprovalFailed`));await t.approveAutoCompact(e)},[Y]),Zn=(0,H.useCallback)(async e=>{let t=Y.current;if(!t?.rejectAutoCompact)throw Error(W(`toolApprovalFailed`));await t.rejectAutoCompact(e)},[Y]),{loadSession:Qn,renameSession:$n,togglePinSession:er,archiveSession:tr,startNewGlobalSession:nr}=Fu({storageRef:l,taskMapRef:pn,currentSessionIdRef:mn,loadAgentSession:sn,setCurrentTitleRef:fn,refreshSessions:Bt,updateSessionTitle:Ut,closeWorkspacePage:_t,startNewGlobalChat:Ln}),rr=(0,H.useCallback)(e=>{bn(e,()=>Qn(e))},[Qn,bn]),ir=(0,H.useCallback)((e,t)=>{L.setSettingsInitialTab(e),L.setSettingsCustomProvider(t),L.setSettingsDialogOpen(!0),L.setMobileSidebarOpen(!1)},[L]),{activateConfiguredModel:ar,openModelSettings:or,openDefaultOptionsSettings:sr,openAboutSettings:cr,activateLiteLlmExampleModel:lr,openCustomModelSelector:ur}=su({storageRef:l,activeModelRef:f,agentRef:Y,createAgent:rn,updateCurrentAgentModel:un,setChatPanelRevision:dn,setNeedsModelSetup:ue,setRestoredDraft:de,notifySettingsChanged:en.notifySettingsChanged,openSettingsPage:ir,loadCloudModels:i.loadCloudModels}),dr=(0,H.useCallback)(()=>{L.setSettingsDialogOpen(!1),L.setSettingsCustomProvider(void 0),(le||!Y.current)&&ar().catch(e=>V.error(`Failed to activate configured model:`,e))},[ar,Y,le,L]),fr=(0,H.useCallback)(()=>{me(!1),cr()},[cr]),pr=(0,H.useMemo)(()=>wt,[wt]),mr=(0,H.useMemo)(()=>{if(J.currentSessionId)return pr.find(e=>e.id===J.currentSessionId)},[J.currentSessionId,pr]),hr=!!mr?.pinnedAt,gr=Bu(pr),_r=(0,H.useCallback)(e=>J.taskStatuses[e.id]??gr[e.id]??e.taskStatus??`idle`,[J.taskStatuses,gr]);(0,H.useEffect)(()=>{if(fe)return window.addEventListener(`click`,vt),window.addEventListener(`blur`,vt),()=>{window.removeEventListener(`click`,vt),window.removeEventListener(`blur`,vt)}},[vt,fe]),(0,H.useEffect)(()=>{if(!L.conversationMenuOpen)return;let e=()=>L.setConversationMenuOpen(!1),t=t=>{t.key===`Escape`&&e()};return window.addEventListener(`click`,e),window.addEventListener(`blur`,e),window.addEventListener(`resize`,e),window.addEventListener(`orientationchange`,e),document.addEventListener(`keydown`,t),()=>{window.removeEventListener(`click`,e),window.removeEventListener(`blur`,e),window.removeEventListener(`resize`,e),window.removeEventListener(`orientationchange`,e),document.removeEventListener(`keydown`,t)}},[L,L.conversationMenuOpen]),(0,H.useEffect)(()=>{if(!ze)return;let e=()=>Be(!1);return window.addEventListener(`click`,e),window.addEventListener(`blur`,e),()=>{window.removeEventListener(`click`,e),window.removeEventListener(`blur`,e)}},[ze]),(0,H.useEffect)(()=>{let t=t=>{if(e){$(`远程客户端不能使用服务端终端`);return}let n=t.detail,r=typeof n?.command==`string`?n.command.trim():``;r&&(async()=>{(n?.confirm||n?.dangerous)&&!await $c({title:W(`confirmExecuteCommandTitle`),description:n?.dangerous?W(`confirmExecuteDangerousCommand`):W(`confirmExecuteMultipleCommands`),confirmLabel:W(`executeInTerminal`),cancelLabel:W(`cancel`),variant:n?.dangerous?`destructive`:`default`})||(z(!1),ye(!0),ge({id:++Ye.current,command:r,execute:!0}))})().catch(e=>{V.error(`Failed to execute markdown command:`,e),$(e instanceof Error?e.message:W(`terminalCommandExecuteFailed`))})};return window.addEventListener(`quickforge:execute-markdown-command`,t),()=>window.removeEventListener(`quickforge:execute-markdown-command`,t)},[e,z]);let vr=(0,H.useCallback)(e=>{ge(t=>t?.id===e?null:t)},[]),yr=(0,H.useCallback)(()=>{L.setFirstUseGuideDismissed(!0)},[L]),br=(0,H.useCallback)(()=>{let e=J.currentToolProject?.id?W(`firstUseGuideProjectPrompt`):W(`firstUseGuideGeneralPrompt`);navigator.clipboard.writeText(e).then(()=>U({sessionId:J.currentSessionId??``,title:W(`copied`),status:`idle`,message:e})).catch(e=>{V.error(`Failed to copy first-use guide prompt:`,e),$(W(`copyFailed`))})},[U,J.currentSessionId,J.currentToolProject?.id]),xr=!le&&!!J.agent&&!J.agent?.state.isStreaming&&(J.agent?.state.messages.length??0)===0;(0,H.useEffect)(()=>{xr&&!je.current&&Ae(!1),je.current=xr},[xr]),(0,H.useEffect)(()=>{!xr||ke||!g||J.chatScope!==`global`||Rn(g)},[g,J.chatScope,ke,xr,Rn]);let Sr=(0,H.useCallback)(()=>{if(Ae(!1),g){Rn(g);return}nr()},[g,nr,Rn]),Cr=(0,H.useCallback)(e=>{Rn(e)},[Rn]),wr=(0,H.useCallback)(()=>{Ae(!0),nr()},[nr]),Tr=(0,H.useCallback)(()=>{k()},[k]),Er=!!nt&&!L.firstUseGuideDismissed&&!xr&&_.length===0&&Ot.length===0,Dr=(0,H.useCallback)(()=>{let e=J.currentSessionId;e&&(L.setConversationMenuOpen(!1),er(e))},[J.currentSessionId,er,L]),Or=(0,H.useCallback)(()=>{let e=J.currentSessionId;e&&(L.setConversationMenuOpen(!1),$n(e,J.currentTitle))},[J.currentSessionId,J.currentTitle,$n,L]),kr=(0,H.useCallback)(()=>{L.setConversationMenuOpen(!1),L.setShareDialogOpen(!0)},[L]),Ar=J.agent,jr=Ar?.harness===`opencode`&&!Ar.state.isStreaming&&Ar instanceof Mc&&!!Ar.harnessSessionId,Mr=(0,H.useCallback)(()=>{let e=J.currentSessionId;e&&(L.setConversationMenuOpen(!1),tr(e))},[J.currentSessionId,tr,L]),{setSkillsDialog:Nr,setSidebarOpen:Pr}=L,Ir=(0,H.useCallback)(()=>{ir(`skills`)},[ir]),Lr=(0,H.useCallback)(()=>{ir(`agents`)},[ir]),Rr=(0,H.useCallback)(()=>{ir(`scheduledTasks`)},[ir]),zr=(0,H.useCallback)(e=>{Nr({scope:`project`,project:e})},[Nr]),Br=(0,H.useCallback)(async e=>{let t=await fetch(`/api/project/${encodeURIComponent(e.id)}/open-in-explorer`,{method:`POST`});if(t.ok)return;let n=await t.json().catch(()=>null);throw Error(n?.error||W(`openInExplorerFailed`))},[]),Vr=(0,H.useCallback)(async e=>{let t=await fetch(`/api/project/${encodeURIComponent(e.id)}/open-in-vscode`,{method:`POST`});if(t.ok)return;let n=await t.json().catch(()=>null);throw Error(n?.error||W(`openInVSCodeFailed`))},[]),Hr=(0,H.useCallback)(async e=>{let t=await fetch(`/api/project/${encodeURIComponent(e.id)}/open-in-idea`,{method:`POST`});if(t.ok)return;let n=await t.json().catch(()=>null);throw Error(n?.error||W(`openInIDEAFailed`))},[]),Ur=(0,H.useCallback)(e=>{Br(e).catch(e=>{V.error(`Failed to open project in explorer:`,e),$(e instanceof Error?e.message:W(`openInExplorerFailed`))})},[Br]),Wr=(0,H.useCallback)(e=>{Vr(e).catch(e=>{V.error(`Failed to open project in VS Code:`,e),$(e instanceof Error?e.message:W(`openInVSCodeFailed`))})},[Vr]),qr=(0,H.useCallback)(e=>{Hr(e).catch(e=>{V.error(`Failed to open project in IntelliJ IDEA:`,e),$(e instanceof Error?e.message:W(`openInIDEAFailed`))})},[Hr]),Yr=(0,H.useCallback)(()=>Pr(e=>!e),[Pr]),Z=(0,H.useCallback)(()=>{L.setMobileSidebarOpen(!1)},[L]),Xr=(0,H.useCallback)(e=>{Z(),rr(e)},[Z,rr]),Zr=(0,H.useCallback)(()=>{Z(),Sr()},[Z,Sr]),Qr=(0,H.useCallback)(e=>{Z(),Rn(e)},[Z,Rn]),$r=(0,H.useCallback)(()=>{Z(),Ir()},[Z,Ir]),ei=(0,H.useCallback)(()=>{Z(),Lr()},[Z,Lr]),ti=(0,H.useCallback)(()=>{Z(),Rr()},[Z,Rr]),ni=(0,H.useCallback)(e=>{Z(),zr(e)},[Z,zr]),ri=(0,H.useCallback)(e=>{if(e.scope===`project`&&e.project&&e.projects){M(e.projects),L.setSkillsDialog({scope:`project`,project:e.project}),m.current?.id===e.project.id&&(re(e.project),m.current=e.project),en.notifyProjectsChanged();return}en.notifyProjectsChanged()},[en,re,M,L]);return Mn?(0,K.jsx)(`div`,{className:`flex h-screen items-center justify-center bg-background p-6 text-foreground`,children:(0,K.jsxs)(`div`,{className:`max-w-md rounded-lg border border-border bg-background p-5 text-center`,children:[(0,K.jsx)(`h1`,{className:`text-base font-semibold`,children:W(`localServiceUnavailableTitle`)}),(0,K.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:Mn}),(0,K.jsxs)(`div`,{className:`mt-4 flex justify-center gap-2`,children:[(0,K.jsx)(q,{variant:`outline`,size:`sm`,onClick:Nn,children:W(`retry`)}),(0,K.jsx)(q,{variant:`default`,size:`sm`,onClick:()=>window.location.reload(),children:W(`reloadPage`)})]})]})}):In?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`quickforge-desktop-titlebar fixed left-0 right-0 top-0 z-40 hidden h-8 items-center px-2`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`quickforge-desktop-titlebar-trigger inline-flex h-8 translate-y-1 items-center gap-2.5 rounded-none px-3 text-[13px] font-medium leading-none text-foreground/90 transition-colors hover:bg-accent hover:text-accent-foreground`,onClick:e=>{e.stopPropagation(),me(e=>!e)},"aria-haspopup":`menu`,"aria-expanded":fe,children:[(0,K.jsxs)(`svg`,{className:`h-[18px] w-[18px] shrink-0`,viewBox:`0 0 64 64`,"aria-hidden":`true`,children:[(0,K.jsxs)(`defs`,{children:[(0,K.jsxs)(`linearGradient`,{id:`titlebarIconStroke`,x1:`0`,y1:`0`,x2:`1`,y2:`1`,children:[(0,K.jsx)(`stop`,{offset:`0`,stopColor:`#9ca3af`}),(0,K.jsx)(`stop`,{offset:`1`,stopColor:`#4b5563`})]}),(0,K.jsxs)(`linearGradient`,{id:`titlebarIconBolt`,x1:`0`,y1:`0`,x2:`1`,y2:`1`,children:[(0,K.jsx)(`stop`,{offset:`0`,stopColor:`#374151`}),(0,K.jsx)(`stop`,{offset:`1`,stopColor:`#0f172a`})]})]}),(0,K.jsx)(`polygon`,{points:`32,6 52.78,18 52.78,42 32,54 11.22,42 11.22,18`,fill:`none`,stroke:`url(#titlebarIconStroke)`,strokeWidth:`4.5`,strokeLinejoin:`round`}),(0,K.jsx)(`path`,{d:`M37.2 13 L22 34 L30.6 34 L26.8 50 L42.8 26 L33.8 26 Z`,fill:`url(#titlebarIconBolt)`}),(0,K.jsx)(`path`,{d:`M37.2 13 L22 34 L30.6 34 L33.8 26 Z`,fill:`#e5e7eb`,opacity:`0.4`})]}),(0,K.jsx)(`span`,{children:`QuickForge`})]}),fe&&(0,K.jsxs)(`div`,{className:`quickforge-desktop-titlebar-menu absolute left-2 top-8 min-w-40 overflow-hidden rounded-md border border-border bg-popover py-1 text-[13px] text-popover-foreground shadow-lg`,role:`menu`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex h-8 w-full items-center gap-2.5 px-3 text-left hover:bg-accent hover:text-accent-foreground`,role:`menuitem`,onClick:fr,children:[(0,K.jsx)(C,{className:`size-4`}),(0,K.jsx)(`span`,{children:W(`about`)})]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-8 w-full items-center gap-2.5 px-3 text-left hover:bg-accent hover:text-accent-foreground`,role:`menuitem`,onClick:yt,children:[(0,K.jsx)(r,{className:`size-4`}),(0,K.jsx)(`span`,{children:W(`desktopUpdate`)})]}),(0,K.jsx)(`div`,{className:`my-1 border-t border-border`}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-8 w-full items-center gap-2.5 px-3 text-left text-destructive hover:bg-destructive/10`,role:`menuitem`,onClick:bt,children:[(0,K.jsx)(u,{className:`size-4`}),(0,K.jsx)(`span`,{children:W(`desktopExit`)})]})]})]}),!L.settingsDialogOpen&&(0,K.jsxs)(`div`,{className:G(`quickforge-window-toolbar fixed right-2 z-30 flex items-center gap-1`,be&&`pointer-events-none invisible`),"aria-hidden":be||void 0,"aria-label":W(`workspacePanel`),children:[!e&&!L.workspaceInspectorOpen?(0,K.jsx)(nn,{project:J.currentToolProject,disabled:le,onOpenInExplorer:Ur,onOpenInVSCode:Wr,onOpenInIDEA:qr}):null,!L.workspaceInspectorOpen&&J.currentToolProject?.id&&Fe?.isGitRepository?(0,K.jsx)(Wd,{projectId:J.currentToolProject.id,status:Fe,expanded:Ve,onExpandedChange:He,onOpenChanges:()=>{He(!1),wn()},onOpenCommitPush:()=>{He(!1),We(!0)},onCheckout:En,onCreated:Dn,onOpenGraph:()=>Ke(!0),mobileShell:n}):null,e?null:(0,K.jsx)(q,{variant:`ghost`,size:`icon`,onClick:()=>{z(!1),ye(e=>!e)},disabled:!J.currentToolProject?.id||le,"aria-label":W(ve?`terminalCollapse`:`rightPanelTerminal`),title:W(ve?`terminalCollapse`:`rightPanelTerminal`),className:G(`rounded-[10px] text-muted-foreground/85 hover:bg-muted/45 hover:text-foreground/90 disabled:opacity-40`,ve?`bg-accent text-accent-foreground hover:bg-accent hover:text-accent-foreground`:void 0),children:(0,K.jsx)(_e,{className:`size-[18px] stroke-[1.85]`})}),(0,K.jsx)(q,{variant:`ghost`,size:`icon`,onClick:()=>{z(!1),L.setWorkspaceInspectorOpen(e=>!e)},disabled:!J.currentToolProject?.id||le,"aria-label":L.workspaceInspectorOpen?W(`workspaceCollapseRightPanel`):W(`workspaceExpandRightPanel`),title:L.workspaceInspectorOpen?W(`workspaceCollapseRightPanel`):W(`workspaceExpandRightPanel`),className:G(`hidden rounded-[10px] text-muted-foreground/85 hover:bg-muted/45 hover:text-foreground/90 disabled:opacity-40 lg:inline-flex`,L.workspaceInspectorOpen?`bg-accent text-accent-foreground hover:bg-accent hover:text-accent-foreground`:void 0),children:(0,K.jsx)(ie,{className:`size-[18px] stroke-[1.85]`})})]}),L.settingsDialogOpen?(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(Yp,{}),children:(0,K.jsx)(zp,{initialTab:L.settingsInitialTab,customProvider:L.settingsCustomProvider,onBack:dr})}):null,(0,K.jsxs)(`div`,{className:G(`flex h-screen min-h-0 supports-[height:100dvh]:h-dvh bg-[var(--quickforge-sidebar-bg)] text-foreground`,L.settingsDialogOpen&&`hidden`),"aria-hidden":L.settingsDialogOpen||void 0,children:[(0,K.jsx)(Rs,{sidebarOpen:L.sidebarOpen,projectsCollapsed:L.projectsCollapsed,pinnedCollapsed:L.pinnedCollapsed,conversationsCollapsed:L.conversationsCollapsed,projects:_,expandedProjectIds:x,activeProject:g,currentSessionId:J.currentSessionId,loadingSessionId:J.loadingSessionId,sessionViewMode:Te,sessionSortMode:De,globalSessions:Ot,pinnedSessions:Tt,pinnedHasMore:Et,pinnedLoading:Dt,sessionsForProject:kt,projectTimelineSessions:jt,projectTimelineHasMore:Mt,projectTimelineLoading:Nt,globalHasMore:At,globalLoading:Ft,onLoadMoreGlobal:Xt,onLoadMorePinned:Jt,projectHasMore:Pt,projectLoading:It,projectLoaded:Lt,onLoadMoreProject:Qt,onLoadMoreProjectTimeline:$t,sessionTaskStatus:_r,selectingProject:S,onTogglePinnedCollapsed:L.togglePinnedCollapsed,onToggleProjectsCollapsed:L.toggleProjectsCollapsed,onToggleConversationsCollapsed:L.toggleConversationsCollapsed,onToggleProjectExpanded:te,onToggleAllProjectsExpanded:j,onReorderProjects:ne,onSelectProjectDirectory:e?void 0:k,onStartNewProjectChat:Rn,onOpenGlobalSkills:Ir,onOpenAgents:Lr,onOpenScheduledTasks:Rr,onOpenProjectSkills:zr,onOpenProjectInExplorer:e?void 0:Ur,onDeleteProject:Gn,onLoadSession:rr,onSessionViewModeChange:Ee,onSessionSortModeChange:Oe,onTogglePinSession:er,onDeleteSession:tr,onStartNewGlobalChat:Sr,onOpenSettings:sr,currentServerUrl:t?`云账户远程访问`:o,currentServerAlias:s,onOpenServer:n||t?c:void 0,updateAvailable:Pn.result.updateAvailable,latestVersion:Pn.result.latestVersion,currentVersion:Pn.result.currentVersion,onOpenUpdate:cr,onDismissUpdate:Pn.dismissUpdate,onToggleSidebar:Yr,currentSessionHoverInfo:Ne}),L.mobileSidebarOpen?(0,K.jsxs)(`div`,{className:`fixed inset-0 z-50 md:hidden`,role:`dialog`,"aria-modal":`true`,children:[(0,K.jsx)(`button`,{type:`button`,className:`absolute inset-0 bg-background/65 backdrop-blur-sm`,onClick:Z,"aria-label":W(`toggleSidebar`)}),(0,K.jsx)(`div`,{className:`absolute inset-y-0 left-0 max-w-[85vw] shadow-quickforge`,children:(0,K.jsx)(Rs,{variant:`mobile`,sidebarOpen:!0,projectsCollapsed:L.projectsCollapsed,pinnedCollapsed:L.pinnedCollapsed,conversationsCollapsed:L.conversationsCollapsed,projects:_,expandedProjectIds:x,activeProject:g,currentSessionId:J.currentSessionId,loadingSessionId:J.loadingSessionId,sessionViewMode:Te,sessionSortMode:De,globalSessions:Ot,pinnedSessions:Tt,pinnedHasMore:Et,pinnedLoading:Dt,sessionsForProject:kt,projectTimelineSessions:jt,projectTimelineHasMore:Mt,projectTimelineLoading:Nt,globalHasMore:At,globalLoading:Ft,onLoadMoreGlobal:Xt,onLoadMorePinned:Jt,projectHasMore:Pt,projectLoading:It,projectLoaded:Lt,onLoadMoreProject:Qt,onLoadMoreProjectTimeline:$t,sessionTaskStatus:_r,selectingProject:S,onTogglePinnedCollapsed:L.togglePinnedCollapsed,onToggleProjectsCollapsed:L.toggleProjectsCollapsed,onToggleConversationsCollapsed:L.toggleConversationsCollapsed,onToggleProjectExpanded:te,onToggleAllProjectsExpanded:j,onReorderProjects:ne,onSelectProjectDirectory:e?void 0:()=>{Z(),k()},onStartNewProjectChat:Qr,onOpenGlobalSkills:$r,onOpenAgents:ei,onOpenScheduledTasks:ti,onOpenProjectSkills:ni,onOpenProjectInExplorer:e?void 0:e=>{Z(),Br(e).catch(e=>{V.error(`Failed to open project in explorer:`,e),$(e instanceof Error?e.message:W(`openInExplorerFailed`))})},onDeleteProject:Gn,onLoadSession:Xr,onSessionViewModeChange:Ee,onSessionSortModeChange:Oe,onTogglePinSession:er,onDeleteSession:tr,onStartNewGlobalChat:Zr,onOpenSettings:()=>{Z(),sr()},currentServerUrl:t?`云账户远程访问`:o,currentServerAlias:s,onOpenServer:n||t?()=>{Z(),c()}:void 0,updateAvailable:Pn.result.updateAvailable,latestVersion:Pn.result.latestVersion,currentVersion:Pn.result.currentVersion,onOpenUpdate:()=>{Z(),cr()},onDismissUpdate:Pn.dismissUpdate,onToggleSidebar:Z,currentSessionHoverInfo:Ne})})]}):null,(0,K.jsxs)(`main`,{className:G(`flex min-w-0 flex-1 flex-col bg-[var(--quickforge-main-bg)] md:overflow-hidden md:rounded-tl-2xl`),children:[(0,K.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-2 border-b border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-3 pr-20`,children:[(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:`md:hidden`,onClick:()=>L.setMobileSidebarOpen(!0),"aria-label":W(`toggleSidebar`),children:(0,K.jsx)(D,{className:`size-[18px]`})}),(0,K.jsx)(`div`,{className:`min-w-0 flex-1`,children:(0,K.jsxs)(`div`,{className:`flex max-w-full min-w-0 items-center gap-2`,children:[(0,K.jsxs)(`div`,{className:`min-w-0`,children:[(0,K.jsx)(`div`,{className:`min-w-0 truncate text-sm font-semibold text-foreground/92`,children:Fn(J.currentTitle,mr?.channelName)}),J.currentToolProject?.name||Fe?.isGitRepository&&Fe.branch?(0,K.jsxs)(`div`,{className:`mt-0.5 flex min-w-0 items-center gap-2 overflow-hidden whitespace-nowrap text-xs leading-none text-muted-foreground sm:hidden`,children:[J.currentToolProject?.name?(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 basis-0 items-center gap-1`,title:J.currentToolProject.name,children:[(0,K.jsx)(A,{className:`size-3 shrink-0`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:J.currentToolProject.name})]}):null,Fe?.isGitRepository&&Fe.branch?(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 basis-0 items-center gap-1`,title:Fe.branch,children:[(0,K.jsx)(pe,{className:`size-3 shrink-0`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:Fe.branch})]}):null]}):null]}),!n&&J.currentToolProject?.name?(0,K.jsxs)(`div`,{className:`hidden h-9 max-w-[220px] shrink-0 items-center gap-2 rounded-full bg-muted/55 px-3 text-sm text-foreground/88 md:inline-flex`,title:J.currentToolProject.name,children:[(0,K.jsx)(A,{className:`size-4 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:J.currentToolProject.name})]}):null,!n&&J.currentToolProject?.id&&Fe?.isGitRepository&&Fe.branch?(0,K.jsxs)(`div`,{className:`relative hidden shrink-0 md:block`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-9 max-w-[220px] items-center gap-2 rounded-full bg-muted/55 px-3 text-sm text-foreground/88 transition-colors hover:bg-muted`,onClick:()=>Be(e=>!e),"aria-label":W(`gitBranchMenu`),"aria-expanded":ze,children:[(0,K.jsx)(pe,{className:`size-4 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:Fe.branch}),(0,K.jsx)(y,{className:`size-4 text-muted-foreground`})]}),ze?(0,K.jsx)(Id,{projectId:J.currentToolProject.id,currentBranch:Fe.branch,dirtyCount:Fe.counts?.total??0,onCheckout:En,onCreated:Dn,onOpenGraph:()=>{Be(!1),Ke(!0)},onOpenChanges:()=>{Be(!1),wn()}}):null]}):null,(0,K.jsxs)(`div`,{className:`relative shrink-0`,onClick:e=>e.stopPropagation(),children:[(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:G(L.conversationMenuOpen&&`bg-muted/45 text-foreground/90`),onClick:()=>L.setConversationMenuOpen(e=>!e),disabled:!J.currentSessionId||le,"aria-label":W(`moreOptions`),"aria-haspopup":`menu`,"aria-expanded":L.conversationMenuOpen,children:(0,K.jsx)(oe,{className:`size-[18px]`})}),L.conversationMenuOpen?(0,K.jsxs)(`div`,{className:G(`fixed inset-x-2 top-14 z-40 max-h-[calc(100dvh-4rem)] overflow-y-auto overscroll-contain rounded-lg border border-border bg-popover p-1 shadow-quickforge md:absolute md:inset-x-auto md:left-0 md:top-full md:z-30 md:mt-1 md:min-w-44 md:max-h-none md:overflow-visible`,n&&`md:fixed md:inset-x-2 md:left-auto md:top-14 md:z-40 md:mt-0 md:max-h-[calc(100dvh-4rem)] md:min-w-0 md:overflow-y-auto lg:inset-x-2 lg:left-auto lg:top-14`),role:`menu`,"aria-label":W(`moreOptions`),children:[(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:Dr,children:[hr?(0,K.jsx)(b,{className:`size-[18px]`}):(0,K.jsx)(a,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(hr?`unpinSession`:`pinSession`)})]}),(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50`,onClick:()=>{L.setConversationMenuOpen(!1),Wn()},disabled:!jr,title:W(`forkCurrentSessionTitle`),children:[(0,K.jsx)(Ce,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(`forkCurrentSession`)})]}),(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:Or,children:[(0,K.jsx)(ae,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(`renameSession`)})]}),(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:kr,children:[(0,K.jsx)(R,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(`shareSession`)})]}),(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:Mr,children:[(0,K.jsx)(d,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(`archiveSession`)})]})]}):null]})]})})]}),(0,K.jsxs)(`section`,{className:`relative flex min-h-0 flex-1 flex-col`,children:[ct?(0,K.jsx)(Qp,{exiting:dt===ct},ct):null,le?(0,K.jsx)(Kr,{onAddModel:or,onUseExample:()=>{lr().catch(e=>V.error(`Failed to use LiteLLM example:`,e))}}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:G(`flex min-h-0 flex-1 flex-col`,xr?`quickforge-empty-chat`:void 0,dt===ct&&`quickforge-conversation-enter`),children:[xr?(0,K.jsx)(`div`,{className:`quickforge-empty-chat-hero`,"aria-hidden":`true`,children:(0,K.jsx)(`h1`,{className:`quickforge-empty-chat-title`,children:W(`newChatEmptyTitle`)})}):null,(0,K.jsx)(Yt,{children:(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(Yp,{}),children:(0,K.jsx)(Fp,{agent:J.agent,onModelSelect:ur,revision:J.chatPanelRevision,agentAccessMode:P,workspaceToolsEnabled:!!J.currentToolProject?.id,project:J.currentToolProject,projectId:J.currentToolProject?.id,chatScope:J.chatScope,onAccessModeChange:Kn,onRollbackFromMessage:zn,onRetryFromMessage:Bn,onCopyAnswer:Vn,onForkFromMessage:Un,onApproveToolCall:qn,onRejectToolCall:Jn,onApproveAutoCompact:Xn,onRejectAutoCompact:Zn,onOpenWorkspaceGitChanges:wn,onOpenLocalFilePath:kn,onArtifactsChange:e=>{we({projectId:J.currentToolProject?.id,sessionId:J.currentSessionId,artifacts:e})},onContextUsageDisplayChange:tn,onInitialRenderReady:vn,onInitialRenderError:yn,capabilities:Mp(J.agent?.harness),disableFork:J.agent?.harness===`opencode`,bypassClientApiKeyCheck:J.agent?.harness===`opencode`,allowModelControls:J.agent?.harness!==`opencode`,restoredDraft:B,onRestoredDraftConsumed:Sn,newChatEmptyState:xr})})}),xr?(0,K.jsx)(Jr,{projects:_,selectedProject:J.chatScope===`project`?J.currentToolProject:void 0,onSelectProject:Cr,onClearProject:wr,onNewProject:Tr}):null]}),Er?(0,K.jsx)(Gr,{hasProject:!!J.currentToolProject?.id,onConfigureModel:or,onAddProject:k,onCopyExamplePrompt:br,onDismiss:yr}):null]})]}),ve&&!e&&J.currentToolProject?.id?(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(Yp,{}),children:(0,K.jsx)(Rp,{project:J.currentToolProject,pendingCommand:he,onPendingCommandHandled:vr,onCollapse:()=>ye(!1)})}):null]}),J.currentToolProject?.id?(0,K.jsxs)(K.Fragment,{children:[L.workspaceInspectorOpen?(0,K.jsx)(`div`,{"aria-hidden":`true`,className:`hidden w-px shrink-0 bg-[color-mix(in_oklab,var(--border)_30%,var(--quickforge-sidebar-bg))] lg:block`}):null,(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(Xp,{}),children:(0,K.jsx)(Lp,{project:J.currentToolProject,open:L.workspaceInspectorOpen,onOpenChange:L.setWorkspaceInspectorOpen,onOpenCommitPush:()=>We(!0),onOpenProjectInExplorer:e?void 0:Ur,onOpenProjectInVSCode:e?void 0:Wr,onOpenProjectInIDEA:e?void 0:qr,onPreviewArtifact:An,request:L.workspaceInspectorRequest,onRequestHandled:Cn,artifacts:Se.projectId===J.currentToolProject.id&&Se.sessionId===J.currentSessionId?Se.artifacts:[],globalTerminalOpen:e?!1:ve,onShowGlobalTerminal:e?void 0:()=>{z(!1),ye(!0)},onFullscreenChange:xe},J.currentToolProject.id)})]}):null,Ge&&J.currentToolProject?.id?(0,K.jsx)(Yd,{projectId:J.currentToolProject.id,projectName:J.currentToolProject.name,onClose:()=>Ke(!1)}):null,Ue?(0,K.jsx)(Hd,{open:!0,projectId:J.currentToolProject?.id,status:Fe,onClose:()=>We(!1),onCheckout:En,onRefreshStatus:Tn,onStatusChange:Ie,onCompleted:On},J.currentToolProject?.id??`git-commit`):null]}),ot?null:(0,K.jsx)(Zp,{exiting:!0}),(0,K.jsx)(Zt,{open:w,initialPath:g?.path,disabled:S,onOpenChange:ee,onSelect:O}),(0,K.jsx)(et,{open:!!L.skillsDialog,scope:L.skillsDialog?.scope??`global`,project:L.skillsDialog?.project,onOpenChange:e=>{e||L.setSkillsDialog(void 0)},onSaved:ri}),(0,K.jsx)(pf,{open:L.shareDialogOpen,sessionId:J.currentSessionId,title:Fn(J.currentTitle),onOpenChange:L.setShareDialogOpen}),(0,K.jsx)(fd,{toasts:pt,onDismiss:ht,onClick:xn}),(0,K.jsx)(ip,{})]}):(0,K.jsx)(Zp,{})}function im(){if(Ut())return(0,K.jsx)(ep,{});let e=window.location.pathname.match(/^\/share\/([^/]+)\/?$/)?.[1];return e?(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(`div`,{className:`flex h-screen items-center justify-center bg-background text-sm text-muted-foreground`,children:W(`loadingChatWorkspace`)}),children:(0,K.jsx)(Ip,{shareId:decodeURIComponent(e)})}):(0,K.jsx)(rm,{})}Tt({hideSelector:!0}),Dt(),Me.isNativePlatform()&&Wt()&&document.documentElement.classList.add(`quickforge-mobile-native`),window.addEventListener(`error`,e=>{V.error(`Uncaught error:`,e.error??e.message)}),window.addEventListener(`unhandledrejection`,e=>{V.error(`Unhandled promise rejection:`,e.reason)}),`serviceWorker`in navigator&&!Me.isNativePlatform()&&window.addEventListener(`load`,()=>{navigator.serviceWorker.register(`/sw.js`).catch(()=>{})}),(0,it.createRoot)(document.getElementById(`root`)).render((0,K.jsx)(H.StrictMode,{children:(0,K.jsx)(h,{strokeWidth:1.75,children:(0,K.jsx)(Yt,{children:(0,K.jsx)(im,{})})})}));export{Tu as $,lr as $t,_d as A,hc as At,Mu as B,Hi as Bt,ff as C,gl as Ct,of as D,Vc as Dt,sf as E,Rc as Et,Cd as F,ts as Ft,wu as G,Sr as Gt,du as H,Fi as Ht,Sd as I,qo as It,_u as J,kr as Jt,Su as K,Ar as Kt,Td as L,ls as Lt,yd as M,pc as Mt,Dd as N,vc as Nt,xd as O,Bc as Ot,Ed as P,lc as Pt,gu as Q,tr as Qt,wd as R,Mo as Rt,uf as S,hl as St,df as T,$c as Tt,xu as U,yi as Ut,Du as V,Pi as Vt,pu as W,Wr as Wt,Eu as X,br as Xt,Cu as Y,xr as Yt,bu as Z,Hn as Zt,$d as _,ht as _n,wl as _t,Cp as a,rr as an,au as at,Qd as b,Al as bt,wp as c,Sn as cn,Kl as ct,yf as d,ln as dn,Rl as dt,ur as en,yu as et,hf as f,on as fn,bl as ft,lf as g,vt as gn,Cl as gt,xf as h,G as hn,Dl as ht,Ep as i,Jn as in,ou as it,gd as j,_c as jt,bd as k,zc as kt,kp as l,xn as ln,Fl as lt,wf as m,q as mn,xl as mt,Np as n,ir as nn,mu as nt,Tp as o,Fn as on,Vl as ot,vf as p,nn as pn,yl as pt,vu as q,Cr as qt,Pp as r,dr as rn,$l as rt,Dp as s,X as sn,Gl as st,Ap as t,$n as tn,hu as tt,mf as u,_n as un,Il as ut,cf as v,gt as vn,Ol as vt,af as w,$ as wt,tf as x,ml as xt,rf as y,W as yn,El as yt,Vu as z,Pa as zt};
65
+ `),[e]),a=(0,H.useCallback)(async()=>{if(r.size===0){n({});return}try{let e=await Ac(),t=new Map(e.map(e=>[e.sessionId,zu(e.status)]).filter(e=>!!e[1]));n(e=>{let n={};for(let i of r){let r=t.get(i),a=e[i];r?n[i]=r:a===`running`?n[i]=`idle`:a&&a!==`idle`&&(n[i]=a)}return n})}catch(e){V.error(`Failed to refresh visible agent statuses:`,e)}},[r]);return(0,H.useEffect)(()=>{let e=window.setTimeout(()=>{a()},0);return()=>window.clearTimeout(e)},[a,i]),(0,H.useEffect)(()=>jc(e=>{let t=e.sessionId;if(!(!t||!r.has(t))){if(e.type===`agent_start`){n(e=>({...e,[t]:`running`}));return}if(e.type===`agent_end`){let r=zu(e.status)===`aborted`?`aborted`:e.errorMessage?`error`:`idle`;n(e=>({...e,[t]:r}))}}}),[r]),(0,H.useEffect)(()=>{let e=()=>{document.visibilityState===`visible`&&a()};return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[a]),t}function Vu(e,t=window.requestAnimationFrame.bind(window),n=window.cancelAnimationFrame.bind(window)){let r=!1,i=t(()=>{r||(i=t(()=>{r||e()}))});return()=>{r=!0,n(i)}}var Hu=`quickforge:tunnel-recovered`,Uu=null;async function Wu(e){if(Uu)return{status:`deferred`,reason:`in-flight`};Uu=Gu(e);try{return await Uu}finally{Uu=null}}async function Gu(e){let t=e.fetchImpl??globalThis.fetch,n=e.reload??(()=>window.location.reload()),r=e.dispatchEvent??(e=>window.dispatchEvent(e)),i=e.maxAttempts??2,a=e.retryDelayMs??700,o=e.timeoutMs??3e3,s=e.recoveryWaitTimeoutMs??5e3;if(!await Ku(e.probe))return{status:`deferred`,reason:`probe-failed`};for(let e=0;e<i;e++)if(e>0&&await Xu(a),await qu(t,o)){if(await Yu(r,s))return{status:`recovered`};break}try{n()}catch{}return{status:`reloaded`}}async function Ku(e){try{return await e()}catch{return!1}}async function qu(e,t){let[n,r]=await Promise.all([Ju(e,`/api/health`,t),Ju(e,`/api/agents`,t)]);if(!n?.ok||!r?.ok)return!1;let i=r.body;return Array.isArray(i?.sessions)}async function Ju(e,t,n){let r=new AbortController,i=globalThis.setTimeout(()=>r.abort(),n);try{let n=await e(t,{cache:`no-store`,signal:r.signal}),i=n.ok?await n.json().catch(()=>null):null;return{ok:n.ok,body:i}}catch{return null}finally{globalThis.clearTimeout(i)}}async function Yu(e,t){let n=0,r=[],i={at:Date.now(),waitUntil:e=>{n+=1,r.push(e)}};try{e(new Event(`online`)),e(new CustomEvent(Hu,{detail:i}))}catch{return!1}if(n===0)return!1;let a=Promise.all(r),o,s=new Promise((e,n)=>{o=globalThis.setTimeout(()=>n(Error(`tunnel recovery waitUntil timeout`)),t)});try{return await Promise.race([a,s]),!0}catch{return!1}finally{globalThis.clearTimeout(o)}}function Xu(e){return new Promise(t=>setTimeout(t,e))}var Zu=`quickforge:sidebar-session-view-mode:v1`,Qu=`quickforge:sidebar-session-sort-mode:v1`,$u=`project`,ed=`updatedAt`;function td(){try{return globalThis.localStorage}catch{return}}function nd(){let e=td();if(!e)return $u;try{let t=e.getItem(Zu);return t===`timeline`||t===`project`?t:$u}catch{return $u}}function rd(e){let t=td();if(t)try{t.setItem(Zu,e)}catch{}}function id(){let e=td();if(!e)return ed;try{let t=e.getItem(Qu);return t===`createdAt`||t===`updatedAt`?t:ed}catch{return ed}}function ad(e){let t=td();if(t)try{t.setItem(Qu,e)}catch{}}function od({ready:e,currentToolProjectId:t,projects:n,activeProject:r,recoveringProjectId:i}){return!e||!t||t===`default`||n.some(e=>e.id===t)||i===t?{type:`none`}:r?{type:`project`,deletedProjectId:t,project:r}:{type:`global`,deletedProjectId:t}}function sd(e,t,n){return e.projectId===t&&e.requestId===n}var cd=new Set([`write_file`,`edit_file`,`run_command`,`run_subagent`]);function ld(e,t,n){return e.type!==`tool_execution_end`||!t||e.sessionId!==t||!n?!1:typeof e.toolName==`string`&&cd.has(e.toolName)}function ud(e){return e===`idle`?{tone:`success`,message:W(`taskCompleted`)}:e===`error`?{tone:`error`,message:W(`taskError`)}:e===`aborted`?{tone:`aborted`,message:W(`processAborted`)}:e===`running`?{tone:`running`,message:W(`taskRunning`)}:{tone:`neutral`,message:W(`taskRunning`)}}function dd({toast:e,onDismiss:t,onClick:n}){let[r,i]=(0,H.useState)(!1),[a,o]=(0,H.useState)(!1),c=(0,H.useRef)(null);(0,H.useEffect)(()=>{let n=window.setTimeout(()=>i(!0),10);return c.current=window.setTimeout(()=>{o(!0),c.current=window.setTimeout(()=>t(e.id),200)},5e3),()=>{window.clearTimeout(n),c.current!==null&&window.clearTimeout(c.current)}},[e.id,t]);let l=()=>{o(!0),c.current!==null&&window.clearTimeout(c.current),c.current=window.setTimeout(()=>t(e.id),200)},u=ud(e.status),d=u.tone===`error`,f=u.tone===`success`,p=G(`size-5`,d&&`text-destructive`,f&&`text-emerald-500`,u.tone===`aborted`&&`text-amber-600`,u.tone===`running`&&`text-blue-600`,u.tone===`neutral`&&`text-muted-foreground`);return(0,K.jsxs)(`div`,{role:`alert`,onClick:()=>n(e.sessionId),className:G(`pointer-events-auto flex w-80 cursor-pointer items-start gap-3 rounded-xl border border-border bg-background p-3 shadow-quickforge transition-all duration-200 ease-out`,r&&!a?`translate-x-0 opacity-100`:`translate-x-4 opacity-0`),children:[(0,K.jsx)(`div`,{className:`mt-0.5 shrink-0`,children:f?(0,K.jsx)(x,{className:p}):(0,K.jsx)(s,{className:p})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`truncate text-sm font-medium text-foreground/90`,children:e.title}),(0,K.jsx)(`p`,{className:`mt-0.5 line-clamp-3 text-xs text-muted-foreground`,children:e.message||u.message})]}),(0,K.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),l()},className:`shrink-0 rounded-md p-0.5 text-muted-foreground/60 transition-colors hover:text-foreground`,"aria-label":W(`close`),children:(0,K.jsx)(z,{className:`size-4`})})]})}function fd({toasts:e,onDismiss:t,onClick:n}){return e.length===0?null:(0,K.jsx)(`div`,{className:`pointer-events-none fixed right-4 top-16 z-50 flex flex-col gap-2`,children:e.map(e=>(0,K.jsx)(dd,{toast:e,onDismiss:t,onClick:n},e.id))})}async function pd(e){let t=await fetch(e,{cache:`no-store`}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||`Request failed: ${t.status}`);return n}async function md(e,t){let n=await fetch(e,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(t)}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||`Request failed: ${n.status}`);return r}function hd(e){return`projectId=${encodeURIComponent(e)}`}function gd(e){return pd(`/api/workspace/tree?${hd(e)}`)}function _d(e,t){return pd(`/api/workspace/file?${hd(e)}&path=${encodeURIComponent(t)}`)}function vd(e,t){return md(`/api/workspace/resolve-path`,{projectId:e,path:t})}function yd(e,t,n){return md(`/api/workspace/open-external`,{projectId:e,path:t,target:n})}function bd(e){return pd(`/api/git/status?${hd(e)}`)}function xd(e,t){return pd(`/api/git/file-diff?${hd(e)}&path=${encodeURIComponent(t)}`)}function Sd(e,t){return md(`/api/git/stage`,{projectId:e,path:t})}function Cd(e){return md(`/api/git/stage-all`,{projectId:e})}function wd(e,t){return md(`/api/git/unstage`,{projectId:e,path:t})}function Td(e){return md(`/api/git/unstage-all`,{projectId:e})}function Ed(e,t){return md(`/api/git/restore`,{projectId:e,path:t})}function Dd(e){return md(`/api/git/restore-all`,{projectId:e})}function Od(e){return pd(`/api/git/branches?${hd(e)}`)}function kd(e,t){return md(`/api/git/checkout`,{projectId:e,branch:t})}function Ad(e,t){return md(`/api/git/create-branch`,{projectId:e,branch:t})}function jd(e){return pd(`/api/git/log?${hd(e)}`)}function Md(e,t,n,r){return md(`/api/git/generate-commit-message`,{projectId:e,modelRef:t&&typeof t==`object`?tt(t):void 0,model:t,thinkingLevel:n,includeUnstaged:r})}function Nd(e,t,n){return md(`/api/git/commit`,{projectId:e,message:t,includeUnstaged:n})}function Pd(e){return md(`/api/git/push`,{projectId:e})}function Fd(e,t,n){return md(`/api/git/commit-and-push`,{projectId:e,message:t,includeUnstaged:n})}function Id({projectId:e,currentBranch:t,dirtyCount:n=0,className:r,openChangesClassName:i,onCheckout:a,onCreated:s,onOpenGraph:c,onOpenChanges:l}){let u=(0,H.useRef)(null),[d,f]=(0,H.useState)(``),[p,m]=(0,H.useState)([]),[h,g]=(0,H.useState)(!0),[_,v]=(0,H.useState)(),[y,b]=(0,H.useState)(),x=(0,H.useCallback)(async()=>{g(!0),v(void 0);try{m((await Od(e)).branches)}catch(e){v(e instanceof Error?e.message:W(`gitBranchesFailed`))}finally{g(!1)}},[e]);(0,H.useEffect)(()=>{let e=window.setTimeout(()=>{x(),u.current?.focus()},0);return()=>window.clearTimeout(e)},[x]);let S=(0,H.useMemo)(()=>{let e=d.trim().toLowerCase();return e?p.filter(t=>t.name.toLowerCase().includes(e)):p},[p,d]),C=(0,H.useCallback)(async e=>{if(!(e.current||y)){b(e.name);try{await a(e.name),await x()}finally{b(void 0)}}},[y,a,x]),w=(0,H.useCallback)(async()=>{let t=await Pu({title:W(`createBranchTitle`),description:W(`createBranchDescription`),placeholder:W(`createBranchPlaceholder`),confirmLabel:W(`createAndCheckoutBranch`),cancelLabel:W(`cancel`)});if(t){b(t);try{let n=await Ad(e,t);s?.(n),await x()}catch(e){$(e instanceof Error?e.message:W(`gitCheckoutFailed`))}finally{b(void 0)}}},[s,e,x]);return(0,K.jsxs)(`div`,{className:G(`absolute left-0 top-10 z-40 w-[340px] overflow-hidden rounded-2xl border border-border bg-popover shadow-quickforge`,r),onClick:e=>e.stopPropagation(),children:[(0,K.jsx)(`div`,{className:`border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] p-3`,children:(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsx)(Se,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground/70`}),(0,K.jsx)(Mu,{ref:u,value:d,onChange:e=>f(e.target.value),placeholder:W(`searchBranches`),className:`h-10 rounded-xl border-transparent bg-background pl-9 text-sm shadow-none focus-visible:border-border`})]})}),l?(0,K.jsxs)(`button`,{type:`button`,className:G(`flex w-full items-center justify-center gap-2 border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-3 py-3 text-sm text-muted-foreground transition-colors hover:bg-muted/20 hover:text-foreground`,i),onClick:l,children:[(0,K.jsx)(`span`,{children:W(`uncommittedChanges`)}),(0,K.jsx)(`span`,{children:W(`filesCount`,{count:n})})]}):null,(0,K.jsx)(`div`,{className:`max-h-[340px] overflow-y-auto p-2`,children:h?(0,K.jsxs)(`div`,{className:`flex items-center justify-center gap-2 px-3 py-8 text-sm text-muted-foreground`,children:[(0,K.jsx)(B,{className:`size-4 animate-spin`}),(0,K.jsx)(`span`,{children:W(`loading`)})]}):_?(0,K.jsx)(`div`,{className:`rounded-xl bg-muted/40 px-3 py-4 text-sm text-muted-foreground`,children:_}):S.length===0?(0,K.jsx)(`div`,{className:`rounded-xl bg-muted/40 px-3 py-4 text-sm text-muted-foreground`,children:W(`noBranchesFound`)}):S.map(e=>{let n=e.current||e.name===t,r=y===e.name;return(0,K.jsxs)(`button`,{type:`button`,className:G(`flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm transition-colors`,n?`bg-muted text-foreground`:`text-foreground/88 hover:bg-muted/70`),onClick:()=>void C(e),disabled:n||!!y,title:e.name,children:[r?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(pe,{className:G(`size-4 shrink-0`,n?`text-foreground`:`text-muted-foreground`)}),(0,K.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.name}),n?(0,K.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:W(`currentBranch`)}):null]},`${e.remote?`remote`:`local`}:${e.name}`)})}),s||c?(0,K.jsxs)(`div`,{className:`border-t-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] p-2`,children:[s?(0,K.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm text-foreground/88 transition-colors hover:bg-muted/70`,onClick:()=>void w(),disabled:!!y,children:[(0,K.jsx)(o,{className:`size-4 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`createAndCheckoutBranchEllipsis`)})]}):null,c?(0,K.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm text-foreground/88 transition-colors hover:bg-muted/70`,onClick:c,children:[(0,K.jsx)(ge,{className:`size-4 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`gitGraph`)})]}):null]}):null]})}function Ld(e){return e?.detached===!0||e?.branch===`HEAD`||!!e?.branch?.startsWith(`HEAD `)}function Rd(e,t){return e?.files?.length?e.files.filter(e=>!e.conflict&&(t||e.staged)):[]}function zd(e,t,n){return!!(e?.isGitRepository&&!e.counts?.conflicts&&!Ld(e)&&n.trim()&&Rd(e,t).length)}function Bd(e){return(e?.files??[]).reduce((e,t)=>(e.additions+=t.additions??0,e.deletions+=t.deletions??0,e),{additions:0,deletions:0})}function Vd(e){return e.conflict?`!`:e.status===`untracked`?`?`:e.status===`added`?`A`:e.status===`deleted`?`D`:e.status===`renamed`?`R`:`M`}function Hd({open:e,projectId:t,status:n,onClose:r,onCheckout:i,onRefreshStatus:a,onStatusChange:o,onCompleted:s}){let[c,l]=(0,H.useState)(``),[u,d]=(0,H.useState)(!1),[p,m]=(0,H.useState)(!1),[h,g]=(0,H.useState)(!1),[_,v]=(0,H.useState)(!0),[b,x]=(0,H.useState)(),[C,w]=(0,H.useState)(``),[E,D]=(0,H.useState)(``),[O,k]=(0,H.useState)(),[ee,te]=(0,H.useState)(`off`),A=(0,H.useMemo)(()=>Bd(n),[n]),ne=(0,H.useMemo)(()=>Rd(n,u),[u,n]),re=(0,H.useMemo)(()=>new Set(ne.map(e=>e.path)),[ne]),M=n?.counts?.total??n?.files.length??0,N=Ld(n),P=!_&&zd(n,u,c);if((0,H.useEffect)(()=>{if(!e)return;let t=!1;return a().then(e=>{!t&&!e&&w(W(`gitStatusRefreshFailed`))}).finally(()=>{t||v(!1)}),()=>{t=!0}},[a,e,t]),(0,H.useEffect)(()=>{if(!e)return;let t=!1;async function n(){try{let e=await $n(),n=await ir(e),r=await fr(e,[],n.model);if(t||!r)return;k(r),te(n.thinkingLevel??tr(r))}catch{}}return n(),()=>{t=!0}},[e]),(0,H.useEffect)(()=>{if(!p)return;let e=()=>m(!1);return window.addEventListener(`click`,e),window.addEventListener(`blur`,e),()=>{window.removeEventListener(`click`,e),window.removeEventListener(`blur`,e)}},[p]),(0,H.useEffect)(()=>{if(!e)return;function t(e){e.key===`Escape`&&!b&&(m(!1),r())}return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[b,r,e]),!e)return null;async function ie(){if(!t){w(W(`gitCommitNoProject`));return}if(!O){w(W(`gitCommitNoModel`));return}if(!ne.length){w(W(`gitNoStagedChanges`));return}x(`generate`),w(``);try{l((await Md(t,O,ee,u)).message)}catch(e){w(e instanceof Error?e.message:W(`gitGenerateCommitMessageFailed`))}finally{x(void 0)}}async function F(e){if(t){if(e!==`push`){if(!c.trim()){w(W(`gitCommitMessageRequired`));return}if(!P){w(W(N?`gitDetachedHeadBlocked`:`gitNoStagedChanges`));return}}if(N){w(W(`gitDetachedHeadBlocked`));return}x(e),w(``);try{if(e===`push`){let e=await Pd(t);D(``),s(e);return}if(e===`commit-push`){let e=await Fd(t,c.trim(),u);if(!e.pushed){o(e),l(``),D(e.pushError||W(`gitOperationFailed`));return}l(``),s(e);return}let n=await Nd(t,c.trim(),u);l(``),s(n)}catch(e){w(e instanceof Error?e.message:W(`gitOperationFailed`))}finally{x(void 0)}}}return(0,qr.createPortal)((0,K.jsx)(`div`,{className:`fixed inset-0 z-[80] flex items-center justify-center bg-black/50 px-6 py-8`,role:`dialog`,"aria-modal":`true`,onMouseDown:e=>{e.target===e.currentTarget&&!b&&(m(!1),r())},children:(0,K.jsxs)(`div`,{className:`flex max-h-[min(700px,calc(100vh-64px))] w-full max-w-[760px] flex-col overflow-hidden rounded-3xl border border-[color-mix(in_oklab,var(--border)_42%,transparent)] bg-background shadow-2xl`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-5`,children:[(0,K.jsxs)(`div`,{className:`relative min-w-0`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex max-w-[280px] items-center gap-2.5 rounded-xl px-2 py-1.5 text-base text-muted-foreground transition-colors hover:bg-muted hover:text-foreground`,onClick:()=>m(e=>!e),disabled:!t||!!b,"aria-label":W(`gitBranchMenu`),"aria-haspopup":`menu`,"aria-expanded":p,children:[(0,K.jsx)(pe,{className:`size-5 shrink-0`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:n?.branch||W(`unknown`)}),(0,K.jsx)(y,{className:`size-4 shrink-0`})]}),p&&t?(0,K.jsx)(Id,{projectId:t,currentBranch:n?.branch,className:`top-11`,onCheckout:async e=>{await i(e),m(!1)}}):null]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-3 text-base font-medium`,children:[(0,K.jsxs)(`span`,{className:`text-emerald-600`,children:[`+`,A.additions]}),(0,K.jsxs)(`span`,{className:`text-red-600`,children:[`-`,A.deletions]}),(0,K.jsx)(`button`,{type:`button`,className:`ml-2 rounded-full p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground`,onClick:()=>{m(!1),r()},disabled:!!b,"aria-label":W(`close`),children:(0,K.jsx)(z,{className:`size-5`})})]})]}),(0,K.jsxs)(`div`,{className:`relative min-h-44 px-6 pb-4`,children:[(0,K.jsx)(`textarea`,{value:c,onChange:e=>{l(e.target.value),w(``)},onKeyDown:e=>{(e.ctrlKey||e.metaKey)&&e.key===`Enter`&&(e.preventDefault(),!b&&P&&F(`commit`))},placeholder:W(`gitCommitMessagePlaceholder`),disabled:!!b,className:`min-h-40 w-full resize-none bg-transparent pr-12 text-base leading-7 text-foreground/90 outline-none placeholder:text-muted-foreground/72 disabled:opacity-60`}),(0,K.jsx)(`button`,{type:`button`,className:G(`absolute right-6 top-0 rounded-full p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground`,b===`generate`&&`pointer-events-none`),onClick:()=>void ie(),disabled:!!b||_||!ne.length||N,title:W(`gitGenerateCommitMessage`),"aria-label":W(`gitGenerateCommitMessage`),children:b===`generate`?(0,K.jsx)(B,{className:`size-5 animate-spin`}):(0,K.jsx)(j,{className:`size-5`})})]}),(0,K.jsxs)(`div`,{className:`border-t border-[color-mix(in_oklab,var(--border)_24%,transparent)] px-6 py-3 text-sm`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,K.jsxs)(`label`,{className:`flex min-w-0 items-center gap-3 text-foreground/92`,children:[(0,K.jsx)(`button`,{type:`button`,className:G(`flex size-5 shrink-0 items-center justify-center rounded-md border transition-colors`,u?`border-black bg-black text-white`:`border-border bg-background text-transparent`),onClick:()=>{d(e=>!e),D(``),w(``)},disabled:!!b||_,"aria-pressed":u,children:(0,K.jsx)(S,{className:`size-3.5`})}),(0,K.jsx)(`span`,{children:W(`gitIncludeUnstagedChanges`)})]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex shrink-0 items-center gap-1.5 text-muted-foreground transition-colors hover:text-foreground`,onClick:()=>g(e=>!e),disabled:!M,children:[(0,K.jsx)(`span`,{children:W(`gitCommitFilesSummary`,{selected:ne.length,total:M})}),(0,K.jsx)(y,{className:G(`size-4 transition-transform`,h&&`rotate-180`)})]})]}),u?(0,K.jsx)(`div`,{className:`mt-2 text-xs text-muted-foreground`,children:W(`gitIncludeUnstagedWarning`)}):null,h?(0,K.jsx)(`div`,{className:`mt-3 max-h-44 space-y-1 overflow-y-auto border-t border-[color-mix(in_oklab,var(--border)_24%,transparent)] pt-3`,children:(n?.files??[]).map(e=>{let t=re.has(e.path);return(0,K.jsxs)(`div`,{className:G(`flex items-center gap-2 rounded-lg px-2 py-1.5`,!t&&`opacity-45`),children:[(0,K.jsx)(`span`,{className:`w-4 shrink-0 text-center font-mono text-xs text-muted-foreground`,children:Vd(e)}),(0,K.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,title:e.path,children:e.oldPath?`${e.oldPath} → ${e.path}`:e.path}),t?null:(0,K.jsx)(`span`,{className:`shrink-0 text-xs text-muted-foreground`,children:W(`gitFileNotIncluded`)})]},`${e.oldPath??``}:${e.path}`)})}):null]}),_?(0,K.jsx)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-muted/55 px-4 py-3 text-sm text-muted-foreground`,children:W(`gitRefreshingStatus`)}):null,N?(0,K.jsx)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-destructive/10 px-4 py-3 text-sm text-destructive`,children:W(`gitDetachedHeadBlocked`)}):null,E?(0,K.jsxs)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-destructive/10 px-4 py-3 text-sm text-destructive`,children:[(0,K.jsx)(`div`,{className:`font-medium`,children:W(`gitCommitSucceededPushFailed`)}),(0,K.jsx)(`div`,{className:`mt-1 break-words text-xs opacity-90`,children:E})]}):null,C?(0,K.jsx)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-destructive/10 px-4 py-3 text-sm text-destructive`,children:C}):null,n?.counts?.conflicts?(0,K.jsx)(`div`,{className:`mx-6 mb-3 rounded-2xl bg-destructive/10 px-4 py-3 text-sm text-destructive`,children:W(`gitCommitConflictsBlocked`)}):null,(0,K.jsx)(`div`,{className:`border-t border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-6 py-4`,children:E?(0,K.jsxs)(`button`,{type:`button`,className:`flex h-12 w-full items-center gap-3 rounded-2xl bg-muted/70 px-3 text-left transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-45`,disabled:!!b||N,onClick:()=>void F(`push`),children:[b===`push`?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(f,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`gitRetryPush`)})]}):(0,K.jsxs)(`div`,{className:`space-y-1.5 text-base`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex h-11 w-full items-center gap-3 rounded-2xl px-3 text-left transition-colors hover:bg-muted/55 disabled:cursor-not-allowed disabled:opacity-45`,disabled:!!b||!P,onClick:()=>void F(`commit`),children:[b===`commit`?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(se,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`gitCommitOnly`)})]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-12 w-full items-center gap-3 rounded-2xl bg-muted/70 px-3 text-left transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-45`,disabled:!!b||!P,onClick:()=>void F(`commit-push`),children:[b===`commit-push`?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(T,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`flex-1`,children:W(`gitCommitAndPush`)})]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-11 w-full items-center gap-3 rounded-2xl px-3 text-left text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-35`,disabled:!!b||_||N,onClick:()=>void F(`push`),children:[b===`push`?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin`}):(0,K.jsx)(f,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{children:W(`gitPushOnly`)})]})]})})]})}),document.body)}function Ud(e){return e.files.reduce((e,t)=>(e.additions+=t.additions??0,e.deletions+=t.deletions??0,e),{additions:0,deletions:0})}function Wd({projectId:e,status:t,expanded:n,onExpandedChange:r,onOpenChanges:i,onOpenCommitPush:a,onCheckout:o,onCreated:s,onOpenGraph:c,mobileShell:l=!1}){let u=(0,H.useRef)(null),[d,f]=(0,H.useState)(!1),p=(0,H.useMemo)(()=>Ud(t),[t]),h=t.counts?.total??t.files.length;return(0,H.useEffect)(()=>{if(!n)return;function e(){f(!1),r(!1)}function t(t){u.current?.contains(t.target)||e()}function i(t){t.key===`Escape`&&e()}return document.addEventListener(`pointerdown`,t),document.addEventListener(`keydown`,i),()=>{document.removeEventListener(`pointerdown`,t),document.removeEventListener(`keydown`,i)}},[n,r]),t.isGitRepository?(0,K.jsxs)(`div`,{ref:u,className:`relative`,onClick:e=>e.stopPropagation(),children:[(0,K.jsx)(`button`,{type:`button`,className:G(`inline-flex size-9 items-center justify-center rounded-2xl bg-transparent text-muted-foreground/85 transition-colors hover:bg-muted/45 hover:text-foreground/90`,n&&`bg-muted/45 text-foreground/90`),onClick:()=>r(!n),"aria-label":W(`togglePinnedSummary`),title:W(`togglePinnedSummary`),"aria-expanded":n,children:(0,K.jsx)(m,{className:`size-[18px]`})}),n?(0,K.jsxs)(`div`,{className:G(`fixed inset-x-2 top-14 z-40 max-h-[calc(100dvh-4rem)] overflow-y-auto overscroll-contain rounded-3xl border border-[color-mix(in_oklab,var(--border)_38%,transparent)] bg-background p-4 text-foreground shadow-quickforge md:absolute md:inset-x-auto md:-right-10 md:top-11 md:max-h-none md:w-[min(15rem,calc(100vw-1rem))] md:overflow-visible lg:-right-20`,l&&`md:fixed md:inset-x-2 md:right-auto md:top-14 md:max-h-[calc(100dvh-4rem)] md:w-auto md:overflow-y-auto lg:inset-x-2 lg:right-auto lg:top-14`),children:[(0,K.jsxs)(`div`,{className:`mb-4 flex items-center justify-between`,children:[(0,K.jsx)(`div`,{className:`text-sm font-medium text-muted-foreground`,children:W(`environmentInfo`)}),(0,K.jsx)(`button`,{type:`button`,className:`rounded-full p-1.5 text-foreground/85 transition-colors hover:bg-muted`,onClick:()=>{f(!1),r(!1)},"aria-label":W(`gitToolsCollapse`),title:W(`gitToolsCollapse`),children:(0,K.jsx)(z,{className:`size-4`})})]}),(0,K.jsxs)(`div`,{className:`space-y-1 text-sm`,children:[(0,K.jsxs)(`button`,{type:`button`,className:G(`hidden h-11 w-full items-center gap-3 rounded-2xl px-2.5 text-left text-foreground/88 transition-colors hover:bg-muted/45 hover:text-foreground md:flex`,l&&`md:hidden`),onClick:i,children:[(0,K.jsx)(ve,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`flex-1 font-medium`,children:W(`gitToolsChanges`)}),(0,K.jsxs)(`span`,{className:`font-medium text-emerald-600`,children:[`+`,p.additions]}),(0,K.jsxs)(`span`,{className:`font-medium text-red-600`,children:[`-`,p.deletions]})]}),(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex h-11 w-full items-center gap-3 rounded-2xl px-2.5 text-left text-foreground/88 transition-colors hover:bg-muted/45 hover:text-foreground`,onClick:()=>f(e=>!e),"aria-expanded":d,children:[(0,K.jsx)(pe,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-medium`,children:t.branch||W(`unknown`)}),(0,K.jsx)(y,{className:G(`size-4 shrink-0 text-muted-foreground transition-transform`,d&&`rotate-180`)})]}),d?(0,K.jsx)(Id,{projectId:e,currentBranch:t.branch,dirtyCount:h,className:G(`fixed inset-x-2 top-[7.75rem] max-h-[calc(100dvh-8.25rem)] w-auto overflow-y-auto md:absolute md:inset-x-auto md:left-auto md:right-0 md:top-full md:mt-2 md:max-h-none md:w-[min(340px,calc(100vw-1rem))] md:overflow-hidden lg:right-full lg:top-0 lg:mr-3 lg:mt-0`,l&&`md:fixed md:inset-x-2 md:right-auto md:top-[7.75rem] md:mt-0 md:max-h-[calc(100dvh-8.25rem)] md:w-auto md:overflow-y-auto lg:inset-x-2 lg:right-auto lg:top-[7.75rem] lg:mr-0`),openChangesClassName:G(`hidden md:flex`,l&&`md:hidden`),onCheckout:async e=>{await o(e),f(!1)},onCreated:e=>{s(e),f(!1)},onOpenGraph:()=>{f(!1),c()},onOpenChanges:()=>{f(!1),i()}}):null]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-11 w-full items-center gap-3 rounded-2xl px-2.5 text-left text-foreground/88 transition-colors hover:bg-muted/45 hover:text-foreground`,onClick:a,children:[(0,K.jsx)(ne,{className:`size-4 shrink-0 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`font-medium`,children:W(`gitToolsCommitOrPush`)})]})]})]}):null]}):null}function Gd(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:new Intl.DateTimeFormat(gt(),{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`}).format(t)}function Kd(e){return e.type===`head`?`border-amber-500 text-foreground`:e.type===`tag`?`border-emerald-600 text-emerald-700 dark:text-emerald-300`:e.type===`remote`?`border-border bg-muted/40 text-muted-foreground`:`border-border bg-muted/30 text-muted-foreground`}function qd({decoration:e}){return(0,K.jsxs)(`span`,{className:G(`inline-flex h-6 items-center gap-1 rounded-lg border px-2 text-xs`,Kd(e)),children:[e.type===`tag`?(0,K.jsx)(L,{className:`size-3`}):(0,K.jsx)(pe,{className:`size-3`}),(0,K.jsx)(`span`,{children:e.name})]})}function Jd({index:e,isLast:t}){return(0,K.jsxs)(`div`,{className:`relative flex h-full min-h-14 w-full justify-center`,"aria-hidden":`true`,children:[t?null:(0,K.jsx)(`div`,{className:`absolute left-1/2 top-0 h-full w-px -translate-x-1/2 bg-amber-500/20`}),e>0?(0,K.jsx)(`div`,{className:`absolute left-1/2 top-0 h-1/2 w-px -translate-x-1/2 bg-amber-500/20`}):null,(0,K.jsx)(`div`,{className:G(`relative z-10 mt-5 rounded-full border bg-background`,e===0?`size-3.5 border-2 border-amber-500/80`:`size-2.5 border-amber-500/65`)})]})}function Yd({projectId:e,projectName:t,onClose:n}){let[i,a]=(0,H.useState)([]),[o,s]=(0,H.useState)(!0),[c,l]=(0,H.useState)(),u=(0,H.useCallback)(async()=>{s(!0),l(void 0);try{a((await jd(e)).commits)}catch(e){l(e instanceof Error?e.message:W(`gitGraphFailed`))}finally{s(!1)}},[e]);(0,H.useEffect)(()=>{let e=window.setTimeout(()=>{u()},0);return()=>window.clearTimeout(e)},[u]),(0,H.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[n]);let d=(0,H.useMemo)(()=>i,[i]);return(0,qr.createPortal)((0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/45 p-6 backdrop-blur-sm`,onClick:e=>e.target===e.currentTarget?n():void 0,children:(0,K.jsxs)(`div`,{className:`flex h-[78vh] w-[86vw] max-w-[1500px] flex-col overflow-hidden rounded-2xl border border-border bg-background shadow-quickforge`,children:[(0,K.jsxs)(`div`,{className:`flex h-14 shrink-0 items-center gap-3 border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5`,children:[(0,K.jsx)(ge,{className:`size-5 text-muted-foreground`}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`div`,{className:`truncate text-base font-medium text-foreground`,children:W(`gitGraph`)}),(0,K.jsx)(`div`,{className:`truncate text-xs text-muted-foreground`,children:t})]}),(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:`size-8`,onClick:()=>void u(),"aria-label":W(`refresh`),disabled:o,children:o?(0,K.jsx)(B,{className:`size-4 animate-spin`}):(0,K.jsx)(r,{className:`size-4`})}),(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:`size-8`,onClick:n,"aria-label":W(`close`),children:(0,K.jsx)(z,{className:`size-4`})})]}),(0,K.jsxs)(`div`,{className:`grid shrink-0 grid-cols-[72px_minmax(360px,1fr)_160px_140px_120px] border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] bg-muted/20 text-sm font-medium text-muted-foreground`,children:[(0,K.jsx)(`div`,{className:`border-r-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3`,children:W(`graphColumn`)}),(0,K.jsx)(`div`,{className:`border-r-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3`,children:W(`description`)}),(0,K.jsx)(`div`,{className:`border-r-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3`,children:W(`date`)}),(0,K.jsx)(`div`,{className:`border-r-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3`,children:W(`author`)}),(0,K.jsx)(`div`,{className:`px-5 py-3`,children:W(`commit`)})]}),(0,K.jsx)(`div`,{className:`min-h-0 flex-1 overflow-auto`,children:o?(0,K.jsxs)(`div`,{className:`flex h-full items-center justify-center gap-2 text-sm text-muted-foreground`,children:[(0,K.jsx)(B,{className:`size-4 animate-spin`}),(0,K.jsx)(`span`,{children:W(`loading`)})]}):c?(0,K.jsx)(`div`,{className:`m-5 rounded-2xl border border-border bg-muted/30 p-5 text-sm text-muted-foreground`,children:c}):d.length===0?(0,K.jsx)(`div`,{className:`m-5 rounded-2xl border border-border bg-muted/30 p-5 text-sm text-muted-foreground`,children:W(`noGitCommits`)}):d.map((e,t)=>(0,K.jsxs)(`div`,{className:G(`grid min-h-14 grid-cols-[72px_minmax(360px,1fr)_160px_140px_120px] border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] text-sm`,e.decorations.some(e=>e.type===`head`||e.name===`HEAD`)?`bg-muted/28`:`bg-background`),children:[(0,K.jsx)(Jd,{index:t,isLast:t===d.length-1}),(0,K.jsx)(`div`,{className:`flex min-w-0 items-center gap-2 px-5 py-3`,children:(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-2`,children:[e.decorations.map(t=>(0,K.jsx)(qd,{decoration:t},`${e.hash}:${t.type}:${t.name}`)),(0,K.jsx)(`span`,{className:`min-w-0 break-words text-foreground/90`,children:e.subject})]})}),(0,K.jsx)(`div`,{className:`flex items-center border-l-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3 text-muted-foreground`,children:Gd(e.date)}),(0,K.jsx)(`div`,{className:`flex min-w-0 items-center border-l-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3 text-muted-foreground`,children:(0,K.jsx)(`span`,{className:`truncate`,children:e.author})}),(0,K.jsx)(`div`,{className:`flex items-center border-l-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-5 py-3 font-mono text-muted-foreground`,children:e.shortHash})]},e.hash))})]})}),document.body)}async function Xd(e,t){let n=await fetch(e,{...t,cache:`no-store`,headers:{...t?.body?{"content-type":`application/json`}:void 0,...t?.headers}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||`Request failed: ${n.status}`);return r}function Zd(e){if(typeof crypto<`u`&&typeof crypto.getRandomValues==`function`){let t=new Uint8Array(1);return crypto.getRandomValues(t),e[t[0]%e.length]}return e[Math.floor(Math.random()*e.length)]}function Qd(){let e=()=>Array.from({length:6},()=>Zd(`ABCDEFGHJKLMNPQRSTUVWXYZ23456789`)).join(``);return`${e()}-${e()}`}function $d(e=24){return new Date(Date.now()+e*60*60*1e3).toISOString()}async function ef(e){return Xd(`/api/shares`,{method:`POST`,body:JSON.stringify(e)})}async function tf(e){return Xd(`/api/shares${e?`?sessionId=${encodeURIComponent(e)}`:``}`)}async function nf(e){return Xd(`/api/shares/${encodeURIComponent(e)}`,{method:`DELETE`})}async function rf(e){return Xd(`/api/shares/${encodeURIComponent(e)}/disable`,{method:`POST`})}async function af(e,t){return Xd(`/api/shares/${encodeURIComponent(e)}/restore`,{method:`POST`,body:JSON.stringify({expiresAt:t})})}async function of(e,t){return Xd(`/api/shares/${encodeURIComponent(e)}/expiration`,{method:`POST`,body:JSON.stringify({expiresAt:t})})}async function sf(e,t){return Xd(`/api/shares/${encodeURIComponent(e)}/update`,{method:`POST`,body:JSON.stringify(t)})}async function cf(e){return Xd(`/api/shares/${encodeURIComponent(e)}/permanent`,{method:`DELETE`})}function lf(e){return e.revokedAt?`disabled`:e.expiresAt&&Date.parse(e.expiresAt)<=Date.now()?`expired`:`active`}async function uf(e){return Xd(`/api/shared/${encodeURIComponent(e)}/meta`)}async function df(e,t=``){return Xd(`/api/shared/${encodeURIComponent(e)}/unlock`,{method:`POST`,body:JSON.stringify({password:t})})}async function ff(e){return Xd(`/api/shared/${encodeURIComponent(e)}/models`)}function pf({open:e,sessionId:t,title:n,onOpenChange:i}){let a=(0,H.useId)(),[o,s]=(0,H.useState)(`read`),[c,l]=(0,H.useState)(``),[u,d]=(0,H.useState)(`24h`),[f,p]=(0,H.useState)(!1),[m,h]=(0,H.useState)(!1),[g,_]=(0,H.useState)(``),[v,y]=(0,H.useState)([]),[b,x]=(0,H.useState)(!1),[S,C]=(0,H.useState)(),w=(0,H.useMemo)(()=>{if(u!==`never`)return $d(u===`1h`?1:u===`7d`?168:24)},[u]);if((0,H.useEffect)(()=>{!e||!t||tf(t).then(e=>y(e.shares)).catch(e=>C(e instanceof Error?e.message:`Failed to load shares`))},[e,t]),!e)return null;let T=o===`operate`,E=!!t&&(o!==`operate`||f&&c.trim()),D=async()=>{if(!(!t||!E)){if(T&&!c.trim()){C(`可操作分享必须设置密码。`);return}x(!0),C(void 0);try{let e=await ef({sessionId:t,permission:o,password:c.trim(),expiresAt:w,allowCloudUsage:o===`operate`&&m});_(e.url),await Vc(e.url),p(!1),y((await tf(t)).shares)}catch(e){C(e instanceof Error?e.message:`Failed to create share`)}finally{x(!1)}}},O=async e=>{let t=e.url||`${window.location.origin}/share/${encodeURIComponent(e.id)}`;_(t),await Vc(t)},k=async e=>{try{await nf(e),y(t=>t.map(t=>t.id===e?{...t,revokedAt:new Date().toISOString()}:t))}catch(e){C(e instanceof Error?e.message:`Failed to revoke share`)}};return(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,onMouseDown:e=>{e.target===e.currentTarget&&i(!1)},children:(0,K.jsxs)(`div`,{className:`flex max-h-[90vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl border border-border bg-background shadow-quickforge`,onMouseDown:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`shrink-0 border-b border-border px-5 py-4`,children:[(0,K.jsx)(`h2`,{className:`text-base font-semibold`,children:`分享到局域网`}),(0,K.jsxs)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:[`当前对话:`,n,`。同一个对话只会有一个固定分享链接;只读分享密码可选,可操作分享必须设置密码。`]})]}),(0,K.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-5 py-4`,children:(0,K.jsxs)(`div`,{className:`space-y-4`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`mb-2 text-sm font-medium`,children:`权限`}),(0,K.jsxs)(`div`,{className:`grid gap-2 sm:grid-cols-2`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`rounded-xl border p-3 text-left text-sm ${o===`read`?`border-primary bg-primary/10`:`border-border`}`,onClick:()=>s(`read`),children:[(0,K.jsx)(`div`,{className:`font-medium`,children:`仅阅读`}),(0,K.jsx)(`div`,{className:`mt-1 text-xs text-muted-foreground`,children:`只能查看这一个对话。`})]}),(0,K.jsxs)(`button`,{type:`button`,className:`rounded-xl border p-3 text-left text-sm ${o===`operate`?`border-red-400 bg-red-50 text-red-950`:`border-border`}`,onClick:()=>s(`operate`),children:[(0,K.jsx)(`div`,{className:`font-medium text-red-700`,children:`可操作(高危)`}),(0,K.jsx)(`div`,{className:`mt-1 text-xs text-red-700`,children:`允许对方操作这个原对话,禁止 Fork。`})]})]})]}),o===`operate`?(0,K.jsxs)(`div`,{className:`rounded-xl border border-red-300 bg-red-50 p-3 text-sm text-red-900`,children:[(0,K.jsxs)(`div`,{className:`flex gap-2 font-semibold`,children:[(0,K.jsx)(ce,{className:`mt-0.5 size-4`}),`高危可操作权限`]}),(0,K.jsx)(`p`,{className:`mt-2 text-xs leading-5`,children:`拥有链接和密码的人只能操作这一个原对话,但对方的消息、停止生成、回滚、模型/思考等级选择、YOLO 状态下可用工具等操作会按正常对话权限直接影响你的本机原对话。可操作分享必须设置密码。`}),(0,K.jsxs)(`label`,{className:`mt-3 flex items-center gap-2 text-xs font-medium`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:f,onChange:e=>p(e.target.checked)}),`我已了解风险,仍然允许可操作权限。`]}),(0,K.jsxs)(`label`,{className:`mt-3 flex items-start gap-2 text-xs font-medium`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:m,onChange:e=>h(e.target.checked)}),(0,K.jsx)(`span`,{children:`允许该分享使用我的 QuickForge Cloud 模型和额度。默认关闭。`})]})]}):null,(0,K.jsxs)(`div`,{className:`space-y-2`,children:[(0,K.jsx)(`label`,{htmlFor:a,className:`block text-sm font-medium`,children:T?`密码(可操作必填)`:`密码(可选)`}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-3 sm:flex-row sm:items-center`,children:[(0,K.jsx)(`input`,{id:a,value:c,onChange:e=>l(e.target.value),className:`h-10 w-full min-w-0 rounded-md border border-input bg-background px-3 text-sm`,placeholder:T?`可操作分享必须设置密码`:`留空则打开链接无需密码`}),(0,K.jsxs)(q,{variant:`outline`,className:`h-10 sm:shrink-0`,onClick:()=>l(Qd()),children:[(0,K.jsx)(r,{className:`mr-2 size-4`}),`生成密码`]})]}),(0,K.jsx)(`span`,{className:`block text-xs text-muted-foreground`,children:T?`可操作分享必须设置非空密码;修改密码后旧密码和已解锁状态会失效。`:`留空保存会取消密码保护;填写新密码保存后旧密码和已解锁状态会失效。`})]}),(0,K.jsxs)(`label`,{className:`block text-sm font-medium`,children:[`有效期`,(0,K.jsxs)(`select`,{value:u,onChange:e=>d(e.target.value),className:`mt-2 h-10 w-full rounded-md border border-input bg-background px-3 text-sm`,children:[(0,K.jsx)(`option`,{value:`1h`,children:`1 小时`}),(0,K.jsx)(`option`,{value:`24h`,children:`24 小时`}),(0,K.jsx)(`option`,{value:`7d`,children:`7 天`}),(0,K.jsx)(`option`,{value:`never`,children:`永久,需手动撤销`})]})]}),g?(0,K.jsxs)(`div`,{className:`rounded-xl border border-emerald-300 bg-emerald-50 p-3 text-sm text-emerald-900`,children:[`已复制到剪切板。`,(0,K.jsx)(`pre`,{className:`mt-2 max-h-36 overflow-auto whitespace-pre-wrap text-xs`,children:g})]}):null,S?(0,K.jsx)(`div`,{className:`rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:S}):null,v.length?(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`mb-2 text-sm font-medium`,children:`已有分享`}),(0,K.jsx)(`div`,{className:`space-y-2`,children:v.map(e=>(0,K.jsxs)(`div`,{className:`flex items-center gap-2 rounded-lg border border-border p-2 text-xs`,children:[(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`div`,{className:`truncate font-mono`,children:e.id}),(0,K.jsxs)(`div`,{className:`text-muted-foreground`,children:[e.permission===`operate`?`可操作`:`只读`,` · `,e.hasPassword?`有密码`:`无密码`,` · `,e.allowCloudUsage?`允许 Cloud`:`不允许 Cloud`,` · `,e.revokedAt?`已撤销`:e.expiresAt?`到期 ${new Date(e.expiresAt).toLocaleString()}`:`永久`]})]}),e.revokedAt?null:(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(q,{variant:`ghost`,size:`icon`,onClick:()=>void O(e),"aria-label":`复制分享链接`,title:`复制分享链接`,children:(0,K.jsx)(Ce,{className:`size-4`})}),(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:`text-destructive`,onClick:()=>void k(e.id),"aria-label":`撤销分享`,title:`撤销分享`,children:(0,K.jsx)(me,{className:`size-4`})})]})]},e.id))})]}):null]})}),(0,K.jsx)(`div`,{className:`shrink-0 border-t border-border px-5 py-4`,children:(0,K.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[(0,K.jsx)(q,{variant:`outline`,onClick:()=>i(!1),children:W(`cancel`)}),(0,K.jsxs)(q,{variant:o===`operate`?`destructive`:`default`,disabled:!E||b,onClick:()=>void D(),title:o===`operate`&&!c.trim()?`可操作分享必须设置密码`:void 0,children:[(0,K.jsx)(Ce,{className:`mr-2 size-4`}),o===`operate`?`保存配置并复制高危可操作链接`:`保存配置并复制链接`]})]})})]})})}function mf(e){let t=e.replace(/\\/g,`/`);return t.split(`/`).filter(Boolean).pop()||t||`artifact`}function hf(e){let t=e.toLowerCase(),n=t.replace(/\\/g,`/`).split(`/`).pop()||t;return t.endsWith(`.html`)||t.endsWith(`.htm`)?`html`:/\.(svg|png|jpe?g|webp|gif|ico)$/i.test(t)?`image`:/\.(md|mdx|markdown)$/i.test(t)?`markdown`:n===`dockerfile`||n.endsWith(`.dockerfile`)||n===`makefile`||/\.(ts|tsx|js|jsx|mjs|cjs|css|scss|less|json|jsonc|txt|csv|tsv|log|sql|xml|yml|yaml|toml|ini|py|rb|go|rs|java|swift|kt|kts|c|h|cpp|hpp|cs|php|sh|bash|zsh|ps1)$/i.test(t)?`code`:`unknown`}function gf(e){return hf(e)!==`unknown`}var _f=/\.(svg|png|jpe?g|webp|gif|ico)$/i;function vf(e){return hf(e)===`html`||_f.test(e)}function yf(e,t=hf(e)){if(t===`markdown`||t===`code`)return`reader`;if((t===`html`||t===`image`)&&vf(e))return`browser`}function bf(e,t){let n=t.replace(/\\/g,`/`);return!e?.trim()||n.startsWith(`/`)||/^[a-zA-Z]:\//.test(n)?t:`${e.trim().replace(/\\/g,`/`).replace(/\/+$/,``)}/${n.replace(/^\/+/,``)}`}function xf(e,t,n){let r=t.replace(/\\/g,`/`),i=r.match(/^\/+/)?.[0]??``,a=i+r.slice(i.length).split(`/`).filter(Boolean).map(e=>encodeURIComponent(e)).join(`/`),o=`/api/workspace/preview/${encodeURIComponent(e)}/${a}`;return n?`${o}?r=${n}`:o}function Sf(e){return e.replace(/\\/g,`/`).toLowerCase()}function Cf(e){let t=mf(e.path).toLowerCase();return e.defaultPreview?0:e.explicit&&e.preview?1:e.explicit?2:t===`index.html`?3:e.kind===`html`?4:e.kind===`image`?5:e.kind===`markdown`?6:e.kind===`code`?7:20}function wf(e){let t=new Map;for(let n of e){if(!n.path)continue;let e=Sf(n.path),r=n.kind??hf(n.path),i=t.get(e),a=n.preview??gf(n.path),o=n.source===`present_files`||n.presentation===`explicit`;if(!i){t.set(e,{id:e,path:n.path,title:n.title,description:n.description,kind:r,preview:a,defaultPreview:!!n.defaultPreview,explicit:o,addedLines:n.addedLines,removedLines:n.removedLines,sources:[n.source],toolCallIds:n.toolCallId?[n.toolCallId]:[]});continue}i.preview=i.preview||a,i.defaultPreview=i.defaultPreview||!!n.defaultPreview,i.explicit=i.explicit||o,i.title=n.title||i.title,i.description=n.description||i.description,typeof n.addedLines==`number`&&(i.addedLines=(i.addedLines??0)+n.addedLines),typeof n.removedLines==`number`&&(i.removedLines=(i.removedLines??0)+n.removedLines),i.kind=i.kind===`unknown`?r:i.kind,i.sources.includes(n.source)||i.sources.push(n.source),n.toolCallId&&!i.toolCallIds.includes(n.toolCallId)&&i.toolCallIds.push(n.toolCallId)}return[...t.values()].sort((e,t)=>Cf(e)-Cf(t))}function Tf(e){let t=wf(e).filter(e=>e.preview&&e.explicit);if(t.length<=1)return t[0];let n=new Map;for(let t=0;t<e.length;t++){let r=e[t]?.toolCallId;r&&n.set(r,t)}let r=e=>{let t=e.toolCallIds,r=-1;for(let e of t){let t=n.get(e);typeof t==`number`&&t>r&&(r=t)}return r};return[...t].sort((e,t)=>r(t)-r(e))[0]}var Ef=`http://42.194.187.88:8080`,Df=`quickforge-mobile`,Of=`1.0.0`,kf=`手机 (Android)`,Af=`android`,jf=`urn:ietf:params:oauth:grant-type:device_code`,Mf=`refresh_token`,Nf=5,Pf=60,Ff=600*1e3,If=class extends Error{status;code;constructor(e,t=0,n=`cloud_remote_request_failed`){super(e),this.name=`CloudRemoteClientError`,this.status=t,this.code=n}};function Lf(e){return typeof e==`object`&&e?e:{}}function Rf(e){if(typeof e==`object`&&e){let t=e,n=t.error;if(typeof n==`string`)return{message:n,code:typeof t.code==`string`?t.code:`cloud_remote_request_failed`};if(typeof n==`object`&&n){let e=n;return{message:typeof e.message==`string`?e.message:`云服务请求失败`,code:typeof e.code==`string`?e.code:`cloud_remote_request_failed`}}}return{message:`云服务请求失败`,code:`cloud_remote_request_failed`}}function zf(){if(globalThis.crypto!==void 0&&typeof globalThis.crypto.randomUUID==`function`)return globalThis.crypto.randomUUID();let e=new Uint8Array(16);globalThis.crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}async function Bf(){if(globalThis.crypto===void 0||globalThis.crypto.subtle===void 0)throw new If(`当前设备不支持安全登录,请升级系统`,0,`cloud_remote_unsupported_crypto`);try{return await globalThis.crypto.subtle.generateKey({name:`Ed25519`},!0,[`sign`,`verify`])}catch{throw new If(`当前设备不支持安全登录,请升级系统`,0,`cloud_remote_unsupported_crypto`)}}async function Vf(e){let t=new Uint8Array(await globalThis.crypto.subtle.exportKey(`raw`,e)),n=``;for(let e of t)n+=String.fromCharCode(e);return btoa(n).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function Hf(e){return new Promise(t=>{setTimeout(t,e)})}async function Uf(e,t,n,r){let i={Accept:`application/json`,...n.body===void 0?{}:{"Content-Type":`application/json`},...r?{Authorization:`Bearer ${r}`}:{},...n.headers};if(Me!==void 0&&typeof Me.isNativePlatform==`function`&&Me.isNativePlatform()){let r=await je.request({url:`${e}${t}`,method:n.method??`GET`,headers:i,data:n.body,connectTimeout:15e3,readTimeout:3e4});if(r.status<200||r.status>=300){let e=Rf(r.data);throw new If(e.message,r.status,e.code)}return r.data}let a=await fetch(`${e}${t}`,{method:n.method??`GET`,headers:i,body:n.body===void 0?void 0:JSON.stringify(n.body),cache:`no-store`});if(!a.ok){let e={};try{e=await a.json()}catch{}let t=Rf(e);throw new If(t.message===`云服务请求失败`?`云服务请求失败 (${a.status})`:t.message,a.status,t.code)}return a.json()}var Wf=class{baseUrl;accessToken=``;refreshToken=``;refreshPromise=null;constructor(e){this.baseUrl=e.replace(/\/+$/,``)}get cloudUrl(){return this.baseUrl}clearTokens(){this.accessToken=``,this.refreshToken=``}async deviceAuthorization(){let e=zf(),t=await Bf(),n=await Vf(t.publicKey),r=Lf(await this.request(`POST`,`/oauth/device_authorization`,{installationId:e,clientId:Df,publicKey:n,installationName:kf,platform:Af,clientVersion:Of})),i=r.deviceCode,a=r.userCode;if(typeof i!=`string`||i===``||typeof a!=`string`||a===``)throw new If(`无法获取设备授权码,请稍后重试`,0,`cloud_remote_request_failed`);return{deviceCode:i,userCode:a,interval:typeof r.interval==`number`&&r.interval>0?r.interval:Nf,privateKey:t.privateKey}}async login(e,t,n=``){let r=await this.request(`POST`,`/v1/accounts/login`,{userCode:n,email:e,password:t});return this.consumeSession(r)}async register(e,t,n=``){let r=await this.request(`POST`,`/v1/accounts/register`,{userCode:n,email:e,password:t});return this.consumeSession(r)}async pollDeviceToken(e,t){let n=t>0?t:Nf,r=Date.now()+Ff;for(;;){if(Date.now()>r)throw new If(`登录超时,请重新发起登录`,0,`device_flow_timeout`);try{let t=await this.request(`POST`,`/oauth/token`,{grantType:jf,deviceCode:e,clientId:Df}),n=this.parseTokenSet(t);return this.accessToken=n.accessToken,this.refreshToken=n.refreshToken,n}catch(e){if(!(e instanceof If)||e.status!==400)throw e;if(e.code!==`authorization_pending`)if(e.code===`slow_down`)n=Math.min(n+5,Pf);else if(e.code===`expired_token`)throw new If(`设备授权已过期,请重新发起登录`,400,`expired_token`);else if(e.code===`access_denied`)throw new If(`设备授权已被拒绝`,400,`access_denied`);else if(e.code===`invalid_grant`)throw new If(`授权请求无效,请重新登录`,400,`invalid_grant`);else throw e;await Hf(n*1e3)}}}refresh(){return this.refreshPromise||=this.doRefresh().finally(()=>{this.refreshPromise=null}),this.refreshPromise}async doRefresh(){if(this.refreshToken===``)throw new If(`登录已过期,请重新登录`,0,`auth_expired`);let e=await this.request(`POST`,`/oauth/token`,{grantType:Mf,refreshToken:this.refreshToken,clientId:Df}),t=this.parseTokenSet(e);return this.accessToken=t.accessToken,t.refreshToken!==``&&(this.refreshToken=t.refreshToken),t}async getMe(){let e=Lf(await this.request(`GET`,`/v1/me`,void 0,!0)),t=Lf(e.account??e);return{id:typeof t.id==`string`?t.id:``,email:typeof t.email==`string`?t.email:``,mode:typeof t.mode==`string`?t.mode:void 0,plan:typeof t.plan==`string`?t.plan:void 0}}async listDevices(){let e=Lf(await this.request(`GET`,`/v1/remote/devices`,void 0,!0)).items;return Array.isArray(e)?{items:e.map(e=>{let t=Lf(e),n=Array.isArray(t.services)?t.services.map(e=>{let t=Lf(e);return{id:typeof t.id==`number`?t.id:0,name:typeof t.name==`string`?t.name:``,port:typeof t.port==`number`?t.port:0,protocol:typeof t.protocol==`string`?t.protocol:``}}):void 0;return{installationId:typeof t.installationId==`string`?t.installationId:typeof t.id==`string`?t.id:``,name:typeof t.name==`string`?t.name:void 0,online:t.online===!0,services:n}})}:{items:[]}}async turnCredentials(){let e=Lf(await this.request(`POST`,`/v1/remote/turn-credentials`,void 0,!0));return{urls:Array.isArray(e.urls)?e.urls.filter(e=>typeof e==`string`):[],username:typeof e.username==`string`?e.username:``,credential:typeof e.credential==`string`?e.credential:``,ttl:typeof e.ttl==`number`?e.ttl:0}}async request(e,t,n,r=!1){try{return await Uf(this.baseUrl,t,{method:e,body:n},r&&this.accessToken||void 0)}catch(i){if(r&&i instanceof If&&i.status===401){try{await this.refresh()}catch{throw new If(`登录已过期,请重新登录`,0,`auth_expired`)}return Uf(this.baseUrl,t,{method:e,body:n},this.accessToken||void 0)}throw i instanceof If?i:new If(`无法连接云服务,请检查网络或云服务地址`,0,`network_error`)}}parseTokenSet(e){let t=Lf(e),n=t.access_token??t.accessToken,r=t.refresh_token??t.refreshToken;if(typeof n!=`string`||n===``)throw new If(`云服务返回了无效的令牌`,0,`cloud_remote_request_failed`);let i=t.token_type??t.tokenType,a=t.expires_in??t.expiresIn,o=t.refresh_token_expires_in??t.refreshTokenExpiresIn,s=t.installation_id??t.installationId,c=t.identity_mode??t.identityMode;return{accessToken:n,refreshToken:typeof r==`string`?r:``,tokenType:typeof i==`string`?i:`Bearer`,expiresIn:typeof a==`number`?a:0,refreshTokenExpiresIn:typeof o==`number`?o:0,installationId:typeof s==`string`?s:``,identityMode:typeof c==`string`?c:``}}consumeSession(e){let t=Lf(e),n=typeof t.token==`object`&&t.token!==null?t.token:t,r=n.access_token??n.accessToken,i=n.refresh_token??n.refreshToken,a=Lf(t.account??t.user),o=Object.keys(a).length>0?{id:typeof a.id==`string`?a.id:``,email:typeof a.email==`string`?a.email:``,mode:typeof a.mode==`string`?a.mode:void 0,plan:typeof a.plan==`string`?a.plan:void 0}:void 0;if(typeof r==`string`&&r!==``&&typeof i==`string`&&i!==``){let e=n.expires_in??n.expiresIn;return this.accessToken=r,this.refreshToken=i,{accessToken:r,refreshToken:i,expiresIn:typeof e==`number`?e:void 0,account:o,bound:!0}}return{accessToken:``,refreshToken:``,account:o,bound:!0}}},Gf=Ae(`RemoteTunnel`),Kf=`http://127.0.0.1:18080/?quickforgeRemote=1`,qf=`http://127.0.0.1:18080/`;async function Jf(){for(let e=0;e<3;e++){let t=new AbortController,n=window.setTimeout(()=>t.abort(),3e3);try{await fetch(qf,{mode:`no-cors`,cache:`no-store`,signal:t.signal}),window.clearTimeout(n),window.location.href=Kf;return}catch{window.clearTimeout(n),e<2&&await new Promise(e=>setTimeout(e,700))}}throw Error(`本地隧道端口未就绪,请断开后重试`)}function Yf(e){return e instanceof If?e.message||`云服务请求失败,请稍后重试`:e instanceof Error?e.message:`操作失败,请稍后重试`}function Xf(e){return e instanceof If?e.code===`cloud_remote_unsupported_crypto`||e.code===`access_denied`||e.code===`expired_token`||e.code===`device_flow_timeout`?e.message||`设备授权未完成,请重新尝试`:e.status===0?`无法连接云服务,请检查“云服务地址”与网络后重试`:e.message||`云服务请求失败,请稍后重试`:`无法连接云服务,请检查“云服务地址”与网络后重试`}function Zf(e){return e.name?.trim()||e.installationId}function Qf({onSessionChange:e}){let[t,n]=(0,H.useState)(`checking`),[i,a]=(0,H.useState)(`login`),[o,s]=(0,H.useState)(``),[l,d]=(0,H.useState)(``),[f,p]=(0,H.useState)(``),[m,h]=(0,H.useState)(!1),[g,_]=(0,H.useState)(Ef),[v,b]=(0,H.useState)(!1),[x,S]=(0,H.useState)(``),[C,w]=(0,H.useState)(``),[T,E]=(0,H.useState)(!1),[D,te]=(0,H.useState)(null),[A,j]=(0,H.useState)([]),[ne,re]=(0,H.useState)(null),[M,N]=(0,H.useState)(null),[P,ie]=(0,H.useState)(null),F=(0,H.useRef)(null),ae=()=>((!F.current||F.current.cloudUrl!==g.replace(/\/+$/,``))&&(F.current=new Wf(g)),F.current);(0,H.useEffect)(()=>{let e=!0;return Gf.addListener(`remoteStateChanged`,t=>{e&&(N(t),t.state===`connected`?Jf().catch(t=>{e&&(re(null),N({state:`error`,error:Yf(t)}),S(Yf(t)),Gf.disconnect().catch(()=>{}))}):t.state===`reconnecting`?(re(null),N(t)):t.state===`error`&&(re(null),S(t.error||`隧道连接失败,请重试`)))}).catch(()=>{}),()=>{e=!1}},[]);let I=async()=>{E(!0),S(``);try{j((await Gf.listDevices()).items??[]),n(`devices`)}catch{try{j((await ae().listDevices()).items),n(`devices`)}catch(e){S(Yf(e)),n(`sign-in`)}}finally{E(!1)}};(0,H.useEffect)(()=>{let t=!0;return(async()=>{try{let r=await Gf.hasSession();if(!t)return;ie(r),e?.(r);let i=r.cloudUrl;i&&_(e=>e===`http://42.194.187.88:8080`?i:e),n(r.signedIn?`session-choice`:`sign-in`)}catch{t&&n(`sign-in`)}})(),()=>{t=!1}},[e]);let L=async()=>{te(`continue`);try{await I()}finally{te(null)}},R=async()=>{E(!0),te(`switch`),S(``),w(``);try{await Gf.disconnect().catch(()=>{}),await Gf.signOut(),ae().clearTokens(),j([]),re(null),N(null),d(``),n(`sign-in`),e?.({signedIn:!1})}catch(e){S(Yf(e))}finally{te(null),E(!1)}},oe=async t=>{t.preventDefault();let n=o.trim(),r=f.trim();if(!n||!l){S(`请输入邮箱和密码`);return}E(!0),S(``),w(``);try{let t=ae();if(r){let a=i===`register`?await t.register(n,l,r):await t.login(n,l,r);a.accessToken&&a.refreshToken?(await Gf.setToken({accessToken:a.accessToken,refreshToken:a.refreshToken,cloudUrl:t.cloudUrl,email:n}),ie({signedIn:!0,email:n,cloudUrl:t.cloudUrl}),e?.({signedIn:!0,email:n,cloudUrl:t.cloudUrl}),await I()):w(`已在电脑端完成设备授权;若电脑端 QuickForge 正在等待授权,请返回电脑端确认。`);return}let a=await t.deviceAuthorization();await(i===`register`?t.register(n,l,a.userCode):t.login(n,l,a.userCode));let o=await t.pollDeviceToken(a.deviceCode,a.interval);await Gf.setToken({accessToken:o.accessToken,refreshToken:o.refreshToken,cloudUrl:t.cloudUrl,email:n}),ie({signedIn:!0,email:n,cloudUrl:t.cloudUrl}),e?.({signedIn:!0,email:n,cloudUrl:t.cloudUrl}),await I()}catch(e){S(Xf(e))}finally{E(!1)}},z=async e=>{S(``),re(e.installationId),N({state:`connecting`});try{(await Gf.getState()).state!==`idle`&&await Gf.disconnect().catch(()=>{}),await Gf.connect({installationId:e.installationId})}catch(e){re(null),S(Yf(e))}},se=async()=>{E(!0),S(``),w(``);try{await Gf.disconnect().catch(()=>{}),await Gf.signOut()}catch(e){S(Yf(e))}finally{ae().clearTokens(),j([]),re(null),N(null),d(``),n(`sign-in`),E(!1),e?.({signedIn:!1})}};return t===`checking`?(0,K.jsxs)(`main`,{className:`flex min-h-dvh flex-col items-center justify-center bg-background px-8 pb-[max(2rem,env(safe-area-inset-bottom))] pt-[max(2rem,env(safe-area-inset-top))] text-foreground`,role:`status`,"aria-live":`polite`,children:[(0,K.jsx)(B,{className:`size-7 animate-spin text-muted-foreground`,"aria-hidden":`true`}),(0,K.jsx)(`p`,{className:`mt-4 text-sm text-muted-foreground`,children:`正在检查云账户状态…`})]}):t===`session-choice`?(0,K.jsxs)(`section`,{"aria-labelledby":`quickforge-cloud-remote-session-choice`,children:[(0,K.jsxs)(`header`,{className:`mb-6 flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(xe,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 pt-0.5`,children:[(0,K.jsx)(`h1`,{id:`quickforge-cloud-remote-session-choice`,className:`text-lg font-semibold tracking-tight`,children:`云账户远程访问`}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:`检测到此设备已登录。选择是否继续当前会话。`})]})]}),(0,K.jsxs)(`div`,{className:`rounded-2xl border border-border bg-background p-4 shadow-quickforge`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`p`,{className:`truncate text-base font-semibold text-foreground`,children:P?.email||`已登录账号`}),(0,K.jsx)(`span`,{className:`shrink-0 rounded-full bg-emerald-500/10 px-2 py-0.5 text-[11px] font-medium text-emerald-600`,children:`会话有效`})]}),P?.cloudUrl?(0,K.jsx)(`p`,{className:`mt-1 truncate font-mono text-xs text-muted-foreground`,children:P.cloudUrl}):null]}),(0,K.jsxs)(`div`,{className:`mt-4 rounded-2xl border border-border bg-background p-5 shadow-quickforge`,children:[(0,K.jsxs)(`div`,{className:`flex gap-2.5 rounded-xl bg-muted/30 px-3 py-2.5 text-xs leading-5 text-muted-foreground`,children:[(0,K.jsx)(ue,{className:`mt-0.5 size-4 shrink-0`,"aria-hidden":`true`}),(0,K.jsx)(`p`,{children:`继续后才会加载当前账户的在线设备;也可以清理本机会话并重新登录。`})]}),x?(0,K.jsx)(`p`,{className:`mt-4 text-sm text-destructive`,role:`alert`,children:x}):null,(0,K.jsxs)(`button`,{type:`button`,className:`mt-5 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85 disabled:opacity-60`,onClick:()=>{L()},disabled:T,children:[D===`continue`?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(xe,{className:`size-4`,"aria-hidden":`true`}),`继续当前登录`]}),(0,K.jsxs)(`button`,{type:`button`,className:`mt-3 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl border border-border text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65 disabled:opacity-60`,onClick:()=>{R()},disabled:T,children:[D===`switch`?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(u,{className:`size-4`,"aria-hidden":`true`}),`使用其他账号`]}),T?(0,K.jsx)(`p`,{className:`mt-2 text-center text-xs text-muted-foreground`,role:`status`,"aria-live":`polite`,children:D===`switch`?`正在清理当前登录…`:`正在加载设备…`}):null]})]}):t===`devices`?(0,K.jsxs)(`section`,{"aria-labelledby":`quickforge-cloud-remote-devices`,children:[(0,K.jsxs)(`header`,{className:`mb-6 flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(xe,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1 pt-0.5`,children:[(0,K.jsx)(`h1`,{id:`quickforge-cloud-remote-devices`,className:`text-lg font-semibold tracking-tight`,children:`云账户远程访问`}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:`选择一台在线设备建立远程连接。`})]}),(0,K.jsx)(`button`,{type:`button`,className:`inline-flex size-10 shrink-0 items-center justify-center rounded-xl text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65`,onClick:()=>{I()},disabled:T,title:`刷新设备列表`,"aria-label":`刷新设备列表`,children:(0,K.jsx)(r,{className:`size-4 ${T?`animate-spin`:``}`,"aria-hidden":`true`})})]}),(0,K.jsxs)(`div`,{className:`mb-4 flex items-center justify-between gap-3 rounded-2xl border border-border bg-background p-4 shadow-quickforge`,children:[(0,K.jsxs)(`div`,{className:`min-w-0`,children:[(0,K.jsx)(`p`,{className:`text-xs font-medium text-muted-foreground`,children:`当前账号`}),(0,K.jsx)(`p`,{className:`mt-0.5 truncate text-sm font-medium text-foreground`,children:P?.email||`已登录账号`}),P?.cloudUrl?(0,K.jsx)(`p`,{className:`mt-0.5 truncate font-mono text-xs text-muted-foreground`,children:P.cloudUrl}):null]}),(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-11 shrink-0 items-center justify-center gap-2 rounded-xl border border-border px-4 text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65 disabled:opacity-60`,onClick:()=>{R()},disabled:T,children:[D===`switch`?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(r,{className:`size-4`,"aria-hidden":`true`}),`切换账号`]})]}),x?(0,K.jsx)(`p`,{className:`mb-4 text-sm text-destructive`,role:`alert`,children:x}):null,C?(0,K.jsx)(`p`,{className:`mb-4 text-sm text-muted-foreground`,role:`status`,children:C}):null,M&&M.state!==`idle`?(0,K.jsxs)(`div`,{className:`mb-4`,children:[(0,K.jsxs)(`p`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,role:`status`,"aria-live":`polite`,children:[M.state===`connecting`||M.state===`reconnecting`?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(fe,{className:`size-4`,"aria-hidden":`true`}),M.state===`connecting`?`正在建立加密隧道…`:M.state===`reconnecting`?`连接中断,正在自动重连…`:M.state===`connected`?`隧道已就绪,正在打开远程界面…`:`连接已断开`]}),M.state===`connected`||M.state===`reconnecting`?(0,K.jsxs)(`p`,{className:`mt-2 flex items-center gap-1.5 text-xs text-muted-foreground`,children:[(0,K.jsx)(ue,{className:`size-3.5 shrink-0`,"aria-hidden":`true`}),`断线自动重连已开启,网络恢复后自动恢复连接`]}):null]}):null,(0,K.jsx)(`div`,{className:`overflow-hidden rounded-2xl border border-border bg-background`,children:A.length===0?(0,K.jsxs)(`div`,{className:`px-5 py-10 text-center`,children:[(0,K.jsx)(c,{className:`mx-auto size-8 text-muted-foreground/50`,"aria-hidden":`true`}),(0,K.jsx)(`p`,{className:`mt-3 text-sm text-muted-foreground`,children:`没有可用的在线设备`}),(0,K.jsx)(`p`,{className:`mt-1 text-xs leading-5 text-muted-foreground/75`,children:`请确认电脑端 QuickForge 的云远程代理(agent)已登录并在线。`})]}):A.map(e=>{let t=ne===e.installationId;return(0,K.jsx)(`div`,{className:`border-b border-border last:border-b-0`,children:(0,K.jsxs)(`button`,{type:`button`,className:`flex min-h-[68px] w-full items-center gap-3 p-3 text-left transition-colors hover:bg-muted/45 active:bg-muted/65 disabled:opacity-60`,onClick:()=>{z(e)},disabled:T||ne!==null||e.online===!1,title:e.online===!1?`设备当前离线`:`连接 ${Zf(e)}`,children:[(0,K.jsx)(`span`,{className:`flex size-9 shrink-0 items-center justify-center rounded-xl bg-muted/45 text-muted-foreground`,children:(0,K.jsx)(ee,{className:`size-4`,"aria-hidden":`true`})}),(0,K.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`span`,{className:`truncate text-sm font-medium text-foreground`,children:Zf(e)}),(0,K.jsx)(`span`,{className:`shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium ${e.online===!1?`bg-muted text-muted-foreground`:`bg-emerald-500/10 text-emerald-600`}`,children:e.online===!1?`离线`:`在线`})]}),(0,K.jsx)(`span`,{className:`mt-1 block truncate font-mono text-xs text-muted-foreground`,children:e.installationId})]}),t?(0,K.jsx)(B,{className:`size-4 shrink-0 animate-spin text-muted-foreground`,"aria-hidden":`true`}):(0,K.jsx)(y,{className:`size-4 shrink-0 -rotate-90 text-muted-foreground/65`,"aria-hidden":`true`})]})},e.installationId)})}),(0,K.jsxs)(`button`,{type:`button`,className:`mt-6 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl border border-border text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65 disabled:opacity-60`,onClick:()=>{se()},disabled:T,children:[(0,K.jsx)(u,{className:`size-4`,"aria-hidden":`true`}),`退出登录`]})]}):(0,K.jsxs)(`section`,{"aria-labelledby":`quickforge-cloud-remote-signin`,children:[(0,K.jsxs)(`header`,{className:`mb-6 flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(xe,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 pt-0.5`,children:[(0,K.jsx)(`h1`,{id:`quickforge-cloud-remote-signin`,className:`text-lg font-semibold tracking-tight`,children:`云账户远程访问`}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:`通过云账户加密隧道访问家中电脑:输入邮箱密码即可登录,手机自动完成设备授权。`})]})]}),(0,K.jsxs)(`form`,{className:`rounded-2xl border border-border bg-background p-5 shadow-quickforge`,onSubmit:oe,children:[(0,K.jsxs)(`div`,{className:`mb-5 grid grid-cols-2 gap-1 rounded-xl bg-muted/40 p-1`,role:`tablist`,"aria-label":`登录或注册`,children:[(0,K.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":i===`login`,className:`rounded-lg py-2 text-sm font-medium transition-colors ${i===`login`?`bg-background text-foreground shadow-sm`:`text-muted-foreground hover:text-foreground`}`,onClick:()=>{a(`login`),S(``),w(``)},children:`登录`}),(0,K.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":i===`register`,className:`rounded-lg py-2 text-sm font-medium transition-colors ${i===`register`?`bg-background text-foreground shadow-sm`:`text-muted-foreground hover:text-foreground`}`,onClick:()=>{a(`register`),S(``),w(``)},children:`注册`})]}),(0,K.jsxs)(`div`,{className:`mb-5 flex gap-2.5 rounded-xl bg-muted/30 px-3 py-2.5 text-xs leading-5 text-muted-foreground`,children:[(0,K.jsx)(ue,{className:`mt-0.5 size-4 shrink-0`,"aria-hidden":`true`}),(0,K.jsx)(`p`,{children:`直连云 API(原生通道绕 CORS)。令牌仅存于内存,刷新令牌由系统安全存储保护。`})]}),(0,K.jsx)(`label`,{className:`block text-sm font-medium`,htmlFor:`quickforge-cloud-remote-email`,children:`邮箱`}),(0,K.jsx)(`input`,{id:`quickforge-cloud-remote-email`,type:`email`,autoCapitalize:`none`,autoCorrect:`off`,spellCheck:!1,autoComplete:`email`,value:o,onChange:e=>{s(e.target.value),S(``),w(``)},placeholder:`you@example.com`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsx)(`label`,{className:`mt-4 block text-sm font-medium`,htmlFor:`quickforge-cloud-remote-password`,children:`密码`}),(0,K.jsx)(`input`,{id:`quickforge-cloud-remote-password`,type:`password`,autoComplete:i===`register`?`new-password`:`current-password`,value:l,onChange:e=>{d(e.target.value),S(``),w(``)},placeholder:i===`register`?`至少 8 个字符`:`输入密码`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsxs)(`button`,{type:`button`,className:`mt-4 flex w-full items-center justify-between rounded-xl px-1 py-2 text-sm text-muted-foreground transition-colors hover:text-foreground`,onClick:()=>h(e=>!e),"aria-expanded":m,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(k,{className:`size-4`,"aria-hidden":`true`}),`设备验证码`,(0,K.jsx)(`span`,{className:`text-xs text-muted-foreground/70`,children:`(高级)`})]}),(0,K.jsx)(y,{className:`size-4 transition-transform ${m?`rotate-180`:``}`,"aria-hidden":`true`})]}),m?(0,K.jsxs)(`div`,{className:`mt-1 rounded-xl bg-muted/30 px-3 py-2.5`,children:[(0,K.jsx)(`input`,{id:`quickforge-cloud-remote-usercode`,autoCapitalize:`characters`,autoCorrect:`off`,spellCheck:!1,value:f,onChange:e=>{p(e.target.value),S(``),w(``)},placeholder:`ABCD-2345`,className:`h-10 w-full rounded-lg border border-input bg-background px-3 font-mono text-sm tracking-widest outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/50 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsx)(`p`,{className:`mt-2 text-xs leading-5 text-muted-foreground`,children:`电脑端 QuickForge 已发起“云远程访问”授权时,可填写电脑端显示的验证码直接批准;通常无需填写。`})]}):null,(0,K.jsxs)(`button`,{type:`button`,className:`mt-2 flex w-full items-center justify-between rounded-xl px-1 py-2 text-sm text-muted-foreground transition-colors hover:text-foreground`,onClick:()=>b(e=>!e),"aria-expanded":v,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(xe,{className:`size-4`,"aria-hidden":`true`}),`云服务地址`]}),(0,K.jsx)(y,{className:`size-4 transition-transform ${v?`rotate-180`:``}`,"aria-hidden":`true`})]}),v?(0,K.jsxs)(`div`,{className:`mt-1 rounded-xl bg-muted/30 px-3 py-2.5`,children:[(0,K.jsx)(`input`,{id:`quickforge-cloud-remote-baseurl`,autoCapitalize:`none`,autoCorrect:`off`,inputMode:`url`,spellCheck:!1,value:g,onChange:e=>{_(e.target.value),S(``),w(``)},placeholder:`https://cloud.quickforge.app`,className:`h-10 w-full rounded-lg border border-input bg-background px-3 font-mono text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/50 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsx)(`p`,{className:`mt-2 text-xs leading-5 text-muted-foreground`,children:`正式域名确定前的占位地址;仅在本次会话内生效,不持久化。`})]}):null,x?(0,K.jsx)(`p`,{className:`mt-3 text-sm text-destructive`,role:`alert`,children:x}):null,C?(0,K.jsx)(`p`,{className:`mt-3 text-sm text-muted-foreground`,role:`status`,children:C}):null,(0,K.jsxs)(`button`,{type:`submit`,className:`mt-5 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85 disabled:opacity-60`,disabled:T,children:[T?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(O,{className:`size-4`,"aria-hidden":`true`}),i===`register`?`注册并授权`:`登录`]}),T?(0,K.jsx)(`p`,{className:`mt-2 text-center text-xs text-muted-foreground`,role:`status`,children:`正在发起安全登录…`}):null]}),(0,K.jsxs)(`p`,{className:`mt-4 px-1 text-xs leading-5 text-muted-foreground/80`,children:[`连接成功后将在本机 `,(0,K.jsx)(`span`,{className:`font-mono text-foreground/70`,children:`127.0.0.1:18080`}),` 打开远程 QuickForge 界面;远程会话沿用与 Tailscale 相同的安全裁剪(终端、系统代理等不可用)。`]})]})}var $f=800;function ep(){let e=(0,H.useMemo)(()=>Rt(),[]),[t,n]=(0,H.useState)(e),[r,i]=(0,H.useState)(null),[a,s]=(0,H.useState)(e.urls.length===0),[c,l]=(0,H.useState)(``),[u,d]=(0,H.useState)(``),[f,p]=(0,H.useState)(``),[m,h]=(0,H.useState)(!1),[g,_]=(0,H.useState)(null),[v,y]=(0,H.useState)(null),[b,x]=(0,H.useState)(``),[C,w]=(0,H.useState)(null),[T,D]=(0,H.useState)(()=>new URLSearchParams(location.search).get(`tab`)===`servers`?`servers`:`cloud`),[O,k]=(0,H.useState)({signedIn:!1});(0,H.useEffect)(()=>{if(!r)return;let e=window.setTimeout(()=>{window.location.assign(Vt(r))},$f);return()=>window.clearTimeout(e)},[r]),(0,H.useEffect)(()=>{let e=!0;return Gf.hasSession().then(t=>{e&&k(t)}).catch(()=>{}),()=>{e=!1}},[]);let te=(0,H.useMemo)(()=>{if(!c.trim())return``;try{return Ft(c)}catch{return``}},[c]),A=e=>{zt(e),n(e)},j=()=>{l(``),d(``),p(``)},ne=()=>{j(),h(!1),_(null),y(null),s(!0)},re=e=>{try{let n=Ft(c),r=t.urls.includes(n)?t.urls:[...t.urls,n],a=u.trim(),o={...t.aliases??{}};a&&(o[n]=a),A({urls:r,aliases:o,lastUsedUrl:e?n:t.lastUsedUrl||n}),j(),h(!0),e?i(n):s(!1)}catch(e){h(!1),p(e instanceof Error?e.message:`无法保存 QuickForge 服务地址`)}},M=e=>{e.preventDefault(),re(!0)},N=e=>{try{A({...t,lastUsedUrl:e}),i(e)}catch(e){p(e instanceof Error?e.message:`无法连接到 QuickForge 服务`)}},P=e=>{try{let n=t.urls.filter(t=>t!==e),r={...t.aliases??{}};delete r[e],A({urls:n,aliases:r,lastUsedUrl:t.lastUsedUrl===e?n[0]||``:t.lastUsedUrl}),_(null),w(null),v===e&&(y(null),x(``)),n.length===0&&s(!0),p(``),h(!1)}catch(e){w(null),p(e instanceof Error?e.message:`无法删除服务器地址`)}},ie=e=>{y(e),x(t.aliases?.[e]??``)},I=()=>{y(null),x(``)},L=e=>{let n=b.trim(),r={...t.aliases??{}};n?r[e]=n:delete r[e],A({...t,aliases:r}),I(),_(null)},R=C?t.aliases?.[C]?.trim()||C:``;if(r){let e=t.aliases?.[r]?.trim()||r;return(0,K.jsxs)(`main`,{className:`flex min-h-dvh flex-col items-center justify-center bg-background px-8 pb-[max(2rem,env(safe-area-inset-bottom))] pt-[max(2rem,env(safe-area-inset-top))] text-foreground`,role:`status`,"aria-live":`polite`,children:[(0,K.jsxs)(`div`,{className:`relative flex size-24 items-center justify-center`,"aria-hidden":`true`,children:[(0,K.jsx)(`span`,{className:`absolute inset-0 animate-ping rounded-full bg-primary/15`}),(0,K.jsx)(`span`,{className:`absolute inset-0 animate-ping rounded-full bg-primary/10 [animation-delay:0.45s]`}),(0,K.jsx)(`div`,{className:`relative flex size-14 items-center justify-center rounded-2xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(ee,{className:`size-6 text-foreground/75`})})]}),(0,K.jsx)(`p`,{className:`mt-9 text-sm font-medium text-foreground/85`,children:`正在建立连接…`}),(0,K.jsx)(`p`,{className:`mt-2 w-full max-w-xs truncate text-center font-mono text-xs text-muted-foreground`,children:e})]})}return(0,K.jsxs)(`main`,{className:`min-h-dvh bg-background px-5 pb-[max(2rem,env(safe-area-inset-bottom))] pt-[max(2rem,env(safe-area-inset-top))] text-foreground`,children:[(0,K.jsxs)(`div`,{className:`mx-auto w-full max-w-md`,children:[(0,K.jsxs)(`div`,{className:`mb-6 grid grid-cols-2 gap-1 rounded-xl bg-muted/40 p-1`,role:`tablist`,"aria-label":`连接方式`,children:[(0,K.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":T===`servers`,className:`flex items-center justify-center gap-1.5 rounded-lg py-2 text-sm font-medium transition-colors ${T===`servers`?`bg-background text-foreground shadow-sm`:`text-muted-foreground hover:text-foreground`}`,onClick:()=>D(`servers`),children:[(0,K.jsx)(ee,{className:`size-4`,"aria-hidden":`true`}),`服务器列表`]}),(0,K.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":T===`cloud`,className:`flex min-w-0 flex-col items-center justify-center gap-0.5 rounded-lg px-1.5 py-1.5 text-sm font-medium transition-colors ${T===`cloud`?`bg-background text-foreground shadow-sm`:`text-muted-foreground hover:text-foreground`}`,onClick:()=>D(`cloud`),children:[(0,K.jsxs)(`span`,{className:`flex items-center justify-center gap-1.5`,children:[(0,K.jsx)(xe,{className:`size-4`,"aria-hidden":`true`}),`云账户`]}),O.signedIn&&O.email?(0,K.jsx)(`span`,{className:`block w-full max-w-full truncate text-center text-xs leading-tight text-muted-foreground/80`,children:O.email}):null]})]}),T===`cloud`?(0,K.jsx)(Qf,{onSessionChange:k}):(0,K.jsxs)(`section`,{className:`mx-auto w-full max-w-md`,children:[(0,K.jsxs)(`header`,{className:`mb-8 flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:(0,K.jsx)(ee,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 pt-0.5`,children:[(0,K.jsx)(`h1`,{className:`text-lg font-semibold tracking-tight`,children:`连接 QuickForge`}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:`选择一台已保存的服务器,或添加新的 Tailscale 地址。`})]})]}),t.urls.length>0?(0,K.jsxs)(`section`,{"aria-labelledby":`quickforge-mobile-saved-servers`,children:[(0,K.jsxs)(`div`,{className:`mb-2.5 flex items-center justify-between px-1`,children:[(0,K.jsx)(`h2`,{id:`quickforge-mobile-saved-servers`,className:`text-xs font-medium text-muted-foreground`,children:`已保存的服务器`}),(0,K.jsxs)(`span`,{className:`text-xs text-muted-foreground/70`,children:[t.urls.length,` 台`]})]}),(0,K.jsx)(`div`,{className:`overflow-hidden rounded-2xl border border-border bg-background`,children:t.urls.map(e=>{let n=e===t.lastUsedUrl,r=t.aliases?.[e]?.trim(),i=g===e,a=v===e;return(0,K.jsxs)(`div`,{className:`border-b border-border last:border-b-0`,children:[(0,K.jsxs)(`div`,{className:`flex min-h-[68px] items-stretch gap-1 p-1.5`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex min-w-0 flex-1 items-center gap-3 rounded-xl px-2.5 py-2 text-left transition-colors hover:bg-muted/45 active:bg-muted/65`,onClick:()=>N(e),title:`连接 ${r||e}`,children:[(0,K.jsx)(`span`,{className:`flex size-9 shrink-0 items-center justify-center rounded-xl bg-muted/45 text-muted-foreground`,children:(0,K.jsx)(ee,{className:`size-4`,"aria-hidden":`true`})}),(0,K.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`span`,{className:`truncate text-sm font-medium text-foreground`,children:r||`QuickForge 服务器`}),n?(0,K.jsx)(`span`,{className:`shrink-0 rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground`,children:`上次使用`}):null]}),(0,K.jsx)(`span`,{className:`mt-1 block truncate font-mono text-xs text-muted-foreground`,children:e})]}),(0,K.jsx)(F,{className:`size-4 shrink-0 text-muted-foreground/65`,"aria-hidden":`true`})]}),(0,K.jsx)(`button`,{type:`button`,className:`inline-flex w-10 shrink-0 items-center justify-center rounded-xl text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65`,onClick:()=>{_(i?null:e),i&&I()},"aria-label":`管理 ${r||e}`,title:`管理服务器`,"aria-expanded":i,children:i?(0,K.jsx)(z,{className:`size-4`,"aria-hidden":`true`}):(0,K.jsx)(oe,{className:`size-5`,"aria-hidden":`true`})})]}),i?(0,K.jsx)(`div`,{className:`border-t border-border bg-muted/30 px-3 py-3`,children:a?(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-xs font-medium text-muted-foreground`,htmlFor:`quickforge-mobile-alias-${e}`,children:`服务器别名`}),(0,K.jsx)(`input`,{id:`quickforge-mobile-alias-${e}`,autoFocus:!0,autoCapitalize:`none`,autoCorrect:`off`,spellCheck:!1,value:b,onChange:e=>x(e.target.value),onKeyDown:t=>{t.key===`Enter`&&L(e),t.key===`Escape`&&I()},placeholder:`例如:公司开发机`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),(0,K.jsxs)(`div`,{className:`mt-2.5 flex justify-end gap-2`,children:[(0,K.jsx)(`button`,{type:`button`,className:`inline-flex h-9 items-center justify-center rounded-xl px-3 text-sm text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground`,onClick:I,children:`取消`}),(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-9 items-center justify-center gap-1.5 rounded-xl bg-primary px-3.5 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85`,onClick:()=>L(e),children:[(0,K.jsx)(S,{className:`size-4`,"aria-hidden":`true`}),`保存`]})]})]}):(0,K.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-10 items-center justify-center gap-2 rounded-xl text-sm text-foreground/80 transition-colors hover:bg-muted/60`,onClick:()=>ie(e),children:[(0,K.jsx)(ae,{className:`size-4 text-muted-foreground`,"aria-hidden":`true`}),`编辑别名`]}),(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-10 items-center justify-center gap-2 rounded-xl text-sm text-foreground/80 transition-colors hover:bg-destructive/10 hover:text-destructive`,onClick:()=>w(e),children:[(0,K.jsx)(me,{className:`size-4 text-muted-foreground`,"aria-hidden":`true`}),`删除服务器`]})]})}):null]},e)})}),a?null:(0,K.jsxs)(`button`,{type:`button`,className:`mt-3 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 active:bg-muted/65`,onClick:ne,children:[(0,K.jsx)(o,{className:`size-4`,"aria-hidden":`true`}),`添加服务器`]}),m&&!a?(0,K.jsxs)(`p`,{className:`mt-2 flex items-center justify-center gap-1.5 text-sm text-muted-foreground`,role:`status`,children:[(0,K.jsx)(S,{className:`size-4`,"aria-hidden":`true`}),`服务器已保存`]}):null]}):null,a?(0,K.jsxs)(`section`,{className:t.urls.length>0?`mt-7`:``,"aria-labelledby":`quickforge-mobile-add-server`,children:[(0,K.jsxs)(`div`,{className:`mb-2.5 flex items-center justify-between px-1`,children:[(0,K.jsx)(`h2`,{id:`quickforge-mobile-add-server`,className:`text-xs font-medium text-muted-foreground`,children:t.urls.length>0?`添加服务器`:`添加第一台服务器`}),t.urls.length>0?(0,K.jsx)(`button`,{type:`button`,className:`rounded-lg px-2 py-1 text-xs text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground`,onClick:()=>{j(),s(!1)},children:`收起`}):null]}),(0,K.jsxs)(`form`,{className:`rounded-2xl border border-border bg-background p-5 shadow-quickforge`,onSubmit:M,children:[(0,K.jsxs)(`div`,{className:`mb-5 flex gap-2.5 rounded-xl bg-muted/30 px-3 py-2.5 text-xs leading-5 text-muted-foreground`,children:[(0,K.jsx)(ue,{className:`mt-0.5 size-4 shrink-0`,"aria-hidden":`true`}),(0,K.jsxs)(`p`,{children:[`仅支持 Tailnet 内的 `,(0,K.jsx)(`span`,{className:`font-mono text-foreground/75`,children:`.ts.net`}),` 或 `,(0,K.jsx)(`span`,{className:`font-mono text-foreground/75`,children:`100.64.0.0/10`}),` 地址,未填写端口时默认使用 5176。`]})]}),(0,K.jsx)(`label`,{className:`block text-sm font-medium`,htmlFor:`quickforge-mobile-server`,children:`服务器地址`}),(0,K.jsx)(`input`,{id:`quickforge-mobile-server`,autoCapitalize:`none`,autoCorrect:`off`,inputMode:`url`,spellCheck:!1,value:c,onChange:e=>{l(e.target.value),p(``),h(!1)},placeholder:`devbox.example.ts.net`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),te?(0,K.jsxs)(`p`,{className:`mt-2 break-all text-xs text-muted-foreground`,children:[`将连接到 `,(0,K.jsx)(`span`,{className:`font-mono text-foreground/70`,children:te})]}):(0,K.jsx)(`p`,{className:`mt-2 text-xs text-muted-foreground`,children:`请确保手机与服务器已登录同一个 Tailnet。`}),(0,K.jsxs)(`label`,{className:`mt-5 block text-sm font-medium`,htmlFor:`quickforge-mobile-server-alias`,children:[`服务器别名 `,(0,K.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`(可选)`})]}),(0,K.jsx)(`input`,{id:`quickforge-mobile-server-alias`,autoCapitalize:`none`,autoCorrect:`off`,spellCheck:!1,value:u,onChange:e=>{d(e.target.value),p(``),h(!1)},placeholder:`例如:公司开发机`,className:`mt-2 h-11 w-full rounded-xl border border-input bg-background px-3.5 text-sm outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground/60 focus:border-foreground/30 focus:shadow-quickforge`}),f?(0,K.jsx)(`p`,{className:`mt-3 text-sm text-destructive`,role:`alert`,children:f}):null,(0,K.jsxs)(`button`,{type:`submit`,className:`mt-5 inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85`,children:[`保存并连接`,(0,K.jsx)(E,{className:`size-4`,"aria-hidden":`true`})]}),(0,K.jsx)(`button`,{type:`button`,className:`mt-2 inline-flex h-10 w-full items-center justify-center rounded-xl text-sm text-muted-foreground transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65`,onClick:()=>re(!1),children:`仅保存,稍后连接`})]})]}):null]})]}),C?(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-end justify-center bg-black/35 p-4 pb-[max(1rem,env(safe-area-inset-bottom))] sm:items-center`,role:`presentation`,children:(0,K.jsxs)(`section`,{className:`w-full max-w-sm rounded-2xl border border-border bg-background p-5 shadow-xl`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`quickforge-mobile-delete-title`,children:[(0,K.jsx)(`h2`,{id:`quickforge-mobile-delete-title`,className:`text-base font-semibold`,children:`删除这台服务器?`}),(0,K.jsxs)(`p`,{className:`mt-2 break-all text-sm leading-6 text-muted-foreground`,children:[`“`,R,`”将从已保存列表中移除,之后仍可重新添加。`]}),(0,K.jsxs)(`div`,{className:`mt-5 grid grid-cols-2 gap-3`,children:[(0,K.jsx)(`button`,{type:`button`,className:`inline-flex h-11 items-center justify-center rounded-xl border border-border text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45`,onClick:()=>w(null),children:`取消`}),(0,K.jsx)(`button`,{type:`button`,className:`inline-flex h-11 items-center justify-center rounded-xl bg-destructive text-sm font-medium text-destructive-foreground transition-opacity hover:opacity-92 active:opacity-85`,onClick:()=>P(C),children:`删除`})]})]})}):null]})}var tp=`https://localhost/?connect=1&tab=cloud`,np=`http://127.0.0.1:18080/`;async function rp(){for(let e=0;e<3;e++){let t=new AbortController,n=window.setTimeout(()=>t.abort(),3e3);try{return await fetch(np,{mode:`no-cors`,cache:`no-store`,signal:t.signal}),window.clearTimeout(n),!0}catch{window.clearTimeout(n),e<2&&await new Promise(e=>setTimeout(e,700))}}return!1}function ip(){let[e,t]=(0,H.useState)(!1),[n,i]=(0,H.useState)(null),[a,o]=(0,H.useState)(!1),[s,c]=(0,H.useState)(0),[l,u]=(0,H.useState)(!1),d=(0,H.useRef)(!1),f=(0,H.useRef)(0),p=(0,H.useCallback)(async()=>{(await Wu({probe:rp})).status===`recovered`&&(d.current=!1,o(!1),i(null))},[]);if((0,H.useEffect)(()=>{let e=!0,n,r=()=>{d.current||(d.current=!0,o(!0))},a=t=>{e&&(i(t),t.state!==`connected`&&r(),t.state===`reconnecting`&&(f.current+=1,c(f.current)),t.state===`connected`&&d.current&&p())};return Gf.getState().then(t=>{if(e)return a(t),Gf.addListener(`remoteStateChanged`,a).then(e=>{n=e})}).catch(()=>{e&&t(!0)}),()=>{e=!1,n?.remove()}},[p]),(0,H.useEffect)(()=>{let e=()=>{document.visibilityState===`visible`&&d.current&&Gf.getState().then(e=>{e.state===`connected`&&d.current&&p()}).catch(()=>{})};return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[p]),!Gt()||e||!n||n.state===`connected`&&!a)return null;let m=n.state===`reconnecting`||n.state===`connecting`,h=n.state===`connected`&&a,g=async()=>{u(!0);try{await Gf.retry()}catch{}finally{u(!1)}},_=()=>{window.location.href=tp},v=`连接已断开`,y=`不会自动重连,请返回设备列表。`;m?y=`连接已断开,正在自动重连…(已重试 ${s} 次)`:h?(v=`正在恢复连接`,y=`连接已恢复,正在同步任务状态…`):n.state===`error`&&(v=`连接失败`,y=n.error||`隧道连接失败,请重试`,y.includes(`登录已过期`)&&(y=`${y},请重新登录`));let b=`inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-92 active:opacity-85 disabled:opacity-60`;return(0,K.jsx)(`div`,{className:`fixed inset-0 z-[90] flex items-center justify-center bg-background/80 p-6 backdrop-blur-sm`,children:(0,K.jsxs)(`div`,{className:`w-full max-w-sm rounded-2xl border border-border bg-background p-5 shadow-quickforge`,role:`status`,"aria-live":`polite`,children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-3.5`,children:[(0,K.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-xl border border-border bg-background shadow-quickforge`,children:m?(0,K.jsx)(B,{className:`size-5 animate-spin text-foreground/75`,"aria-hidden":`true`}):(0,K.jsx)(N,{className:`size-5 text-foreground/75`,"aria-hidden":`true`})}),(0,K.jsxs)(`div`,{className:`min-w-0 pt-0.5`,children:[(0,K.jsx)(`h2`,{className:`text-base font-semibold tracking-tight`,children:v}),(0,K.jsx)(`p`,{className:`mt-1 text-sm leading-5 text-muted-foreground`,children:y})]})]}),(0,K.jsxs)(`div`,{className:`mt-5 flex flex-col gap-2.5`,children:[m?(0,K.jsxs)(`button`,{type:`button`,className:b,onClick:()=>{g()},disabled:l,children:[l?(0,K.jsx)(B,{className:`size-4 animate-spin`,"aria-hidden":`true`}):(0,K.jsx)(r,{className:`size-4`,"aria-hidden":`true`}),`立即重试`]}):null,(0,K.jsx)(`button`,{type:`button`,className:m?`inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl border border-border text-sm font-medium text-foreground/80 transition-colors hover:bg-muted/45 hover:text-foreground active:bg-muted/65 disabled:opacity-60`:b,onClick:_,children:`返回设备列表`})]})]})})}var ap=`quickforge:system-notifications-enabled`,op=`quickforge:android-remote-notification-permission-requested:v1`,sp=`quickforge:system-notifications-recent:v1`,cp=`quickforge:open-session`,lp=1e4,up=100,dp=!1,fp=!1;function pp(){if(!(typeof window>`u`||!Me.isNativePlatform()))return window.QuickForgeBridge}function mp(){if(typeof window>`u`)return;let e=window;e.__quickforgeOpenSession||=e=>{yp(e)}}function hp(){let e=pp();if(!e?.setNotificationService)return;let t=window.location.origin;if(t)try{e.setNotificationService(Cp(),t)}catch(e){V.warn(`Failed to sync native notification service:`,e)}}mp();function gp(){if(typeof document>`u`||typeof window>`u`)return!1;let e=window;return document.body?.classList.contains(`quickforge-desktop-app`)||e.__quickforgeDesktopApp===!0}function _p(){return Me.isNativePlatform()&&Me.isPluginAvailable(`LocalNotifications`)}function vp(e){return`${W(e===`idle`?`taskCompleted`:e===`error`?`taskError`:e===`aborted`?`processAborted`:`taskRunning`)}. ${W(`systemNotificationOpenDetails`)}`}function yp(e){typeof window>`u`||(window.focus(),e&&window.dispatchEvent(new CustomEvent(`quickforge:open-session-from-settings`,{detail:{sessionId:e}})))}function bp(e){let t=0;for(let n=0;n<e.length;n+=1)t=(t<<5)-t+e.charCodeAt(n)|0;return(t>>>0)%2147483646+1}function xp(){if(typeof localStorage>`u`)return{};try{let e=JSON.parse(localStorage.getItem(sp)||`{}`);return!e||typeof e!=`object`||Array.isArray(e)?{}:Object.fromEntries(Object.entries(e).filter(e=>typeof e[1]==`number`&&Number.isFinite(e[1])))}catch{return{}}}function Sp(e){if(typeof localStorage>`u`)return!0;let t=Date.now(),n=xp(),r=n[e];if(typeof r==`number`&&t-r<lp)return!1;let i=Object.entries({...n,[e]:t}).filter(([,e])=>t-e<lp).sort((e,t)=>t[1]-e[1]).slice(0,up);try{localStorage.setItem(sp,JSON.stringify(Object.fromEntries(i)))}catch{}return!0}function Cp(){if(typeof localStorage>`u`)return!1;try{return localStorage.getItem(ap)===`1`}catch{return!1}}function wp(e){if(!(typeof localStorage>`u`)){try{e?localStorage.setItem(ap,`1`):localStorage.removeItem(ap)}catch{}hp()}}function Tp(){if(!(typeof window>`u`||typeof navigator>`u`)&&!(Me.isNativePlatform()||!/Android/i.test(navigator.userAgent))&&!(!Gt()||!window.isSecureContext)&&!(typeof Notification>`u`||!navigator.serviceWorker)&&!(Notification.permission!==`default`||typeof localStorage>`u`)){try{if(localStorage.getItem(op))return;localStorage.setItem(op,`1`)}catch{return}Dp()}}async function Ep(){try{if(_p()){let{LocalNotifications:e}=await Xe(async()=>{let{LocalNotifications:e}=await import(`./esm-sdsK6gaB.js`);return{LocalNotifications:e}},__vite__mapDeps([0,1,2,3])),t=await e.checkPermissions();return t.display===`granted`?`granted`:t.display===`prompt`||t.display===`prompt-with-rationale`?`prompt`:`denied`}return gp()||typeof Notification>`u`?`unsupported`:Notification.permission===`granted`?`granted`:Notification.permission===`denied`?`denied`:`prompt`}catch(e){return V.warn(`Failed to check system notification permission:`,e),`unsupported`}}async function Dp(){try{let e;if(_p()){let{LocalNotifications:t}=await Xe(async()=>{let{LocalNotifications:e}=await import(`./esm-sdsK6gaB.js`);return{LocalNotifications:e}},__vite__mapDeps([0,1,2,3]));e=(await t.requestPermissions()).display===`granted`?`granted`:`denied`,await Op()}else if(!gp()&&typeof Notification<`u`){let t=await Notification.requestPermission();e=t===`granted`?`granted`:t===`denied`?`denied`:`prompt`}else e=`unsupported`;return wp(e===`granted`),e}catch(e){return V.warn(`Failed to request system notification permission:`,e),wp(!1),`denied`}}async function Op(){if(hp(),!fp&&typeof navigator<`u`&&navigator.serviceWorker&&(fp=!0,navigator.serviceWorker.addEventListener(`message`,e=>{let t=e.data;t?.type===cp&&yp(typeof t.sessionId==`string`?t.sessionId:void 0)})),!(!_p()||dp)){dp=!0;try{let{LocalNotifications:e}=await Xe(async()=>{let{LocalNotifications:e}=await import(`./esm-sdsK6gaB.js`);return{LocalNotifications:e}},__vite__mapDeps([0,1,2,3]));await e.addListener(`localNotificationActionPerformed`,e=>{let t=e.notification.extra?.sessionId;yp(typeof t==`string`?t:void 0)})}catch(e){dp=!1,V.warn(`Failed to initialize native notification listener:`,e)}}}async function kp(e){if(!Cp()||!e.force&&e.status===`running`&&typeof document<`u`&&document.visibilityState===`visible`&&document.hasFocus())return!1;try{if(await Ep()!==`granted`||!Sp(e.key))return!1;let t=vp(e.status);if(_p()){let{LocalNotifications:n}=await Xe(async()=>{let{LocalNotifications:e}=await import(`./esm-sdsK6gaB.js`);return{LocalNotifications:e}},__vite__mapDeps([0,1,2,3]));return await Op(),await n.schedule({notifications:[{id:bp(e.key),title:e.title,body:t,extra:{sessionId:e.sessionId}}]}),!0}if(typeof Notification>`u`)return!1;let n=typeof navigator<`u`&&/Android/i.test(navigator.userAgent);if(typeof navigator<`u`&&navigator.serviceWorker)try{let n=await navigator.serviceWorker.getRegistration();if(n?.showNotification)return await n.showNotification(e.title,{body:t,icon:`/pwa-icon-192.png`,tag:e.key,data:{sessionId:e.sessionId}}),!0}catch(e){V.warn(`Failed to show Service Worker notification:`,e)}if(n)return!1;let r=new Notification(e.title,{body:t,icon:`/pwa-icon-192.png`,tag:e.key});return r.onclick=()=>{r.close(),yp(e.sessionId)},!0}catch(e){return V.warn(`Failed to show system notification:`,e),!1}}var Ap=Object.freeze({modelSelection:!0,thinkingSelection:!0,clientApiKeyCheck:!0,planMode:!0,accessMode:!0,commands:!0,capabilitySuggestions:!0,contextUsage:!0,compaction:!0,rollback:!0,retry:!0,forkFromMessage:!0,forkSession:!1,harnessConfig:!1,attachments:!0}),jp=Object.freeze({modelSelection:!1,thinkingSelection:!1,clientApiKeyCheck:!1,planMode:!1,accessMode:!1,commands:!1,capabilitySuggestions:!1,contextUsage:!1,compaction:!1,rollback:!1,retry:!1,forkFromMessage:!1,forkSession:!0,harnessConfig:!0,attachments:!0});function Mp(e){return e===`opencode`?jp:Ap}function Np(e,t){return!t.readOnly&&!t.disableFork?e:{...e,rollback:e.rollback&&!t.readOnly,retry:e.retry&&!t.readOnly,forkFromMessage:e.forkFromMessage&&!t.readOnly&&!t.disableFork,forkSession:e.forkSession&&!t.readOnly&&!t.disableFork,harnessConfig:e.harnessConfig&&!t.readOnly,attachments:e.attachments&&!t.readOnly,planMode:e.planMode&&!t.readOnly,accessMode:e.accessMode&&!t.readOnly,commands:e.commands&&!t.readOnly,capabilitySuggestions:e.capabilitySuggestions&&!t.readOnly}}function Pp(e,t,n){let r=String(t??``).trim().length>0,i=(n?.length??0)>0;return!e.attachments&&i?!1:r||i}var Fp=(0,H.lazy)(()=>Xe(()=>import(`./ChatPanelHost-Dul1ahKj.js`).then(e=>({default:e.ChatPanelHost})),__vite__mapDeps([4,2,5,1,6,7,8,9,10,11,12]))),Ip=(0,H.lazy)(()=>Xe(()=>import(`./SharedConversationPage-BK9XJnEe.js`).then(e=>({default:e.SharedConversationPage})),__vite__mapDeps([13,2,1,5,6,7,8,4,9,10,11,12,14]))),Lp=(0,H.lazy)(()=>Xe(()=>import(`./WorkspaceInspector-MNBLIKMn.js`).then(e=>({default:e.WorkspaceInspector})),__vite__mapDeps([15,2,16,7,8,17,18,19,12,1]))),Rp=(0,H.lazy)(()=>Xe(()=>import(`./TerminalDock-CL7HU9DI.js`).then(e=>({default:e.TerminalDock})),__vite__mapDeps([17,2,18,19,7,8]))),zp=(0,H.lazy)(()=>Xe(()=>import(`./SettingsWorkspacePage-BE2T4d3P.js`).then(e=>({default:e.SettingsWorkspacePage})),__vite__mapDeps([20,2,1,5,6,7,8,10,11]))),Bp=`quickforge:auto-preview-seen-signatures`,Vp=200,Hp=`https://github.com/shawnstack/quickforge/releases/latest`,Up=1350,Wp=280,Gp=280;function Kp(){if(typeof window>`u`)return new Set;try{let e=window.sessionStorage.getItem(Bp),t=e?JSON.parse(e):void 0;return Array.isArray(t)?new Set(t.filter(e=>typeof e==`string`&&e.length>0)):new Set}catch{return new Set}}function qp(e){return Kp().has(e)}function Jp(e){if(!(typeof window>`u`))try{let t=[...Kp(),e].slice(-Vp);window.sessionStorage.setItem(Bp,JSON.stringify(t))}catch{}}function Yp(){return(0,K.jsx)(`div`,{className:`flex min-h-0 flex-1 items-center justify-center text-sm text-muted-foreground`,children:W(`loading`)})}function Xp(){return null}function Zp({exiting:e=!1}){let t=W(`loadingChatWorkspace`);return(0,K.jsxs)(`div`,{className:G(`quickforge-startup-splash`,e&&`quickforge-startup-splash-exit`),role:`status`,"aria-label":t,children:[(0,K.jsxs)(`svg`,{className:`quickforge-startup-splash-icon`,viewBox:`0 0 64 64`,fill:`none`,"aria-hidden":`true`,children:[(0,K.jsxs)(`defs`,{children:[(0,K.jsxs)(`linearGradient`,{id:`startupIconStroke`,x1:`0`,y1:`0`,x2:`1`,y2:`1`,children:[(0,K.jsx)(`stop`,{offset:`0`,stopColor:`#9ca3af`}),(0,K.jsx)(`stop`,{offset:`1`,stopColor:`#4b5563`})]}),(0,K.jsxs)(`linearGradient`,{id:`startupIconBolt`,x1:`0`,y1:`0`,x2:`1`,y2:`1`,children:[(0,K.jsx)(`stop`,{offset:`0`,stopColor:`#374151`}),(0,K.jsx)(`stop`,{offset:`1`,stopColor:`#0f172a`})]})]}),(0,K.jsx)(`polygon`,{className:`quickforge-startup-splash-outline`,points:`32,6 52.78,18 52.78,42 32,54 11.22,42 11.22,18`,fill:`none`,stroke:`url(#startupIconStroke)`,strokeWidth:`4.5`,strokeLinejoin:`round`}),(0,K.jsx)(`polygon`,{className:`quickforge-startup-splash-outline-final`,points:`32,6 52.78,18 52.78,42 32,54 11.22,42 11.22,18`,fill:`none`,stroke:`url(#startupIconStroke)`,strokeWidth:`4.5`,strokeLinejoin:`round`}),(0,K.jsx)(`path`,{className:`quickforge-startup-splash-bolt`,d:`M37.2 13 L22 34 L30.6 34 L26.8 50 L42.8 26 L33.8 26 Z`,fill:`url(#startupIconBolt)`}),(0,K.jsx)(`path`,{className:`quickforge-startup-splash-bolt-trace`,d:`M37.2 13 L22 34 L30.6 34 L26.8 50 L42.8 26 L33.8 26 Z`,fill:`none`,stroke:`#f8fafc`,strokeWidth:`2.5`,strokeLinecap:`round`,strokeLinejoin:`round`}),(0,K.jsx)(`path`,{className:`quickforge-startup-splash-bolt-highlight`,d:`M37.2 13 L22 34 L30.6 34 L33.8 26 Z`,fill:`#e5e7eb`})]}),(0,K.jsx)(`span`,{className:`sr-only`,children:t})]})}function Qp({exiting:e=!1}){let t=W(`loadingConversation`);return(0,K.jsxs)(`div`,{className:G(`quickforge-conversation-loading`,e&&`quickforge-conversation-loading-exit`),role:`status`,"aria-live":`polite`,"aria-label":t,children:[(0,K.jsxs)(`div`,{className:`quickforge-conversation-loading-status`,"aria-hidden":`true`,children:[(0,K.jsx)(`span`,{children:t}),(0,K.jsxs)(`span`,{className:`quickforge-conversation-loading-dots`,children:[(0,K.jsx)(`span`,{children:`•`}),(0,K.jsx)(`span`,{children:`•`}),(0,K.jsx)(`span`,{children:`•`})]})]}),(0,K.jsx)(`div`,{className:`quickforge-conversation-loading-track`,"aria-hidden":`true`,children:(0,K.jsx)(`div`,{className:`quickforge-conversation-loading-runner`})}),(0,K.jsx)(`span`,{className:`quickforge-conversation-loading-helper`,"aria-hidden":`true`,children:W(`loadingConversationPreparing`)})]})}function $p(e){return e===`idle`||e===`running`||e===`error`||e===`aborted`}function em(e){return e.type===`scheduled_task_notification`}function tm(e){return e.type===`scheduled_task_started`}function nm(e){return e.workspace?.kind===`project`&&typeof e.workspace.id==`string`&&e.workspace.id.length>0?e.workspace.id:typeof e.projectId==`string`&&e.projectId.length>0?e.projectId:void 0}function rm(){let e=Gt(),t=Kt(),n=Wt(),i=Ou(!0),o=n?window.location.origin:void 0,s=n?Ht():void 0,c=()=>qt(t?`cloud`:`servers`),l=(0,H.useRef)(null),f=(0,H.useRef)(Yn(Hn)),p=(0,H.useRef)(`default`),m=(0,H.useRef)(void 0),h=(0,H.useRef)(void 0),{activeProject:g,projects:_,defaultWorkspace:v,expandedProjectIds:x,selectingProject:S,projectPickerOpen:w,loadProject:T,switchActiveProject:E,handleSelectProjectPath:O,selectProjectDirectory:k,setProjectPickerOpen:ee,toggleProjectExpanded:te,toggleAllProjectsExpanded:j,reorderProjects:ne,setActiveProject:re,setProjects:M,setExpandedProjectIds:N}=rc(),{agentAccessMode:P,setAgentAccessMode:F,initialize:I}=ic(),L=Ru(),{setArtifactPreviewOpen:z,setWorkspaceInspectorOpen:se,setWorkspaceInspectorRequest:ce}=L,[le,ue]=(0,H.useState)(!1),[B,de]=(0,H.useState)(),[fe,me]=(0,H.useState)(!1),[he,ge]=(0,H.useState)(null),[ve,ye]=(0,H.useState)(!1),[be,xe]=(0,H.useState)(!1),[Se,we]=(0,H.useState)({artifacts:[]}),[Te,Ee]=(0,H.useState)(nd),[De,Oe]=(0,H.useState)(id),[ke,Ae]=(0,H.useState)(!1),je=(0,H.useRef)(!1),Me=(0,H.useRef)(``),[Ne,Pe]=(0,H.useState)(),[Fe,Ie]=(0,H.useState)(),Le=(0,H.useRef)(0),Re=(0,H.useRef)(void 0),[ze,Be]=(0,H.useState)(!1),[Ve,He]=(0,H.useState)(!1),[Ue,We]=(0,H.useState)(!1),[Ge,Ke]=(0,H.useState)(!1),[qe,Je]=(0,H.useState)(()=>new Set),Ye=(0,H.useRef)(0),Xe=(0,H.useRef)(0),Ze=(0,H.useRef)(0),Qe=(0,H.useRef)(0),$e=(0,H.useRef)(void 0),tt=(0,H.useRef)(void 0),[nt,rt]=(0,H.useState)(null),[it,at]=(0,H.useState)(!1),[ot,st]=(0,H.useState)(!1),[ct,lt]=(0,H.useState)(),ut=(0,H.useRef)(void 0),[dt,ft]=(0,H.useState)(),{toasts:pt,handleTaskComplete:mt,addToast:U,dismissToast:ht}=ll(),gt=(0,H.useCallback)((e,t,n)=>{mt(e,t,n),kp({key:`agent:${e}:${n}`,sessionId:e,title:t,status:n})},[mt]),_t=(0,H.useCallback)(()=>void 0,[]),vt=(0,H.useCallback)(()=>me(!1),[]),yt=(0,H.useCallback)(()=>{me(!1),window.open(Hp,`_blank`,`noopener,noreferrer`)},[]),bt=(0,H.useCallback)(()=>{me(!1),window.open(`quickforge://exit`,`_blank`,`noopener,noreferrer`)},[]);(0,H.useEffect)(()=>{rd(Te)},[Te]),(0,H.useEffect)(()=>{ad(De)},[De]);let xt=(0,H.useRef)(null),St=(0,H.useRef)(null),Ct=(0,H.useRef)(null),{allLoadedSessions:wt,pinnedSessions:Tt,pinnedHasMore:Et,pinnedLoading:Dt,globalSessions:Ot,sessionsForProject:kt,globalHasMore:At,projectTimelineSessions:jt,projectTimelineHasMore:Mt,projectTimelineLoading:Nt,projectHasMore:Pt,globalLoading:Ft,projectLoading:It,projectLoaded:Lt,loadGlobalSessions:Rt,loadProjectSessions:zt,refreshSessions:Bt,upsertSessionMetadata:Vt,updateSessionTitle:Ut,loadMorePinned:Jt,loadMoreGlobal:Xt,loadMoreProject:Qt,loadMoreProjectTimeline:$t}=cl({backendRef:Ct,expandedProjectIds:x,externalProjectIds:qe,viewMode:Te,sortMode:De,onBroadcastSessionsChanged:(0,H.useCallback)(()=>xt.current?.notifySessionsChanged(),[])}),en=dc({onSessionsChanged:()=>{Bt()},onProjectsChanged:()=>{T(!0)},onSettingsChanged:e=>{Bt(),e?.defaultHarness&&St.current?.(e.defaultHarness).catch(e=>{V.error(`Failed to apply the cross-tab default Harness change:`,e)})}});(0,H.useEffect)(()=>{p.current=P},[P]),(0,H.useEffect)(()=>{m.current=g},[g]),(0,H.useEffect)(()=>{h.current=v},[v]),(0,H.useEffect)(()=>{xt.current=en},[en]),(0,H.useEffect)(()=>{Op()},[]),(0,H.useEffect)(()=>{let e=window.setTimeout(()=>at(!0),Up);return()=>window.clearTimeout(e)},[]);let tn=(0,H.useCallback)((e,t)=>{Pe(n=>n?.sessionId===e&&Fr(n,t)?n:{sessionId:e,...t})},[]),J=el({storageRef:l,activeModelRef:f,agentAccessModeRef:p,activeProjectRef:m,defaultWorkspaceRef:h,setAgentAccessMode:F,switchActiveProject:E,sessions:wt,refreshSessions:Bt,updateSessionTitle:Ut,loadCloudModels:i.loadCloudModels,onTaskComplete:gt});(0,H.useEffect)(()=>{let e=J.loadingSessionId;if(!e||ut.current===e)return;let t=window.setTimeout(()=>{ut.current!==e&&($e.current?.(),$e.current=void 0,Qe.current+=1,ft(void 0),ut.current=e,lt(e))},0);return()=>window.clearTimeout(t)},[J.loadingSessionId]),(0,H.useEffect)(()=>{let e=ut.current;if(!e||dt!==e)return;let t=window.setTimeout(()=>{ut.current===e&&(ut.current=void 0,lt(void 0))},Gp);return()=>window.clearTimeout(t)},[J.loadingSessionId,dt,ct]);let{createAgent:rn,startDeferredSession:an,applyDefaultHarnessToBlankSession:on,loadSession:sn,syncSessionUI:cn,setCurrentAgentMessages:ln,updateCurrentAgentModel:un,setChatPanelRevision:dn,setCurrentTitleRef:fn,agentRef:Y,taskMapRef:pn,currentSessionIdRef:mn,currentChatScopeRef:hn}=J;(0,H.useEffect)(()=>{St.current=on},[on]),(0,H.useEffect)(()=>{Re.current=J.currentToolProject?.id,Le.current+=1,Ze.current+=1},[J.currentToolProject?.id]);let gn=(0,H.useCallback)(e=>{if(!e||e===mn.current)return;$e.current?.(),$e.current=void 0;let t=Qe.current+1;return Qe.current=t,ft(void 0),ut.current=e,lt(e),t},[mn]),_n=(0,H.useCallback)((e,t)=>{t!==void 0&&Qe.current!==t||ut.current===e&&($e.current?.(),$e.current=void 0,Qe.current+=1,ut.current=void 0,ft(void 0),lt(void 0))},[]),vn=(0,H.useCallback)(e=>{ut.current===e&&($e.current=void 0,ft(e))},[]),yn=(0,H.useCallback)((e,t)=>{V.error(`Failed to render conversation:`,t),_n(e),U({sessionId:e,title:W(`conversationLoadFailed`),status:`error`})},[U,_n]),bn=(0,H.useCallback)((e,t)=>{let n=gn(e);if(n===void 0){$e.current?.(),$e.current=void 0,Qe.current+=1,t();return}$e.current=Vu(()=>{$e.current=void 0,!(Qe.current!==n||ut.current!==e)&&t().then(t=>{t||_n(e,n)})})},[gn,_n]);(0,H.useEffect)(()=>()=>{$e.current?.()},[]);let xn=(0,H.useCallback)(e=>{e&&bn(e,()=>sn(e))},[sn,bn]);(0,H.useEffect)(()=>{let e=e=>{let t=e.detail;typeof t?.sessionId==`string`&&xn(t.sessionId)};return window.addEventListener(`quickforge:open-session-from-settings`,e),()=>window.removeEventListener(`quickforge:open-session-from-settings`,e)},[xn]);let Sn=(0,H.useCallback)(e=>{de(t=>t?.id===e?void 0:t)},[]),X=(0,H.useCallback)(e=>{Xe.current+=1,ce({...e,id:Xe.current}),se(!0)},[se,ce]),Cn=(0,H.useCallback)(e=>{ce(t=>t?.id===e?void 0:t)},[ce]),wn=(0,H.useCallback)(()=>{let e=J.currentToolProject?.id;e&&(z(!1),X({projectId:e,kind:`review`,view:`changes`}))},[J.currentToolProject?.id,X,z]),Tn=(0,H.useCallback)(async()=>{let e=J.currentToolProject?.id,t=Le.current+1;if(Le.current=t,!e){Ie(void 0);return}try{let n=await bd(e);return sd({projectId:e,requestId:t},Re.current,Le.current)?(Ie(n),n):void 0}catch(n){if(!sd({projectId:e,requestId:t},Re.current,Le.current))return;V.warn(`Failed to refresh title git status:`,n),Ie(void 0);return}},[J.currentToolProject?.id]);(0,H.useEffect)(()=>{let e=window.setTimeout(()=>{Tn()},0);return()=>window.clearTimeout(e)},[Tn]),(0,H.useEffect)(()=>{let e,t=jc(t=>{ld(t,mn.current,Re.current)&&(e!==void 0&&window.clearTimeout(e),e=window.setTimeout(()=>{e=void 0,Tn()},400))});return()=>{e!==void 0&&window.clearTimeout(e),t()}},[J.currentSessionId,mn,Tn]);let En=(0,H.useCallback)(async e=>{let t=J.currentToolProject?.id;if(!t)return;let n=Le.current+1;Le.current=n;try{let r=await kd(t,e);if(!sd({projectId:t,requestId:n},Re.current,Le.current))return;Ie(r),Be(!1),U({sessionId:J.currentSessionId??``,title:W(`gitBranchSwitched`),status:`idle`,message:e})}catch(e){if(!sd({projectId:t,requestId:n},Re.current,Le.current))return;throw V.error(`Failed to checkout git branch:`,e),$(e instanceof Error?e.message:W(`gitCheckoutFailed`)),e}},[U,J.currentSessionId,J.currentToolProject?.id]),Dn=(0,H.useCallback)(e=>{Ie(e),Be(!1),U({sessionId:J.currentSessionId??``,title:W(`gitBranchCreated`),status:`idle`,message:e.branch??``})},[U,J.currentSessionId]),On=(0,H.useCallback)(e=>{Ie(e),U({sessionId:J.currentSessionId??``,title:W(`gitOperationCompleted`),status:`idle`,message:e.branch??``})},[U,J.currentSessionId]),kn=(0,H.useCallback)(async e=>{let t=J.currentToolProject?.id;if(!t){U({sessionId:J.currentSessionId??``,title:`无法打开文件`,status:`error`,message:`当前对话没有关联项目。`});return}let n=Ze.current+1;Ze.current=n;try{let r=await vd(t,e);if(!sd({projectId:t,requestId:n},Re.current,Ze.current))return;X({projectId:t,kind:`reader`,path:r.relativePath})}catch(e){if(!sd({projectId:t,requestId:n},Re.current,Ze.current))return;let r=e instanceof Error?e.message:`打开文件失败`;U({sessionId:J.currentSessionId??``,title:`无法打开文件`,status:`error`,message:r})}},[U,J.currentSessionId,J.currentToolProject?.id,X]),An=(0,H.useCallback)((e,t,n)=>{let r=J.currentToolProject,i=yf(t,n);if(!(!r||r.id!==e||!i)){if(z(!1),i===`reader`){X({projectId:e,kind:`reader`,path:t});return}X({projectId:e,kind:`browser`,url:bf(r.path,t)})}},[J.currentToolProject,X,z]);(0,H.useEffect)(()=>{let e=J.currentToolProject,t=e?.id;if(!t||Se.projectId!==t||Se.sessionId!==J.currentSessionId)return;let n=Tf(Se.artifacts);if(!n?.path)return;let r=n.toolCallIds[n.toolCallIds.length-1],i=`${t}:${n.path}:${n.defaultPreview?`default`:n.explicit?`explicit`:`inferred`}:${r??``}`;if(i!==Me.current){if(qp(i)){Me.current=i;return}Me.current=i,Jp(i),queueMicrotask(()=>{let r=yf(n.path,n.kind);r&&(z(!1),X(r===`reader`?{projectId:t,kind:`reader`,path:n.path}:{projectId:t,kind:`browser`,url:bf(e.path,n.path)}))})}},[J.currentSessionId,J.currentToolProject,Se,X,z]),(0,H.useEffect)(()=>{Me.current=``,z(!1),ce(void 0)},[J.currentToolProject?.id,z,ce]),(0,H.useEffect)(()=>{if(!An)return;let e=e=>{let t=e.detail,n=J.currentToolProject?.id;n&&t&&typeof t.path==`string`&&An(n,t.path,t.kind)};return window.addEventListener(`quickforge:preview-artifact`,e),()=>window.removeEventListener(`quickforge:preview-artifact`,e)},[J.currentToolProject?.id,An]),(0,H.useEffect)(()=>{let e=e=>{let t=e.detail;if(!t||typeof t.waitUntil!=`function`)return;let n=(async()=>{let e=new Set,t=Y.current;t instanceof Mc&&e.add(t);for(let t of pn.current.values())t.agent instanceof Mc&&e.add(t.agent);await Promise.all([...e].map(async e=>{try{let t=await fetch(`/api/agents/${encodeURIComponent(e.sessionId)}/state`,{cache:`no-store`});if(!t.ok)throw Error(`HTTP ${t.status}`);await e.syncState()}catch(e){throw V.error(`Tunnel recovery failed to sync agent state:`,e),e}})),await Bt({broadcast:!0})})();t.waitUntil(n)};return window.addEventListener(Hu,e),()=>window.removeEventListener(Hu,e)},[Y,pn,Bt]),(0,H.useEffect)(()=>jc(e=>{if(tm(e)){let t=typeof e.projectId==`string`?e.projectId:void 0;t&&(N(e=>{let n=new Set(e);return n.add(t),n}),zt(t,0)),Bt({broadcast:!0});return}if(e.type===`session_created`){let t=e.metadata;t?.id&&Vt(t)}else if(e.type===`title_updated`){let t=typeof e.sessionId==`string`?e.sessionId:void 0,n=typeof e.title==`string`?e.title:void 0;t&&n&&Ut(t,n)}else (e.type===`agent_end`||e.type===`session_forked`)&&Bt({broadcast:!0});if(!em(e))return;let t=typeof e.sessionId==`string`?e.sessionId:void 0,n=typeof e.title==`string`?e.title:W(`scheduledTasks`),r=$p(e.status)?e.status:`idle`,i=typeof e.message==`string`?e.message:void 0;U({sessionId:t??``,title:n,status:r,message:i});let a=typeof e.runId==`string`?e.runId:void 0;kp({key:a?`scheduled:${a}`:`scheduled:${t??n}:${r}`,sessionId:t,title:n,status:r})}),[U,zt,Bt,N,Ut,Vt]);let{ready:jn,startupError:Mn,retryBootstrap:Nn}=zl({storageRef:l,backendRef:Ct,activeModelRef:f,agentAccessModeRef:p,taskMapRef:pn,refreshSessions:Bt,loadProject:T,initAgentAccessMode:I,createAgent:rn,loadSession:sn,loadCloudModels:i.loadCloudModels,setNeedsModelSetup:ue,onStorageReady:rt}),Pn=Yl(l,jn),In=jn&&it&&!!(J.agent||le);(0,H.useEffect)(()=>{if(!In)return;let e=window.setTimeout(()=>st(!0),Wp);return()=>window.clearTimeout(e)},[In]),(0,H.useEffect)(()=>{if(!jn)return;let e=new EventSource(`/api/channels/events`),t=e=>{try{let t=JSON.parse(e.data);if(t.type!==`sessions-changed`||typeof t.sessionId!=`string`)return;let n=nm(t);n&&Je(e=>e.has(n)?e:new Set([...e,n])),t.metadata?.id===t.sessionId?Vt(t.metadata):n?zt(n,0):Rt(0);let r=Y.current;t.sessionId===mn.current&&r instanceof Mc&&r.syncState()}catch{}};return e.addEventListener(`sessions-changed`,t),()=>{e.removeEventListener(`sessions-changed`,t),e.close()}},[Y,mn,Rt,zt,jn,Vt]),(0,H.useEffect)(()=>{if(jn)for(let e of x)!Lt(e)&&!It(e)&&zt(e,0)},[jn,x,Lt,It,zt]);let{startNewGlobalChat:Ln,startNewProjectChat:Rn,rollbackFromMessage:zn,retryFromMessage:Bn,copyAnswer:Vn,forkFromMessage:Un,forkCurrentSession:Wn}=Au({storageRef:l,activeModelRef:f,activeProjectRef:m,currentChatScopeRef:hn,currentSessionIdRef:mn,taskMapRef:pn,agentRef:Y,createAgent:rn,startDeferredSession:an,syncSessionUI:cn,setCurrentAgentMessages:ln,setChatPanelRevision:dn,refreshSessions:Bt,needsModelSetup:le,setNeedsModelSetup:ue,switchActiveProject:E,closeWorkspacePage:_t,setRestoredDraft:de}),{deleteProjectInline:Gn}=ju({activeProjectRef:m,refreshSessions:Bt,notifyProjectsChanged:en.notifyProjectsChanged,setActiveProject:re,setProjects:M,setExpandedProjectIds:N,setChatPanelRevision:dn});(0,H.useEffect)(()=>{let e=od({ready:jn,currentToolProjectId:J.currentToolProject?.id,projects:_,activeProject:g,recoveringProjectId:tt.current});if(e.type===`none`){let e=J.currentToolProject?.id;tt.current&&tt.current!==e&&(tt.current=void 0);return}tt.current=e.deletedProjectId,we({artifacts:[]}),ce(void 0),z(!1),ge(null),ye(!1),Ze.current+=1,an(e.type===`project`?{scope:`project`,project:e.project}:{scope:`global`}).catch(e=>{tt.current=void 0,V.error(`Failed to recover after the current project was deleted:`,e)})},[g,J.currentToolProject?.id,_,jn,z,ce,an]);let{setAccessMode:Kn}=Lu({storageRef:l,agentAccessModeRef:p,setAgentAccessMode:F,agentRef:Y,setChatPanelRevision:dn,notifySettingsChanged:en.notifySettingsChanged}),qn=(0,H.useCallback)(async e=>{let t=Y.current;if(!t)throw Error(W(`toolApprovalFailed`));try{await t.approveToolCall(e)}catch(e){throw V.error(`Failed to approve tool call:`,e),e instanceof Error?e:Error(W(`toolApprovalFailed`))}},[Y]),Jn=(0,H.useCallback)(async e=>{let t=Y.current;if(!t)throw Error(W(`toolApprovalFailed`));try{await t.rejectToolCall(e)}catch(e){throw V.error(`Failed to reject tool call:`,e),e instanceof Error?e:Error(W(`toolApprovalFailed`))}},[Y]),Xn=(0,H.useCallback)(async e=>{let t=Y.current;if(!t?.approveAutoCompact)throw Error(W(`toolApprovalFailed`));await t.approveAutoCompact(e)},[Y]),Zn=(0,H.useCallback)(async e=>{let t=Y.current;if(!t?.rejectAutoCompact)throw Error(W(`toolApprovalFailed`));await t.rejectAutoCompact(e)},[Y]),{loadSession:Qn,renameSession:$n,togglePinSession:er,archiveSession:tr,startNewGlobalSession:nr}=Fu({storageRef:l,taskMapRef:pn,currentSessionIdRef:mn,loadAgentSession:sn,setCurrentTitleRef:fn,refreshSessions:Bt,updateSessionTitle:Ut,closeWorkspacePage:_t,startNewGlobalChat:Ln}),rr=(0,H.useCallback)(e=>{bn(e,()=>Qn(e))},[Qn,bn]),ir=(0,H.useCallback)((e,t)=>{L.setSettingsInitialTab(e),L.setSettingsCustomProvider(t),L.setSettingsDialogOpen(!0),L.setMobileSidebarOpen(!1)},[L]),{activateConfiguredModel:ar,openModelSettings:or,openDefaultOptionsSettings:sr,openAboutSettings:cr,activateLiteLlmExampleModel:lr,openCustomModelSelector:ur}=su({storageRef:l,activeModelRef:f,agentRef:Y,createAgent:rn,updateCurrentAgentModel:un,setChatPanelRevision:dn,setNeedsModelSetup:ue,setRestoredDraft:de,notifySettingsChanged:en.notifySettingsChanged,openSettingsPage:ir,loadCloudModels:i.loadCloudModels}),dr=(0,H.useCallback)(()=>{L.setSettingsDialogOpen(!1),L.setSettingsCustomProvider(void 0),(le||!Y.current)&&ar().catch(e=>V.error(`Failed to activate configured model:`,e))},[ar,Y,le,L]),fr=(0,H.useCallback)(()=>{me(!1),cr()},[cr]),pr=(0,H.useMemo)(()=>wt,[wt]),mr=(0,H.useMemo)(()=>{if(J.currentSessionId)return pr.find(e=>e.id===J.currentSessionId)},[J.currentSessionId,pr]),hr=!!mr?.pinnedAt,gr=Bu(pr),_r=(0,H.useCallback)(e=>J.taskStatuses[e.id]??gr[e.id]??e.taskStatus??`idle`,[J.taskStatuses,gr]);(0,H.useEffect)(()=>{if(fe)return window.addEventListener(`click`,vt),window.addEventListener(`blur`,vt),()=>{window.removeEventListener(`click`,vt),window.removeEventListener(`blur`,vt)}},[vt,fe]),(0,H.useEffect)(()=>{if(!L.conversationMenuOpen)return;let e=()=>L.setConversationMenuOpen(!1),t=t=>{t.key===`Escape`&&e()};return window.addEventListener(`click`,e),window.addEventListener(`blur`,e),window.addEventListener(`resize`,e),window.addEventListener(`orientationchange`,e),document.addEventListener(`keydown`,t),()=>{window.removeEventListener(`click`,e),window.removeEventListener(`blur`,e),window.removeEventListener(`resize`,e),window.removeEventListener(`orientationchange`,e),document.removeEventListener(`keydown`,t)}},[L,L.conversationMenuOpen]),(0,H.useEffect)(()=>{if(!ze)return;let e=()=>Be(!1);return window.addEventListener(`click`,e),window.addEventListener(`blur`,e),()=>{window.removeEventListener(`click`,e),window.removeEventListener(`blur`,e)}},[ze]),(0,H.useEffect)(()=>{let t=t=>{if(e){$(`远程客户端不能使用服务端终端`);return}let n=t.detail,r=typeof n?.command==`string`?n.command.trim():``;r&&(async()=>{(n?.confirm||n?.dangerous)&&!await $c({title:W(`confirmExecuteCommandTitle`),description:n?.dangerous?W(`confirmExecuteDangerousCommand`):W(`confirmExecuteMultipleCommands`),confirmLabel:W(`executeInTerminal`),cancelLabel:W(`cancel`),variant:n?.dangerous?`destructive`:`default`})||(z(!1),ye(!0),ge({id:++Ye.current,command:r,execute:!0}))})().catch(e=>{V.error(`Failed to execute markdown command:`,e),$(e instanceof Error?e.message:W(`terminalCommandExecuteFailed`))})};return window.addEventListener(`quickforge:execute-markdown-command`,t),()=>window.removeEventListener(`quickforge:execute-markdown-command`,t)},[e,z]);let vr=(0,H.useCallback)(e=>{ge(t=>t?.id===e?null:t)},[]),yr=(0,H.useCallback)(()=>{L.setFirstUseGuideDismissed(!0)},[L]),br=(0,H.useCallback)(()=>{let e=J.currentToolProject?.id?W(`firstUseGuideProjectPrompt`):W(`firstUseGuideGeneralPrompt`);navigator.clipboard.writeText(e).then(()=>U({sessionId:J.currentSessionId??``,title:W(`copied`),status:`idle`,message:e})).catch(e=>{V.error(`Failed to copy first-use guide prompt:`,e),$(W(`copyFailed`))})},[U,J.currentSessionId,J.currentToolProject?.id]),xr=!le&&!!J.agent&&!J.agent?.state.isStreaming&&(J.agent?.state.messages.length??0)===0;(0,H.useEffect)(()=>{xr&&!je.current&&Ae(!1),je.current=xr},[xr]),(0,H.useEffect)(()=>{!xr||ke||!g||J.chatScope!==`global`||Rn(g)},[g,J.chatScope,ke,xr,Rn]);let Sr=(0,H.useCallback)(()=>{if(Ae(!1),g){Rn(g);return}nr()},[g,nr,Rn]),Cr=(0,H.useCallback)(e=>{Rn(e)},[Rn]),wr=(0,H.useCallback)(()=>{Ae(!0),nr()},[nr]),Tr=(0,H.useCallback)(()=>{k()},[k]),Er=!!nt&&!L.firstUseGuideDismissed&&!xr&&_.length===0&&Ot.length===0,Dr=(0,H.useCallback)(()=>{let e=J.currentSessionId;e&&(L.setConversationMenuOpen(!1),er(e))},[J.currentSessionId,er,L]),Or=(0,H.useCallback)(()=>{let e=J.currentSessionId;e&&(L.setConversationMenuOpen(!1),$n(e,J.currentTitle))},[J.currentSessionId,J.currentTitle,$n,L]),kr=(0,H.useCallback)(()=>{L.setConversationMenuOpen(!1),L.setShareDialogOpen(!0)},[L]),Ar=J.agent,jr=Ar?.harness===`opencode`&&!Ar.state.isStreaming&&Ar instanceof Mc&&!!Ar.harnessSessionId,Mr=(0,H.useCallback)(()=>{let e=J.currentSessionId;e&&(L.setConversationMenuOpen(!1),tr(e))},[J.currentSessionId,tr,L]),{setSkillsDialog:Nr,setSidebarOpen:Pr}=L,Ir=(0,H.useCallback)(()=>{ir(`skills`)},[ir]),Lr=(0,H.useCallback)(()=>{ir(`agents`)},[ir]),Rr=(0,H.useCallback)(()=>{ir(`scheduledTasks`)},[ir]),zr=(0,H.useCallback)(e=>{Nr({scope:`project`,project:e})},[Nr]),Br=(0,H.useCallback)(async e=>{let t=await fetch(`/api/project/${encodeURIComponent(e.id)}/open-in-explorer`,{method:`POST`});if(t.ok)return;let n=await t.json().catch(()=>null);throw Error(n?.error||W(`openInExplorerFailed`))},[]),Vr=(0,H.useCallback)(async e=>{let t=await fetch(`/api/project/${encodeURIComponent(e.id)}/open-in-vscode`,{method:`POST`});if(t.ok)return;let n=await t.json().catch(()=>null);throw Error(n?.error||W(`openInVSCodeFailed`))},[]),Hr=(0,H.useCallback)(async e=>{let t=await fetch(`/api/project/${encodeURIComponent(e.id)}/open-in-idea`,{method:`POST`});if(t.ok)return;let n=await t.json().catch(()=>null);throw Error(n?.error||W(`openInIDEAFailed`))},[]),Ur=(0,H.useCallback)(e=>{Br(e).catch(e=>{V.error(`Failed to open project in explorer:`,e),$(e instanceof Error?e.message:W(`openInExplorerFailed`))})},[Br]),Wr=(0,H.useCallback)(e=>{Vr(e).catch(e=>{V.error(`Failed to open project in VS Code:`,e),$(e instanceof Error?e.message:W(`openInVSCodeFailed`))})},[Vr]),qr=(0,H.useCallback)(e=>{Hr(e).catch(e=>{V.error(`Failed to open project in IntelliJ IDEA:`,e),$(e instanceof Error?e.message:W(`openInIDEAFailed`))})},[Hr]),Yr=(0,H.useCallback)(()=>Pr(e=>!e),[Pr]),Z=(0,H.useCallback)(()=>{L.setMobileSidebarOpen(!1)},[L]),Xr=(0,H.useCallback)(e=>{Z(),rr(e)},[Z,rr]),Zr=(0,H.useCallback)(()=>{Z(),Sr()},[Z,Sr]),Qr=(0,H.useCallback)(e=>{Z(),Rn(e)},[Z,Rn]),$r=(0,H.useCallback)(()=>{Z(),Ir()},[Z,Ir]),ei=(0,H.useCallback)(()=>{Z(),Lr()},[Z,Lr]),ti=(0,H.useCallback)(()=>{Z(),Rr()},[Z,Rr]),ni=(0,H.useCallback)(e=>{Z(),zr(e)},[Z,zr]),ri=(0,H.useCallback)(e=>{if(e.scope===`project`&&e.project&&e.projects){M(e.projects),L.setSkillsDialog({scope:`project`,project:e.project}),m.current?.id===e.project.id&&(re(e.project),m.current=e.project),en.notifyProjectsChanged();return}en.notifyProjectsChanged()},[en,re,M,L]);return Mn?(0,K.jsx)(`div`,{className:`flex h-screen items-center justify-center bg-background p-6 text-foreground`,children:(0,K.jsxs)(`div`,{className:`max-w-md rounded-lg border border-border bg-background p-5 text-center`,children:[(0,K.jsx)(`h1`,{className:`text-base font-semibold`,children:W(`localServiceUnavailableTitle`)}),(0,K.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:Mn}),(0,K.jsxs)(`div`,{className:`mt-4 flex justify-center gap-2`,children:[(0,K.jsx)(q,{variant:`outline`,size:`sm`,onClick:Nn,children:W(`retry`)}),(0,K.jsx)(q,{variant:`default`,size:`sm`,onClick:()=>window.location.reload(),children:W(`reloadPage`)})]})]})}):In?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`quickforge-desktop-titlebar fixed left-0 right-0 top-0 z-40 hidden h-8 items-center px-2`,children:[(0,K.jsxs)(`button`,{type:`button`,className:`quickforge-desktop-titlebar-trigger inline-flex h-8 translate-y-1 items-center gap-2.5 rounded-none px-3 text-[13px] font-medium leading-none text-foreground/90 transition-colors hover:bg-accent hover:text-accent-foreground`,onClick:e=>{e.stopPropagation(),me(e=>!e)},"aria-haspopup":`menu`,"aria-expanded":fe,children:[(0,K.jsxs)(`svg`,{className:`h-[18px] w-[18px] shrink-0`,viewBox:`0 0 64 64`,"aria-hidden":`true`,children:[(0,K.jsxs)(`defs`,{children:[(0,K.jsxs)(`linearGradient`,{id:`titlebarIconStroke`,x1:`0`,y1:`0`,x2:`1`,y2:`1`,children:[(0,K.jsx)(`stop`,{offset:`0`,stopColor:`#9ca3af`}),(0,K.jsx)(`stop`,{offset:`1`,stopColor:`#4b5563`})]}),(0,K.jsxs)(`linearGradient`,{id:`titlebarIconBolt`,x1:`0`,y1:`0`,x2:`1`,y2:`1`,children:[(0,K.jsx)(`stop`,{offset:`0`,stopColor:`#374151`}),(0,K.jsx)(`stop`,{offset:`1`,stopColor:`#0f172a`})]})]}),(0,K.jsx)(`polygon`,{points:`32,6 52.78,18 52.78,42 32,54 11.22,42 11.22,18`,fill:`none`,stroke:`url(#titlebarIconStroke)`,strokeWidth:`4.5`,strokeLinejoin:`round`}),(0,K.jsx)(`path`,{d:`M37.2 13 L22 34 L30.6 34 L26.8 50 L42.8 26 L33.8 26 Z`,fill:`url(#titlebarIconBolt)`}),(0,K.jsx)(`path`,{d:`M37.2 13 L22 34 L30.6 34 L33.8 26 Z`,fill:`#e5e7eb`,opacity:`0.4`})]}),(0,K.jsx)(`span`,{children:`QuickForge`})]}),fe&&(0,K.jsxs)(`div`,{className:`quickforge-desktop-titlebar-menu absolute left-2 top-8 min-w-40 overflow-hidden rounded-md border border-border bg-popover py-1 text-[13px] text-popover-foreground shadow-lg`,role:`menu`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`button`,{type:`button`,className:`flex h-8 w-full items-center gap-2.5 px-3 text-left hover:bg-accent hover:text-accent-foreground`,role:`menuitem`,onClick:fr,children:[(0,K.jsx)(C,{className:`size-4`}),(0,K.jsx)(`span`,{children:W(`about`)})]}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-8 w-full items-center gap-2.5 px-3 text-left hover:bg-accent hover:text-accent-foreground`,role:`menuitem`,onClick:yt,children:[(0,K.jsx)(r,{className:`size-4`}),(0,K.jsx)(`span`,{children:W(`desktopUpdate`)})]}),(0,K.jsx)(`div`,{className:`my-1 border-t border-border`}),(0,K.jsxs)(`button`,{type:`button`,className:`flex h-8 w-full items-center gap-2.5 px-3 text-left text-destructive hover:bg-destructive/10`,role:`menuitem`,onClick:bt,children:[(0,K.jsx)(u,{className:`size-4`}),(0,K.jsx)(`span`,{children:W(`desktopExit`)})]})]})]}),!L.settingsDialogOpen&&(0,K.jsxs)(`div`,{className:G(`quickforge-window-toolbar fixed right-2 z-30 flex items-center gap-1`,be&&`pointer-events-none invisible`),"aria-hidden":be||void 0,"aria-label":W(`workspacePanel`),children:[!e&&!L.workspaceInspectorOpen?(0,K.jsx)(nn,{project:J.currentToolProject,disabled:le,onOpenInExplorer:Ur,onOpenInVSCode:Wr,onOpenInIDEA:qr}):null,!L.workspaceInspectorOpen&&J.currentToolProject?.id&&Fe?.isGitRepository?(0,K.jsx)(Wd,{projectId:J.currentToolProject.id,status:Fe,expanded:Ve,onExpandedChange:He,onOpenChanges:()=>{He(!1),wn()},onOpenCommitPush:()=>{He(!1),We(!0)},onCheckout:En,onCreated:Dn,onOpenGraph:()=>Ke(!0),mobileShell:n}):null,e?null:(0,K.jsx)(q,{variant:`ghost`,size:`icon`,onClick:()=>{z(!1),ye(e=>!e)},disabled:!J.currentToolProject?.id||le,"aria-label":W(ve?`terminalCollapse`:`rightPanelTerminal`),title:W(ve?`terminalCollapse`:`rightPanelTerminal`),className:G(`rounded-[10px] text-muted-foreground/85 hover:bg-muted/45 hover:text-foreground/90 disabled:opacity-40`,ve?`bg-accent text-accent-foreground hover:bg-accent hover:text-accent-foreground`:void 0),children:(0,K.jsx)(_e,{className:`size-[18px] stroke-[1.85]`})}),(0,K.jsx)(q,{variant:`ghost`,size:`icon`,onClick:()=>{z(!1),L.setWorkspaceInspectorOpen(e=>!e)},disabled:!J.currentToolProject?.id||le,"aria-label":L.workspaceInspectorOpen?W(`workspaceCollapseRightPanel`):W(`workspaceExpandRightPanel`),title:L.workspaceInspectorOpen?W(`workspaceCollapseRightPanel`):W(`workspaceExpandRightPanel`),className:G(`hidden rounded-[10px] text-muted-foreground/85 hover:bg-muted/45 hover:text-foreground/90 disabled:opacity-40 lg:inline-flex`,L.workspaceInspectorOpen?`bg-accent text-accent-foreground hover:bg-accent hover:text-accent-foreground`:void 0),children:(0,K.jsx)(ie,{className:`size-[18px] stroke-[1.85]`})})]}),L.settingsDialogOpen?(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(Yp,{}),children:(0,K.jsx)(zp,{initialTab:L.settingsInitialTab,customProvider:L.settingsCustomProvider,onBack:dr})}):null,(0,K.jsxs)(`div`,{className:G(`flex h-screen min-h-0 supports-[height:100dvh]:h-dvh bg-[var(--quickforge-sidebar-bg)] text-foreground`,L.settingsDialogOpen&&`hidden`),"aria-hidden":L.settingsDialogOpen||void 0,children:[(0,K.jsx)(Rs,{sidebarOpen:L.sidebarOpen,projectsCollapsed:L.projectsCollapsed,pinnedCollapsed:L.pinnedCollapsed,conversationsCollapsed:L.conversationsCollapsed,projects:_,expandedProjectIds:x,activeProject:g,currentSessionId:J.currentSessionId,loadingSessionId:J.loadingSessionId,sessionViewMode:Te,sessionSortMode:De,globalSessions:Ot,pinnedSessions:Tt,pinnedHasMore:Et,pinnedLoading:Dt,sessionsForProject:kt,projectTimelineSessions:jt,projectTimelineHasMore:Mt,projectTimelineLoading:Nt,globalHasMore:At,globalLoading:Ft,onLoadMoreGlobal:Xt,onLoadMorePinned:Jt,projectHasMore:Pt,projectLoading:It,projectLoaded:Lt,onLoadMoreProject:Qt,onLoadMoreProjectTimeline:$t,sessionTaskStatus:_r,selectingProject:S,onTogglePinnedCollapsed:L.togglePinnedCollapsed,onToggleProjectsCollapsed:L.toggleProjectsCollapsed,onToggleConversationsCollapsed:L.toggleConversationsCollapsed,onToggleProjectExpanded:te,onToggleAllProjectsExpanded:j,onReorderProjects:ne,onSelectProjectDirectory:e?void 0:k,onStartNewProjectChat:Rn,onOpenGlobalSkills:Ir,onOpenAgents:Lr,onOpenScheduledTasks:Rr,onOpenProjectSkills:zr,onOpenProjectInExplorer:e?void 0:Ur,onDeleteProject:Gn,onLoadSession:rr,onSessionViewModeChange:Ee,onSessionSortModeChange:Oe,onTogglePinSession:er,onDeleteSession:tr,onStartNewGlobalChat:Sr,onOpenSettings:sr,currentServerUrl:t?`云账户远程访问`:o,currentServerAlias:s,onOpenServer:n||t?c:void 0,updateAvailable:Pn.result.updateAvailable,latestVersion:Pn.result.latestVersion,currentVersion:Pn.result.currentVersion,onOpenUpdate:cr,onDismissUpdate:Pn.dismissUpdate,onToggleSidebar:Yr,currentSessionHoverInfo:Ne}),L.mobileSidebarOpen?(0,K.jsxs)(`div`,{className:`fixed inset-0 z-50 md:hidden`,role:`dialog`,"aria-modal":`true`,children:[(0,K.jsx)(`button`,{type:`button`,className:`absolute inset-0 bg-background/65 backdrop-blur-sm`,onClick:Z,"aria-label":W(`toggleSidebar`)}),(0,K.jsx)(`div`,{className:`absolute inset-y-0 left-0 max-w-[85vw] shadow-quickforge`,children:(0,K.jsx)(Rs,{variant:`mobile`,sidebarOpen:!0,projectsCollapsed:L.projectsCollapsed,pinnedCollapsed:L.pinnedCollapsed,conversationsCollapsed:L.conversationsCollapsed,projects:_,expandedProjectIds:x,activeProject:g,currentSessionId:J.currentSessionId,loadingSessionId:J.loadingSessionId,sessionViewMode:Te,sessionSortMode:De,globalSessions:Ot,pinnedSessions:Tt,pinnedHasMore:Et,pinnedLoading:Dt,sessionsForProject:kt,projectTimelineSessions:jt,projectTimelineHasMore:Mt,projectTimelineLoading:Nt,globalHasMore:At,globalLoading:Ft,onLoadMoreGlobal:Xt,onLoadMorePinned:Jt,projectHasMore:Pt,projectLoading:It,projectLoaded:Lt,onLoadMoreProject:Qt,onLoadMoreProjectTimeline:$t,sessionTaskStatus:_r,selectingProject:S,onTogglePinnedCollapsed:L.togglePinnedCollapsed,onToggleProjectsCollapsed:L.toggleProjectsCollapsed,onToggleConversationsCollapsed:L.toggleConversationsCollapsed,onToggleProjectExpanded:te,onToggleAllProjectsExpanded:j,onReorderProjects:ne,onSelectProjectDirectory:e?void 0:()=>{Z(),k()},onStartNewProjectChat:Qr,onOpenGlobalSkills:$r,onOpenAgents:ei,onOpenScheduledTasks:ti,onOpenProjectSkills:ni,onOpenProjectInExplorer:e?void 0:e=>{Z(),Br(e).catch(e=>{V.error(`Failed to open project in explorer:`,e),$(e instanceof Error?e.message:W(`openInExplorerFailed`))})},onDeleteProject:Gn,onLoadSession:Xr,onSessionViewModeChange:Ee,onSessionSortModeChange:Oe,onTogglePinSession:er,onDeleteSession:tr,onStartNewGlobalChat:Zr,onOpenSettings:()=>{Z(),sr()},currentServerUrl:t?`云账户远程访问`:o,currentServerAlias:s,onOpenServer:n||t?()=>{Z(),c()}:void 0,updateAvailable:Pn.result.updateAvailable,latestVersion:Pn.result.latestVersion,currentVersion:Pn.result.currentVersion,onOpenUpdate:()=>{Z(),cr()},onDismissUpdate:Pn.dismissUpdate,onToggleSidebar:Z,currentSessionHoverInfo:Ne})})]}):null,(0,K.jsxs)(`main`,{className:G(`flex min-w-0 flex-1 flex-col bg-[var(--quickforge-main-bg)] md:overflow-hidden md:rounded-tl-2xl`),children:[(0,K.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-2 border-b border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-3 pr-20`,children:[(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:`md:hidden`,onClick:()=>L.setMobileSidebarOpen(!0),"aria-label":W(`toggleSidebar`),children:(0,K.jsx)(D,{className:`size-[18px]`})}),(0,K.jsx)(`div`,{className:`min-w-0 flex-1`,children:(0,K.jsxs)(`div`,{className:`flex max-w-full min-w-0 items-center gap-2`,children:[(0,K.jsxs)(`div`,{className:`min-w-0`,children:[(0,K.jsx)(`div`,{className:`min-w-0 truncate text-sm font-semibold text-foreground/92`,children:Fn(J.currentTitle,mr?.channelName)}),J.currentToolProject?.name||Fe?.isGitRepository&&Fe.branch?(0,K.jsxs)(`div`,{className:`mt-0.5 flex min-w-0 items-center gap-2 overflow-hidden whitespace-nowrap text-xs leading-none text-muted-foreground sm:hidden`,children:[J.currentToolProject?.name?(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 basis-0 items-center gap-1`,title:J.currentToolProject.name,children:[(0,K.jsx)(A,{className:`size-3 shrink-0`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:J.currentToolProject.name})]}):null,Fe?.isGitRepository&&Fe.branch?(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 basis-0 items-center gap-1`,title:Fe.branch,children:[(0,K.jsx)(pe,{className:`size-3 shrink-0`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:Fe.branch})]}):null]}):null]}),!n&&J.currentToolProject?.name?(0,K.jsxs)(`div`,{className:`hidden h-9 max-w-[220px] shrink-0 items-center gap-2 rounded-full bg-muted/55 px-3 text-sm text-foreground/88 md:inline-flex`,title:J.currentToolProject.name,children:[(0,K.jsx)(A,{className:`size-4 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:J.currentToolProject.name})]}):null,!n&&J.currentToolProject?.id&&Fe?.isGitRepository&&Fe.branch?(0,K.jsxs)(`div`,{className:`relative hidden shrink-0 md:block`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`button`,{type:`button`,className:`inline-flex h-9 max-w-[220px] items-center gap-2 rounded-full bg-muted/55 px-3 text-sm text-foreground/88 transition-colors hover:bg-muted`,onClick:()=>Be(e=>!e),"aria-label":W(`gitBranchMenu`),"aria-expanded":ze,children:[(0,K.jsx)(pe,{className:`size-4 text-muted-foreground`}),(0,K.jsx)(`span`,{className:`min-w-0 truncate`,children:Fe.branch}),(0,K.jsx)(y,{className:`size-4 text-muted-foreground`})]}),ze?(0,K.jsx)(Id,{projectId:J.currentToolProject.id,currentBranch:Fe.branch,dirtyCount:Fe.counts?.total??0,onCheckout:En,onCreated:Dn,onOpenGraph:()=>{Be(!1),Ke(!0)},onOpenChanges:()=>{Be(!1),wn()}}):null]}):null,(0,K.jsxs)(`div`,{className:`relative shrink-0`,onClick:e=>e.stopPropagation(),children:[(0,K.jsx)(q,{variant:`ghost`,size:`icon`,className:G(L.conversationMenuOpen&&`bg-muted/45 text-foreground/90`),onClick:()=>L.setConversationMenuOpen(e=>!e),disabled:!J.currentSessionId||le,"aria-label":W(`moreOptions`),"aria-haspopup":`menu`,"aria-expanded":L.conversationMenuOpen,children:(0,K.jsx)(oe,{className:`size-[18px]`})}),L.conversationMenuOpen?(0,K.jsxs)(`div`,{className:G(`fixed inset-x-2 top-14 z-40 max-h-[calc(100dvh-4rem)] overflow-y-auto overscroll-contain rounded-lg border border-border bg-popover p-1 shadow-quickforge md:absolute md:inset-x-auto md:left-0 md:top-full md:z-30 md:mt-1 md:min-w-44 md:max-h-none md:overflow-visible`,n&&`md:fixed md:inset-x-2 md:left-auto md:top-14 md:z-40 md:mt-0 md:max-h-[calc(100dvh-4rem)] md:min-w-0 md:overflow-y-auto lg:inset-x-2 lg:left-auto lg:top-14`),role:`menu`,"aria-label":W(`moreOptions`),children:[(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:Dr,children:[hr?(0,K.jsx)(b,{className:`size-[18px]`}):(0,K.jsx)(a,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(hr?`unpinSession`:`pinSession`)})]}),(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50`,onClick:()=>{L.setConversationMenuOpen(!1),Wn()},disabled:!jr,title:W(`forkCurrentSessionTitle`),children:[(0,K.jsx)(Ce,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(`forkCurrentSession`)})]}),(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:Or,children:[(0,K.jsx)(ae,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(`renameSession`)})]}),(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:kr,children:[(0,K.jsx)(R,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(`shareSession`)})]}),(0,K.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`flex h-10 w-full items-center gap-2 whitespace-nowrap rounded-md px-2 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:Mr,children:[(0,K.jsx)(d,{className:`size-[18px]`}),(0,K.jsx)(`span`,{children:W(`archiveSession`)})]})]}):null]})]})})]}),(0,K.jsxs)(`section`,{className:`relative flex min-h-0 flex-1 flex-col`,children:[ct?(0,K.jsx)(Qp,{exiting:dt===ct},ct):null,le?(0,K.jsx)(Kr,{onAddModel:or,onUseExample:()=>{lr().catch(e=>V.error(`Failed to use LiteLLM example:`,e))}}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:G(`flex min-h-0 flex-1 flex-col`,xr?`quickforge-empty-chat`:void 0,dt===ct&&`quickforge-conversation-enter`),children:[xr?(0,K.jsx)(`div`,{className:`quickforge-empty-chat-hero`,"aria-hidden":`true`,children:(0,K.jsx)(`h1`,{className:`quickforge-empty-chat-title`,children:W(`newChatEmptyTitle`)})}):null,(0,K.jsx)(Yt,{children:(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(Yp,{}),children:(0,K.jsx)(Fp,{agent:J.agent,onModelSelect:ur,revision:J.chatPanelRevision,agentAccessMode:P,workspaceToolsEnabled:!!J.currentToolProject?.id,project:J.currentToolProject,projectId:J.currentToolProject?.id,chatScope:J.chatScope,onAccessModeChange:Kn,onRollbackFromMessage:zn,onRetryFromMessage:Bn,onCopyAnswer:Vn,onForkFromMessage:Un,onApproveToolCall:qn,onRejectToolCall:Jn,onApproveAutoCompact:Xn,onRejectAutoCompact:Zn,onOpenWorkspaceGitChanges:wn,onOpenLocalFilePath:kn,onArtifactsChange:e=>{we({projectId:J.currentToolProject?.id,sessionId:J.currentSessionId,artifacts:e})},onContextUsageDisplayChange:tn,onInitialRenderReady:vn,onInitialRenderError:yn,capabilities:Mp(J.agent?.harness),disableFork:J.agent?.harness===`opencode`,bypassClientApiKeyCheck:J.agent?.harness===`opencode`,allowModelControls:J.agent?.harness!==`opencode`,restoredDraft:B,onRestoredDraftConsumed:Sn,newChatEmptyState:xr})})}),xr?(0,K.jsx)(Jr,{projects:_,selectedProject:J.chatScope===`project`?J.currentToolProject:void 0,onSelectProject:Cr,onClearProject:wr,onNewProject:Tr}):null]}),Er?(0,K.jsx)(Gr,{hasProject:!!J.currentToolProject?.id,onConfigureModel:or,onAddProject:k,onCopyExamplePrompt:br,onDismiss:yr}):null]})]}),ve&&!e&&J.currentToolProject?.id?(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(Yp,{}),children:(0,K.jsx)(Rp,{project:J.currentToolProject,pendingCommand:he,onPendingCommandHandled:vr,onCollapse:()=>ye(!1)})}):null]}),J.currentToolProject?.id?(0,K.jsxs)(K.Fragment,{children:[L.workspaceInspectorOpen?(0,K.jsx)(`div`,{"aria-hidden":`true`,className:`hidden w-px shrink-0 bg-[color-mix(in_oklab,var(--border)_30%,var(--quickforge-sidebar-bg))] lg:block`}):null,(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(Xp,{}),children:(0,K.jsx)(Lp,{project:J.currentToolProject,open:L.workspaceInspectorOpen,onOpenChange:L.setWorkspaceInspectorOpen,onOpenCommitPush:()=>We(!0),onOpenProjectInExplorer:e?void 0:Ur,onOpenProjectInVSCode:e?void 0:Wr,onOpenProjectInIDEA:e?void 0:qr,onPreviewArtifact:An,request:L.workspaceInspectorRequest,onRequestHandled:Cn,artifacts:Se.projectId===J.currentToolProject.id&&Se.sessionId===J.currentSessionId?Se.artifacts:[],globalTerminalOpen:e?!1:ve,onShowGlobalTerminal:e?void 0:()=>{z(!1),ye(!0)},onFullscreenChange:xe},J.currentToolProject.id)})]}):null,Ge&&J.currentToolProject?.id?(0,K.jsx)(Yd,{projectId:J.currentToolProject.id,projectName:J.currentToolProject.name,onClose:()=>Ke(!1)}):null,Ue?(0,K.jsx)(Hd,{open:!0,projectId:J.currentToolProject?.id,status:Fe,onClose:()=>We(!1),onCheckout:En,onRefreshStatus:Tn,onStatusChange:Ie,onCompleted:On},J.currentToolProject?.id??`git-commit`):null]}),ot?null:(0,K.jsx)(Zp,{exiting:!0}),(0,K.jsx)(Zt,{open:w,initialPath:g?.path,disabled:S,onOpenChange:ee,onSelect:O}),(0,K.jsx)(et,{open:!!L.skillsDialog,scope:L.skillsDialog?.scope??`global`,project:L.skillsDialog?.project,onOpenChange:e=>{e||L.setSkillsDialog(void 0)},onSaved:ri}),(0,K.jsx)(pf,{open:L.shareDialogOpen,sessionId:J.currentSessionId,title:Fn(J.currentTitle),onOpenChange:L.setShareDialogOpen}),(0,K.jsx)(fd,{toasts:pt,onDismiss:ht,onClick:xn}),(0,K.jsx)(ip,{})]}):(0,K.jsx)(Zp,{})}function im(){if(Ut())return(0,K.jsx)(ep,{});let e=window.location.pathname.match(/^\/share\/([^/]+)\/?$/)?.[1];return e?(0,K.jsx)(H.Suspense,{fallback:(0,K.jsx)(`div`,{className:`flex h-screen items-center justify-center bg-background text-sm text-muted-foreground`,children:W(`loadingChatWorkspace`)}),children:(0,K.jsx)(Ip,{shareId:decodeURIComponent(e)})}):(0,K.jsx)(rm,{})}Tt({hideSelector:!0}),Dt(),Me.isNativePlatform()&&Wt()&&document.documentElement.classList.add(`quickforge-mobile-native`),window.addEventListener(`error`,e=>{V.error(`Uncaught error:`,e.error??e.message)}),window.addEventListener(`unhandledrejection`,e=>{V.error(`Unhandled promise rejection:`,e.reason)}),`serviceWorker`in navigator&&!Me.isNativePlatform()&&window.addEventListener(`load`,()=>{navigator.serviceWorker.register(`/sw.js`).catch(()=>{})}),(0,it.createRoot)(document.getElementById(`root`)).render((0,K.jsx)(H.StrictMode,{children:(0,K.jsx)(h,{strokeWidth:1.75,children:(0,K.jsx)(Yt,{children:(0,K.jsx)(im,{})})})}));export{Tu as $,lr as $t,_d as A,hc as At,Mu as B,Hi as Bt,ff as C,gl as Ct,of as D,Vc as Dt,sf as E,Rc as Et,Cd as F,ts as Ft,wu as G,Sr as Gt,du as H,Fi as Ht,Sd as I,qo as It,_u as J,kr as Jt,Su as K,Ar as Kt,Td as L,ls as Lt,yd as M,pc as Mt,Dd as N,vc as Nt,xd as O,Bc as Ot,Ed as P,lc as Pt,gu as Q,tr as Qt,wd as R,Mo as Rt,uf as S,hl as St,df as T,$c as Tt,xu as U,yi as Ut,Du as V,Pi as Vt,pu as W,Wr as Wt,Eu as X,br as Xt,Cu as Y,xr as Yt,bu as Z,Hn as Zt,$d as _,ht as _n,wl as _t,Cp as a,rr as an,au as at,Qd as b,Al as bt,wp as c,Sn as cn,Kl as ct,yf as d,ln as dn,Rl as dt,ur as en,yu as et,hf as f,on as fn,bl as ft,lf as g,vt as gn,Cl as gt,xf as h,G as hn,Dl as ht,Ep as i,Jn as in,ou as it,gd as j,_c as jt,bd as k,zc as kt,kp as l,xn as ln,Fl as lt,wf as m,q as mn,xl as mt,Np as n,ir as nn,mu as nt,Tp as o,Fn as on,Vl as ot,vf as p,nn as pn,yl as pt,vu as q,Cr as qt,Pp as r,dr as rn,$l as rt,Dp as s,X as sn,Gl as st,Ap as t,$n as tn,hu as tt,mf as u,_n as un,Il as ut,cf as v,gt as vn,Ol as vt,af as w,$ as wt,tf as x,ml as xt,rf as y,W as yn,El as yt,Vu as z,Pa as zt};