@shawnstack/quickforge 1.3.30 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -12
- package/dist/assets/AgentProfilesPage-CNK5PxA3.js +1 -0
- package/dist/assets/ChatPanelHost-FqPQwwMO.js +217 -0
- package/dist/assets/PluginsPage-BCu1Ept0.js +1 -0
- package/dist/assets/ScheduledTasksPage-Bx04rjui.js +2 -0
- package/dist/assets/SharedConversationPage-55vX9sqe.js +1 -0
- package/dist/assets/TerminalDock-DLN_pLkJ.js +2 -0
- package/dist/assets/WorkspaceInspector-DoemHHnY.js +3 -0
- package/dist/assets/WorkspaceReaderDialog-C6xUHBCw.js +6 -0
- package/dist/assets/{icons-BVM5--R9.js → icons-BWtivFsx.js} +1 -1
- package/dist/assets/index-CxOHP41X.css +3 -0
- package/dist/assets/index-Dcf73EL8.js +895 -0
- package/dist/assets/logger-B65Akg8A.js +1 -0
- package/dist/assets/monaco-evITXh-m.js +11 -0
- package/dist/assets/pi-ai-Cx633yhb.js +134 -0
- package/dist/assets/pi-web-ui-CBet4bMl.js +2770 -0
- package/dist/assets/plugin-api-YfYj_Bd7.js +1 -0
- package/dist/assets/{react-vendor-DAoL5p8_.js → react-vendor-Mthyt1p4.js} +1 -1
- package/dist/assets/rolldown-runtime-DWdDZTNf.js +1 -0
- package/dist/assets/xterm-5XDrJ343.js +36 -0
- package/dist/assets/xterm-BrP-ENHg.css +1 -0
- package/dist/index.html +8 -5
- package/package.json +1 -1
- package/server/agent-manager.mjs +189 -31
- package/server/approval-store.mjs +13 -1
- package/server/auto-compaction.mjs +63 -72
- package/server/context-usage.mjs +108 -0
- package/server/custom-commands.mjs +145 -28
- package/server/index.mjs +13 -0
- package/server/mcp/registry.mjs +40 -0
- package/server/routes/agent.mjs +20 -1
- package/server/routes/mcp.mjs +7 -1
- package/server/routes/project.mjs +32 -2
- package/server/routes/shared-conversation.mjs +1 -1
- package/server/storage.mjs +32 -19
- package/server/subagents.mjs +8 -6
- package/server/system-prompt.mjs +2 -2
- package/server/tools/definitions.mjs +1 -1
- package/server/utils/logger.mjs +0 -2
- package/dist/assets/anthropic-DYkQmon0.js +0 -39
- package/dist/assets/azure-openai-responses-B1_ZuuCX.js +0 -1
- package/dist/assets/github-copilot-headers-CMb2BbzT.js +0 -1
- package/dist/assets/google-Bx1PGUtS.js +0 -1
- package/dist/assets/google-shared-Cqjw1plk.js +0 -11
- package/dist/assets/google-vertex-1iRQw75f.js +0 -1
- package/dist/assets/hash-kZ2KD_no.js +0 -1
- package/dist/assets/headers-5EYI0_pl.js +0 -1
- package/dist/assets/index-CQq-kPng.js +0 -3837
- package/dist/assets/index-D0c0FMPa.css +0 -3
- package/dist/assets/mistral-B1j5S2k5.js +0 -44
- package/dist/assets/openai-Bf1npfRy.js +0 -16
- package/dist/assets/openai-codex-responses-BJKEqst-.js +0 -7
- package/dist/assets/openai-completions-B_cU49Pc.js +0 -5
- package/dist/assets/openai-prompt-cache-CErE62Yt.js +0 -1
- package/dist/assets/openai-responses-DgGY16ph.js +0 -1
- package/dist/assets/openai-responses-shared-J1-i-goZ.js +0 -12
- package/dist/assets/openrouter-BVaMghZV.js +0 -1
- package/dist/assets/rolldown-runtime-CkqCuyE9.js +0 -1
- package/dist/assets/sanitize-unicode-BhyPmlyt.js +0 -1
- package/dist/assets/transform-messages-Dhj_4OTw.js +0 -1
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ChatPanelHost-FqPQwwMO.js","assets/rolldown-runtime-DWdDZTNf.js","assets/pi-web-ui-CBet4bMl.js","assets/pi-ai-Cx633yhb.js","assets/lit-vendor-Dr3cpBGF.js","assets/icons-BWtivFsx.js","assets/react-vendor-Mthyt1p4.js","assets/plugin-api-YfYj_Bd7.js","assets/logger-B65Akg8A.js","assets/TerminalDock-DLN_pLkJ.js","assets/xterm-5XDrJ343.js","assets/xterm-BrP-ENHg.css","assets/ScheduledTasksPage-Bx04rjui.js","assets/AgentProfilesPage-CNK5PxA3.js","assets/PluginsPage-BCu1Ept0.js","assets/SharedConversationPage-55vX9sqe.js","assets/WorkspaceInspector-DoemHHnY.js","assets/WorkspaceReaderDialog-C6xUHBCw.js","assets/monaco-evITXh-m.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{$ as t,A as n,B as r,C as i,D as a,E as o,G as s,H as c,I as l,J as u,L as d,M as f,P as p,R as m,S as h,Z as g,_,a as v,at as y,b,ct as x,d as S,et as C,f as w,g as T,h as E,i as D,j as O,l as k,lt as ee,m as A,n as j,nt as M,o as N,ot as P,p as F,q as te,rt as I,s as ne,tt as re,u as ie,ut as L,v as ae,w as R,x as oe,y as se,z as ce}from"./icons-BWtivFsx.js";import{i as le,n as ue,r as de}from"./react-vendor-Mthyt1p4.js";import{f as fe,p as z,u as pe}from"./lit-vendor-Dr3cpBGF.js";import{n as me,r as he,t as ge}from"./css-utils-rkE68RDy.js";import{_ as B,a as _e,d as V,f as ve,g as ye,h as be,i as xe,m as Se,n as Ce,o as we,p as Te,r as Ee,t as De,u as Oe}from"./pi-web-ui-CBet4bMl.js";import{_ as ke,p as Ae,y as H}from"./pi-ai-Cx633yhb.js";import{t as U}from"./logger-B65Akg8A.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 W=e(L(),1),je=de(),G=`language`,Me=[`en`,`zh`],Ne={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`,loadingChatWorkspace:`Loading chat workspace...`,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`,noConversations:`No conversations`,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.`,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`,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`,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 build, change, or debug...`,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`,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.`,compactCommandDescription:`Create a new chat with this conversation compacted to reduce context usage.`,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 because YOLO mode is disabled. Enable YOLO mode inside the input box to grant local project access.`,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.`,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.`,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:`Default Options`,defaultOptionsDescription:`Configure the default model, thinking level, tool display, and appearance for new chats and scheduled tasks.`,defaultModel:`Default model`,defaultThinkingLevel:`Default thinking level`,toolDisplay:`Tool Display`,showToolDetails:`Show detailed tool JSON`,expandToolsByDefault:`Expand tool calls by default`,showToolDetailsDescription:`When disabled, tool input and details JSON are hidden. Console output, status, summaries, and diffs remain visible.`,fontSize:`Font size`,fontSizeDescription:`Adjust the global base font size and common body text size.`,baseFontSize:`Base font size (px)`,bodyFontSize:`Body text size (px)`,bodyFontSizeNote:`Applies to the Tailwind text-sm utility used by common interface text.`,toolDetailsHidden:`Tool details are hidden. Enable detailed tool JSON in Settings to view full parameters.`,toolArgsSummary:`Arguments summary`,saveDefaultOptions:`Save defaults`,saving:`Saving...`,defaultOptionsSaved:`Default options saved`,contextManagement:`Context Management`,autoCompactEnabled:`Automatically compact context`,autoCompactRequireConfirmation:`Ask before compacting automatically`,autoCompactTriggerNote:`Checks run before each model request. Lower the threshold or reduce the model Context Window to test triggering.`,autoCompactThresholdPercent:`Compact when context reaches (%)`,autoCompactKeepRecentTurns:`Keep recent user turns`,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.`,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
|
+
"X-Custom-Header": "value"
|
|
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.)`,providerProtocol:`Protocol`,model:`Model`,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`,searchModels:`Search models...`,noMatchingCustomModels:`No matching custom models`,readFile:`Read File`,searchFiles:`Search Files`,writeFile:`Write File`,editFile:`Edit File`,runCommand:`Run Command`,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 YOLO mode. The previous state has been restored.`,toolApprovalFailed:`Failed to submit tool approval. Please try again.`,toolApprovalSubmitting:`Submitting...`,terminateCommand:`Terminate`,terminateCommandTitle:`Terminate this running command`,commandTerminateRequested:`Terminating...`,running:`Running`,done:`Done`,error:`Error`,taskCompleted:`Task completed`,taskError:`Task error`,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.`,enabledAsSubagent:`Enabled 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`,allowedTools:`Allowed tools`,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`,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`,pluginOpenaiDocumentsName:`Documents`,pluginOpenaiDocumentsDescription:`Create and edit document artifacts`,pluginOpenaiSpreadsheetsName:`Spreadsheets`,pluginOpenaiSpreadsheetsDescription:`Create, analyze, and structure spreadsheet files`,pluginOpenaiPresentationsName:`Presentations`,pluginOpenaiPresentationsDescription:`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`,mcpReconnect:`Reconnect`,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 servers.`,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.`,selectProjectForCommands:`Please select or add a project before configuring project commands.`,commandDirectory:`Command directory`,commandDirectories:`Command directories`,commandDirectoryPlaceholder:`.claude/commands
|
|
5
|
+
.opencode/commands
|
|
6
|
+
D:\\shared\\ai-commands`,commandDirectoryHelp:`One directory per line. Supports relative paths and absolute paths. Relative paths are resolved from the current project root. Leave empty to use the built-in compatible command directories only.`,commandDirectoryExamples:`Examples`,projectCommandsSaved:`Project command settings saved.`,loadedCommands:`Loaded commands ({count})`,noCommandsLoaded:`No commands loaded yet. Add a directory above or create a command to get started.`,openCommandDir:`Open command directory`,createCommand:`New command`,newCommandPrompt:`Enter a command name (lowercase letters, numbers, hyphens):`,commandCreated:`Command created: {name}`,commandAlreadyExists:`Command already exists: {name}`,invalidCommandName:`Invalid command name. Use lowercase letters, numbers, and hyphens.`,manageSkills:`Manage skills`,manageGlobalSkills:`Manage global skills`,manageProjectSkills:`Manage project skills`,openFolder:`Open folder`,openInExplorer:`Open in Explorer`,openInExplorerFailed:`Failed to open the project folder.`,moreOptions:`More options`,pinSession:`Pin conversation`,unpinSession:`Unpin conversation`,shareSession:`Share conversation`,selectProjectForSkills:`Please select or add a project before managing skills.`,skillsDescription:`Select reusable Agent Skills enabled for project "{project}". QuickForge discloses only name/description in the prompt; full SKILL.md instructions are loaded on demand with activate_skill.`,globalSkillsDescription:`Select reusable Agent Skills enabled globally for QuickForge. Skills are discovered from ~/.claude/skills, ~/.opencode/skills, ~/.agents/skills, and ~/.quickforge/skills. Only the catalog is injected into new chats; instructions load on demand.`,projectSkillsDescription:`Select project Agent Skills for "{project}". Project skills are discovered from .claude/skills, .opencode/skills, .agents/skills, and .quickforge/skills; they override global skills with the same name and load on demand in new project chats.`,searchSkills:`Search skills...`,availableSkills:`Available skills`,selectedSkillsCount:`{count} selected`,noMatchingSkills:`No matching skills found`,skillSearchPaths:`Search paths`,failedToLoadSkills:`Failed to load skills.`,failedToSaveSkills:`Failed to save skills.`,readSkill:`Read skill`,readSkillContent:`Read skill content`,backToSkillList:`Back to skill list`,failedToReadSkill:`Failed to read skill content.`,noSkillContent:`This skill has no readable content.`,requestFailed:`Request failed`,backupRestore:`Backup & Restore`,backupRestoreDescription:`Export or restore QuickForge settings, providers, projects, scheduled tasks, and conversations. Imports create a safety backup on the local service before writing data. Backups may contain sensitive conversations, local paths, code snippets, and optionally API keys.`,exportData:`Export data`,exportDataDescription:`Download a JSON backup that you can keep or move to another QuickForge installation. API keys are excluded unless you explicitly include them.`,exportScope:`Export scope`,exportScopeAll:`Everything`,exportScopeConfig:`Configuration only`,exportScopeSessions:`Conversations only`,includeApiKeys:`Include API keys`,includeApiKeysDescription:`API keys are sensitive. Only enable this for private encrypted storage or trusted migration.`,backupExportSecretsConfirm:`This backup will contain API keys. Do not commit it to Git or share it with untrusted people. Continue?`,exportBackup:`Export backup`,backupExported:`Backup exported.`,backupExportFailed:`Backup export failed.`,importData:`Import data`,importDataDescription:`Restore a previously exported JSON backup. The file will be inspected first, then matching sections in the current local data will be replaced.`,importBackup:`Import backup`,backupInspectTitle:`Backup preview`,backupInspectExportedAt:`Exported at`,backupInspectVersion:`Version`,backupInspectScope:`Scope`,backupInspectSecrets:`Contains API keys`,backupInspectSections:`Sections`,backupInspectFailed:`Backup inspection failed.`,backupInspected:`Backup inspected. Choose what to restore below.`,selectRestoreSections:`Select data to restore`,confirmImportSelected:`Import selected data`,selectAtLeastOneRestoreSection:`Select at least one data section to restore.`,restoreSettings:`Settings`,restoreSettingsDescription:`App preferences such as language and default options.`,restoreProviderKeys:`API keys`,restoreProviderKeysDescription:`Sensitive provider API keys. Restoring replaces current saved keys.`,restoreCustomProviders:`Custom providers and models`,restoreCustomProvidersDescription:`Custom model providers, endpoints, model IDs, and related configuration.`,restoreProjects:`Projects`,restoreProjectsDescription:`Project list, active project, and selected skills.`,restoreScheduledTasks:`Scheduled tasks`,restoreScheduledTasksDescription:`Saved scheduled AI tasks.`,restoreConversations:`Conversations`,restoreConversationsDescription:`Conversation history and metadata. This is restored as one consistent unit.`,backupImportConfirm:`Importing will replace matching local QuickForge data. A safety backup will be created first. Continue?`,backupImported:`Backup imported. The app will reload.`,backupImportFailed:`Backup import failed.`,backupSafetyBackupPath:`Safety backup saved at`,backendService:`Backend Service`,backendServiceDescription:`Restart the local QuickForge backend service. Running generations will be interrupted and the page will reconnect automatically.`,backendServiceStatus:`Service status`,restartBackendService:`Restart backend service`,restartBackendServiceDescription:`Use this when the local backend is stuck or after changing environment-level service settings.`,restartBackendConfirm:`Restart the backend service now? Running generations will be interrupted and the page will reconnect automatically.`,backendRestarting:`Backend is restarting...`,backendRestarted:`Backend restarted. Reloading...`,backendRestartFailed:`Backend restart failed.`,backendRestartTimeout:`Backend restart timed out. Please restart QuickForge manually.`,backendRestartUnsupported:`This launch mode does not support restarting from the UI. Please restart QuickForge manually.`,serviceMode:`Mode`,servicePid:`PID`,serviceStartedAt:`Started at`,serviceDataDir:`Data directory`,serviceWorkspace:`Workspace`,terminalShell:`Terminal shell`,terminalShellDescription:`QuickForge auto-detects common macOS, Windows, and Linux shells. Pick the checked default, or add a custom command/path only when it is missing. QUICKFORGE_TERMINAL_SHELL still takes priority.`,terminalShellAutoDetectedHint:`Detected entries are shown automatically for this computer.`,terminalShellDefault:`Default shell`,terminalShellSaved:`Terminal shell setting saved. New terminal sessions will use it.`,terminalShellProfilesSaved:`Terminal shell profiles saved.`,terminalShellCommand:`Custom shell command or path`,terminalShellCommandPlaceholder:`C:\\Program Files\\Git\\bin\\bash.exe`,terminalShellAdd:`Add`,terminalShellSetDefault:`Set as default`,terminalShellDefaultBadge:`Default`,terminalShellDetected:`Detected`,terminalShellNoDetected:`No shell was detected. Add a custom shell command or path below.`,terminalShellProfileRequired:`Enter a shell command or executable path before saving.`,terminalShellDeleteConfirm:`Delete terminal shell profile "{name}"?`,terminalNew:`New terminal`,terminalNewWith:`New terminal with`,terminalNewWithProfile:`New terminal: {name}`,terminalSelectShell:`Choose shell for new terminal`,terminalCollapse:`Collapse terminal`,terminalFullscreen:`Fullscreen terminal`,terminalExitFullscreen:`Exit fullscreen`,terminalStarting:`Starting terminal...`,terminalUnavailable:`Terminal unavailable`,terminalNoSessions:`No terminal sessions`,terminalCreateFailed:`Failed to create terminal`,terminalCloseFailed:`Failed to close terminal`,terminalConnectionFailed:`Failed to connect to terminal.`,terminalConnectionClosedUnexpectedly:`Terminal connection closed unexpectedly.`,terminalCloseSession:`Close {name}`,workspaceNoFilesToDisplay:`No files to display.`,workspaceNoWorkingTreeChanges:`No working tree changes.`,noProjectSelected:`No project selected`,workspacePanel:`Workspace`,workspaceOverview:`Overview`,workspaceFiles:`Workspace Files`,workspaceBrowser:`Browser`,workspaceChanges:`Changes`,workspaceCurrentArtifacts:`This AI turn`,workspaceNoArtifacts:`No AI-produced files detected for this turn. Direct write_file/edit_file changes will appear here; command outputs are shown as low-confidence signals.`,workspaceCommands:`Commands`,workspaceCurrentBranch:`Current branch`,workspaceChangeCount:`changes`,workspaceNotGitRepository:`This project is not a Git repository.`,workspaceSelectProject:`Select a project to inspect its workspace.`,workspaceLoading:`Loading workspace...`,workspaceLoadFailed:`Failed to load workspace.`,workspaceFilterFiles:`Filter files by name or path`,workspaceOpenFileHint:`Click a file to open the Monaco reader.`,workspaceOpenFileFailed:`Failed to open file.`,workspaceOpenDiffFailed:`Failed to open diff.`,refreshWorkspace:`Refresh workspace`,closeWorkspace:`Close workspace`,workspaceStaged:`Staged`,workspaceUntracked:`Untracked`,workspaceConflicts:`Conflicts`,workspaceStagedChanges:`Staged Changes`,workspaceReview:`Review`,workspaceCommitMessage:`Commit msg`,unknown:`Unknown`,webPreview:`Web Preview`,closeWebPreview:`Close web preview`,previewUrl:`Preview URL`,previewUrlPlaceholder:`http://localhost:5173`,openPreview:`Open`,refreshPreview:`Refresh preview`,openInBrowser:`Open in browser`,invalidPreviewUrl:`Please enter a valid http:// or https:// URL.`,noPreviewUrlTitle:`Enter a preview URL`,noPreviewUrlDescription:`Run your project dev server in the terminal, then enter its local URL here. Vite, Next, Astro and similar tools usually update live through HMR.`,workspaceStatusAdded:`Added`,workspaceStatusDeleted:`Deleted`,workspaceStatusRenamed:`Renamed`,workspaceStatusUntracked:`Untracked`,workspaceStatusConflict:`Conflict`,workspaceStatusModified:`Modified`,lanAccess:`LAN Access`,lanAccessDescription:`Allow trusted devices on the same LAN to access the full QuickForge app after entering a password.`,lanAccessRiskWarning:`High risk: LAN devices that pass this password can access your conversations, projects, and available tools. Enable only on trusted networks.`,lanAccessStatus:`LAN access status`,lanAccessEnabled:`Full LAN access`,lanAccessPassword:`Access password`,lanAccessActiveDevices:`Unlocked devices`,lanAccessUrls:`LAN URLs`,lanAccessAllowFull:`Allow LAN devices to access full QuickForge`,lanAccessPasswordPlaceholder:`At least 8 characters`,lanAccessPasswordPlaceholderConfigured:`Leave empty to keep current password`,lanAccessSessionTtl:`Login validity`,lanAccessRevokeAll:`Sign out all LAN devices`,lanAccessRevokeAllConfirm:`Sign out all unlocked LAN devices now?`,lanAccessEnableConfirm:`Enable full LAN access? Only continue on a trusted network.`,lanAccessPasswordRequired:`Set an access password before enabling LAN access.`,lanAccessPasswordTooShort:`The access password must be at least 8 characters.`,lanAccessSaved:`LAN access settings saved.`,lanAccessRevoked:`All LAN devices have been signed out.`,enabled:`Enabled`,disabled:`Disabled`,configured:`Configured`,notConfigured:`Not configured`,generatePassword:`Generate password`,hour:`hour`,hours:`hours`,days:`days`,toolApprovalWaiting:`Waiting for approval: {toolName}`,autoCompactApprovalWaiting:`Context reached {percent}% of the {threshold}% threshold. Compact now?`,autoCompactApprovalPreview:`QuickForge will summarize older history and continue with the summary plus the latest {keepRecentTurns} user turn(s). Full chat history remains visible.`,autoCompactFailed:`Automatic context compaction failed; continuing with the current history.`,contextCompactedTimelineLabel:`Earlier context is summarized for the model`,contextCompactedLabel:`Compressed context`,contextCompactedTooltip:`This chat is using a summarized context for model requests while keeping the full history visible.`,contextCompactedViewSummary:`View summary`,contextCompactedHideSummary:`Hide summary`,contextCompactedSummaryTitle:`Summary used by the model`,contextCompactedCopySummary:`Copy summary`,toolApprovalAccept:`✓ Accept`,toolApprovalReject:`✗ Reject`,toolApprovalTimeout:`Timeout`,toolApprovalTruncated:`... (truncated)`,processed:`Processed`,processing:`Processing`,processFailed:`Failed`,processAborted:`Aborted`,expandProcess:`Expand processing details`,collapseProcess:`Collapse processing details`,relativeMinuteShort:`{count}m`,relativeHourShort:`{count}h`,relativeDayShort:`{count}d`,relativeWeekShort:`{count}w`,relativeYearShort:`{count}y`},zh:{language:`语言`,displayLanguage:`界面语言`,languageDescription:`选择速构 QuickForge 的界面显示语言。切换后页面会刷新以应用到所有组件。`,simplifiedChinese:`简体中文`,english:`English`,apply:`应用`,noLanguageChange:`当前已经是所选语言。`,newChat:`新建对话`,loadingChatWorkspace:`正在加载聊天工作区...`,localServiceUnavailableTitle:`QuickForge 本地服务不可用`,localServiceUnavailableDescription:`QuickForge 需要通过本地服务进行存储。请使用 npm run dev 或 quickforge 命令启动后刷新此页面。`,project:`项目`,projects:`项目`,loadingProject:`正在加载项目...`,addProject:`添加项目`,noProjects:`暂无项目。`,expandProject:`展开项目`,collapseProject:`折叠项目`,expandAllProjects:`展开所有项目`,collapseAllProjects:`折叠所有项目`,dragToReorder:`拖拽排序`,newProjectChat:`新建项目对话`,projectChat:`项目对话`,normalChat:`普通对话`,conversations:`对话`,noConversations:`暂无对话`,filter:`筛选`,selecting:`选择中...`,chooseFolder:`选择文件夹`,selectProjectDirectory:`选择项目目录`,selectProjectDirectoryDescription:`浏览本地文件夹或粘贴路径,然后选择一个文件夹作为项目。`,quickAccess:`快捷入口`,path:`路径`,go:`前往`,parentDirectory:`上级目录`,noFolders:`该目录下没有文件夹。`,selectThisFolder:`选择此文件夹`,folderPickerPathPlaceholder:`输入或粘贴文件夹路径`,filesystemRootsFailed:`加载文件系统入口失败。`,directoryLoadFailed:`加载目录失败。`,noSavedConversations:`暂无保存的对话。`,deleteProject:`删除项目`,deleteProjectConfirm:`确定要删除项目「{name}」吗?该项目的对话记录将保留。`,deleteSession:`删除会话`,deleteSessionConfirm:`确定要删除该对话吗?删除后不可恢复。`,confirm:`确认`,confirmDelete:`确认删除`,rename:`重命名`,renameSession:`重命名对话`,sessionName:`对话名称`,settings:`设置`,toggleSidebar:`切换侧边栏`,failedToSelectProjectDirectory:`选择项目目录失败。`,projectSwitchFailed:`切换到该对话绑定的项目失败,工作区工具未启动。`,copy:`复制`,copied:`已复制`,rollback:`回滚`,retry:`重试`,reloadPage:`刷新页面`,fork:`分支`,forkConversation:`从此处分支新对话`,yoloEnabledTitle:`工作区授权已开启:本地工具可使用当前项目`,yoloDisabledTitle:`工作区授权已锁定:本地工具已阻止`,planModeLabel:`计划`,planModeEnabledTitle:`计划模式已开启:下一条消息会按 /plan 发送。点击可移除。快捷键:Shift+Tab`,planModeDisabledTitle:`计划模式:下一条消息按 /plan 发送。快捷键:Shift+Tab`,composerPlaceholder:`描述你想构建、修改或排查的问题...`,assistantWaitingThinking:`正在思考`,assistantWaitingOrganizing:`正在整理答案`,assistantWaitingContinuing:`内容较多,正在继续处理`,assistantWaitingAriaLabel:`AI 正在准备回复`,customCommandsHint:`自定义指令`,customCommandsEmptyHint:`还没有项目指令。`,customCommandsListDescription:`列出项目自定义指令`,customCommandsNewDescription:`创建项目自定义指令`,planCommandDescription:`先生成计划;本轮禁止编辑文件或运行命令。`,reviewCommandDescription:`提交前自检待提交代码;本轮禁止编辑文件。`,compactCommandDescription:`基于当前对话创建压缩后的新对话,减少上下文占用。`,clearCommandDescription:`清除当前对话历史和上下文,不调用模型。`,helpCommandDescription:`显示所有可用命令及其用法。`,yoloBlockedReason:`本地工具 {name} 已被阻止,因为 YOLO 模式已关闭。请在输入框内启用 YOLO 模式以授予本地项目访问权限。`,globalToolBlockedReason:`本地工具 {name} 已被阻止,因为这是未绑定项目的普通对话。请新建或打开项目对话后使用工作区工具。`,noActiveProjectToolBlockedReason:`本地工具 {name} 已被阻止,因为当前没有激活项目。请添加或选择项目后再使用工作区工具。`,generationStillRunning:`生成仍在进行中。请停止生成或等待完成后再回滚。`,noConversationTurnToRollback:`没有可回滚的对话轮次。`,rollbackConfirmTitle:`确认回滚?`,rollbackConfirm:`确定回滚到这条消息之前吗?该消息及其之后的对话记录会被移除,消息内容会恢复到输入框。`,sharedRollbackConfirmTitle:`确认回滚分享对话?`,sharedRollbackConfirm:`该操作会直接影响分享者本机中的原始对话。该消息及其之后的对话记录会被移除,消息内容会恢复到输入框。`,confirmRollback:`确认回滚`,rollingBack:`回滚中...`,rollbackFailed:`回滚失败。`,retryFailed:`重试失败。`,copyFailed:`复制失败,请检查剪贴板权限。`,errorBoundaryTitle:`出错了`,errorBoundaryUnexpected:`发生了意外错误。`,errorBoundaryTryAgain:`重试`,execute:`执行`,addCustomModelFirst:`请先在设置里添加自定义模型,并确保填写了模型 ID 后保存。`,modelSetupRequired:`请先添加模型后再新建对话。`,modelSetupTitle:`还没有配置模型`,modelSetupDescription:`添加一个 OpenAI-Compatible 或 Anthropic 兼容模型后即可开始对话。QuickForge 只会使用你自己配置的模型。`,modelSetupSupports:`支持 LiteLLM、OpenRouter、DeepSeek、通义千问、智谱、Ollama,以及大多数 /v1/chat/completions 服务。`,modelSetupLocalStorage:`提供商、模型 ID 和 API Key 会由本机 QuickForge 本地服务保存。`,modelSetupAddModel:`添加模型`,modelSetupUseLiteLlmExample:`使用 LiteLLM 示例配置`,firstUseGuideTitle:`从安全工作流开始`,firstUseGuideDescription:`添加项目后,先让 QuickForge 理解项目;涉及代码修改时,建议先用 /plan 生成计划,再授权本地工具执行。`,firstUseGuideStepModel:`确认要使用的模型配置。`,firstUseGuideStepProject:`添加本地项目,让 AI 使用工作区上下文。`,firstUseGuideStepPlan:`先使用 /plan;该轮不会编辑文件或运行命令。`,firstUseGuideConfigureModel:`配置模型`,firstUseGuideAddProject:`添加项目`,firstUseGuideUsePrompt:`试用示例提示词`,firstUseGuideCopyPrompt:`复制 /plan 示例`,firstUseGuideDismiss:`我知道了`,firstUseGuideProjectPrompt:`/plan 阅读这个项目,说明项目结构、运行方式和主要风险。先不要修改文件。`,firstUseGuideGeneralPrompt:`/plan 先把这个需求拆成实现步骤和风险点。暂时不要修改文件。`,defaultOptions:`默认选项`,defaultOptionsDescription:`配置新建对话和定时任务默认使用的模型、思考等级、工具展示和外观。`,defaultModel:`默认模型`,defaultThinkingLevel:`默认思考等级`,toolDisplay:`工具展示`,showToolDetails:`显示 Tool 详细 JSON`,expandToolsByDefault:`默认展开 Tool 调用`,showToolDetailsDescription:`关闭后将隐藏 Tool 参数和 details JSON,但仍会显示控制台输出、状态、摘要和 diff。`,fontSize:`字号`,fontSizeDescription:`调整全局基础字号和常用正文字号。`,baseFontSize:`基础字号(px)`,bodyFontSize:`正文字号(px)`,bodyFontSizeNote:`应用到界面常用文字使用的 Tailwind text-sm 工具类。`,toolDetailsHidden:`Tool 详细信息已隐藏。可在设置中开启“显示 Tool 详细 JSON”查看完整参数。`,toolArgsSummary:`参数摘要`,saveDefaultOptions:`保存默认选项`,saving:`保存中...`,defaultOptionsSaved:`默认选项已保存`,contextManagement:`上下文管理`,autoCompactEnabled:`自动压缩上下文`,autoCompactRequireConfirmation:`自动压缩前先询问确认`,autoCompactTriggerNote:`系统会在每次请求模型前检查。测试时可降低阈值,或调小模型 Context Window。`,autoCompactThresholdPercent:`上下文达到多少百分比时压缩`,autoCompactKeepRecentTurns:`保留最近用户回合数`,autoCompactDescription:`当预计下一次请求达到模型上下文窗口的指定比例时,QuickForge 会总结较早历史并继续当前任务。该过程会额外消耗一次模型调用。`,autoCompactHistoryPreserved:`完整聊天历史仍会保留在界面中;只有发送给模型的上下文会被压缩。`,thinkingLevel:`思考等级`,thinkingOff:`关`,thinkingLow:`低`,thinkingMedium:`中`,thinkingHigh:`高`,thinkingXHigh:`极高`,currentConfiguration:`当前配置`,thinkingSupported:`支持思考`,thinkingNotSupported:`该模型不支持思考等级。`,thinkingRequiresReasoningModel:`思考等级需要推理/思考模型。`,customModels:`自定义模型`,customModelsTitle:`自定义模型`,customModelsDescription:`只使用你配置的自定义 OpenAI-Compatible 模型。`,addModel:`添加模型`,editModel:`编辑模型`,delete:`删除`,editCustomModel:`编辑自定义模型`,addCustomModel:`添加自定义模型`,providerName:`提供商名称`,providerNamePlaceholder:`例如:LiteLLM`,protocolType:`协议类型`,protocolHelp:`LiteLLM、OpenRouter、大多数 /v1/chat/completions 服务请选择 OpenAI Compatible;直连 Anthropic API 才选 Anthropic Messages。`,apiKey:`API Key`,apiKeyPlaceholder:`没有可以留空`,showApiKey:`查看 API Key`,hideApiKey:`隐藏 API Key`,customHeaders:`自定义 Headers JSON`,customHeadersPlaceholder:`{
|
|
7
|
+
"X-Custom-Header": "value"
|
|
8
|
+
}`,customHeadersHelp:`可选的提供商级 HTTP Headers。必须是值为字符串的 JSON 对象,会随模型配置保存在本地。`,invalidHeadersJson:`自定义 Headers 必须是有效 JSON 对象,并且键和值都必须是字符串。`,modelId:`模型 ID`,modelIdPlaceholder:`例如:anthropic/claude-sonnet-4`,contextWindow:`Context Window`,maxTokens:`Max Tokens`,reasoningModel:`推理/思考模型(DeepSeek V4、Qwen 等)`,providerProtocol:`协议`,model:`模型`,noModelAdded:`未添加模型`,modelsCount:`{count} 个模型`,modelIndex:`模型 #{index}`,modelsList:`模型列表`,atLeastOneModel:`至少需要一个模型。`,duplicateModelId:`模型 ID 不能重复。`,cancel:`取消`,save:`保存`,yes:`是`,no:`否`,loading:`加载中...`,noCustomModels:`还没有自定义模型,请点击"添加模型"。`,fillProviderBaseUrlModel:`请填写提供商名称和 Base URL。`,saveCustomModelFailed:`保存自定义模型失败。`,confirmDeleteProvider:`确定删除 {name} 吗?`,deleteFailed:`删除失败。`,selectCustomModel:`选择自定义模型`,close:`关闭`,searchModels:`搜索模型...`,noMatchingCustomModels:`没有匹配的自定义模型`,readFile:`读取文件`,searchFiles:`搜索文件`,writeFile:`写入文件`,editFile:`编辑文件`,runCommand:`运行命令`,executeInTerminal:`在终端中执行`,confirmExecuteCommandTitle:`在终端中执行命令?`,confirmExecuteMultipleCommands:`即将在本地终端中执行多行命令,是否继续?`,confirmExecuteDangerousCommand:`该命令可能修改系统、发布包、推送代码或执行远程脚本,是否继续?`,terminalCommandExecuteFailed:`在终端中执行命令失败。`,runSubagent:`运行 subagent`,subagentGeneral:`General`,subagentExplore:`Explore`,subagentRunning:`{name} 运行中`,subagentCompleted:`{name} 已完成`,subagentFailed:`{name} 失败`,subagentTask:`任务`,subagentContext:`上下文`,subagentExpectedOutput:`期望输出`,subagentResult:`结果`,subagentToolCalls:`工具调用`,subagentToolApprovalWaiting:`{source} 请求审批:{toolName}`,toolApprovalSourceSubagent:`来源:{source} subagent`,activateSkill:`激活技能`,readSkillResource:`读取技能资源`,yoloModeSyncFailed:`同步 YOLO 模式失败,已恢复为之前的状态。`,toolApprovalFailed:`提交工具审批失败,请重试。`,toolApprovalSubmitting:`提交中...`,terminateCommand:`终止`,terminateCommandTitle:`终止这个正在运行的命令`,commandTerminateRequested:`正在终止...`,running:`运行中`,done:`完成`,error:`错误`,taskCompleted:`对话任务完成`,taskError:`对话任务出错`,called:`已调用`,input:`输入`,output:`输出`,details:`详情`,scheduledTasks:`定时任务`,scheduledTasksDescription:`任务保存在本地后台服务中,并按 AI 解析出的 cron 表达式执行。`,createTask:`创建任务`,editTask:`编辑`,cancelEditTask:`取消编辑`,saveTask:`保存任务`,taskScheduleDescriptionLabel:`定时描述`,taskScheduleDescriptionPlaceholder:`例如:每天早上 9 点,把这段内容发给 AI:帮我生成销售日报。`,quickAiParseTask:`AI 会把这段描述解析为 cron 表达式,系统只保存并按 cron 执行。`,taskTitleLabel:`任务名称`,taskTitlePlaceholder:`例如:每日工作总结`,promptContentLabel:`AI 将发送的内容`,promptContentPlaceholder:`填写到点后原样发送给 AI 的内容。`,taskEnabledSwitch:`启用这个任务`,taskInstructionPlaceholder:`例如:每天早上 9 点帮我生成销售日报`,aiParseTask:`AI 解析任务`,confirmCreate:`确认创建`,taskList:`任务列表`,noScheduledTasks:`还没有定时任务。先输入一句自然语言指令创建一个。`,taskEnabled:`启用中`,taskRunning:`执行中`,taskPaused:`已暂停`,taskFinished:`已完成`,taskFailed:`执行失败`,executeNow:`立即执行`,enable:`启用`,pauseTask:`暂停`,deleteTask:`删除`,recentExecutions:`最近执行记录`,executionSuccess:`成功`,executionRunning:`执行中`,nextExecution:`下一次:`,lastExecution:`上次:`,noModelAvailable:`暂无可用模型`,noProjectBound:`不绑定项目`,aiParsed:`AI 已解析,请确认`,taskName:`任务名称:`,executionRule:`执行规则:`,nextExecutionTime:`下一次执行:`,taskProject:`项目:`,taskThinkingLevel:`思考:`,aiInstruction:`AI 指令:`,taskModel:`模型`,taskThinking:`思考`,taskProjectLabel:`项目`,taskExecutionMode:`执行模式`,taskExecutionModeSerial:`串行`,taskExecutionModeParallel:`并行`,taskExecutionModeHelp:`该设置只控制同一个任务是否允许重叠执行;不同定时任务之间仍可并行执行。`,tasksCount:`共 {total} 个任务,{enabled} 个启用中`,confirmDeleteTask:`确定要删除这个定时任务吗?删除后不可恢复。`,waitingForResult:`等待结果`,autoRun:`自动执行`,manualRun:`手动测试`,runInputContent:`发送给 AI 的内容`,runAiResult:`AI 结果`,runDuration:`耗时:`,taskListTab:`任务列表`,executionHistoryTab:`执行历史`,agentsTab:`Agents`,agentsDescription:`创建可复用的 Agent Profile,用于定时任务和 run_subagent 委派。`,createAgent:`创建 Agent`,editAgent:`编辑 Agent`,builtinAgent:`内置`,builtinAgentReadonly:`内置 Agent 在当前版本中只读。`,enabledAsSubagent:`允许作为 sub agent`,noDescription:`暂无描述。`,maxRuntimeMs:`最大运行时间:`,maxToolCalls:`最大工具调用:`,defaultAgent:`默认 Agent`,executionAgent:`执行 Agent:`,agentName:`Agent 名称`,agentLabel:`显示名称`,agentLabelPlaceholder:`例如:代码审查 Agent`,agentDescription:`描述`,agentSystemPrompt:`系统提示词`,allowedTools:`可用工具`,highRiskTool:`高风险`,confirmDeleteAgent:`确定删除这个自定义 Agent 吗?使用它的定时任务将回退到默认 Agent。`,aiFillAgent:`AI 填充`,aiFillAgentDescription:`描述你想创建的 Agent,AI 只会填充 Agent 名称、显示名称、描述和系统提示词。`,aiFillAgentPlaceholder:`例如:生成一个只读代码审查 Agent,重点检查架构、潜在 bug 和测试覆盖。`,aiFillAgentLoading:`生成中...`,aiFillAgentNoModel:`请先配置默认模型。`,aiFillAgentFailed:`AI 填充失败,请检查模型配置和 API Key 后重试。`,aiFillAgentInputRequired:`请描述你想创建的 Agent。`,taskContent:`任务内容`,viewDetails:`查看详情`,moreActions:`更多操作`,historyFilters:`筛选条件`,allTasks:`全部任务`,allStatuses:`全部状态`,allTriggers:`全部触发方式`,triggerType:`触发方式`,keyword:`关键词`,keywordPlaceholder:`搜索输入、结果或错误`,startTime:`开始时间`,endTime:`结束时间`,query:`查询`,reset:`重置`,previousPage:`上一页`,nextPage:`下一页`,pageSize:`每页 {size} 条`,paginationSummary:`第 {page} / {pages} 页,共 {total} 条`,noExecutionHistory:`暂无执行历史。`,viewConversation:`查看对话`,createdAt:`创建时间`,status:`状态`,search:`搜索`,searchDialog:`搜索对话记录...`,noSearchResults:`没有找到相关对话`,searchHint:`输入关键词搜索已加载的对话记录`,scheduledTasksLabel:`定时任务`,skills:`技能`,mcp:`MCP`,mcpServers:`MCP 服务`,plugins:`插件`,pluginMentionHeader:`插件`,composerAddMenu:`添加`,composerAddAttachment:`附件`,composerAddPlugins:`插件`,composerAddBack:`返回`,pluginOpenaiDocumentsName:`文档`,pluginOpenaiDocumentsDescription:`创建和编辑文档产物`,pluginOpenaiSpreadsheetsName:`表格`,pluginOpenaiSpreadsheetsDescription:`创建、分析和整理表格文件`,pluginOpenaiPresentationsName:`演示文稿`,pluginOpenaiPresentationsDescription:`创建和编辑演示文稿`,pluginsDescription:`管理本地 QuickForge 插件。当前首版支持通过 manifest 声明并贡献 Agent 工具的插件。`,pluginsReload:`重新加载插件`,loadingPlugins:`正在加载插件...`,noPlugins:`未发现插件`,noPluginsDescription:`将包含 plugin.json 的插件目录放到以下任一搜索路径,然后重新加载。`,pluginsCount:`共 {total} 个插件,{enabled} 个已启用`,pluginToolsCount:`{count} 个工具`,pluginPermissionsCount:`{count} 个权限`,pluginDetails:`插件详情`,pluginVersion:`版本`,pluginStatusLoaded:`已加载`,pluginStatusDisabled:`已停用`,pluginStatusError:`错误`,pluginTools:`工具`,pluginPermissions:`声明权限`,pluginNoTools:`未声明工具。`,pluginNoPermissions:`未声明权限。`,pluginTrustedNotice:`首版插件属于本地可信 Node.js 代码;权限目前用于展示和后续强校验。`,pluginDiscoveryErrors:`插件发现错误`,enablePlugin:`启用`,disablePlugin:`禁用`,pluginsLoadFailed:`加载插件失败。`,pluginsSaveFailed:`更新插件失败。`,manageMcpServers:`管理 MCP 服务`,mcpNoServersDescription:`还没有配置 MCP 服务。点击「添加服务」,或在右侧粘贴 mcpServers JSON 配置。`,mcpConfiguredServers:`已配置服务`,mcpReconnect:`重新连接`,mcpAddServer:`添加服务`,mcpEditServer:`编辑服务`,mcpServerName:`服务名称`,mcpCommand:`命令`,mcpTransport:`传输方式`,mcpUrl:`URL`,mcpArgs:`参数,每行一个`,mcpCwd:`工作目录`,mcpEnv:`环境变量,每行 KEY=value`,mcpToolsCount:`{count} 个工具`,mcpLoadFailed:`加载 MCP 服务失败。`,mcpSaveFailed:`保存 MCP 服务失败。`,mcpDeleteFailed:`删除 MCP 服务失败。`,mcpReconnectFailed:`重新连接 MCP 服务失败。`,mcpDeleteConfirm:`确定删除 MCP 服务「{name}」吗?`,mcpImportConfig:`导入 MCP JSON`,mcpImportConfigDescription:"直接粘贴 mcpServers 格式的 MCP JSON 配置。QuickForge 支持 stdio、HTTP 和 SSE 传输;远程服务可使用 headers,并支持通过 ${...} 从后端进程环境变量读取。",mcpUseExample:`使用示例`,mcpImportUpdate:`导入 / 更新`,mcpReplaceAll:`替换全部`,mcpReplaceConfirm:`这会删除当前未包含在 JSON 中的 MCP 服务,确定继续吗?`,mcpInvalidJson:`MCP 配置必须是合法 JSON。`,mcpInvalidConfigJson:`MCP 配置必须包含 mcpServers 对象。`,mcpEmptyConfigJson:`mcpServers 不能为空。`,mcpInvalidServerName:`MCP 服务名称无效:{name}。请只使用小写字母、数字和连字符。`,mcpInvalidServerConfig:`MCP 服务「{name}」必须是对象。`,mcpInvalidTransport:`MCP 服务「{name}」的传输方式必须是 stdio、http 或 sse。`,mcpMissingCommand:`MCP 服务「{name}」使用 stdio 传输时必须提供 command。`,mcpMissingUrl:`MCP 服务「{name}」使用 HTTP/SSE 传输时必须提供 url。`,mcpArgsMustBeArray:`MCP 服务「{name}」的 args 必须是数组。`,mcpEnvMustBeObject:`MCP 服务「{name}」的 env 必须是对象。`,mcpHeadersMustBeObject:`MCP 服务「{name}」的 headers 必须是对象。`,mcpHeaders:`Headers,每行 KEY=value`,mcpReconnectServer:`重连`,mcpMoreTools:`+{count}`,mcpNamePlaceholder:`例如 my-server`,mcpUrlPlaceholder:`https://example.com/mcp`,mcpCommandPlaceholder:`例如 npx`,mcpTabServer:`服务`,mcpTabJson:`JSON`,optional:`可选`,globalSkills:`全局技能`,projectSkills:`项目技能`,help:`帮助`,projectCommands:`项目命令`,projectCommandsDescription:`为当前项目配置额外的 Markdown slash command 目录。QuickForge 还会读取用户级目录 ~/.quickforge/commands/(所有项目共享),然后依次读取项目目录 .claude/commands、.opencode/commands、.ai/commands 及此处的配置目录;同名 command 以后面的目录覆盖前面的目录。`,selectProjectForCommands:`请先选择或添加一个项目,再配置项目命令。`,commandDirectory:`命令目录`,commandDirectories:`命令目录`,commandDirectoryPlaceholder:`.claude/commands
|
|
9
|
+
.opencode/commands
|
|
10
|
+
D:\\shared\\ai-commands`,commandDirectoryHelp:`一行一个目录。支持相对路径和绝对路径。相对路径会基于当前项目根目录解析。留空则只使用内置兼容命令目录。`,commandDirectoryExamples:`示例`,projectCommandsSaved:`项目命令设置已保存。`,loadedCommands:`已加载命令({count})`,noCommandsLoaded:`暂未加载到任何命令。请在上方添加目录或新建命令后重试。`,openCommandDir:`打开命令目录`,createCommand:`新建命令`,newCommandPrompt:`请输入命令名(小写字母、数字、连字符):`,commandCreated:`命令已创建:{name}`,commandAlreadyExists:`命令已存在:{name}`,invalidCommandName:`命令名无效,请使用小写字母、数字和连字符。`,manageSkills:`管理技能`,manageGlobalSkills:`管理全局技能`,manageProjectSkills:`管理项目技能`,openFolder:`打开文件夹`,openInExplorer:`在资源管理器打开`,openInExplorerFailed:`打开项目目录失败。`,moreOptions:`更多选项`,pinSession:`置顶对话`,unpinSession:`取消置顶`,shareSession:`分享对话`,selectProjectForSkills:`请先选择或添加一个项目,再管理技能。`,skillsDescription:`选择项目「{project}」启用的 Agent Skills。QuickForge 只在提示词中披露名称/描述;完整 SKILL.md 指令会在需要时通过 activate_skill 按需加载。`,globalSkillsDescription:`选择 QuickForge 全局启用的 Agent Skills。技能会从 ~/.claude/skills、~/.opencode/skills、~/.agents/skills 和 ~/.quickforge/skills 发现。新对话只注入目录,完整指令按需加载。`,projectSkillsDescription:`选择项目「{project}」启用的 Agent Skills。项目技能从 .claude/skills、.opencode/skills、.agents/skills 和 .quickforge/skills 发现;同名项目技能会覆盖全局技能,并只在新项目对话中按需加载。`,searchSkills:`搜索技能...`,availableSkills:`可用技能`,selectedSkillsCount:`已选择 {count} 个`,noMatchingSkills:`没有匹配的技能`,skillSearchPaths:`搜索路径`,failedToLoadSkills:`加载技能失败。`,failedToSaveSkills:`保存技能失败。`,readSkill:`阅读技能`,readSkillContent:`阅读技能内容`,backToSkillList:`返回技能列表`,failedToReadSkill:`读取技能内容失败。`,noSkillContent:`该技能没有可阅读的内容。`,requestFailed:`请求失败`,backupRestore:`备份与恢复`,backupRestoreDescription:`导出或恢复 QuickForge 的设置、模型提供商、项目、定时任务和对话。导入前本地服务会先创建一份安全备份。备份可能包含敏感对话、本机路径、代码片段,并可选包含 API Key。`,exportData:`导出数据`,exportDataDescription:`下载 JSON 备份文件,可自行保存或迁移到其他 QuickForge 安装。默认不包含 API Key,除非你明确勾选。`,exportScope:`导出范围`,exportScopeAll:`全部数据`,exportScopeConfig:`仅配置`,exportScopeSessions:`仅对话`,includeApiKeys:`包含 API Key`,includeApiKeysDescription:`API Key 属于敏感信息。仅在私密加密保存或可信迁移时启用。`,backupExportSecretsConfirm:`此备份将包含 API Key。请不要提交到 Git 或分享给不可信人员。是否继续?`,exportBackup:`导出备份`,backupExported:`备份已导出。`,backupExportFailed:`导出备份失败。`,importData:`导入数据`,importDataDescription:`恢复之前导出的 JSON 备份。系统会先检查文件内容,然后替换当前本地数据中对应的部分。`,importBackup:`导入备份`,backupInspectTitle:`备份预览`,backupInspectExportedAt:`导出时间`,backupInspectVersion:`版本`,backupInspectScope:`范围`,backupInspectSecrets:`包含 API Key`,backupInspectSections:`数据项`,backupInspectFailed:`检查备份失败。`,backupInspected:`备份已检查,请在下方选择要恢复的数据。`,selectRestoreSections:`选择要恢复的数据`,confirmImportSelected:`导入所选数据`,selectAtLeastOneRestoreSection:`请至少选择一个要恢复的数据项。`,restoreSettings:`设置`,restoreSettingsDescription:`语言、默认选项等应用偏好设置。`,restoreProviderKeys:`API Key`,restoreProviderKeysDescription:`敏感的模型提供商 API Key。恢复后会替换当前保存的密钥。`,restoreCustomProviders:`自定义提供商和模型`,restoreCustomProvidersDescription:`自定义模型提供商、端点、模型 ID 及相关配置。`,restoreProjects:`项目`,restoreProjectsDescription:`项目列表、当前项目和已选择的技能。`,restoreScheduledTasks:`定时任务`,restoreScheduledTasksDescription:`已保存的 AI 定时任务。`,restoreConversations:`对话`,restoreConversationsDescription:`对话历史和元数据。会作为一个一致的整体恢复。`,backupImportConfirm:`导入会替换当前 QuickForge 本地数据中对应的部分。系统会先创建安全备份。是否继续?`,backupImported:`备份已导入,应用即将刷新。`,backupImportFailed:`导入备份失败。`,backupSafetyBackupPath:`安全备份保存位置`,backendService:`后端服务`,backendServiceDescription:`重启 QuickForge 本地后端服务。正在运行的生成会被中断,页面会自动重新连接。`,backendServiceStatus:`服务状态`,restartBackendService:`重启后端服务`,restartBackendServiceDescription:`当本地后端卡住,或调整了服务级环境配置后,可以在这里重启。`,restartBackendConfirm:`确定现在重启后端服务吗?正在运行的生成会被中断,页面会自动重新连接。`,backendRestarting:`后端正在重启...`,backendRestarted:`后端已重启,正在刷新页面...`,backendRestartFailed:`后端重启失败。`,backendRestartTimeout:`后端重启超时,请手动重启 QuickForge。`,backendRestartUnsupported:`当前启动方式不支持从界面重启,请手动重启 QuickForge。`,serviceMode:`模式`,servicePid:`PID`,serviceStartedAt:`启动时间`,serviceDataDir:`数据目录`,serviceWorkspace:`工作区`,terminalShell:`终端 Shell`,terminalShellDescription:`QuickForge 会自动识别这台电脑上常见的 macOS、Windows 和 Linux Shell。勾选默认项即可;只有缺少时才需要添加自定义命令或路径。QUICKFORGE_TERMINAL_SHELL 仍会优先生效。`,terminalShellAutoDetectedHint:`已识别的条目会自动显示在列表中。`,terminalShellDefault:`默认 Shell`,terminalShellSaved:`终端 Shell 设置已保存,新建终端会话会使用该设置。`,terminalShellProfilesSaved:`终端 Shell 配置已保存。`,terminalShellCommand:`自定义 Shell 命令或路径`,terminalShellCommandPlaceholder:`C:\\Program Files\\Git\\bin\\bash.exe`,terminalShellAdd:`添加`,terminalShellSetDefault:`设为默认`,terminalShellDefaultBadge:`默认`,terminalShellDetected:`已识别`,terminalShellNoDetected:`未识别到可用 Shell,请在下方添加自定义 Shell 命令或路径。`,terminalShellProfileRequired:`保存前请输入 Shell 命令或可执行文件路径。`,terminalShellDeleteConfirm:`确定删除终端 Shell 配置“{name}”吗?`,terminalNew:`新建终端`,terminalNewWith:`新建终端使用`,terminalNewWithProfile:`新建终端:{name}`,terminalSelectShell:`选择 Shell 新建终端`,terminalCollapse:`收起终端`,terminalFullscreen:`全屏终端`,terminalExitFullscreen:`退出全屏`,terminalStarting:`正在启动终端...`,terminalUnavailable:`终端不可用`,terminalNoSessions:`没有终端会话`,terminalCreateFailed:`创建终端失败`,terminalCloseFailed:`关闭终端失败`,terminalConnectionFailed:`连接终端失败。`,terminalConnectionClosedUnexpectedly:`终端连接异常断开。`,terminalCloseSession:`关闭 {name}`,workspaceNoFilesToDisplay:`没有可显示的文件。`,workspaceNoWorkingTreeChanges:`工作区没有变更。`,noProjectSelected:`未选择项目`,workspacePanel:`工作空间`,workspaceOverview:`概览`,workspaceFiles:`工作空间文件`,workspaceBrowser:`浏览器`,workspaceChanges:`变更`,workspaceCurrentArtifacts:`本次 AI 修改`,workspaceNoArtifacts:`未检测到本轮 AI 产生的文件。直接 write_file/edit_file 修改会显示在这里;命令执行会作为低置信度线索展示。`,workspaceCommands:`命令`,workspaceCurrentBranch:`当前分支`,workspaceChangeCount:`项变更`,workspaceNotGitRepository:`此项目不是 Git 仓库。`,workspaceSelectProject:`请选择一个项目来查看工作空间。`,workspaceLoading:`正在加载工作空间...`,workspaceLoadFailed:`加载工作空间失败。`,workspaceFilterFiles:`按名称或路径筛选文件`,workspaceOpenFileHint:`点击文件可打开 Monaco 阅读器。`,workspaceOpenFileFailed:`打开文件失败。`,workspaceOpenDiffFailed:`打开 diff 失败。`,refreshWorkspace:`刷新工作空间`,closeWorkspace:`关闭工作空间`,workspaceStaged:`已暂存`,workspaceUntracked:`未跟踪`,workspaceConflicts:`冲突`,workspaceStagedChanges:`已暂存变更`,workspaceReview:`审查`,workspaceCommitMessage:`提交信息`,unknown:`未知`,webPreview:`网页预览`,closeWebPreview:`关闭网页预览`,previewUrl:`预览地址`,previewUrlPlaceholder:`http://localhost:5173`,openPreview:`打开`,refreshPreview:`刷新预览`,openInBrowser:`在浏览器中打开`,invalidPreviewUrl:`请输入有效的 http:// 或 https:// 地址。`,noPreviewUrlTitle:`输入预览地址`,noPreviewUrlDescription:`先在终端中运行项目开发服务器,然后在这里输入本地地址。Vite、Next、Astro 等工具通常会通过 HMR 实时更新。`,workspaceStatusAdded:`新增`,workspaceStatusDeleted:`删除`,workspaceStatusRenamed:`重命名`,workspaceStatusUntracked:`未跟踪`,workspaceStatusConflict:`冲突`,workspaceStatusModified:`修改`,lanAccess:`局域网访问`,lanAccessDescription:`允许同一局域网内可信设备在输入密码后访问完整 QuickForge。`,lanAccessRiskWarning:`高风险:通过密码的局域网设备可以访问你的对话、项目和可用工具。请只在可信网络中开启。`,lanAccessStatus:`局域网访问状态`,lanAccessEnabled:`完整局域网访问`,lanAccessPassword:`访问密码`,lanAccessActiveDevices:`已解锁设备`,lanAccessUrls:`局域网地址`,lanAccessAllowFull:`允许局域网设备访问完整 QuickForge`,lanAccessPasswordPlaceholder:`至少 8 个字符`,lanAccessPasswordPlaceholderConfigured:`留空则保留当前密码`,lanAccessSessionTtl:`登录有效期`,lanAccessRevokeAll:`踢掉所有局域网设备`,lanAccessRevokeAllConfirm:`确定要让所有已解锁的局域网设备退出登录吗?`,lanAccessEnableConfirm:`确定开启完整局域网访问吗?请仅在可信网络中继续。`,lanAccessPasswordRequired:`开启局域网访问前请先设置访问密码。`,lanAccessPasswordTooShort:`访问密码至少需要 8 个字符。`,lanAccessSaved:`局域网访问设置已保存。`,lanAccessRevoked:`所有局域网设备已退出登录。`,enabled:`已开启`,disabled:`已关闭`,configured:`已设置`,notConfigured:`未设置`,generatePassword:`生成密码`,hour:`小时`,hours:`小时`,days:`天`,toolApprovalWaiting:`等待审批:{toolName}`,autoCompactApprovalWaiting:`上下文已达到 {percent}%(阈值 {threshold}%),是否现在压缩?`,autoCompactApprovalPreview:`QuickForge 会总结较早历史,并使用摘要加最近 {keepRecentTurns} 个用户回合继续任务。完整聊天历史仍会保留在界面中。`,autoCompactFailed:`自动上下文压缩失败,将继续使用当前历史。`,contextCompactedTimelineLabel:`较早上下文已整理为摘要供模型使用`,contextCompactedLabel:`已压缩上下文`,contextCompactedTooltip:`此对话的模型请求正在使用摘要上下文,完整聊天历史仍会保留在界面中。`,contextCompactedViewSummary:`查看摘要`,contextCompactedHideSummary:`收起摘要`,contextCompactedSummaryTitle:`模型正在使用的压缩摘要`,contextCompactedCopySummary:`复制摘要`,toolApprovalAccept:`✓ 允许`,toolApprovalReject:`✗ 拒绝`,toolApprovalTimeout:`超时时间`,toolApprovalTruncated:`...(内容已截断)`,processed:`已处理`,processing:`处理中`,processFailed:`处理出错`,processAborted:`已中止`,expandProcess:`展开处理详情`,collapseProcess:`收起处理详情`,relativeMinuteShort:`{count}分`,relativeHourShort:`{count}小时`,relativeDayShort:`{count}天`,relativeWeekShort:`{count}周`,relativeYearShort:`{count}年`}},Pe={...Te.en,"Configure API keys for LLM providers. Keys are stored locally in your browser.":`Configure API keys for LLM providers. Keys are stored by the local QuickForge service on this machine.`,"Settings are stored locally in your browser":`Settings are stored by the local QuickForge service on this machine`,"Storage Permission Required":`Local Service Required`,"This app needs persistent storage to save your conversations":`This app needs the local QuickForge service to save your conversations`,"Without persistent storage, your browser may delete saved conversations when it needs disk space. Granting this permission ensures your chat history is preserved.":`QuickForge saves data to local files through the local service on this machine so your chat history is preserved.`,"Your conversations will be saved locally in your browser":`Your conversations will be saved to local files by the local QuickForge service`,"Cloud LLM providers with predefined models. API keys are stored locally in your browser.":`Cloud LLM providers with predefined models. API keys are stored by the local QuickForge service on this machine.`},Fe={...Te.en,Free:`免费`,"Input Required":`需要输入`,Cancel:`取消`,Confirm:`确认`,"Select Model":`选择模型`,"Search models...":`搜索模型...`,Format:`格式`,Thinking:`思考`,Vision:`视觉`,You:`你`,Assistant:`助手`,"Thinking...":`正在思考...`,"Type your message...":`输入你的消息...`,"API Keys Configuration":`API Key 配置`,"Configure API keys for LLM providers. Keys are stored locally in your browser.":`配置 LLM 提供商的 API Key。密钥会由本机 QuickForge 本地服务保存。`,Configured:`已配置`,"Not configured":`未配置`,"✓ Valid":`✓ 有效`,"✗ Invalid":`✗ 无效`,"Testing...":`测试中...`,Update:`更新`,Test:`测试`,Remove:`移除`,Save:`保存`,"Update API key":`更新 API Key`,"Enter API key":`输入 API Key`,"Type a message...":`输入消息...`,"Failed to fetch file":`获取文件失败`,"Invalid source type":`无效的来源类型`,PDF:`PDF`,Document:`文档`,Presentation:`演示文稿`,Spreadsheet:`电子表格`,Text:`文本`,"Error loading file":`加载文件出错`,"No text content available":`没有可用的文本内容`,"Failed to load PDF":`加载 PDF 失败`,"Failed to load document":`加载文档失败`,"Failed to load spreadsheet":`加载电子表格失败`,"Error loading PDF":`加载 PDF 出错`,"Error loading document":`加载文档出错`,"Error loading spreadsheet":`加载电子表格出错`,"Preview not available for this file type.":`此文件类型不支持预览。`,"Click the download button above to view it on your computer.":`点击上方下载按钮在电脑上查看。`,"No content available":`没有可用内容`,"Failed to display text content":`显示文本内容失败`,"API keys are required to use AI models. Get your keys from the provider's website.":`使用 AI 模型需要 API Key。请从提供商网站获取。`,console:`控制台`,"Copy output":`复制输出`,"Copied!":`已复制!`,"Error:":`错误:`,"Request aborted":`请求已中止`,Call:`调用`,Result:`结果`,"(no result)":`(无结果)`,"Waiting for tool result…":`等待工具结果…`,"Call was aborted; no result.":`调用已中止,没有结果。`,"No session available":`没有可用会话`,"No session set":`未设置会话`,"Preparing tool parameters...":`正在准备工具参数...`,"(no output)":`(无输出)`,Input:`输入`,Output:`输出`,"Writing expression...":`正在写入表达式...`,"Waiting for expression...":`等待表达式...`,Calculating:`计算中`,"Getting current time in":`正在获取当前时间:`,"Getting current date and time":`正在获取当前日期和时间`,"Waiting for command...":`等待命令...`,"Writing command...":`正在写入命令...`,"Running command...":`正在运行命令...`,"Command failed:":`命令失败:`,"Enter Auth Token":`输入认证令牌`,"Please enter your auth token.":`请输入你的认证令牌。`,"Execution aborted":`执行已中止`,"Code parameter is required":`需要代码参数`,"Unknown error":`未知错误`,"Code executed successfully (no output)":`代码执行成功(无输出)`,"Execution failed":`执行失败`,"JavaScript REPL":`JavaScript REPL`,"JavaScript code to execute":`要执行的 JavaScript 代码`,"Writing JavaScript code...":`正在写入 JavaScript 代码...`,"Executing JavaScript":`正在执行 JavaScript`,"Preparing JavaScript...":`正在准备 JavaScript...`,"Preparing command...":`正在准备命令...`,"Preparing calculation...":`正在准备计算...`,"Preparing tool...":`正在准备工具...`,"Getting time...":`正在获取时间...`,"Processing artifact...":`正在处理产物...`,"Preparing artifact...":`正在准备产物...`,"Processing artifact":`正在处理产物`,"Processed artifact":`已处理产物`,"Creating artifact":`正在创建产物`,"Created artifact":`已创建产物`,"Updating artifact":`正在更新产物`,"Updated artifact":`已更新产物`,"Rewriting artifact":`正在重写产物`,"Rewrote artifact":`已重写产物`,"Getting artifact":`正在获取产物`,"Got artifact":`已获取产物`,"Deleting artifact":`正在删除产物`,"Deleted artifact":`已删除产物`,"Getting logs":`正在获取日志`,"Got logs":`已获取日志`,"An error occurred":`发生错误`,"Copy logs":`复制日志`,"Autoscroll enabled":`已启用自动滚动`,"Autoscroll disabled":`已关闭自动滚动`,Processing:`处理中`,Create:`创建`,Rewrite:`重写`,Get:`获取`,Delete:`删除`,"Get logs":`获取日志`,"Show artifacts":`显示产物`,"Close artifacts":`关闭产物`,Artifacts:`产物`,"Copy HTML":`复制 HTML`,"Download HTML":`下载 HTML`,"Reload HTML":`重新加载 HTML`,"Copy SVG":`复制 SVG`,"Download SVG":`下载 SVG`,"Copy Markdown":`复制 Markdown`,"Download Markdown":`下载 Markdown`,Download:`下载`,"No logs for {filename}":`{filename} 没有日志`,"API Keys Settings":`API Key 设置`,Settings:`设置`,"API Keys":`API Key`,"Settings are stored locally in your browser":`设置会由本机 QuickForge 本地服务保存`,Clear:`清除`,"API Key Required":`需要 API Key`,"Enter your API key for {provider}":`输入 {provider} 的 API Key`,Off:`关闭`,Minimal:`最小`,Low:`低`,Medium:`中`,High:`高`,"Storage Permission Required":`需要本地服务`,"This app needs persistent storage to save your conversations":`此应用需要 QuickForge 本地服务来保存你的对话`,"Why is this needed?":`为什么需要?`,"Without persistent storage, your browser may delete saved conversations when it needs disk space. Granting this permission ensures your chat history is preserved.":`QuickForge 会通过本机本地服务把数据保存到本地文件中,确保聊天历史可持久保留。`,"What this means:":`这意味着:`,"Your conversations will be saved locally in your browser":`你的对话会由本机 QuickForge 本地服务保存到本地文件`,"Data will not be deleted automatically to free up space":`数据不会被自动删除来释放空间`,"You can still manually clear data at any time":`你仍然可以随时手动清除数据`,"No data is sent to external servers":`不会向外部服务器发送数据`,"Continue Anyway":`仍然继续`,"Requesting...":`请求中...`,"Grant Permission":`授予权限`,Sessions:`会话`,"Load a previous conversation":`加载之前的对话`,"No sessions yet":`暂无会话`,"Delete this session?":`删除此会话?`,Today:`今天`,Yesterday:`昨天`,"{days} days ago":`{days} 天前`,messages:`条消息`,tokens:`tokens`,"Drop files here":`将文件拖到这里`,"Providers & Models":`提供商与模型`,"Cloud Providers":`云提供商`,"Cloud LLM providers with predefined models. API keys are stored locally in your browser.":`带有预定义模型的云 LLM 提供商。API Key 会由本机 QuickForge 本地服务保存。`,"Custom Providers":`自定义提供商`,"User-configured servers with auto-discovered or manually defined models.":`用户配置的服务器,支持自动发现或手动定义模型。`,"Add Provider":`添加提供商`,"No custom providers configured. Click 'Add Provider' to get started.":`尚未配置自定义提供商。点击"添加提供商"开始。`,Models:`模型`,"auto-discovered":`自动发现`,Refresh:`刷新`,Edit:`编辑`,"Are you sure you want to delete this provider?":`确定删除这个提供商吗?`,"Edit Provider":`编辑提供商`,"Provider Name":`提供商名称`,"e.g., My Ollama Server":`例如:我的 Ollama 服务`,"Provider Type":`提供商类型`,"Base URL":`Base URL`,"e.g., http://localhost:11434":`例如:http://localhost:11434`,"API Key (Optional)":`API Key(可选)`,"Leave empty if not required":`不需要可以留空`,"Test Connection":`测试连接`,Discovered:`已发现`,models:`个模型`,and:`以及`,more:`更多`,"For manual provider types, add models after saving the provider.":`手动提供商类型需要保存提供商后再添加模型。`,"Please fill in all required fields":`请填写所有必填项`,"Failed to save provider":`保存提供商失败`,"OpenAI Completions Compatible":`OpenAI Completions 兼容`,"OpenAI Responses Compatible":`OpenAI Responses 兼容`,"Anthropic Messages Compatible":`Anthropic Messages 兼容`,"Checking...":`检查中...`,Disconnected:`未连接`,"*":`*`,Copy:`复制`,"Copy code":`复制代码`,Close:`关闭`,Preview:`预览`,Code:`代码`,"Loading...":`加载中...`,"Select an option":`选择一个选项`,"Mode 1":`模式 1`,"Mode 2":`模式 2`,Required:`必填`,Optional:`可选`},Ie=Le();function Le(){return typeof navigator<`u`&&navigator.language.toLowerCase().startsWith(`zh`)?`zh`:`en`}function Re(e){return typeof e==`string`&&Me.includes(e)}function ze(e){typeof document>`u`||(document.documentElement.lang=e===`zh`?`zh-CN`:`en`,document.documentElement.dir=`ltr`)}function K(e){let t=e===`zh`?Fe:Pe;for(let e of Object.keys(Te))Te[e]=t}function Be(e){Ie=e,K(e),ze(e)}Te.zh=Fe,Be(Ie);function Ve(){return Ie}function q(e,t){let n=Ne[Ve()][e]??Ne.en[e];if(!t)return n;for(let[e,r]of Object.entries(t))n=n.replaceAll(`{${e}}`,String(r));return n}function He(){return Ve()===`zh`?`zh-CN`:`en-US`}async function Ue(e){let t=await e.settings.get(G),n=Re(t)?t:Le();return Re(t)||await e.settings.set(G,n),Be(n),n}async function We(e,t){return t===Ve()?!1:(await e.settings.set(G,t),Be(t),window.location.reload(),!0)}var Ge=new Set([`off`,`low`,`medium`,`high`,`xhigh`]),Ke=[{value:`off`,label:()=>B(`Off`)},{value:`low`,label:()=>B(`Low`)},{value:`medium`,label:()=>B(`Medium`)},{value:`high`,label:()=>B(`High`)},{value:`xhigh`,label:()=>Ve()===`zh`?`极高`:`XHigh`}];function qe(e){return typeof e==`string`&&Ge.has(e)}function Je(e){return Array.from(e.querySelectorAll(`.flex.gap-2.items-center`)).find(e=>e.querySelector(`button[role="combobox"]`)||e.querySelector(`[data-quickforge-thinking-selector]`))}function Ye(e,t){fe(Se({value:qe(t.thinkingLevel)?t.thinkingLevel:`off`,placeholder:B(`Off`),options:Ke.map(e=>({value:e.value,label:e.label(),icon:be(ye,`sm`)})),onChange:e=>{let n=qe(e)?e:`off`;t.thinkingLevel=n,t.onThinkingChange?.(n),t.requestUpdate?.()},width:`80px`,size:`sm`,variant:`ghost`,fitContent:!0}),e)}function Xe(e){let t=e;qe(t.thinkingLevel)||(t.thinkingLevel=`off`,t.onThinkingChange?.(`off`));let n=Je(e);if(!n)return;let r=n.querySelector(`[data-quickforge-thinking-selector]`);if(r){Ye(r,t);return}let i=n.querySelector(`button[role="combobox"]`);if(!i)return;i.style.display=`none`,i.setAttribute(`aria-hidden`,`true`);let a=document.createElement(`span`);a.dataset.quickforgeThinkingSelector=`true`,i.insertAdjacentElement(`afterend`,a),Ye(a,t)}function Ze(e={}){let{hideSelector:t=!1}=e,n=()=>{let e=customElements.get(`message-editor`);if(!e?.prototype.render||e.prototype.render.__quickforgePatched)return;let n=e.prototype.render;e.prototype.render=function(){let e=n.call(this);return queueMicrotask(()=>{if(t){let e=this;e.showThinkingSelector!==!1&&(e.showThinkingSelector=!1,e.requestUpdate?.());return}Xe(this)}),e},e.prototype.render.__quickforgePatched=!0};if(customElements.get(`message-editor`)){n();return}customElements.whenDefined(`message-editor`).then(n).catch(()=>{})}function Qe(e){return new Promise((t,n)=>{let r=document.createElement(`textarea`);r.value=e,r.style.position=`fixed`,r.style.left=`-9999px`,r.style.top=`-9999px`,r.style.opacity=`0`,document.body.append(r),r.select();try{document.execCommand(`copy`)?t():n(Error(`execCommand("copy") returned false`))}catch(e){n(e)}finally{r.remove()}})}function $e(){navigator.clipboard||Object.defineProperty(navigator,`clipboard`,{value:{writeText:Qe,readText:()=>Promise.reject(Error(`Clipboard read is not available in non-secure contexts`)),read:()=>Promise.reject(Error(`Clipboard read is not available in non-secure contexts`)),write:()=>Promise.reject(Error(`Clipboard write is not available in non-secure contexts`))},configurable:!0,enumerable:!0,writable:!1})}function J(...e){return he(me(e))}var Y=ue(),et=ge(`inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0`,{variants:{variant:{default:`bg-primary text-primary-foreground hover:bg-primary/90`,destructive:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,outline:`border border-input bg-background hover:bg-accent hover:text-accent-foreground`,secondary:`bg-secondary text-secondary-foreground hover:bg-secondary/80`,ghost:`hover:bg-accent hover:text-accent-foreground`},size:{default:`h-9 px-4 py-2`,sm:`h-8 rounded-md px-3`,icon:`size-9`}},defaultVariants:{variant:`default`,size:`default`}}),X=W.forwardRef(({className:e,variant:t,size:n,...r},i)=>(0,Y.jsx)(`button`,{className:J(et({variant:t,size:n,className:e})),ref:i,...r}));X.displayName=`Button`;var tt=class extends W.Component{constructor(e){super(e),this.state={error:null}}static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e,t){U.error(`ErrorBoundary caught an error:`,e,t)}handleRetry=()=>{this.setState({error:null})};handleReload=()=>{window.location.reload()};render(){return this.state.error?this.props.fallback?this.props.fallback:(0,Y.jsx)(`div`,{className:`flex h-screen items-center justify-center bg-background p-6 text-foreground`,children:(0,Y.jsxs)(`div`,{className:`max-w-md rounded-lg border border-border bg-card p-5 shadow-sm text-center`,children:[(0,Y.jsx)(`h1`,{className:`text-base font-semibold`,children:q(`errorBoundaryTitle`)}),(0,Y.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground break-all`,children:this.state.error.message||q(`errorBoundaryUnexpected`)}),(0,Y.jsxs)(`div`,{className:`mt-4 flex justify-center gap-2`,children:[(0,Y.jsx)(X,{variant:`outline`,size:`sm`,onClick:this.handleRetry,children:q(`errorBoundaryTryAgain`)}),(0,Y.jsx)(X,{variant:`default`,size:`sm`,onClick:this.handleReload,children:q(`reloadPage`)})]})]})}):this.props.children}};async function nt(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||`HTTP ${e.status}`);return t}function rt({open:e,initialPath:t,disabled:n,onOpenChange:r,onSelect:i}){let a=(0,W.useRef)(null),[o,s]=(0,W.useState)([]),[c,l]=(0,W.useState)(``),[u,d]=(0,W.useState)(``),[f,h]=(0,W.useState)(null),[g,_]=(0,W.useState)([]),[v,y]=(0,W.useState)(!1),[b,x]=(0,W.useState)(!1),[S,C]=(0,W.useState)(``),w=async e=>{if(e.trim()){y(!0),C(``);try{let t=await nt(await fetch(`/api/filesystem/directories?path=${encodeURIComponent(e.trim())}`));l(t.path),d(t.path),h(t.parent),_(Array.isArray(t.directories)?t.directories:[])}catch(e){C(e instanceof Error?e.message:q(`directoryLoadFailed`))}finally{y(!1)}}};return(0,W.useEffect)(()=>{if(!e)return;let n=!1;return(async()=>{y(!0),C(``);try{let e=await nt(await fetch(`/api/filesystem/roots`));if(n)return;let r=Array.isArray(e.roots)?e.roots:[];s(r);let i=t||r[0]?.path||``;i&&await w(i)}catch(e){n||C(e instanceof Error?e.message:q(`filesystemRootsFailed`))}finally{n||y(!1)}})(),window.setTimeout(()=>a.current?.focus(),0),()=>{n=!0}},[t,e]),(0,W.useEffect)(()=>{if(!e)return;let t=e=>{e.key===`Escape`&&!b&&r(!1)};return document.addEventListener(`keydown`,t),()=>document.removeEventListener(`keydown`,t)},[r,e,b]),e?(0,Y.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,onClick:e=>{e.target===e.currentTarget&&!b&&r(!1)},children:(0,Y.jsxs)(`div`,{className:`flex max-h-[85vh] w-full max-w-2xl flex-col rounded-lg border border-border bg-background shadow-xl`,children:[(0,Y.jsxs)(`div`,{className:`border-b border-border p-4`,children:[(0,Y.jsx)(`h2`,{className:`text-base font-semibold text-foreground`,children:q(`selectProjectDirectory`)}),(0,Y.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:q(`selectProjectDirectoryDescription`)})]}),(0,Y.jsxs)(`div`,{className:`space-y-4 overflow-y-auto p-4`,children:[o.length>0?(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`div`,{className:`mb-2 text-xs font-medium uppercase tracking-wide text-muted-foreground`,children:q(`quickAccess`)}),(0,Y.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:o.map(e=>(0,Y.jsx)(X,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>w(e.path),disabled:v||b,children:e.name},`${e.name}:${e.path}`))})]}):null,(0,Y.jsxs)(`form`,{className:`space-y-2`,onSubmit:e=>{e.preventDefault(),w(u)},children:[(0,Y.jsx)(`label`,{className:`text-xs font-medium uppercase tracking-wide text-muted-foreground`,htmlFor:`project-path-input`,children:q(`path`)}),(0,Y.jsxs)(`div`,{className:`flex gap-2`,children:[(0,Y.jsx)(`input`,{id:`project-path-input`,ref:a,className:J(`min-w-0 flex-1 rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground shadow-sm`,`focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring`),value:u,onChange:e=>d(e.target.value),placeholder:q(`folderPickerPathPlaceholder`),disabled:v||b}),(0,Y.jsx)(X,{type:`submit`,variant:`outline`,disabled:v||b||!u.trim(),children:q(`go`)})]})]}),S?(0,Y.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:S}):null,(0,Y.jsxs)(`div`,{className:`rounded-md border border-border`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center justify-between gap-2 border-b border-border px-3 py-2`,children:[(0,Y.jsx)(`div`,{className:`min-w-0 truncate text-sm font-medium`,title:c,children:c||q(`loading`)}),v?(0,Y.jsx)(p,{className:`size-4 shrink-0 animate-spin text-muted-foreground`}):null]}),(0,Y.jsxs)(`div`,{className:`max-h-80 overflow-y-auto p-1`,children:[f?(0,Y.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm hover:bg-secondary disabled:opacity-50`,onClick:()=>w(f),disabled:v||b,children:[(0,Y.jsx)(I,{className:`size-4 text-muted-foreground`}),(0,Y.jsx)(`span`,{children:q(`parentDirectory`)})]}):null,!v&&g.length===0?(0,Y.jsx)(`div`,{className:`px-3 py-8 text-center text-sm text-muted-foreground`,children:q(`noFolders`)}):null,g.map(e=>(0,Y.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm hover:bg-secondary disabled:opacity-50`,onClick:()=>w(e.path),disabled:v||b,title:e.path,children:[(0,Y.jsx)(m,{className:`size-4 shrink-0 text-muted-foreground`}),(0,Y.jsx)(`span`,{className:`truncate`,children:e.name})]},e.path))]})]})]}),(0,Y.jsxs)(`div`,{className:`flex justify-end gap-2 border-t border-border p-4`,children:[(0,Y.jsx)(X,{type:`button`,variant:`outline`,onClick:()=>r(!1),disabled:b,children:q(`cancel`)}),(0,Y.jsx)(X,{type:`button`,onClick:async()=>{let e=u.trim()||c;if(!(!e||b||n)){x(!0),C(``);try{await i(e),r(!1)}catch(e){C(e instanceof Error?e.message:q(`failedToSelectProjectDirectory`))}finally{x(!1)}}},disabled:v||b||n||!(u.trim()||c),children:q(b?`selecting`:`selectThisFolder`)})]})]})}):null}async function it(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||`HTTP ${e.status}`);return t}function at({open:e,scope:t,project:n,onOpenChange:r,onSaved:i}){let[a,o]=(0,W.useState)([]),[s,c]=(0,W.useState)(()=>new Set),[l,u]=(0,W.useState)(``),[d,f]=(0,W.useState)([]),[m,h]=(0,W.useState)(!1),[g,_]=(0,W.useState)(!1),[v,b]=(0,W.useState)(``),x=t===`project`,[S,C]=(0,W.useState)(null),[w,T]=(0,W.useState)(null),[E,D]=(0,W.useState)(!1),[O,k]=(0,W.useState)(``),j=(0,W.useCallback)(()=>{C(null),T(null),k(``)},[]),M=(0,W.useCallback)(()=>{j(),r(!1)},[r,j]);(0,W.useEffect)(()=>{if(!e||x&&!n)return;let t=!1;return(async()=>{h(!0),b(``);try{let e=x?`/api/skills?projectId=${encodeURIComponent(n.id)}`:`/api/skills?scope=global`,r=await it(await fetch(e));if(t)return;o(Array.isArray(r.skills)?r.skills:[]),c(new Set(Array.isArray(r.selectedSkills)?r.selectedSkills:[])),f(Array.isArray(r.searchPaths)?r.searchPaths:[])}catch(e){t||b(e instanceof Error?e.message:q(`failedToLoadSkills`))}finally{t||h(!1)}})(),()=>{t=!0}},[e,n,x]),(0,W.useEffect)(()=>{if(!e)return;let t=e=>{e.key===`Escape`&&(S?j():g||M())};return document.addEventListener(`keydown`,t),()=>document.removeEventListener(`keydown`,t)},[M,e,g,S,j]);let N=(0,W.useMemo)(()=>{let e=l.trim().toLowerCase();return e?a.filter(t=>[t.name,t.displayName,t.description,t.source,t.compatibility,t.allowedTools,...t.tags??[],...t.triggers??[]].filter(Boolean).join(` `).toLowerCase().includes(e)):a},[l,a]),P=async e=>{C(e),T(null),k(``),D(!0);try{let t=new URLSearchParams({name:e});x&&n?(t.set(`scope`,`project`),t.set(`projectId`,n.id)):t.set(`scope`,`global`),T(await it(await fetch(`/api/skills/content?${t}`)))}catch(e){k(e instanceof Error?e.message:q(`failedToReadSkill`))}finally{D(!1)}},F=()=>{j()};if(!e||x&&!n)return null;let te=e=>{c(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},ne=async()=>{if(!g){_(!0),b(``);try{let e=await it(await fetch(x?`/api/skills/project`:`/api/skills/global`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify(x?{projectId:n.id,selectedSkills:[...s]}:{selectedSkills:[...s]})}));i({scope:t,project:x?e.projects?.find(e=>e.id===n.id)??{...n,skills:e.selectedSkills}:void 0,projects:e.projects,selectedSkills:e.selectedSkills}),M()}catch(e){b(e instanceof Error?e.message:q(`failedToSaveSkills`))}finally{_(!1)}}},re=q(x?`projectSkills`:`globalSkills`),ie=x?q(`projectSkillsDescription`,{project:n.name}):q(`globalSkillsDescription`),L=!!S;return(0,Y.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,onClick:e=>{e.target===e.currentTarget&&!g&&M()},children:(0,Y.jsxs)(`div`,{className:`flex max-h-[85vh] w-full max-w-2xl flex-col rounded-lg border border-border bg-background shadow-xl`,children:[(0,Y.jsx)(`div`,{className:`border-b border-border p-4`,children:L?(0,Y.jsxs)(`button`,{type:`button`,className:`flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground transition-colors`,onClick:F,children:[(0,Y.jsx)(I,{className:`size-4`}),q(`backToSkillList`)]}):(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`h2`,{className:`text-base font-semibold text-foreground`,children:re}),(0,Y.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:ie}),d.length?(0,Y.jsxs)(`p`,{className:`mt-2 break-all text-xs text-muted-foreground/65`,children:[q(`skillSearchPaths`),`: `,d.join(` · `)]}):null]})}),(0,Y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto p-4`,children:L?E?(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-8 text-sm text-muted-foreground`,children:[(0,Y.jsx)(p,{className:`size-4 animate-spin`}),q(`loading`)]}):O?(0,Y.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:O}):w?(0,Y.jsxs)(`div`,{className:`space-y-3`,children:[(0,Y.jsxs)(`div`,{className:`rounded-md border border-border px-3 py-2 text-sm space-y-1`,children:[(0,Y.jsxs)(`div`,{className:`font-medium text-foreground/90`,children:[w.displayName||w.name,w.version?(0,Y.jsxs)(`span`,{className:`ml-2 text-xs text-muted-foreground`,children:[`v`,w.version]}):null]}),w.description?(0,Y.jsx)(`div`,{className:`text-muted-foreground/70`,children:w.description}):null,(0,Y.jsxs)(`div`,{className:`flex flex-wrap gap-x-4 gap-y-0.5 text-xs text-muted-foreground/60`,children:[w.source?(0,Y.jsx)(`span`,{children:w.source}):null,w.compatibility?(0,Y.jsxs)(`span`,{children:[`· `,w.compatibility]}):null,w.allowedTools?(0,Y.jsxs)(`span`,{children:[`· `,w.allowedTools]}):null,w.license?(0,Y.jsxs)(`span`,{children:[`· `,w.license]}):null]}),w.tags?.length?(0,Y.jsx)(`div`,{className:`flex flex-wrap gap-1 pt-1`,children:w.tags.map(e=>(0,Y.jsx)(`span`,{className:`rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground`,children:e},e))}):null,w.triggers?.length?(0,Y.jsxs)(`div`,{className:`text-xs text-muted-foreground/60`,children:[`Triggers: `,w.triggers.join(`, `)]}):null]}),w.instructions?(0,Y.jsx)(`pre`,{className:`whitespace-pre-wrap break-words rounded-md border border-border bg-muted/30 px-4 py-3 text-sm leading-6 text-foreground/80 font-mono`,children:w.instructions}):(0,Y.jsx)(`div`,{className:`py-4 text-center text-sm text-muted-foreground`,children:q(`noSkillContent`)})]}):null:(0,Y.jsxs)(`div`,{className:`space-y-3`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md border border-input bg-background px-3 py-2`,children:[(0,Y.jsx)(A,{className:`size-4 shrink-0 text-muted-foreground/60`}),(0,Y.jsx)(`input`,{value:l,onChange:e=>u(e.target.value),placeholder:q(`searchSkills`),className:`min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground/45`,disabled:m||g})]}),v?(0,Y.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:v}):null,(0,Y.jsxs)(`div`,{className:`rounded-md border border-border`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center justify-between border-b border-border px-3 py-2 text-xs text-muted-foreground`,children:[(0,Y.jsx)(`span`,{children:q(`availableSkills`)}),(0,Y.jsx)(`span`,{children:q(`selectedSkillsCount`,{count:s.size})})]}),(0,Y.jsx)(`div`,{className:`max-h-[46vh] overflow-y-auto p-1`,children:m?(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 px-3 py-8 text-sm text-muted-foreground`,children:[(0,Y.jsx)(p,{className:`size-4 animate-spin`}),q(`loading`)]}):N.length===0?(0,Y.jsx)(`div`,{className:`px-3 py-8 text-center text-sm text-muted-foreground`,children:q(`noMatchingSkills`)}):N.map(e=>{let t=s.has(e.name);return(0,Y.jsxs)(`div`,{className:J(`flex w-full items-start gap-3 rounded-md px-3 py-3 text-left text-sm transition-colors hover:bg-secondary disabled:opacity-50`,t&&`bg-secondary/70`),children:[(0,Y.jsx)(`button`,{type:`button`,className:J(`mt-0.5 flex size-5 shrink-0 items-center justify-center rounded border border-input`,t&&`border-primary bg-primary text-primary-foreground`),onClick:()=>te(e.name),disabled:g,"aria-label":t?`Deselect ${e.name}`:`Select ${e.name}`,children:t?(0,Y.jsx)(y,{className:`size-3.5`}):null}),(0,Y.jsxs)(`span`,{className:`min-w-0 flex-1 cursor-pointer`,onClick:()=>te(e.name),children:[(0,Y.jsx)(`span`,{className:`block truncate font-medium text-foreground/90`,children:e.displayName||e.name}),e.description?(0,Y.jsx)(`span`,{className:`mt-0.5 block text-xs leading-5 text-muted-foreground/70`,children:e.description}):null,(0,Y.jsxs)(`span`,{className:`mt-1 flex flex-wrap gap-1 text-[11px] text-muted-foreground/60`,children:[e.source?(0,Y.jsx)(`span`,{children:e.source}):null,e.compatibility?(0,Y.jsxs)(`span`,{children:[`· `,e.compatibility]}):null,e.allowedTools?(0,Y.jsxs)(`span`,{children:[`· `,e.allowedTools]}):null]}),e.tags?.length?(0,Y.jsx)(`span`,{className:`mt-2 flex flex-wrap gap-1`,children:e.tags.slice(0,5).map(e=>(0,Y.jsx)(`span`,{className:`rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground`,children:e},e))}):null]}),(0,Y.jsx)(`button`,{type:`button`,className:`mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground/60 transition-colors hover:bg-secondary hover:text-foreground`,onClick:()=>void P(e.name),disabled:g||E,title:q(`readSkill`),"aria-label":`${q(`readSkill`)}: ${e.displayName||e.name}`,children:(0,Y.jsx)(ee,{className:`size-4`})})]},e.name)})})]})]})}),L?null:(0,Y.jsxs)(`div`,{className:`flex justify-end gap-2 border-t border-border p-4`,children:[(0,Y.jsx)(X,{type:`button`,variant:`outline`,onClick:M,disabled:g,children:q(`cancel`)}),(0,Y.jsx)(X,{type:`button`,onClick:ne,disabled:m||g,children:q(g?`saving`:`save`)})]})]})})}var ot=le();function st({title:e,description:t,actions:n,onCancel:r}){let i=(0,W.useRef)(null),a=(0,W.useRef)(!1),o=(0,W.useCallback)(()=>{a.current||(a.current=!0,r())},[r]),s=(0,W.useCallback)(e=>{a.current||(a.current=!0,e.onClick())},[]);return(0,W.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,ot.createPortal)((0,Y.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,Y.jsxs)(`div`,{className:J(`w-full max-w-[420px] rounded-2xl border border-border bg-background p-5 shadow-xl`),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,Y.jsx)(`h2`,{id:`message-dialog-title`,className:`text-base font-semibold text-foreground/90`,children:e}):null,(0,Y.jsx)(`p`,{id:`message-dialog-description`,className:J(`text-sm leading-6 text-muted-foreground/72`,e?`mt-2`:void 0),children:t}),(0,Y.jsx)(`div`,{className:`mt-6 flex justify-end gap-2`,children:n.map((e,t)=>(0,Y.jsx)(X,{ref:e.autoFocus?i:void 0,variant:e.variant,size:`sm`,onClick:()=>s(e),children:e.label},`${e.label}-${t}`))})]})}),document.body)}function ct(e){return new Promise(t=>{let n=document.createElement(`div`);document.body.appendChild(n);let r=(0,je.createRoot)(n);function i(){r.unmount(),setTimeout(()=>n.remove(),0)}function a(e){i(),t(e)}r.render(e(a))})}function lt(e){return ct(t=>(0,Y.jsx)(st,{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 Z(e){let t=typeof e==`string`?{description:e}:e;return ct(e=>(0,Y.jsx)(st,{title:t.title,description:t.description,onCancel:()=>e(),actions:[{label:t.confirmLabel??`OK`,autoFocus:!0,onClick:()=>e()}]}))}function ut(e){return e===`connected`?`bg-emerald-500/12 text-emerald-700 dark:text-emerald-300`:e===`error`?`bg-destructive/12 text-destructive`:e===`disabled`?`bg-muted text-muted-foreground`:`bg-amber-500/12 text-amber-700 dark:text-amber-300`}var dt=12;function ft({server:e,toggling:t,reconnecting:n,onToggle:r,onEdit:a,onDelete:o,onReconnect:s}){let c=e.tools?.slice(0,dt)??[],l=e.toolCount??e.tools?.length??0,u=Math.max(0,l-c.length),d=e.enabled&&e.status!==`connected`;return(0,Y.jsxs)(`div`,{className:`rounded-lg border border-border p-3`,children:[(0,Y.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,Y.jsxs)(`div`,{className:`min-w-0`,children:[(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Y.jsx)(`div`,{className:`truncate text-sm font-medium text-foreground/90`,children:e.name}),(0,Y.jsx)(`span`,{className:J(`rounded-full px-2 py-0.5 text-[11px]`,ut(e.status)),children:e.status||`unknown`}),(0,Y.jsx)(`span`,{className:`text-[11px] text-muted-foreground/60`,children:q(`mcpToolsCount`,{count:l})})]}),(0,Y.jsx)(`div`,{className:`mt-1 truncate text-xs text-muted-foreground/65`,children:e.transport===`stdio`?`${e.command} ${(e.args||[]).join(` `)}`:e.url}),e.error?(0,Y.jsx)(`div`,{className:`mt-1 text-xs text-destructive`,children:e.error}):null]}),(0,Y.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1`,children:[(0,Y.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":e.enabled,disabled:t,className:J(`relative h-6 w-11 rounded-full transition-colors disabled:cursor-not-allowed disabled:opacity-60`,e.enabled?`bg-emerald-500`:`bg-muted-foreground/30`),onClick:()=>r(e),title:e.enabled?q(`pauseTask`):q(`enable`),children:(0,Y.jsx)(`span`,{className:J(`absolute left-0.5 top-0.5 size-5 rounded-full bg-white shadow transition-transform`,e.enabled?`translate-x-5`:`translate-x-0`)})}),d?(0,Y.jsx)(X,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 text-muted-foreground`,onClick:()=>s(e.name),disabled:n,"aria-label":q(`mcpReconnectServer`),title:q(`mcpReconnectServer`),children:n?(0,Y.jsx)(p,{className:`size-4 animate-spin`}):(0,Y.jsx)(E,{className:`size-4`})}):null,(0,Y.jsx)(X,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 text-muted-foreground`,onClick:()=>a(e),"aria-label":q(`editTask`),title:q(`editTask`),children:(0,Y.jsx)(i,{className:`size-4`})}),(0,Y.jsx)(X,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8 text-destructive`,onClick:()=>o(e.name),"aria-label":q(`delete`),title:q(`delete`),children:(0,Y.jsx)(v,{className:`size-4`})})]})]}),c.length>0?(0,Y.jsxs)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:[c.map(e=>(0,Y.jsx)(`span`,{className:`rounded-md bg-muted/50 px-1.5 py-0.5 text-[11px] text-muted-foreground/75`,title:e.quickForgeName,children:e.name},e.quickForgeName)),u>0?(0,Y.jsx)(`span`,{className:`rounded-md px-1.5 py-0.5 text-[11px] text-muted-foreground/55`,children:q(`mcpMoreTools`,{count:u})}):null]}):null]})}var pt=W.forwardRef(({className:e,type:t,...n},r)=>(0,Y.jsx)(`input`,{type:t,className:J(`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50`,e),ref:r,...n}));pt.displayName=`Input`;function mt(){return{name:``,transport:`stdio`,command:``,args:[],url:``,cwd:``,env:{}}}function ht(e){return{name:e.name,transport:e.transport,command:e.command,args:e.args||[],url:e.url||``,cwd:e.cwd||``,env:e.env||{}}}function gt(e){return(e||[]).join(`
|
|
11
|
+
`)}function _t(e){return Object.entries(e||{}).map(([e,t])=>`${e}=${t}`).join(`
|
|
12
|
+
`)}function vt(e){return e.split(`
|
|
13
|
+
`).map(e=>e.trim()).filter(Boolean)}function yt(e){let t={};for(let n of e.split(`
|
|
14
|
+
`)){let e=n.trim();if(!e)continue;let r=e.indexOf(`=`);if(r<=0)continue;let i=e.slice(0,r).trim(),a=e.slice(r+1).trim();i&&(t[i]=a)}return t}function bt(e){let t={type:e.transport||`stdio`};e.transport===`stdio`?(t.command=e.command||``,t.args=e.args||[],e.cwd&&(t.cwd=e.cwd),e.env&&Object.keys(e.env).length>0&&(t.env=e.env)):(t.url=e.url||``,e.env&&Object.keys(e.env).length>0&&(t.headers=e.env));let n=e.name||`server`;return JSON.stringify({mcpServers:{[n]:t}},null,2)}function xt(e){return!!(e&&typeof e==`object`&&!Array.isArray(e))}function St(e){let t;try{t=JSON.parse(e)}catch{throw Error(q(`mcpInvalidJson`))}if(!xt(t))throw Error(q(`mcpInvalidConfigJson`));let n=``,r=null;if(xt(t.mcpServers)){let e=Object.entries(t.mcpServers);if(e.length===0)throw Error(q(`mcpEmptyConfigJson`));let[i,a]=e[0];n=i,xt(a)&&(r=a)}else r=t;if(!r)throw Error(q(`mcpInvalidConfigJson`));let i=String(r.transport||r.type||`stdio`);if(![`stdio`,`http`,`sse`].includes(i))throw Error(q(`mcpInvalidTransport`,{name:n||`server`}));let a=r.env??r.headers??{};return{name:n,transport:i,command:String(r.command||``),args:Array.isArray(r.args)?r.args:[],url:String(r.url||``),cwd:String(r.cwd||``),env:xt(a)?a:{}}}var Ct=`mb-1 block text-xs text-muted-foreground/72`,wt=`min-h-20 w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs text-foreground outline-none focus:border-ring`,Tt=`flex h-9 w-full rounded-md border border-input bg-transparent px-3 text-sm outline-none focus:border-ring`;function Et({value:e,onChange:t,isEdit:n,disabled:r}){let i=e.transport===`stdio`,a=n=>t({...e,...n});return(0,Y.jsxs)(`div`,{className:`space-y-3 p-3`,children:[(0,Y.jsx)(`div`,{className:`text-xs text-muted-foreground/60`,children:q(n?`mcpEditServer`:`mcpAddServer`)}),(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`label`,{className:Ct,htmlFor:`mcp-server-name`,children:q(`mcpServerName`)}),(0,Y.jsx)(pt,{id:`mcp-server-name`,value:e.name,onChange:e=>a({name:e.target.value}),placeholder:q(`mcpNamePlaceholder`),disabled:n||r})]}),(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`label`,{className:Ct,htmlFor:`mcp-server-transport`,children:q(`mcpTransport`)}),(0,Y.jsxs)(`select`,{id:`mcp-server-transport`,className:Tt,value:e.transport,onChange:e=>a({transport:e.target.value}),disabled:r,children:[(0,Y.jsx)(`option`,{value:`stdio`,children:`stdio`}),(0,Y.jsx)(`option`,{value:`http`,children:`http`}),(0,Y.jsx)(`option`,{value:`sse`,children:`sse`})]})]}),i?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`label`,{className:Ct,htmlFor:`mcp-server-command`,children:q(`mcpCommand`)}),(0,Y.jsx)(pt,{id:`mcp-server-command`,value:e.command,onChange:e=>a({command:e.target.value}),placeholder:q(`mcpCommandPlaceholder`),disabled:r})]}),(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`label`,{className:Ct,htmlFor:`mcp-server-args`,children:q(`mcpArgs`)}),(0,Y.jsx)(`textarea`,{id:`mcp-server-args`,className:wt,value:gt(e.args),onChange:e=>a({args:vt(e.target.value)}),spellCheck:!1,disabled:r})]}),(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`label`,{className:Ct,htmlFor:`mcp-server-cwd`,children:q(`mcpCwd`)}),(0,Y.jsx)(pt,{id:`mcp-server-cwd`,value:e.cwd,onChange:e=>a({cwd:e.target.value}),disabled:r})]}),(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`label`,{className:Ct,htmlFor:`mcp-server-env`,children:q(`mcpEnv`)}),(0,Y.jsx)(`textarea`,{id:`mcp-server-env`,className:wt,value:_t(e.env),onChange:e=>a({env:yt(e.target.value)}),spellCheck:!1,disabled:r})]})]}):(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`label`,{className:Ct,htmlFor:`mcp-server-url`,children:q(`mcpUrl`)}),(0,Y.jsx)(pt,{id:`mcp-server-url`,value:e.url,onChange:e=>a({url:e.target.value}),placeholder:q(`mcpUrlPlaceholder`),disabled:r})]}),(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`label`,{className:Ct,htmlFor:`mcp-server-headers`,children:q(`mcpHeaders`)}),(0,Y.jsx)(`textarea`,{id:`mcp-server-headers`,className:wt,value:_t(e.env),onChange:e=>a({env:yt(e.target.value)}),spellCheck:!1,disabled:r})]})]})]})}function Dt({configText:e,onConfigTextChange:t,onImport:n,onUseExample:r,saving:i}){return(0,Y.jsxs)(`div`,{className:`space-y-3 p-3`,children:[(0,Y.jsx)(`p`,{className:`text-xs leading-5 text-muted-foreground/72`,children:q(`mcpImportConfigDescription`)}),(0,Y.jsx)(`textarea`,{className:`min-h-96 w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs text-foreground outline-none focus:border-ring`,value:e,onChange:e=>t(e.target.value),spellCheck:!1}),(0,Y.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,Y.jsx)(X,{type:`button`,variant:`ghost`,size:`sm`,onClick:r,disabled:i,children:q(`mcpUseExample`)}),(0,Y.jsxs)(`div`,{className:`flex gap-2`,children:[(0,Y.jsxs)(X,{type:`button`,size:`sm`,onClick:()=>n(`merge`),disabled:i||!e.trim(),children:[i?(0,Y.jsx)(p,{className:`mr-1.5 size-3.5 animate-spin`}):(0,Y.jsx)(ae,{className:`mr-1.5 size-3.5`}),q(`mcpImportUpdate`)]}),(0,Y.jsx)(X,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>n(`replace`),disabled:i||!e.trim(),children:q(`mcpReplaceAll`)})]})]})]})}var Ot=`{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"zai-mcp-server": {
|
|
17
|
+
"type": "stdio",
|
|
18
|
+
"command": "npx",
|
|
19
|
+
"args": [
|
|
20
|
+
"-y",
|
|
21
|
+
"@z_ai/mcp-server"
|
|
22
|
+
],
|
|
23
|
+
"env": {
|
|
24
|
+
"Z_AI_API_KEY": "\${Z_AI_API_KEY}",
|
|
25
|
+
"Z_AI_MODE": "ZHIPU"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}`;async function kt(e){let t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||`HTTP ${e.status}`);return t}function At(e){return!!(e&&typeof e==`object`&&!Array.isArray(e))}function jt(e){let t;try{t=JSON.parse(e)}catch{throw Error(q(`mcpInvalidJson`))}if(!At(t)||!At(t.mcpServers))throw Error(q(`mcpInvalidConfigJson`));let n=Object.entries(t.mcpServers);if(n.length===0)throw Error(q(`mcpEmptyConfigJson`));for(let[e,t]of n){if(!/^(?!.*--)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(e))throw Error(q(`mcpInvalidServerName`,{name:e}));if(!At(t))throw Error(q(`mcpInvalidServerConfig`,{name:e}));let n=String(t.transport||t.type||`stdio`);if(![`stdio`,`http`,`sse`].includes(n))throw Error(q(`mcpInvalidTransport`,{name:e}));if(n===`stdio`&&typeof t.command!=`string`)throw Error(q(`mcpMissingCommand`,{name:e}));if(n!==`stdio`&&typeof t.url!=`string`)throw Error(q(`mcpMissingUrl`,{name:e}));if(t.args!==void 0&&!Array.isArray(t.args))throw Error(q(`mcpArgsMustBeArray`,{name:e}));if(t.env!==void 0&&!At(t.env))throw Error(q(`mcpEnvMustBeObject`,{name:e}));if(t.headers!==void 0&&!At(t.headers))throw Error(q(`mcpHeadersMustBeObject`,{name:e}))}return t}function Mt({open:e,onOpenChange:t}){let[n,r]=(0,W.useState)([]),[i,a]=(0,W.useState)(Ot),[o,s]=(0,W.useState)(!1),[l,u]=(0,W.useState)(!1),[d,f]=(0,W.useState)(!1),[m,h]=(0,W.useState)(new Set),[g,_]=(0,W.useState)(null),[v,y]=(0,W.useState)(``),[b,x]=(0,W.useState)(!1),[S,C]=(0,W.useState)(null),[w,E]=(0,W.useState)(mt),[D,O]=(0,W.useState)(`form`),[k,ee]=(0,W.useState)(``),[A,M]=(0,W.useState)(``),N=l||d,P=(0,W.useCallback)(e=>{r(e?.servers??[])},[]),te=(0,W.useCallback)(async()=>{s(!0),y(``);try{P(await kt(await fetch(`/api/mcp/servers`)))}catch(e){y(e instanceof Error?e.message:q(`mcpLoadFailed`))}finally{s(!1)}},[P]);if((0,W.useEffect)(()=>{if(!e)return;let t=window.setTimeout(()=>{te()},0);return()=>window.clearTimeout(t)},[e,te]),!e)return null;let I=e=>{e===`json`&&(ee(bt(w)),M(``)),O(e)},ne=()=>{C(null),E(mt()),O(`form`),x(!0),y(``)},re=e=>{let t=ht(e);C(e),E(t),ee(bt(t)),M(``),O(`form`),x(!0),y(``)},ie=()=>{x(!1),C(null),ee(``),M(``),y(``)},L=e=>{E(e)},R=e=>{ee(e);try{let t=St(e);E(e=>({...t,name:t.name||e.name})),M(``)}catch(e){M(e instanceof Error?e.message:q(`mcpInvalidJson`))}},oe=async e=>{if(!d&&!(e===`replace`&&!await lt({description:q(`mcpReplaceConfirm`),confirmLabel:q(`mcpReplaceAll`),cancelLabel:q(`cancel`)}))){f(!0),y(``);try{let t=jt(i);P(await kt(await fetch(`/api/mcp/config`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({mode:e,...t})})))}catch(e){y(e instanceof Error?e.message:q(`mcpSaveFailed`))}finally{f(!1)}}},ce=async()=>{if(!l){if(A&&D===`json`){y(A);return}u(!0),y(``);try{P(await kt(await fetch(`/api/mcp/servers`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({server:{...w,enabled:S?.enabled??!0}})}))),ie()}catch(e){y(e instanceof Error?e.message:q(`mcpSaveFailed`))}finally{u(!1)}}},le=async e=>{if(await lt({description:q(`mcpDeleteConfirm`,{name:e}),confirmLabel:q(`confirmDelete`),cancelLabel:q(`cancel`),variant:`destructive`})){y(``);try{P(await kt(await fetch(`/api/mcp/servers/${encodeURIComponent(e)}`,{method:`DELETE`})))}catch(e){y(e instanceof Error?e.message:q(`mcpDeleteFailed`))}}},ue=async e=>{if(!m.has(e.name)){h(t=>new Set(t).add(e.name)),y(``);try{P(await kt(await fetch(`/api/mcp/servers/${encodeURIComponent(e.name)}/enabled`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({enabled:!e.enabled})})))}catch(e){y(e instanceof Error?e.message:q(`mcpSaveFailed`))}finally{h(t=>{let n=new Set(t);return n.delete(e.name),n})}}},de=async()=>{s(!0),y(``);try{P(await kt(await fetch(`/api/mcp/reconnect`,{method:`POST`})))}catch(e){y(e instanceof Error?e.message:q(`mcpReconnectFailed`))}finally{s(!1)}},fe=async e=>{if(!g){_(e),y(``);try{P(await kt(await fetch(`/api/mcp/reconnect/${encodeURIComponent(e)}`,{method:`POST`})))}catch(e){y(e instanceof Error?e.message:q(`mcpReconnectFailed`))}finally{_(null)}}},z=!!S,pe=!!w.name.trim()&&!!(w.transport===`stdio`?w.command.trim():w.url.trim());return(0,Y.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`mcp-servers-title`,onClick:e=>{e.target===e.currentTarget&&!N&&t(!1)},children:(0,Y.jsxs)(`div`,{className:`flex max-h-[88vh] w-full max-w-5xl flex-col rounded-lg border border-border bg-background shadow-xl`,children:[(0,Y.jsxs)(`div`,{className:`flex items-start gap-3 border-b border-border p-4`,children:[(0,Y.jsx)(`span`,{className:`mt-0.5 inline-flex size-8 shrink-0 items-center justify-center rounded-full bg-muted/40 text-muted-foreground`,children:(0,Y.jsx)(se,{className:`size-4`})}),(0,Y.jsx)(`div`,{className:`min-w-0 flex-1`,children:(0,Y.jsx)(`h2`,{id:`mcp-servers-title`,className:`text-base font-semibold text-foreground`,children:q(`mcpServers`)})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:`size-8 shrink-0 rounded-full text-muted-foreground`,onClick:()=>t(!1),disabled:N,"aria-label":q(`close`),children:(0,Y.jsx)(j,{className:`size-4`})})]}),(0,Y.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto p-4`,children:[v?(0,Y.jsx)(`div`,{className:`mb-3 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:v}):null,(0,Y.jsxs)(`div`,{className:`grid gap-4 lg:grid-cols-[1fr_28rem]`,children:[(0,Y.jsxs)(`div`,{className:`min-w-0 space-y-2`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,Y.jsx)(`h3`,{className:`text-sm font-medium text-foreground/90`,children:q(`mcpConfiguredServers`)}),(0,Y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Y.jsxs)(X,{type:`button`,variant:`ghost`,size:`sm`,onClick:ne,disabled:b&&!z,children:[(0,Y.jsx)(ae,{className:`mr-1.5 size-3.5`}),q(`mcpAddServer`)]}),(0,Y.jsxs)(X,{type:`button`,variant:`ghost`,size:`sm`,onClick:de,disabled:o,children:[o?(0,Y.jsx)(p,{className:`mr-1.5 size-3.5 animate-spin`}):(0,Y.jsx)(T,{className:`mr-1.5 size-3.5`}),q(`mcpReconnect`)]})]})]}),o&&n.length===0?(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 rounded-lg border border-border py-8 text-sm text-muted-foreground`,children:[(0,Y.jsx)(p,{className:`size-4 animate-spin`}),q(`loading`)]}):n.length===0?(0,Y.jsx)(`div`,{className:`rounded-lg border border-border bg-muted/15 p-4 text-sm text-muted-foreground/72`,children:q(`mcpNoServersDescription`)}):n.map(e=>(0,Y.jsx)(ft,{server:e,toggling:m.has(e.name),reconnecting:g===e.name,onToggle:e=>{ue(e)},onEdit:re,onDelete:e=>{le(e)},onReconnect:e=>{fe(e)}},e.name))]}),(0,Y.jsx)(`div`,{className:`flex min-h-0 flex-col rounded-lg border border-border`,children:b?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsxs)(`div`,{className:`flex border-b border-border`,children:[(0,Y.jsxs)(`button`,{type:`button`,onClick:()=>I(`form`),className:J(`flex flex-1 items-center justify-center gap-1.5 px-3 py-2.5 text-xs font-medium transition-colors`,D===`form`?`border-b-2 border-primary text-foreground/90 -mb-px`:`text-muted-foreground/60 hover:text-foreground/85`),children:[(0,Y.jsx)(F,{className:`size-3.5`}),q(`mcpTabServer`)]}),(0,Y.jsxs)(`button`,{type:`button`,onClick:()=>I(`json`),className:J(`flex flex-1 items-center justify-center gap-1.5 px-3 py-2.5 text-xs font-medium transition-colors`,D===`json`?`border-b-2 border-primary text-foreground/90 -mb-px`:`text-muted-foreground/60 hover:text-foreground/85`),children:[(0,Y.jsx)(c,{className:`size-3.5`}),q(`mcpTabJson`)]})]}),(0,Y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:D===`form`?(0,Y.jsx)(Et,{value:w,onChange:L,isEdit:z,disabled:l}):(0,Y.jsxs)(`div`,{className:`space-y-2 p-3`,children:[(0,Y.jsx)(`textarea`,{className:`min-h-96 w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs text-foreground outline-none focus:border-ring`,value:k,onChange:e=>R(e.target.value),spellCheck:!1}),A?(0,Y.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive`,children:A}):null,(0,Y.jsx)(`p`,{className:`text-[11px] text-muted-foreground/55`,children:q(`mcpImportConfigDescription`)})]})}),(0,Y.jsxs)(`div`,{className:`flex justify-end gap-2 border-t border-border p-3`,children:[(0,Y.jsx)(X,{type:`button`,variant:`outline`,size:`sm`,onClick:ie,disabled:l,children:q(`cancel`)}),(0,Y.jsxs)(X,{type:`button`,size:`sm`,onClick:()=>{ce()},disabled:l||!pe,children:[l?(0,Y.jsx)(p,{className:`mr-1.5 size-3.5 animate-spin`}):null,q(`save`)]})]})]}):(0,Y.jsx)(Dt,{configText:i,onConfigTextChange:a,onImport:e=>{oe(e)},onUseExample:()=>{a(Ot),y(``)},saving:d})})]})]})]})})}var Nt=new Set;function Pt(e){return typeof e[Symbol.iterator]==`function`}var Ft=class{baseUrl;blockedStores;storeOverrides;fakeProviderKeys;constructor(e=``,t=Nt){this.baseUrl=e,Pt(t)?(this.blockedStores=new Set(t),this.storeOverrides={},this.fakeProviderKeys=new Set):(this.blockedStores=new Set(t.blockedStores??Nt),this.storeOverrides=t.storeOverrides??{},this.fakeProviderKeys=new Set(t.fakeProviderKeys??[]))}assertStoreAccess(e){if(this.blockedStores.has(e))throw Error(`This storage area is not available in the current page.`)}static async isAvailable(e=``){let t=new AbortController,n=window.setTimeout(()=>t.abort(),1e3);try{let n=await fetch(`${e}/api/health`,{method:`GET`,cache:`no-store`,signal:t.signal});return n.ok?(await n.json().catch(()=>null))?.ok===!0:!1}catch{return!1}finally{window.clearTimeout(n)}}path(...e){return`${this.baseUrl}/api/storage/${e.map(e=>encodeURIComponent(e)).join(`/`)}`}async request(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||`Local storage request failed: ${n.status}`);return r}async get(e,t){if(e===`provider-keys`&&this.fakeProviderKeys.has(t))return`shared-server-managed-key`;let n=this.storeOverrides[e];return n?.get?n.get(t):(this.assertStoreAccess(e),(await this.request(this.path(e,`key`,t))).value??null)}async set(e,t,n){this.assertStoreAccess(e),await this.request(this.path(e,`key`,t),{method:`PUT`,body:JSON.stringify({value:n})})}async delete(e,t){this.assertStoreAccess(e),await this.request(this.path(e,`key`,t),{method:`DELETE`})}async keys(e,t){if(e===`provider-keys`&&this.fakeProviderKeys.size>0)return[...this.fakeProviderKeys];let n=this.storeOverrides[e];if(n?.keys)return n.keys(t);this.assertStoreAccess(e);let r=t?`?prefix=${encodeURIComponent(t)}`:``;return(await this.request(`${this.path(e,`keys`)}${r}`)).keys}async getAllFromIndex(e,t,n=`asc`){return this.assertStoreAccess(e),(await this.request(`${this.path(e,`index`,t)}?direction=${encodeURIComponent(n)}`)).values}async fetchPaginatedFromIndex(e,t,n){this.assertStoreAccess(e);let r=new URLSearchParams;return r.set(`direction`,n.direction||`desc`),r.set(`limit`,String(n.limit)),r.set(`offset`,String(n.offset)),n.scope&&r.set(`scope`,n.scope),n.projectId&&r.set(`projectId`,n.projectId),this.request(`${this.path(e,`index`,t)}?${r.toString()}`)}async clear(e){this.assertStoreAccess(e),await this.request(this.path(e),{method:`DELETE`})}async has(e,t){if(e===`provider-keys`&&this.fakeProviderKeys.has(t))return!0;let n=this.storeOverrides[e];return n?.has?n.has(t):(this.assertStoreAccess(e),(await this.request(this.path(e,`has`,t))).exists)}async transaction(e,t,n){for(let t of e)t===`provider-keys`&&this.fakeProviderKeys.size>0||this.storeOverrides[t]||this.assertStoreAccess(t);return n({get:(e,t)=>this.get(e,t),set:(e,t,n)=>this.set(e,t,n),delete:(e,t)=>this.delete(e,t)})}async getQuotaInfo(){return this.request(`${this.baseUrl}/api/storage/quota`)}async requestPersistence(){return!0}};function It(){if(typeof crypto<`u`&&typeof crypto.randomUUID==`function`)return crypto.randomUUID();let e=new Uint8Array(16);if(typeof crypto<`u`&&typeof crypto.getRandomValues==`function`)crypto.getRandomValues(e);else for(let t=0;t<e.length;t+=1)e[t]=Math.floor(Math.random()*256);e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e,e=>e.toString(16).padStart(2,`0`));return`${t.slice(0,4).join(``)}-${t.slice(4,6).join(``)}-${t.slice(6,8).join(``)}-${t.slice(8,10).join(``)}-${t.slice(10).join(``)}`}var Lt=`active-model`,Rt=`yolo-mode`,zt=`yolo-mode-project:`,Bt=`default-options`,Vt={id:`default-litellm-anthropic`,name:`LiteLLM Anthropic`,baseUrl:`http://localhost:4000/v1`,apiKey:``,modelId:`anthropic/claude-sonnet-4`,contextWindow:2e5,maxTokens:8192};function Ht(e,t,n=``){let r=e.toLowerCase(),i=t.toLowerCase(),a=n.toLowerCase();return r.includes(`deepseek-v4`)&&(a.includes(`deepseek`)||i.includes(`api.deepseek.com`)||i.includes(`deepseek.com`))}function Ut(){return{requiresReasoningContentOnAssistantMessages:!0,thinkingFormat:`deepseek`}}var Wt={low:`high`,medium:`high`,high:`high`,xhigh:`max`};function Q(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n.includes(`deepseek`)||r.includes(`api.deepseek.com`)||r.includes(`deepseek.com`)?`deepseek`:r.includes(`openrouter.ai`)?`openrouter`:n===`zai`||r.includes(`bigmodel.cn`)||r.includes(`z.ai`)?`zai`:`openai`}function Gt(e){let t={...e.compat,...e.reasoning===!0&&e.compat?.supportsReasoningEffort===void 0?{supportsReasoningEffort:!0}:{},thinkingFormat:e.compat?.thinkingFormat??Q(e.provider,e.baseUrl)};return{...e,compat:t}}function Kt(e){if(e.api!==`openai-completions`)return e;let t=Gt(e);return Ht(t.id,t.baseUrl,t.provider)?{...t,reasoning:!0,thinkingLevelMap:{...t.thinkingLevelMap,...Wt},compat:{...t.compat,supportsReasoningEffort:!0,...Ut()}}:t}function qt(e){let t=e.baseUrl.trim().replace(/\/$/,``),n=e.modelId.trim(),r=e.name.trim(),i=Ht(n,t,r),a=e.reasoning===!0||i;return Kt({id:n,name:`${n} (${r})`,api:`openai-completions`,provider:r,baseUrl:t,reasoning:a,input:[`text`,`image`],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:Number(e.contextWindow)||Vt.contextWindow,maxTokens:Number(e.maxTokens)||Vt.maxTokens,thinkingLevelMap:i?Wt:void 0,compat:{supportsStore:!1,supportsDeveloperRole:!1,supportsReasoningEffort:a,supportsUsageInStreaming:!1,supportsStrictMode:!1,maxTokensField:`max_tokens`,...i?Ut():{}}})}function Jt(){return{settings:new De,providerKeys:new Ee,sessions:new Ce,customProviders:new xe}}function Yt(e,t){e.settings.setBackend(t),e.providerKeys.setBackend(t),e.sessions.setBackend(t),e.customProviders.setBackend(t)}async function Xt(e){if(!await Ft.isAvailable())throw Error(`QuickForge local service is unavailable.`);return new Ft(``,e)}async function Zt(e={}){let t=Jt(),n=await Xt(e.blockedStores);Yt(t,n);let r=new Oe(t.settings,t.providerKeys,t.sessions,t.customProviders,n);return ve(r),r}async function Qt(e,t){await e.settings.set(Lt,Kt(t))}function $t(e){return e?.reasoning?`medium`:`off`}function en(e){return e===`off`||e===`low`||e===`medium`||e===`high`||e===`xhigh`}async function tn(e,t){await e.settings.set(Bt,{model:t.model?Kt(t.model):void 0,thinkingLevel:en(t.thinkingLevel)?t.thinkingLevel:void 0})}async function nn(e){let t=await e.settings.get(Bt);return!t||typeof t!=`object`?{}:{model:t.model?Kt(t.model):void 0,thinkingLevel:en(t.thinkingLevel)?t.thinkingLevel:void 0}}async function rn(e){let t=await e.settings.get(Lt);return!t||typeof t!=`object`||!t.id||!t.provider||!t.api||!t.baseUrl?null:Kt(t)}function an(e,t){return(e??``).trim().replace(/\/$/,``)===(t??``).trim().replace(/\/$/,``)}function on(e,t){return e.id===t.id&&e.provider===t.provider&&e.api===t.api&&an(e.baseUrl,t.baseUrl)}function sn(e){let t=e;return!!(t?.id&&t.provider&&t.api&&t.baseUrl)}function cn(e){return e.flatMap(e=>e.models??[]).filter(sn).map(e=>Kt(e))}async function ln(e){return cn(await e.customProviders.getAll())}async function un(e){let t=await ln(e);if(t.length===0)return null;let n=await rn(e);if(n){let e=t.find(e=>on(e,n));if(e)return e}return t[0]}function dn(e,t){return e.customProviders.getAll().then(e=>{for(let n of e){let e=(n.models??[]).find(e=>e.id===t.id&&e.api===t.api&&e.provider===t.provider&&an(e.baseUrl,t.baseUrl));if(e)return e}})}async function fn(e,t){try{let n=await dn(e,t);if(n)return n.reasoning===!0?Kt(n):n}catch(e){U.warn(`Failed to resolve configured model:`,e)}return Kt(t)}async function pn(e,t,n){let r=n?`${zt}${n}`:Rt;await e.settings.set(r,t)}async function mn(e,t){if(t){let n=`${zt}${t}`,r=await e.settings.get(n);if(r!=null)return r===!0||r===`true`}let n=await e.settings.get(Rt);return n==null?(await pn(e,!0),!0):n===!0||n===`true`}async function hn(e,t,n){let r=t.id||It(),i={id:r,name:t.name.trim(),type:`openai-completions`,baseUrl:n.baseUrl,apiKey:t.apiKey.trim()||void 0,models:[n]};return await e.customProviders.set(i),t.apiKey.trim()&&await e.providerKeys.set(n.provider,t.apiKey.trim()),r}function gn(e){return e?.scope===`project`?`project`:`global`}function _n(e){return e===`New chat`?q(`newChat`):e}function vn({hasProject:e,onConfigureModel:t,onAddProject:r,onCopyExamplePrompt:i,onDismiss:a}){return(0,Y.jsx)(`div`,{className:`pointer-events-none absolute inset-0 z-20 flex items-center justify-center bg-background/35 p-3 backdrop-blur-sm sm:p-6`,children:(0,Y.jsx)(`div`,{className:`pointer-events-auto w-full max-w-4xl rounded-2xl border border-border bg-background/95 p-5 shadow-lg backdrop-blur-md sm:p-6`,children:(0,Y.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,Y.jsx)(`div`,{className:`mt-0.5 flex size-10 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary`,children:(0,Y.jsx)(x,{className:`size-5`})}),(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Y.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Y.jsx)(`h2`,{className:`text-base font-semibold text-foreground sm:text-lg`,children:q(`firstUseGuideTitle`)}),(0,Y.jsx)(`p`,{className:`mt-1.5 text-sm leading-6 text-muted-foreground`,children:q(`firstUseGuideDescription`)})]}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:`-mr-1 -mt-1 size-7 shrink-0`,onClick:a,"aria-label":q(`firstUseGuideDismiss`),children:(0,Y.jsx)(j,{className:`size-4`})})]}),(0,Y.jsxs)(`div`,{className:`mt-4 grid gap-3 text-sm text-muted-foreground sm:grid-cols-3`,children:[(0,Y.jsxs)(`div`,{className:`flex gap-2.5 rounded-xl border border-border/70 bg-muted/15 p-3`,children:[(0,Y.jsx)(S,{className:`mt-0.5 size-4 shrink-0 text-primary`}),(0,Y.jsx)(`span`,{children:q(`firstUseGuideStepModel`)})]}),(0,Y.jsxs)(`div`,{className:`flex gap-2.5 rounded-xl border border-border/70 bg-muted/15 p-3`,children:[(0,Y.jsx)(ce,{className:`mt-0.5 size-4 shrink-0 text-primary`}),(0,Y.jsx)(`span`,{children:q(`firstUseGuideStepProject`)})]}),(0,Y.jsxs)(`div`,{className:`flex gap-2.5 rounded-xl border border-border/70 bg-muted/15 p-3`,children:[(0,Y.jsx)(k,{className:`mt-0.5 size-4 shrink-0 text-primary`}),(0,Y.jsx)(`span`,{children:q(`firstUseGuideStepPlan`)})]})]}),(0,Y.jsxs)(`div`,{className:`mt-4 flex flex-wrap gap-2.5`,children:[(0,Y.jsxs)(X,{size:`sm`,onClick:t,children:[(0,Y.jsx)(S,{className:`size-4`}),q(`firstUseGuideConfigureModel`)]}),(0,Y.jsxs)(X,{size:`sm`,variant:e?`outline`:`default`,onClick:r,children:[(0,Y.jsx)(ce,{className:`size-4`}),q(`firstUseGuideAddProject`)]}),(0,Y.jsxs)(X,{size:`sm`,variant:`outline`,onClick:i,children:[(0,Y.jsx)(n,{className:`size-4`}),q(`firstUseGuideCopyPrompt`)]}),(0,Y.jsx)(X,{size:`sm`,variant:`ghost`,onClick:a,children:q(`firstUseGuideDismiss`)})]})]})]})})})}function yn({onAddModel:e,onUseExample:t}){return(0,Y.jsx)(`div`,{className:`flex min-h-0 flex-1 items-center justify-center p-6`,children:(0,Y.jsxs)(`div`,{className:`w-full max-w-xl rounded-2xl border border-border bg-card/80 p-6 text-center shadow-sm backdrop-blur`,children:[(0,Y.jsx)(`div`,{className:`mx-auto flex size-12 items-center justify-center rounded-2xl bg-primary/10 text-primary`,children:(0,Y.jsx)(x,{className:`size-6`})}),(0,Y.jsx)(`h2`,{className:`mt-4 text-lg font-semibold text-foreground`,children:q(`modelSetupTitle`)}),(0,Y.jsx)(`p`,{className:`mx-auto mt-2 max-w-md text-sm leading-6 text-muted-foreground`,children:q(`modelSetupDescription`)}),(0,Y.jsxs)(`div`,{className:`mt-5 grid gap-3 rounded-xl border border-border/70 bg-muted/25 p-4 text-left text-sm`,children:[(0,Y.jsxs)(`div`,{className:`flex gap-3`,children:[(0,Y.jsx)(ne,{className:`mt-0.5 size-4 shrink-0 text-primary`}),(0,Y.jsx)(`span`,{className:`text-muted-foreground`,children:q(`modelSetupSupports`)})]}),(0,Y.jsxs)(`div`,{className:`flex gap-3`,children:[(0,Y.jsx)(te,{className:`mt-0.5 size-4 shrink-0 text-primary`}),(0,Y.jsx)(`span`,{className:`text-muted-foreground`,children:q(`modelSetupLocalStorage`)})]})]}),(0,Y.jsxs)(`div`,{className:`mt-6 flex flex-col justify-center gap-3 sm:flex-row`,children:[(0,Y.jsxs)(X,{onClick:e,className:`gap-2`,children:[(0,Y.jsx)(ae,{className:`size-4`}),q(`modelSetupAddModel`)]}),(0,Y.jsx)(X,{variant:`outline`,onClick:t,children:q(`modelSetupUseLiteLlmExample`)})]})]})})}function bn(){var e=[...arguments];return(0,W.useMemo)(()=>t=>{e.forEach(e=>e(t))},e)}var xn=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function Sn(e){let t=Object.prototype.toString.call(e);return t===`[object Window]`||t===`[object global]`}function Cn(e){return`nodeType`in e}function wn(e){return e?Sn(e)?e:Cn(e)?e.ownerDocument?.defaultView??window:window:window}function Tn(e){let{Document:t}=wn(e);return e instanceof t}function En(e){return Sn(e)?!1:e instanceof wn(e).HTMLElement}function Dn(e){return e instanceof wn(e).SVGElement}function On(e){return e?Sn(e)?e.document:Cn(e)?Tn(e)?e:En(e)||Dn(e)?e.ownerDocument:document:document:document}var kn=xn?W.useLayoutEffect:W.useEffect;function An(e){let t=(0,W.useRef)(e);return kn(()=>{t.current=e}),(0,W.useCallback)(function(){var e=[...arguments];return t.current==null?void 0:t.current(...e)},[])}function jn(){let e=(0,W.useRef)(null);return[(0,W.useCallback)((t,n)=>{e.current=setInterval(t,n)},[]),(0,W.useCallback)(()=>{e.current!==null&&(clearInterval(e.current),e.current=null)},[])]}function Mn(e,t){t===void 0&&(t=[e]);let n=(0,W.useRef)(e);return kn(()=>{n.current!==e&&(n.current=e)},t),n}function Nn(e,t){let n=(0,W.useRef)();return(0,W.useMemo)(()=>{let t=e(n.current);return n.current=t,t},[...t])}function Pn(e){let t=An(e),n=(0,W.useRef)(null);return[n,(0,W.useCallback)(e=>{e!==n.current&&t?.(e,n.current),n.current=e},[])]}function Fn(e){let t=(0,W.useRef)();return(0,W.useEffect)(()=>{t.current=e},[e]),t.current}var In={};function Ln(e,t){return(0,W.useMemo)(()=>{if(t)return t;let n=In[e]==null?0:In[e]+1;return In[e]=n,e+`-`+n},[e,t])}function Rn(e){return function(t){return[...arguments].slice(1).reduce((t,n)=>{let r=Object.entries(n);for(let[n,i]of r){let r=t[n];r!=null&&(t[n]=r+e*i)}return t},{...t})}}var zn=Rn(1),Bn=Rn(-1);function Vn(e){return`clientX`in e&&`clientY`in e}function Hn(e){if(!e)return!1;let{KeyboardEvent:t}=wn(e.target);return t&&e instanceof t}function Un(e){if(!e)return!1;let{TouchEvent:t}=wn(e.target);return t&&e instanceof t}function Wn(e){if(Un(e)){if(e.touches&&e.touches.length){let{clientX:t,clientY:n}=e.touches[0];return{x:t,y:n}}else if(e.changedTouches&&e.changedTouches.length){let{clientX:t,clientY:n}=e.changedTouches[0];return{x:t,y:n}}}return Vn(e)?{x:e.clientX,y:e.clientY}:null}var Gn=Object.freeze({Translate:{toString(e){if(!e)return;let{x:t,y:n}=e;return`translate3d(`+(t?Math.round(t):0)+`px, `+(n?Math.round(n):0)+`px, 0)`}},Scale:{toString(e){if(!e)return;let{scaleX:t,scaleY:n}=e;return`scaleX(`+t+`) scaleY(`+n+`)`}},Transform:{toString(e){if(e)return[Gn.Translate.toString(e),Gn.Scale.toString(e)].join(` `)}},Transition:{toString(e){let{property:t,duration:n,easing:r}=e;return t+` `+n+`ms `+r}}}),Kn=`a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]`;function qn(e){return e.matches(Kn)?e:e.querySelector(Kn)}var Jn={display:`none`};function Yn(e){let{id:t,value:n}=e;return W.createElement(`div`,{id:t,style:Jn},n)}function Xn(e){let{id:t,announcement:n,ariaLiveType:r=`assertive`}=e;return W.createElement(`div`,{id:t,style:{position:`fixed`,top:0,left:0,width:1,height:1,margin:-1,border:0,padding:0,overflow:`hidden`,clip:`rect(0 0 0 0)`,clipPath:`inset(100%)`,whiteSpace:`nowrap`},role:`status`,"aria-live":r,"aria-atomic":!0},n)}function Zn(){let[e,t]=(0,W.useState)(``);return{announce:(0,W.useCallback)(e=>{e!=null&&t(e)},[]),announcement:e}}var Qn=(0,W.createContext)(null);function $n(e){let t=(0,W.useContext)(Qn);(0,W.useEffect)(()=>{if(!t)throw Error(`useDndMonitor must be used within a children of <DndContext>`);return t(e)},[e,t])}function er(){let[e]=(0,W.useState)(()=>new Set),t=(0,W.useCallback)(t=>(e.add(t),()=>e.delete(t)),[e]);return[(0,W.useCallback)(t=>{let{type:n,event:r}=t;e.forEach(e=>e[n]?.call(e,r))},[e]),t]}var tr={draggable:`
|
|
30
|
+
To pick up a draggable item, press the space bar.
|
|
31
|
+
While dragging, use the arrow keys to move the item.
|
|
32
|
+
Press space again to drop the item in its new position, or press escape to cancel.
|
|
33
|
+
`},nr={onDragStart(e){let{active:t}=e;return`Picked up draggable item `+t.id+`.`},onDragOver(e){let{active:t,over:n}=e;return n?`Draggable item `+t.id+` was moved over droppable area `+n.id+`.`:`Draggable item `+t.id+` is no longer over a droppable area.`},onDragEnd(e){let{active:t,over:n}=e;return n?`Draggable item `+t.id+` was dropped over droppable area `+n.id:`Draggable item `+t.id+` was dropped.`},onDragCancel(e){let{active:t}=e;return`Dragging was cancelled. Draggable item `+t.id+` was dropped.`}};function rr(e){let{announcements:t=nr,container:n,hiddenTextDescribedById:r,screenReaderInstructions:i=tr}=e,{announce:a,announcement:o}=Zn(),s=Ln(`DndLiveRegion`),[c,l]=(0,W.useState)(!1);if((0,W.useEffect)(()=>{l(!0)},[]),$n((0,W.useMemo)(()=>({onDragStart(e){let{active:n}=e;a(t.onDragStart({active:n}))},onDragMove(e){let{active:n,over:r}=e;t.onDragMove&&a(t.onDragMove({active:n,over:r}))},onDragOver(e){let{active:n,over:r}=e;a(t.onDragOver({active:n,over:r}))},onDragEnd(e){let{active:n,over:r}=e;a(t.onDragEnd({active:n,over:r}))},onDragCancel(e){let{active:n,over:r}=e;a(t.onDragCancel({active:n,over:r}))}}),[a,t])),!c)return null;let u=W.createElement(W.Fragment,null,W.createElement(Yn,{id:r,value:i.draggable}),W.createElement(Xn,{id:s,announcement:o}));return n?(0,ot.createPortal)(u,n):u}var ir;(function(e){e.DragStart=`dragStart`,e.DragMove=`dragMove`,e.DragEnd=`dragEnd`,e.DragCancel=`dragCancel`,e.DragOver=`dragOver`,e.RegisterDroppable=`registerDroppable`,e.SetDroppableDisabled=`setDroppableDisabled`,e.UnregisterDroppable=`unregisterDroppable`})(ir||={});function ar(){}function or(e,t){return(0,W.useMemo)(()=>({sensor:e,options:t??{}}),[e,t])}function sr(){var e=[...arguments];return(0,W.useMemo)(()=>[...e].filter(e=>e!=null),[...e])}var cr=Object.freeze({x:0,y:0});function lr(e,t){return Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2)}function ur(e,t){let{data:{value:n}}=e,{data:{value:r}}=t;return n-r}function dr(e,t){let{data:{value:n}}=e,{data:{value:r}}=t;return r-n}function fr(e,t){if(!e||e.length===0)return null;let[n]=e;return t?n[t]:n}function pr(e,t,n){return t===void 0&&(t=e.left),n===void 0&&(n=e.top),{x:t+e.width*.5,y:n+e.height*.5}}var mr=e=>{let{collisionRect:t,droppableRects:n,droppableContainers:r}=e,i=pr(t,t.left,t.top),a=[];for(let e of r){let{id:t}=e,r=n.get(t);if(r){let n=lr(pr(r),i);a.push({id:t,data:{droppableContainer:e,value:n}})}}return a.sort(ur)};function hr(e,t){let n=Math.max(t.top,e.top),r=Math.max(t.left,e.left),i=Math.min(t.left+t.width,e.left+e.width),a=Math.min(t.top+t.height,e.top+e.height),o=i-r,s=a-n;if(r<i&&n<a){let n=t.width*t.height,r=e.width*e.height,i=o*s,a=i/(n+r-i);return Number(a.toFixed(4))}return 0}var gr=e=>{let{collisionRect:t,droppableRects:n,droppableContainers:r}=e,i=[];for(let e of r){let{id:r}=e,a=n.get(r);if(a){let n=hr(a,t);n>0&&i.push({id:r,data:{droppableContainer:e,value:n}})}}return i.sort(dr)};function _r(e,t,n){return{...e,scaleX:t&&n?t.width/n.width:1,scaleY:t&&n?t.height/n.height:1}}function vr(e,t){return e&&t?{x:e.left-t.left,y:e.top-t.top}:cr}function yr(e){return function(t){return[...arguments].slice(1).reduce((t,n)=>({...t,top:t.top+e*n.y,bottom:t.bottom+e*n.y,left:t.left+e*n.x,right:t.right+e*n.x}),{...t})}}var br=yr(1);function xr(e){if(e.startsWith(`matrix3d(`)){let t=e.slice(9,-1).split(/, /);return{x:+t[12],y:+t[13],scaleX:+t[0],scaleY:+t[5]}}else if(e.startsWith(`matrix(`)){let t=e.slice(7,-1).split(/, /);return{x:+t[4],y:+t[5],scaleX:+t[0],scaleY:+t[3]}}return null}function Sr(e,t,n){let r=xr(t);if(!r)return e;let{scaleX:i,scaleY:a,x:o,y:s}=r,c=e.left-o-(1-i)*parseFloat(n),l=e.top-s-(1-a)*parseFloat(n.slice(n.indexOf(` `)+1)),u=i?e.width/i:e.width,d=a?e.height/a:e.height;return{width:u,height:d,top:l,right:c+u,bottom:l+d,left:c}}var Cr={ignoreTransform:!1};function wr(e,t){t===void 0&&(t=Cr);let n=e.getBoundingClientRect();if(t.ignoreTransform){let{transform:t,transformOrigin:r}=wn(e).getComputedStyle(e);t&&(n=Sr(n,t,r))}let{top:r,left:i,width:a,height:o,bottom:s,right:c}=n;return{top:r,left:i,width:a,height:o,bottom:s,right:c}}function Tr(e){return wr(e,{ignoreTransform:!0})}function Er(e){let t=e.innerWidth,n=e.innerHeight;return{top:0,left:0,right:t,bottom:n,width:t,height:n}}function Dr(e,t){return t===void 0&&(t=wn(e).getComputedStyle(e)),t.position===`fixed`}function Or(e,t){t===void 0&&(t=wn(e).getComputedStyle(e));let n=/(auto|scroll|overlay)/;return[`overflow`,`overflowX`,`overflowY`].some(e=>{let r=t[e];return typeof r==`string`?n.test(r):!1})}function kr(e,t){let n=[];function r(i){if(t!=null&&n.length>=t||!i)return n;if(Tn(i)&&i.scrollingElement!=null&&!n.includes(i.scrollingElement))return n.push(i.scrollingElement),n;if(!En(i)||Dn(i)||n.includes(i))return n;let a=wn(e).getComputedStyle(i);return i!==e&&Or(i,a)&&n.push(i),Dr(i,a)?n:r(i.parentNode)}return e?r(e):n}function Ar(e){let[t]=kr(e,1);return t??null}function jr(e){return!xn||!e?null:Sn(e)?e:Cn(e)?Tn(e)||e===On(e).scrollingElement?window:En(e)?e:null:null}function Mr(e){return Sn(e)?e.scrollX:e.scrollLeft}function Nr(e){return Sn(e)?e.scrollY:e.scrollTop}function Pr(e){return{x:Mr(e),y:Nr(e)}}var Fr;(function(e){e[e.Forward=1]=`Forward`,e[e.Backward=-1]=`Backward`})(Fr||={});function Ir(e){return!xn||!e?!1:e===document.scrollingElement}function Lr(e){let t={x:0,y:0},n=Ir(e)?{height:window.innerHeight,width:window.innerWidth}:{height:e.clientHeight,width:e.clientWidth},r={x:e.scrollWidth-n.width,y:e.scrollHeight-n.height};return{isTop:e.scrollTop<=t.y,isLeft:e.scrollLeft<=t.x,isBottom:e.scrollTop>=r.y,isRight:e.scrollLeft>=r.x,maxScroll:r,minScroll:t}}var Rr={x:.2,y:.2};function zr(e,t,n,r,i){let{top:a,left:o,right:s,bottom:c}=n;r===void 0&&(r=10),i===void 0&&(i=Rr);let{isTop:l,isBottom:u,isLeft:d,isRight:f}=Lr(e),p={x:0,y:0},m={x:0,y:0},h={height:t.height*i.y,width:t.width*i.x};return!l&&a<=t.top+h.height?(p.y=Fr.Backward,m.y=r*Math.abs((t.top+h.height-a)/h.height)):!u&&c>=t.bottom-h.height&&(p.y=Fr.Forward,m.y=r*Math.abs((t.bottom-h.height-c)/h.height)),!f&&s>=t.right-h.width?(p.x=Fr.Forward,m.x=r*Math.abs((t.right-h.width-s)/h.width)):!d&&o<=t.left+h.width&&(p.x=Fr.Backward,m.x=r*Math.abs((t.left+h.width-o)/h.width)),{direction:p,speed:m}}function Br(e){if(e===document.scrollingElement){let{innerWidth:e,innerHeight:t}=window;return{top:0,left:0,right:e,bottom:t,width:e,height:t}}let{top:t,left:n,right:r,bottom:i}=e.getBoundingClientRect();return{top:t,left:n,right:r,bottom:i,width:e.clientWidth,height:e.clientHeight}}function Vr(e){return e.reduce((e,t)=>zn(e,Pr(t)),cr)}function Hr(e){return e.reduce((e,t)=>e+Mr(t),0)}function Ur(e){return e.reduce((e,t)=>e+Nr(t),0)}function Wr(e,t){if(t===void 0&&(t=wr),!e)return;let{top:n,left:r,bottom:i,right:a}=t(e);Ar(e)&&(i<=0||a<=0||n>=window.innerHeight||r>=window.innerWidth)&&e.scrollIntoView({block:`center`,inline:`center`})}var Gr=[[`x`,[`left`,`right`],Hr],[`y`,[`top`,`bottom`],Ur]],Kr=class{constructor(e,t){this.rect=void 0,this.width=void 0,this.height=void 0,this.top=void 0,this.bottom=void 0,this.right=void 0,this.left=void 0;let n=kr(t),r=Vr(n);this.rect={...e},this.width=e.width,this.height=e.height;for(let[e,t,i]of Gr)for(let a of t)Object.defineProperty(this,a,{get:()=>{let t=i(n),o=r[e]-t;return this.rect[a]+o},enumerable:!0});Object.defineProperty(this,`rect`,{enumerable:!1})}},qr=class{constructor(e){this.target=void 0,this.listeners=[],this.removeAll=()=>{this.listeners.forEach(e=>this.target?.removeEventListener(...e))},this.target=e}add(e,t,n){var r;(r=this.target)==null||r.addEventListener(e,t,n),this.listeners.push([e,t,n])}};function Jr(e){let{EventTarget:t}=wn(e);return e instanceof t?e:On(e)}function Yr(e,t){let n=Math.abs(e.x),r=Math.abs(e.y);return typeof t==`number`?Math.sqrt(n**2+r**2)>t:`x`in t&&`y`in t?n>t.x&&r>t.y:`x`in t?n>t.x:`y`in t?r>t.y:!1}var Xr;(function(e){e.Click=`click`,e.DragStart=`dragstart`,e.Keydown=`keydown`,e.ContextMenu=`contextmenu`,e.Resize=`resize`,e.SelectionChange=`selectionchange`,e.VisibilityChange=`visibilitychange`})(Xr||={});function Zr(e){e.preventDefault()}function Qr(e){e.stopPropagation()}var $;(function(e){e.Space=`Space`,e.Down=`ArrowDown`,e.Right=`ArrowRight`,e.Left=`ArrowLeft`,e.Up=`ArrowUp`,e.Esc=`Escape`,e.Enter=`Enter`,e.Tab=`Tab`})($||={});var $r={start:[$.Space,$.Enter],cancel:[$.Esc],end:[$.Space,$.Enter,$.Tab]},ei=(e,t)=>{let{currentCoordinates:n}=t;switch(e.code){case $.Right:return{...n,x:n.x+25};case $.Left:return{...n,x:n.x-25};case $.Down:return{...n,y:n.y+25};case $.Up:return{...n,y:n.y-25}}},ti=class{constructor(e){this.props=void 0,this.autoScrollEnabled=!1,this.referenceCoordinates=void 0,this.listeners=void 0,this.windowListeners=void 0,this.props=e;let{event:{target:t}}=e;this.props=e,this.listeners=new qr(On(t)),this.windowListeners=new qr(wn(t)),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleCancel=this.handleCancel.bind(this),this.attach()}attach(){this.handleStart(),this.windowListeners.add(Xr.Resize,this.handleCancel),this.windowListeners.add(Xr.VisibilityChange,this.handleCancel),setTimeout(()=>this.listeners.add(Xr.Keydown,this.handleKeyDown))}handleStart(){let{activeNode:e,onStart:t}=this.props,n=e.node.current;n&&Wr(n),t(cr)}handleKeyDown(e){if(Hn(e)){let{active:t,context:n,options:r}=this.props,{keyboardCodes:i=$r,coordinateGetter:a=ei,scrollBehavior:o=`smooth`}=r,{code:s}=e;if(i.end.includes(s)){this.handleEnd(e);return}if(i.cancel.includes(s)){this.handleCancel(e);return}let{collisionRect:c}=n.current,l=c?{x:c.left,y:c.top}:cr;this.referenceCoordinates||=l;let u=a(e,{active:t,context:n.current,currentCoordinates:l});if(u){let t=Bn(u,l),r={x:0,y:0},{scrollableAncestors:i}=n.current;for(let n of i){let i=e.code,{isTop:a,isRight:s,isLeft:c,isBottom:l,maxScroll:d,minScroll:f}=Lr(n),p=Br(n),m={x:Math.min(i===$.Right?p.right-p.width/2:p.right,Math.max(i===$.Right?p.left:p.left+p.width/2,u.x)),y:Math.min(i===$.Down?p.bottom-p.height/2:p.bottom,Math.max(i===$.Down?p.top:p.top+p.height/2,u.y))},h=i===$.Right&&!s||i===$.Left&&!c,g=i===$.Down&&!l||i===$.Up&&!a;if(h&&m.x!==u.x){let e=n.scrollLeft+t.x,a=i===$.Right&&e<=d.x||i===$.Left&&e>=f.x;if(a&&!t.y){n.scrollTo({left:e,behavior:o});return}a?r.x=n.scrollLeft-e:r.x=i===$.Right?n.scrollLeft-d.x:n.scrollLeft-f.x,r.x&&n.scrollBy({left:-r.x,behavior:o});break}else if(g&&m.y!==u.y){let e=n.scrollTop+t.y,a=i===$.Down&&e<=d.y||i===$.Up&&e>=f.y;if(a&&!t.x){n.scrollTo({top:e,behavior:o});return}a?r.y=n.scrollTop-e:r.y=i===$.Down?n.scrollTop-d.y:n.scrollTop-f.y,r.y&&n.scrollBy({top:-r.y,behavior:o});break}}this.handleMove(e,zn(Bn(u,this.referenceCoordinates),r))}}}handleMove(e,t){let{onMove:n}=this.props;e.preventDefault(),n(t)}handleEnd(e){let{onEnd:t}=this.props;e.preventDefault(),this.detach(),t()}handleCancel(e){let{onCancel:t}=this.props;e.preventDefault(),this.detach(),t()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll()}};ti.activators=[{eventName:`onKeyDown`,handler:(e,t,n)=>{let{keyboardCodes:r=$r,onActivation:i}=t,{active:a}=n,{code:o}=e.nativeEvent;if(r.start.includes(o)){let t=a.activatorNode.current;return t&&e.target!==t?!1:(e.preventDefault(),i?.({event:e.nativeEvent}),!0)}return!1}}];function ni(e){return!!(e&&`distance`in e)}function ri(e){return!!(e&&`delay`in e)}var ii=class{constructor(e,t,n){n===void 0&&(n=Jr(e.event.target)),this.props=void 0,this.events=void 0,this.autoScrollEnabled=!0,this.document=void 0,this.activated=!1,this.initialCoordinates=void 0,this.timeoutId=null,this.listeners=void 0,this.documentListeners=void 0,this.windowListeners=void 0,this.props=e,this.events=t;let{event:r}=e,{target:i}=r;this.props=e,this.events=t,this.document=On(i),this.documentListeners=new qr(this.document),this.listeners=new qr(n),this.windowListeners=new qr(wn(i)),this.initialCoordinates=Wn(r)??cr,this.handleStart=this.handleStart.bind(this),this.handleMove=this.handleMove.bind(this),this.handleEnd=this.handleEnd.bind(this),this.handleCancel=this.handleCancel.bind(this),this.handleKeydown=this.handleKeydown.bind(this),this.removeTextSelection=this.removeTextSelection.bind(this),this.attach()}attach(){let{events:e,props:{options:{activationConstraint:t,bypassActivationConstraint:n}}}=this;if(this.listeners.add(e.move.name,this.handleMove,{passive:!1}),this.listeners.add(e.end.name,this.handleEnd),e.cancel&&this.listeners.add(e.cancel.name,this.handleCancel),this.windowListeners.add(Xr.Resize,this.handleCancel),this.windowListeners.add(Xr.DragStart,Zr),this.windowListeners.add(Xr.VisibilityChange,this.handleCancel),this.windowListeners.add(Xr.ContextMenu,Zr),this.documentListeners.add(Xr.Keydown,this.handleKeydown),t){if(n!=null&&n({event:this.props.event,activeNode:this.props.activeNode,options:this.props.options}))return this.handleStart();if(ri(t)){this.timeoutId=setTimeout(this.handleStart,t.delay),this.handlePending(t);return}if(ni(t)){this.handlePending(t);return}}this.handleStart()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll(),setTimeout(this.documentListeners.removeAll,50),this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}handlePending(e,t){let{active:n,onPending:r}=this.props;r(n,e,this.initialCoordinates,t)}handleStart(){let{initialCoordinates:e}=this,{onStart:t}=this.props;e&&(this.activated=!0,this.documentListeners.add(Xr.Click,Qr,{capture:!0}),this.removeTextSelection(),this.documentListeners.add(Xr.SelectionChange,this.removeTextSelection),t(e))}handleMove(e){let{activated:t,initialCoordinates:n,props:r}=this,{onMove:i,options:{activationConstraint:a}}=r;if(!n)return;let o=Wn(e)??cr,s=Bn(n,o);if(!t&&a){if(ni(a)){if(a.tolerance!=null&&Yr(s,a.tolerance))return this.handleCancel();if(Yr(s,a.distance))return this.handleStart()}if(ri(a)&&Yr(s,a.tolerance))return this.handleCancel();this.handlePending(a,s);return}e.cancelable&&e.preventDefault(),i(o)}handleEnd(){let{onAbort:e,onEnd:t}=this.props;this.detach(),this.activated||e(this.props.active),t()}handleCancel(){let{onAbort:e,onCancel:t}=this.props;this.detach(),this.activated||e(this.props.active),t()}handleKeydown(e){e.code===$.Esc&&this.handleCancel()}removeTextSelection(){var e;(e=this.document.getSelection())==null||e.removeAllRanges()}},ai={cancel:{name:`pointercancel`},move:{name:`pointermove`},end:{name:`pointerup`}},oi=class extends ii{constructor(e){let{event:t}=e,n=On(t.target);super(e,ai,n)}};oi.activators=[{eventName:`onPointerDown`,handler:(e,t)=>{let{nativeEvent:n}=e,{onActivation:r}=t;return!n.isPrimary||n.button!==0?!1:(r?.({event:n}),!0)}}];var si={move:{name:`mousemove`},end:{name:`mouseup`}},ci;(function(e){e[e.RightClick=2]=`RightClick`})(ci||={});var li=class extends ii{constructor(e){super(e,si,On(e.event.target))}};li.activators=[{eventName:`onMouseDown`,handler:(e,t)=>{let{nativeEvent:n}=e,{onActivation:r}=t;return n.button===ci.RightClick?!1:(r?.({event:n}),!0)}}];var ui={cancel:{name:`touchcancel`},move:{name:`touchmove`},end:{name:`touchend`}},di=class extends ii{constructor(e){super(e,ui)}static setup(){return window.addEventListener(ui.move.name,e,{capture:!1,passive:!1}),function(){window.removeEventListener(ui.move.name,e)};function e(){}}};di.activators=[{eventName:`onTouchStart`,handler:(e,t)=>{let{nativeEvent:n}=e,{onActivation:r}=t,{touches:i}=n;return i.length>1?!1:(r?.({event:n}),!0)}}];var fi;(function(e){e[e.Pointer=0]=`Pointer`,e[e.DraggableRect=1]=`DraggableRect`})(fi||={});var pi;(function(e){e[e.TreeOrder=0]=`TreeOrder`,e[e.ReversedTreeOrder=1]=`ReversedTreeOrder`})(pi||={});function mi(e){let{acceleration:t,activator:n=fi.Pointer,canScroll:r,draggingRect:i,enabled:a,interval:o=5,order:s=pi.TreeOrder,pointerCoordinates:c,scrollableAncestors:l,scrollableAncestorRects:u,delta:d,threshold:f}=e,p=gi({delta:d,disabled:!a}),[m,h]=jn(),g=(0,W.useRef)({x:0,y:0}),_=(0,W.useRef)({x:0,y:0}),v=(0,W.useMemo)(()=>{switch(n){case fi.Pointer:return c?{top:c.y,bottom:c.y,left:c.x,right:c.x}:null;case fi.DraggableRect:return i}},[n,i,c]),y=(0,W.useRef)(null),b=(0,W.useCallback)(()=>{let e=y.current;if(!e)return;let t=g.current.x*_.current.x,n=g.current.y*_.current.y;e.scrollBy(t,n)},[]),x=(0,W.useMemo)(()=>s===pi.TreeOrder?[...l].reverse():l,[s,l]);(0,W.useEffect)(()=>{if(!a||!l.length||!v){h();return}for(let e of x){if(r?.(e)===!1)continue;let n=u[l.indexOf(e)];if(!n)continue;let{direction:i,speed:a}=zr(e,n,v,t,f);for(let e of[`x`,`y`])p[e][i[e]]||(a[e]=0,i[e]=0);if(a.x>0||a.y>0){h(),y.current=e,m(b,o),g.current=a,_.current=i;return}}g.current={x:0,y:0},_.current={x:0,y:0},h()},[t,b,r,h,a,o,JSON.stringify(v),JSON.stringify(p),m,l,x,u,JSON.stringify(f)])}var hi={x:{[Fr.Backward]:!1,[Fr.Forward]:!1},y:{[Fr.Backward]:!1,[Fr.Forward]:!1}};function gi(e){let{delta:t,disabled:n}=e,r=Fn(t);return Nn(e=>{if(n||!r||!e)return hi;let i={x:Math.sign(t.x-r.x),y:Math.sign(t.y-r.y)};return{x:{[Fr.Backward]:e.x[Fr.Backward]||i.x===-1,[Fr.Forward]:e.x[Fr.Forward]||i.x===1},y:{[Fr.Backward]:e.y[Fr.Backward]||i.y===-1,[Fr.Forward]:e.y[Fr.Forward]||i.y===1}}},[n,t,r])}function _i(e,t){let n=t==null?void 0:e.get(t),r=n?n.node.current:null;return Nn(e=>t==null?null:r??e??null,[r,t])}function vi(e,t){return(0,W.useMemo)(()=>e.reduce((e,n)=>{let{sensor:r}=n,i=r.activators.map(e=>({eventName:e.eventName,handler:t(e.handler,n)}));return[...e,...i]},[]),[e,t])}var yi;(function(e){e[e.Always=0]=`Always`,e[e.BeforeDragging=1]=`BeforeDragging`,e[e.WhileDragging=2]=`WhileDragging`})(yi||={});var bi;(function(e){e.Optimized=`optimized`})(bi||={});var xi=new Map;function Si(e,t){let{dragging:n,dependencies:r,config:i}=t,[a,o]=(0,W.useState)(null),{frequency:s,measure:c,strategy:l}=i,u=(0,W.useRef)(e),d=g(),f=Mn(d),p=(0,W.useCallback)(function(e){e===void 0&&(e=[]),!f.current&&o(t=>t===null?e:t.concat(e.filter(e=>!t.includes(e))))},[f]),m=(0,W.useRef)(null),h=Nn(t=>{if(d&&!n)return xi;if(!t||t===xi||u.current!==e||a!=null){let t=new Map;for(let n of e){if(!n)continue;if(a&&a.length>0&&!a.includes(n.id)&&n.rect.current){t.set(n.id,n.rect.current);continue}let e=n.node.current,r=e?new Kr(c(e),e):null;n.rect.current=r,r&&t.set(n.id,r)}return t}return t},[e,a,n,d,c]);return(0,W.useEffect)(()=>{u.current=e},[e]),(0,W.useEffect)(()=>{d||p()},[n,d]),(0,W.useEffect)(()=>{a&&a.length>0&&o(null)},[JSON.stringify(a)]),(0,W.useEffect)(()=>{d||typeof s!=`number`||m.current!==null||(m.current=setTimeout(()=>{p(),m.current=null},s))},[s,d,p,...r]),{droppableRects:h,measureDroppableContainers:p,measuringScheduled:a!=null};function g(){switch(l){case yi.Always:return!1;case yi.BeforeDragging:return n;default:return!n}}}function Ci(e,t){return Nn(n=>e?n||(typeof t==`function`?t(e):e):null,[t,e])}function wi(e,t){return Ci(e,t)}function Ti(e){let{callback:t,disabled:n}=e,r=An(t),i=(0,W.useMemo)(()=>{if(n||typeof window>`u`||window.MutationObserver===void 0)return;let{MutationObserver:e}=window;return new e(r)},[r,n]);return(0,W.useEffect)(()=>()=>i?.disconnect(),[i]),i}function Ei(e){let{callback:t,disabled:n}=e,r=An(t),i=(0,W.useMemo)(()=>{if(n||typeof window>`u`||window.ResizeObserver===void 0)return;let{ResizeObserver:e}=window;return new e(r)},[n]);return(0,W.useEffect)(()=>()=>i?.disconnect(),[i]),i}function Di(e){return new Kr(wr(e),e)}function Oi(e,t,n){t===void 0&&(t=Di);let[r,i]=(0,W.useState)(null);function a(){i(r=>{if(!e)return null;if(e.isConnected===!1)return r??n??null;let i=t(e);return JSON.stringify(r)===JSON.stringify(i)?r:i})}let o=Ti({callback(t){if(e)for(let n of t){let{type:t,target:r}=n;if(t===`childList`&&r instanceof HTMLElement&&r.contains(e)){a();break}}}}),s=Ei({callback:a});return kn(()=>{a(),e?(s?.observe(e),o?.observe(document.body,{childList:!0,subtree:!0})):(s?.disconnect(),o?.disconnect())},[e]),r}function ki(e){return vr(e,Ci(e))}var Ai=[];function ji(e){let t=(0,W.useRef)(e),n=Nn(n=>e?n&&n!==Ai&&e&&t.current&&e.parentNode===t.current.parentNode?n:kr(e):Ai,[e]);return(0,W.useEffect)(()=>{t.current=e},[e]),n}function Mi(e){let[t,n]=(0,W.useState)(null),r=(0,W.useRef)(e),i=(0,W.useCallback)(e=>{let t=jr(e.target);t&&n(e=>e?(e.set(t,Pr(t)),new Map(e)):null)},[]);return(0,W.useEffect)(()=>{let t=r.current;if(e!==t){a(t);let o=e.map(e=>{let t=jr(e);return t?(t.addEventListener(`scroll`,i,{passive:!0}),[t,Pr(t)]):null}).filter(e=>e!=null);n(o.length?new Map(o):null),r.current=e}return()=>{a(e),a(t)};function a(e){e.forEach(e=>{jr(e)?.removeEventListener(`scroll`,i)})}},[i,e]),(0,W.useMemo)(()=>e.length?t?Array.from(t.values()).reduce((e,t)=>zn(e,t),cr):Vr(e):cr,[e,t])}function Ni(e,t){t===void 0&&(t=[]);let n=(0,W.useRef)(null);return(0,W.useEffect)(()=>{n.current=null},t),(0,W.useEffect)(()=>{let t=e!==cr;t&&!n.current&&(n.current=e),!t&&n.current&&(n.current=null)},[e]),n.current?Bn(e,n.current):cr}function Pi(e){(0,W.useEffect)(()=>{if(!xn)return;let t=e.map(e=>{let{sensor:t}=e;return t.setup==null?void 0:t.setup()});return()=>{for(let e of t)e?.()}},e.map(e=>{let{sensor:t}=e;return t}))}function Fi(e,t){return(0,W.useMemo)(()=>e.reduce((e,n)=>{let{eventName:r,handler:i}=n;return e[r]=e=>{i(e,t)},e},{}),[e,t])}function Ii(e){return(0,W.useMemo)(()=>e?Er(e):null,[e])}var Li=[];function Ri(e,t){t===void 0&&(t=wr);let[n]=e,r=Ii(n?wn(n):null),[i,a]=(0,W.useState)(Li);function o(){a(()=>e.length?e.map(e=>Ir(e)?r:new Kr(t(e),e)):Li)}let s=Ei({callback:o});return kn(()=>{s?.disconnect(),o(),e.forEach(e=>s?.observe(e))},[e]),i}function zi(e){if(!e)return null;if(e.children.length>1)return e;let t=e.children[0];return En(t)?t:e}function Bi(e){let{measure:t}=e,[n,r]=(0,W.useState)(null),i=Ei({callback:(0,W.useCallback)(e=>{for(let{target:n}of e)if(En(n)){r(e=>{let r=t(n);return e?{...e,width:r.width,height:r.height}:r});break}},[t])}),[a,o]=Pn((0,W.useCallback)(e=>{let n=zi(e);i?.disconnect(),n&&i?.observe(n),r(n?t(n):null)},[t,i]));return(0,W.useMemo)(()=>({nodeRef:a,rect:n,setRef:o}),[n,a,o])}var Vi=[{sensor:oi,options:{}},{sensor:ti,options:{}}],Hi={current:{}},Ui={draggable:{measure:Tr},droppable:{measure:Tr,strategy:yi.WhileDragging,frequency:bi.Optimized},dragOverlay:{measure:wr}},Wi=class extends Map{get(e){return e==null?void 0:super.get(e)??void 0}toArray(){return Array.from(this.values())}getEnabled(){return this.toArray().filter(e=>{let{disabled:t}=e;return!t})}getNodeFor(e){return this.get(e)?.node.current??void 0}},Gi={activatorEvent:null,active:null,activeNode:null,activeNodeRect:null,collisions:null,containerNodeRect:null,draggableNodes:new Map,droppableRects:new Map,droppableContainers:new Wi,over:null,dragOverlay:{nodeRef:{current:null},rect:null,setRef:ar},scrollableAncestors:[],scrollableAncestorRects:[],measuringConfiguration:Ui,measureDroppableContainers:ar,windowRect:null,measuringScheduled:!1},Ki={activatorEvent:null,activators:[],active:null,activeNodeRect:null,ariaDescribedById:{draggable:``},dispatch:ar,draggableNodes:new Map,over:null,measureDroppableContainers:ar},qi=(0,W.createContext)(Ki),Ji=(0,W.createContext)(Gi);function Yi(){return{draggable:{active:null,initialCoordinates:{x:0,y:0},nodes:new Map,translate:{x:0,y:0}},droppable:{containers:new Wi}}}function Xi(e,t){switch(t.type){case ir.DragStart:return{...e,draggable:{...e.draggable,initialCoordinates:t.initialCoordinates,active:t.active}};case ir.DragMove:return e.draggable.active==null?e:{...e,draggable:{...e.draggable,translate:{x:t.coordinates.x-e.draggable.initialCoordinates.x,y:t.coordinates.y-e.draggable.initialCoordinates.y}}};case ir.DragEnd:case ir.DragCancel:return{...e,draggable:{...e.draggable,active:null,initialCoordinates:{x:0,y:0},translate:{x:0,y:0}}};case ir.RegisterDroppable:{let{element:n}=t,{id:r}=n,i=new Wi(e.droppable.containers);return i.set(r,n),{...e,droppable:{...e.droppable,containers:i}}}case ir.SetDroppableDisabled:{let{id:n,key:r,disabled:i}=t,a=e.droppable.containers.get(n);if(!a||r!==a.key)return e;let o=new Wi(e.droppable.containers);return o.set(n,{...a,disabled:i}),{...e,droppable:{...e.droppable,containers:o}}}case ir.UnregisterDroppable:{let{id:n,key:r}=t,i=e.droppable.containers.get(n);if(!i||r!==i.key)return e;let a=new Wi(e.droppable.containers);return a.delete(n),{...e,droppable:{...e.droppable,containers:a}}}default:return e}}function Zi(e){let{disabled:t}=e,{active:n,activatorEvent:r,draggableNodes:i}=(0,W.useContext)(qi),a=Fn(r),o=Fn(n?.id);return(0,W.useEffect)(()=>{if(!t&&!r&&a&&o!=null){if(!Hn(a)||document.activeElement===a.target)return;let e=i.get(o);if(!e)return;let{activatorNode:t,node:n}=e;if(!t.current&&!n.current)return;requestAnimationFrame(()=>{for(let e of[t.current,n.current]){if(!e)continue;let t=qn(e);if(t){t.focus();break}}})}},[r,t,i,o,a]),null}function Qi(e,t){let{transform:n,...r}=t;return e!=null&&e.length?e.reduce((e,t)=>t({transform:e,...r}),n):n}function $i(e){return(0,W.useMemo)(()=>({draggable:{...Ui.draggable,...e?.draggable},droppable:{...Ui.droppable,...e?.droppable},dragOverlay:{...Ui.dragOverlay,...e?.dragOverlay}}),[e?.draggable,e?.droppable,e?.dragOverlay])}function ea(e){let{activeNode:t,measure:n,initialRect:r,config:i=!0}=e,a=(0,W.useRef)(!1),{x:o,y:s}=typeof i==`boolean`?{x:i,y:i}:i;kn(()=>{if(!o&&!s||!t){a.current=!1;return}if(a.current||!r)return;let e=t?.node.current;if(!e||e.isConnected===!1)return;let i=vr(n(e),r);if(o||(i.x=0),s||(i.y=0),a.current=!0,Math.abs(i.x)>0||Math.abs(i.y)>0){let t=Ar(e);t&&t.scrollBy({top:i.y,left:i.x})}},[t,o,s,r,n])}var ta=(0,W.createContext)({...cr,scaleX:1,scaleY:1}),na;(function(e){e[e.Uninitialized=0]=`Uninitialized`,e[e.Initializing=1]=`Initializing`,e[e.Initialized=2]=`Initialized`})(na||={});var ra=(0,W.memo)(function(e){let{id:t,accessibility:n,autoScroll:r=!0,children:i,sensors:a=Vi,collisionDetection:o=gr,measuring:s,modifiers:c,...l}=e,[u,d]=(0,W.useReducer)(Xi,void 0,Yi),[f,p]=er(),[m,h]=(0,W.useState)(na.Uninitialized),g=m===na.Initialized,{draggable:{active:_,nodes:v,translate:y},droppable:{containers:b}}=u,x=_==null?null:v.get(_),S=(0,W.useRef)({initial:null,translated:null}),C=(0,W.useMemo)(()=>_==null?null:{id:_,data:x?.data??Hi,rect:S},[_,x]),w=(0,W.useRef)(null),[T,E]=(0,W.useState)(null),[D,O]=(0,W.useState)(null),k=Mn(l,Object.values(l)),ee=Ln(`DndDescribedBy`,t),A=(0,W.useMemo)(()=>b.getEnabled(),[b]),j=$i(s),{droppableRects:M,measureDroppableContainers:N,measuringScheduled:P}=Si(A,{dragging:g,dependencies:[y.x,y.y],config:j.droppable}),F=_i(v,_),te=(0,W.useMemo)(()=>D?Wn(D):null,[D]),I=De(),ne=wi(F,j.draggable.measure);ea({activeNode:_==null?null:v.get(_),config:I.layoutShiftCompensation,initialRect:ne,measure:j.draggable.measure});let re=Oi(F,j.draggable.measure,ne),ie=Oi(F?F.parentElement:null),L=(0,W.useRef)({activatorEvent:null,active:null,activeNode:F,collisionRect:null,collisions:null,droppableRects:M,draggableNodes:v,draggingNode:null,draggingNodeRect:null,droppableContainers:b,over:null,scrollableAncestors:[],scrollAdjustedTranslate:null}),ae=b.getNodeFor(L.current.over?.id),R=Bi({measure:j.dragOverlay.measure}),oe=R.nodeRef.current??F,se=g?R.rect??re:null,ce=!!(R.nodeRef.current&&R.rect),le=ki(ce?null:re),ue=Ii(oe?wn(oe):null),de=ji(g?ae??F:null),fe=Ri(de),z=Qi(c,{transform:{x:y.x-le.x,y:y.y-le.y,scaleX:1,scaleY:1},activatorEvent:D,active:C,activeNodeRect:re,containerNodeRect:ie,draggingNodeRect:se,over:L.current.over,overlayNodeRect:R.rect,scrollableAncestors:de,scrollableAncestorRects:fe,windowRect:ue}),pe=te?zn(te,y):null,me=Mi(de),he=Ni(me),ge=Ni(me,[re]),B=zn(z,he),_e=se?br(se,z):null,V=C&&_e?o({active:C,collisionRect:_e,droppableRects:M,droppableContainers:A,pointerCoordinates:pe}):null,ve=fr(V,`id`),[ye,be]=(0,W.useState)(null),xe=_r(ce?z:zn(z,ge),ye?.rect??null,re),Se=(0,W.useRef)(null),Ce=(0,W.useCallback)((e,t)=>{let{sensor:n,options:r}=t;if(w.current==null)return;let i=v.get(w.current);if(!i)return;let a=e.nativeEvent;Se.current=new n({active:w.current,activeNode:i,event:a,options:r,context:L,onAbort(e){if(!v.get(e))return;let{onDragAbort:t}=k.current,n={id:e};t?.(n),f({type:`onDragAbort`,event:n})},onPending(e,t,n,r){if(!v.get(e))return;let{onDragPending:i}=k.current,a={id:e,constraint:t,initialCoordinates:n,offset:r};i?.(a),f({type:`onDragPending`,event:a})},onStart(e){let t=w.current;if(t==null)return;let n=v.get(t);if(!n)return;let{onDragStart:r}=k.current,i={activatorEvent:a,active:{id:t,data:n.data,rect:S}};(0,ot.unstable_batchedUpdates)(()=>{r?.(i),h(na.Initializing),d({type:ir.DragStart,initialCoordinates:e,active:t}),f({type:`onDragStart`,event:i}),E(Se.current),O(a)})},onMove(e){d({type:ir.DragMove,coordinates:e})},onEnd:o(ir.DragEnd),onCancel:o(ir.DragCancel)});function o(e){return async function(){let{active:t,collisions:n,over:r,scrollAdjustedTranslate:i}=L.current,o=null;if(t&&i){let{cancelDrop:s}=k.current;o={activatorEvent:a,active:t,collisions:n,delta:i,over:r},e===ir.DragEnd&&typeof s==`function`&&await Promise.resolve(s(o))&&(e=ir.DragCancel)}w.current=null,(0,ot.unstable_batchedUpdates)(()=>{d({type:e}),h(na.Uninitialized),be(null),E(null),O(null),Se.current=null;let t=e===ir.DragEnd?`onDragEnd`:`onDragCancel`;if(o){let e=k.current[t];e?.(o),f({type:t,event:o})}})}}},[v]),we=vi(a,(0,W.useCallback)((e,t)=>(n,r)=>{let i=n.nativeEvent,a=v.get(r);if(w.current!==null||!a||i.dndKit||i.defaultPrevented)return;let o={active:a};e(n,t.options,o)===!0&&(i.dndKit={capturedBy:t.sensor},w.current=r,Ce(n,t))},[v,Ce]));Pi(a),kn(()=>{re&&m===na.Initializing&&h(na.Initialized)},[re,m]),(0,W.useEffect)(()=>{let{onDragMove:e}=k.current,{active:t,activatorEvent:n,collisions:r,over:i}=L.current;if(!t||!n)return;let a={active:t,activatorEvent:n,collisions:r,delta:{x:B.x,y:B.y},over:i};(0,ot.unstable_batchedUpdates)(()=>{e?.(a),f({type:`onDragMove`,event:a})})},[B.x,B.y]),(0,W.useEffect)(()=>{let{active:e,activatorEvent:t,collisions:n,droppableContainers:r,scrollAdjustedTranslate:i}=L.current;if(!e||w.current==null||!t||!i)return;let{onDragOver:a}=k.current,o=r.get(ve),s=o&&o.rect.current?{id:o.id,rect:o.rect.current,data:o.data,disabled:o.disabled}:null,c={active:e,activatorEvent:t,collisions:n,delta:{x:i.x,y:i.y},over:s};(0,ot.unstable_batchedUpdates)(()=>{be(s),a?.(c),f({type:`onDragOver`,event:c})})},[ve]),kn(()=>{L.current={activatorEvent:D,active:C,activeNode:F,collisionRect:_e,collisions:V,droppableRects:M,draggableNodes:v,draggingNode:oe,draggingNodeRect:se,droppableContainers:b,over:ye,scrollableAncestors:de,scrollAdjustedTranslate:B},S.current={initial:se,translated:_e}},[C,F,V,_e,v,oe,se,M,b,ye,de,B]),mi({...I,delta:y,draggingRect:_e,pointerCoordinates:pe,scrollableAncestors:de,scrollableAncestorRects:fe});let Te=(0,W.useMemo)(()=>({active:C,activeNode:F,activeNodeRect:re,activatorEvent:D,collisions:V,containerNodeRect:ie,dragOverlay:R,draggableNodes:v,droppableContainers:b,droppableRects:M,over:ye,measureDroppableContainers:N,scrollableAncestors:de,scrollableAncestorRects:fe,measuringConfiguration:j,measuringScheduled:P,windowRect:ue}),[C,F,re,D,V,ie,R,v,b,M,ye,N,de,fe,j,P,ue]),Ee=(0,W.useMemo)(()=>({activatorEvent:D,activators:we,active:C,activeNodeRect:re,ariaDescribedById:{draggable:ee},dispatch:d,draggableNodes:v,over:ye,measureDroppableContainers:N}),[D,we,C,re,d,ee,v,ye,N]);return W.createElement(Qn.Provider,{value:p},W.createElement(qi.Provider,{value:Ee},W.createElement(Ji.Provider,{value:Te},W.createElement(ta.Provider,{value:xe},i)),W.createElement(Zi,{disabled:n?.restoreFocus===!1})),W.createElement(rr,{...n,hiddenTextDescribedById:ee}));function De(){let e=T?.autoScrollEnabled===!1,t=typeof r==`object`?r.enabled===!1:r===!1,n=g&&!e&&!t;return typeof r==`object`?{...r,enabled:n}:{enabled:n}}}),ia=(0,W.createContext)(null),aa=`button`,oa=`Draggable`;function sa(e){let{id:t,data:n,disabled:r=!1,attributes:i}=e,a=Ln(oa),{activators:o,activatorEvent:s,active:c,activeNodeRect:l,ariaDescribedById:u,draggableNodes:d,over:f}=(0,W.useContext)(qi),{role:p=aa,roleDescription:m=`draggable`,tabIndex:h=0}=i??{},g=c?.id===t,_=(0,W.useContext)(g?ta:ia),[v,y]=Pn(),[b,x]=Pn(),S=Fi(o,t),C=Mn(n);return kn(()=>(d.set(t,{id:t,key:a,node:v,activatorNode:b,data:C}),()=>{let e=d.get(t);e&&e.key===a&&d.delete(t)}),[d,t]),{active:c,activatorEvent:s,activeNodeRect:l,attributes:(0,W.useMemo)(()=>({role:p,tabIndex:h,"aria-disabled":r,"aria-pressed":g&&p===aa?!0:void 0,"aria-roledescription":m,"aria-describedby":u.draggable}),[r,p,h,g,m,u.draggable]),isDragging:g,listeners:r?void 0:S,node:v,over:f,setNodeRef:y,setActivatorNodeRef:x,transform:_}}function ca(){return(0,W.useContext)(Ji)}var la=`Droppable`,ua={timeout:25};function da(e){let{data:t,disabled:n=!1,id:r,resizeObserverConfig:i}=e,a=Ln(la),{active:o,dispatch:s,over:c,measureDroppableContainers:l}=(0,W.useContext)(qi),u=(0,W.useRef)({disabled:n}),d=(0,W.useRef)(!1),f=(0,W.useRef)(null),p=(0,W.useRef)(null),{disabled:m,updateMeasurementsFor:h,timeout:g}={...ua,...i},_=Mn(h??r),v=Ei({callback:(0,W.useCallback)(()=>{if(!d.current){d.current=!0;return}p.current!=null&&clearTimeout(p.current),p.current=setTimeout(()=>{l(Array.isArray(_.current)?_.current:[_.current]),p.current=null},g)},[g]),disabled:m||!o}),[y,b]=Pn((0,W.useCallback)((e,t)=>{v&&(t&&(v.unobserve(t),d.current=!1),e&&v.observe(e))},[v])),x=Mn(t);return(0,W.useEffect)(()=>{!v||!y.current||(v.disconnect(),d.current=!1,v.observe(y.current))},[y,v]),(0,W.useEffect)(()=>(s({type:ir.RegisterDroppable,element:{id:r,key:a,disabled:n,node:y,rect:f,data:x}}),()=>s({type:ir.UnregisterDroppable,key:a,id:r})),[r]),(0,W.useEffect)(()=>{n!==u.current.disabled&&(s({type:ir.SetDroppableDisabled,id:r,key:a,disabled:n}),u.current.disabled=n)},[r,a,n,s]),{active:o,rect:f,isOver:c?.id===r,node:y,over:c,setNodeRef:b}}function fa(e,t,n){let r=e.slice();return r.splice(n<0?r.length+n:n,0,r.splice(t,1)[0]),r}function pa(e,t){return e.reduce((e,n,r)=>{let i=t.get(n);return i&&(e[r]=i),e},Array(e.length))}function ma(e){return e!==null&&e>=0}function ha(e,t){if(e===t)return!0;if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function ga(e){return typeof e==`boolean`?{draggable:e,droppable:e}:e}var _a=e=>{let{rects:t,activeIndex:n,overIndex:r,index:i}=e,a=fa(t,r,n),o=t[i],s=a[i];return!s||!o?null:{x:s.left-o.left,y:s.top-o.top,scaleX:s.width/o.width,scaleY:s.height/o.height}},va={scaleX:1,scaleY:1},ya=e=>{let{activeIndex:t,activeNodeRect:n,index:r,rects:i,overIndex:a}=e,o=i[t]??n;if(!o)return null;if(r===t){let e=i[a];return e?{x:0,y:t<a?e.top+e.height-(o.top+o.height):e.top-o.top,...va}:null}let s=ba(i,r,t);return r>t&&r<=a?{x:0,y:-o.height-s,...va}:r<t&&r>=a?{x:0,y:o.height+s,...va}:{x:0,y:0,...va}};function ba(e,t,n){let r=e[t],i=e[t-1],a=e[t+1];return r?n<t?i?r.top-(i.top+i.height):a?a.top-(r.top+r.height):0:a?a.top-(r.top+r.height):i?r.top-(i.top+i.height):0:0}var xa=`Sortable`,Sa=W.createContext({activeIndex:-1,containerId:xa,disableTransforms:!1,items:[],overIndex:-1,useDragOverlay:!1,sortedRects:[],strategy:_a,disabled:{draggable:!1,droppable:!1}});function Ca(e){let{children:t,id:n,items:r,strategy:i=_a,disabled:a=!1}=e,{active:o,dragOverlay:s,droppableRects:c,over:l,measureDroppableContainers:u}=ca(),d=Ln(xa,n),f=s.rect!==null,p=(0,W.useMemo)(()=>r.map(e=>typeof e==`object`&&`id`in e?e.id:e),[r]),m=o!=null,h=o?p.indexOf(o.id):-1,g=l?p.indexOf(l.id):-1,_=(0,W.useRef)(p),v=!ha(p,_.current),y=g!==-1&&h===-1||v,b=ga(a);kn(()=>{v&&m&&u(p)},[v,p,m,u]),(0,W.useEffect)(()=>{_.current=p},[p]);let x=(0,W.useMemo)(()=>({activeIndex:h,containerId:d,disabled:b,disableTransforms:y,items:p,overIndex:g,useDragOverlay:f,sortedRects:pa(p,c),strategy:i}),[h,d,b.draggable,b.droppable,y,p,g,c,f,i]);return W.createElement(Sa.Provider,{value:x},t)}var wa=e=>{let{id:t,items:n,activeIndex:r,overIndex:i}=e;return fa(n,r,i).indexOf(t)},Ta=e=>{let{containerId:t,isSorting:n,wasDragging:r,index:i,items:a,newIndex:o,previousItems:s,previousContainerId:c,transition:l}=e;return!l||!r||s!==a&&i===o?!1:n?!0:o!==i&&t===c},Ea={duration:200,easing:`ease`},Da=`transform`,Oa=Gn.Transition.toString({property:Da,duration:0,easing:`linear`}),ka={roleDescription:`sortable`};function Aa(e){let{disabled:t,index:n,node:r,rect:i}=e,[a,o]=(0,W.useState)(null),s=(0,W.useRef)(n);return kn(()=>{if(!t&&n!==s.current&&r.current){let e=i.current;if(e){let t=wr(r.current,{ignoreTransform:!0}),n={x:e.left-t.left,y:e.top-t.top,scaleX:e.width/t.width,scaleY:e.height/t.height};(n.x||n.y)&&o(n)}}n!==s.current&&(s.current=n)},[t,n,r,i]),(0,W.useEffect)(()=>{a&&o(null)},[a]),a}function ja(e){let{animateLayoutChanges:t=Ta,attributes:n,disabled:r,data:i,getNewIndex:a=wa,id:o,strategy:s,resizeObserverConfig:c,transition:l=Ea}=e,{items:u,containerId:d,activeIndex:f,disabled:p,disableTransforms:m,sortedRects:h,overIndex:g,useDragOverlay:_,strategy:v}=(0,W.useContext)(Sa),y=Ma(r,p),b=u.indexOf(o),x=(0,W.useMemo)(()=>({sortable:{containerId:d,index:b,items:u},...i}),[d,i,b,u]),S=(0,W.useMemo)(()=>u.slice(u.indexOf(o)),[u,o]),{rect:C,node:w,isOver:T,setNodeRef:E}=da({id:o,data:x,disabled:y.droppable,resizeObserverConfig:{updateMeasurementsFor:S,...c}}),{active:D,activatorEvent:O,activeNodeRect:k,attributes:ee,setNodeRef:A,listeners:j,isDragging:M,over:N,setActivatorNodeRef:P,transform:F}=sa({id:o,data:x,attributes:{...ka,...n},disabled:y.draggable}),te=bn(E,A),I=!!D,ne=I&&!m&&ma(f)&&ma(g),re=!_&&M,ie=ne?(re&&ne?F:null)??(s??v)({rects:h,activeNodeRect:k,activeIndex:f,overIndex:g,index:b}):null,L=ma(f)&&ma(g)?a({id:o,items:u,activeIndex:f,overIndex:g}):b,ae=D?.id,R=(0,W.useRef)({activeId:ae,items:u,newIndex:L,containerId:d}),oe=u!==R.current.items,se=t({active:D,containerId:d,isDragging:M,isSorting:I,id:o,index:b,items:u,newIndex:R.current.newIndex,previousItems:R.current.items,previousContainerId:R.current.containerId,transition:l,wasDragging:R.current.activeId!=null}),ce=Aa({disabled:!se,index:b,node:w,rect:C});return(0,W.useEffect)(()=>{I&&R.current.newIndex!==L&&(R.current.newIndex=L),d!==R.current.containerId&&(R.current.containerId=d),u!==R.current.items&&(R.current.items=u)},[I,L,d,u]),(0,W.useEffect)(()=>{if(ae===R.current.activeId)return;if(ae!=null&&R.current.activeId==null){R.current.activeId=ae;return}let e=setTimeout(()=>{R.current.activeId=ae},50);return()=>clearTimeout(e)},[ae]),{active:D,activeIndex:f,attributes:ee,data:x,rect:C,index:b,newIndex:L,items:u,isOver:T,isSorting:I,isDragging:M,listeners:j,node:w,overIndex:g,over:N,setNodeRef:te,setActivatorNodeRef:P,setDroppableNodeRef:E,setDraggableNodeRef:A,transform:ce??ie,transition:le()};function le(){if(ce||oe&&R.current.newIndex===b)return Oa;if(!(re&&!Hn(O)||!l)&&(I||se))return Gn.Transition.toString({...l,property:Da})}}function Ma(e,t){return typeof e==`boolean`?{draggable:e,droppable:!1}:{draggable:e?.draggable??t.draggable,droppable:e?.droppable??t.droppable}}$.Down,$.Right,$.Up,$.Left;function Na(e,t){let n=(0,W.useRef)(null),r=(0,W.useRef)(e);(0,W.useEffect)(()=>{r.current=e},[e]);let i=(0,W.useCallback)(e=>{n.current=e},[]);return(0,W.useEffect)(()=>{let e=n.current;if(!e||!t)return;let i=new IntersectionObserver(e=>{e[0]?.isIntersecting&&r.current()},{root:null,rootMargin:`100px`,threshold:0});return i.observe(e),()=>i.disconnect()},[t]),i}var Pa=60*1e3,Fa=60*Pa,Ia=24*Fa,La=7*Ia,Ra=365*Ia,za=360,Ba=192,Va=120;function Ha(e){let t=new Date(e).getTime();if(Number.isNaN(t))return``;let n=Math.max(0,Date.now()-t);return n<Fa?q(`relativeMinuteShort`,{count:Math.max(1,Math.floor(n/Pa))}):n<Ia?q(`relativeHourShort`,{count:Math.floor(n/Fa)}):n<La?q(`relativeDayShort`,{count:Math.floor(n/Ia)}):n<Ra?q(`relativeWeekShort`,{count:Math.floor(n/La)}):q(`relativeYearShort`,{count:Math.floor(n/Ra)})}function Ua({onLoadMore:e,enabled:t}){let n=Na(e,t);return t?(0,Y.jsx)(`div`,{ref:n,className:`flex items-center justify-center py-1`,children:(0,Y.jsx)(p,{className:`size-3 animate-spin text-muted-foreground/45`})}):null}function Wa({id:e,children:t}){let{attributes:n,listeners:r,setNodeRef:i,transform:a,transition:o,isDragging:s}=ja({id:e});return(0,Y.jsx)(`div`,{ref:i,style:{transform:Gn.Transform.toString(a),transition:o},className:J(s&&`relative z-50 opacity-40`),children:t({listeners:r,attributes:n})})}var Ga=(0,W.memo)(function({sidebarOpen:e,variant:t=`desktop`,scheduledTasksActive:n,agentProfilesActive:i,pluginsActive:c,projectsCollapsed:u,conversationsCollapsed:f,projects:g,expandedProjectIds:y,activeProject:S,currentSessionId:T,globalSessions:E,sessionsForProject:D,globalHasMore:k,globalLoading:ee,onLoadMoreGlobal:j,projectHasMore:N,projectLoading:F,projectLoaded:te,onLoadMoreProject:I,sessionTaskStatus:ie,selectingProject:L,onToggleProjectsCollapsed:R,onToggleConversationsCollapsed:oe,onToggleProjectExpanded:ce,onToggleAllProjectsExpanded:le,onReorderProjects:ue,onSelectProjectDirectory:de,onStartNewProjectChat:fe,onOpenGlobalSkills:z,onOpenMcpServers:pe,onOpenProjectSkills:me,onOpenProjectInExplorer:he,onDeleteProject:ge,onLoadSession:B,onTogglePinSession:_e,onRenameSession:V,onDeleteSession:ve,onStartNewGlobalChat:ye,onOpenScheduledTasks:be,onOpenAgentProfiles:xe,onOpenPlugins:Se,onOpenSettings:Ce,onToggleSidebar:we,currentSessionHoverInfo:Te}){let Ee=`mb-1 flex w-full items-center gap-1 rounded-lg px-2 py-1 text-sm font-medium leading-5 text-muted-foreground/72 transition-colors hover:bg-[color-mix(in_oklab,var(--muted)_52%,transparent)]`,De=`flex min-w-0 flex-1 items-center gap-1 text-left transition-colors hover:text-foreground/80`,Oe=`size-4 shrink-0 transition-transform duration-200 ease-out motion-reduce:transition-none`,ke=`grid transition-[grid-template-rows,opacity] duration-200 ease-out motion-reduce:transition-none`,Ae=`grid-rows-[1fr] opacity-100`,H=`pointer-events-none grid-rows-[0fr] opacity-0`,U=`min-h-0 overflow-hidden`,je=`hover:shadow-[0_8px_18px_-14px_rgb(15_23_42_/_0.5)]`,G=`group relative flex items-center gap-2 overflow-hidden rounded-lg px-2 py-1.5 text-left transition-all duration-160 ease-out hover:-translate-y-px active:translate-y-0 hover:shadow-[0_10px_26px_-18px_rgb(15_23_42_/_0.48)]`,Me=`bg-[color-mix(in_oklab,var(--muted)_70%,transparent)] text-foreground/92 shadow-[0_10px_26px_-20px_rgb(15_23_42_/_0.36)]`,Ne=`text-muted-foreground/72 hover:bg-[color-mix(in_oklab,var(--muted)_52%,transparent)] hover:text-foreground/86`,Pe=`text-muted-foreground/76 hover:bg-[color-mix(in_oklab,var(--muted)_52%,transparent)] hover:text-foreground/90`,Fe=`inline-flex size-6 shrink-0 items-center justify-center rounded-full text-muted-foreground/55 transition-colors group-hover:text-foreground/70`,Ie=`size-7 shrink-0 rounded-full text-muted-foreground/55 transition-all duration-160 ease-out hover:-translate-y-px hover:bg-[color-mix(in_oklab,var(--muted)_52%,transparent)] hover:text-foreground/85 active:translate-y-0 ${je}`,Le=`pointer-events-none absolute inset-y-0 right-1 flex items-center gap-px rounded-r-lg bg-gradient-to-l from-background via-background/95 to-transparent pl-4 opacity-0 transition-opacity duration-160 group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100`,Re=`size-6 shrink-0 rounded-full text-muted-foreground/55 transition-all duration-160 ease-out hover:-translate-y-px hover:bg-[color-mix(in_oklab,var(--muted)_52%,transparent)] hover:text-foreground/85 active:translate-y-0 ${je}`,ze=`size-6 shrink-0 rounded-full text-muted-foreground/55 transition-all duration-160 ease-out hover:-translate-y-px hover:bg-destructive/14 hover:text-destructive/90 active:translate-y-0 ${je}`,K=`truncate text-sm leading-5`,Be=`flex min-w-0 flex-1 items-center gap-2 text-left`,Ve=`flex min-w-0 flex-1 items-center gap-1 truncate transition-[padding] duration-160 group-hover:pr-14 group-focus-within:pr-14`,He=`relative z-10 inline-flex size-5 shrink-0 items-center justify-center rounded-full text-muted-foreground/55 transition-opacity duration-160 transition-colors hover:bg-[color-mix(in_oklab,var(--muted)_52%,transparent)] hover:text-foreground/85`,Ue=`group-hover:opacity-0 group-focus-within:opacity-0`,We=`font-medium text-foreground/92`,Ge=`shrink-0 text-[11px] leading-4 text-muted-foreground/55 transition-opacity duration-160`,Ke=`mt-2 flex items-center gap-2 text-sm leading-5 text-muted-foreground/72`,qe=t===`mobile`,[Je,Ye]=(0,W.useState)(!1),[Xe,Ze]=(0,W.useState)(``),[Qe,$e]=(0,W.useState)(null),[et,tt]=(0,W.useState)(null),[nt,rt]=(0,W.useState)(null),[it,at]=(0,W.useState)(null),[st,ct]=(0,W.useState)(null),[lt,Z]=(0,W.useState)(null),[ut,dt]=(0,W.useState)(null),[ft,pt]=(0,W.useState)(null),mt=(0,W.useRef)(null),ht=(0,W.useRef)(null),gt=sr(or(oi,{activationConstraint:{distance:6}})),_t=(0,W.useCallback)(e=>({...e.transform,x:0}),[]),vt=(0,W.useMemo)(()=>g.map(e=>e.id),[g]),yt=(0,W.useMemo)(()=>g.find(e=>e.id===Qe),[Qe,g]),bt=(0,W.useCallback)(e=>{let{active:t,over:n}=e;if(!n||t.id===n.id)return;let r=vt.indexOf(t.id),i=vt.indexOf(n.id);if(r===-1||i===-1)return;let a=[...vt];a.splice(r,1),a.splice(i,0,t.id),ue(a)},[vt,ue]),xt=(0,W.useRef)(null),St=(0,W.useMemo)(()=>{let e=g.flatMap(e=>D(e.id).map(t=>({session:t,projectName:e.name}))),t=E.map(e=>({session:e,projectName:``})),n=new Set;return[...e,...t].filter(({session:e})=>n.has(e.id)?!1:(n.add(e.id),!0))},[E,g,D]),Ct=Xe.trim()?St.filter(({session:e,projectName:t})=>`${_n(e.title)} ${t}`.toLowerCase().includes(Xe.trim().toLowerCase())).slice(0,8):[],wt=()=>{Ye(!0),window.setTimeout(()=>xt.current?.focus(),0)},Tt=e=>{B(e),Ye(!1),Ze(``)},Et=(e,t)=>{if(qe)return;let n=e.currentTarget.getBoundingClientRect();pt({sessionId:t,x:Math.max(8,Math.min(n.right+8,window.innerWidth-392)),y:n.top+n.height/2})},Dt=e=>{pt(t=>t?.sessionId===e?null:t)},Ot=(e,t)=>{e.stopPropagation();let n=e.currentTarget.getBoundingClientRect();rt(null),$e(e=>e===t?(tt(null),null):(tt({x:Math.max(8,Math.min(n.right-Ba,window.innerWidth-Ba-8)),y:Math.max(8,Math.min(n.bottom+4,window.innerHeight-Va-8))}),t))},kt=(0,W.useCallback)(()=>{$e(null),tt(null),rt(null)},[]),At=(e,t)=>{e.stopPropagation(),rt(t)},jt=(e,t)=>{e.stopPropagation(),$e(null),tt(null),at(t),ht.current!==null&&window.clearTimeout(ht.current),ht.current=window.setTimeout(()=>{ht.current=null,rt(e=>e===t?null:e),Promise.resolve(ge(t)).catch(()=>{at(e=>e===t?null:e)})},za)},Mt=(e,t)=>{e.currentTarget.blur(),ct(t),_e(t)},Nt=(e,t)=>{e.stopPropagation(),e.currentTarget.blur(),Z(t)},Pt=(e,t)=>{e.stopPropagation(),dt(t),Dt(t),mt.current!==null&&window.clearTimeout(mt.current),mt.current=window.setTimeout(()=>{mt.current=null,Z(e=>e===t?null:e),Promise.resolve(ve(t)).catch(()=>{dt(e=>e===t?null:e)})},za)};return(0,W.useEffect)(()=>()=>{mt.current!==null&&window.clearTimeout(mt.current),ht.current!==null&&window.clearTimeout(ht.current)},[]),(0,W.useEffect)(()=>{if(Qe)return window.addEventListener(`click`,kt),window.addEventListener(`blur`,kt),window.addEventListener(`resize`,kt),()=>{window.removeEventListener(`click`,kt),window.removeEventListener(`blur`,kt),window.removeEventListener(`resize`,kt)}},[Qe,kt]),(0,Y.jsxs)(`aside`,{className:J(`relative z-10 min-h-0 shrink-0 overflow-hidden border-r border-border bg-background transition-[width] duration-200 ease-out motion-reduce:transition-none`,qe?`flex h-full flex-col w-80 max-w-[85vw]`:`hidden md:flex md:flex-col`,e?`w-80`:`w-14`),children:[(0,Y.jsxs)(`div`,{className:`shrink-0 px-3 pt-3 pb-1`,children:[(0,Y.jsxs)(`button`,{type:`button`,className:J(G,`w-full`,Ne),onClick:we,"aria-label":q(`toggleSidebar`),children:[(0,Y.jsxs)(`span`,{className:J(Fe,`relative`),children:[(0,Y.jsx)(ne,{className:J(`size-4 transition-opacity duration-160`,!e&&`group-hover:opacity-0`)}),e?null:(0,Y.jsx)(o,{className:`absolute size-4 opacity-0 transition-opacity duration-160 group-hover:opacity-100`})]}),(0,Y.jsx)(`span`,{className:J(`ml-auto inline-flex size-6 items-center justify-center text-muted-foreground/55 transition-opacity duration-100 group-hover:text-foreground/70`,!e&&`opacity-0`),children:(0,Y.jsx)(a,{className:`size-4`})})]}),(0,Y.jsxs)(`button`,{type:`button`,className:J(G,`mt-4 w-full`,Ne),onClick:wt,"aria-label":q(`search`),children:[(0,Y.jsx)(`span`,{className:Fe,children:(0,Y.jsx)(A,{className:`size-4`})}),e?(0,Y.jsx)(`span`,{className:K,children:q(`search`)}):null]}),(0,Y.jsxs)(`button`,{type:`button`,className:J(G,`w-full`,Ne),onClick:z,"aria-label":q(`manageGlobalSkills`),title:q(`manageGlobalSkills`),children:[(0,Y.jsx)(`span`,{className:Fe,children:(0,Y.jsx)(_,{className:`size-4`})}),e?(0,Y.jsx)(`span`,{className:K,children:q(`skills`)}):null]}),(0,Y.jsxs)(`button`,{type:`button`,className:J(G,`w-full`,Ne),onClick:pe,"aria-label":q(`manageMcpServers`),title:q(`manageMcpServers`),children:[(0,Y.jsx)(`span`,{className:Fe,children:(0,Y.jsx)(se,{className:`size-4`})}),e?(0,Y.jsx)(`span`,{className:K,children:q(`mcp`)}):null]}),(0,Y.jsxs)(`button`,{type:`button`,className:J(G,`w-full`,n?Me:Ne),onClick:be,"aria-label":q(`scheduledTasksLabel`),children:[(0,Y.jsx)(`span`,{className:Fe,children:(0,Y.jsx)(P,{className:`size-4`})}),e?(0,Y.jsx)(`span`,{className:J(K,n&&We),children:q(`scheduledTasksLabel`)}):null]}),(0,Y.jsxs)(`button`,{type:`button`,className:J(G,`w-full`,i?Me:Ne),onClick:xe,"aria-label":q(`agentsTab`),title:q(`agentsTab`),children:[(0,Y.jsx)(`span`,{className:Fe,children:(0,Y.jsx)(x,{className:`size-4`})}),e?(0,Y.jsx)(`span`,{className:J(K,i&&We),children:q(`agentsTab`)}):null]}),(0,Y.jsxs)(`button`,{type:`button`,className:J(G,`w-full`,c?Me:Ne),onClick:Se,"aria-label":q(`plugins`),title:q(`plugins`),children:[(0,Y.jsx)(`span`,{className:Fe,children:(0,Y.jsx)(_,{className:`size-4`})}),e?(0,Y.jsx)(`span`,{className:J(K,c&&We),children:q(`plugins`)}):null]})]}),e?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`div`,{className:`shrink-0 px-3 max-h-[55%] flex flex-col min-h-0 overflow-hidden`,children:(0,Y.jsxs)(`div`,{className:`shrink-0 mb-0.5`,children:[(0,Y.jsxs)(`div`,{className:Ee,children:[(0,Y.jsxs)(`button`,{type:`button`,className:De,onClick:R,"aria-expanded":!u,children:[(0,Y.jsx)(M,{className:J(Oe,!u&&`rotate-90`)}),(0,Y.jsx)(`span`,{className:`flex-1 truncate`,children:q(`projects`)})]}),g.length>0&&(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:Ie,onClick:le,"aria-label":y.size===g.length?q(`collapseAllProjects`):q(`expandAllProjects`),children:y.size===g.length?(0,Y.jsx)(re,{className:`size-4`}):(0,Y.jsx)(C,{className:`size-4`})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:Ie,onClick:de,disabled:L,"aria-label":q(`addProject`),children:(0,Y.jsx)(ae,{className:`size-4`})})]}),(0,Y.jsx)(`div`,{className:J(ke,`flex-1 min-h-0`,u?H:Ae),children:(0,Y.jsx)(`div`,{className:U,children:(0,Y.jsx)(`div`,{className:`h-full overflow-y-auto`,children:(0,Y.jsx)(`div`,{className:`space-y-0.5`,children:g.length===0?(0,Y.jsx)(`div`,{className:`px-3 py-3 text-xs text-muted-foreground/55`,children:q(`noProjects`)}):(0,Y.jsx)(ra,{sensors:gt,collisionDetection:mr,onDragEnd:bt,modifiers:[_t],children:(0,Y.jsx)(Ca,{items:vt,strategy:ya,children:g.map(e=>{let t=D(e.id),n=y.has(e.id),i=S?.id===e.id,a=te(e.id),o=Qe===e.id,c=it===e.id;return(0,Y.jsx)(Wa,{id:e.id,children:({listeners:l,attributes:u})=>(0,Y.jsx)(`div`,{className:J(`grid transition-[grid-template-rows,opacity,transform] duration-[360ms] ease-[cubic-bezier(0.2,0,0,1)] motion-reduce:transition-none`,c?`grid-rows-[0fr] -translate-x-1 opacity-0`:`grid-rows-[1fr] translate-x-0 opacity-100`),children:(0,Y.jsxs)(`div`,{className:`min-h-0 overflow-hidden`,children:[(0,Y.jsxs)(`div`,{className:J(G,i?`text-foreground/84 hover:bg-[color-mix(in_oklab,var(--muted)_52%,transparent)]`:Ne,o&&`z-20 overflow-visible`,c&&`pointer-events-none scale-[0.98] opacity-0 duration-[360ms] ease-[cubic-bezier(0.2,0,0,1)] motion-reduce:transition-none`),style:{touchAction:`none`},...l,...u,children:[(0,Y.jsx)(`button`,{type:`button`,className:Fe,onClick:()=>ce(e.id),"aria-label":q(n?`collapseProject`:`expandProject`),children:n?(0,Y.jsx)(r,{className:`size-4`}):(0,Y.jsx)(m,{className:`size-4`})}),(0,Y.jsx)(`button`,{className:`flex min-w-0 flex-1 items-center text-left`,type:`button`,title:e.path,onClick:()=>ce(e.id),children:(0,Y.jsx)(`span`,{className:J(K,i&&`font-medium text-foreground/84`),children:e.name})}),(0,Y.jsxs)(`div`,{className:Le,children:[(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:Re,onClick:t=>Ot(t,e.id),"aria-label":q(`moreOptions`),"aria-expanded":o,children:(0,Y.jsx)(s,{className:`size-4`})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:Re,onClick:()=>fe(e),"aria-label":q(`newProjectChat`),children:(0,Y.jsx)(O,{className:`size-4`})})]})]}),(0,Y.jsx)(`div`,{className:J(ke,n?Ae:H),children:(0,Y.jsx)(`div`,{className:U,children:(0,Y.jsx)(`div`,{className:`mt-0.5 space-y-0.5 pl-8 max-h-[35vh] overflow-y-auto`,children:t.length===0&&!a||t.length===0&&F(e.id)?(0,Y.jsxs)(`div`,{className:`flex items-center px-2 py-1.5 text-xs text-muted-foreground/55`,children:[(0,Y.jsx)(p,{className:`mr-1.5 size-3 animate-spin`}),q(`loadingChatWorkspace`)]}):t.length===0&&!N(e.id)?(0,Y.jsx)(`div`,{className:`px-2 py-1.5 text-xs text-muted-foreground/55`,children:q(`noConversations`)}):(0,Y.jsxs)(Y.Fragment,{children:[t.map(e=>{let t=T===e.id,n=st===e.id,r=ut===e.id;return(0,Y.jsx)(`div`,{className:J(`grid transition-[grid-template-rows,opacity,transform] duration-[360ms] ease-[cubic-bezier(0.2,0,0,1)] motion-reduce:transition-none`,r?`grid-rows-[0fr] -translate-x-1 opacity-0`:`grid-rows-[1fr] translate-x-0 opacity-100`),children:(0,Y.jsx)(`div`,{className:`min-h-0 overflow-hidden`,children:(0,Y.jsxs)(`div`,{className:J(G,`gap-1`,t?Me:Pe,r&&`pointer-events-none scale-[0.98] opacity-0 duration-[360ms] ease-[cubic-bezier(0.2,0,0,1)] motion-reduce:transition-none`),onMouseEnter:t=>Et(t,e.id),onMouseLeave:()=>{ct(t=>t===e.id?null:t),r||Z(t=>t===e.id?null:t),Dt(e.id)},children:[(0,Y.jsxs)(`button`,{className:Be,type:`button`,onClick:()=>B(e.id),children:[(0,Y.jsxs)(`div`,{className:Ve,children:[ie(e)===`running`?(0,Y.jsx)(`span`,{className:`size-1.5 shrink-0 rounded-full bg-emerald-500`}):null,(0,Y.jsx)(`span`,{className:J(K,t&&We),children:_n(e.title)})]}),e.pinnedAt?(0,Y.jsx)(`button`,{type:`button`,className:J(He,!n&&Ue),onClick:t=>{t.stopPropagation(),_e(e.id)},"aria-label":q(`unpinSession`),title:q(`unpinSession`),children:(0,Y.jsx)(b,{className:`size-3`})}):null,(0,Y.jsx)(`span`,{className:J(Ge,!n&&Ue),children:Ha(e.lastModified)})]}),(0,Y.jsx)(`div`,{className:J(Le,n&&`hidden`),children:lt===e.id?(0,Y.jsx)(X,{variant:`destructive`,size:`sm`,className:`h-6 rounded-full px-2 text-xs`,onClick:t=>Pt(t,e.id),"aria-label":q(`confirmDelete`),title:q(`confirmDelete`),children:q(`confirm`)}):(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:Re,onClick:t=>Mt(t,e.id),"aria-label":e.pinnedAt?q(`unpinSession`):q(`pinSession`),children:(0,Y.jsx)(b,{className:`size-3.5`})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:Re,onClick:()=>V(e.id,e.title),"aria-label":q(`renameSession`),children:(0,Y.jsx)(h,{className:`size-3.5`})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:ze,onClick:t=>Nt(t,e.id),"aria-label":q(`deleteSession`),children:(0,Y.jsx)(v,{className:`size-3.5`})})]})})]})})},e.id)}),(0,Y.jsx)(Ua,{onLoadMore:()=>I(e.id),enabled:N(e.id)&&!F(e.id)})]})})})})]})})},e.id)})})})})})})})]})}),(0,Y.jsxs)(`div`,{className:`flex-1 min-h-0 flex flex-col px-3 pb-3`,children:[(0,Y.jsxs)(`div`,{className:Ee,children:[(0,Y.jsxs)(`button`,{type:`button`,className:De,onClick:oe,"aria-expanded":!f,children:[(0,Y.jsx)(M,{className:J(Oe,!f&&`rotate-90`)}),(0,Y.jsx)(`span`,{className:`flex-1 truncate`,children:q(`conversations`)})]}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:Ie,onClick:ye,"aria-label":q(`newChat`),children:(0,Y.jsx)(O,{className:`size-4`})})]}),(0,Y.jsx)(`div`,{className:J(ke,`flex-1 min-h-0`,f?H:Ae),children:(0,Y.jsx)(`div`,{className:U,children:(0,Y.jsx)(`div`,{className:`h-full overflow-y-auto`,children:E.length===0&&!k?(0,Y.jsx)(`div`,{className:`px-3 py-3 text-xs text-muted-foreground/55`,children:q(`noSavedConversations`)}):(0,Y.jsxs)(`div`,{className:`space-y-0.5`,children:[E.map(e=>{let t=T===e.id,n=st===e.id,r=ut===e.id;return(0,Y.jsx)(`div`,{className:J(`grid transition-[grid-template-rows,opacity,transform] duration-[360ms] ease-[cubic-bezier(0.2,0,0,1)] motion-reduce:transition-none`,r?`grid-rows-[0fr] -translate-x-1 opacity-0`:`grid-rows-[1fr] translate-x-0 opacity-100`),children:(0,Y.jsx)(`div`,{className:`min-h-0 overflow-hidden`,children:(0,Y.jsxs)(`div`,{className:J(G,t?Me:Pe,r&&`pointer-events-none scale-[0.98] opacity-0 duration-[360ms] ease-[cubic-bezier(0.2,0,0,1)] motion-reduce:transition-none`),onMouseEnter:t=>Et(t,e.id),onMouseLeave:()=>{ct(t=>t===e.id?null:t),r||Z(t=>t===e.id?null:t),Dt(e.id)},children:[(0,Y.jsxs)(`button`,{className:Be,type:`button`,onClick:()=>B(e.id),children:[(0,Y.jsxs)(`div`,{className:Ve,children:[ie(e)===`running`?(0,Y.jsx)(`span`,{className:`size-1.5 shrink-0 rounded-full bg-emerald-500`}):null,(0,Y.jsx)(`span`,{className:J(K,t&&We),children:_n(e.title)})]}),e.pinnedAt?(0,Y.jsx)(`button`,{type:`button`,className:J(He,!n&&Ue),onClick:t=>{t.stopPropagation(),_e(e.id)},"aria-label":q(`unpinSession`),title:q(`unpinSession`),children:(0,Y.jsx)(b,{className:`size-3`})}):null,(0,Y.jsx)(`span`,{className:J(Ge,!n&&Ue),children:Ha(e.lastModified)})]}),(0,Y.jsx)(`div`,{className:J(Le,n&&`hidden`),children:lt===e.id?(0,Y.jsx)(X,{variant:`destructive`,size:`sm`,className:`h-6 rounded-full px-2 text-xs`,onClick:t=>Pt(t,e.id),"aria-label":q(`confirmDelete`),title:q(`confirmDelete`),children:q(`confirm`)}):(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:Re,onClick:t=>Mt(t,e.id),"aria-label":e.pinnedAt?q(`unpinSession`):q(`pinSession`),children:(0,Y.jsx)(b,{className:`size-3.5`})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:Re,onClick:()=>V(e.id,e.title),"aria-label":q(`renameSession`),children:(0,Y.jsx)(h,{className:`size-3.5`})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:ze,onClick:t=>Nt(t,e.id),"aria-label":q(`deleteSession`),children:(0,Y.jsx)(v,{className:`size-4`})})]})})]})})},e.id)}),(0,Y.jsx)(Ua,{onLoadMore:j,enabled:k&&!ee})]})})})})]})]}):null,(0,Y.jsx)(`div`,{className:`mt-auto shrink-0 border-t border-border px-3 py-3`,children:(0,Y.jsxs)(`button`,{type:`button`,className:J(G,`w-full`,Ne),onClick:Ce,"aria-label":q(`settings`),title:q(`settings`),children:[(0,Y.jsx)(`span`,{className:Fe,children:(0,Y.jsx)(w,{className:`size-4`})}),e?(0,Y.jsx)(`span`,{className:K,children:q(`settings`)}):null]})}),ft?(()=>{let e=St.find(e=>e.session.id===ft.sessionId)?.session;if(!e)return null;let t=Te?.sessionId===e.id;return(0,Y.jsxs)(`div`,{className:`pointer-events-none fixed z-50 w-[min(24rem,calc(100vw-1rem))] max-w-sm rounded-2xl border border-border bg-card px-4 py-3 text-left shadow-xl`,style:{left:ft.x,top:ft.y,transform:`translateY(-50%)`},children:[(0,Y.jsx)(`div`,{className:`truncate text-sm font-medium leading-5 text-foreground/92`,children:_n(e.title)}),t&&Te?.gitBranch?(0,Y.jsxs)(`div`,{className:Ke,children:[(0,Y.jsx)(l,{className:`size-4 shrink-0 text-muted-foreground/60`}),(0,Y.jsx)(`span`,{className:`truncate`,children:Te.gitBranch})]}):null,t&&Te?.context?(0,Y.jsxs)(`div`,{className:Ke,title:Te.context.title,children:[(0,Y.jsx)(d,{className:`size-4 shrink-0 text-muted-foreground/60`}),(0,Y.jsx)(`span`,{className:`size-2 shrink-0 rounded-full`,style:{backgroundColor:Te.context.color}}),(0,Y.jsx)(`span`,{className:`truncate`,children:Te.context.label})]}):null]})})():null,yt&&et?(0,ot.createPortal)((0,Y.jsxs)(`div`,{className:`fixed z-50 min-w-48 overflow-hidden rounded-lg border border-border bg-background p-1 shadow-xl`,style:{left:et.x,top:et.y},onClick:e=>e.stopPropagation(),children:[(0,Y.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 whitespace-nowrap rounded-md px-2 py-1.5 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,title:q(`openInExplorer`),"aria-label":q(`openInExplorer`),onClick:()=>{kt(),he(yt)},children:[(0,Y.jsx)(r,{className:`size-4 shrink-0 text-muted-foreground/70`}),(0,Y.jsx)(`span`,{children:q(`openFolder`)})]}),(0,Y.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 whitespace-nowrap rounded-md px-2 py-1.5 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:()=>{kt(),me(yt)},children:[(0,Y.jsx)(_,{className:`size-4 shrink-0 text-muted-foreground/70`}),(0,Y.jsx)(`span`,{children:q(`manageProjectSkills`)})]}),nt===yt.id?(0,Y.jsx)(`button`,{type:`button`,className:`flex w-full items-center justify-center gap-2 whitespace-nowrap rounded-md bg-destructive px-2 py-1.5 text-left text-sm font-medium text-destructive-foreground transition-colors hover:bg-destructive/90`,"aria-label":q(`confirmDelete`),onClick:e=>jt(e,yt.id),children:(0,Y.jsx)(`span`,{children:q(`confirm`)})}):(0,Y.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 whitespace-nowrap rounded-md px-2 py-1.5 text-left text-sm text-destructive transition-colors hover:bg-destructive/10`,"aria-label":q(`deleteProject`),onClick:e=>At(e,yt.id),children:[(0,Y.jsx)(v,{className:`size-4 shrink-0`}),(0,Y.jsx)(`span`,{children:q(`deleteProject`)})]})]}),document.body):null,Je?(0,Y.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-start justify-center bg-background/50 px-4 pt-[12vh] backdrop-blur-sm`,role:`dialog`,"aria-modal":`true`,onMouseDown:()=>Ye(!1),children:(0,Y.jsxs)(`div`,{className:`w-full max-w-xl rounded-2xl border border-border bg-card p-3 shadow-xl`,onMouseDown:e=>e.stopPropagation(),children:[(0,Y.jsxs)(`div`,{className:`flex items-center gap-2 rounded-xl border border-input bg-background px-3 py-2`,children:[(0,Y.jsx)(A,{className:`size-4 shrink-0 text-muted-foreground/60`}),(0,Y.jsx)(`input`,{ref:xt,value:Xe,onChange:e=>Ze(e.target.value),onKeyDown:e=>{e.key===`Escape`&&Ye(!1)},placeholder:q(`searchDialog`),className:`min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground/45`})]}),(0,Y.jsx)(`div`,{className:`mt-2 max-h-[50vh] overflow-y-auto`,children:Xe.trim()?Ct.length>0?Ct.map(({session:e,projectName:t})=>(0,Y.jsxs)(`button`,{type:`button`,className:`block w-full rounded-xl px-3 py-2 text-left transition-colors hover:bg-muted/60`,onClick:()=>Tt(e.id),children:[(0,Y.jsx)(`div`,{className:`truncate text-sm text-foreground/90`,children:_n(e.title)}),(0,Y.jsxs)(`div`,{className:`truncate text-[11px] text-muted-foreground/55`,children:[t||q(`normalChat`),` · `,Ha(e.lastModified)]})]},e.id)):(0,Y.jsx)(`div`,{className:`px-3 py-3 text-xs text-muted-foreground/55`,children:q(`noSearchResults`)}):(0,Y.jsx)(`div`,{className:`px-3 py-3 text-xs text-muted-foreground/55`,children:q(`searchHint`)})})]})}):null]})});function Ka(){let[e,t]=(0,W.useState)(),[n,r]=(0,W.useState)([]),[i,a]=(0,W.useState)(()=>new Set),[o,s]=(0,W.useState)(!1),[c,l]=(0,W.useState)(!1);return{activeProject:e,projects:n,expandedProjectIds:i,selectingProject:o,projectPickerOpen:c,loadProject:(0,W.useCallback)(async()=>{try{let e=await fetch(`/api/project`);if(!e.ok)return;let n=await e.json();t(n.project),r(Array.isArray(n.projects)?n.projects:[]),a(e=>{let t=new Set(e);for(let e of Array.isArray(n.projects)?n.projects:[])t.add(e.id);return t})}catch(e){U.error(`Failed to load project:`,e)}},[]),switchActiveProject:(0,W.useCallback)(async e=>{let n=await fetch(`/api/project/active`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:e})}),i=await n.json().catch(()=>null);if(!n.ok)throw Error(i?.error||`Project switch failed with HTTP ${n.status}`);return t(i.project),r(Array.isArray(i.projects)?i.projects:[]),a(e=>{let t=new Set(e);for(let e of Array.isArray(i.projects)?i.projects:[])t.add(e.id);return t}),i.project},[]),handleSelectProjectPath:(0,W.useCallback)(async e=>{s(!0);try{let n=await fetch(`/api/project/path`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({path:e})}),i=await n.json().catch(()=>null);if(!n.ok)throw Error(i?.error||`Project selection failed with HTTP ${n.status}`);i?.project&&(t(i.project),r(Array.isArray(i.projects)?i.projects:[]),a(e=>{let t=new Set(e);for(let e of Array.isArray(i.projects)?i.projects:[])t.add(e.id);return t}))}catch(e){throw U.error(`Failed to select project:`,e),e}finally{s(!1)}},[]),selectProjectDirectory:(0,W.useCallback)(()=>{l(!0)},[]),setProjectPickerOpen:l,toggleProjectExpanded:(0,W.useCallback)(e=>{a(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),toggleAllProjectsExpanded:(0,W.useCallback)(()=>{a(e=>e.size===n.length&&n.length>0?new Set:new Set(n.map(e=>e.id)))},[n]),reorderProjects:(0,W.useCallback)(async e=>{r(t=>{let n=new Map(t.map(e=>[e.id,e])),r=[];for(let t of e){let e=n.get(t);e&&(r.push(e),n.delete(t))}return r});try{let t=await fetch(`/api/project/reorder`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({orderedIds:e})}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||`Reorder failed with HTTP ${t.status}`);Array.isArray(n?.projects)&&r(n.projects)}catch(e){U.error(`Failed to reorder projects:`,e)}},[]),setActiveProject:t,setProjects:r,setExpandedProjectIds:a}}function qa(){let[e,t]=(0,W.useState)(!1);return{yoloMode:e,setYoloMode:t,initialize:(0,W.useCallback)(async e=>{let n=await mn(e);return t(n),n},[])}}var Ja=`quickforge-sync`;function Ya(e){let t=(0,W.useRef)(e);(0,W.useEffect)(()=>{t.current=e});let n=(0,W.useRef)(It()),r=(0,W.useRef)(null);(0,W.useEffect)(()=>{if(typeof BroadcastChannel<`u`)try{let e=new BroadcastChannel(Ja);r.current=e;let i=e=>{let r=e.data;if(!(!r||r.sourceTabId===n.current))switch(r.type){case`sessions-changed`:t.current.onSessionsChanged();break;case`projects-changed`:t.current.onProjectsChanged();break;case`settings-changed`:t.current.onSettingsChanged();break}};return e.addEventListener(`message`,i),()=>{e.removeEventListener(`message`,i),e.close()}}catch{r.current=null}},[]),(0,W.useEffect)(()=>{let e=()=>{document.visibilityState===`visible`&&(t.current.onSessionsChanged(),t.current.onProjectsChanged())};return document.addEventListener(`visibilitychange`,e),()=>{document.removeEventListener(`visibilitychange`,e)}},[]);let i=(0,W.useCallback)(e=>{let t={type:e,sourceTabId:n.current,timestamp:Date.now()};r.current?.postMessage(t)},[]);return{notifySessionsChanged:(0,W.useCallback)(()=>i(`sessions-changed`),[i]),notifyProjectsChanged:(0,W.useCallback)(()=>i(`projects-changed`),[i]),notifySettingsChanged:(0,W.useCallback)(()=>i(`settings-changed`),[i])}}function Xa(e,t){let n=t.toolCallId;if(t.role===`toolResult`&&typeof n==`string`){let r=e.findIndex(e=>e.role===`toolResult`&&e.toolCallId===n);if(r>=0){let n=e.slice();return n[r]=t,n}}if(t.role===`assistant`){let n=t.timestamp;if(n!==void 0){let r=e.findIndex(e=>e.role===`assistant`&&e.timestamp===n);if(r>=0){let n=e.slice();return n[r]=t,n}}}let r=e.slice(),i=r.length-1;return i>=0&&r[i]?.role===t.role?r[i]=t:r.push(t),r}function Za(e){return!!(e&&typeof e==`object`&&!Array.isArray(e))}function Qa(e){if(!Za(e))return;let t=e.quickforgeTiming;if(!Za(t))return;let n=typeof t.startedAt==`number`?t.startedAt:void 0,r=typeof t.finishedAt==`number`?t.finishedAt:void 0,i=typeof t.durationMs==`number`?t.durationMs:void 0;if(!(n===void 0&&r===void 0&&i===void 0))return{startedAt:n,finishedAt:r,durationMs:i}}function $a(e,t){return Za(e)?{...e,quickforgeTiming:t}:{quickforgeTiming:t}}function eo(e,t){let n=e.quickforgeTiming??Qa(e.partialResult?.details)??{startedAt:Date.now()};return{...e,partialResult:e.partialResult??{content:[],details:{quickforgeTiming:n,sessionId:t,toolCallId:e.toolCallId}}}}function to(e,t,n){if(!t.toolCallId||!t.toolName)return e;let r=n?t.partialResult:t.result;if(!r)return e;let i=Qa(r.details)??t.quickforgeTiming;if(!i){let n=e.findIndex(e=>e.role===`toolResult`&&e.toolCallId===t.toolCallId);n>=0&&(i=Qa(e[n].details))}let a=i?$a(r.details,i):r.details,o=Za(a)?{...a,sessionId:a.sessionId??t.sessionId,toolCallId:a.toolCallId??t.toolCallId}:a;return Xa(e,{role:`toolResult`,toolCallId:t.toolCallId,toolName:t.toolName,content:r.content??[],details:o,isError:n?!1:t.isError,timestamp:Date.now()})}function no(){return``}var ro=5e3,io=15e3,ao=new class{eventSource=null;handlersBySession=new Map;baseUrl=``;reconnectTimer=null;reconnectDelay=1e3;directBaseUrl=no();fallbackBaseUrl=``;subscribe(e,t,n){this.fallbackBaseUrl=t;let r=this.directBaseUrl||this.fallbackBaseUrl;(!this.eventSource||this.baseUrl!==r)&&(this.disconnect(),this.baseUrl=r,this.connect());let i=this.handlersBySession.get(e);return i||(i=new Set,this.handlersBySession.set(e,i)),i.add(n),()=>{let t=this.handlersBySession.get(e);t?.delete(n),t?.size===0&&this.handlersBySession.delete(e),this.handlersBySession.size===0&&this.globalHandlers.size===0&&this.disconnect()}}globalHandlers=new Set;subscribeAll(e,t){this.fallbackBaseUrl=e;let n=this.directBaseUrl||this.fallbackBaseUrl;return(!this.eventSource||this.baseUrl!==n)&&(this.disconnect(),this.baseUrl=n,this.connect()),this.globalHandlers.add(t),()=>{this.globalHandlers.delete(t),this.handlersBySession.size===0&&this.globalHandlers.size===0&&this.disconnect()}}connect(){let e=`${this.baseUrl}/api/agents/events`;this.eventSource=new EventSource(e),this.eventSource.onopen=()=>{this.reconnectDelay=1e3};let t=[`state`,`agent_start`,`agent_end`,`message_start`,`message_end`,`turn_start`,`turn_end`,`message_update`,`tool_execution_start`,`tool_execution_update`,`tool_execution_end`,`error`,`title_updated`,`session_forked`,`scheduled_task_notification`,`scheduled_task_started`,`tool_approval_required`,`auto_compact_threshold_reached`,`auto_compact_approval_required`,`auto_compact_completed`,`auto_compact_failed`,`messages_replaced`],n=e=>t=>{try{let n=JSON.parse(t.data),r=n.sessionId;if(!r&&e!==`scheduled_task_notification`)return;let i=e?{type:e,...n}:n;r?this.emit(r,i):this.emitGlobal(i)}catch{}};this.eventSource.onmessage=n();for(let e of t)this.eventSource.addEventListener(e,n(e));this.eventSource.onerror=()=>{if(this.eventSource?.close(),this.eventSource=null,this.baseUrl===this.directBaseUrl&&this.fallbackBaseUrl!==this.directBaseUrl){this.baseUrl=this.fallbackBaseUrl,this.connect();return}this.scheduleReconnect()}}scheduleReconnect(){this.reconnectTimer||this.handlersBySession.size===0&&this.globalHandlers.size===0||(this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,!(this.handlersBySession.size===0&&this.globalHandlers.size===0)&&(this.reconnectDelay=Math.min(this.reconnectDelay*2,3e4),this.connect())},this.reconnectDelay))}emitGlobal(e){for(let t of this.globalHandlers)try{t(e)}catch{}}emit(e,t){this.emitGlobal(t);let n=this.handlersBySession.get(e);if(n)for(let e of n)try{e(t)}catch{}}disconnect(){this.reconnectTimer&&=(clearTimeout(this.reconnectTimer),null),this.eventSource?.close(),this.eventSource=null}};async function oo(e=``){let t=await fetch(`${e}/api/agents`,{cache:`no-store`});if(!t.ok)return[];let n=await t.json().catch(()=>null);return Array.isArray(n?.sessions)?n.sessions:[]}function so(e,t=``){return ao.subscribeAll(t,e)}var co=class e{state;streamFn=Ae;getApiKey;sessionId;listeners=new Set;unsubscribeSse;baseUrl;disposed=!1;_syncingThinkingLevel=!1;pollTimer=null;refreshPromise=null;statusPromise=null;lastSseEventAt=Date.now();lastServerStateVersion=0;nextPromptCapabilities=[];planMode=!1;onPlanModeConsumed;stateVersion=0;constructor(e){this.sessionId=e.sessionId,this.baseUrl=e.baseUrl??``;let t=e.initialState??{};this.lastServerStateVersion=typeof t.stateVersion==`number`?t.stateVersion:0;let n={systemPrompt:t.systemPrompt??``,model:t.model??null,thinkingLevel:t.thinkingLevel??`off`,messages:t.messages?.slice()??[],tools:t.tools??[],yoloMode:t.yoloMode??!1,isStreaming:t.isStreaming??!1,streamingMessage:void 0,pendingToolCalls:new Set,errorMessage:t.errorMessage,contextCompaction:t.contextCompaction??null,contextUsage:t.contextUsage??null};this.state=new Proxy(n,{set:(e,t,n)=>{let r=e[t];return e[t]=n,t===`thinkingLevel`&&!this._syncingThinkingLevel&&n!==r&&this.updateThinkingLevel(n),!0}}),this.unsubscribeSse=ao.subscribe(this.sessionId,this.baseUrl,e=>this.handleSseEvent(e)),this.state.isStreaming&&this.startStateWatchdog()}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}setNextPromptCapabilities(e){this.nextPromptCapabilities=Array.isArray(e)?e.slice(0,4):[]}setPlanMode(e,t){this.planMode=e,this.onPlanModeConsumed=e?t:void 0}async prompt(e){if(this.disposed)return;let t;t=typeof e==`string`?{role:`user`,content:e,timestamp:Date.now()}:Array.isArray(e)?[...e].reverse().find(e=>e.role===`user`||e.role===`user-with-attachments`)??e[e.length-1]:e;let n=this.nextPromptCapabilities,r=this.planMode?{type:`plan`}:void 0;if(this.nextPromptCapabilities=[],this.planMode){this.planMode=!1;let e=this.onPlanModeConsumed;this.onPlanModeConsumed=void 0,e?.()}let i=t;this.state.messages=[...this.state.messages,i],this.state.contextUsage=null,this.emitToListeners({type:`message_start`,message:i}),this.state.isStreaming||(this.state.isStreaming=!0,this.state.errorMessage=void 0,this.emitToListeners({type:`agent_start`}));let a=new AbortController,o=setTimeout(()=>a.abort(),3e4),s=this.state.messages.length,c=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/prompt`;fetch(c,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({message:i,selectedCapabilities:n,command:r}),signal:a.signal}).then(e=>{if(clearTimeout(o),!e.ok)throw Error(`Failed to send prompt: HTTP ${e.status}`)}).catch(e=>{clearTimeout(o);let t=e instanceof Error?e.message:String(e);U.error(`Failed to send prompt:`,e),this.state.messages.length===s+1&&(this.state.messages=this.state.messages.slice(0,-1)),this.state.errorMessage=t,this.state.isStreaming=!1,this.state.streamingMessage=void 0,this.stopStateWatchdog(),this.emitToListeners({type:`error`,error:t}),this.emitToListeners({type:`agent_end`,messages:this.state.messages})}),this.startStateWatchdog()}abort(){let e=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/abort`;fetch(e,{method:`POST`}).catch(e=>{U.error(`Failed to abort:`,e)})}steer(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/steer`;fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({message:e})}).catch(e=>{U.error(`Failed to send steer:`,e)})}followUp(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/follow-up`;fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({message:e})}).catch(e=>{U.error(`Failed to send follow-up:`,e)})}reset(){this.state.messages=[],this.state.errorMessage=void 0,this.state.isStreaming=!1,this.state.streamingMessage=void 0,this.state.pendingToolCalls=new Set}async updateYoloMode(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/yolo-mode`,n=await fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({yoloMode:e})});if(!n.ok){let e=await n.json().catch(()=>null);throw Error(e?.error||`Failed to sync YOLO mode: HTTP ${n.status}`)}this.state.yoloMode=e}async updateModel(e){this.state.model=e,this.state.contextUsage=null;let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/model`;fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({model:e})}).catch(e=>{U.error(`Failed to sync model update to server:`,e)})}async updateThinkingLevel(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/thinking-level`;fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({thinkingLevel:e})}).catch(e=>{U.error(`Failed to sync thinking level update to server:`,e)})}async rollback(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/rollback`,n=await fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({messageIndex:e})}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||`Failed to roll back: HTTP ${n.status}`);return r}async continue(){let e=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/continue`,t=await fetch(e,{method:`POST`});if(!t.ok){let e=await t.json().catch(()=>null);throw Error(e?.error||`Failed to continue: HTTP ${t.status}`)}this.state.isStreaming=!0,this.state.errorMessage=void 0,this.startStateWatchdog()}async approveToolCall(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/approve-tool`,n=await fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({toolCallId:e})});if(!n.ok){let e=await n.json().catch(()=>null);throw Error(e?.error||`Failed to approve tool call: HTTP ${n.status}`)}}async rejectToolCall(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/reject-tool`,n=await fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({toolCallId:e})});if(!n.ok){let e=await n.json().catch(()=>null);throw Error(e?.error||`Failed to reject tool call: HTTP ${n.status}`)}}async approveAutoCompact(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/approve-auto-compact`,n=await fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({approvalId:e})});if(!n.ok){let e=await n.json().catch(()=>null);throw Error(e?.error||`Failed to approve auto compact: HTTP ${n.status}`)}}async rejectAutoCompact(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/reject-auto-compact`,n=await fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({approvalId:e})});if(!n.ok){let e=await n.json().catch(()=>null);throw Error(e?.error||`Failed to reject auto compact: HTTP ${n.status}`)}}dispose(){this.disposed=!0,this.pollTimer&&=(clearInterval(this.pollTimer),null),this.statusPromise=null,this.unsubscribeSse?.(),this.unsubscribeSse=void 0,this.listeners.clear()}handleSseEvent(e){switch(this.noteSseEvent(e),e.type){case`state`:{let t=e;t.systemPrompt!==void 0&&(this.state.systemPrompt=t.systemPrompt),t.messages&&(t.messages.length>this.state.messages.length||!this.state.isStreaming&&t.messages.length===this.state.messages.length)&&(this.state.messages=t.messages,this.stateVersion++),t.model&&(this.state.model=t.model),t.thinkingLevel&&(this._syncingThinkingLevel=!0,this.state.thinkingLevel=t.thinkingLevel,this._syncingThinkingLevel=!1),t.yoloMode!==void 0&&(this.state.yoloMode=!!t.yoloMode),t.tools&&(this.state.tools=t.tools),t.contextCompaction!==void 0&&(this.state.contextCompaction=t.contextCompaction),t.contextUsage===void 0?t.messages&&(this.state.contextUsage=null):this.state.contextUsage=t.contextUsage;let n=this.state.isStreaming;t.isStreaming!==void 0&&(n=this.state.isStreaming,this.state.isStreaming=t.isStreaming,t.isStreaming?this.startStateWatchdog():this.stopStateWatchdog()),t.isStreaming?(this.state.errorMessage=void 0,this.emitToListeners({type:`agent_start`})):n&&(this.stateVersion++,this.emitToListeners({type:`agent_end`,messages:this.state.messages}));return}case`agent_start`:this.state.isStreaming=!0,this.state.errorMessage=void 0,this.startStateWatchdog();break;case`agent_end`:{this.stopStateWatchdog();let t=e;if(t.messages&&t.messages.length>=this.state.messages.length){this.state.messages=t.messages,this.state.contextUsage=t.contextUsage===void 0?null:t.contextUsage,this.state.isStreaming=!1,this.state.streamingMessage=void 0,t.errorMessage&&(this.state.errorMessage=t.errorMessage),this.stateVersion++,this.emitToListeners(e);return}this.refreshStateFromServer({forceMessages:!0}).finally(()=>{this.state.isStreaming=!1,this.state.streamingMessage=void 0,t.errorMessage&&(this.state.errorMessage=t.errorMessage),this.emitToListeners(e)});return}case`message_end`:{let t=e;if(t.message){this.state.messages=Xa(this.state.messages,t.message),this.state.contextUsage=t.contextUsage===void 0?null:t.contextUsage,this.stateVersion++,this.emitToListeners(e);return}if(t.messages&&t.messages.length>=this.state.messages.length){this.state.messages=t.messages,this.state.contextUsage=t.contextUsage===void 0?null:t.contextUsage,this.stateVersion++,this.emitToListeners(e);return}this.refreshStateFromServer().finally(()=>{this.emitToListeners(e)});return}case`turn_end`:{let t=e;if(t.messages&&t.messages.length>=this.state.messages.length){this.state.messages=t.messages,this.state.contextUsage=t.contextUsage===void 0?null:t.contextUsage,this.stateVersion++,this.emitToListeners(e);return}this.refreshStateFromServer().finally(()=>{this.emitToListeners(e)});return}case`messages_replaced`:{let t=e;t.messages&&(this.state.messages=t.messages,this.state.streamingMessage=void 0,this.stateVersion++),t.contextCompaction!==void 0&&(this.state.contextCompaction=t.contextCompaction),t.contextUsage===void 0?t.messages&&(this.state.contextUsage=null):this.state.contextUsage=t.contextUsage;break}case`error`:{this.stopStateWatchdog();let t=e.error;this.state.errorMessage=t||`Unknown error`,this.state.isStreaming=!1;break}case`title_updated`:break;case`session_forked`:break;case`tool_execution_start`:{let t=e;t.toolCallId&&(this.state.messages=to(this.state.messages,eo(t,this.sessionId),!0),this.state.pendingToolCalls=new Set([...this.state.pendingToolCalls,t.toolCallId]),this.stateVersion++);break}case`tool_execution_update`:{let t=e;this.state.messages=to(this.state.messages,t,!0),t.toolCallId&&(this.state.pendingToolCalls=new Set([...this.state.pendingToolCalls,t.toolCallId])),this.stateVersion++;break}case`tool_execution_end`:{let t=e;if(this.state.messages=to(this.state.messages,t,!1),t.toolCallId){let e=new Set(this.state.pendingToolCalls);e.delete(t.toolCallId),this.state.pendingToolCalls=e}this.stateVersion++;break}case`auto_compact_completed`:{let t=e;t.contextCompaction!==void 0&&(this.state.contextCompaction=t.contextCompaction),t.contextUsage!==void 0&&(this.state.contextUsage=t.contextUsage);break}case`auto_compact_failed`:case`message_start`:case`message_update`:case`turn_start`:case`tool_approval_required`:case`auto_compact_threshold_reached`:case`auto_compact_approval_required`:break}this.emitToListeners(e)}emitToListeners(e){for(let t of this.listeners)try{t(e)}catch{}}noteSseEvent(e){this.lastSseEventAt=Date.now();let t=e.stateVersion;typeof t==`number`&&Number.isFinite(t)&&(this.lastServerStateVersion=Math.max(this.lastServerStateVersion,t))}startStateWatchdog(){this.pollTimer||this.disposed||(this.lastSseEventAt=Date.now(),this.pollTimer=setInterval(()=>{if(this.disposed||!this.state.isStreaming){this.stopStateWatchdog();return}Date.now()-this.lastSseEventAt<io||this.refreshStatusFromServer()},ro))}stopStateWatchdog(){this.pollTimer&&=(clearInterval(this.pollTimer),null)}async refreshStatusFromServer(){return this.statusPromise||=this._doRefreshStatusFromServer().finally(()=>{this.statusPromise=null}),this.statusPromise}async _doRefreshStatusFromServer(){let e=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/status`;try{let t=await fetch(e);if(!t.ok){t.status===404&&this.state.isStreaming&&(this.state.isStreaming=!1,this.stopStateWatchdog(),this.emitToListeners({type:`agent_end`,messages:this.state.messages}));return}let n=await t.json();this.lastSseEventAt=Date.now();let r=typeof n.stateVersion==`number`&&Number.isFinite(n.stateVersion)?n.stateVersion:this.lastServerStateVersion;if(n.isStreaming===!1){this.stopStateWatchdog(),await this.refreshStateFromServer({notify:!0,forceMessages:!0});return}n.isStreaming===!0&&(this.state.isStreaming=!0,this.state.errorMessage=n.errorMessage),r>this.lastServerStateVersion&&await this.refreshStateFromServer({notify:!0,forceMessages:!0})}catch{}}async refreshStateFromServer(e){return this.refreshPromise||=this._doRefreshStateFromServer(e).finally(()=>{this.refreshPromise=null}),this.refreshPromise}async _doRefreshStateFromServer(e){let t=`${this.baseUrl}/api/agents/${encodeURIComponent(this.sessionId)}/state`;try{let n=this.stateVersion,r=await fetch(t);if(!r.ok){r.status===404&&this.state.isStreaming&&(this.state.isStreaming=!1,this.stopStateWatchdog(),this.emitToListeners({type:`agent_end`,messages:this.state.messages}));return}let i=await r.json();if(typeof i.stateVersion==`number`&&Number.isFinite(i.stateVersion)&&(this.lastServerStateVersion=Math.max(this.lastServerStateVersion,i.stateVersion)),!e?.forceMessages&&n!==this.stateVersion)return;let a=!!(i.messages&&(e?.forceMessages||i.messages.length>this.state.messages.length||!this.state.isStreaming&&i.messages.length===this.state.messages.length));if(a&&(this.state.messages=i.messages,this.state.contextUsage=i.contextUsage===void 0?null:i.contextUsage,this.stateVersion++),i.systemPrompt!==void 0&&(this.state.systemPrompt=i.systemPrompt),i.model&&(this.state.model=i.model),i.thinkingLevel&&(this._syncingThinkingLevel=!0,this.state.thinkingLevel=i.thinkingLevel,this._syncingThinkingLevel=!1),i.yoloMode!==void 0&&(this.state.yoloMode=!!i.yoloMode),i.tools&&(this.state.tools=i.tools),i.contextCompaction!==void 0&&(this.state.contextCompaction=i.contextCompaction),i.contextUsage!==void 0&&(this.state.contextUsage=i.contextUsage),i.isStreaming!==void 0){let t=this.state.isStreaming;if(this.state.isStreaming=!!i.isStreaming,i.isStreaming?(this.state.errorMessage=void 0,t||this.emitToListeners({type:`agent_start`})):this.stopStateWatchdog(),e?.notify&&t&&!i.isStreaming){this.stateVersion++,this.emitToListeners({type:`agent_end`,messages:this.state.messages});return}}if(e?.notify)if(i.isStreaming&&a){let e=this.state.messages[this.state.messages.length-1];e&&this.emitToListeners({type:`message_update`,message:e})}else i.isStreaming||this.emitToListeners({type:`message_end`})}catch{}}static async create(t,n={}){let r=n.baseUrl??``,i=await fetch(`${r}/api/agents/${encodeURIComponent(t)}`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({scope:n.scope??`global`,projectId:n.projectId,yoloMode:n.yoloMode??!1,model:n.model,thinkingLevel:n.thinkingLevel??`off`,messages:n.messages??[],title:n.title??`New chat`,contextCompaction:n.contextCompaction})});if(!i.ok){let e=await i.json().catch(()=>({error:`Failed to create agent`}));throw Error(e.error||`Failed to create agent`)}let a={};try{let e=await fetch(`${r}/api/agents/${encodeURIComponent(t)}/state`);e.ok&&(a=await e.json())}catch{}return new e({sessionId:t,baseUrl:r,initialState:{systemPrompt:a.systemPrompt??``,model:a.model??n.model??null,thinkingLevel:a.thinkingLevel??n.thinkingLevel??`off`,messages:a.messages??n.messages??[],tools:a.tools??[],yoloMode:!!(a.yoloMode??n.yoloMode),isStreaming:!!a.isStreaming,errorMessage:a.errorMessage,contextCompaction:a.contextCompaction,contextUsage:a.contextUsage,stateVersion:a.stateVersion}})}},lo=class{sessionId;streamFn=Ae;getApiKey;scope;project;createAgent;listeners=new Set;disposed=!1;realAgentPromise;promotedAgent;nextPromptCapabilities=[];planMode=!1;onPlanModeConsumed;state;constructor(e){this.sessionId=`pending-${It()}`,this.scope=e.scope,this.project=e.project,this.createAgent=e.createAgent,this.state={systemPrompt:``,model:e.model,thinkingLevel:e.thinkingLevel,messages:[],tools:[],yoloMode:e.yoloMode,isStreaming:!1,pendingToolCalls:new Set,contextCompaction:null,contextUsage:null}}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}setNextPromptCapabilities(e){this.nextPromptCapabilities=Array.isArray(e)?e.slice(0,4):[]}setPlanMode(e,t){this.planMode=e,this.onPlanModeConsumed=e?t:void 0}async prompt(e){if(this.disposed)return;let t=await this.ensureRealAgent();t.setNextPromptCapabilities(this.nextPromptCapabilities),t.setPlanMode(this.planMode,this.onPlanModeConsumed),this.nextPromptCapabilities=[],this.planMode=!1,this.onPlanModeConsumed=void 0,await t.prompt(e)}abort(){this.realAgentPromise?.then(e=>e.abort())}reset(){this.state.messages=[],this.state.isStreaming=!1,this.state.streamingMessage=void 0,this.state.pendingToolCalls=new Set,this.state.errorMessage=void 0}async rollback(){throw Error(`Cannot roll back a pending chat`)}async continue(){await(await this.ensureRealAgent()).continue()}async approveToolCall(){throw Error(`No pending tool call`)}async rejectToolCall(){throw Error(`No pending tool call`)}async approveAutoCompact(){throw Error(`No pending auto compact request`)}async rejectAutoCompact(){throw Error(`No pending auto compact request`)}async updateYoloMode(e){this.state.yoloMode=e;let t=await this.realAgentPromise;t&&await t.updateYoloMode(e)}async updateModel(e){this.state.model=e;let t=await this.realAgentPromise;t&&await t.updateModel(e)}async updateThinkingLevel(e){this.state.thinkingLevel=e;let t=await this.realAgentPromise;t&&await t.updateThinkingLevel(e)}dispose(){this.disposed=!0,this.listeners.clear(),this.promotedAgent||this.realAgentPromise?.then(e=>{this.promotedAgent!==e&&e.dispose()}).catch(()=>{})}promoteTo(e){this.promotedAgent=e,this.listeners.clear()}async ensureRealAgent(){if(!this.realAgentPromise){let e=It();this.realAgentPromise=this.createAgent({model:this.state.model,thinkingLevel:this.state.thinkingLevel,tools:[]},e,{scope:this.scope,project:this.project,attachToView:!0,yoloMode:this.state.yoloMode}).then(e=>(this.disposed&&this.promotedAgent!==e&&e.dispose(),e))}return this.realAgentPromise}};function uo(e,t=` `){return Array.isArray(e)?e.filter(e=>typeof e==`object`&&!!e&&`type`in e&&e.type===`text`&&`text`in e&&typeof e.text==`string`).map(e=>e.text).join(t):``}function fo(e){return e.role===`assistant`?uo(e.content,`
|
|
34
|
+
|
|
35
|
+
`).trim():``}function po(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 mo(e){return e.role!==`user`&&e.role!==`user-with-attachments`?``:typeof e.content==`string`?e.content:uo(e.content,`
|
|
36
|
+
|
|
37
|
+
`)}async function ho(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 go(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:uo(n)).trim().replace(/\s+/g,` `);return r?r.length>46?`${r.slice(0,43)}...`:r:`New chat`}function _o(e){return e===`New chat`||e===q(`newChat`)}function vo(e){return e.some(e=>e.role===`user`||e.role===`user-with-attachments`)}function yo(e){return vo(e)&&e.some(e=>e.role===`assistant`)}function bo(e){let t=e;if(t?.role!==`user`)return!1;let n=t.content;return(typeof n==`string`?n:Array.isArray(n)?n.filter(e=>e?.type===`text`).map(e=>String(e.text??``)).join(`
|
|
38
|
+
`):``).includes(`<compact_summary>`)}function xo(e){let t=e.findIndex(bo);return t<0?null:{summaryMessage:e[t],compactedUpToIndex:Math.min(e.length,t+2)}}function So(e){let{storageRef:t,activeModelRef:n,yoloModeRef:r,activeProjectRef:i,setYoloMode:a,switchActiveProject:o,sessions:s,refreshSessions:c}=e,l=(0,W.useRef)(null),u=(0,W.useRef)(new Map),d=(0,W.useRef)(`global`),f=(0,W.useRef)(void 0),p=(0,W.useRef)(`New chat`),m=(0,W.useRef)(void 0),h=(0,W.useRef)(null),g=(0,W.useRef)(e.onTaskComplete);(0,W.useEffect)(()=>{g.current=e.onTaskComplete});let[_,v]=(0,W.useState)(null),[y,b]=(0,W.useState)(),[x,S]=(0,W.useState)(`New chat`),[C,w]=(0,W.useState)(`global`),[T,E]=(0,W.useState)(),[D,O]=(0,W.useState)({}),[k,ee]=(0,W.useState)(0),A=(0,W.useCallback)((e,t)=>{!e||e===t||[...u.current.values()].some(t=>t.agent===e)||e.dispose()},[u]),j=(0,W.useCallback)(async e=>{if(f.current===e.sessionId){let t=e.agent.state.messages,n=e.title;_o(n)&&(n=go(t)),m.current=e.createdAt??new Date().toISOString(),p.current=n,S(n)}await c({broadcast:!0})},[c]),M=(0,W.useCallback)(e=>{A(l.current,e.agent),d.current=e.scope,f.current=e.sessionId,m.current=e.createdAt,p.current=e.title,w(e.scope),b(e.sessionId),S(e.title),E(e.project),l.current=e.agent,v(e.agent);let t=new URL(window.location.href);t.searchParams.set(`session`,e.sessionId),window.history.replaceState({},``,t)},[A]),N=(0,W.useCallback)(async(e,o=It(),s)=>{let m=l.current,_=u.current.get(o);if(_)return s?.attachToView!==!1&&(A(m,_.agent),M(_)),_.agent;let v=s?.scope??d.current,y=v===`project`?s?.project??i.current:void 0,b=new Date().toISOString(),{model:x,thinkingLevel:C,tools:w,...T}=e??{},E=t.current,D=E?await nn(E):{},k=x??D.model??n.current,ee=E?await fn(E,k):Kt(k),N=C??D.thinkingLevel??$t(ee);n.current=ee;let P=s?.yoloMode??r.current;r.current=P,a(P);let F=await co.create(o,{scope:v,projectId:y?.id,yoloMode:P,model:ee,thinkingLevel:N,messages:T.messages??[],title:s?.title,contextCompaction:T.contextCompaction});T.contextCompaction&&!F.state.contextCompaction&&(F.state.contextCompaction=T.contextCompaction);let te=F.state.isStreaming?`running`:F.state.errorMessage?`error`:`idle`,I={sessionId:F.sessionId,agent:F,scope:v,project:y,title:s?.title??`New chat`,createdAt:s?.createdAt??b,status:te,startedAt:b,unsubscribe:()=>void 0};return I.unsubscribe=F.subscribe(e=>{if(e.type===`agent_start`&&(I.status=`running`,I.startedAt=I.startedAt??new Date().toISOString(),I.finishedAt=void 0,O(e=>({...e,[I.sessionId]:I.status}))),e.type===`message_end`&&(F.state.messages=[...F.state.messages]),e.type===`agent_end`){let t=I.status===`running`,n=e;I.status=n.status===`aborted`?`aborted`:n.errorMessage||F.state.errorMessage?`error`:`idle`,I.finishedAt=new Date().toISOString(),O(e=>({...e,[I.sessionId]:I.status})),j(I).catch(e=>U.error(`Failed to sync session UI:`,e)),t&&g.current?.(I.sessionId,I.title,I.status)}if(e.type===`title_updated`){let t=e;t.title&&(I.title=t.title),I.sessionId===f.current&&t.title&&(p.current=t.title,S(t.title)),c({broadcast:!0}).catch(e=>U.error(`Failed to refresh sessions:`,e))}if(e.type===`session_forked`){let t=e;if(!t.targetSessionId)return;c({broadcast:!0}).catch(e=>U.error(`Failed to refresh sessions:`,e)),h.current?.(t.targetSessionId,{title:t.title,createdAt:t.createdAt,scope:t.scope,projectId:t.projectId??void 0})}}),u.current.set(o,I),I.status!==`idle`&&O(e=>({...e,[I.sessionId]:I.status})),s?.attachToView!==!1&&(m instanceof lo?m.promoteTo(I.agent):l.current===m&&A(m,I.agent),M(I)),F.state.messages.length>0&&await c({broadcast:!0}),F},[M,A,c,j,t,n,r,i,a]),P=(0,W.useCallback)(async e=>{let i=t.current,a=i?await nn(i):{},o=a.model??n.current,s=i?await fn(i,o):Kt(o),c=a.thinkingLevel??$t(s);n.current=s;let u=e.scope,h=u===`project`?e.project:void 0,g=new lo({scope:u,project:h,model:s,thinkingLevel:c,yoloMode:r.current,createAgent:N});A(l.current),d.current=u,f.current=void 0,m.current=void 0,p.current=`New chat`,w(u),b(void 0),S(`New chat`),E(h),l.current=g,v(g);let _=new URL(window.location.href);return _.searchParams.delete(`session`),window.history.replaceState({},``,_),g},[n,N,A,t,r]),F=(0,W.useCallback)(async(e,r)=>{let a=u.current.get(e);if(a){if(a.scope===`project`&&a.project?.id&&i.current?.id!==a.project.id)try{await o(a.project.id)}catch(e){U.error(`Failed to switch project for running session:`,e)}M(a);return}let c=t.current;if(!c){await N({tools:[]},e,{scope:r?.scope??`global`,attachToView:!0,createdAt:r?.createdAt,title:r?.title});return}let l=await c.sessions.get(e);if(!l)return;let d=s.find(t=>t.id===e)??await c.sessions.getMetadata(e),f=r?.scope??gn(d??l),p=r?.projectId??d?.projectId??l.projectId,m;if(f===`project`&&p){let e=p;if(i.current?.id!==e)try{m=await o(e)}catch(e){U.error(`Failed to switch project for session:`,e),Z(q(`projectSwitchFailed`));return}else m=i.current}n.current=l.model,await N({model:l.model,thinkingLevel:l.thinkingLevel,messages:l.messages,contextCompaction:l.contextCompaction??xo(l.messages)},l.id,{scope:f,project:m,attachToView:!0,createdAt:l.createdAt??r?.createdAt,title:l.title??r?.title,yoloMode:l.yoloMode===!0})},[M,N,s,o,t,n,i]);return(0,W.useEffect)(()=>{h.current=F},[F]),{agentRef:l,taskMapRef:u,currentSessionIdRef:f,currentChatScopeRef:d,agent:_,currentSessionId:y,currentTitle:x,chatScope:C,currentToolProject:T,taskStatuses:D,chatPanelRevision:k,createAgent:N,startDeferredSession:P,loadSession:F,syncSessionUI:j,setChatPanelRevision:ee,setCurrentAgentMessages:(0,W.useCallback)(e=>{l.current&&(l.current.state.messages=e)},[]),updateCurrentAgentModel:(0,W.useCallback)(e=>{l.current&&(l.current.state.model=e,l.current.updateModel(e).catch(e=>{U.error(`Failed to sync model to server:`,e)}))},[]),setCurrentTitleRef:(0,W.useCallback)(e=>{p.current=e},[])}}var Co=20;function wo(e){if(!e)return 0;let t=new Date(e).getTime();return Number.isNaN(t)?0:t}function To(e){return[...e].sort((e,t)=>{let n=wo(t.pinnedAt)-wo(e.pinnedAt);return n===0?e.pinnedAt&&!t.pinnedAt?-1:!e.pinnedAt&&t.pinnedAt?1:wo(t.lastModified)-wo(e.lastModified):n})}function Eo({backendRef:e,expandedProjectIds:t,onBroadcastSessionsChanged:n}){let[r,i]=(0,W.useState)({items:[],total:0,loading:!1}),[a,o]=(0,W.useState)({}),s=(0,W.useRef)(a),c=(0,W.useRef)(t);(0,W.useEffect)(()=>{s.current=a},[a]),(0,W.useEffect)(()=>{c.current=t},[t]);let l=(0,W.useMemo)(()=>[...r.items,...Object.values(a).flatMap(e=>e.items)],[r.items,a]),u=(0,W.useCallback)(async t=>{let n=e.current;if(n){i(e=>({...e,loading:!0}));try{let e=await n.fetchPaginatedFromIndex(`sessions-metadata`,`lastModified`,{direction:`desc`,limit:Co,offset:t,scope:`global`});i(n=>({items:To(t===0?e.values:[...n.items,...e.values]),total:e.total,loading:!1}))}catch{i(e=>({...e,loading:!1}))}}},[e]),d=(0,W.useCallback)(async(t,n)=>{let r=e.current;if(r){o(e=>{let n=e[t];return{...e,[t]:{...n??{items:[],total:0},loading:!0}}});try{let e=await r.fetchPaginatedFromIndex(`sessions-metadata`,`lastModified`,{direction:`desc`,limit:Co,offset:n,scope:`project`,projectId:t});o(r=>{let i=r[t]?.items??[];return{...r,[t]:{items:To(n===0?e.values:[...i,...e.values]),total:e.total,loading:!1}}})}catch{o(e=>{let n=e[t];return{...e,[t]:{...n??{items:[],total:0},loading:!1}}})}}},[e]),f=(0,W.useCallback)(async e=>{await u(0);let t=new Set([...Object.keys(s.current),...c.current]);t.size===0?o({}):(o(e=>{let n={};for(let r of t)n[r]={...e[r]??{items:[],total:0},loading:!0};return n}),await Promise.all([...t].map(e=>d(e,0)))),e?.broadcast&&n?.()},[u,d,n]),p=(0,W.useCallback)(e=>a[e]?.items??[],[a]),m=(0,W.useCallback)(e=>{let t=a[e];return t?t.items.length<t.total:!0},[a]),h=(0,W.useCallback)(e=>a[e]?.loading??!1,[a]),g=(0,W.useCallback)(e=>e in a,[a]),_=(0,W.useCallback)(()=>{u(r.items.length)},[r.items.length,u]),v=(0,W.useCallback)(e=>{let t=a[e];d(e,t?.items.length??0)},[d,a]);return{allLoadedSessions:l,globalSessions:r.items,sessionsForProject:p,globalHasMore:r.items.length<r.total,projectHasMore:m,globalLoading:r.loading,projectLoading:h,projectLoaded:g,loadGlobalSessions:u,loadProjectSessions:d,refreshSessions:f,loadMoreGlobal:_,loadMoreProject:v}}function Do(){let[e,t]=(0,W.useState)([]),n=(0,W.useCallback)(e=>{t(t=>[...t,{...e,id:It(),createdAt:Date.now()}])},[]);return{toasts:e,handleTaskComplete:(0,W.useCallback)((e,t,r)=>{n({sessionId:e,title:t,status:r})},[n]),addToast:n,dismissToast:(0,W.useCallback)(e=>{t(t=>t.filter(t=>t.id!==e))},[])}}var Oo=`tool-display-settings`,ko={showToolDetails:!1,expandToolsByDefault:!1},Ao={...ko};function jo(e){if(!e||typeof e!=`object`)return{...ko};let t=e;return{showToolDetails:t.showToolDetails===!0,expandToolsByDefault:t.expandToolsByDefault===!0}}function Mo(){return Ao}async function No(e){let t=jo(await e.settings.get(Oo));return Ao=t,t}async function Po(e,t){let n=jo(t);await e.settings.set(Oo,n),Ao=n}var Fo=`font-size-settings`,Io={baseFontSizePx:14,bodyFontSizePx:12};function Lo(e,t,n,r){let i=Number(e);return Number.isFinite(i)?Math.min(r,Math.max(n,Math.round(i))):t}function Ro(e){if(!e||typeof e!=`object`)return{...Io};let t=e;return{baseFontSizePx:Lo(t.baseFontSizePx,Io.baseFontSizePx,12,18),bodyFontSizePx:Lo(t.bodyFontSizePx,Io.bodyFontSizePx,11,16)}}function zo(e){if(typeof document>`u`)return;let t=Ro(e),n=document.documentElement;n.style.fontSize=`${t.baseFontSizePx}px`,n.style.setProperty(`--text-sm`,`${t.bodyFontSizePx}px`),n.style.setProperty(`--text-sm--line-height`,String(16/t.bodyFontSizePx))}async function Bo(e){return Ro(await e.settings.get(Fo))}async function Vo(e){let t=await Bo(e);return zo(t),t}async function Ho(e,t){let n=Ro(t);await e.settings.set(Fo,n),zo(n)}function Uo({storageRef:e,backendRef:t,activeModelRef:n,yoloModeRef:r,activeProjectRef:i,setYoloMode:a,taskMapRef:o,loadGlobalSessions:s,loadProject:c,initYoloMode:l,switchActiveProject:u,createAgent:d,setNeedsModelSetup:f,onStorageReady:p}){let[m,h]=(0,W.useState)(!1),[g,_]=(0,W.useState)(),[v,y]=(0,W.useState)(0),b=(0,W.useRef)({loadGlobalSessions:s,loadProject:c,initYoloMode:l,switchActiveProject:u,createAgent:d,setNeedsModelSetup:f,onStorageReady:p});return(0,W.useEffect)(()=>{b.current={loadGlobalSessions:s,loadProject:c,initYoloMode:l,switchActiveProject:u,createAgent:d,setNeedsModelSetup:f,onStorageReady:p}}),(0,W.useEffect)(()=>{let s=!1;async function c(){let{loadGlobalSessions:o,loadProject:c,initYoloMode:l,switchActiveProject:u,createAgent:d,setNeedsModelSetup:f,onStorageReady:p}=b.current;try{h(!1),_(void 0);let m=await Zt();if(s)return;e.current=m,p?.(m),t.current=m.backend,await Ue(m),await No(m),await Vo(m),await Promise.all([o(0),c()]),r.current=await l(m);let g=await un(m),v=await nn(m);g&&(n.current=v.model??g);let y=new URLSearchParams(window.location.search).get(`session`);if(y){let e=await m.sessions.get(y);if(e){let t=await m.sessions.getMetadata(e.id),o=gn(t??e),s;if(o===`project`&&(t?.projectId||e.projectId)){let n=t?.projectId??e.projectId;if(i.current?.id!==n)try{s=await u(n)}catch(e){U.error(`Failed to switch project for initial session:`,e),Z(q(`projectSwitchFailed`)),g?await d({model:v.model??g,thinkingLevel:v.thinkingLevel,tools:[]},It(),{scope:`global`,attachToView:!0}):f(!0),h(!0);return}else s=i.current}n.current=e.model;let c=e.yoloMode===!0;r.current=c,a(c),await d({model:e.model,thinkingLevel:e.thinkingLevel,messages:e.messages,tools:[]},e.id,{scope:o,project:s,attachToView:!0,createdAt:e.createdAt,title:e.title,yoloMode:c})}else g?await d({model:v.model??g,thinkingLevel:v.thinkingLevel,tools:[]},It(),{scope:`global`,attachToView:!0}):f(!0)}else g?await d({model:v.model??g,thinkingLevel:v.thinkingLevel,tools:[]},It(),{scope:`global`,attachToView:!0}):f(!0);h(!0)}catch(e){U.error(`Failed to bootstrap QuickForge:`,e),s||_(q(`localServiceUnavailableDescription`))}}c();let l=o.current;return()=>{s=!0;for(let e of l.values())e.unsubscribe(),e.agent.dispose();l.clear()}},[e,t,n,r,i,a,o,v]),{ready:m,startupError:g,retryBootstrap:(0,W.useCallback)(()=>{h(!1),_(void 0),y(e=>e+1)},[])}}var Wo=()=>({modelId:``,contextWindow:Vt.contextWindow,maxTokens:Vt.maxTokens,reasoning:!0}),Go=()=>({name:Vt.name,baseUrl:Vt.baseUrl,apiKey:``,headersJson:`{}`,protocol:`openai-completions`,models:[Wo()]}),Ko=class extends we{providers=[];form=Go();editingProviderId;formOpen=!1;loading=!0;apiKeyVisible=!1;autoEditProviderName=null;async connectedCallback(){if(super.connectedCallback(),await this.loadProviders(),this.autoEditProviderName){let e=this.providers.find(e=>e.name===this.autoEditProviderName);e&&await this.openEditForm(e),this.autoEditProviderName=null}}getTabName(){return q(`customModels`)}async loadProviders(){this.loading=!0,this.requestUpdate();try{this.providers=await V().customProviders.getAll()}catch(e){U.error(`Failed to load custom providers:`,e),this.providers=[]}finally{this.loading=!1,this.requestUpdate()}}openAddForm(){this.editingProviderId=void 0,this.form=Go(),this.apiKeyVisible=!1,this.formOpen=!0,this.requestUpdate()}async openEditForm(e){let t=await V().providerKeys.get(e.name)??e.apiKey??``,n=e.models??[],r=n.length>0?n.map(e=>({modelId:e.id,contextWindow:e.contextWindow??Vt.contextWindow,maxTokens:e.maxTokens??Vt.maxTokens,reasoning:e.reasoning===!0})):[Wo()];this.editingProviderId=e.id,this.form={providerId:e.id,id:e.id,name:e.name,baseUrl:e.baseUrl,apiKey:t,headersJson:JSON.stringify(n[0]?.headers??{},null,2),protocol:e.type===`anthropic-messages`?`anthropic-messages`:`openai-completions`,models:r},this.apiKeyVisible=!1,this.formOpen=!0,this.requestUpdate()}closeForm(){this.formOpen=!1,this.editingProviderId=void 0,this.form=Go(),this.apiKeyVisible=!1,this.requestUpdate()}toggleApiKeyVisibility(){this.apiKeyVisible=!this.apiKeyVisible,this.requestUpdate()}updateForm(e,t){this.form={...this.form,[e]:t},this.requestUpdate()}updateModelField(e,t,n){let r=this.form.models.map((r,i)=>i===e?{...r,[t]:n}:r);this.form={...this.form,models:r},this.requestUpdate()}addModelRow(){this.form={...this.form,models:[...this.form.models,Wo()]},this.requestUpdate()}removeModelRow(e){let t=this.form.models.filter((t,n)=>n!==e);this.form={...this.form,models:t},this.requestUpdate()}parseHeadersJson(){let e=this.form.headersJson.trim();if(!e)return{};let t;try{t=JSON.parse(e)}catch{return Z(q(`invalidHeadersJson`)),null}if(!t||typeof t!=`object`||Array.isArray(t))return Z(q(`invalidHeadersJson`)),null;let n={};for(let[e,r]of Object.entries(t)){if(!e.trim()||typeof r!=`string`)return Z(q(`invalidHeadersJson`)),null;n[e]=r}return n}buildModel(e,t){let n=this.form.name.trim(),r=this.form.baseUrl.trim(),i=e.reasoning===!0,a=r.includes(`api.deepseek.com`);return Kt({id:e.modelId,name:`${e.modelId} (${n})`,api:this.form.protocol,provider:n,baseUrl:r.replace(/\/$/,``),reasoning:i,input:[`text`,`image`],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:Number(e.contextWindow)||Vt.contextWindow,maxTokens:Number(e.maxTokens)||Vt.maxTokens,headers:Object.keys(t).length>0?t:void 0,thinkingLevelMap:a&&i?{low:`high`,medium:`high`,high:`high`,xhigh:`max`}:void 0,compat:this.form.protocol===`openai-completions`?{supportsStore:!1,supportsDeveloperRole:!1,supportsReasoningEffort:i,supportsUsageInStreaming:!1,supportsStrictMode:!1,maxTokensField:`max_tokens`,...a&&i?{requiresReasoningContentOnAssistantMessages:!0,thinkingFormat:`deepseek`}:{}}:void 0})}async saveModel(){let e=this.form.name.trim(),t=this.form.baseUrl.trim();if(!e||!t){Z(q(`fillProviderBaseUrlModel`));return}let n=this.form.models.filter(e=>e.modelId.trim());if(n.length===0){Z(q(`atLeastOneModel`));return}let r=n.map(e=>e.modelId.trim());if(new Set(r).size!==r.length){Z(q(`duplicateModelId`));return}let i=this.parseHeadersJson();if(!i)return;let a=n.map(e=>this.buildModel(e,i)),o=this.form.apiKey.trim(),s=this.editingProviderId?this.providers.find(e=>e.id===this.editingProviderId):void 0,c={id:this.editingProviderId??It(),name:e,type:this.form.protocol,baseUrl:a[0].baseUrl,apiKey:o||void 0,models:a};try{let e=V();await e.customProviders.set(c),s&&s.name!==c.name&&await e.providerKeys.delete(s.name),o?await e.providerKeys.set(c.name,o):await e.providerKeys.delete(c.name),this.closeForm(),await this.loadProviders()}catch(e){U.error(`Failed to save custom model:`,e),Z(q(`saveCustomModelFailed`))}}async deleteProvider(e){if(await lt({description:q(`confirmDeleteProvider`,{name:e.name}),confirmLabel:q(`confirmDelete`),cancelLabel:q(`cancel`),variant:`destructive`}))try{let t=V();await t.customProviders.delete(e.id),await t.providerKeys.delete(e.name),await this.loadProviders()}catch(e){U.error(`Failed to delete custom provider:`,e),Z(q(`deleteFailed`))}}renderProvider(e){let t=e.models??[],n=t.length;return z`
|
|
39
|
+
<div class="rounded-lg border border-border p-4">
|
|
40
|
+
<div class="flex items-start justify-between gap-4">
|
|
41
|
+
<div class="min-w-0 flex-1">
|
|
42
|
+
<div class="text-sm font-medium text-foreground">${e.name}</div>
|
|
43
|
+
<div class="mt-1 break-all text-xs text-muted-foreground">${e.baseUrl}</div>
|
|
44
|
+
<div class="mt-2 text-xs text-muted-foreground">
|
|
45
|
+
${q(`providerProtocol`)}: ${e.type===`anthropic-messages`?`Anthropic Messages`:`OpenAI Compatible`}
|
|
46
|
+
</div>
|
|
47
|
+
${n===0?z`<div class="mt-1 text-xs text-muted-foreground">${q(`noModelAdded`)}</div>`:z`
|
|
48
|
+
<div class="mt-2 text-xs text-muted-foreground">${q(`modelsCount`,{count:n})}</div>
|
|
49
|
+
<div class="mt-1 flex flex-wrap gap-1">
|
|
50
|
+
${t.map(e=>z`
|
|
51
|
+
<span class="inline-flex items-center gap-1 rounded-md border border-border bg-muted px-2 py-0.5 text-xs text-foreground">
|
|
52
|
+
<span class="font-medium">${e.id}</span>
|
|
53
|
+
<span class="text-muted-foreground">${e.contextWindow}/${e.maxTokens}</span>
|
|
54
|
+
</span>
|
|
55
|
+
`)}
|
|
56
|
+
</div>
|
|
57
|
+
`}
|
|
58
|
+
</div>
|
|
59
|
+
<div class="flex shrink-0 gap-2">
|
|
60
|
+
<button
|
|
61
|
+
class="rounded-md px-3 py-1.5 text-sm hover:bg-secondary"
|
|
62
|
+
type="button"
|
|
63
|
+
@click=${()=>this.openEditForm(e)}
|
|
64
|
+
>
|
|
65
|
+
${q(`editModel`)}
|
|
66
|
+
</button>
|
|
67
|
+
<button
|
|
68
|
+
class="rounded-md px-3 py-1.5 text-sm text-destructive hover:bg-secondary"
|
|
69
|
+
type="button"
|
|
70
|
+
@click=${()=>this.deleteProvider(e)}
|
|
71
|
+
>
|
|
72
|
+
${q(`delete`)}
|
|
73
|
+
</button>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
`}renderModelRow(e,t){return z`
|
|
78
|
+
<div class="rounded-md border border-border p-3">
|
|
79
|
+
<div class="mb-2 flex items-center justify-between">
|
|
80
|
+
<span class="text-xs font-medium text-muted-foreground">${q(`modelIndex`,{index:t+1})}</span>
|
|
81
|
+
${this.form.models.length>1?z`
|
|
82
|
+
<button
|
|
83
|
+
class="rounded px-1.5 py-0.5 text-xs text-muted-foreground hover:text-destructive hover:bg-secondary"
|
|
84
|
+
type="button"
|
|
85
|
+
@click=${()=>this.removeModelRow(t)}
|
|
86
|
+
>
|
|
87
|
+
✕
|
|
88
|
+
</button>
|
|
89
|
+
`:``}
|
|
90
|
+
</div>
|
|
91
|
+
<div class="grid gap-3">
|
|
92
|
+
<label class="grid gap-1 text-xs">
|
|
93
|
+
<span class="text-muted-foreground">${q(`modelId`)}</span>
|
|
94
|
+
<input
|
|
95
|
+
class="rounded-md border border-input bg-background px-3 py-1.5 text-sm"
|
|
96
|
+
.value=${e.modelId}
|
|
97
|
+
@input=${e=>this.updateModelField(t,`modelId`,e.target.value)}
|
|
98
|
+
placeholder=${q(`modelIdPlaceholder`)}
|
|
99
|
+
/>
|
|
100
|
+
</label>
|
|
101
|
+
<div class="grid grid-cols-2 gap-3">
|
|
102
|
+
<label class="grid gap-1 text-xs">
|
|
103
|
+
<span class="text-muted-foreground">${q(`contextWindow`)}</span>
|
|
104
|
+
<input
|
|
105
|
+
class="rounded-md border border-input bg-background px-3 py-1.5 text-sm"
|
|
106
|
+
.value=${String(e.contextWindow)}
|
|
107
|
+
type="number"
|
|
108
|
+
@input=${e=>this.updateModelField(t,`contextWindow`,Number(e.target.value))}
|
|
109
|
+
/>
|
|
110
|
+
</label>
|
|
111
|
+
<label class="grid gap-1 text-xs">
|
|
112
|
+
<span class="text-muted-foreground">${q(`maxTokens`)}</span>
|
|
113
|
+
<input
|
|
114
|
+
class="rounded-md border border-input bg-background px-3 py-1.5 text-sm"
|
|
115
|
+
.value=${String(e.maxTokens)}
|
|
116
|
+
type="number"
|
|
117
|
+
@input=${e=>this.updateModelField(t,`maxTokens`,Number(e.target.value))}
|
|
118
|
+
/>
|
|
119
|
+
</label>
|
|
120
|
+
</div>
|
|
121
|
+
<label class="mt-3 flex items-center gap-2 text-xs">
|
|
122
|
+
<input
|
|
123
|
+
class="rounded border-border"
|
|
124
|
+
type="checkbox"
|
|
125
|
+
.checked=${e.reasoning}
|
|
126
|
+
@change=${e=>this.updateModelField(t,`reasoning`,e.target.checked)}
|
|
127
|
+
/>
|
|
128
|
+
<span class="text-muted-foreground">${q(`reasoningModel`)}</span>
|
|
129
|
+
</label>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
`}renderForm(){return z`
|
|
133
|
+
<div class="rounded-lg border border-border p-4">
|
|
134
|
+
<div class="mb-4 text-sm font-semibold text-foreground">
|
|
135
|
+
${this.editingProviderId?q(`editCustomModel`):q(`addCustomModel`)}
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div class="grid gap-4">
|
|
139
|
+
<label class="grid gap-1.5 text-sm">
|
|
140
|
+
<span class="text-foreground">${q(`providerName`)}</span>
|
|
141
|
+
<input
|
|
142
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
143
|
+
.value=${this.form.name}
|
|
144
|
+
@input=${e=>this.updateForm(`name`,e.target.value)}
|
|
145
|
+
placeholder=${q(`providerNamePlaceholder`)}
|
|
146
|
+
/>
|
|
147
|
+
</label>
|
|
148
|
+
|
|
149
|
+
<label class="grid gap-1.5 text-sm">
|
|
150
|
+
<span class="text-foreground">${q(`protocolType`)}</span>
|
|
151
|
+
<select
|
|
152
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
153
|
+
.value=${this.form.protocol}
|
|
154
|
+
@change=${e=>this.updateForm(`protocol`,e.target.value)}
|
|
155
|
+
>
|
|
156
|
+
<option value="openai-completions">OpenAI Compatible / Chat Completions</option>
|
|
157
|
+
<option value="anthropic-messages">Anthropic Messages</option>
|
|
158
|
+
</select>
|
|
159
|
+
<span class="text-xs text-muted-foreground">
|
|
160
|
+
${q(`protocolHelp`)}
|
|
161
|
+
</span>
|
|
162
|
+
</label>
|
|
163
|
+
|
|
164
|
+
<label class="grid gap-1.5 text-sm">
|
|
165
|
+
<span class="text-foreground">Base URL</span>
|
|
166
|
+
<input
|
|
167
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
168
|
+
.value=${this.form.baseUrl}
|
|
169
|
+
@input=${e=>this.updateForm(`baseUrl`,e.target.value)}
|
|
170
|
+
placeholder=${this.form.protocol===`anthropic-messages`?`e.g., https://api.anthropic.com`:`e.g., http://localhost:4000/v1`}
|
|
171
|
+
/>
|
|
172
|
+
</label>
|
|
173
|
+
|
|
174
|
+
<label class="grid gap-1.5 text-sm">
|
|
175
|
+
<span class="text-foreground">${q(`apiKey`)}</span>
|
|
176
|
+
<div class="relative">
|
|
177
|
+
<input
|
|
178
|
+
class="w-full rounded-md border border-input bg-background px-3 py-2 pr-10 text-sm"
|
|
179
|
+
.value=${this.form.apiKey}
|
|
180
|
+
type=${this.apiKeyVisible?`text`:`password`}
|
|
181
|
+
@input=${e=>this.updateForm(`apiKey`,e.target.value)}
|
|
182
|
+
placeholder=${q(`apiKeyPlaceholder`)}
|
|
183
|
+
/>
|
|
184
|
+
<button
|
|
185
|
+
class="absolute inset-y-0 right-0 flex w-10 items-center justify-center rounded-r-md text-muted-foreground hover:text-foreground/85 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
186
|
+
type="button"
|
|
187
|
+
title=${this.apiKeyVisible?q(`hideApiKey`):q(`showApiKey`)}
|
|
188
|
+
aria-label=${this.apiKeyVisible?q(`hideApiKey`):q(`showApiKey`)}
|
|
189
|
+
aria-pressed=${this.apiKeyVisible?`true`:`false`}
|
|
190
|
+
@click=${()=>this.toggleApiKeyVisibility()}
|
|
191
|
+
>
|
|
192
|
+
${this.apiKeyVisible?z`<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.53 13.53 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" y1="2" x2="22" y2="22"/><path d="M8.53 8.53A5 5 0 0 0 12 17a5 5 0 0 0 3.47-8.53"/></svg>`:z`<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>`}
|
|
193
|
+
</button>
|
|
194
|
+
</div>
|
|
195
|
+
</label>
|
|
196
|
+
|
|
197
|
+
<label class="grid gap-1.5 text-sm">
|
|
198
|
+
<span class="text-foreground">${q(`customHeaders`)}</span>
|
|
199
|
+
<textarea
|
|
200
|
+
class="min-h-24 rounded-md border border-input bg-background px-3 py-2 font-mono text-sm"
|
|
201
|
+
.value=${this.form.headersJson}
|
|
202
|
+
@input=${e=>this.updateForm(`headersJson`,e.target.value)}
|
|
203
|
+
placeholder=${q(`customHeadersPlaceholder`)}
|
|
204
|
+
></textarea>
|
|
205
|
+
<span class="text-xs text-muted-foreground">
|
|
206
|
+
${q(`customHeadersHelp`)}
|
|
207
|
+
</span>
|
|
208
|
+
</label>
|
|
209
|
+
|
|
210
|
+
<div class="grid gap-3">
|
|
211
|
+
<div class="flex items-center justify-between">
|
|
212
|
+
<span class="text-sm font-medium text-foreground">${q(`modelsList`)}</span>
|
|
213
|
+
<button
|
|
214
|
+
class="rounded-md px-2 py-1 text-xs hover:bg-secondary"
|
|
215
|
+
type="button"
|
|
216
|
+
@click=${()=>this.addModelRow()}
|
|
217
|
+
>
|
|
218
|
+
+ ${q(`addModel`)}
|
|
219
|
+
</button>
|
|
220
|
+
</div>
|
|
221
|
+
${this.form.models.map((e,t)=>this.renderModelRow(e,t))}
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
|
|
225
|
+
<div class="mt-4 flex justify-end gap-2">
|
|
226
|
+
<button class="rounded-md px-3 py-2 text-sm hover:bg-secondary" type="button" @click=${()=>this.closeForm()}>
|
|
227
|
+
${q(`cancel`)}
|
|
228
|
+
</button>
|
|
229
|
+
<button
|
|
230
|
+
class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground"
|
|
231
|
+
type="button"
|
|
232
|
+
@click=${()=>this.saveModel()}
|
|
233
|
+
>
|
|
234
|
+
${q(`save`)}
|
|
235
|
+
</button>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
`}render(){return z`
|
|
239
|
+
<div class="flex flex-col gap-6">
|
|
240
|
+
<div class="flex items-center justify-between gap-4">
|
|
241
|
+
<div>
|
|
242
|
+
<h3 class="mb-2 text-sm font-semibold text-foreground">${q(`customModelsTitle`)}</h3>
|
|
243
|
+
<p class="text-sm text-muted-foreground">${q(`customModelsDescription`)}</p>
|
|
244
|
+
</div>
|
|
245
|
+
<button
|
|
246
|
+
class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground"
|
|
247
|
+
type="button"
|
|
248
|
+
@click=${()=>this.openAddForm()}
|
|
249
|
+
>
|
|
250
|
+
${q(`addModel`)}
|
|
251
|
+
</button>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
${this.formOpen?this.renderForm():``}
|
|
255
|
+
|
|
256
|
+
${this.loading?z`<div class="py-8 text-center text-sm text-muted-foreground">${q(`loading`)}</div>`:this.providers.length===0?z`<div class="py-8 text-center text-sm text-muted-foreground">${q(`noCustomModels`)}</div>`:z`<div class="flex flex-col gap-3">${this.providers.map(e=>this.renderProvider(e))}</div>`}
|
|
257
|
+
</div>
|
|
258
|
+
`}},qo=`quickforge-custom-providers-only-tab`;customElements.get(qo)||customElements.define(qo,Ko);function Jo(e){let t=document.createElement(qo);return e&&(t.autoEditProviderName=e),t}var Yo=class extends we{selectedLanguage=Ve();getTabName(){return q(`language`)}updateLanguage(e){this.selectedLanguage=e===`zh`?`zh`:`en`,this.requestUpdate()}async applyLanguage(){await We(V(),this.selectedLanguage)||Z(q(`noLanguageChange`))}render(){return z`
|
|
259
|
+
<div class="flex flex-col gap-6">
|
|
260
|
+
<div>
|
|
261
|
+
<h3 class="mb-2 text-sm font-semibold text-foreground">${q(`language`)}</h3>
|
|
262
|
+
<p class="text-sm text-muted-foreground">${q(`languageDescription`)}</p>
|
|
263
|
+
</div>
|
|
264
|
+
|
|
265
|
+
<label class="grid max-w-sm gap-1.5 text-sm">
|
|
266
|
+
<span class="text-foreground">${q(`displayLanguage`)}</span>
|
|
267
|
+
<select
|
|
268
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
269
|
+
.value=${this.selectedLanguage}
|
|
270
|
+
@change=${e=>this.updateLanguage(e.target.value)}
|
|
271
|
+
>
|
|
272
|
+
<option value="zh">${q(`simplifiedChinese`)}</option>
|
|
273
|
+
<option value="en">${q(`english`)}</option>
|
|
274
|
+
</select>
|
|
275
|
+
</label>
|
|
276
|
+
|
|
277
|
+
<div>
|
|
278
|
+
<button
|
|
279
|
+
class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground"
|
|
280
|
+
type="button"
|
|
281
|
+
@click=${()=>this.applyLanguage()}
|
|
282
|
+
>
|
|
283
|
+
${q(`apply`)}
|
|
284
|
+
</button>
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
`}},Xo=`quickforge-language-settings-tab`;customElements.get(Xo)||customElements.define(Xo,Yo);function Zo(){return document.createElement(Xo)}var Qo=`auto-compact-settings`,$o={enabled:!1,thresholdPercent:80,keepRecentTurns:2,minSourceChars:1600,requireConfirmation:!0};function es(e,t,n,r){let i=Number(e);return Number.isFinite(i)?Math.min(r,Math.max(n,Math.round(i))):t}function ts(e){if(!e||typeof e!=`object`)return{...$o};let t=e;return{enabled:t.enabled===!0,thresholdPercent:es(t.thresholdPercent,$o.thresholdPercent,50,95),keepRecentTurns:es(t.keepRecentTurns,$o.keepRecentTurns,1,20),minSourceChars:es(t.minSourceChars,$o.minSourceChars,0,2e5),requireConfirmation:t.requireConfirmation!==!1}}async function ns(e){return ts(await e.settings.get(Qo))}async function rs(e,t){await e.settings.set(Qo,ts(t))}var is=[{value:`off`,label:()=>q(`thinkingOff`)},{value:`low`,label:()=>q(`thinkingLow`)},{value:`medium`,label:()=>q(`thinkingMedium`)},{value:`high`,label:()=>q(`thinkingHigh`)},{value:`xhigh`,label:()=>q(`thinkingXHigh`)}];function as(e){return(e??``).trim().replace(/\/$/,``)}function os(e){return JSON.stringify([e.provider,e.id,e.api,as(e.baseUrl)])}function ss(e){return`${e.provider} / ${e.id}`}var cs=class extends we{models=[];selectedModel;thinkingLevel=`off`;showToolDetails=!1;expandToolsByDefault=!1;autoCompactEnabled=!1;autoCompactRequireConfirmation=!0;autoCompactThresholdPercent=80;autoCompactThresholdPercentInput=`80`;autoCompactKeepRecentTurns=2;baseFontSizePx=14;bodyFontSizePx=12;loading=!0;saved=!1;error=``;getTabName(){return q(`defaultOptions`)}async connectedCallback(){super.connectedCallback(),await this.loadSettings()}updated(){this.syncSelectValues()}syncSelectValues(){let e=this.querySelector(`[data-default-model-select]`);e&&this.selectedModel&&(e.value=os(this.selectedModel));let t=this.querySelector(`[data-default-thinking-select]`);t&&(t.value=this.thinkingLevel)}async loadSettings(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=V(),[t,n,r,i,a]=await Promise.all([ln(e),nn(e),No(e),ns(e),Bo(e)]);this.models=t,this.selectedModel=n.model?t.find(e=>os(e)===os(n.model))??n.model:t[0],this.thinkingLevel=n.thinkingLevel??$t(this.selectedModel),this.showToolDetails=r.showToolDetails,this.expandToolsByDefault=r.expandToolsByDefault,this.autoCompactEnabled=i.enabled,this.autoCompactRequireConfirmation=i.requireConfirmation,this.autoCompactThresholdPercent=i.thresholdPercent,this.autoCompactThresholdPercentInput=String(i.thresholdPercent),this.autoCompactKeepRecentTurns=i.keepRecentTurns,this.baseFontSizePx=a.baseFontSizePx,this.bodyFontSizePx=a.bodyFontSizePx}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}updateModel(e){let t=this.models.find(t=>os(t)===e);this.selectedModel=t,this.thinkingLevel=$t(t),this.saved=!1,this.requestUpdate()}updateThinkingLevel(e){this.thinkingLevel=is.some(t=>t.value===e)?e:`off`,this.saved=!1,this.requestUpdate()}updateShowToolDetails(e){this.showToolDetails=e,this.saved=!1,this.requestUpdate()}updateExpandToolsByDefault(e){this.expandToolsByDefault=e,this.saved=!1,this.requestUpdate()}updateAutoCompactEnabled(e){this.autoCompactEnabled=e,this.saved=!1,this.requestUpdate()}updateAutoCompactRequireConfirmation(e){this.autoCompactRequireConfirmation=e,this.saved=!1,this.requestUpdate()}updateAutoCompactThresholdPercent(e){this.autoCompactThresholdPercentInput=e;let t=Number(e);e!==``&&Number.isFinite(t)&&(this.autoCompactThresholdPercent=t),this.saved=!1,this.requestUpdate()}updateAutoCompactKeepRecentTurns(e){this.autoCompactKeepRecentTurns=Number(e)||2,this.saved=!1,this.requestUpdate()}updateBaseFontSize(e){this.baseFontSizePx=Number(e)||14,this.saved=!1,this.requestUpdate()}updateBodyFontSize(e){this.bodyFontSizePx=Number(e)||12,this.saved=!1,this.requestUpdate()}modelOptions(){if(!this.selectedModel)return this.models;let e=os(this.selectedModel);return this.models.some(t=>os(t)===e)?this.models:[this.selectedModel,...this.models]}async save(){try{let e=this.selectedModel?.reasoning?this.thinkingLevel:`off`;await tn(V(),{model:this.selectedModel,thinkingLevel:e}),await Po(V(),{showToolDetails:this.showToolDetails,expandToolsByDefault:this.expandToolsByDefault}),await rs(V(),{enabled:this.autoCompactEnabled,thresholdPercent:this.autoCompactThresholdPercent,keepRecentTurns:this.autoCompactKeepRecentTurns,minSourceChars:1600,requireConfirmation:this.autoCompactRequireConfirmation}),await Ho(V(),{baseFontSizePx:this.baseFontSizePx,bodyFontSizePx:this.bodyFontSizePx}),await this.loadSettings(),this.saved=!0,this.error=``,this.requestUpdate()}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`),this.requestUpdate()}}render(){return this.loading?z`<div class="text-sm text-muted-foreground">${q(`loading`)}</div>`:z`
|
|
288
|
+
<div class="flex flex-col gap-6">
|
|
289
|
+
<div>
|
|
290
|
+
<h3 class="mb-2 text-sm font-semibold text-foreground">${q(`defaultOptions`)}</h3>
|
|
291
|
+
<p class="text-sm text-muted-foreground">${q(`defaultOptionsDescription`)}</p>
|
|
292
|
+
</div>
|
|
293
|
+
|
|
294
|
+
<label class="grid max-w-md gap-1.5 text-sm">
|
|
295
|
+
<span class="text-foreground">${q(`defaultModel`)}</span>
|
|
296
|
+
<select
|
|
297
|
+
data-default-model-select
|
|
298
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
299
|
+
.value=${this.selectedModel?os(this.selectedModel):``}
|
|
300
|
+
@change=${e=>this.updateModel(e.target.value)}
|
|
301
|
+
>
|
|
302
|
+
${this.modelOptions().length===0?z`<option value="">${q(`noModelAvailable`)}</option>`:this.modelOptions().map(e=>z`
|
|
303
|
+
<option .value=${os(e)}>${ss(e)}</option>
|
|
304
|
+
`)}
|
|
305
|
+
</select>
|
|
306
|
+
</label>
|
|
307
|
+
|
|
308
|
+
<label class="grid max-w-sm gap-1.5 text-sm">
|
|
309
|
+
<span class="text-foreground">${q(`defaultThinkingLevel`)}</span>
|
|
310
|
+
<select
|
|
311
|
+
data-default-thinking-select
|
|
312
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm disabled:opacity-60"
|
|
313
|
+
.value=${this.thinkingLevel}
|
|
314
|
+
?disabled=${!this.selectedModel?.reasoning}
|
|
315
|
+
@change=${e=>this.updateThinkingLevel(e.target.value)}
|
|
316
|
+
>
|
|
317
|
+
${is.map(e=>z`
|
|
318
|
+
<option .value=${e.value}>${e.label()}</option>
|
|
319
|
+
`)}
|
|
320
|
+
</select>
|
|
321
|
+
${this.selectedModel?.reasoning?null:z`<span class="text-xs text-muted-foreground">${q(`thinkingRequiresReasoningModel`)}</span>`}
|
|
322
|
+
</label>
|
|
323
|
+
|
|
324
|
+
<div class="grid max-w-xl gap-3 rounded-lg border border-border p-4">
|
|
325
|
+
<div>
|
|
326
|
+
<h4 class="text-sm font-medium text-foreground">${q(`toolDisplay`)}</h4>
|
|
327
|
+
<p class="mt-1 text-xs text-muted-foreground">${q(`showToolDetailsDescription`)}</p>
|
|
328
|
+
</div>
|
|
329
|
+
<label class="flex items-center gap-2 text-sm text-foreground">
|
|
330
|
+
<input
|
|
331
|
+
type="checkbox"
|
|
332
|
+
class="size-4 rounded border-input"
|
|
333
|
+
.checked=${this.showToolDetails}
|
|
334
|
+
@change=${e=>this.updateShowToolDetails(e.target.checked)}
|
|
335
|
+
/>
|
|
336
|
+
<span>${q(`showToolDetails`)}</span>
|
|
337
|
+
</label>
|
|
338
|
+
<label class="flex items-center gap-2 text-sm text-foreground">
|
|
339
|
+
<input
|
|
340
|
+
type="checkbox"
|
|
341
|
+
class="size-4 rounded border-input"
|
|
342
|
+
.checked=${this.expandToolsByDefault}
|
|
343
|
+
@change=${e=>this.updateExpandToolsByDefault(e.target.checked)}
|
|
344
|
+
/>
|
|
345
|
+
<span>${q(`expandToolsByDefault`)}</span>
|
|
346
|
+
</label>
|
|
347
|
+
</div>
|
|
348
|
+
|
|
349
|
+
<div class="grid max-w-xl gap-3 rounded-lg border border-border p-4">
|
|
350
|
+
<div>
|
|
351
|
+
<h4 class="text-sm font-medium text-foreground">${q(`fontSize`)}</h4>
|
|
352
|
+
<p class="mt-1 text-xs text-muted-foreground">${q(`fontSizeDescription`)}</p>
|
|
353
|
+
</div>
|
|
354
|
+
<label class="grid max-w-xs gap-1.5 text-sm">
|
|
355
|
+
<span class="text-foreground">${q(`baseFontSize`)}</span>
|
|
356
|
+
<input
|
|
357
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
358
|
+
type="number"
|
|
359
|
+
min="12"
|
|
360
|
+
max="18"
|
|
361
|
+
step="1"
|
|
362
|
+
.value=${String(this.baseFontSizePx)}
|
|
363
|
+
@input=${e=>this.updateBaseFontSize(e.target.value)}
|
|
364
|
+
/>
|
|
365
|
+
</label>
|
|
366
|
+
<label class="grid max-w-xs gap-1.5 text-sm">
|
|
367
|
+
<span class="text-foreground">${q(`bodyFontSize`)}</span>
|
|
368
|
+
<input
|
|
369
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
370
|
+
type="number"
|
|
371
|
+
min="11"
|
|
372
|
+
max="16"
|
|
373
|
+
step="1"
|
|
374
|
+
.value=${String(this.bodyFontSizePx)}
|
|
375
|
+
@input=${e=>this.updateBodyFontSize(e.target.value)}
|
|
376
|
+
/>
|
|
377
|
+
<span class="text-xs text-muted-foreground">${q(`bodyFontSizeNote`)}</span>
|
|
378
|
+
</label>
|
|
379
|
+
</div>
|
|
380
|
+
|
|
381
|
+
<div class="grid max-w-xl gap-3 rounded-lg border border-border p-4">
|
|
382
|
+
<div>
|
|
383
|
+
<h4 class="text-sm font-medium text-foreground">${q(`contextManagement`)}</h4>
|
|
384
|
+
<p class="mt-1 text-xs text-muted-foreground">${q(`autoCompactDescription`)}</p>
|
|
385
|
+
</div>
|
|
386
|
+
<label class="flex items-center gap-2 text-sm text-foreground">
|
|
387
|
+
<input
|
|
388
|
+
type="checkbox"
|
|
389
|
+
class="size-4 rounded border-input"
|
|
390
|
+
.checked=${this.autoCompactEnabled}
|
|
391
|
+
@change=${e=>this.updateAutoCompactEnabled(e.target.checked)}
|
|
392
|
+
/>
|
|
393
|
+
<span>${q(`autoCompactEnabled`)}</span>
|
|
394
|
+
</label>
|
|
395
|
+
<p class="text-xs text-muted-foreground">${q(`autoCompactTriggerNote`)}</p>
|
|
396
|
+
<label class="flex items-center gap-2 text-sm text-foreground">
|
|
397
|
+
<input
|
|
398
|
+
type="checkbox"
|
|
399
|
+
class="size-4 rounded border-input disabled:opacity-60"
|
|
400
|
+
.checked=${this.autoCompactRequireConfirmation}
|
|
401
|
+
?disabled=${!this.autoCompactEnabled}
|
|
402
|
+
@change=${e=>this.updateAutoCompactRequireConfirmation(e.target.checked)}
|
|
403
|
+
/>
|
|
404
|
+
<span>${q(`autoCompactRequireConfirmation`)}</span>
|
|
405
|
+
</label>
|
|
406
|
+
<label class="grid max-w-xs gap-1.5 text-sm">
|
|
407
|
+
<span class="text-foreground">${q(`autoCompactThresholdPercent`)}</span>
|
|
408
|
+
<input
|
|
409
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm disabled:opacity-60"
|
|
410
|
+
type="number"
|
|
411
|
+
min="50"
|
|
412
|
+
max="95"
|
|
413
|
+
step="1"
|
|
414
|
+
.value=${this.autoCompactThresholdPercentInput}
|
|
415
|
+
?disabled=${!this.autoCompactEnabled}
|
|
416
|
+
@input=${e=>this.updateAutoCompactThresholdPercent(e.target.value)}
|
|
417
|
+
/>
|
|
418
|
+
</label>
|
|
419
|
+
<label class="grid max-w-xs gap-1.5 text-sm">
|
|
420
|
+
<span class="text-foreground">${q(`autoCompactKeepRecentTurns`)}</span>
|
|
421
|
+
<input
|
|
422
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm disabled:opacity-60"
|
|
423
|
+
type="number"
|
|
424
|
+
min="1"
|
|
425
|
+
max="20"
|
|
426
|
+
step="1"
|
|
427
|
+
.value=${String(this.autoCompactKeepRecentTurns)}
|
|
428
|
+
?disabled=${!this.autoCompactEnabled}
|
|
429
|
+
@input=${e=>this.updateAutoCompactKeepRecentTurns(e.target.value)}
|
|
430
|
+
/>
|
|
431
|
+
<span class="text-xs text-muted-foreground">${q(`autoCompactHistoryPreserved`)}</span>
|
|
432
|
+
</label>
|
|
433
|
+
</div>
|
|
434
|
+
|
|
435
|
+
<div class="flex items-center gap-3">
|
|
436
|
+
<button
|
|
437
|
+
class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground disabled:opacity-60"
|
|
438
|
+
type="button"
|
|
439
|
+
?disabled=${!this.selectedModel}
|
|
440
|
+
@click=${()=>this.save()}
|
|
441
|
+
>
|
|
442
|
+
${q(`saveDefaultOptions`)}
|
|
443
|
+
</button>
|
|
444
|
+
${this.saved?z`<span class="text-sm text-muted-foreground">${q(`defaultOptionsSaved`)}</span>`:null}
|
|
445
|
+
${this.error?z`<span class="text-sm text-destructive">${this.error}</span>`:null}
|
|
446
|
+
</div>
|
|
447
|
+
</div>
|
|
448
|
+
`}},ls=`quickforge-default-options-settings-tab`;customElements.get(ls)||customElements.define(ls,cs);function us(){return document.createElement(ls)}var ds=`quickforge-backup`,fs=[{id:`settings`,countKey:`settings`,label:()=>q(`restoreSettings`),description:()=>q(`restoreSettingsDescription`)},{id:`providerKeys`,countKey:`providerKeys`,label:()=>q(`restoreProviderKeys`),description:()=>q(`restoreProviderKeysDescription`)},{id:`customProviders`,countKey:`customProviders`,label:()=>q(`restoreCustomProviders`),description:()=>q(`restoreCustomProvidersDescription`)},{id:`projects`,countKey:`projects`,label:()=>q(`restoreProjects`),description:()=>q(`restoreProjectsDescription`)},{id:`scheduledTasks`,countKey:`scheduledTasks`,label:()=>q(`restoreScheduledTasks`),description:()=>q(`restoreScheduledTasksDescription`)},{id:`conversations`,countKey:`sessions`,label:()=>q(`restoreConversations`),description:()=>q(`restoreConversationsDescription`)}];function ps(e,t){let n=new Blob([`${JSON.stringify(t,null,2)}\n`],{type:`application/json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=e,document.body.appendChild(i),i.click(),i.remove(),URL.revokeObjectURL(r)}function ms(){return new Date().toISOString().replace(/[:.]/g,`-`)}function hs(e){return e?Object.entries(e).map(([e,t])=>`${e}: ${t}`).join(`, `):``}function gs(e){return fs.filter(t=>(e.sections?.[t.countKey]??0)>0)}var _s=class extends we{exportScope=`all`;includeSecrets=!1;busy=!1;message=``;error=``;safetyBackupPath=``;pendingImport=null;getTabName(){return q(`backupRestore`)}setScope(e){this.exportScope=e===`config`||e===`sessions`?e:`all`,this.exportScope===`sessions`&&(this.includeSecrets=!1),this.clearStatus(),this.requestUpdate()}clearStatus(){this.message=``,this.error=``,this.safetyBackupPath=``}setIncludeSecrets(e){this.includeSecrets=e&&this.exportScope!==`sessions`,this.message=``,this.error=``,this.requestUpdate()}async exportBackup(){if(!(this.includeSecrets&&!await lt({description:q(`backupExportSecretsConfirm`),confirmLabel:q(`exportBackup`),cancelLabel:q(`cancel`)}))){this.busy=!0,this.clearStatus(),this.requestUpdate();try{let e=new URLSearchParams({scope:this.exportScope,includeSecrets:this.includeSecrets?`1`:`0`}),t=await fetch(`/api/backup/export?${e.toString()}`,{cache:`no-store`}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||q(`backupExportFailed`));let r=this.includeSecrets?`with-secrets`:`no-secrets`;ps(`${ds}-${this.exportScope}-${r}-${ms()}.json`,n),this.message=q(`backupExported`)}catch(e){this.error=e instanceof Error?e.message:q(`backupExportFailed`)}finally{this.busy=!1,this.requestUpdate()}}}async inspectBackup(e){let t=await fetch(`/api/backup/inspect`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e)}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||q(`backupInspectFailed`));if(!n)throw Error(q(`backupInspectFailed`));return n}async importBackupFromFile(e){this.busy=!0,this.clearStatus(),this.pendingImport=null,this.requestUpdate();try{let t=await e.text(),n=JSON.parse(t),r=await this.inspectBackup(n),i=new Set(gs(r).map(e=>e.id));this.pendingImport={backup:n,inspect:r,selectedSections:i},this.message=q(`backupInspected`)}catch(e){this.error=e instanceof Error?e.message:q(`backupImportFailed`)}finally{this.busy=!1,this.requestUpdate()}}togglePendingSection(e,t){this.pendingImport&&(t?this.pendingImport.selectedSections.add(e):this.pendingImport.selectedSections.delete(e),this.message=``,this.error=``,this.requestUpdate())}cancelPendingImport(){this.pendingImport=null,this.message=``,this.error=``,this.requestUpdate()}async confirmPendingImport(){if(this.pendingImport){if(this.pendingImport.selectedSections.size===0){this.error=q(`selectAtLeastOneRestoreSection`),this.requestUpdate();return}this.busy=!0,this.clearStatus(),this.requestUpdate();try{let e=await fetch(`/api/backup/import`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({backup:this.pendingImport.backup,sections:[...this.pendingImport.selectedSections]})}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||q(`backupImportFailed`));let n=hs(t?.summary);this.safetyBackupPath=t?.safetyBackupPath||``,this.pendingImport=null,this.message=n?`${q(`backupImported`)} ${n}`:q(`backupImported`),window.setTimeout(()=>window.location.reload(),1500)}catch(e){this.error=e instanceof Error?e.message:q(`backupImportFailed`)}finally{this.busy=!1,this.requestUpdate()}}}handleFileChange(e){let t=e.target,n=t.files?.[0];t.value=``,n&&this.importBackupFromFile(n)}renderPendingImport(){if(!this.pendingImport)return null;let{inspect:e,selectedSections:t}=this.pendingImport,n=gs(e);return z`
|
|
449
|
+
<section class="rounded-lg border border-amber-500/30 bg-amber-500/5 p-4">
|
|
450
|
+
<h4 class="text-sm font-semibold text-foreground">${q(`backupInspectTitle`)}</h4>
|
|
451
|
+
<dl class="mt-3 grid gap-1 text-sm text-muted-foreground">
|
|
452
|
+
<div><span class="text-foreground">${q(`backupInspectExportedAt`)}:</span> ${e.exportedAt||`-`}</div>
|
|
453
|
+
<div><span class="text-foreground">${q(`backupInspectVersion`)}:</span> ${e.version??`-`}</div>
|
|
454
|
+
<div><span class="text-foreground">${q(`backupInspectScope`)}:</span> ${e.scope||`-`}</div>
|
|
455
|
+
<div><span class="text-foreground">${q(`backupInspectSecrets`)}:</span> ${e.includeSecrets?q(`yes`):q(`no`)}</div>
|
|
456
|
+
</dl>
|
|
457
|
+
|
|
458
|
+
${e.warnings?.length?z`
|
|
459
|
+
<div class="mt-3 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-xs text-amber-700 dark:text-amber-300">
|
|
460
|
+
${e.warnings.map(e=>z`<div>⚠ ${e}</div>`)}
|
|
461
|
+
</div>
|
|
462
|
+
`:null}
|
|
463
|
+
|
|
464
|
+
<div class="mt-4">
|
|
465
|
+
<div class="text-sm font-medium text-foreground">${q(`selectRestoreSections`)}</div>
|
|
466
|
+
<div class="mt-2 grid gap-2">
|
|
467
|
+
${n.map(n=>z`
|
|
468
|
+
<label class="flex items-start gap-2 rounded-md border border-border bg-background/60 p-3 text-sm">
|
|
469
|
+
<input
|
|
470
|
+
class="mt-1"
|
|
471
|
+
type="checkbox"
|
|
472
|
+
.checked=${t.has(n.id)}
|
|
473
|
+
?disabled=${this.busy}
|
|
474
|
+
@change=${e=>this.togglePendingSection(n.id,e.target.checked)}
|
|
475
|
+
/>
|
|
476
|
+
<span>
|
|
477
|
+
<span class="block text-foreground">${n.label()} (${e.sections?.[n.countKey]??0})</span>
|
|
478
|
+
<span class="block text-xs text-muted-foreground">${n.description()}</span>
|
|
479
|
+
</span>
|
|
480
|
+
</label>
|
|
481
|
+
`)}
|
|
482
|
+
</div>
|
|
483
|
+
</div>
|
|
484
|
+
|
|
485
|
+
<div class="mt-4 flex flex-wrap gap-2">
|
|
486
|
+
<button
|
|
487
|
+
class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground disabled:opacity-60"
|
|
488
|
+
type="button"
|
|
489
|
+
?disabled=${this.busy||t.size===0}
|
|
490
|
+
@click=${()=>this.confirmPendingImport()}
|
|
491
|
+
>
|
|
492
|
+
${this.busy?q(`loading`):q(`confirmImportSelected`)}
|
|
493
|
+
</button>
|
|
494
|
+
<button
|
|
495
|
+
class="rounded-md border border-input px-3 py-2 text-sm hover:bg-muted/60 disabled:opacity-60"
|
|
496
|
+
type="button"
|
|
497
|
+
?disabled=${this.busy}
|
|
498
|
+
@click=${()=>this.cancelPendingImport()}
|
|
499
|
+
>
|
|
500
|
+
${q(`cancel`)}
|
|
501
|
+
</button>
|
|
502
|
+
</div>
|
|
503
|
+
</section>
|
|
504
|
+
`}render(){return z`
|
|
505
|
+
<div class="flex flex-col gap-6">
|
|
506
|
+
<div>
|
|
507
|
+
<h3 class="mb-2 text-sm font-semibold text-foreground">${q(`backupRestore`)}</h3>
|
|
508
|
+
<p class="text-sm text-muted-foreground">${q(`backupRestoreDescription`)}</p>
|
|
509
|
+
</div>
|
|
510
|
+
|
|
511
|
+
<section class="rounded-lg border border-border p-4">
|
|
512
|
+
<h4 class="text-sm font-semibold text-foreground">${q(`exportData`)}</h4>
|
|
513
|
+
<p class="mt-1 text-sm text-muted-foreground">${q(`exportDataDescription`)}</p>
|
|
514
|
+
|
|
515
|
+
<label class="mt-4 grid max-w-sm gap-1.5 text-sm">
|
|
516
|
+
<span class="text-foreground">${q(`exportScope`)}</span>
|
|
517
|
+
<select
|
|
518
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
519
|
+
.value=${this.exportScope}
|
|
520
|
+
?disabled=${this.busy}
|
|
521
|
+
@change=${e=>this.setScope(e.target.value)}
|
|
522
|
+
>
|
|
523
|
+
<option value="all">${q(`exportScopeAll`)}</option>
|
|
524
|
+
<option value="config">${q(`exportScopeConfig`)}</option>
|
|
525
|
+
<option value="sessions">${q(`exportScopeSessions`)}</option>
|
|
526
|
+
</select>
|
|
527
|
+
</label>
|
|
528
|
+
|
|
529
|
+
<label class="mt-4 flex max-w-sm items-start gap-2 text-sm text-foreground ${this.exportScope===`sessions`?`opacity-60`:``}">
|
|
530
|
+
<input
|
|
531
|
+
class="mt-1"
|
|
532
|
+
type="checkbox"
|
|
533
|
+
.checked=${this.includeSecrets}
|
|
534
|
+
?disabled=${this.busy||this.exportScope===`sessions`}
|
|
535
|
+
@change=${e=>this.setIncludeSecrets(e.target.checked)}
|
|
536
|
+
/>
|
|
537
|
+
<span>
|
|
538
|
+
<span class="block">${q(`includeApiKeys`)}</span>
|
|
539
|
+
<span class="block text-xs text-muted-foreground">${q(`includeApiKeysDescription`)}</span>
|
|
540
|
+
</span>
|
|
541
|
+
</label>
|
|
542
|
+
|
|
543
|
+
<button
|
|
544
|
+
class="mt-4 rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground disabled:opacity-60"
|
|
545
|
+
type="button"
|
|
546
|
+
?disabled=${this.busy}
|
|
547
|
+
@click=${()=>this.exportBackup()}
|
|
548
|
+
>
|
|
549
|
+
${this.busy?q(`loading`):q(`exportBackup`)}
|
|
550
|
+
</button>
|
|
551
|
+
</section>
|
|
552
|
+
|
|
553
|
+
<section class="rounded-lg border border-border p-4">
|
|
554
|
+
<h4 class="text-sm font-semibold text-foreground">${q(`importData`)}</h4>
|
|
555
|
+
<p class="mt-1 text-sm text-muted-foreground">${q(`importDataDescription`)}</p>
|
|
556
|
+
|
|
557
|
+
<label class="mt-4 inline-flex cursor-pointer rounded-md border border-input px-3 py-2 text-sm hover:bg-muted/60 ${this.busy?`pointer-events-none opacity-60`:``}">
|
|
558
|
+
<input
|
|
559
|
+
class="hidden"
|
|
560
|
+
type="file"
|
|
561
|
+
accept="application/json,.json"
|
|
562
|
+
?disabled=${this.busy}
|
|
563
|
+
@change=${e=>this.handleFileChange(e)}
|
|
564
|
+
/>
|
|
565
|
+
${q(`importBackup`)}
|
|
566
|
+
</label>
|
|
567
|
+
</section>
|
|
568
|
+
|
|
569
|
+
${this.renderPendingImport()}
|
|
570
|
+
${this.message?z`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
|
|
571
|
+
${this.safetyBackupPath?z`<div class="rounded-md border border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground">${q(`backupSafetyBackupPath`)}: <code>${this.safetyBackupPath}</code></div>`:null}
|
|
572
|
+
${this.error?z`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
|
|
573
|
+
</div>
|
|
574
|
+
`}},vs=`quickforge-backup-settings-tab`;customElements.get(vs)||customElements.define(vs,_s);function ys(){return document.createElement(vs)}var bs=3e4,xs=800;function Ss(e){return new Promise(t=>window.setTimeout(t,e))}function Cs(e){if(!e)return`-`;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString(He())}function ws(){return`custom_${globalThis.crypto?.randomUUID?.().slice(0,8)||Date.now().toString(36)}`}function Ts(e){let t=e.trim(),n=t.split(/[\\/]/).pop()?.replace(/^"|"$/g,``)||t;return/^bash(\.exe)?$/i.test(n)?`Bash`:/^zsh$/i.test(n)?`Zsh`:/^fish$/i.test(n)?`Fish`:/^cmd(\.exe)?$/i.test(n)?`Command Prompt`:/^powershell(\.exe)?$/i.test(n)?`Windows PowerShell`:/^pwsh(\.exe)?$/i.test(n)?`PowerShell 7+`:n||`Custom Shell`}var Es=z`
|
|
575
|
+
<svg class="size-3.5" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
576
|
+
<path d="M3.5 8.2 6.6 11.3 12.7 4.7" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
|
|
577
|
+
</svg>
|
|
578
|
+
`,Ds=z`
|
|
579
|
+
<svg class="size-3.5" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
580
|
+
<circle cx="8" cy="8" r="4.8" stroke="currentColor" stroke-width="1.5" />
|
|
581
|
+
</svg>
|
|
582
|
+
`,Os=z`
|
|
583
|
+
<svg class="size-3.5" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
584
|
+
<path d="M4.5 4.5 11.5 11.5M11.5 4.5 4.5 11.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" />
|
|
585
|
+
</svg>
|
|
586
|
+
`,ks=class extends we{status;loading=!0;restarting=!1;message=``;error=``;terminalShellConfig={terminalShell:`auto`,defaultProfileId:`auto`,profiles:[]};customShellCommand=``;getTabName(){return q(`backendService`)}async connectedCallback(){super.connectedCallback(),await Promise.all([this.loadStatus(),this.loadTerminalShell()])}customShellProfiles(){return this.terminalShellConfig.profiles.filter(e=>!e.builtin)}async loadTerminalShell(){try{let e=await fetch(`/api/system/terminal-shell`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||q(`requestFailed`));this.terminalShellConfig={terminalShell:t?.terminalShell||`auto`,defaultProfileId:t?.defaultProfileId||`auto`,profiles:Array.isArray(t?.profiles)?t.profiles:[]}}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.requestUpdate()}}async saveTerminalShellConfig(e,t=this.customShellProfiles(),n=q(`terminalShellSaved`)){try{let r=await fetch(`/api/system/terminal-shell`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({defaultProfileId:e,profiles:t})}),i=await r.json().catch(()=>null);if(!r.ok)throw Error(i?.error||q(`requestFailed`));this.terminalShellConfig=i,this.message=n,this.error=``}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.requestUpdate()}}async addCustomTerminalShell(){let e=this.customShellCommand.trim();if(!e){this.error=q(`terminalShellProfileRequired`),this.requestUpdate();return}let t=[...this.customShellProfiles(),{id:ws(),name:Ts(e),command:e,builtin:!1}];this.customShellCommand=``,await this.saveTerminalShellConfig(this.terminalShellConfig.defaultProfileId,t,q(`terminalShellProfilesSaved`))}async deleteCustomTerminalShell(e){let t=this.terminalShellConfig.profiles.find(t=>t.id===e);if(!t||t.builtin||!await lt({description:q(`terminalShellDeleteConfirm`,{name:t.name}),confirmLabel:q(`confirmDelete`),cancelLabel:q(`cancel`),variant:`destructive`}))return;let n=this.customShellProfiles().filter(t=>t.id!==e),r=this.terminalShellConfig.defaultProfileId===e?`auto`:this.terminalShellConfig.defaultProfileId;await this.saveTerminalShellConfig(r,n,q(`terminalShellProfilesSaved`))}async loadStatus(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=await fetch(`/api/health`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||q(`requestFailed`));this.status=t}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}async pollUntilRestarted(e){let t=Date.now();for(;Date.now()-t<bs;){await Ss(xs);try{let t=await fetch(`/api/health?restartPoll=${Date.now()}`,{cache:`no-store`}),n=await t.json().catch(()=>null);if(t.ok&&n?.ok&&n.bootId&&n.bootId!==e){this.message=q(`backendRestarted`),this.requestUpdate(),window.setTimeout(()=>window.location.reload(),300);return}}catch{}}throw Error(q(`backendRestartTimeout`))}async restartService(){if(!this.status||this.restarting||!await lt({description:q(`restartBackendConfirm`),confirmLabel:q(`restartBackendService`),cancelLabel:q(`cancel`)}))return;this.restarting=!0,this.message=q(`backendRestarting`),this.error=``,this.requestUpdate();let e=this.status.bootId;try{let t=await fetch(`/api/system/restart`,{method:`POST`,headers:{"x-quickforge-action":`restart`}}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||q(`backendRestartFailed`));await this.pollUntilRestarted(e)}catch(e){this.error=e instanceof Error?e.message:q(`backendRestartFailed`),this.message=``,this.restarting=!1,this.requestUpdate()}}statusRows(){return this.status?z`
|
|
587
|
+
<dl class="grid gap-3 text-sm">
|
|
588
|
+
${[[q(`serviceMode`),this.status.mode],[q(`servicePid`),String(this.status.pid)],[q(`serviceStartedAt`),Cs(this.status.startedAt)],[q(`serviceDataDir`),this.status.dataDir],[q(`serviceWorkspace`),this.status.workspaceRoot]].map(([e,t])=>z`
|
|
589
|
+
<div class="grid gap-1 sm:grid-cols-[120px_1fr] sm:gap-3">
|
|
590
|
+
<dt class="text-muted-foreground">${e}</dt>
|
|
591
|
+
<dd class="min-w-0 break-all text-foreground">${t}</dd>
|
|
592
|
+
</div>
|
|
593
|
+
`)}
|
|
594
|
+
</dl>
|
|
595
|
+
`:null}shellProfileRow(e,t=!1){let n=e.id===this.terminalShellConfig.defaultProfileId||this.terminalShellConfig.defaultProfileId===`auto`&&t;return z`
|
|
596
|
+
<div class="flex min-w-0 items-center gap-3 border-b px-1.5 py-2 last:border-b-0 hover:bg-muted/5" style="border-bottom-color: color-mix(in oklab, var(--border) 32%, transparent);">
|
|
597
|
+
<div class="min-w-0 flex-1">
|
|
598
|
+
<div class="truncate text-sm font-medium text-foreground/90">${e.name}</div>
|
|
599
|
+
<div class="truncate font-mono text-xs text-muted-foreground/55" title=${e.command}>${e.command}</div>
|
|
600
|
+
</div>
|
|
601
|
+
<div class="flex shrink-0 items-center gap-1">
|
|
602
|
+
${n?z`
|
|
603
|
+
<span class="inline-flex size-7 items-center justify-center rounded-md text-emerald-500/85" title=${q(`terminalShellDefaultBadge`)} aria-label=${q(`terminalShellDefaultBadge`)}>
|
|
604
|
+
${Es}
|
|
605
|
+
</span>
|
|
606
|
+
`:z`
|
|
607
|
+
<button
|
|
608
|
+
class="inline-flex size-7 items-center justify-center rounded-md text-muted-foreground/55 hover:bg-muted/20 hover:text-foreground/85"
|
|
609
|
+
type="button"
|
|
610
|
+
title=${q(`terminalShellSetDefault`)}
|
|
611
|
+
aria-label=${q(`terminalShellSetDefault`)}
|
|
612
|
+
@click=${()=>this.saveTerminalShellConfig(e.id)}
|
|
613
|
+
>
|
|
614
|
+
${Ds}
|
|
615
|
+
</button>
|
|
616
|
+
`}
|
|
617
|
+
${e.builtin?null:z`
|
|
618
|
+
<button
|
|
619
|
+
class="inline-flex size-7 items-center justify-center rounded-md text-muted-foreground/55 hover:bg-destructive/10 hover:text-destructive"
|
|
620
|
+
type="button"
|
|
621
|
+
title=${q(`delete`)}
|
|
622
|
+
aria-label=${q(`delete`)}
|
|
623
|
+
@click=${()=>this.deleteCustomTerminalShell(e.id)}
|
|
624
|
+
>
|
|
625
|
+
${Os}
|
|
626
|
+
</button>
|
|
627
|
+
`}
|
|
628
|
+
</div>
|
|
629
|
+
</div>
|
|
630
|
+
`}terminalShellSettings(){let e=this.terminalShellConfig.profiles;return z`
|
|
631
|
+
<section class="rounded-lg border border-border p-4">
|
|
632
|
+
<div>
|
|
633
|
+
<h4 class="text-sm font-semibold text-foreground">${q(`terminalShell`)}</h4>
|
|
634
|
+
<p class="mt-1 max-w-2xl text-sm text-muted-foreground">${q(`terminalShellDescription`)}</p>
|
|
635
|
+
<p class="mt-1 text-xs text-muted-foreground/60">${q(`terminalShellAutoDetectedHint`)}</p>
|
|
636
|
+
</div>
|
|
637
|
+
|
|
638
|
+
<div class="mt-4 overflow-hidden rounded-lg border bg-transparent" style="border-color: color-mix(in oklab, var(--border) 36%, transparent);">
|
|
639
|
+
${e.length>0?e.map((e,t)=>this.shellProfileRow(e,t===0)):z`<div class="px-2 py-3 text-sm text-muted-foreground">${q(`terminalShellNoDetected`)}</div>`}
|
|
640
|
+
</div>
|
|
641
|
+
|
|
642
|
+
<div class="mt-3 grid gap-2 sm:grid-cols-[1fr_auto] sm:items-end">
|
|
643
|
+
<label class="grid gap-1 text-sm">
|
|
644
|
+
<span class="text-xs text-muted-foreground/70">${q(`terminalShellCommand`)}</span>
|
|
645
|
+
<input
|
|
646
|
+
class="h-9 rounded-md border border-border bg-background px-3 font-mono text-sm text-foreground outline-none focus:border-ring"
|
|
647
|
+
type="text"
|
|
648
|
+
.value=${this.customShellCommand}
|
|
649
|
+
placeholder=${q(`terminalShellCommandPlaceholder`)}
|
|
650
|
+
@input=${e=>{this.customShellCommand=e.target.value}}
|
|
651
|
+
/>
|
|
652
|
+
</label>
|
|
653
|
+
<button
|
|
654
|
+
class="h-9 rounded-md bg-primary px-3 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-60"
|
|
655
|
+
type="button"
|
|
656
|
+
title=${q(`terminalShellAdd`)}
|
|
657
|
+
aria-label=${q(`terminalShellAdd`)}
|
|
658
|
+
@click=${()=>this.addCustomTerminalShell()}
|
|
659
|
+
>
|
|
660
|
+
${q(`terminalShellAdd`)}
|
|
661
|
+
</button>
|
|
662
|
+
</div>
|
|
663
|
+
</section>
|
|
664
|
+
`}render(){if(this.loading)return z`<div class="text-sm text-muted-foreground">${q(`loading`)}</div>`;let e=this.status?.restartUnsupportedReason||q(`backendRestartUnsupported`),t=this.restarting||!this.status?.restartSupported;return z`
|
|
665
|
+
<div class="flex flex-col gap-6">
|
|
666
|
+
<div>
|
|
667
|
+
<h3 class="mb-2 text-sm font-semibold text-foreground">${q(`backendService`)}</h3>
|
|
668
|
+
<p class="text-sm text-muted-foreground">${q(`backendServiceDescription`)}</p>
|
|
669
|
+
</div>
|
|
670
|
+
|
|
671
|
+
<section class="rounded-lg border border-border p-4">
|
|
672
|
+
<h4 class="text-sm font-semibold text-foreground">${q(`backendServiceStatus`)}</h4>
|
|
673
|
+
<div class="mt-4">${this.statusRows()}</div>
|
|
674
|
+
</section>
|
|
675
|
+
|
|
676
|
+
${this.terminalShellSettings()}
|
|
677
|
+
|
|
678
|
+
<section class="rounded-lg border border-border p-4">
|
|
679
|
+
<h4 class="text-sm font-semibold text-foreground">${q(`restartBackendService`)}</h4>
|
|
680
|
+
<p class="mt-1 text-sm text-muted-foreground">${q(`restartBackendServiceDescription`)}</p>
|
|
681
|
+
|
|
682
|
+
${this.status?.restartSupported?null:z`<div class="mt-4 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-sm text-amber-700 dark:text-amber-300">${e}</div>`}
|
|
683
|
+
|
|
684
|
+
<button
|
|
685
|
+
class="mt-4 rounded-md bg-destructive px-3 py-2 text-sm text-destructive-foreground disabled:opacity-60"
|
|
686
|
+
type="button"
|
|
687
|
+
?disabled=${t}
|
|
688
|
+
@click=${()=>this.restartService()}
|
|
689
|
+
>
|
|
690
|
+
${this.restarting?q(`backendRestarting`):q(`restartBackendService`)}
|
|
691
|
+
</button>
|
|
692
|
+
</section>
|
|
693
|
+
|
|
694
|
+
${this.message?z`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
|
|
695
|
+
${this.error?z`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
|
|
696
|
+
</div>
|
|
697
|
+
`}},As=`quickforge-service-settings-tab`;customElements.get(As)||customElements.define(As,ks);function js(){return document.createElement(As)}function Ms(){return Array.from({length:16},()=>`ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#$%^&*`[Math.floor(Math.random()*65)]).join(``)}var Ns=class extends we{loading=!0;saving=!1;enabled=!1;hasPassword=!1;password=``;sessionTtlHours=12;activeTokenCount=0;lanUrls=[];error=``;message=``;getTabName(){return q(`lanAccess`)}async connectedCallback(){super.connectedCallback(),await this.loadStatus()}async request(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||q(`requestFailed`));return r}applyStatus(e){this.enabled=!!e.enabled,this.hasPassword=!!e.hasPassword,this.sessionTtlHours=Number(e.sessionTtlHours||12),this.activeTokenCount=Number(e.activeTokenCount||0),this.lanUrls=Array.isArray(e.lanUrls)?e.lanUrls:[]}async loadStatus(){this.loading=!0,this.error=``,this.requestUpdate();try{this.applyStatus(await this.request(`/api/lan-access/status`))}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}updatePassword(e){this.password=e,this.requestUpdate()}updateEnabled(e){this.enabled=e,this.requestUpdate()}updateTtl(e){this.sessionTtlHours=Number(e)||12,this.requestUpdate()}async saveSettings(){if(!this.saving){if(this.enabled&&!this.hasPassword&&!this.password.trim()){this.error=q(`lanAccessPasswordRequired`),this.requestUpdate();return}if(this.password.trim()&&this.password.trim().length<8){this.error=q(`lanAccessPasswordTooShort`),this.requestUpdate();return}if(!(this.enabled&&!await lt({description:q(`lanAccessEnableConfirm`),confirmLabel:q(`enabled`),cancelLabel:q(`cancel`)}))){this.saving=!0,this.error=``,this.message=``,this.requestUpdate();try{let e=await this.request(`/api/lan-access/settings`,{method:`PUT`,body:JSON.stringify({enabled:this.enabled,password:this.password.trim()||void 0,sessionTtlHours:this.sessionTtlHours})});this.applyStatus(e),this.password=``,this.message=q(`lanAccessSaved`)}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}}async revokeAll(){if(await lt({description:q(`lanAccessRevokeAllConfirm`),confirmLabel:q(`lanAccessRevokeAll`),cancelLabel:q(`cancel`),variant:`destructive`})){this.saving=!0,this.error=``,this.message=``,this.requestUpdate();try{let e=await this.request(`/api/lan-access/revoke-all`,{method:`POST`});this.applyStatus(e),this.message=q(`lanAccessRevoked`)}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}render(){return this.loading?z`<div class="text-sm text-muted-foreground">${q(`loading`)}</div>`:z`
|
|
698
|
+
<div class="flex flex-col gap-6">
|
|
699
|
+
<div>
|
|
700
|
+
<h3 class="mb-2 text-sm font-semibold text-foreground">${q(`lanAccess`)}</h3>
|
|
701
|
+
<p class="text-sm text-muted-foreground">${q(`lanAccessDescription`)}</p>
|
|
702
|
+
</div>
|
|
703
|
+
|
|
704
|
+
<section class="rounded-lg border border-amber-500/30 bg-amber-500/10 p-4 text-sm text-amber-800 dark:text-amber-200">
|
|
705
|
+
${q(`lanAccessRiskWarning`)}
|
|
706
|
+
</section>
|
|
707
|
+
|
|
708
|
+
<section class="rounded-lg border border-border p-4">
|
|
709
|
+
<h4 class="text-sm font-semibold text-foreground">${q(`lanAccessStatus`)}</h4>
|
|
710
|
+
<dl class="mt-4 grid gap-3 text-sm">
|
|
711
|
+
<div class="grid gap-1 sm:grid-cols-[140px_1fr] sm:gap-3">
|
|
712
|
+
<dt class="text-muted-foreground">${q(`lanAccessEnabled`)}</dt>
|
|
713
|
+
<dd>${this.enabled?q(`enabled`):q(`disabled`)}</dd>
|
|
714
|
+
</div>
|
|
715
|
+
<div class="grid gap-1 sm:grid-cols-[140px_1fr] sm:gap-3">
|
|
716
|
+
<dt class="text-muted-foreground">${q(`lanAccessPassword`)}</dt>
|
|
717
|
+
<dd>${this.hasPassword?q(`configured`):q(`notConfigured`)}</dd>
|
|
718
|
+
</div>
|
|
719
|
+
<div class="grid gap-1 sm:grid-cols-[140px_1fr] sm:gap-3">
|
|
720
|
+
<dt class="text-muted-foreground">${q(`lanAccessActiveDevices`)}</dt>
|
|
721
|
+
<dd>${this.activeTokenCount}</dd>
|
|
722
|
+
</div>
|
|
723
|
+
<div class="grid gap-1 sm:grid-cols-[140px_1fr] sm:gap-3">
|
|
724
|
+
<dt class="text-muted-foreground">${q(`lanAccessUrls`)}</dt>
|
|
725
|
+
<dd class="min-w-0 break-all">${this.lanUrls.length?this.lanUrls.map(e=>z`<div>${e}</div>`):`-`}</dd>
|
|
726
|
+
</div>
|
|
727
|
+
</dl>
|
|
728
|
+
</section>
|
|
729
|
+
|
|
730
|
+
<section class="rounded-lg border border-border p-4">
|
|
731
|
+
<label class="flex items-center gap-2 text-sm font-medium text-foreground">
|
|
732
|
+
<input type="checkbox" .checked=${this.enabled} @change=${e=>this.updateEnabled(e.target.checked)} />
|
|
733
|
+
${q(`lanAccessAllowFull`)}
|
|
734
|
+
</label>
|
|
735
|
+
|
|
736
|
+
<label class="mt-4 block text-sm font-medium text-foreground">
|
|
737
|
+
${q(`lanAccessPassword`)}
|
|
738
|
+
<div class="mt-2 flex flex-col gap-3 sm:flex-row">
|
|
739
|
+
<input class="h-10 min-w-0 flex-1 rounded-md border border-input bg-background px-3 text-sm" type="password" .value=${this.password} @input=${e=>this.updatePassword(e.target.value)} placeholder=${this.hasPassword?q(`lanAccessPasswordPlaceholderConfigured`):q(`lanAccessPasswordPlaceholder`)} />
|
|
740
|
+
<button class="rounded-md border border-input px-3 py-2 text-sm" type="button" @click=${()=>this.updatePassword(Ms())}>${q(`generatePassword`)}</button>
|
|
741
|
+
</div>
|
|
742
|
+
</label>
|
|
743
|
+
|
|
744
|
+
<label class="mt-4 block text-sm font-medium text-foreground">
|
|
745
|
+
${q(`lanAccessSessionTtl`)}
|
|
746
|
+
<select class="mt-2 h-10 w-full rounded-md border border-input bg-background px-3 text-sm" .value=${String(this.sessionTtlHours)} @change=${e=>this.updateTtl(e.target.value)}>
|
|
747
|
+
<option value="1">1 ${q(`hour`)}</option>
|
|
748
|
+
<option value="12">12 ${q(`hours`)}</option>
|
|
749
|
+
<option value="24">24 ${q(`hours`)}</option>
|
|
750
|
+
<option value="168">7 ${q(`days`)}</option>
|
|
751
|
+
</select>
|
|
752
|
+
</label>
|
|
753
|
+
|
|
754
|
+
<div class="mt-4 flex flex-wrap gap-2">
|
|
755
|
+
<button class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground disabled:opacity-60" type="button" ?disabled=${this.saving} @click=${()=>this.saveSettings()}>${this.saving?q(`saving`):q(`save`)}</button>
|
|
756
|
+
<button class="rounded-md border border-destructive/40 px-3 py-2 text-sm text-destructive disabled:opacity-60" type="button" ?disabled=${this.saving} @click=${()=>this.revokeAll()}>${q(`lanAccessRevokeAll`)}</button>
|
|
757
|
+
</div>
|
|
758
|
+
</section>
|
|
759
|
+
|
|
760
|
+
${this.message?z`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
|
|
761
|
+
${this.error?z`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
|
|
762
|
+
</div>
|
|
763
|
+
`}},Ps=`quickforge-lan-access-settings-tab`;customElements.get(Ps)||customElements.define(Ps,Ns);function Fs(){return document.createElement(Ps)}var Is=class extends pe{static properties={label:{type:String}};_open=!1;_popover=null;_hoverTimer;createRenderRoot(){return this}_clearHoverTimer(){this._hoverTimer&&=(clearTimeout(this._hoverTimer),void 0)}_openPopover(){this._clearHoverTimer(),!this._open&&(this._open=!0,this._renderPopover(),this._updateTriggerAria())}_closePopover(){this._clearHoverTimer(),this._open&&(this._open=!1,this._removePopover(),this._updateTriggerAria())}_togglePopover(){this._clearHoverTimer(),this._open?this._closePopover():this._openPopover()}_updateTriggerAria(){this.querySelector(`.quickforge-info-tip-trigger`)?.setAttribute(`aria-expanded`,this._open?`true`:`false`)}_renderPopover(){if(this._removePopover(),!this.label)return;let e=this.querySelector(`.quickforge-info-tip-trigger`);if(!e)return;let t=document.createElement(`div`);t.className=`quickforge-info-tip-popover`,t.setAttribute(`role`,`tooltip`),t.textContent=this.label,document.body.appendChild(t),this._popover=t,this._positionPopover(e,t)}_positionPopover(e,t){let n=e.getBoundingClientRect(),{width:r,height:i}=t.getBoundingClientRect(),a=n.left;a+r>window.innerWidth-8&&(a=window.innerWidth-r-8),a<8&&(a=8);let o=n.bottom+6;if(o+i>window.innerHeight-8){let e=n.top-6-i;o=e>8?e:n.bottom+6}t.style.top=`${Math.round(o)}px`,t.style.left=`${Math.round(a)}px`}_removePopover(){this._popover&&=(this._popover.remove(),null)}_handleEnter=()=>{this._clearHoverTimer(),this._hoverTimer=setTimeout(()=>this._openPopover(),150)};_handleLeave=()=>{this._clearHoverTimer(),this._hoverTimer=setTimeout(()=>this._closePopover(),120)};_handleFocus=()=>{this._clearHoverTimer(),this._openPopover()};_handleOutsidePointerDown=e=>{if(!this._open)return;let t=e.target;t&&(this.contains(t)||this._popover?.contains(t))||this._closePopover()};_handleKeyDown=e=>{!this._open||e.key!==`Escape`||(e.preventDefault(),e.stopPropagation(),this._closePopover())};_handleScrollOrResize=()=>{if(!this._open)return;let e=this.querySelector(`.quickforge-info-tip-trigger`);e&&this._popover&&this._positionPopover(e,this._popover)};connectedCallback(){super.connectedCallback(),document.addEventListener(`pointerdown`,this._handleOutsidePointerDown,!0),document.addEventListener(`keydown`,this._handleKeyDown,!0),window.addEventListener(`scroll`,this._handleScrollOrResize,!0),window.addEventListener(`resize`,this._handleScrollOrResize)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(`pointerdown`,this._handleOutsidePointerDown,!0),document.removeEventListener(`keydown`,this._handleKeyDown,!0),window.removeEventListener(`scroll`,this._handleScrollOrResize,!0),window.removeEventListener(`resize`,this._handleScrollOrResize),this._clearHoverTimer(),this._removePopover()}render(){return z`
|
|
764
|
+
<span class="quickforge-info-tip">
|
|
765
|
+
<button
|
|
766
|
+
type="button"
|
|
767
|
+
class="quickforge-info-tip-trigger"
|
|
768
|
+
aria-label=${q(`help`)}
|
|
769
|
+
aria-expanded="false"
|
|
770
|
+
@mouseenter=${this._handleEnter}
|
|
771
|
+
@mouseleave=${this._handleLeave}
|
|
772
|
+
@focus=${this._handleFocus}
|
|
773
|
+
@blur=${this._handleLeave}
|
|
774
|
+
@click=${this._togglePopover}
|
|
775
|
+
>
|
|
776
|
+
<svg
|
|
777
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
778
|
+
width="14"
|
|
779
|
+
height="14"
|
|
780
|
+
viewBox="0 0 24 24"
|
|
781
|
+
fill="none"
|
|
782
|
+
stroke="currentColor"
|
|
783
|
+
stroke-width="2"
|
|
784
|
+
stroke-linecap="round"
|
|
785
|
+
stroke-linejoin="round"
|
|
786
|
+
aria-hidden="true"
|
|
787
|
+
>
|
|
788
|
+
<circle cx="12" cy="12" r="10" />
|
|
789
|
+
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
|
|
790
|
+
<path d="M12 17h.01" />
|
|
791
|
+
</svg>
|
|
792
|
+
</button>
|
|
793
|
+
</span>
|
|
794
|
+
`}},Ls=`quickforge-info-tip`;customElements.get(Ls)||customElements.define(Ls,Is);var Rs=class extends we{loading=!0;saving=!1;saved=!1;error=``;message=``;projects=[];project;commandDir=``;commands=[];loadingCommands=!1;getTabName(){return q(`projectCommands`)}async connectedCallback(){super.connectedCallback(),await this.loadProjects()}async request(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||q(`requestFailed`));return r}async loadProjects(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=await this.request(`/api/project`);this.projects=e?.projects??(e?.project?[e.project]:[]),this.project=e?.project??this.projects[0],this.commandDir=typeof this.project?.commandDir==`string`?this.project.commandDir:``,await this.loadCommands()}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}selectProject(e){let t=e.target,n=this.projects.find(e=>e.id===t.value);n&&(this.project=n,this.commandDir=typeof n.commandDir==`string`?n.commandDir:``,this.saved=!1,this.message=``,this.error=``,this.commands=[],this.requestUpdate(),this.loadCommands())}async loadCommands(){if(this.project?.id){this.loadingCommands=!0,this.requestUpdate();try{let e=await this.request(`/api/project/commands?projectId=${encodeURIComponent(this.project.id)}`);this.commands=e?.commands??[]}catch{this.commands=[]}finally{this.loadingCommands=!1,this.requestUpdate()}}}updateCommandDir(e){this.commandDir=e,this.saved=!1,this.message=``,this.requestUpdate()}async save(){if(!(!this.project||this.saving)){this.saving=!0,this.saved=!1,this.error=``,this.message=``,this.requestUpdate();try{let e=await this.request(`/api/project/${encodeURIComponent(this.project.id)}/command-dir`,{method:`PUT`,body:JSON.stringify({commandDir:this.commandDir})});if(this.project=e?.project??this.project,this.project){let e=this.projects.findIndex(e=>e.id===this.project.id);e>=0&&(this.projects[e]=this.project)}this.commandDir=typeof this.project?.commandDir==`string`?this.project.commandDir:``,this.saved=!0,await this.loadCommands()}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}async openCommandDir(){if(this.project){this.error=``,this.message=``,this.requestUpdate();try{await this.request(`/api/project/open-path`,{method:`POST`,body:JSON.stringify({path:`.ai/commands`,projectId:this.project.id})})}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`),this.requestUpdate()}}}async createCommand(){if(!this.project)return;let e=window.prompt(q(`newCommandPrompt`));if(e?.trim()){this.error=``,this.message=``,this.requestUpdate();try{let t=await this.request(`/api/project/command`,{method:`POST`,body:JSON.stringify({name:e.trim(),projectId:this.project.id})});t.ok?(this.message=q(`commandCreated`,{name:t.name??e.trim()}),await this.loadCommands()):t.reason===`exists`?this.error=q(`commandAlreadyExists`,{name:t.name??e.trim()}):this.error=q(`invalidCommandName`)}catch(e){this.error=e instanceof Error?e.message:q(`requestFailed`)}finally{this.requestUpdate()}}}render(){return this.loading?z`<div class="text-sm text-muted-foreground">${q(`loading`)}</div>`:this.projects.length===0?z`
|
|
795
|
+
<div class="flex flex-col gap-3">
|
|
796
|
+
<h3 class="text-sm font-semibold text-foreground">${q(`projectCommands`)}</h3>
|
|
797
|
+
<p class="text-sm text-muted-foreground">${q(`selectProjectForCommands`)}</p>
|
|
798
|
+
${this.error?z`<div class="text-sm text-destructive">${this.error}</div>`:null}
|
|
799
|
+
</div>
|
|
800
|
+
`:z`
|
|
801
|
+
<div class="flex flex-col gap-6">
|
|
802
|
+
<div>
|
|
803
|
+
<h3 class="mb-2 text-sm font-semibold text-foreground">
|
|
804
|
+
${q(`projectCommands`)}
|
|
805
|
+
<quickforge-info-tip .label=${q(`projectCommandsDescription`)}></quickforge-info-tip>
|
|
806
|
+
</h3>
|
|
807
|
+
</div>
|
|
808
|
+
|
|
809
|
+
<div class="grid max-w-xl gap-1.5 text-sm">
|
|
810
|
+
<span class="text-foreground">${q(`project`)}</span>
|
|
811
|
+
<select
|
|
812
|
+
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
813
|
+
.value=${this.project?.id??``}
|
|
814
|
+
@change=${e=>this.selectProject(e)}
|
|
815
|
+
>
|
|
816
|
+
${this.projects.map(e=>z`<option value=${e.id} ?selected=${e.id===this.project?.id}>${e.name}</option>`)}
|
|
817
|
+
</select>
|
|
818
|
+
${this.project?.path?z`<span class="break-all text-xs text-muted-foreground">${this.project.path}</span>`:null}
|
|
819
|
+
</div>
|
|
820
|
+
|
|
821
|
+
<label class="grid max-w-xl gap-1.5 text-sm">
|
|
822
|
+
<span class="text-foreground">${q(`commandDirectories`)}</span>
|
|
823
|
+
<textarea
|
|
824
|
+
class="min-h-28 rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
825
|
+
.value=${this.commandDir}
|
|
826
|
+
placeholder=${q(`commandDirectoryPlaceholder`)}
|
|
827
|
+
@input=${e=>this.updateCommandDir(e.target.value)}
|
|
828
|
+
></textarea>
|
|
829
|
+
<span class="text-xs leading-5 text-muted-foreground">${q(`commandDirectoryHelp`)}</span>
|
|
830
|
+
</label>
|
|
831
|
+
|
|
832
|
+
<div class="rounded-lg border border-border p-4 text-xs leading-5 text-muted-foreground">
|
|
833
|
+
<div class="mb-1 font-medium text-foreground">${q(`commandDirectoryExamples`)}</div>
|
|
834
|
+
<ul class="list-disc space-y-1 pl-5">
|
|
835
|
+
<li>.ai/commands</li>
|
|
836
|
+
<li>.claude/commands</li>
|
|
837
|
+
<li>.opencode/commands</li>
|
|
838
|
+
<li>D:\\shared\\ai-commands</li>
|
|
839
|
+
</ul>
|
|
840
|
+
</div>
|
|
841
|
+
|
|
842
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
843
|
+
<button
|
|
844
|
+
class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground disabled:opacity-60"
|
|
845
|
+
type="button"
|
|
846
|
+
?disabled=${this.saving}
|
|
847
|
+
@click=${()=>this.save()}
|
|
848
|
+
>
|
|
849
|
+
${this.saving?q(`saving`):q(`save`)}
|
|
850
|
+
</button>
|
|
851
|
+
${this.saved?z`<span class="text-sm text-muted-foreground">${q(`projectCommandsSaved`)}</span>`:null}
|
|
852
|
+
${this.message?z`<span class="text-sm text-muted-foreground">${this.message}</span>`:null}
|
|
853
|
+
${this.error?z`<span class="text-sm text-destructive">${this.error}</span>`:null}
|
|
854
|
+
</div>
|
|
855
|
+
|
|
856
|
+
<section class="rounded-lg border border-border p-4">
|
|
857
|
+
<div class="mb-3 flex flex-wrap items-center justify-between gap-2">
|
|
858
|
+
<h4 class="text-sm font-semibold text-foreground">
|
|
859
|
+
${q(`loadedCommands`,{count:this.commands.length})}
|
|
860
|
+
</h4>
|
|
861
|
+
<div class="flex items-center gap-2">
|
|
862
|
+
<button
|
|
863
|
+
class="rounded-md border border-border px-3 py-1.5 text-xs text-foreground hover:bg-muted/50 disabled:opacity-60"
|
|
864
|
+
type="button"
|
|
865
|
+
?disabled=${this.loadingCommands}
|
|
866
|
+
@click=${()=>this.openCommandDir()}
|
|
867
|
+
>
|
|
868
|
+
${q(`openCommandDir`)}
|
|
869
|
+
</button>
|
|
870
|
+
<button
|
|
871
|
+
class="rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground hover:bg-primary/90 disabled:opacity-60"
|
|
872
|
+
type="button"
|
|
873
|
+
?disabled=${this.loadingCommands}
|
|
874
|
+
@click=${()=>this.createCommand()}
|
|
875
|
+
>
|
|
876
|
+
${q(`createCommand`)}
|
|
877
|
+
</button>
|
|
878
|
+
</div>
|
|
879
|
+
</div>
|
|
880
|
+
|
|
881
|
+
${this.loadingCommands?z`<div class="text-sm text-muted-foreground">${q(`loading`)}</div>`:this.commands.length===0?z`<p class="text-sm text-muted-foreground">${q(`noCommandsLoaded`)}</p>`:z`<ul class="grid gap-2">
|
|
882
|
+
${this.commands.map(e=>{let t=e.argumentHint?` ${e.argumentHint}`:``;return z`
|
|
883
|
+
<li class="grid gap-0.5 text-sm">
|
|
884
|
+
<span class="text-foreground">
|
|
885
|
+
<code class="text-xs">/${e.name}${t}</code>
|
|
886
|
+
${e.description?z` — <span class="text-muted-foreground">${e.description}</span>`:null}
|
|
887
|
+
</span>
|
|
888
|
+
${e.relativePath?z`<span class="text-xs text-muted-foreground">${e.relativePath}</span>`:null}
|
|
889
|
+
</li>
|
|
890
|
+
`})}
|
|
891
|
+
</ul>`}
|
|
892
|
+
</section>
|
|
893
|
+
</div>
|
|
894
|
+
`}},zs=`quickforge-project-commands-settings-tab`;customElements.get(zs)||customElements.define(zs,Rs);function Bs(){return document.createElement(zs)}var Vs=[`off`,`low`,`medium`,`high`,`xhigh`];function Hs(e){switch(e){case`low`:return q(`thinkingLow`);case`medium`:return q(`thinkingMedium`);case`high`:return q(`thinkingHigh`);case`xhigh`:return q(`thinkingXHigh`);default:return q(`thinkingOff`)}}function Us(e){return`${e.provider} / ${e.id}`}function Ws(e,t){let n=document.createElement(`button`);return n.type=`button`,n.className=e,n.textContent=t,n}var Gs=`<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.85 2.85 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg>`;function Ks(e,t,n,r,i={}){let a=t.map(e=>({provider:e.provider,id:e.id,model:e})),o=i.thinkingLevel??`off`,s=document.createElement(`div`);s.className=`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`;let c=document.createElement(`div`);c.className=`flex max-h-[80vh] w-full max-w-lg flex-col overflow-hidden rounded-lg border border-border bg-background text-foreground shadow-xl`;let l=document.createElement(`div`);l.className=`border-b border-border p-4`;let u=document.createElement(`div`);u.className=`mb-3 flex items-center justify-between gap-3`;let d=document.createElement(`div`);d.className=`text-sm font-semibold`,d.textContent=q(`selectCustomModel`);let f=Ws(`rounded-md px-2 py-1 text-sm text-muted-foreground hover:bg-secondary`,q(`close`));f.onclick=()=>s.remove(),u.append(d,f);let p=document.createElement(`input`);p.className=`w-full rounded-md border border-input bg-background px-3 py-2 text-sm`,p.placeholder=q(`searchModels`),l.append(u,p);let m=document.createElement(`div`);m.className=`mt-3 rounded-lg border border-border bg-muted/20 p-3`;let h=document.createElement(`div`);h.className=`text-xs font-medium text-muted-foreground`,h.textContent=q(`currentConfiguration`);let g=document.createElement(`div`);g.className=`mt-1 truncate text-sm font-medium`,g.textContent=e?Us(e):q(`noModelAdded`);let _=document.createElement(`div`);_.className=`mt-3 flex flex-wrap items-center gap-1.5`;let v=document.createElement(`span`);v.className=`mr-1 text-xs text-muted-foreground`,v.textContent=q(`thinkingLevel`);let y=()=>{if(_.replaceChildren(v),e?.reasoning!==!0){let e=document.createElement(`span`);e.className=`text-xs text-muted-foreground`,e.textContent=q(`thinkingNotSupported`),_.append(e);return}for(let e of Vs){let t=Ws(`rounded-full border px-2.5 py-1 text-xs transition-colors ${o===e?`border-primary bg-primary/10 text-primary`:`border-border text-muted-foreground hover:bg-muted hover:text-foreground`}`,Hs(e));t.onclick=()=>{o=e,i.onThinkingLevelSelect?.(e),y()},_.append(t)}};m.append(h,g,_),l.append(m),y();let b=document.createElement(`div`);b.className=`min-h-0 flex-1 overflow-y-auto`;let x=()=>{let t=p.value.trim().toLowerCase();b.replaceChildren();let c=a.filter(({model:e})=>t?Us(e).toLowerCase().includes(t):!0).sort((t,n)=>{let r=ke(e,t.model),i=ke(e,n.model);return r&&!i?-1:!r&&i?1:Us(t.model).localeCompare(Us(n.model))});if(c.length===0){let e=document.createElement(`div`);e.className=`p-8 text-center text-sm text-muted-foreground`,e.textContent=q(`noMatchingCustomModels`),b.append(e);return}for(let{model:t}of c){let a=Ws(`w-full border-b border-border px-4 py-3 text-left hover:bg-muted`,``),c=document.createElement(`div`);c.className=`flex items-center justify-between gap-2`;let l=document.createElement(`div`);l.className=`min-w-0 truncate text-sm font-medium`,l.textContent=t.id;let u=document.createElement(`div`);u.className=`flex shrink-0 items-center gap-1.5`;let d=document.createElement(`div`);if(d.className=`rounded-md border border-border px-2 py-0.5 text-xs text-muted-foreground`,d.textContent=t.provider,u.append(d),r){let e=document.createElement(`button`);e.type=`button`,e.className=`shrink-0 rounded p-0.5 text-muted-foreground hover:bg-secondary hover:text-foreground`,e.innerHTML=Gs,e.setAttribute(`aria-label`,q(`editModel`)),e.onclick=e=>{e.stopPropagation(),s.remove(),r(t)},u.append(e)}c.append(l,u);let f=document.createElement(`div`);if(f.className=`mt-1 text-xs text-muted-foreground`,f.textContent=`${t.api} · ${t.contextWindow}/${t.maxTokens}${t.reasoning?` · ${q(`thinkingSupported`)}`:``}`,ke(e,t)){let e=document.createElement(`span`);e.className=`ml-2 text-green-500`,e.textContent=`✓`,l.append(e)}a.append(c,f),a.onclick=()=>{!t.reasoning&&o!==`off`&&(o=`off`,i.onThinkingLevelSelect?.(`off`)),n(t),g.textContent=Us(t),s.remove()},b.append(a)}};p.oninput=x,s.onclick=e=>{e.target===s&&s.remove()},c.onclick=e=>e.stopPropagation(),c.append(l,b),s.append(c),document.body.append(s),x(),p.focus()}function qs({storageRef:e,activeModelRef:t,agentRef:n,createAgent:r,updateCurrentAgentModel:i,setChatPanelRevision:a,needsModelSetup:o,setNeedsModelSetup:s,setRestoredDraft:c,notifySettingsChanged:l}){let u=(0,W.useCallback)(async()=>{let o=e.current;if(!o)return!1;let c=await un(o);return c?(t.current=c,s(!1),await Qt(o,c),n.current?(i(c),a(e=>e+1)):await r({model:c,tools:[]},It(),{scope:`global`,attachToView:!0}),l(),!0):(s(!0),!1)},[e,t,n,r,i,a,s,l]),d=(0,W.useCallback)(e=>{_e.open([Zo(),us(),Jo(),Bs(),ys(),js(),Fs()],()=>{(o||!n.current)&&u().catch(e=>U.error(`Failed to activate configured model:`,e))}),window.setTimeout(()=>{let t=document.querySelector(`settings-dialog`);t&&(t.activeTabIndex=e===`defaults`?1:2,t.requestUpdate?.())},0)},[u,o,n]),f=(0,W.useCallback)(()=>{d(`customModels`)},[d]);return{activateConfiguredModel:u,openModelSettings:f,openDefaultOptionsSettings:(0,W.useCallback)(()=>{d(`defaults`)},[d]),activateLiteLlmExampleModel:(0,W.useCallback)(async()=>{let o=e.current;if(!o)return;let c=qt(Vt);await hn(o,Vt,c),await Qt(o,c),t.current=c,s(!1),n.current?(i(c),a(e=>e+1)):await r({model:c,tools:[]},It(),{scope:`global`,attachToView:!0}),l()},[e,t,n,r,i,a,s,l]),openCustomModelSelector:(0,W.useCallback)(async()=>{let r=e.current,o=n.current;if(!r||!o)return;let s=document.querySelector(`agent-interface message-editor textarea`)?.value??``,l=cn(await r.customProviders.getAll());if(l.length===0){await lt({description:q(`addCustomModelFirst`),confirmLabel:q(`modelSetupAddModel`),cancelLabel:q(`cancel`)})&&f();return}Ks(o.state.model??t.current,l,e=>{let n=e,l=n.reasoning?o.state.thinkingLevel:`off`;o.state.thinkingLevel!==l&&(o.state.thinkingLevel=l,o.updateThinkingLevel(l).catch(e=>{U.error(`Failed to sync thinking level to server:`,e)})),t.current=n,i(n),s&&c({id:Date.now(),sessionId:o.sessionId,text:s}),a(e=>e+1),Qt(r,n).catch(e=>{U.error(`Failed to save active model:`,e)})},async e=>{await _e.open([Zo(),us(),Jo(e.provider),Bs(),ys(),js(),Fs()]);let t=document.querySelector(`settings-dialog`);t&&(t.activeTabIndex=2,t.requestUpdate?.())},{thinkingLevel:o.state.thinkingLevel,onThinkingLevelSelect:e=>{o.state.thinkingLevel=e,o.updateThinkingLevel(e).catch(e=>{U.error(`Failed to sync thinking level to server:`,e)}),a(e=>e+1)}})},[e,t,n,i,a,c,f])}}function Js(){let e=new URL(window.location.href);e.searchParams.delete(`session`),window.history.replaceState({},``,e)}function Ys(e){return!!(e&&!e.state.isStreaming&&e.state.messages.length===0)}function Xs({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,switchActiveProject:m,closeWorkspacePage:h,setRestoredDraft:g}){let _=(0,W.useCallback)(async()=>{if(p){Z(q(`modelSetupRequired`));return}h(),!(Ys(o.current)&&r.current===`global`)&&(g(void 0),Js(),await s({scope:`global`}))},[o,r,p,g,h,s]),v=(0,W.useCallback)(async e=>{if(p){Z(q(`modelSetupRequired`));return}h();let t=e??n.current;t&&(Ys(o.current)&&r.current===`project`&&n.current?.id===t.id||(n.current?.id!==t.id&&await m(t.id),g(void 0),Js(),await s({scope:`project`,project:t})))},[n,o,r,p,g,h,s,m]),y=(0,W.useCallback)(async s=>{let p=o.current;if(!p)return;if(p.state.isStreaming){Z(q(`generationStillRunning`));return}let m=po(p.state.messages,s),h=m>=0?p.state.messages[m]:void 0;if(m<0||!h){Z(q(`noConversationTurnToRollback`));return}let _={id:Date.now(),sessionId:p.sessionId,text:mo(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){U.error(`Failed to rollback conversation:`,e),Z(e instanceof Error?e.message:q(`rollbackFailed`));return}u(v);let y=i.current?a.current.get(i.current):void 0;if(yo(v)&&y){_&&g(_),d(e=>e+1),l(y).catch(e=>U.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){let e=a.current.get(x);e?.unsubscribe(),e?.agent.dispose(),a.current.delete(x)}if(b&&x)try{await b.sessions.delete(x),await f({broadcast:!0})}catch(e){U.error(`Failed to delete rolled back empty session:`,e)}let E=It();await c({model:w,thinkingLevel:T,messages:[],tools:[]},E,{scope:S,project:C,attachToView:!0,title:`New chat`}),g({..._,sessionId:E}),d(e=>e+1)},[t,n,o,c,r,i,f,d,u,g,e,l,a]),b=(0,W.useCallback)(async e=>{try{await ho(e)}catch(e){throw U.error(`Failed to copy answer:`,e),Z(q(`copyFailed`)),e}},[]),x=(0,W.useCallback)(async i=>{let a=o.current;if(!a)return;if(a.state.isStreaming){Z(q(`generationStillRunning`));return}let s=a.state.messages.slice(0,i+1);if(!vo(s))return;let l=r.current,u=l===`project`?n.current:void 0,d=It(),p=go(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}),m&&f({broadcast:!0}).catch(e=>U.error(`Failed to refresh sessions:`,e))},[t,n,o,c,r,f,e]);return{startNewGlobalChat:_,startNewProjectChat:v,rollbackFromMessage:y,retryFromMessage:(0,W.useCallback)(async e=>{let t=o.current;if(!t)return;if(t.state.isStreaming){Z(q(`generationStillRunning`));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){U.error(`Failed to retry:`,e),Z(e instanceof Error?e.message:q(`retryFailed`));return}let s=i.current?a.current.get(i.current):void 0;s&&(l(s).catch(e=>U.error(`Failed to sync session UI after retry:`,e)),d(e=>e+1))},[o,i,d,u,l,a]),copyAnswer:b,forkFromMessage:x}}function Zs({activeProjectRef:e,refreshSessions:t,notifyProjectsChanged:n,setActiveProject:r,setProjects:i,setExpandedProjectIds:a,setChatPanelRevision:o}){return{deleteProjectInline:(0,W.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}),await t({broadcast:!0}),n(),e.current?.id===s&&(e.current=l.project,o(e=>e+1))},[e,t,n,r,i,a,o])}}function Qs({options:e,onResolve:t}){let n=(0,W.useRef)(null),[r,i]=(0,W.useState)(e.defaultValue??``),a=(0,W.useRef)(r);return(0,W.useEffect)(()=>{a.current=r},[r]),(0,W.useEffect)(()=>{n.current?.focus(),n.current?.select()},[]),(0,W.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,ot.createPortal)((0,Y.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,Y.jsxs)(`div`,{className:J(`w-full max-w-sm rounded-lg border border-border bg-background p-6 shadow-lg`,`mx-4`),children:[(0,Y.jsx)(`h2`,{className:`text-base font-semibold text-foreground`,children:e.title}),e.description?(0,Y.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:e.description}):null,(0,Y.jsx)(`div`,{className:`mt-4`,children:(0,Y.jsx)(pt,{ref:n,value:r,onChange:e=>i(e.target.value),placeholder:e.placeholder,className:`w-full`})}),(0,Y.jsxs)(`div`,{className:`mt-5 flex justify-end gap-2`,children:[(0,Y.jsx)(X,{variant:`outline`,size:`sm`,onClick:()=>t(null),children:e.cancelLabel??`Cancel`}),(0,Y.jsx)(X,{size:`sm`,onClick:()=>r.trim()?t(r.trim()):void 0,disabled:!r.trim(),children:e.confirmLabel??`Save`})]})]})}),document.body)}function $s(e){return new Promise(t=>{let n=document.createElement(`div`);document.body.appendChild(n);let r=(0,je.createRoot)(n);function i(){r.unmount(),setTimeout(()=>n.remove(),0)}function a(e){i(),t(e)}r.render((0,Y.jsx)(Qs,{options:e,onResolve:a}))})}function ec({storageRef:e,taskMapRef:t,currentSessionIdRef:n,loadAgentSession:r,setCurrentTitleRef:i,refreshSessions:a,closeWorkspacePage:o,startNewGlobalChat:s}){return{loadSession:(0,W.useCallback)(e=>{o(),r(e)},[r,o]),renameSession:(0,W.useCallback)(async(t,r)=>{let o=e.current;if(!o)return;let s=await $s({title:q(`renameSession`),description:q(`sessionName`),defaultValue:r,confirmLabel:q(`save`),cancelLabel:q(`cancel`)});if(!s||s===r)return;let c=await o.sessions.get(t);if(!c)return;let l=await o.sessions.getMetadata(t);l&&(await o.sessions.save(c,{...l,title:s}),await a({broadcast:!0}),n.current===t&&i(s))},[n,a,i,e]),togglePinSession:(0,W.useCallback)(async t=>{let n=e.current;if(!n)return;let r=await n.sessions.get(t);if(!r)return;let i=await n.sessions.getMetadata(t);if(!i)return;let o=i.pinnedAt?void 0:new Date().toISOString(),s={...r,pinnedAt:o},c={...i,pinnedAt:o};await n.sessions.save(s,c),await a({broadcast:!0})},[a,e]),deleteSession:(0,W.useCallback)(async r=>{let i=e.current;if(!i)return;let c=t.current.get(r);c?.unsubscribe(),c?.agent.dispose(),t.current.delete(r),await i.sessions.delete(r),await a({broadcast:!0}),n.current===r&&(o(),await s())},[n,a,o,s,e,t]),startNewGlobalSession:(0,W.useCallback)(()=>{o(),s()},[o,s])}}function tc({storageRef:e,yoloModeRef:t,setYoloMode:n,agentRef:r,setChatPanelRevision:i,notifySettingsChanged:a}){return{toggleYoloMode:(0,W.useCallback)(()=>{let o=e.current,s=r.current,c=t.current,l=!c;n(l),t.current=l;let u=()=>{t.current=c,n(c),i(e=>e+1)};(async()=>{try{s&&await s.updateYoloMode(l),o&&await pn(o,l),i(e=>e+1),a()}catch(e){U.error(`Failed to sync YOLO mode:`,e),u(),Z(e instanceof Error?e.message:q(`yoloModeSyncFailed`))}})()},[r,a,i,n,e,t])}}function nc(){let[e,t]=(0,W.useState)(!0),[n,r]=(0,W.useState)(!1),[i,a]=(0,W.useState)(!1),[o,s]=(0,W.useState)(!1),[c,l]=(0,W.useState)(!1),[u,d]=(0,W.useState)(),[f,p]=(0,W.useState)(!1),[m,h]=(0,W.useState)(!1),[g,_]=(0,W.useState)(!1),[v,y]=(0,W.useState)(`files`),[b,x]=(0,W.useState)(),[S,C]=(0,W.useState)(``),[w,T]=(0,W.useState)(!1),[E,D]=(0,W.useState)(),[O,k]=(0,W.useState)(!1),[ee,A]=(0,W.useState)(),[j,M]=(0,W.useState)(!1);return{sidebarOpen:e,setSidebarOpen:t,mobileSidebarOpen:n,setMobileSidebarOpen:r,projectsCollapsed:i,setProjectsCollapsed:a,conversationsCollapsed:o,setConversationsCollapsed:s,mcpServersDialogOpen:c,setMcpServersDialogOpen:l,skillsDialog:u,setSkillsDialog:d,shareDialogOpen:f,setShareDialogOpen:p,conversationMenuOpen:m,setConversationMenuOpen:h,workspaceInspectorOpen:g,setWorkspaceInspectorOpen:_,workspacePanelView:v,setWorkspacePanelView:y,workspaceInspectorFocusTarget:b,setWorkspaceInspectorFocusTarget:x,webPreviewUrl:S,setWebPreviewUrl:C,inlineReaderOpen:w,setInlineReaderOpen:T,inlineReaderFile:E,setInlineReaderFile:D,inlineReaderLoading:O,setInlineReaderLoading:k,inlineReaderError:ee,setInlineReaderError:A,firstUseGuideDismissed:j,setFirstUseGuideDismissed:M,toggleProjectsCollapsed:(0,W.useCallback)(()=>a(e=>!e),[]),toggleConversationsCollapsed:(0,W.useCallback)(()=>s(e=>!e),[])}}function rc(e){return e===`running`||e===`idle`||e===`error`||e===`aborted`?e:void 0}function ic(e){let[t,n]=(0,W.useState)({}),r=(0,W.useMemo)(()=>new Set(e.map(e=>e.id)),[e]),i=(0,W.useMemo)(()=>e.map(e=>e.id).sort().join(`
|
|
895
|
+
`),[e]),a=(0,W.useCallback)(async()=>{if(r.size===0){n({});return}try{let e=await oo(),t=new Map(e.map(e=>[e.sessionId,rc(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){U.error(`Failed to refresh visible agent statuses:`,e)}},[r]);return(0,W.useEffect)(()=>{let e=window.setTimeout(()=>{a()},0);return()=>window.clearTimeout(e)},[a,i]),(0,W.useEffect)(()=>so(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=rc(e.status)===`aborted`?`aborted`:e.errorMessage?`error`:`idle`;n(e=>({...e,[t]:r}))}}}),[r]),(0,W.useEffect)(()=>{let e=()=>{document.visibilityState===`visible`&&a()};return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[a]),t}function ac(e){return e===`idle`?{tone:`success`,message:q(`taskCompleted`)}:e===`error`?{tone:`error`,message:q(`taskError`)}:e===`aborted`?{tone:`aborted`,message:q(`processAborted`)}:e===`running`?{tone:`running`,message:q(`taskRunning`)}:{tone:`neutral`,message:q(`taskRunning`)}}function oc({toast:e,onDismiss:n,onClick:r}){let[i,a]=(0,W.useState)(!1),[o,s]=(0,W.useState)(!1),c=(0,W.useRef)(null);(0,W.useEffect)(()=>{let t=window.setTimeout(()=>a(!0),10);return c.current=window.setTimeout(()=>{s(!0),c.current=window.setTimeout(()=>n(e.id),200)},5e3),()=>{window.clearTimeout(t),c.current!==null&&window.clearTimeout(c.current)}},[e.id,n]);let l=()=>{s(!0),c.current!==null&&window.clearTimeout(c.current),c.current=window.setTimeout(()=>n(e.id),200)},u=ac(e.status),d=u.tone===`error`,f=u.tone===`success`,p=J(`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,Y.jsxs)(`div`,{role:`alert`,onClick:()=>r(e.sessionId),className:J(`pointer-events-auto flex w-80 cursor-pointer items-start gap-3 rounded-xl border border-border bg-background p-3 shadow-lg transition-all duration-200 ease-out`,i&&!o?`translate-x-0 opacity-100`:`translate-x-4 opacity-0`),children:[(0,Y.jsx)(`div`,{className:`mt-0.5 shrink-0`,children:f?(0,Y.jsx)(t,{className:p}):(0,Y.jsx)(g,{className:p})}),(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Y.jsx)(`p`,{className:`truncate text-sm font-medium text-foreground/90`,children:e.title}),(0,Y.jsx)(`p`,{className:`mt-0.5 line-clamp-3 text-xs text-muted-foreground`,children:e.message||u.message})]}),(0,Y.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":q(`close`),children:(0,Y.jsx)(j,{className:`size-4`})})]})}function sc({toasts:e,onDismiss:t,onClick:n}){return e.length===0?null:(0,Y.jsx)(`div`,{className:`pointer-events-none fixed right-4 top-16 z-50 flex flex-col gap-2`,children:e.map(e=>(0,Y.jsx)(oc,{toast:e,onDismiss:t,onClick:n},e.id))})}async function cc(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 lc(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 uc(){let e=()=>Array.from({length:6},()=>lc(`ABCDEFGHJKLMNPQRSTUVWXYZ23456789`)).join(``);return`${e()}-${e()}`}function dc(e=24){return new Date(Date.now()+e*60*60*1e3).toISOString()}async function fc(e){return cc(`/api/shares`,{method:`POST`,body:JSON.stringify(e)})}async function pc(e){return cc(`/api/shares${e?`?sessionId=${encodeURIComponent(e)}`:``}`)}async function mc(e){return cc(`/api/shares/${encodeURIComponent(e)}`,{method:`DELETE`})}async function hc(e){return cc(`/api/shared/${encodeURIComponent(e)}/meta`)}async function gc(e,t=``){return cc(`/api/shared/${encodeURIComponent(e)}/unlock`,{method:`POST`,body:JSON.stringify({password:t})})}async function _c(e){return cc(`/api/shared/${encodeURIComponent(e)}/models`)}function vc({open:e,sessionId:t,title:n,onOpenChange:r}){let i=(0,W.useId)(),[a,o]=(0,W.useState)(`read`),[s,c]=(0,W.useState)(``),[l,d]=(0,W.useState)(`24h`),[f,p]=(0,W.useState)(!1),[m,h]=(0,W.useState)(``),[g,_]=(0,W.useState)([]),[y,b]=(0,W.useState)(!1),[x,S]=(0,W.useState)(),C=(0,W.useMemo)(()=>{if(l!==`never`)return dc(l===`1h`?1:l===`7d`?168:24)},[l]);if((0,W.useEffect)(()=>{!e||!t||pc(t).then(e=>_(e.shares)).catch(e=>S(e instanceof Error?e.message:`Failed to load shares`))},[e,t]),!e)return null;let w=a===`operate`,E=!!t&&(a!==`operate`||f&&s.trim()),O=async()=>{if(!(!t||!E)){if(w&&!s.trim()){S(`可操作分享必须设置密码。`);return}b(!0),S(void 0);try{let e=await fc({sessionId:t,permission:a,password:s.trim(),expiresAt:C});h(e.url),await ho(e.url),p(!1),_((await pc(t)).shares)}catch(e){S(e instanceof Error?e.message:`Failed to create share`)}finally{b(!1)}}},k=async e=>{let t=e.url||`${window.location.origin}/share/${encodeURIComponent(e.id)}`;h(t),await ho(t)},ee=async e=>{try{await mc(e),_(t=>t.map(t=>t.id===e?{...t,revokedAt:new Date().toISOString()}:t))}catch(e){S(e instanceof Error?e.message:`Failed to revoke share`)}};return(0,Y.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,onMouseDown:e=>{e.target===e.currentTarget&&r(!1)},children:(0,Y.jsxs)(`div`,{className:`flex max-h-[90vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl border border-border bg-background shadow-2xl`,onMouseDown:e=>e.stopPropagation(),children:[(0,Y.jsxs)(`div`,{className:`shrink-0 border-b border-border px-5 py-4`,children:[(0,Y.jsx)(`h2`,{className:`text-base font-semibold`,children:`分享到局域网`}),(0,Y.jsxs)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:[`当前对话:`,n,`。同一个对话只会有一个固定分享链接;只读分享密码可选,可操作分享必须设置密码。`]})]}),(0,Y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-5 py-4`,children:(0,Y.jsxs)(`div`,{className:`space-y-4`,children:[(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`div`,{className:`mb-2 text-sm font-medium`,children:`权限`}),(0,Y.jsxs)(`div`,{className:`grid gap-2 sm:grid-cols-2`,children:[(0,Y.jsxs)(`button`,{type:`button`,className:`rounded-xl border p-3 text-left text-sm ${a===`read`?`border-primary bg-primary/10`:`border-border`}`,onClick:()=>o(`read`),children:[(0,Y.jsx)(`div`,{className:`font-medium`,children:`仅阅读`}),(0,Y.jsx)(`div`,{className:`mt-1 text-xs text-muted-foreground`,children:`只能查看这一个对话。`})]}),(0,Y.jsxs)(`button`,{type:`button`,className:`rounded-xl border p-3 text-left text-sm ${a===`operate`?`border-red-400 bg-red-50 text-red-950`:`border-border`}`,onClick:()=>o(`operate`),children:[(0,Y.jsx)(`div`,{className:`font-medium text-red-700`,children:`可操作(高危)`}),(0,Y.jsx)(`div`,{className:`mt-1 text-xs text-red-700`,children:`允许对方操作这个原对话,禁止 Fork。`})]})]})]}),a===`operate`?(0,Y.jsxs)(`div`,{className:`rounded-xl border border-red-300 bg-red-50 p-3 text-sm text-red-900`,children:[(0,Y.jsxs)(`div`,{className:`flex gap-2 font-semibold`,children:[(0,Y.jsx)(D,{className:`mt-0.5 size-4`}),`高危可操作权限`]}),(0,Y.jsx)(`p`,{className:`mt-2 text-xs leading-5`,children:`拥有链接和密码的人只能操作这一个原对话,但对方的消息、停止生成、回滚、模型/思考等级选择、YOLO 状态下可用工具等操作会按正常对话权限直接影响你的本机原对话。可操作分享必须设置密码。`}),(0,Y.jsxs)(`label`,{className:`mt-3 flex items-center gap-2 text-xs font-medium`,children:[(0,Y.jsx)(`input`,{type:`checkbox`,checked:f,onChange:e=>p(e.target.checked)}),`我已了解风险,仍然允许可操作权限。`]})]}):null,(0,Y.jsxs)(`div`,{className:`space-y-2`,children:[(0,Y.jsx)(`label`,{htmlFor:i,className:`block text-sm font-medium`,children:w?`密码(可操作必填)`:`密码(可选)`}),(0,Y.jsxs)(`div`,{className:`flex flex-col gap-3 sm:flex-row sm:items-center`,children:[(0,Y.jsx)(`input`,{id:i,value:s,onChange:e=>c(e.target.value),className:`h-10 w-full min-w-0 rounded-md border border-input bg-background px-3 text-sm`,placeholder:w?`可操作分享必须设置密码`:`留空则打开链接无需密码`}),(0,Y.jsxs)(X,{variant:`outline`,className:`h-10 sm:shrink-0`,onClick:()=>c(uc()),children:[(0,Y.jsx)(T,{className:`mr-2 size-4`}),`生成密码`]})]}),(0,Y.jsx)(`span`,{className:`block text-xs text-muted-foreground`,children:w?`可操作分享必须设置非空密码;修改密码后旧密码和已解锁状态会失效。`:`留空保存会取消密码保护;填写新密码保存后旧密码和已解锁状态会失效。`})]}),(0,Y.jsxs)(`label`,{className:`block text-sm font-medium`,children:[`有效期`,(0,Y.jsxs)(`select`,{value:l,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,Y.jsx)(`option`,{value:`1h`,children:`1 小时`}),(0,Y.jsx)(`option`,{value:`24h`,children:`24 小时`}),(0,Y.jsx)(`option`,{value:`7d`,children:`7 天`}),(0,Y.jsx)(`option`,{value:`never`,children:`永久,需手动撤销`})]})]}),m?(0,Y.jsxs)(`div`,{className:`rounded-xl border border-emerald-300 bg-emerald-50 p-3 text-sm text-emerald-900`,children:[`已复制到剪切板。`,(0,Y.jsx)(`pre`,{className:`mt-2 max-h-36 overflow-auto whitespace-pre-wrap text-xs`,children:m})]}):null,x?(0,Y.jsx)(`div`,{className:`rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:x}):null,g.length?(0,Y.jsxs)(`div`,{children:[(0,Y.jsx)(`div`,{className:`mb-2 text-sm font-medium`,children:`已有分享`}),(0,Y.jsx)(`div`,{className:`space-y-2`,children:g.map(e=>(0,Y.jsxs)(`div`,{className:`flex items-center gap-2 rounded-lg border border-border p-2 text-xs`,children:[(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Y.jsx)(`div`,{className:`truncate font-mono`,children:e.id}),(0,Y.jsxs)(`div`,{className:`text-muted-foreground`,children:[e.permission===`operate`?`可操作`:`只读`,` · `,e.hasPassword?`有密码`:`无密码`,` · `,e.revokedAt?`已撤销`:e.expiresAt?`到期 ${new Date(e.expiresAt).toLocaleString()}`:`永久`]})]}),e.revokedAt?null:(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,onClick:()=>void k(e),"aria-label":`复制分享链接`,title:`复制分享链接`,children:(0,Y.jsx)(u,{className:`size-4`})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:`text-destructive`,onClick:()=>void ee(e.id),"aria-label":`撤销分享`,title:`撤销分享`,children:(0,Y.jsx)(v,{className:`size-4`})})]})]},e.id))})]}):null]})}),(0,Y.jsx)(`div`,{className:`shrink-0 border-t border-border px-5 py-4`,children:(0,Y.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[(0,Y.jsx)(X,{variant:`outline`,onClick:()=>r(!1),children:q(`cancel`)}),(0,Y.jsxs)(X,{variant:a===`operate`?`destructive`:`default`,disabled:!E||y,onClick:()=>void O(),title:a===`operate`&&!s.trim()?`可操作分享必须设置密码`:void 0,children:[(0,Y.jsx)(u,{className:`mr-2 size-4`}),a===`operate`?`保存配置并复制高危可操作链接`:`保存配置并复制链接`]})]})})]})})}async function yc(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 bc(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 xc(e){return`projectId=${encodeURIComponent(e)}`}function Sc(e){return yc(`/api/workspace/tree?${xc(e)}`)}function Cc(e,t){return yc(`/api/workspace/file?${xc(e)}&path=${encodeURIComponent(t)}`)}function wc(e,t){return bc(`/api/workspace/resolve-path`,{projectId:e,path:t})}function Tc(e){return yc(`/api/git/status?${xc(e)}`)}function Ec(e,t){return yc(`/api/git/file-diff?${xc(e)}&path=${encodeURIComponent(t)}`)}var Dc=(0,W.lazy)(()=>H(()=>import(`./ChatPanelHost-FqPQwwMO.js`).then(e=>({default:e.ChatPanelHost})),__vite__mapDeps([0,1,2,3,4,5,6,7,8]))),Oc=(0,W.lazy)(()=>H(()=>import(`./TerminalDock-DLN_pLkJ.js`).then(e=>({default:e.TerminalDock})),__vite__mapDeps([9,1,10,11,5,6]))),kc=(0,W.lazy)(()=>H(()=>import(`./ScheduledTasksPage-Bx04rjui.js`).then(e=>({default:e.ScheduledTasksPage})),__vite__mapDeps([12,1,5,6]))),Ac=(0,W.lazy)(()=>H(()=>import(`./AgentProfilesPage-CNK5PxA3.js`).then(e=>({default:e.AgentProfilesPage})),__vite__mapDeps([13,1,5,6]))),jc=(0,W.lazy)(()=>H(()=>import(`./PluginsPage-BCu1Ept0.js`).then(e=>({default:e.PluginsPage})),__vite__mapDeps([14,1,5,6,7]))),Mc=(0,W.lazy)(()=>H(()=>import(`./SharedConversationPage-55vX9sqe.js`).then(e=>({default:e.SharedConversationPage})),__vite__mapDeps([15,1,3,2,4,5,6,0,7,8]))),Nc=(0,W.lazy)(()=>H(()=>import(`./WorkspaceInspector-DoemHHnY.js`).then(e=>({default:e.WorkspaceInspector})),__vite__mapDeps([16,1,5,6,17,18]))),Pc=(0,W.lazy)(()=>H(()=>import(`./WorkspaceReaderDialog-C6xUHBCw.js`).then(e=>({default:e.WorkspaceReaderDialog})),__vite__mapDeps([17,1,18,5,6])));function Fc(){return(0,Y.jsx)(`div`,{className:`flex min-h-0 flex-1 items-center justify-center text-sm text-muted-foreground`,children:q(`loading`)})}function Ic(){return null}function Lc(e){return e===`idle`||e===`running`||e===`error`||e===`aborted`}function Rc(e){return e.type===`scheduled_task_notification`}function zc(e){return e.type===`scheduled_task_started`}function Bc(){let e=(0,W.useRef)(null),t=(0,W.useRef)(qt(Vt)),n=(0,W.useRef)(!1),r=(0,W.useRef)(void 0),{activeProject:i,projects:a,expandedProjectIds:o,selectingProject:c,projectPickerOpen:l,loadProject:u,switchActiveProject:d,handleSelectProjectPath:p,selectProjectDirectory:m,setProjectPickerOpen:g,toggleProjectExpanded:_,toggleAllProjectsExpanded:v,reorderProjects:y,setActiveProject:x,setProjects:S,setExpandedProjectIds:C}=Ka(),{yoloMode:w,setYoloMode:T,initialize:E}=qa(),D=nc(),[O,k]=(0,W.useState)(!1),[ee,A]=(0,W.useState)(),[j,M]=(0,W.useState)(`chat`),[P,F]=(0,W.useState)(!1),[te,I]=(0,W.useState)(null),[ne,re]=(0,W.useState)([]),[L,ae]=(0,W.useState)(),se=(0,W.useRef)(0),[ce,le]=(0,W.useState)(null),{toasts:ue,handleTaskComplete:de,addToast:fe,dismissToast:z}=Do(),pe=j===`scheduledTasks`,me=j===`agentProfiles`,he=j===`plugins`,ge=j!==`chat`,B=(0,W.useCallback)(()=>M(`chat`),[]),_e=(0,W.useRef)(null),V=(0,W.useRef)(null),{allLoadedSessions:ve,globalSessions:ye,sessionsForProject:be,globalHasMore:xe,projectHasMore:Se,globalLoading:Ce,projectLoading:we,projectLoaded:Te,loadGlobalSessions:Ee,loadProjectSessions:De,refreshSessions:Oe,loadMoreGlobal:ke,loadMoreProject:Ae}=Eo({backendRef:V,expandedProjectIds:o,onBroadcastSessionsChanged:(0,W.useCallback)(()=>_e.current?.notifySessionsChanged(),[])}),H=Ya({onSessionsChanged:()=>{Oe()},onProjectsChanged:()=>{u()},onSettingsChanged:()=>{Oe()}});(0,W.useEffect)(()=>{n.current=w},[w]),(0,W.useEffect)(()=>{r.current=i},[i]),(0,W.useEffect)(()=>{_e.current=H},[H]);let je=(0,W.useCallback)((e,t)=>{ae({sessionId:e,...t})},[]),G=So({storageRef:e,activeModelRef:t,yoloModeRef:n,activeProjectRef:r,setYoloMode:T,switchActiveProject:d,sessions:ve,refreshSessions:Oe,onTaskComplete:de}),{createAgent:Me,startDeferredSession:Ne,loadSession:Pe,syncSessionUI:Fe,setCurrentAgentMessages:Ie,updateCurrentAgentModel:Le,setChatPanelRevision:Re,setCurrentTitleRef:ze,agentRef:K,taskMapRef:Be,currentSessionIdRef:Ve,currentChatScopeRef:He}=G,Ue=(0,W.useCallback)(e=>{e&&(B(),Pe(e))},[B,Pe]),We=(0,W.useCallback)(e=>{e.trim()&&(B(),A({id:Date.now(),sessionId:K.current?.sessionId,text:e}))},[K,B]),Ge=(0,W.useCallback)(()=>{G.currentToolProject?.id&&(B(),D.setWorkspacePanelView(`changes`),D.setWorkspaceInspectorFocusTarget({tab:`git`,nonce:Date.now()}),D.setWorkspaceInspectorOpen(!0))},[G.currentToolProject?.id,B,D]),Ke=(0,W.useCallback)(async e=>{let t=G.currentToolProject?.id;if(!t){fe({sessionId:G.currentSessionId??``,title:`无法打开文件`,status:`error`,message:`当前对话没有关联项目。`});return}D.setInlineReaderOpen(!0),D.setInlineReaderLoading(!0),D.setInlineReaderError(void 0),D.setInlineReaderFile(void 0);try{let n=await Cc(t,(await wc(t,e)).relativePath);D.setInlineReaderFile(n)}catch(e){let t=e instanceof Error?e.message:`打开文件失败`;D.setInlineReaderError(t),fe({sessionId:G.currentSessionId??``,title:`无法打开文件`,status:`error`,message:t})}finally{D.setInlineReaderLoading(!1)}},[fe,G.currentSessionId,G.currentToolProject?.id,D]);(0,W.useEffect)(()=>so(e=>{if(zc(e)){let t=typeof e.projectId==`string`?e.projectId:void 0;t&&(C(e=>{let n=new Set(e);return n.add(t),n}),De(t,0)),Oe({broadcast:!0});return}if((e.type===`agent_end`||e.type===`title_updated`||e.type===`session_forked`)&&Oe({broadcast:!0}),!Rc(e))return;let t=typeof e.sessionId==`string`?e.sessionId:void 0,n=typeof e.title==`string`?e.title:q(`scheduledTasks`),r=Lc(e.status)?e.status:`idle`,i=typeof e.message==`string`?e.message:void 0;fe({sessionId:t??``,title:n,status:r,message:i})}),[fe,De,Oe,C]);let{ready:qe,startupError:Je,retryBootstrap:Ye}=Uo({storageRef:e,backendRef:V,activeModelRef:t,yoloModeRef:n,activeProjectRef:r,setYoloMode:T,taskMapRef:Be,loadGlobalSessions:Ee,loadProject:u,initYoloMode:E,switchActiveProject:d,createAgent:Me,setNeedsModelSetup:k,onStorageReady:le});(0,W.useEffect)(()=>{if(qe)for(let e of o)!Te(e)&&!we(e)&&De(e,0)},[qe,o,Te,we,De]);let{startNewGlobalChat:Xe,startNewProjectChat:Ze,rollbackFromMessage:Qe,retryFromMessage:$e,copyAnswer:J,forkFromMessage:et}=Xs({storageRef:e,activeModelRef:t,activeProjectRef:r,currentChatScopeRef:He,currentSessionIdRef:Ve,taskMapRef:Be,agentRef:K,createAgent:Me,startDeferredSession:Ne,syncSessionUI:Fe,setCurrentAgentMessages:Ie,setChatPanelRevision:Re,refreshSessions:Oe,needsModelSetup:O,switchActiveProject:d,closeWorkspacePage:B,setRestoredDraft:A}),{deleteProjectInline:nt}=Zs({activeProjectRef:r,refreshSessions:Oe,notifyProjectsChanged:H.notifyProjectsChanged,setActiveProject:x,setProjects:S,setExpandedProjectIds:C,setChatPanelRevision:Re}),{toggleYoloMode:it}=tc({storageRef:e,yoloModeRef:n,setYoloMode:T,agentRef:K,setChatPanelRevision:Re,notifySettingsChanged:H.notifySettingsChanged}),ot=(0,W.useCallback)(async e=>{let t=K.current;if(!t)throw Error(q(`toolApprovalFailed`));try{await t.approveToolCall(e)}catch(e){throw U.error(`Failed to approve tool call:`,e),e instanceof Error?e:Error(q(`toolApprovalFailed`))}},[K]),st=(0,W.useCallback)(async e=>{let t=K.current;if(!t)throw Error(q(`toolApprovalFailed`));try{await t.rejectToolCall(e)}catch(e){throw U.error(`Failed to reject tool call:`,e),e instanceof Error?e:Error(q(`toolApprovalFailed`))}},[K]),ct=(0,W.useCallback)(async e=>{let t=K.current;if(!t?.approveAutoCompact)throw Error(q(`toolApprovalFailed`));await t.approveAutoCompact(e)},[K]),ut=(0,W.useCallback)(async e=>{let t=K.current;if(!t?.rejectAutoCompact)throw Error(q(`toolApprovalFailed`));await t.rejectAutoCompact(e)},[K]),{loadSession:dt,renameSession:ft,togglePinSession:pt,deleteSession:mt,startNewGlobalSession:ht}=ec({storageRef:e,taskMapRef:Be,currentSessionIdRef:Ve,loadAgentSession:Pe,setCurrentTitleRef:ze,refreshSessions:Oe,closeWorkspacePage:B,startNewGlobalChat:Xe}),{openModelSettings:gt,openDefaultOptionsSettings:_t,activateLiteLlmExampleModel:vt,openCustomModelSelector:yt}=qs({storageRef:e,activeModelRef:t,agentRef:K,createAgent:Me,updateCurrentAgentModel:Le,setChatPanelRevision:Re,needsModelSetup:O,setNeedsModelSetup:k,setRestoredDraft:A,notifySettingsChanged:H.notifySettingsChanged}),bt=(0,W.useMemo)(()=>[...ye,...a.flatMap(e=>be(e.id))],[ye,a,be]),xt=!!(0,W.useMemo)(()=>{if(G.currentSessionId)return bt.find(e=>e.id===G.currentSessionId)},[G.currentSessionId,bt])?.pinnedAt,St=ic(bt),Ct=(0,W.useCallback)(e=>G.taskStatuses[e.id]??St[e.id]??e.taskStatus??`idle`,[G.taskStatuses,St]);(0,W.useEffect)(()=>{if(!D.conversationMenuOpen)return;let e=()=>D.setConversationMenuOpen(!1);return window.addEventListener(`click`,e),window.addEventListener(`blur`,e),()=>{window.removeEventListener(`click`,e),window.removeEventListener(`blur`,e)}},[D,D.conversationMenuOpen]),(0,W.useEffect)(()=>{let e=e=>{let t=e.detail,n=typeof t?.command==`string`?t.command.trim():``;n&&(async()=>{(t?.confirm||t?.dangerous)&&!await lt({title:q(`confirmExecuteCommandTitle`),description:t?.dangerous?q(`confirmExecuteDangerousCommand`):q(`confirmExecuteMultipleCommands`),confirmLabel:q(`executeInTerminal`),cancelLabel:q(`cancel`),variant:t?.dangerous?`destructive`:`default`})||(F(!0),I({id:++se.current,command:n,execute:!0}))})().catch(e=>{U.error(`Failed to execute markdown command:`,e),Z(e instanceof Error?e.message:q(`terminalCommandExecuteFailed`))})};return window.addEventListener(`quickforge:execute-markdown-command`,e),()=>window.removeEventListener(`quickforge:execute-markdown-command`,e)},[]);let wt=(0,W.useCallback)(e=>{I(t=>t?.id===e?null:t)},[]),Tt=(0,W.useCallback)(()=>{D.setFirstUseGuideDismissed(!0)},[D]),Et=(0,W.useCallback)(()=>{let e=G.currentToolProject?.id?q(`firstUseGuideProjectPrompt`):q(`firstUseGuideGeneralPrompt`);navigator.clipboard.writeText(e).then(()=>fe({sessionId:G.currentSessionId??``,title:q(`copied`),status:`idle`,message:e})).catch(e=>{U.error(`Failed to copy first-use guide prompt:`,e),Z(q(`copyFailed`))})},[fe,G.currentSessionId,G.currentToolProject?.id]),Dt=!!ce&&!D.firstUseGuideDismissed&&!P&&a.length===0&&ye.length===0,Ot=(0,W.useCallback)(()=>{let e=G.currentSessionId;e&&(D.setConversationMenuOpen(!1),pt(e))},[G.currentSessionId,pt,D]),kt=(0,W.useCallback)(()=>{let e=G.currentSessionId;e&&(D.setConversationMenuOpen(!1),ft(e,G.currentTitle))},[G.currentSessionId,G.currentTitle,ft,D]),At=(0,W.useCallback)(()=>{D.setConversationMenuOpen(!1),D.setShareDialogOpen(!0)},[D]),{setSkillsDialog:jt,setMcpServersDialogOpen:Nt,setSidebarOpen:Pt}=D,Ft=(0,W.useCallback)(()=>{jt({scope:`global`})},[jt]),It=(0,W.useCallback)(e=>{jt({scope:`project`,project:e})},[jt]),Lt=(0,W.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||q(`openInExplorerFailed`))},[]),Rt=(0,W.useCallback)(()=>{Nt(!0)},[Nt]),zt=(0,W.useCallback)(e=>{Lt(e).catch(e=>{U.error(`Failed to open project in explorer:`,e),Z(e instanceof Error?e.message:q(`openInExplorerFailed`))})},[Lt]),Bt=(0,W.useCallback)(()=>M(`scheduledTasks`),[M]),Ht=(0,W.useCallback)(()=>M(`agentProfiles`),[M]),Ut=(0,W.useCallback)(()=>M(`plugins`),[M]),Wt=(0,W.useCallback)(()=>Pt(e=>!e),[Pt]),Q=(0,W.useCallback)(()=>{D.setMobileSidebarOpen(!1)},[D]),Gt=(0,W.useCallback)(e=>{Q(),dt(e)},[Q,dt]),Kt=(0,W.useCallback)(()=>{Q(),ht()},[Q,ht]),Jt=(0,W.useCallback)(e=>{Q(),Ze(e)},[Q,Ze]),Yt=(0,W.useCallback)(()=>{Q(),M(`scheduledTasks`)},[Q]),Xt=(0,W.useCallback)(()=>{Q(),M(`agentProfiles`)},[Q]),Zt=(0,W.useCallback)(()=>{Q(),Ft()},[Q,Ft]),Qt=(0,W.useCallback)(()=>{Q(),D.setMcpServersDialogOpen(!0)},[Q,D]),$t=(0,W.useCallback)(e=>{Q(),It(e)},[Q,It]),en=(0,W.useCallback)(e=>{if(e.scope===`project`&&e.project&&e.projects){S(e.projects),D.setSkillsDialog({scope:`project`,project:e.project}),r.current?.id===e.project.id&&(x(e.project),r.current=e.project),H.notifyProjectsChanged();return}H.notifyProjectsChanged()},[H,x,S,D]),tn=(0,Y.jsx)(`div`,{className:`flex h-full w-full items-center justify-center text-sm text-muted-foreground`,children:q(`loadingChatWorkspace`)});return Je?(0,Y.jsx)(`div`,{className:`flex h-screen items-center justify-center bg-background p-6 text-foreground`,children:(0,Y.jsxs)(`div`,{className:`max-w-md rounded-lg border border-border bg-card p-5 shadow-sm text-center`,children:[(0,Y.jsx)(`h1`,{className:`text-base font-semibold`,children:q(`localServiceUnavailableTitle`)}),(0,Y.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:Je}),(0,Y.jsxs)(`div`,{className:`mt-4 flex justify-center gap-2`,children:[(0,Y.jsx)(X,{variant:`outline`,size:`sm`,onClick:Ye,children:q(`retry`)}),(0,Y.jsx)(X,{variant:`default`,size:`sm`,onClick:()=>window.location.reload(),children:q(`reloadPage`)})]})]})}):!qe||!G.agent&&!O?(0,Y.jsx)(`div`,{className:`flex h-screen items-center justify-center bg-background text-foreground`,children:(0,Y.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:q(`loadingChatWorkspace`)})}):(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsxs)(`div`,{className:`flex h-screen min-h-0 bg-background text-foreground`,children:[(0,Y.jsx)(Ga,{sidebarOpen:D.sidebarOpen,scheduledTasksActive:pe,agentProfilesActive:me,pluginsActive:he,projectsCollapsed:D.projectsCollapsed,conversationsCollapsed:D.conversationsCollapsed,projects:a,expandedProjectIds:o,activeProject:i,currentSessionId:G.currentSessionId,globalSessions:ye,sessionsForProject:be,globalHasMore:xe,globalLoading:Ce,onLoadMoreGlobal:ke,projectHasMore:Se,projectLoading:we,projectLoaded:Te,onLoadMoreProject:Ae,sessionTaskStatus:Ct,selectingProject:c,onToggleProjectsCollapsed:D.toggleProjectsCollapsed,onToggleConversationsCollapsed:D.toggleConversationsCollapsed,onToggleProjectExpanded:_,onToggleAllProjectsExpanded:v,onReorderProjects:y,onSelectProjectDirectory:m,onStartNewProjectChat:Ze,onOpenGlobalSkills:Ft,onOpenMcpServers:Rt,onOpenProjectSkills:It,onOpenProjectInExplorer:zt,onDeleteProject:nt,onLoadSession:dt,onTogglePinSession:pt,onRenameSession:ft,onDeleteSession:mt,onStartNewGlobalChat:ht,onOpenScheduledTasks:Bt,onOpenAgentProfiles:Ht,onOpenPlugins:Ut,onOpenSettings:_t,onToggleSidebar:Wt,currentSessionHoverInfo:L}),D.mobileSidebarOpen?(0,Y.jsxs)(`div`,{className:`fixed inset-0 z-50 md:hidden`,role:`dialog`,"aria-modal":`true`,children:[(0,Y.jsx)(`button`,{type:`button`,className:`absolute inset-0 bg-background/65 backdrop-blur-sm`,onClick:Q,"aria-label":q(`toggleSidebar`)}),(0,Y.jsx)(`div`,{className:`absolute inset-y-0 left-0 max-w-[85vw] shadow-2xl`,children:(0,Y.jsx)(Ga,{variant:`mobile`,sidebarOpen:!0,scheduledTasksActive:pe,agentProfilesActive:me,pluginsActive:he,projectsCollapsed:D.projectsCollapsed,conversationsCollapsed:D.conversationsCollapsed,projects:a,expandedProjectIds:o,activeProject:i,currentSessionId:G.currentSessionId,globalSessions:ye,sessionsForProject:be,globalHasMore:xe,globalLoading:Ce,onLoadMoreGlobal:ke,projectHasMore:Se,projectLoading:we,projectLoaded:Te,onLoadMoreProject:Ae,sessionTaskStatus:Ct,selectingProject:c,onToggleProjectsCollapsed:D.toggleProjectsCollapsed,onToggleConversationsCollapsed:D.toggleConversationsCollapsed,onToggleProjectExpanded:_,onToggleAllProjectsExpanded:v,onReorderProjects:y,onSelectProjectDirectory:()=>{Q(),m()},onStartNewProjectChat:Jt,onOpenGlobalSkills:Zt,onOpenMcpServers:Qt,onOpenProjectSkills:$t,onOpenProjectInExplorer:e=>{Q(),Lt(e).catch(e=>{U.error(`Failed to open project in explorer:`,e),Z(e instanceof Error?e.message:q(`openInExplorerFailed`))})},onDeleteProject:nt,onLoadSession:Gt,onTogglePinSession:pt,onRenameSession:ft,onDeleteSession:mt,onStartNewGlobalChat:Kt,onOpenScheduledTasks:Yt,onOpenAgentProfiles:Xt,onOpenPlugins:()=>{Q(),M(`plugins`)},onOpenSettings:()=>{Q(),_t()},onToggleSidebar:Q,currentSessionHoverInfo:L})})]}):null,(0,Y.jsxs)(`main`,{className:`flex min-w-0 flex-1 flex-col`,children:[(0,Y.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-2 border-b border-border px-3`,children:[(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:`md:hidden`,onClick:()=>D.setMobileSidebarOpen(!0),"aria-label":q(`toggleSidebar`),children:(0,Y.jsx)(f,{className:`size-4`})}),(0,Y.jsx)(`div`,{className:`min-w-0 flex-1`,children:pe?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`div`,{className:`truncate text-xs text-muted-foreground`,children:`AI Workspace`}),(0,Y.jsx)(`div`,{className:`truncate text-sm font-semibold`,children:q(`scheduledTasks`)})]}):me?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`div`,{className:`truncate text-xs text-muted-foreground`,children:`AI Workspace`}),(0,Y.jsx)(`div`,{className:`truncate text-sm font-semibold`,children:q(`agentsTab`)})]}):he?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`div`,{className:`truncate text-xs text-muted-foreground`,children:`AI Workspace`}),(0,Y.jsx)(`div`,{className:`truncate text-sm font-semibold`,children:q(`plugins`)})]}):(0,Y.jsxs)(`div`,{className:`flex max-w-full min-w-0 items-center`,children:[G.currentToolProject?.name?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`div`,{className:`min-w-0 truncate text-sm font-semibold text-muted-foreground/72`,children:G.currentToolProject.name}),(0,Y.jsx)(`div`,{className:`mx-1 shrink-0 text-sm text-muted-foreground/45`,children:`/`})]}):null,(0,Y.jsx)(`div`,{className:`min-w-0 truncate text-sm font-semibold`,children:_n(G.currentTitle)}),(0,Y.jsxs)(`div`,{className:`relative ml-0.5 shrink-0`,onClick:e=>e.stopPropagation(),children:[(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,className:`size-6`,onClick:()=>D.setConversationMenuOpen(e=>!e),disabled:!G.currentSessionId||O,"aria-label":q(`moreOptions`),"aria-expanded":D.conversationMenuOpen,children:(0,Y.jsx)(s,{className:`size-4`})}),D.conversationMenuOpen?(0,Y.jsxs)(`div`,{className:`absolute left-0 top-8 z-30 min-w-44 rounded-lg border border-border bg-card p-1 shadow-xl`,children:[(0,Y.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 whitespace-nowrap rounded-md px-2 py-1.5 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:Ot,children:[xt?(0,Y.jsx)(oe,{className:`size-4`}):(0,Y.jsx)(b,{className:`size-4`}),(0,Y.jsx)(`span`,{children:q(xt?`unpinSession`:`pinSession`)})]}),(0,Y.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 whitespace-nowrap rounded-md px-2 py-1.5 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:kt,children:[(0,Y.jsx)(h,{className:`size-4`}),(0,Y.jsx)(`span`,{children:q(`renameSession`)})]}),(0,Y.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-2 whitespace-nowrap rounded-md px-2 py-1.5 text-left text-sm text-foreground/86 transition-colors hover:bg-muted`,onClick:At,children:[(0,Y.jsx)(ie,{className:`size-4`}),(0,Y.jsx)(`span`,{children:q(`shareSession`)})]})]}):null]})]})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,onClick:()=>D.setWorkspaceInspectorOpen(e=>!e),disabled:!G.currentToolProject?.id||ge||O,"aria-label":q(`workspacePanel`),title:q(`workspacePanel`),className:D.workspaceInspectorOpen?`hidden bg-accent text-accent-foreground lg:inline-flex`:`hidden lg:inline-flex`,children:(0,Y.jsx)(R,{className:`size-4`})}),(0,Y.jsx)(X,{variant:`ghost`,size:`icon`,onClick:()=>F(e=>!e),disabled:ge||O,"aria-label":`终端`,title:`终端`,className:P?`bg-accent text-accent-foreground`:void 0,children:(0,Y.jsx)(N,{className:`size-4`})})]}),(0,Y.jsx)(`section`,{className:`relative flex min-h-0 flex-1 flex-col`,children:pe?(0,Y.jsx)(W.Suspense,{fallback:tn,children:(0,Y.jsx)(kc,{onOpenSession:Ue})}):me?(0,Y.jsx)(W.Suspense,{fallback:tn,children:(0,Y.jsx)(Ac,{})}):he?(0,Y.jsx)(W.Suspense,{fallback:tn,children:(0,Y.jsx)(jc,{})}):O?(0,Y.jsx)(yn,{onAddModel:gt,onUseExample:()=>{vt().catch(e=>U.error(`Failed to use LiteLLM example:`,e))}}):(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col`,children:(0,Y.jsx)(tt,{children:(0,Y.jsx)(W.Suspense,{fallback:(0,Y.jsx)(Fc,{}),children:(0,Y.jsx)(Dc,{agent:G.agent,onModelSelect:yt,revision:G.chatPanelRevision,yoloMode:w,workspaceToolsEnabled:!!G.currentToolProject?.id,project:G.currentToolProject,projectId:G.currentToolProject?.id,chatScope:G.chatScope,storage:ce,onToggleYoloMode:it,onRollbackFromMessage:Qe,onRetryFromMessage:$e,onCopyAnswer:J,onForkFromMessage:et,onApproveToolCall:ot,onRejectToolCall:st,onApproveAutoCompact:ct,onRejectAutoCompact:ut,onOpenWorkspaceGitChanges:Ge,onOpenLocalFilePath:Ke,onArtifactsChange:re,onContextUsageDisplayChange:je,disableFork:!1,restoredDraft:ee})})})}),Dt?(0,Y.jsx)(vn,{hasProject:!!G.currentToolProject?.id,onConfigureModel:gt,onAddProject:m,onCopyExamplePrompt:Et,onDismiss:Tt}):null,P?(0,Y.jsx)(W.Suspense,{fallback:null,children:(0,Y.jsx)(Oc,{project:G.currentToolProject,pendingCommand:te,onPendingCommandHandled:wt,onCollapse:()=>F(!1)})}):null]})})]}),D.workspaceInspectorOpen&&G.currentToolProject?.id?(0,Y.jsx)(W.Suspense,{fallback:(0,Y.jsx)(Ic,{}),children:(0,Y.jsx)(Nc,{project:G.currentToolProject,open:!0,view:D.workspacePanelView,onViewChange:D.setWorkspacePanelView,onOpenChange:D.setWorkspaceInspectorOpen,onDraftRequest:We,focusTarget:D.workspaceInspectorFocusTarget,previewUrl:D.webPreviewUrl,onPreviewUrlChange:D.setWebPreviewUrl,artifacts:ne})}):null,D.inlineReaderOpen?(0,Y.jsx)(W.Suspense,{fallback:(0,Y.jsx)(Ic,{}),children:(0,Y.jsx)(Pc,{open:!0,mode:`file`,file:D.inlineReaderFile,loading:D.inlineReaderLoading,error:D.inlineReaderError,onOpenChange:D.setInlineReaderOpen,onDraftRequest:We})}):null]}),(0,Y.jsx)(rt,{open:l,initialPath:i?.path,disabled:c,onOpenChange:g,onSelect:p}),(0,Y.jsx)(at,{open:!!D.skillsDialog,scope:D.skillsDialog?.scope??`global`,project:D.skillsDialog?.project,onOpenChange:e=>{e||D.setSkillsDialog(void 0)},onSaved:en}),(0,Y.jsx)(Mt,{open:D.mcpServersDialogOpen,onOpenChange:D.setMcpServersDialogOpen}),(0,Y.jsx)(vc,{open:D.shareDialogOpen,sessionId:G.currentSessionId,title:_n(G.currentTitle),onOpenChange:D.setShareDialogOpen}),(0,Y.jsx)(sc,{toasts:ue,onDismiss:z,onClick:Ue})]})}function Vc(){let e=window.location.pathname.match(/^\/share\/([^/]+)\/?$/)?.[1];return e?(0,Y.jsx)(W.Suspense,{fallback:(0,Y.jsx)(`div`,{className:`flex h-screen items-center justify-center bg-background text-sm text-muted-foreground`,children:q(`loadingChatWorkspace`)}),children:(0,Y.jsx)(Mc,{shareId:decodeURIComponent(e)})}):(0,Y.jsx)(Bc,{})}Ze({hideSelector:!0}),$e(),window.addEventListener(`error`,e=>{U.error(`Uncaught error:`,e.error??e.message)}),window.addEventListener(`unhandledrejection`,e=>{U.error(`Unhandled promise rejection:`,e.reason)}),`serviceWorker`in navigator&&window.addEventListener(`load`,()=>{navigator.serviceWorker.register(`/sw.js`).catch(()=>{})}),(0,je.createRoot)(document.getElementById(`root`)).render((0,Y.jsx)(W.StrictMode,{children:(0,Y.jsx)(tt,{children:(0,Y.jsx)(Vc,{})})}));export{Ft as C,J as D,X as E,q as O,un as S,lt as T,to as _,hc as a,Zt as b,Ks as c,ho as d,mo as f,Xa as g,eo as h,Sc as i,Mo as l,Qa as m,Tc as n,_c as o,po as p,Cc as r,gc as s,Ec as t,fo as u,$t as v,Z as w,nn as x,ln as y};
|